OpenCut/docs/agent-tool-specs.md

450 lines
10 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Agent Tool Specs — NeuralCut
Este documento define las primitives iniciales del agente. Cada tool debe ser pequeña, accionable y componible. El agente puede resolver features complejas combinando estas tools, pero ninguna tool debe intentar “hacer todo”.
## Principios generales
- Las tools reciben datos estructurados, no instrucciones libres.
- Las tools deben validar inputs y devolver errores claros.
- Las tools que modifican el editor deben usar los comandos/managers existentes para preservar undo/redo cuando aplique.
- El agente debe usar `list_project_assets` y `list_timeline` antes de editar cuando no tenga IDs concretos.
- Gemini se usa para comprensión multimodal; la edición real se ejecuta con tools determinísticas.
---
## 1. `list_project_assets`
### Propósito
Listar assets disponibles en el proyecto para que el agente sepa qué archivos existen y cuáles están usados en el timeline.
### Input
```ts
{
filter?: "all" | "used" | "unused";
type?: "all" | "video" | "audio" | "image";
}
```
### Output
```ts
{
assets: Array<{
id: string;
name: string;
type: "video" | "audio" | "image";
duration?: number;
usedInTimeline: boolean;
}>;
}
```
### Requirements
- MUST return all loaded project assets by default.
- MUST support filtering by usage: `used`, `unused`, `all`.
- MUST support filtering by asset type.
- MUST include stable internal `id` values.
- MUST NOT mutate editor state.
### Errors
- If no project is loaded, return `{ error: "No active project" }`.
---
## 2. `list_timeline`
### Propósito
Listar el estado actual del timeline para que el agente pueda referenciar clips, textos, stickers y otros elementos por `trackId`/`elementId`.
### Input
```ts
{}
```
### Output
```ts
{
tracks: Array<{
trackId: string;
type: "main" | "overlay" | "audio" | "text" | "effect";
elements: Array<{
elementId: string;
type: string;
assetId?: string;
name?: string;
start: number;
end: number;
}>;
}>;
}
```
### Requirements
- MUST return a structured timeline summary.
- MUST include `trackId` and `elementId` for editable elements.
- MUST include timing in seconds or a clearly documented unit.
- MUST NOT mutate editor state.
### Errors
- If no active scene/timeline exists, return `{ error: "No active timeline" }`.
---
## 3. `load_asset_context`
### Propósito
Cargar un asset en el contexto multimodal del agente usando Gemini. Esta es la base para que el agente entienda video/audio/imagen antes de editar.
### Input
```ts
{
assetId: string;
}
```
### Output
```ts
{
assetId: string;
status: "loaded" | "processing";
cached: boolean;
provider: "gemini";
fileUri?: string;
summary?: string;
}
```
### Requirements
- MUST resolve the asset by internal `assetId`.
- MAY support fallback by filename if unambiguous, but internal ID is preferred.
- MUST upload/process the asset with Gemini when not cached.
- MUST cache the provider file reference by `assetId` to avoid repeated uploads.
- MUST keep API keys server-side.
- MUST support video first; audio/image support may be added if Gemini path supports it cleanly.
- MUST NOT edit the timeline.
### Cache behavior
- Cache is application/orchestrator infrastructure, not necessarily a visible LLM tool.
- Cache should store at least:
```ts
{
assetId: string;
provider: "gemini";
fileUri: string;
status: "active" | "processing" | "failed";
createdAt: number;
}
```
### Errors
- Unknown asset: `{ error: "Asset not found" }`.
- Unsupported type: `{ error: "Unsupported asset type" }`.
- Upload/processing failure: `{ error: "Failed to load asset context" }` with safe details.
### Non-goals
- No editing actions.
- No `@asset` UI autocomplete.
- No streaming progress in the first implementation.
---
## 4. `split`
### Propósito
Dividir elementos del timeline en uno o más puntos de tiempo, sin borrar contenido. Esta primitive equivale a hacer cortes/splits puntuales en el editor; eliminar material debe ser una tool separada y puede componerse después de hacer splits.
### Input
```ts
{
times: number[]; // timeline seconds
}
```
### Output
```ts
{
success: boolean;
affectedElements: string[];
}
```
### Requirements
- MUST validate `times` contains at least one finite number.
- MUST accept timeline times in seconds and convert to the editors canonical time unit internally.
- MUST use existing timeline/command infrastructure when possible.
- MUST split every timeline element intersecting each requested time when the split point falls strictly inside the element.
- MUST NOT delete, trim away, or move timeline content.
- MUST be idempotent at existing boundaries: if a requested time already equals an element boundary, it MUST NOT create a duplicate split there.
- MUST preserve undo/redo behavior if the editor supports it for the operation.
### Errors
- Invalid times: `{ error: "Invalid split times" }`.
- Empty timeline: `{ error: "No timeline content" }`.
---
## 5. `add_text`
### Propósito
Agregar texto visual al timeline. Esta primitive cubre títulos, hooks, labels y subtítulos básicos.
### Input
```ts
{
text: string;
start: number;
end: number;
position: "top" | "center" | "bottom";
style?: "plain" | "subtitle" | "hook" | "label";
}
```
### Output
```ts
{
elementId: string;
trackId: string;
}
```
### Requirements
- MUST validate non-empty `text`.
- MUST validate `start < end`.
- MUST create a text element using existing timeline APIs.
- MUST map `position` to a sensible default placement.
- SHOULD provide simple style presets, but implementation may start with defaults.
- MUST NOT generate full subtitles automatically; that is a flow using transcript/context + repeated `add_text` calls.
### Errors
- Empty text: `{ error: "Text is required" }`.
- Invalid range: `{ error: "Invalid time range" }`.
---
## 6. `update_text`
### Propósito
Editar un texto existente en el timeline.
### Input
```ts
{
trackId: string;
elementId: string;
text?: string;
start?: number;
end?: number;
position?: "top" | "center" | "bottom";
}
```
### Output
```ts
{
success: boolean;
elementId: string;
}
```
### Requirements
- MUST find an existing text element by `trackId` + `elementId`.
- MUST only update provided fields.
- MUST validate timing if `start`/`end` are provided.
- MUST preserve undo/redo behavior if supported.
### Errors
- Missing element: `{ error: "Text element not found" }`.
- Wrong element type: `{ error: "Element is not text" }`.
- Invalid range: `{ error: "Invalid time range" }`.
---
## 7. `add_media_to_timeline`
### Propósito
Agregar un asset existente al timeline.
### Input
```ts
{
assetId: string;
startTime: number;
trackType: "main" | "overlay" | "audio";
}
```
### Output
```ts
{
elementId: string;
trackId: string;
}
```
### Requirements
- MUST resolve asset by `assetId`.
- MUST validate asset type compatibility with `trackType`.
- MUST insert the element using existing timeline APIs.
- SHOULD choose a sensible track when one is not obvious, but first version requires explicit `trackType`.
### Errors
- Asset not found: `{ error: "Asset not found" }`.
- Invalid track type: `{ error: "Invalid track type for asset" }`.
---
## 8. `delete_element`
### Propósito
Eliminar un elemento específico del timeline.
### Input
```ts
{
trackId: string;
elementId: string;
}
```
### Output
```ts
{
success: boolean;
}
```
### Requirements
- MUST find element by `trackId` + `elementId`.
- MUST remove only that element.
- MUST preserve undo/redo behavior if supported.
### Errors
- Missing element: `{ error: "Element not found" }`.
---
## 9. `set_volume`
### Propósito
Ajustar volumen de un elemento de audio o video.
### Input
```ts
{
trackId: string;
elementId: string;
volume: number;
}
```
### Output
```ts
{
success: boolean;
volume: number;
}
```
### Requirements
- MUST validate `volume` in range `0..1`.
- MUST only apply to elements that support audio volume.
- MUST preserve undo/redo behavior if supported.
### Errors
- Invalid volume: `{ error: "Volume must be between 0 and 1" }`.
- Unsupported element: `{ error: "Element does not support volume" }`.
---
## 10. `add_sticker`
### Propósito
Agregar un sticker existente al timeline.
### Input
```ts
{
stickerId: string;
start: number;
end: number;
position: "top-left" | "top-right" | "center" | "bottom-left" | "bottom-right";
}
```
### Output
```ts
{
elementId: string;
trackId: string;
}
```
### Requirements
- MUST resolve sticker by `stickerId`.
- MUST validate `start < end`.
- MUST create a timeline element using existing sticker/timeline APIs.
- MUST map `position` to sensible coordinates.
### Errors
- Sticker not found: `{ error: "Sticker not found" }`.
- Invalid range: `{ error: "Invalid time range" }`.
---
## 11. `apply_effect`
### Propósito
Aplicar un efecto existente a un clip. En el estado actual del repo, el efecto real disponible parece ser `blur`.
### Input
```ts
{
trackId: string;
elementId: string;
effectType: "blur";
params?: {
intensity?: number;
};
}
```
### Output
```ts
{
effectId: string;
elementId: string;
}
```
### Requirements
- MUST validate the element is visual and supports effects.
- MUST validate `effectType` exists in the effects registry.
- MUST apply default params when `params` are omitted.
- MUST validate `intensity` if provided.
- MUST preserve undo/redo behavior if supported.
### Errors
- Effect not found: `{ error: "Effect not found" }`.
- Unsupported element: `{ error: "Element does not support effects" }`.
- Invalid params: `{ error: "Invalid effect parameters" }`.
---
## Existing/secondary tool: `transcribe_video`
### Propósito
Transcribir audio usando Whisper local. Es útil para captions y edición por texto, pero no debe ser la primitive principal de comprensión si `load_asset_context` con Gemini está disponible.
### Input
```ts
{
assetId?: string;
language?: string;
modelId?: string;
}
```
### Estado
- Implementada.
- Debe mantenerse como secundaria.
- Puede ser usada por flujos de subtítulos.