返回 html-video
types.ts
根目录 / packages / runtime / src / types.ts
1 /**
2 * Runtime types — slim variant of OD's RuntimeAgentDef.
3 * v0.1: only the fields html-video needs to spawn + read stdout.
4 * Future expansion (prompt-budget, stream-json, MCP) lands per-need.
5 */
6
7 export interface AgentDef {
8 /** Stable id — `claude` / `cursor-agent` / `codex` / `opencode` / `anthropic-api` etc */
9 id: string;
10 /** Human label */
11 name: string;
12 /** CLI binary name (looked up via PATH). For `kind: "http"` agents this is a
13 * pseudo name that doctor() displays but never spawns — set it to something
14 * recognisable like "anthropic-api". */
15 bin: string;
16 /** Absolute-path fallbacks tried (in order) when `bin` is not on PATH.
17 * Used for agents shipped inside another app bundle — e.g. AMR's `vela`
18 * lives in Open Design.app, not on PATH. List real candidate paths; the
19 * first existing one wins and is used as the spawn binary. */
20 binFallbacks?: string[];
21 /** Last-resort async binary resolver, tried after PATH + binFallbacks miss.
22 * Lets an agent pull its binary from a bundled npm package (e.g. AMR resolves
23 * `vela` via @powerformer/vela-cli, which ships per-platform binaries) so the
24 * product works without any external install. Return an absolute path or null. */
25 resolveBinFallback?: () => Promise<string | null>;
26 /** Args to print version (used in `doctor`). Ignored for http agents. */
27 versionArgs: string[];
28 /** Build the argv list given the user prompt. Ignored for http agents. */
29 buildArgs(prompt: string, ctx: AgentInvokeContext): string[];
30 /**
31 * How agent emits to stdout:
32 * - `plain`: free-form text (everything printed is output)
33 * - `claude-stream`: claude --output-format stream-json (NDJSON wrapped events)
34 * - `json-event-stream`: NDJSON {type, ...} event stream
35 * - `acp-json-rpc`: bidirectional ACP JSON-RPC over stdio (AMR/vela). Spawn
36 * stays open; we drive initialize → session/new → session/prompt and read
37 * streamed session/update notifications. Handled by a dedicated path.
38 */
39 streamFormat: 'plain' | 'claude-stream' | 'json-event-stream' | 'acp-json-rpc';
40 /** Pass prompt via stdin instead of argv (recommended for long prompts) */
41 promptViaStdin?: boolean;
42 /**
43 * Optional extra availability gate run AFTER the binary is found (child
44 * agents only). Lets an agent report "installed but not usable" — e.g. AMR
45 * is on disk but the user isn't logged in. Return available=false + a hint.
46 * `resolvedBin` is the path that detection settled on (PATH or a fallback).
47 */
48 extraDetect?: (resolvedBin: string) => Promise<{ available: boolean; version?: string | null; hint?: string }>;
49 /** Default model id for ACP agents that REQUIRE session/set_model before
50 * session/prompt (AMR rejects a missing model). The ACP client sends this via
51 * set_model when the caller doesn't specify one. */
52 defaultModel?: string;
53 /** Extra fixed env vars on spawn */
54 env?: Record<string, string>;
55 /** Where to find install instructions */
56 installUrl?: string;
57 /**
58 * Runtime kind (default `child`).
59 * - `child`: spawn `bin` as a child process (the v0.1 behaviour)
60 * - `http`: skip spawn, call `httpHandler` instead. Used for direct
61 * API agents (e.g. Anthropic Messages, OpenAI ChatCompletions).
62 */
63 kind?: 'child' | 'http';
64 /**
65 * For `kind: "http"` agents — performs the request and streams events.
66 * Should never throw; instead emit `{ type: 'error', message }` and finish
67 * with `{ type: 'message_end' }`.
68 */
69 httpHandler?: (
70 prompt: string,
71 ctx: AgentInvokeContext,
72 onEvent: (e: import('./types.js').AgentEvent) => void,
73 abortSignal: AbortSignal,
74 ) => Promise<{ exitCode: number }>;
75 /**
76 * Whether the http agent is configured / reachable. Used by doctor() in
77 * place of a `which`/`--version` probe. Returns `{ available, error?, hint? }`.
78 */
79 httpProbe?: () => Promise<{ available: boolean; version?: string | null; hint?: string }>;
80 }
81
82 export interface AgentInvokeContext {
83 cwd: string;
84 /** Allowed working dirs (e.g. project's .html-video/projects/<id>/) */
85 extraAllowedDirs?: string[];
86 /** Model override for agents that support selection (e.g. AMR). Falls back to
87 * the agent's defaultModel when unset. */
88 model?: string;
89 }
90
91 export interface DetectedAgent {
92 id: string;
93 name: string;
94 bin: string;
95 available: boolean;
96 path?: string;
97 version?: string | null;
98 installUrl?: string;
99 /** Why it's unavailable / what to do — e.g. AMR found but not logged in. */
100 hint?: string;
101 }
102
103 export type AgentEvent =
104 | { type: 'text'; chunk: string }
105 | { type: 'tool_use'; tool: string; input: unknown; id?: string }
106 | { type: 'tool_result'; id?: string; output: unknown; isError?: boolean }
107 | { type: 'message_end'; reason?: string }
108 | { type: 'error'; message: string };
109
110 export interface SpawnHandle {
111 pid: number;
112 stop(): void;
113 done: Promise<{ exitCode: number; signal: NodeJS.Signals | null }>;
114 }
115
115 lines TYPESCRIPT