Miraiclip SDK
API reference

@miraiclip/assistant

An AI editing assistant for Miraiclip: a vendor-neutral ChatModel contract (OpenAI first; any OpenAI-compatible server works), an agent loop that edits a forked project and lands each request as one undo step, high-level editing tools, and a server handler that keeps API keys off the browser.

npm install @miraiclip/assistant
Version0.1.1
Runs inBrowser or Node
Exports52
GuidesEditing assistant

Functions

applyChecked

Apply a batch as one all-or-nothing step, with two checks core doesn't do: fields a command would silently ignore are errors, and commands that changed nothing are reported, so the model never claims an edit that didn't happen.

function applyChecked(project: Project, commands: Command[]): ToolOutput

Guides: Editing assistant

applyCommandsSchema

apply_commands' input schema: type is an enum of the catalog's commands.

function applyCommandsSchema(catalog: Record<string, unknown>): Record<string, unknown>

Guides: Editing assistant

commitFork

Replay a fork's commands onto the real project as one undoable step.

function commitFork(project: Project, fork: RecordingProject, label?: string): CommitResult

Guides: Editing assistant

createAssistant

function createAssistant(options: AssistantOptions): Assistant

Guides: Editing assistant

createChatHandler

function createChatHandler(model: ChatModel, options?: ChatHandlerOptions): (request: Request) => Promise<Response | null>

Guides: Editing assistant

defineChatModel

Check an adapter's shape once, at registration.

function defineChatModel<M extends ChatModel>(model: M): M

Guides: Editing assistant

defineTool

function defineTool(tool: AssistantTool): AssistantTool

Guides: Editing assistant

describeCommands

One line per command, for a "what changed" list (keyframe edits fold into one line per clip).

function describeCommands(commands: readonly Command[]): string[]

Guides: Editing assistant

describeForAssistant

The project as the model sees it: core's describeProject, plus what a model needs to make RELATIVE edits ("bigger", "louder", "keep the entrance") — track names, every clip's position, size and opacity, text styling, volume, effects and its animation recipe.

function describeForAssistant(doc: ProjectDocument): string

Guides: Editing assistant

editorTools

The tools that edit a Miraiclip project: read state, look up a command's schema, apply command batches, and two high-level tools (transitions, animation presets) that use the same logic as the editor's panels.

function editorTools(options?: EditorToolsOptions): AssistantTool[]

Guides: Editing assistant

forkProject

function forkProject(project: Project, options?: ForkOptions): RecordingProject

Guides: Editing assistant

openAIChatModel

function openAIChatModel(options: OpenAIChatModelOptions): ChatModel

Guides: Editing assistant

parseToolArguments

Parse a tool call's JSON arguments; unparseable JSON is reported to the model as a tool error.

function parseToolArguments(raw: string): Record<string, unknown>

Guides: Editing assistant

rateLimitedChatModel

Wrap a model so calls wait for room under your provider's per-minute limits instead of failing with 429s — for batch jobs (evals, bulk edits) and for a server sharing one key. Each call reserves an estimate, which is replaced by the real usage when the response reports it.

function rateLimitedChatModel(model: ChatModel, options: RateLimitOptions): ChatModel

Guides: Editing assistant

remoteChatModel

The model a backend serves, as a browser-side ChatModel.

function remoteChatModel(endpoint: string, options?: RemoteChatModelOptions): Promise<ChatModel>

Guides: Editing assistant

retryDelayMs

How long the server asked us to wait (Retry-After header, or "try again in 1.2s / 350ms"), else exponential backoff.

function retryDelayMs(res: Pick<Response, "headers">, message: string, attempt: number): number

Guides: Editing assistant

scriptedChatModel

A model that answers from a script: for tests, demos and offline development. Each complete call takes the next step; a string is a final text answer, an object can call tools. Requests are kept in requests.

function scriptedChatModel(steps: ScriptStep[], options?: {
    id?: string;
}): ChatModel & {
    requests: ChatRequest[];
}

Guides: Editing assistant

toolsFromDefinitions

Adopt tools that come as definitions plus one runner — e.g. @miraiclip/audio-sources' audioToolDefinitions + runAudioTool. Accepts { name, description, input_schema } or OpenAI function tools.

function toolsFromDefinitions(definitions: readonly unknown[], run: (name: string, input: Record<string, unknown>, ctx: ToolContext) => Promise<{
    ok: boolean;
    result?: unknown;
    error?: unknown;
}>, options?: {
    changes?: (name: string, input: Record<string, unknown>, result: unknown) => string[] | undefined;
}): AssistantTool[]

Guides: Editing assistant

toOpenAIMessages

Neutral messages → Chat Completions messages.

function toOpenAIMessages(messages: readonly ChatMessage[]): OpenAIMessage[]

Guides: Editing assistant

unknownFields

Unknown payload fields for a command, judged against the best-matching schema branch.

function unknownFields(schema: unknown, payload: unknown): UnknownFields | null

Guides: Editing assistant

withExplicitIds

