feat: add update_effect tool for modifying existing effect params

This commit is contained in:
Luis Esteban Acevedo Ladino 2026-04-26 17:03:55 -05:00
parent 277321628c
commit 9775f6f30c
5 changed files with 154 additions and 0 deletions

View File

@ -617,6 +617,66 @@ export const EditorContextAdapter = {
appliedParams: element.params,
};
},
updateEffectElement({
elementId,
params,
}: {
elementId: string;
params: Record<string, number | string | boolean>;
}):
| {
success: boolean;
elementId: string;
appliedParams: Record<string, number | string | boolean>;
}
| { error: string } {
const core = EditorCore.getInstance();
const activeScene = core.scenes.getActiveSceneOrNull();
if (!activeScene) {
return { error: "No active timeline" };
}
const [resolved] = findTimelineElementsWithTracksByIds({
tracks: activeScene.tracks,
elementIds: [elementId],
});
if (!resolved) {
return { error: `Timeline element not found: ${elementId}` };
}
if (resolved.element.type !== "effect") {
return { error: "Element is not an effect" };
}
const effectElement = resolved.element as import("@/lib/timeline/types").EffectElement;
const definition = effectsRegistry.get(effectElement.effectType);
if (!definition) {
return { error: `Effect not found: ${effectElement.effectType}` };
}
const validationError = validateEffectParams(definition.params, params);
if (validationError) {
return { error: validationError };
}
const mergedParams = { ...effectElement.params, ...params };
core.timeline.updateElements({
updates: [
{
trackId: resolved.track.id,
elementId,
patch: { params: mergedParams } as Partial<import("@/lib/timeline/types").TimelineElement>,
},
],
});
return {
success: true,
elementId,
appliedParams: mergedParams,
};
},
};
function secondsToTicks(seconds: number): number {

View File

@ -23,3 +23,4 @@ import "@/agent/tools/update-text.tool";
import "@/agent/tools/list-effects.tool";
import "@/agent/tools/get-effect.tool";
import "@/agent/tools/apply-effect.tool";
import "@/agent/tools/update-effect.tool";

View File

@ -161,6 +161,16 @@ export const applyEffectSchema: ToolSchema = {
],
};
export const updateEffectSchema: ToolSchema = {
name: "update_effect",
description:
"Updates parameters of an existing effect element on the timeline. Use list_timeline to find the elementId of the effect, then pass the params you want to change. Only the provided parameters are updated; others keep their current values. Use get_effect to discover valid parameter keys and ranges.",
parameters: [
{ key: "elementId", type: "string", required: true },
{ key: "params", type: "object", required: true },
],
};
/**
* The exact list of schemas exposed to the LLM.
* Excludes internal-only tools (transcribe_video, mock).
@ -179,4 +189,5 @@ export const providerToolSchemas: ToolSchema[] = [
listEffectsSchema,
getEffectSchema,
applyEffectSchema,
updateEffectSchema,
];

View File

@ -0,0 +1,39 @@
import type { AgentContext, ToolDefinition } from "@/agent/types";
import { toolRegistry } from "@/agent/tools/registry";
import { updateEffectSchema } from "@/agent/tools/schemas";
import { EditorContextAdapter } from "@/agent/context";
const updateEffectTool: ToolDefinition = {
...updateEffectSchema,
execute: async (
args: Record<string, unknown>,
_context: AgentContext,
): Promise<
| {
success: boolean;
elementId: string;
appliedParams: Record<string, number | string | boolean>;
}
| { error: string }
> => {
const elementId = args.elementId;
const params = args.params as
| Record<string, number | string | boolean>
| undefined;
if (typeof elementId !== "string" || !elementId.trim()) {
return { error: "Invalid element id" };
}
if (!params || typeof params !== "object" || Object.keys(params).length === 0) {
return { error: "params is required and must be a non-empty object" };
}
return EditorContextAdapter.updateEffectElement({
elementId,
params,
});
},
};
toolRegistry.register(updateEffectSchema.name, updateEffectTool);

View File

@ -654,6 +654,49 @@ Agregar un efecto como elemento standalone al timeline en una pista de efectos,
---
## 17. `update_effect`
### Propósito
Actualizar los parámetros de un elemento de efecto existente en el timeline. Solo se actualizan los parámetros proporcionados; el resto mantiene sus valores actuales.
### Input
```ts
{
elementId: string;
params: Record<string, number | string | boolean>;
}
```
### Output
```ts
{
success: boolean;
elementId: string;
appliedParams: Record<string, number | string | boolean>;
}
```
### Requirements
- MUST validate `elementId` exists in the active timeline.
- MUST validate the target element is an effect element (`type: "effect"`).
- MUST validate `params` against the effect's parameter definitions (types, ranges).
- MUST merge provided `params` with existing params (only override specified keys).
- MUST use `updateElements` to apply the param patch.
- MUST preserve undo/redo behavior.
- MUST return the full merged params after update.
### Errors
- Invalid element id: `{ error: "Invalid element id" }`.
- Missing params: `{ error: "params is required and must be a non-empty object" }`.
- No active timeline: `{ error: "No active timeline" }`.
- Missing element: `{ error: "Timeline element not found: <id>" }`.
- Wrong type: `{ error: "Element is not an effect" }`.
- Effect not found: `{ error: "Effect not found: <type>" }`.
- Unknown parameter: `{ error: "Unknown parameter: <key>" }`.
- Out of range: `{ error: "Parameter '<key>' must be >= <min>" }`.
---
## Existing/secondary tool: `transcribe_video`
### Propósito