@miraiclip/assistant 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.cts CHANGED
@@ -17,6 +17,12 @@ interface ToolCall {
17
17
  */
18
18
  meta?: Record<string, unknown>;
19
19
  }
20
+ /** An image the model looks at (a rendered preview a tool returns): base64 bytes and their type. */
21
+ interface ChatImage {
22
+ mimeType: string;
23
+ /** Base64, no `data:` prefix. */
24
+ data: string;
25
+ }
20
26
  type ChatMessage = {
21
27
  role: "system";
22
28
  content: string;
@@ -27,11 +33,14 @@ type ChatMessage = {
27
33
  role: "assistant";
28
34
  content: string;
29
35
  toolCalls?: ToolCall[];
30
- } | {
36
+ }
37
+ /** `images`: pictures that come with the result (e.g. rendered frames), for models that can see. */
38
+ | {
31
39
  role: "tool";
32
40
  toolCallId: string;
33
41
  name: string;
34
42
  content: string;
43
+ images?: ChatImage[];
35
44
  };
36
45
  /** A tool as the model sees it: name, description and a JSON Schema for its input. */
37
46
  interface ToolSpec {
@@ -153,9 +162,21 @@ interface OpenAIChatModelOptions {
153
162
  label?: string;
154
163
  fetch?: FetchLike;
155
164
  }
165
+ type OpenAIPart = {
166
+ type: "text";
167
+ text: string;
168
+ } | {
169
+ type: "image_url";
170
+ image_url: {
171
+ url: string;
172
+ };
173
+ };
156
174
  type OpenAIMessage = {
157
175
  role: "system" | "user";
158
176
  content: string;
177
+ } | {
178
+ role: "user";
179
+ content: OpenAIPart[];
159
180
  } | {
160
181
  role: "assistant";
161
182
  content: string | null;
@@ -221,6 +242,14 @@ interface AnthropicChatModelOptions {
221
242
  label?: string;
222
243
  fetch?: FetchLike;
223
244
  }
245
+ type ImageBlock = {
246
+ type: "image";
247
+ source: {
248
+ type: "base64";
249
+ media_type: string;
250
+ data: string;
251
+ };
252
+ };
224
253
  type Block = {
225
254
  type: "text";
226
255
  text: string;
@@ -232,7 +261,10 @@ type Block = {
232
261
  } | {
233
262
  type: "tool_result";
234
263
  tool_use_id: string;
235
- content: string;
264
+ content: string | ({
265
+ type: "text";
266
+ text: string;
267
+ } | ImageBlock)[];
236
268
  } | {
237
269
  type: "thinking";
238
270
  thinking: string;
@@ -300,6 +332,10 @@ type Part = {
300
332
  name: string;
301
333
  response: Record<string, unknown>;
302
334
  };
335
+ inlineData?: {
336
+ mimeType: string;
337
+ data: string;
338
+ };
303
339
  };
304
340
  type GeminiContent = {
305
341
  role: "user" | "model";
@@ -550,16 +586,32 @@ interface UnknownFields {
550
586
  /** Unknown payload fields for a command, judged against the best-matching schema branch. */
551
587
  declare function unknownFields(schema: unknown, payload: unknown): UnknownFields | null;
552
588
 
589
+ /**
590
+ * Checks an html clip's template the way the renderer will read it: as XML
591
+ * (it rasterizes through an SVG `foreignObject`). Markup that isn't
592
+ * well-formed renders nothing, silently, so the assistant rejects it up front
593
+ * with an error the model can fix.
594
+ */
595
+ /** Why the markup won't parse as XML, or undefined when it's well-formed. */
596
+ declare function markupProblem(markup: string): string | undefined;
597
+ /** `asset:<id>` references in a template. */
598
+ declare function assetRefs(markup: string): string[];
599
+
553
600
  /** What a tool's `run` gets. `project` is the turn's working copy. */
554
601
  interface ToolContext {
555
602
  project: Project;
556
603
  signal?: AbortSignal;
557
604
  }
558
- /** A tool's answer. `changes` are human-readable lines for the app's "what changed" list. */
605
+ /**
606
+ * A tool's answer. `changes` are human-readable lines for the app's "what
607
+ * changed" list. `images` go to the model with the result, so it can look at
608
+ * what it made (rendered frames); models that can't see get the text only.
609
+ */
559
610
  type ToolOutput = {
560
611
  ok: true;
561
612
  result?: unknown;
562
613
  changes?: string[];
614
+ images?: ChatImage[];
563
615
  } | {
564
616
  ok: false;
565
617
  error: unknown;
@@ -590,6 +642,13 @@ interface EditorToolsOptions {
590
642
  transitionKinds?: string[];
591
643
  /** The command catalog to offer in apply_commands (default: the built-ins). Pass `project.commandCatalog()` when you register custom commands. */
592
644
  commandCatalog?: Record<string, unknown>;
645
+ /**
646
+ * Runs the continuous-shot check over the document (e.g. `checkShot` from `@miraiclip/server-export`, or the app's
647
+ * in-browser equivalent). The `check_sequence` tool is offered only when this is given, because the check needs a browser.
648
+ */
649
+ checkSequence?: (doc: ProjectDocument, options: {
650
+ clipId?: string;
651
+ }) => Promise<unknown>;
593
652
  }
594
653
  /**
595
654
  * The tools that edit a Miraiclip project: read state, look up a command's
@@ -642,12 +701,75 @@ type CommitResult = {
642
701
  /** Replay a fork's commands onto the real project as one undoable step. */
643
702
  declare function commitFork(project: Project, fork: RecordingProject, label?: string): CommitResult;
644
703
 
704
+ /**
705
+ * Skills: playbooks for bigger jobs (a launch video, captions, a reformat),
706
+ * loaded by the model only when a request needs one.
707
+ *
708
+ * The system prompt lists each skill's name and description. The model calls
709
+ * `load_skill` to read one, and `read_skill_file` for the reference files it
710
+ * points to, so the prompt stays small however many skills there are. An app
711
+ * can also start a request with a skill already loaded (`TurnOptions.skills`),
712
+ * e.g. from a button.
713
+ *
714
+ * Skills are plain Markdown with a front matter (`name`, `description`), the
715
+ * same shape as Claude Code skills. `MIRAICLIP_SKILLS` are the Miraiclip
716
+ * plugin's skills, in their editor versions.
717
+ */
718
+ interface AssistantSkill {
719
+ /** Lowercase letters, digits and dashes, e.g. "captions". */
720
+ name: string;
721
+ /** When to use it, in one or two sentences. The model picks skills by this. */
722
+ description: string;
723
+ /** The playbook (Markdown, without the front matter). */
724
+ instructions: string;
725
+ /** Reference files the playbook points to, by relative path ("reference/craft.md"). */
726
+ files?: Readonly<Record<string, string>>;
727
+ }
728
+ declare function defineSkill(skill: AssistantSkill): AssistantSkill;
729
+ /** Split `---\nkey: value\n---\nbody` into its fields and body. Values may be quoted. */
730
+ declare function parseFrontMatter(markdown: string): {
731
+ data: Record<string, string>;
732
+ body: string;
733
+ };
734
+ /** One skill from its Markdown (front matter `name` and `description`). */
735
+ declare function parseSkill(markdown: string, options?: {
736
+ name?: string;
737
+ description?: string;
738
+ files?: Record<string, string>;
739
+ }): AssistantSkill;
740
+ interface SkillsFromFilesOptions {
741
+ /**
742
+ * Which file in a skill folder is the playbook, in order of preference.
743
+ * Default `["SKILL.md"]`. The Miraiclip plugin keeps the Claude Code
744
+ * version in SKILL.md and the in-editor version in EDITOR.md, so an editor
745
+ * passes `["EDITOR.md"]` (folders without one are skipped). The other
746
+ * entry file's front matter fills in a missing name or description.
747
+ */
748
+ entry?: string[];
749
+ }
750
+ /**
751
+ * Skills from a folder of skill folders, given as `{ path: text }` — e.g.
752
+ * Vite's `import.meta.glob("./skills/**\/*.md", { query: "?raw", import: "default", eager: true })`.
753
+ * Every other `.md` in a skill's folder becomes one of its files.
754
+ */
755
+ declare function skillsFromFiles(files: Record<string, string>, options?: SkillsFromFilesOptions): AssistantSkill[];
756
+ /** The skill list for the system prompt. */
757
+ declare function describeSkills(skills: readonly AssistantSkill[]): string;
758
+ /** `load_skill` and `read_skill_file` for these skills. */
759
+ declare function skillTools(skills: readonly AssistantSkill[]): AssistantTool[];
760
+
645
761
  interface AssistantOptions {
646
762
  model: ChatModel;
647
763
  /** Default `editorTools()`. Add your own (audio, captions, stock media…). */
648
764
  tools?: AssistantTool[];
649
765
  /** Extra system instructions (brand voice, house rules). */
650
766
  instructions?: string;
767
+ /**
768
+ * Playbooks the model can load when a request needs one (e.g.
769
+ * `MIRAICLIP_SKILLS`). Adds `load_skill` and `read_skill_file` to the tools
770
+ * and lists each skill's name and description in the system prompt.
771
+ */
772
+ skills?: readonly AssistantSkill[];
651
773
  /** Model round-trips per request (default 12). */
652
774
  maxSteps?: number;
653
775
  /** Model id when the adapter serves several. */
@@ -669,6 +791,8 @@ type AssistantEvent = {
669
791
  ok: boolean;
670
792
  changes?: string[];
671
793
  error?: string;
794
+ /** Images the tool returned (previews, storyboards) — the model sees them too; apps may show them. */
795
+ images?: ChatImage[];
672
796
  } | {
673
797
  type: "step";
674
798
  index: number;
@@ -684,6 +808,13 @@ interface TurnOptions {
684
808
  onEvent?: (event: AssistantEvent) => void;
685
809
  /** History label for the undo step (default "Assistant: <request>"). */
686
810
  label?: string;
811
+ /**
812
+ * Skills to load up front for this request, by name (e.g. the user picked
813
+ * "Captions" in the app). Their playbooks go into the system prompt, so the
814
+ * model starts on them without a `load_skill` call. Unknown names are
815
+ * ignored.
816
+ */
817
+ skills?: readonly string[];
687
818
  }
688
819
  interface AssistantTurn {
689
820
  /** The model's final answer to the user. */
@@ -714,6 +845,9 @@ interface Assistant {
714
845
  declare const DEFAULT_INSTRUCTIONS = "You are the editing assistant inside a video editor. You change the user's project by calling tools; every change you make lands as ONE undo step when you finish, so act confidently.\n\nHow to work:\n- The current project is summarized below. Clip, track and asset ids there are what tools expect. Call get_state to re-read it after big changes.\n- Prefer the high-level tools when they fit (add_transition, animate_clip, add_effect, set_effects_enabled, set_background, trim_clip, set_keyframes, close_gaps, and any audio or media tools). Call tools directly; apply_commands takes only editing commands like \"clip/add\", never tool names. Use apply_commands for everything else, batching related commands; look up a command's payload with get_command_schema the first time you use it, and use only the fields it lists.\n- Fading a picture (text, image, logo, video) in or out is animate_clip (in / out: fade). fadeInUs / fadeOutUs are audio fades. \"Fade the video in at the start / out at the end\" means the first clip's entrance and the last clip's exit.\n- Constant values are set directly with clip/set-property: rotation (\"rotate 45\u00B0\", \"tilt\"), volume (\"lower to 30%\", \"louder\"), position, size, opacity. Only values that CHANGE over a time range (\"duck the music between 10 and 15 s\", \"fade to silence between 18 and 20 s\", \"spin one full turn\", \"pan across\") are keyframes: set_keyframes, with times in timeline seconds. Remove an animation with keyframe/clear.\n- \"Cuts\" are the ones listed in the project summary; use their times (e.g. one sound per cut).\n- \"Add N more seconds of footage\" adds a new clip (clip/add with trimStartUs for the source point) after the last one; it does not stretch an existing clip.\n- Caption looks (box behind the text, outline, shadow, colors, word preset) are the caption clip's style (clip/set-property { style }).\n- \"The whole video\" means from 0 to the composition length (trim_clip startSeconds / endSeconds).\n- A solid color background behind everything is set_background (add, recolor, remove). Other html clips are recolored through the params their template uses (shown in the clip details). A new track goes on top unless track/add gets index 0 (the bottom).\n- \"Replace X with Y\" removes X and adds Y in the same turn, whichever tool adds Y (audio tools take replaceClipId, which does both).\n- Solo / mute / lock / hide a track with track/set-property (solo, muted, locked, hidden). \"Solo X\" is solo: true on X, not muting the others.\n- Relative requests (\"bigger\", \"louder\", \"a bit brighter\", \"twice as big\") start from the current values in the clip details below: make a visible change in the asked direction (about 25% for \"bigger\"/\"smaller\", \u00D72 for \"twice\").\n- When something is selected, \"this\", \"it\", \"the clip\" and any request that names no target mean ONLY the selection, even with words like \"at the end\" (the end of that clip). Edit nothing else. \"Here\" / \"now\" / \"this point\" mean the playhead. \"Clips\" without a kind mean the video clips on the main video track.\n- \"Again\" / \"also\" / \"another\" mean keep the original and add a copy (clip/duplicate, or clip/add with the same asset); never move the original. \"Instead\" means move or replace.\n- Removing a clip leaves a gap; when asked to close it, also run close_gaps (or trim_clip with ripple).\n- Commands use integer microseconds (1 second = 1000000). High-level tools take seconds.\n- Positions (transform x, y) are fractions of the frame: 0.5, 0.5 is the center.\n- Only reference media that exists in the project or that a tool returned. Never invent file URLs.\n- If a tool fails, read the error, fix the input and retry. A failed apply_commands batch applied NONE of its commands: resend all of them, corrected. If something can't be done, say why.\n- If the request is ambiguous in a way that matters, ask one short question instead of guessing.\n\nWhen you're done, reply in one to three short sentences: what you changed, in plain words (times in seconds, names over ids). Describe only edits your tools reported as applied; if a tool says something changed nothing or failed, fix it or say so. No markdown headings.";
715
846
  declare function createAssistant(options: AssistantOptions): Assistant;
716
847
 
848
+ /** The Miraiclip plugin's skills, in their in-editor versions: pass to `createAssistant({ skills })`. */
849
+ declare const MIRAICLIP_SKILLS: readonly AssistantSkill[];
850
+
717
851
  type ScriptStep = string | {
718
852
  text?: string;
719
853
  toolCalls?: (Omit<ToolCall, "id"> & {
@@ -731,4 +865,4 @@ declare function scriptedChatModel(steps: ScriptStep[], options?: {
731
865
  requests: ChatRequest[];
732
866
  };
733
867
 
734
- export { AI_PROVIDERS, type AiProviderInfo, type AnthropicChatModelOptions, type Assistant, type AssistantEvent, type AssistantOptions, type AssistantTool, type AssistantTurn, BACKGROUND_TEMPLATE, type ChatHandlerOptions, type ChatMessage, type ChatModel, ChatModelError, type ChatModelInfo, type ChatModelsFromEnvOptions, type ChatOptions, type ChatRequest, type ChatResponse, type ChatUsage, type CommitResult, type CreateChatModelOptions, DEFAULT_INSTRUCTIONS, type EditorToolsOptions, type FetchLike, type ForkOptions, type GeminiChatModelOptions, type ModelEntry, type OpenAIChatModelOptions, type ProviderApi, type RateLimitOptions, type RecordingProject, type RemoteChatModelOptions, type RemoteModelInfo, type RoutedChatModelOptions, type ScriptStep, type ToolCall, type ToolContext, type ToolOutput, type ToolSpec, type TurnOptions, USER_KEY_HEADERS, type UnknownFields, type UserCredentials, type UserKeyInfo, type UserKeyOptions, aiProvider, anthropicChatModel, applyChecked, applyCommandsSchema, chatModelsFromEnv, commitFork, createAssistant, createChatHandler, createChatModel, defineChatModel, defineTool, describeCommands, describeForAssistant, editorTools, forkProject, geminiChatModel, openAIChatModel, parseToolArguments, rateLimitedChatModel, remoteChatModel, retryDelayMs, routedChatModel, scriptedChatModel, splitModelRef, toAnthropicMessages, toGeminiContents, toOpenAIMessages, toolsFromDefinitions, unknownFields, userKeyHeaders, withExplicitIds };
868
+ export { AI_PROVIDERS, type AiProviderInfo, type AnthropicChatModelOptions, type Assistant, type AssistantEvent, type AssistantOptions, type AssistantSkill, type AssistantTool, type AssistantTurn, BACKGROUND_TEMPLATE, type ChatHandlerOptions, type ChatImage, type ChatMessage, type ChatModel, ChatModelError, type ChatModelInfo, type ChatModelsFromEnvOptions, type ChatOptions, type ChatRequest, type ChatResponse, type ChatUsage, type CommitResult, type CreateChatModelOptions, DEFAULT_INSTRUCTIONS, type EditorToolsOptions, type FetchLike, type ForkOptions, type GeminiChatModelOptions, MIRAICLIP_SKILLS, type ModelEntry, type OpenAIChatModelOptions, type ProviderApi, type RateLimitOptions, type RecordingProject, type RemoteChatModelOptions, type RemoteModelInfo, type RoutedChatModelOptions, type ScriptStep, type SkillsFromFilesOptions, type ToolCall, type ToolContext, type ToolOutput, type ToolSpec, type TurnOptions, USER_KEY_HEADERS, type UnknownFields, type UserCredentials, type UserKeyInfo, type UserKeyOptions, aiProvider, anthropicChatModel, applyChecked, applyCommandsSchema, assetRefs, chatModelsFromEnv, commitFork, createAssistant, createChatHandler, createChatModel, defineChatModel, defineSkill, defineTool, describeCommands, describeForAssistant, describeSkills, editorTools, forkProject, geminiChatModel, markupProblem, openAIChatModel, parseFrontMatter, parseSkill, parseToolArguments, rateLimitedChatModel, remoteChatModel, retryDelayMs, routedChatModel, scriptedChatModel, skillTools, skillsFromFiles, splitModelRef, toAnthropicMessages, toGeminiContents, toOpenAIMessages, toolsFromDefinitions, unknownFields, userKeyHeaders, withExplicitIds };
package/dist/index.d.ts CHANGED
@@ -17,6 +17,12 @@ interface ToolCall {
17
17
  */
18
18
  meta?: Record<string, unknown>;
19
19
  }
20
+ /** An image the model looks at (a rendered preview a tool returns): base64 bytes and their type. */
21
+ interface ChatImage {
22
+ mimeType: string;
23
+ /** Base64, no `data:` prefix. */
24
+ data: string;
25
+ }
20
26
  type ChatMessage = {
21
27
  role: "system";
22
28
  content: string;
@@ -27,11 +33,14 @@ type ChatMessage = {
27
33
  role: "assistant";
28
34
  content: string;
29
35
  toolCalls?: ToolCall[];
30
- } | {
36
+ }
37
+ /** `images`: pictures that come with the result (e.g. rendered frames), for models that can see. */
38
+ | {
31
39
  role: "tool";
32
40
  toolCallId: string;
33
41
  name: string;
34
42
  content: string;
43
+ images?: ChatImage[];
35
44
  };
36
45
  /** A tool as the model sees it: name, description and a JSON Schema for its input. */
37
46
  interface ToolSpec {
@@ -153,9 +162,21 @@ interface OpenAIChatModelOptions {
153
162
  label?: string;
154
163
  fetch?: FetchLike;
155
164
  }
165
+ type OpenAIPart = {
166
+ type: "text";
167
+ text: string;
168
+ } | {
169
+ type: "image_url";
170
+ image_url: {
171
+ url: string;
172
+ };
173
+ };
156
174
  type OpenAIMessage = {
157
175
  role: "system" | "user";
158
176
  content: string;
177
+ } | {
178
+ role: "user";
179
+ content: OpenAIPart[];
159
180
  } | {
160
181
  role: "assistant";
161
182
  content: string | null;
@@ -221,6 +242,14 @@ interface AnthropicChatModelOptions {
221
242
  label?: string;
222
243
  fetch?: FetchLike;
223
244
  }
245
+ type ImageBlock = {
246
+ type: "image";
247
+ source: {
248
+ type: "base64";
249
+ media_type: string;
250
+ data: string;
251
+ };
252
+ };
224
253
  type Block = {
225
254
  type: "text";
226
255
  text: string;
@@ -232,7 +261,10 @@ type Block = {
232
261
  } | {
233
262
  type: "tool_result";
234
263
  tool_use_id: string;
235
- content: string;
264
+ content: string | ({
265
+ type: "text";
266
+ text: string;
267
+ } | ImageBlock)[];
236
268
  } | {
237
269
  type: "thinking";
238
270
  thinking: string;
@@ -300,6 +332,10 @@ type Part = {
300
332
  name: string;
301
333
  response: Record<string, unknown>;
302
334
  };
335
+ inlineData?: {
336
+ mimeType: string;
337
+ data: string;
338
+ };
303
339
  };
304
340
  type GeminiContent = {
305
341
  role: "user" | "model";
@@ -550,16 +586,32 @@ interface UnknownFields {
550
586
  /** Unknown payload fields for a command, judged against the best-matching schema branch. */
551
587
  declare function unknownFields(schema: unknown, payload: unknown): UnknownFields | null;
552
588
 
589
+ /**
590
+ * Checks an html clip's template the way the renderer will read it: as XML
591
+ * (it rasterizes through an SVG `foreignObject`). Markup that isn't
592
+ * well-formed renders nothing, silently, so the assistant rejects it up front
593
+ * with an error the model can fix.
594
+ */
595
+ /** Why the markup won't parse as XML, or undefined when it's well-formed. */
596
+ declare function markupProblem(markup: string): string | undefined;
597
+ /** `asset:<id>` references in a template. */
598
+ declare function assetRefs(markup: string): string[];
599
+
553
600
  /** What a tool's `run` gets. `project` is the turn's working copy. */
554
601
  interface ToolContext {
555
602
  project: Project;
556
603
  signal?: AbortSignal;
557
604
  }
558
- /** A tool's answer. `changes` are human-readable lines for the app's "what changed" list. */
605
+ /**
606
+ * A tool's answer. `changes` are human-readable lines for the app's "what
607
+ * changed" list. `images` go to the model with the result, so it can look at
608
+ * what it made (rendered frames); models that can't see get the text only.
609
+ */
559
610
  type ToolOutput = {
560
611
  ok: true;
561
612
  result?: unknown;
562
613
  changes?: string[];
614
+ images?: ChatImage[];
563
615
  } | {
564
616
  ok: false;
565
617
  error: unknown;
@@ -590,6 +642,13 @@ interface EditorToolsOptions {
590
642
  transitionKinds?: string[];
591
643
  /** The command catalog to offer in apply_commands (default: the built-ins). Pass `project.commandCatalog()` when you register custom commands. */
592
644
  commandCatalog?: Record<string, unknown>;
645
+ /**
646
+ * Runs the continuous-shot check over the document (e.g. `checkShot` from `@miraiclip/server-export`, or the app's
647
+ * in-browser equivalent). The `check_sequence` tool is offered only when this is given, because the check needs a browser.
648
+ */
649
+ checkSequence?: (doc: ProjectDocument, options: {
650
+ clipId?: string;
651
+ }) => Promise<unknown>;
593
652
  }
594
653
  /**
595
654
  * The tools that edit a Miraiclip project: read state, look up a command's
@@ -642,12 +701,75 @@ type CommitResult = {
642
701
  /** Replay a fork's commands onto the real project as one undoable step. */
643
702
  declare function commitFork(project: Project, fork: RecordingProject, label?: string): CommitResult;
644
703
 
704
+ /**
705
+ * Skills: playbooks for bigger jobs (a launch video, captions, a reformat),
706
+ * loaded by the model only when a request needs one.
707
+ *
708
+ * The system prompt lists each skill's name and description. The model calls
709
+ * `load_skill` to read one, and `read_skill_file` for the reference files it
710
+ * points to, so the prompt stays small however many skills there are. An app
711
+ * can also start a request with a skill already loaded (`TurnOptions.skills`),
712
+ * e.g. from a button.
713
+ *
714
+ * Skills are plain Markdown with a front matter (`name`, `description`), the
715
+ * same shape as Claude Code skills. `MIRAICLIP_SKILLS` are the Miraiclip
716
+ * plugin's skills, in their editor versions.
717
+ */
718
+ interface AssistantSkill {
719
+ /** Lowercase letters, digits and dashes, e.g. "captions". */
720
+ name: string;
721
+ /** When to use it, in one or two sentences. The model picks skills by this. */
722
+ description: string;
723
+ /** The playbook (Markdown, without the front matter). */
724
+ instructions: string;
725
+ /** Reference files the playbook points to, by relative path ("reference/craft.md"). */
726
+ files?: Readonly<Record<string, string>>;
727
+ }
728
+ declare function defineSkill(skill: AssistantSkill): AssistantSkill;
729
+ /** Split `---\nkey: value\n---\nbody` into its fields and body. Values may be quoted. */
730
+ declare function parseFrontMatter(markdown: string): {
731
+ data: Record<string, string>;
732
+ body: string;
733
+ };
734
+ /** One skill from its Markdown (front matter `name` and `description`). */
735
+ declare function parseSkill(markdown: string, options?: {
736
+ name?: string;
737
+ description?: string;
738
+ files?: Record<string, string>;
739
+ }): AssistantSkill;
740
+ interface SkillsFromFilesOptions {
741
+ /**
742
+ * Which file in a skill folder is the playbook, in order of preference.
743
+ * Default `["SKILL.md"]`. The Miraiclip plugin keeps the Claude Code
744
+ * version in SKILL.md and the in-editor version in EDITOR.md, so an editor
745
+ * passes `["EDITOR.md"]` (folders without one are skipped). The other
746
+ * entry file's front matter fills in a missing name or description.
747
+ */
748
+ entry?: string[];
749
+ }
750
+ /**
751
+ * Skills from a folder of skill folders, given as `{ path: text }` — e.g.
752
+ * Vite's `import.meta.glob("./skills/**\/*.md", { query: "?raw", import: "default", eager: true })`.
753
+ * Every other `.md` in a skill's folder becomes one of its files.
754
+ */
755
+ declare function skillsFromFiles(files: Record<string, string>, options?: SkillsFromFilesOptions): AssistantSkill[];
756
+ /** The skill list for the system prompt. */
757
+ declare function describeSkills(skills: readonly AssistantSkill[]): string;
758
+ /** `load_skill` and `read_skill_file` for these skills. */
759
+ declare function skillTools(skills: readonly AssistantSkill[]): AssistantTool[];
760
+
645
761
  interface AssistantOptions {
646
762
  model: ChatModel;
647
763
  /** Default `editorTools()`. Add your own (audio, captions, stock media…). */
648
764
  tools?: AssistantTool[];
649
765
  /** Extra system instructions (brand voice, house rules). */
650
766
  instructions?: string;
767
+ /**
768
+ * Playbooks the model can load when a request needs one (e.g.
769
+ * `MIRAICLIP_SKILLS`). Adds `load_skill` and `read_skill_file` to the tools
770
+ * and lists each skill's name and description in the system prompt.
771
+ */
772
+ skills?: readonly AssistantSkill[];
651
773
  /** Model round-trips per request (default 12). */
652
774
  maxSteps?: number;
653
775
  /** Model id when the adapter serves several. */
@@ -669,6 +791,8 @@ type AssistantEvent = {
669
791
  ok: boolean;
670
792
  changes?: string[];
671
793
  error?: string;
794
+ /** Images the tool returned (previews, storyboards) — the model sees them too; apps may show them. */
795
+ images?: ChatImage[];
672
796
  } | {
673
797
  type: "step";
674
798
  index: number;
@@ -684,6 +808,13 @@ interface TurnOptions {
684
808
  onEvent?: (event: AssistantEvent) => void;
685
809
  /** History label for the undo step (default "Assistant: <request>"). */
686
810
  label?: string;
811
+ /**
812
+ * Skills to load up front for this request, by name (e.g. the user picked
813
+ * "Captions" in the app). Their playbooks go into the system prompt, so the
814
+ * model starts on them without a `load_skill` call. Unknown names are
815
+ * ignored.
816
+ */
817
+ skills?: readonly string[];
687
818
  }
688
819
  interface AssistantTurn {
689
820
  /** The model's final answer to the user. */
@@ -714,6 +845,9 @@ interface Assistant {
714
845
  declare const DEFAULT_INSTRUCTIONS = "You are the editing assistant inside a video editor. You change the user's project by calling tools; every change you make lands as ONE undo step when you finish, so act confidently.\n\nHow to work:\n- The current project is summarized below. Clip, track and asset ids there are what tools expect. Call get_state to re-read it after big changes.\n- Prefer the high-level tools when they fit (add_transition, animate_clip, add_effect, set_effects_enabled, set_background, trim_clip, set_keyframes, close_gaps, and any audio or media tools). Call tools directly; apply_commands takes only editing commands like \"clip/add\", never tool names. Use apply_commands for everything else, batching related commands; look up a command's payload with get_command_schema the first time you use it, and use only the fields it lists.\n- Fading a picture (text, image, logo, video) in or out is animate_clip (in / out: fade). fadeInUs / fadeOutUs are audio fades. \"Fade the video in at the start / out at the end\" means the first clip's entrance and the last clip's exit.\n- Constant values are set directly with clip/set-property: rotation (\"rotate 45\u00B0\", \"tilt\"), volume (\"lower to 30%\", \"louder\"), position, size, opacity. Only values that CHANGE over a time range (\"duck the music between 10 and 15 s\", \"fade to silence between 18 and 20 s\", \"spin one full turn\", \"pan across\") are keyframes: set_keyframes, with times in timeline seconds. Remove an animation with keyframe/clear.\n- \"Cuts\" are the ones listed in the project summary; use their times (e.g. one sound per cut).\n- \"Add N more seconds of footage\" adds a new clip (clip/add with trimStartUs for the source point) after the last one; it does not stretch an existing clip.\n- Caption looks (box behind the text, outline, shadow, colors, word preset) are the caption clip's style (clip/set-property { style }).\n- \"The whole video\" means from 0 to the composition length (trim_clip startSeconds / endSeconds).\n- A solid color background behind everything is set_background (add, recolor, remove). Other html clips are recolored through the params their template uses (shown in the clip details). A new track goes on top unless track/add gets index 0 (the bottom).\n- \"Replace X with Y\" removes X and adds Y in the same turn, whichever tool adds Y (audio tools take replaceClipId, which does both).\n- Solo / mute / lock / hide a track with track/set-property (solo, muted, locked, hidden). \"Solo X\" is solo: true on X, not muting the others.\n- Relative requests (\"bigger\", \"louder\", \"a bit brighter\", \"twice as big\") start from the current values in the clip details below: make a visible change in the asked direction (about 25% for \"bigger\"/\"smaller\", \u00D72 for \"twice\").\n- When something is selected, \"this\", \"it\", \"the clip\" and any request that names no target mean ONLY the selection, even with words like \"at the end\" (the end of that clip). Edit nothing else. \"Here\" / \"now\" / \"this point\" mean the playhead. \"Clips\" without a kind mean the video clips on the main video track.\n- \"Again\" / \"also\" / \"another\" mean keep the original and add a copy (clip/duplicate, or clip/add with the same asset); never move the original. \"Instead\" means move or replace.\n- Removing a clip leaves a gap; when asked to close it, also run close_gaps (or trim_clip with ripple).\n- Commands use integer microseconds (1 second = 1000000). High-level tools take seconds.\n- Positions (transform x, y) are fractions of the frame: 0.5, 0.5 is the center.\n- Only reference media that exists in the project or that a tool returned. Never invent file URLs.\n- If a tool fails, read the error, fix the input and retry. A failed apply_commands batch applied NONE of its commands: resend all of them, corrected. If something can't be done, say why.\n- If the request is ambiguous in a way that matters, ask one short question instead of guessing.\n\nWhen you're done, reply in one to three short sentences: what you changed, in plain words (times in seconds, names over ids). Describe only edits your tools reported as applied; if a tool says something changed nothing or failed, fix it or say so. No markdown headings.";
715
846
  declare function createAssistant(options: AssistantOptions): Assistant;
716
847
 
848
+ /** The Miraiclip plugin's skills, in their in-editor versions: pass to `createAssistant({ skills })`. */
849
+ declare const MIRAICLIP_SKILLS: readonly AssistantSkill[];
850
+
717
851
  type ScriptStep = string | {
718
852
  text?: string;
719
853
  toolCalls?: (Omit<ToolCall, "id"> & {
@@ -731,4 +865,4 @@ declare function scriptedChatModel(steps: ScriptStep[], options?: {
731
865
  requests: ChatRequest[];
732
866
  };
733
867
 
734
- export { AI_PROVIDERS, type AiProviderInfo, type AnthropicChatModelOptions, type Assistant, type AssistantEvent, type AssistantOptions, type AssistantTool, type AssistantTurn, BACKGROUND_TEMPLATE, type ChatHandlerOptions, type ChatMessage, type ChatModel, ChatModelError, type ChatModelInfo, type ChatModelsFromEnvOptions, type ChatOptions, type ChatRequest, type ChatResponse, type ChatUsage, type CommitResult, type CreateChatModelOptions, DEFAULT_INSTRUCTIONS, type EditorToolsOptions, type FetchLike, type ForkOptions, type GeminiChatModelOptions, type ModelEntry, type OpenAIChatModelOptions, type ProviderApi, type RateLimitOptions, type RecordingProject, type RemoteChatModelOptions, type RemoteModelInfo, type RoutedChatModelOptions, type ScriptStep, type ToolCall, type ToolContext, type ToolOutput, type ToolSpec, type TurnOptions, USER_KEY_HEADERS, type UnknownFields, type UserCredentials, type UserKeyInfo, type UserKeyOptions, aiProvider, anthropicChatModel, applyChecked, applyCommandsSchema, chatModelsFromEnv, commitFork, createAssistant, createChatHandler, createChatModel, defineChatModel, defineTool, describeCommands, describeForAssistant, editorTools, forkProject, geminiChatModel, openAIChatModel, parseToolArguments, rateLimitedChatModel, remoteChatModel, retryDelayMs, routedChatModel, scriptedChatModel, splitModelRef, toAnthropicMessages, toGeminiContents, toOpenAIMessages, toolsFromDefinitions, unknownFields, userKeyHeaders, withExplicitIds };
868
+ export { AI_PROVIDERS, type AiProviderInfo, type AnthropicChatModelOptions, type Assistant, type AssistantEvent, type AssistantOptions, type AssistantSkill, type AssistantTool, type AssistantTurn, BACKGROUND_TEMPLATE, type ChatHandlerOptions, type ChatImage, type ChatMessage, type ChatModel, ChatModelError, type ChatModelInfo, type ChatModelsFromEnvOptions, type ChatOptions, type ChatRequest, type ChatResponse, type ChatUsage, type CommitResult, type CreateChatModelOptions, DEFAULT_INSTRUCTIONS, type EditorToolsOptions, type FetchLike, type ForkOptions, type GeminiChatModelOptions, MIRAICLIP_SKILLS, type ModelEntry, type OpenAIChatModelOptions, type ProviderApi, type RateLimitOptions, type RecordingProject, type RemoteChatModelOptions, type RemoteModelInfo, type RoutedChatModelOptions, type ScriptStep, type SkillsFromFilesOptions, type ToolCall, type ToolContext, type ToolOutput, type ToolSpec, type TurnOptions, USER_KEY_HEADERS, type UnknownFields, type UserCredentials, type UserKeyInfo, type UserKeyOptions, aiProvider, anthropicChatModel, applyChecked, applyCommandsSchema, assetRefs, chatModelsFromEnv, commitFork, createAssistant, createChatHandler, createChatModel, defineChatModel, defineSkill, defineTool, describeCommands, describeForAssistant, describeSkills, editorTools, forkProject, geminiChatModel, markupProblem, openAIChatModel, parseFrontMatter, parseSkill, parseToolArguments, rateLimitedChatModel, remoteChatModel, retryDelayMs, routedChatModel, scriptedChatModel, skillTools, skillsFromFiles, splitModelRef, toAnthropicMessages, toGeminiContents, toOpenAIMessages, toolsFromDefinitions, unknownFields, userKeyHeaders, withExplicitIds };