Built-in commands that would otherwise get a random id inside the engine.

function withExplicitIds(command: Command): Command

Guides: Editing assistant

Classes

ChatModelError

An error from a model vendor, carrying its HTTP status when there was one.

Extends Error.

new ChatModelError(provider: string, message: string, status?: number | undefined)
MemberTypeDescription
providerstring
status?number | undefined

Guides: Editing assistant

Constants

BACKGROUND_TEMPLATE

The html template set_background uses: one {{color}} fill.

const BACKGROUND_TEMPLATE: "<div style=\"width:100%;height:100%;background:{{color}}\"></div>"

DEFAULT_INSTRUCTIONS

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 ...

Guides: Editing assistant

Interfaces

Assistant

MemberTypeDescription
toolsreadonly AssistantTool[]
run(project: Project, request: string, options?: TurnOptions) => Promise<AssistantTurn>

AssistantOptions

MemberTypeDescription
modelChatModel
tools?AssistantTool[]Default editorTools(). Add your own (audio, captions, stock media…).
instructions?stringExtra system instructions (brand voice, house rules).
maxSteps?numberModel round-trips per request (default 12).
modelId?stringModel id when the adapter serves several.
maxOutputTokens?number
params?Record<string, unknown>Vendor request fields, passed through.
fork?ForkOptions

AssistantTool

Extends ToolSpec.

MemberTypeDescription
run(input: Record<string, unknown>, ctx: ToolContext) => Promise<ToolOutput> | ToolOutput

AssistantTurn

MemberTypeDescription
replystringThe model's final answer to the user.
changesstring[]Human-readable list of what the turn changed (empty when nothing).
commandsreadonly Command[]The commands the turn makes, in order (replayed onto the project on apply).
status"applied" | "review" | "no-changes" | "failed" | "canceled"applied: committed as one undo step. review: waiting for apply()/discard(). no-changes: nothing to apply. failed / canceled: the project wasn't touched.
error?string
previewProjectDocumentThe project as the turn left it (for previews in review mode).
messagesChatMessage[]The conversation so far, without the system prompt: pass back as history.
usageRequired<ChatUsage>
apply() => CommitResultCommit a reviewed turn (no-op once applied).
discard() => void

ChatHandlerOptions

Keys stay on the server: run the real model adapter in your backend behind createChatHandler, and give the browser remoteChatModel(endpoint) — a proxy with the same ChatModel shape. The agent loop and the tools run in the browser, next to the project; only model calls cross the network.

GET {base}/ → { id, label, models } POST {base}/chat { request: ChatRequest } → application/x-ndjson, one JSON object per line: { "type": "text", "delta": "…" } (as it streams) { "type": "done", "response": ChatResponse } { "type": "error", "error": "…", "status": 401 } errors before streaming → { error } with 400 / 404 / 413, or the vendor's status

Fetch-API handler (Request → Response): mounts in Node 18+, edge runtimes, Next, Hono, Express (via an adapter).

MemberTypeDescription
basePath?stringPath prefix the handler is mounted at, e.g. "/api/assistant".
maxBodyBytes?numberReject request bodies larger than this (default 2 MB).
authorize?(request: Request) => Promise<Response | undefined> | Response | undefinedReturn a Response to refuse a request (auth, rate limits); undefined to allow.
prepare?(request: ChatRequest) => ChatRequestAdjust each request server-side (pin a model, cap tokens, add instructions).

ChatModel

Extends ChatModelInfo.

MemberTypeDescription
complete(request: ChatRequest, options?: ChatOptions) => Promise<ChatResponse>

Guides: Editing assistant

ChatModelInfo

MemberTypeDescription
idstringAdapter id, e.g. "openai". Alphanumeric with - or _.
labelstring
models?{ id: string; label?: string; }[]Models this adapter serves; the first is the default.

ChatOptions

MemberTypeDescription
signal?AbortSignal
onText?(delta: string) => voidStreaming text, as it arrives (adapters that can't stream call it once).

Guides: Editing assistant

ChatRequest

MemberTypeDescription
messagesChatMessage[]
tools?ToolSpec[]
model?stringModel id, when the adapter serves several.
maxOutputTokens?number
params?Record<string, unknown>Vendor-specific request fields, passed through untouched (e.g. { reasoning_effort: "low" }).

Guides: Editing assistant

ChatResponse

MemberTypeDescription
contentstring
toolCallsToolCall[]
finish"stop" | "tool_calls" | "length" | "content_filter" | "other"Why the model stopped.
model?string
usage?ChatUsage

Guides: Editing assistant

ChatUsage

MemberTypeDescription
inputTokens?number
outputTokens?number

EditorToolsOptions

MemberTypeDescription
transitionKinds?string[]Transition kinds to offer (default: the built-ins). Add your registered custom kinds.
commandCatalog?Record<string, unknown>The command catalog to offer in apply_commands (default: the built-ins). Pass project.commandCatalog() when you register custom commands.

ForkOptions

MemberTypeDescription
createFork?(doc: ReturnType<Project["toJSON"]>) => ProjectBuild the copy (default: createProject(doc)). Register custom commands here.
ensureIds?(command: Command) => CommandGive commands explicit ids (default handles the built-ins with optional ids).

OpenAIChatModelOptions

OpenAI adapter, over the Chat Completions API with function calling.

Chat Completions is also what most other servers speak (Azure OpenAI, OpenRouter, Groq, Together, vLLM, Ollama, LM Studio…), so baseUrl points this one adapter at any of them.

MemberTypeDescription
modelstringModel id, e.g. "gpt-5.4-mini". Required: model names change faster than this package.
models?{ id: string; label?: string; }[]Other models the app may pick per request (ChatRequest.model).
apiKey?stringAPI key. Omit for local servers that don't need one. Keep it server-side (see createChatHandler).
baseUrl?stringDefault https://api.openai.com/v1. Any OpenAI-compatible base URL works.
organization?string
project?string
headers?Record<string, string>
params?Record<string, unknown>Default request fields merged into every call (e.g. { reasoning_effort: "low" }).
stream?booleanStream responses (default true).
maxRetries?numberRetries on rate limits (429) and server errors (500/502/503/504), waiting as long as the server asks (Retry-After, or "try again in 1.2s"), else backing off 1 s, 2 s, 4 s… (capped at 30 s). Default 4; 0 disables.
id?stringAdapter id / label (default "openai" / "OpenAI"), e.g. "ollama" when pointing elsewhere.
label?string
fetch?FetchLike

RateLimitOptions

MemberTypeDescription
tokensPerMinute?numberTokens per rolling minute across every caller of this model (input + output).
requestsPerMinute?numberRequests per rolling minute.
estimate?(request: ChatRequest) => numberToken estimate for a request before it's sent (default: JSON length ÷ 4, plus room for the reply).

RecordingProject

A working copy of a project that records every command that sticks.

The assistant edits the copy while the model thinks (async, many steps); the real project only changes when the turn commits, by replaying the recorded commands in one transaction — one undo step, and nothing half-done if the request fails. Commands inside a transaction that rolls back are dropped, exactly as the copy drops their effects.

Replay must produce the same ids the model saw, so commands whose ids are optional get explicit ones before they run.

Extends Project.

MemberTypeDescription
recordedreadonly Command[]Commands that changed the copy, in order.

RemoteChatModelOptions

MemberTypeDescription
fetch?FetchLike
headers?Record<string, string>
info?{ id: string; label: string; models?: { id: string; label?: string; }[]; }Skip the GET for model info (id/label/models default to "remote").

ToolCall

A tool call the model made. arguments is already parsed JSON.

MemberTypeDescription
idstring
namestring
argumentsRecord<string, unknown>

ToolContext

What a tool's run gets. project is the turn's working copy.

MemberTypeDescription
projectProject
signal?AbortSignal

ToolSpec

A tool as the model sees it: name, description and a JSON Schema for its input.

MemberTypeDescription
namestring
descriptionstring
inputSchemaRecord<string, unknown>

TurnOptions

MemberTypeDescription
history?readonly ChatMessage[]Earlier messages of this conversation (turn.messages from the last turn).
context?stringWhat the user is looking at, e.g. "Selected: clip t-1. Playhead: 4.2s."
apply?"auto" | "review""auto" (default) commits when the request finishes; "review" waits for turn.apply().
signal?AbortSignal
onEvent?(event: AssistantEvent) => void
label?stringHistory label for the undo step (default "Assistant: <request>").

UnknownFields

MemberTypeDescription
unknownstring[]
allowedstring[]The fields the command does take (for the error message).

Types

AssistantEvent

type AssistantEvent = {
    type: "text";
    delta: string;
} | {
    type: "tool-start";
    call: ToolCall;
} | {
    type: "tool-end";
    call: ToolCall;
    ok: boolean;
    changes?: string[];
    error?: string;
} | {
    type: "step";
    index: number;
};

ChatMessage

type ChatMessage = {
    role: "system";
    content: string;
} | {
    role: "user";
    content: string;
} | {
    role: "assistant";
    content: string;
    toolCalls?: ToolCall[];
} | {
    role: "tool";
    toolCallId: string;
    name: string;
    content: string;
};

Guides: Editing assistant

CommitResult

type CommitResult = {
    ok: true;
    applied: number;
} | {
    ok: false;
    error: string;
};

FetchLike

type FetchLike = (url: string, init?: RequestInit) => Promise<Response>;

ScriptStep

type ScriptStep = string | {
    text?: string;
    toolCalls?: (Omit<ToolCall, "id"> & {
        id?: string;
    })[];
} | ((request: ChatRequest, index: number) => ScriptStep);

ToolOutput

A tool's answer. changes are human-readable lines for the app's "what changed" list.

type ToolOutput = {
    ok: true;
    result?: unknown;
    changes?: string[];
} | {
    ok: false;
    error: unknown;
};

On this page