@nimashoghi/code-agent-kit 0.1.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.
@@ -0,0 +1,123 @@
1
+ // src/runtime.ts
2
+ import fs from "fs/promises";
3
+ import path from "path";
4
+ function featureDescription(feature) {
5
+ switch (feature) {
6
+ case "resumeSession":
7
+ return "session resume";
8
+ case "eventStreaming":
9
+ return "event streaming";
10
+ }
11
+ }
12
+ var UnsupportedRuntimeFeatureError = class extends Error {
13
+ runtime;
14
+ feature;
15
+ operation;
16
+ details;
17
+ constructor(options) {
18
+ const message = [
19
+ `Runtime "${options.runtime}" does not support ${featureDescription(options.feature)} for ${options.operation}.`,
20
+ options.details
21
+ ].filter(Boolean).join(" ");
22
+ super(message);
23
+ this.name = "UnsupportedRuntimeFeatureError";
24
+ this.runtime = options.runtime;
25
+ this.feature = options.feature;
26
+ this.operation = options.operation;
27
+ this.details = options.details;
28
+ }
29
+ };
30
+ function supportsFeature(capabilities, feature) {
31
+ switch (feature) {
32
+ case "resumeSession":
33
+ return capabilities.resumeSession;
34
+ case "eventStreaming":
35
+ return capabilities.eventStreaming;
36
+ }
37
+ }
38
+ function getRequestedRuntimeFeatures(options) {
39
+ const features = [];
40
+ if (options.onEvent) {
41
+ features.push("eventStreaming");
42
+ }
43
+ if (options.session?.mode === "resume") {
44
+ features.push("resumeSession");
45
+ }
46
+ return features;
47
+ }
48
+ function getRuntimeCapabilities(runtime) {
49
+ if (typeof runtime === "function") {
50
+ return runtime.capabilities;
51
+ }
52
+ const runtimeClass = runtime.constructor;
53
+ if (!runtimeClass.capabilities) {
54
+ throw new Error(
55
+ `Runtime "${runtime.name}" is missing static capabilities metadata on its constructor.`
56
+ );
57
+ }
58
+ return runtimeClass.capabilities;
59
+ }
60
+ function getRuntimeDisplayName(runtime) {
61
+ if (typeof runtime === "function") {
62
+ return runtime.runtimeName;
63
+ }
64
+ const runtimeClass = runtime.constructor;
65
+ return runtimeClass.runtimeName ?? runtime.name;
66
+ }
67
+ function assertRuntimeSupports(runtime, features, operation) {
68
+ const capabilities = getRuntimeCapabilities(runtime);
69
+ const runtimeName = getRuntimeDisplayName(runtime);
70
+ for (const feature of features) {
71
+ if (supportsFeature(capabilities, feature)) {
72
+ continue;
73
+ }
74
+ throw new UnsupportedRuntimeFeatureError({
75
+ runtime: runtimeName,
76
+ feature,
77
+ operation
78
+ });
79
+ }
80
+ }
81
+ function assertRuntimeRunOptionsSupported(runtime, options, operation) {
82
+ assertRuntimeSupports(
83
+ runtime,
84
+ getRequestedRuntimeFeatures(options),
85
+ operation
86
+ );
87
+ }
88
+ async function buildRuntimePrompt(options) {
89
+ const attachments = await Promise.all(
90
+ (options.attachments ?? []).map(async (attachment) => {
91
+ const content = attachment.content ?? await fs.readFile(
92
+ path.resolve(options.workingDirectory, attachment.path),
93
+ "utf8"
94
+ );
95
+ return {
96
+ path: attachment.path,
97
+ content
98
+ };
99
+ })
100
+ );
101
+ if (attachments.length === 0) {
102
+ return options.prompt;
103
+ }
104
+ const attachmentText = attachments.map(
105
+ (attachment) => [
106
+ `Attached file: ${attachment.path}`,
107
+ "```",
108
+ attachment.content,
109
+ "```"
110
+ ].join("\n")
111
+ ).join("\n\n");
112
+ return [attachmentText, `Task:
113
+ ${options.prompt}`].join("\n\n");
114
+ }
115
+
116
+ export {
117
+ UnsupportedRuntimeFeatureError,
118
+ getRequestedRuntimeFeatures,
119
+ assertRuntimeSupports,
120
+ assertRuntimeRunOptionsSupported,
121
+ buildRuntimePrompt
122
+ };
123
+ //# sourceMappingURL=chunk-YAZLCEAU.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/runtime.ts"],"sourcesContent":["import fs from \"node:fs/promises\";\nimport path from \"node:path\";\n\n/** Core runtime abstractions for running a coding agent on a task. */\n\n/** Event emitted during agent execution for real-time progress streaming. */\nexport type RuntimeEvent =\n | { type: \"text\"; content: string }\n | { type: \"tool_use\"; tool: string; input?: unknown }\n | { type: \"tool_result\"; tool: string; output?: string; isError?: boolean }\n | { type: \"thinking\"; content: string }\n | { type: \"error\"; message: string };\n\nexport type RuntimeFeature =\n | \"resumeSession\"\n | \"eventStreaming\";\n\nexport interface RuntimeCapabilities {\n readonly resumeSession: boolean;\n readonly eventStreaming: boolean;\n}\n\nexport interface RuntimeClass<T extends AgentRuntime = AgentRuntime> {\n new (): T;\n readonly runtimeName: string;\n readonly capabilities: RuntimeCapabilities;\n}\n\nexport type RuntimeSession =\n | { mode: \"new\" }\n | { mode: \"resume\"; sessionId: string };\n\n/** Options passed to AgentRuntime.run(). */\nexport interface RuntimeRunOptions {\n /** Directory the agent operates in. */\n workingDirectory: string;\n\n /** The task/instructions for the agent. */\n prompt: string;\n\n /** Optional system prompt text for the run. */\n systemPrompt?: string;\n\n /** Optional text file attachments included alongside the prompt. */\n attachments?: RuntimeAttachment[];\n\n /** Environment variables injected into the agent process. */\n env?: Record<string, string>;\n\n /** Session behavior for the run. */\n session?: RuntimeSession;\n\n /** Timeout in milliseconds. */\n timeoutMs?: number;\n\n /** Abort signal for cancellation. */\n signal?: AbortSignal;\n\n /** Optional streaming callback for real-time progress. */\n onEvent?: (event: RuntimeEvent) => void;\n}\n\n/** Result returned by AgentRuntime.run(). */\nexport interface AgentResult {\n success: boolean;\n output: string;\n error?: string;\n sessionId?: string;\n}\n\nexport interface RuntimeAttachment {\n /** File path to attach. Relative paths resolve from workingDirectory. */\n path: string;\n\n /** Optional inline content. When omitted, the file is read from disk. */\n content?: string;\n}\n\nfunction featureDescription(feature: RuntimeFeature): string {\n switch (feature) {\n case \"resumeSession\":\n return \"session resume\";\n case \"eventStreaming\":\n return \"event streaming\";\n }\n}\n\nexport class UnsupportedRuntimeFeatureError extends Error {\n readonly runtime: string;\n readonly feature: RuntimeFeature;\n readonly operation: string;\n readonly details?: string;\n\n constructor(options: {\n runtime: string;\n feature: RuntimeFeature;\n operation: string;\n details?: string;\n }) {\n const message = [\n `Runtime \"${options.runtime}\" does not support ${featureDescription(options.feature)} for ${options.operation}.`,\n options.details,\n ]\n .filter(Boolean)\n .join(\" \");\n\n super(message);\n this.name = \"UnsupportedRuntimeFeatureError\";\n this.runtime = options.runtime;\n this.feature = options.feature;\n this.operation = options.operation;\n this.details = options.details;\n }\n}\n\nfunction supportsFeature(\n capabilities: RuntimeCapabilities,\n feature: RuntimeFeature,\n): boolean {\n switch (feature) {\n case \"resumeSession\":\n return capabilities.resumeSession;\n case \"eventStreaming\":\n return capabilities.eventStreaming;\n }\n}\n\nexport function getRequestedRuntimeFeatures(\n options: Pick<RuntimeRunOptions, \"onEvent\" | \"session\">,\n): RuntimeFeature[] {\n const features: RuntimeFeature[] = [];\n\n if (options.onEvent) {\n features.push(\"eventStreaming\");\n }\n\n if (options.session?.mode === \"resume\") {\n features.push(\"resumeSession\");\n }\n\n return features;\n}\n\n/** The core abstraction: run a coding agent on a task. */\nexport interface AgentRuntime {\n readonly name: string;\n\n /** Run the agent on a prompt in a directory, return when done. */\n run(options: RuntimeRunOptions): Promise<AgentResult>;\n\n /** Optional cleanup. */\n dispose?(): Promise<void>;\n}\n\nfunction getRuntimeCapabilities(\n runtime: AgentRuntime | RuntimeClass,\n): RuntimeCapabilities {\n if (typeof runtime === \"function\") {\n return runtime.capabilities;\n }\n\n const runtimeClass = runtime.constructor as RuntimeClass;\n if (!runtimeClass.capabilities) {\n throw new Error(\n `Runtime \"${runtime.name}\" is missing static capabilities metadata on its constructor.`,\n );\n }\n\n return runtimeClass.capabilities;\n}\n\nfunction getRuntimeDisplayName(runtime: AgentRuntime | RuntimeClass): string {\n if (typeof runtime === \"function\") {\n return runtime.runtimeName;\n }\n\n const runtimeClass = runtime.constructor as RuntimeClass;\n return runtimeClass.runtimeName ?? runtime.name;\n}\n\nexport function assertRuntimeSupports(\n runtime: AgentRuntime | RuntimeClass,\n features: readonly RuntimeFeature[],\n operation: string,\n): void {\n const capabilities = getRuntimeCapabilities(runtime);\n const runtimeName = getRuntimeDisplayName(runtime);\n\n for (const feature of features) {\n if (supportsFeature(capabilities, feature)) {\n continue;\n }\n\n throw new UnsupportedRuntimeFeatureError({\n runtime: runtimeName,\n feature,\n operation,\n });\n }\n}\n\nexport function assertRuntimeRunOptionsSupported(\n runtime: AgentRuntime | RuntimeClass,\n options: Pick<RuntimeRunOptions, \"onEvent\" | \"session\">,\n operation: string,\n): void {\n assertRuntimeSupports(\n runtime,\n getRequestedRuntimeFeatures(options),\n operation,\n );\n}\n\nexport async function buildRuntimePrompt(\n options: Pick<RuntimeRunOptions, \"workingDirectory\" | \"prompt\" | \"attachments\">,\n): Promise<string> {\n const attachments = await Promise.all(\n (options.attachments ?? []).map(async (attachment) => {\n const content =\n attachment.content ??\n (await fs.readFile(\n path.resolve(options.workingDirectory, attachment.path),\n \"utf8\",\n ));\n\n return {\n path: attachment.path,\n content,\n };\n }),\n );\n\n if (attachments.length === 0) {\n return options.prompt;\n }\n\n const attachmentText = attachments\n .map(\n (attachment) =>\n [\n `Attached file: ${attachment.path}`,\n \"```\",\n attachment.content,\n \"```\",\n ].join(\"\\n\"),\n )\n .join(\"\\n\\n\");\n\n return [attachmentText, `Task:\\n${options.prompt}`].join(\"\\n\\n\");\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,228 @@
1
+ import {
2
+ assertRuntimeRunOptionsSupported,
3
+ buildRuntimePrompt
4
+ } from "./chunk-YAZLCEAU.js";
5
+
6
+ // src/runtimes/gemini.ts
7
+ import { execFile, spawn } from "child_process";
8
+ import { createInterface } from "readline";
9
+ var GeminiRuntime = class _GeminiRuntime {
10
+ static runtimeName = "gemini";
11
+ static capabilities = {
12
+ resumeSession: true,
13
+ eventStreaming: true
14
+ };
15
+ name = _GeminiRuntime.runtimeName;
16
+ config;
17
+ constructor(config) {
18
+ this.config = config ?? {};
19
+ }
20
+ async run(options) {
21
+ assertRuntimeRunOptionsSupported(_GeminiRuntime, options, "runtime.run");
22
+ const prompt = applySystemPrompt(
23
+ await buildRuntimePrompt(options),
24
+ options.systemPrompt
25
+ );
26
+ if (options.onEvent) {
27
+ return this.runStreamed(prompt, options);
28
+ }
29
+ return this.runBuffered(prompt, options);
30
+ }
31
+ async runBuffered(prompt, options) {
32
+ const args = this.buildArgs(prompt, options, "json");
33
+ try {
34
+ const stdout = await execGemini(args, {
35
+ cwd: options.workingDirectory,
36
+ env: buildGeminiEnv(process.env, options.env),
37
+ timeoutMs: options.timeoutMs,
38
+ signal: options.signal
39
+ });
40
+ const result = JSON.parse(stdout);
41
+ return {
42
+ success: true,
43
+ output: result.response,
44
+ sessionId: result.session_id
45
+ };
46
+ } catch (error) {
47
+ return {
48
+ success: false,
49
+ output: "",
50
+ error: error instanceof Error ? error.message : String(error)
51
+ };
52
+ }
53
+ }
54
+ async runStreamed(prompt, options) {
55
+ const args = this.buildArgs(prompt, options, "stream-json");
56
+ const child = spawn("gemini", args, {
57
+ cwd: options.workingDirectory,
58
+ env: buildGeminiEnv(process.env, options.env),
59
+ signal: options.signal
60
+ });
61
+ const stderrChunks = [];
62
+ child.stderr?.on("data", (chunk) => {
63
+ stderrChunks.push(String(chunk));
64
+ });
65
+ let timeoutId;
66
+ if (options.timeoutMs) {
67
+ timeoutId = setTimeout(() => child.kill(), options.timeoutMs);
68
+ }
69
+ try {
70
+ if (!child.stdout) {
71
+ throw new Error("Gemini process did not provide stdout");
72
+ }
73
+ const exitCodePromise = new Promise((resolve, reject) => {
74
+ child.once("error", reject);
75
+ child.once("close", (code) => resolve(code));
76
+ });
77
+ const lines = createInterface({
78
+ input: child.stdout,
79
+ crlfDelay: Infinity
80
+ });
81
+ let sessionId;
82
+ let output = "";
83
+ let hasDeltaOutput = false;
84
+ let reportedError;
85
+ for await (const line of lines) {
86
+ const trimmed = line.trim();
87
+ if (!trimmed) {
88
+ continue;
89
+ }
90
+ const event = JSON.parse(trimmed);
91
+ if (isGeminiInitEvent(event)) {
92
+ sessionId = event.session_id;
93
+ continue;
94
+ }
95
+ if (isGeminiMessageEvent(event)) {
96
+ if (event.role !== "assistant") {
97
+ continue;
98
+ }
99
+ if (event.delta) {
100
+ hasDeltaOutput = true;
101
+ output += event.content;
102
+ options.onEvent?.({ type: "text", content: event.content });
103
+ continue;
104
+ }
105
+ if (!hasDeltaOutput) {
106
+ output = event.content;
107
+ options.onEvent?.({ type: "text", content: event.content });
108
+ } else if (!output) {
109
+ output = event.content;
110
+ }
111
+ continue;
112
+ }
113
+ if (isGeminiResultEvent(event) && event.status !== "success") {
114
+ reportedError = event.message ?? `Gemini run failed with status: ${event.status}`;
115
+ options.onEvent?.({ type: "error", message: reportedError });
116
+ }
117
+ }
118
+ const exitCode = await exitCodePromise;
119
+ if (exitCode !== 0) {
120
+ const stderr = stderrChunks.join("").trim();
121
+ const suffix = stderr ? `: ${stderr}` : "";
122
+ return {
123
+ success: false,
124
+ output: "",
125
+ error: `Gemini exited with code ${exitCode}${suffix}`
126
+ };
127
+ }
128
+ if (reportedError) {
129
+ return { success: false, output, error: reportedError, sessionId };
130
+ }
131
+ return { success: true, output, sessionId };
132
+ } catch (error) {
133
+ return {
134
+ success: false,
135
+ output: "",
136
+ error: error instanceof Error ? error.message : String(error)
137
+ };
138
+ } finally {
139
+ if (timeoutId) {
140
+ clearTimeout(timeoutId);
141
+ }
142
+ }
143
+ }
144
+ buildArgs(prompt, options, outputFormat) {
145
+ const args = ["-p", prompt, "-o", outputFormat];
146
+ if (this.config.model) {
147
+ args.push("--model", this.config.model);
148
+ }
149
+ if (this.config.sandbox !== void 0) {
150
+ args.push(`--sandbox=${this.config.sandbox ? "true" : "false"}`);
151
+ }
152
+ if (this.config.approvalMode) {
153
+ args.push("--approval-mode", this.config.approvalMode);
154
+ }
155
+ for (const policy of this.config.policy ?? []) {
156
+ args.push("--policy", policy);
157
+ }
158
+ for (const extension of this.config.extensions ?? []) {
159
+ args.push("--extensions", extension);
160
+ }
161
+ for (const directory of this.config.includeDirectories ?? []) {
162
+ args.push("--include-directories", directory);
163
+ }
164
+ if (options.session?.mode === "resume") {
165
+ args.push("--resume", options.session.sessionId);
166
+ }
167
+ return args;
168
+ }
169
+ };
170
+ function applySystemPrompt(prompt, systemPrompt) {
171
+ if (!systemPrompt) {
172
+ return prompt;
173
+ }
174
+ return [`System instructions:
175
+ ${systemPrompt}`, prompt].join("\n\n");
176
+ }
177
+ function isGeminiInitEvent(event) {
178
+ return isRecord(event) && event.type === "init" && typeof event.session_id === "string";
179
+ }
180
+ function isGeminiMessageEvent(event) {
181
+ return isRecord(event) && event.type === "message" && (event.role === "user" || event.role === "assistant") && typeof event.content === "string" && (event.delta === void 0 || typeof event.delta === "boolean");
182
+ }
183
+ function isGeminiResultEvent(event) {
184
+ return isRecord(event) && event.type === "result" && typeof event.status === "string" && (event.message === void 0 || typeof event.message === "string");
185
+ }
186
+ function isRecord(value) {
187
+ return typeof value === "object" && value !== null;
188
+ }
189
+ function buildGeminiEnv(...sources) {
190
+ const env = {};
191
+ for (const source of sources) {
192
+ if (!source) {
193
+ continue;
194
+ }
195
+ for (const [key, value] of Object.entries(source)) {
196
+ if (value !== void 0) {
197
+ env[key] = value;
198
+ }
199
+ }
200
+ }
201
+ return env;
202
+ }
203
+ function execGemini(args, options) {
204
+ return new Promise((resolve, reject) => {
205
+ execFile(
206
+ "gemini",
207
+ args,
208
+ {
209
+ cwd: options.cwd,
210
+ env: options.env,
211
+ timeout: options.timeoutMs,
212
+ signal: options.signal
213
+ },
214
+ (error, stdout, stderr) => {
215
+ if (error) {
216
+ reject(new Error(stderr.trim() || error.message));
217
+ return;
218
+ }
219
+ resolve(stdout.trim());
220
+ }
221
+ );
222
+ });
223
+ }
224
+
225
+ export {
226
+ GeminiRuntime
227
+ };
228
+ //# sourceMappingURL=chunk-ZUMYGBXZ.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/runtimes/gemini.ts"],"sourcesContent":["import { execFile, spawn } from \"node:child_process\";\nimport { createInterface } from \"node:readline\";\nimport {\n assertRuntimeRunOptionsSupported,\n type AgentRuntime,\n type AgentResult,\n buildRuntimePrompt,\n type RuntimeRunOptions,\n} from \"../runtime.js\";\n\nexport interface GeminiRuntimeConfig {\n /** Gemini model to use. */\n model?: string;\n /** Whether to enable sandbox mode. */\n sandbox?: boolean;\n /** Gemini approval mode. */\n approvalMode?: \"default\" | \"auto_edit\" | \"yolo\" | \"plan\";\n /** Additional policy files or directories to load. */\n policy?: string[];\n /** Limit Gemini to the specified extensions. */\n extensions?: string[];\n /** Additional directories to include in the workspace. */\n includeDirectories?: string[];\n}\n\ninterface GeminiJsonResult {\n session_id: string;\n response: string;\n}\n\ninterface GeminiInitEvent {\n type: \"init\";\n session_id: string;\n}\n\ninterface GeminiMessageEvent {\n type: \"message\";\n role: \"user\" | \"assistant\";\n content: string;\n delta?: boolean;\n}\n\ninterface GeminiResultEvent {\n type: \"result\";\n status: string;\n message?: string;\n}\n\nexport class GeminiRuntime implements AgentRuntime {\n static readonly runtimeName = \"gemini\";\n static readonly capabilities = {\n resumeSession: true,\n eventStreaming: true,\n } as const;\n readonly name = GeminiRuntime.runtimeName;\n private readonly config: GeminiRuntimeConfig;\n\n constructor(config?: GeminiRuntimeConfig) {\n this.config = config ?? {};\n }\n\n async run(options: RuntimeRunOptions): Promise<AgentResult> {\n assertRuntimeRunOptionsSupported(GeminiRuntime, options, \"runtime.run\");\n const prompt = applySystemPrompt(\n await buildRuntimePrompt(options),\n options.systemPrompt,\n );\n\n if (options.onEvent) {\n return this.runStreamed(prompt, options);\n }\n\n return this.runBuffered(prompt, options);\n }\n\n private async runBuffered(\n prompt: string,\n options: RuntimeRunOptions,\n ): Promise<AgentResult> {\n const args = this.buildArgs(prompt, options, \"json\");\n\n try {\n const stdout = await execGemini(args, {\n cwd: options.workingDirectory,\n env: buildGeminiEnv(process.env, options.env),\n timeoutMs: options.timeoutMs,\n signal: options.signal,\n });\n const result = JSON.parse(stdout) as GeminiJsonResult;\n\n return {\n success: true,\n output: result.response,\n sessionId: result.session_id,\n };\n } catch (error) {\n return {\n success: false,\n output: \"\",\n error: error instanceof Error ? error.message : String(error),\n };\n }\n }\n\n private async runStreamed(\n prompt: string,\n options: RuntimeRunOptions,\n ): Promise<AgentResult> {\n const args = this.buildArgs(prompt, options, \"stream-json\");\n const child = spawn(\"gemini\", args, {\n cwd: options.workingDirectory,\n env: buildGeminiEnv(process.env, options.env),\n signal: options.signal,\n });\n\n const stderrChunks: string[] = [];\n child.stderr?.on(\"data\", (chunk: Buffer | string) => {\n stderrChunks.push(String(chunk));\n });\n\n let timeoutId: ReturnType<typeof setTimeout> | undefined;\n if (options.timeoutMs) {\n timeoutId = setTimeout(() => child.kill(), options.timeoutMs);\n }\n\n try {\n if (!child.stdout) {\n throw new Error(\"Gemini process did not provide stdout\");\n }\n\n const exitCodePromise = new Promise<number | null>((resolve, reject) => {\n child.once(\"error\", reject);\n child.once(\"close\", (code) => resolve(code));\n });\n\n const lines = createInterface({\n input: child.stdout,\n crlfDelay: Infinity,\n });\n let sessionId: string | undefined;\n let output = \"\";\n let hasDeltaOutput = false;\n let reportedError: string | undefined;\n\n for await (const line of lines) {\n const trimmed = line.trim();\n if (!trimmed) {\n continue;\n }\n\n const event = JSON.parse(trimmed) as unknown;\n\n if (isGeminiInitEvent(event)) {\n sessionId = event.session_id;\n continue;\n }\n\n if (isGeminiMessageEvent(event)) {\n if (event.role !== \"assistant\") {\n continue;\n }\n\n if (event.delta) {\n hasDeltaOutput = true;\n output += event.content;\n options.onEvent?.({ type: \"text\", content: event.content });\n continue;\n }\n\n if (!hasDeltaOutput) {\n output = event.content;\n options.onEvent?.({ type: \"text\", content: event.content });\n } else if (!output) {\n output = event.content;\n }\n continue;\n }\n\n if (isGeminiResultEvent(event) && event.status !== \"success\") {\n reportedError =\n event.message ?? `Gemini run failed with status: ${event.status}`;\n options.onEvent?.({ type: \"error\", message: reportedError });\n }\n }\n\n const exitCode = await exitCodePromise;\n\n if (exitCode !== 0) {\n const stderr = stderrChunks.join(\"\").trim();\n const suffix = stderr ? `: ${stderr}` : \"\";\n return {\n success: false,\n output: \"\",\n error: `Gemini exited with code ${exitCode}${suffix}`,\n };\n }\n\n if (reportedError) {\n return { success: false, output, error: reportedError, sessionId };\n }\n\n return { success: true, output, sessionId };\n } catch (error) {\n return {\n success: false,\n output: \"\",\n error: error instanceof Error ? error.message : String(error),\n };\n } finally {\n if (timeoutId) {\n clearTimeout(timeoutId);\n }\n }\n }\n\n private buildArgs(\n prompt: string,\n options: RuntimeRunOptions,\n outputFormat: \"json\" | \"stream-json\",\n ): string[] {\n const args = [\"-p\", prompt, \"-o\", outputFormat];\n\n if (this.config.model) {\n args.push(\"--model\", this.config.model);\n }\n\n if (this.config.sandbox !== undefined) {\n args.push(`--sandbox=${this.config.sandbox ? \"true\" : \"false\"}`);\n }\n\n if (this.config.approvalMode) {\n args.push(\"--approval-mode\", this.config.approvalMode);\n }\n\n for (const policy of this.config.policy ?? []) {\n args.push(\"--policy\", policy);\n }\n\n for (const extension of this.config.extensions ?? []) {\n args.push(\"--extensions\", extension);\n }\n\n for (const directory of this.config.includeDirectories ?? []) {\n args.push(\"--include-directories\", directory);\n }\n\n if (options.session?.mode === \"resume\") {\n args.push(\"--resume\", options.session.sessionId);\n }\n\n return args;\n }\n}\n\nfunction applySystemPrompt(prompt: string, systemPrompt?: string): string {\n if (!systemPrompt) {\n return prompt;\n }\n\n return [`System instructions:\\n${systemPrompt}`, prompt].join(\"\\n\\n\");\n}\n\nfunction isGeminiInitEvent(event: unknown): event is GeminiInitEvent {\n return (\n isRecord(event) &&\n event.type === \"init\" &&\n typeof event.session_id === \"string\"\n );\n}\n\nfunction isGeminiMessageEvent(event: unknown): event is GeminiMessageEvent {\n return (\n isRecord(event) &&\n event.type === \"message\" &&\n (event.role === \"user\" || event.role === \"assistant\") &&\n typeof event.content === \"string\" &&\n (event.delta === undefined || typeof event.delta === \"boolean\")\n );\n}\n\nfunction isGeminiResultEvent(event: unknown): event is GeminiResultEvent {\n return (\n isRecord(event) &&\n event.type === \"result\" &&\n typeof event.status === \"string\" &&\n (event.message === undefined || typeof event.message === \"string\")\n );\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null;\n}\n\nfunction buildGeminiEnv(\n ...sources: (Record<string, string> | NodeJS.ProcessEnv | undefined)[]\n): Record<string, string> {\n const env: Record<string, string> = {};\n\n for (const source of sources) {\n if (!source) {\n continue;\n }\n\n for (const [key, value] of Object.entries(source)) {\n if (value !== undefined) {\n env[key] = value;\n }\n }\n }\n\n return env;\n}\n\nfunction execGemini(\n args: string[],\n options: {\n cwd: string;\n env: Record<string, string>;\n timeoutMs?: number;\n signal?: AbortSignal;\n },\n): Promise<string> {\n return new Promise((resolve, reject) => {\n execFile(\n \"gemini\",\n args,\n {\n cwd: options.cwd,\n env: options.env,\n timeout: options.timeoutMs,\n signal: options.signal,\n },\n (error, stdout, stderr) => {\n if (error) {\n reject(new Error(stderr.trim() || error.message));\n return;\n }\n\n resolve(stdout.trim());\n },\n );\n });\n}\n"],"mappings":";;;;;;AAAA,SAAS,UAAU,aAAa;AAChC,SAAS,uBAAuB;AA+CzB,IAAM,gBAAN,MAAM,eAAsC;AAAA,EACjD,OAAgB,cAAc;AAAA,EAC9B,OAAgB,eAAe;AAAA,IAC7B,eAAe;AAAA,IACf,gBAAgB;AAAA,EAClB;AAAA,EACS,OAAO,eAAc;AAAA,EACb;AAAA,EAEjB,YAAY,QAA8B;AACxC,SAAK,SAAS,UAAU,CAAC;AAAA,EAC3B;AAAA,EAEA,MAAM,IAAI,SAAkD;AAC1D,qCAAiC,gBAAe,SAAS,aAAa;AACtE,UAAM,SAAS;AAAA,MACb,MAAM,mBAAmB,OAAO;AAAA,MAChC,QAAQ;AAAA,IACV;AAEA,QAAI,QAAQ,SAAS;AACnB,aAAO,KAAK,YAAY,QAAQ,OAAO;AAAA,IACzC;AAEA,WAAO,KAAK,YAAY,QAAQ,OAAO;AAAA,EACzC;AAAA,EAEA,MAAc,YACZ,QACA,SACsB;AACtB,UAAM,OAAO,KAAK,UAAU,QAAQ,SAAS,MAAM;AAEnD,QAAI;AACF,YAAM,SAAS,MAAM,WAAW,MAAM;AAAA,QACpC,KAAK,QAAQ;AAAA,QACb,KAAK,eAAe,QAAQ,KAAK,QAAQ,GAAG;AAAA,QAC5C,WAAW,QAAQ;AAAA,QACnB,QAAQ,QAAQ;AAAA,MAClB,CAAC;AACD,YAAM,SAAS,KAAK,MAAM,MAAM;AAEhC,aAAO;AAAA,QACL,SAAS;AAAA,QACT,QAAQ,OAAO;AAAA,QACf,WAAW,OAAO;AAAA,MACpB;AAAA,IACF,SAAS,OAAO;AACd,aAAO;AAAA,QACL,SAAS;AAAA,QACT,QAAQ;AAAA,QACR,OAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAAA,MAC9D;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAc,YACZ,QACA,SACsB;AACtB,UAAM,OAAO,KAAK,UAAU,QAAQ,SAAS,aAAa;AAC1D,UAAM,QAAQ,MAAM,UAAU,MAAM;AAAA,MAClC,KAAK,QAAQ;AAAA,MACb,KAAK,eAAe,QAAQ,KAAK,QAAQ,GAAG;AAAA,MAC5C,QAAQ,QAAQ;AAAA,IAClB,CAAC;AAED,UAAM,eAAyB,CAAC;AAChC,UAAM,QAAQ,GAAG,QAAQ,CAAC,UAA2B;AACnD,mBAAa,KAAK,OAAO,KAAK,CAAC;AAAA,IACjC,CAAC;AAED,QAAI;AACJ,QAAI,QAAQ,WAAW;AACrB,kBAAY,WAAW,MAAM,MAAM,KAAK,GAAG,QAAQ,SAAS;AAAA,IAC9D;AAEA,QAAI;AACF,UAAI,CAAC,MAAM,QAAQ;AACjB,cAAM,IAAI,MAAM,uCAAuC;AAAA,MACzD;AAEA,YAAM,kBAAkB,IAAI,QAAuB,CAAC,SAAS,WAAW;AACtE,cAAM,KAAK,SAAS,MAAM;AAC1B,cAAM,KAAK,SAAS,CAAC,SAAS,QAAQ,IAAI,CAAC;AAAA,MAC7C,CAAC;AAED,YAAM,QAAQ,gBAAgB;AAAA,QAC5B,OAAO,MAAM;AAAA,QACb,WAAW;AAAA,MACb,CAAC;AACD,UAAI;AACJ,UAAI,SAAS;AACb,UAAI,iBAAiB;AACrB,UAAI;AAEJ,uBAAiB,QAAQ,OAAO;AAC9B,cAAM,UAAU,KAAK,KAAK;AAC1B,YAAI,CAAC,SAAS;AACZ;AAAA,QACF;AAEA,cAAM,QAAQ,KAAK,MAAM,OAAO;AAEhC,YAAI,kBAAkB,KAAK,GAAG;AAC5B,sBAAY,MAAM;AAClB;AAAA,QACF;AAEA,YAAI,qBAAqB,KAAK,GAAG;AAC/B,cAAI,MAAM,SAAS,aAAa;AAC9B;AAAA,UACF;AAEA,cAAI,MAAM,OAAO;AACf,6BAAiB;AACjB,sBAAU,MAAM;AAChB,oBAAQ,UAAU,EAAE,MAAM,QAAQ,SAAS,MAAM,QAAQ,CAAC;AAC1D;AAAA,UACF;AAEA,cAAI,CAAC,gBAAgB;AACnB,qBAAS,MAAM;AACf,oBAAQ,UAAU,EAAE,MAAM,QAAQ,SAAS,MAAM,QAAQ,CAAC;AAAA,UAC5D,WAAW,CAAC,QAAQ;AAClB,qBAAS,MAAM;AAAA,UACjB;AACA;AAAA,QACF;AAEA,YAAI,oBAAoB,KAAK,KAAK,MAAM,WAAW,WAAW;AAC5D,0BACE,MAAM,WAAW,kCAAkC,MAAM,MAAM;AACjE,kBAAQ,UAAU,EAAE,MAAM,SAAS,SAAS,cAAc,CAAC;AAAA,QAC7D;AAAA,MACF;AAEA,YAAM,WAAW,MAAM;AAEvB,UAAI,aAAa,GAAG;AAClB,cAAM,SAAS,aAAa,KAAK,EAAE,EAAE,KAAK;AAC1C,cAAM,SAAS,SAAS,KAAK,MAAM,KAAK;AACxC,eAAO;AAAA,UACL,SAAS;AAAA,UACT,QAAQ;AAAA,UACR,OAAO,2BAA2B,QAAQ,GAAG,MAAM;AAAA,QACrD;AAAA,MACF;AAEA,UAAI,eAAe;AACjB,eAAO,EAAE,SAAS,OAAO,QAAQ,OAAO,eAAe,UAAU;AAAA,MACnE;AAEA,aAAO,EAAE,SAAS,MAAM,QAAQ,UAAU;AAAA,IAC5C,SAAS,OAAO;AACd,aAAO;AAAA,QACL,SAAS;AAAA,QACT,QAAQ;AAAA,QACR,OAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAAA,MAC9D;AAAA,IACF,UAAE;AACA,UAAI,WAAW;AACb,qBAAa,SAAS;AAAA,MACxB;AAAA,IACF;AAAA,EACF;AAAA,EAEQ,UACN,QACA,SACA,cACU;AACV,UAAM,OAAO,CAAC,MAAM,QAAQ,MAAM,YAAY;AAE9C,QAAI,KAAK,OAAO,OAAO;AACrB,WAAK,KAAK,WAAW,KAAK,OAAO,KAAK;AAAA,IACxC;AAEA,QAAI,KAAK,OAAO,YAAY,QAAW;AACrC,WAAK,KAAK,aAAa,KAAK,OAAO,UAAU,SAAS,OAAO,EAAE;AAAA,IACjE;AAEA,QAAI,KAAK,OAAO,cAAc;AAC5B,WAAK,KAAK,mBAAmB,KAAK,OAAO,YAAY;AAAA,IACvD;AAEA,eAAW,UAAU,KAAK,OAAO,UAAU,CAAC,GAAG;AAC7C,WAAK,KAAK,YAAY,MAAM;AAAA,IAC9B;AAEA,eAAW,aAAa,KAAK,OAAO,cAAc,CAAC,GAAG;AACpD,WAAK,KAAK,gBAAgB,SAAS;AAAA,IACrC;AAEA,eAAW,aAAa,KAAK,OAAO,sBAAsB,CAAC,GAAG;AAC5D,WAAK,KAAK,yBAAyB,SAAS;AAAA,IAC9C;AAEA,QAAI,QAAQ,SAAS,SAAS,UAAU;AACtC,WAAK,KAAK,YAAY,QAAQ,QAAQ,SAAS;AAAA,IACjD;AAEA,WAAO;AAAA,EACT;AACF;AAEA,SAAS,kBAAkB,QAAgB,cAA+B;AACxE,MAAI,CAAC,cAAc;AACjB,WAAO;AAAA,EACT;AAEA,SAAO,CAAC;AAAA,EAAyB,YAAY,IAAI,MAAM,EAAE,KAAK,MAAM;AACtE;AAEA,SAAS,kBAAkB,OAA0C;AACnE,SACE,SAAS,KAAK,KACd,MAAM,SAAS,UACf,OAAO,MAAM,eAAe;AAEhC;AAEA,SAAS,qBAAqB,OAA6C;AACzE,SACE,SAAS,KAAK,KACd,MAAM,SAAS,cACd,MAAM,SAAS,UAAU,MAAM,SAAS,gBACzC,OAAO,MAAM,YAAY,aACxB,MAAM,UAAU,UAAa,OAAO,MAAM,UAAU;AAEzD;AAEA,SAAS,oBAAoB,OAA4C;AACvE,SACE,SAAS,KAAK,KACd,MAAM,SAAS,YACf,OAAO,MAAM,WAAW,aACvB,MAAM,YAAY,UAAa,OAAO,MAAM,YAAY;AAE7D;AAEA,SAAS,SAAS,OAAkD;AAClE,SAAO,OAAO,UAAU,YAAY,UAAU;AAChD;AAEA,SAAS,kBACJ,SACqB;AACxB,QAAM,MAA8B,CAAC;AAErC,aAAW,UAAU,SAAS;AAC5B,QAAI,CAAC,QAAQ;AACX;AAAA,IACF;AAEA,eAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,MAAM,GAAG;AACjD,UAAI,UAAU,QAAW;AACvB,YAAI,GAAG,IAAI;AAAA,MACb;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;AAEA,SAAS,WACP,MACA,SAMiB;AACjB,SAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AACtC;AAAA,MACE;AAAA,MACA;AAAA,MACA;AAAA,QACE,KAAK,QAAQ;AAAA,QACb,KAAK,QAAQ;AAAA,QACb,SAAS,QAAQ;AAAA,QACjB,QAAQ,QAAQ;AAAA,MAClB;AAAA,MACA,CAAC,OAAO,QAAQ,WAAW;AACzB,YAAI,OAAO;AACT,iBAAO,IAAI,MAAM,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAChD;AAAA,QACF;AAEA,gBAAQ,OAAO,KAAK,CAAC;AAAA,MACvB;AAAA,IACF;AAAA,EACF,CAAC;AACH;","names":[]}
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env node
2
+ import { Command } from 'commander';
3
+ import { RuntimeName } from '../index.js';
4
+ import '../runtime-DxAkSUZk.js';
5
+
6
+ declare const RUNTIME_SELECTION_ENV = "CODE_AGENT_KIT_RUNTIME";
7
+ declare function getDefaultRuntime(env?: NodeJS.ProcessEnv): RuntimeName;
8
+ declare function createCliProgram(): Command;
9
+
10
+ export { RUNTIME_SELECTION_ENV, createCliProgram, getDefaultRuntime };
@@ -0,0 +1,84 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ createRuntime,
4
+ getAvailableRuntimeNames
5
+ } from "../chunk-NKMHTQVX.js";
6
+ import "../chunk-EN5WJJ2G.js";
7
+ import "../chunk-CGK4TBZD.js";
8
+ import "../chunk-AVSJQKCD.js";
9
+ import "../chunk-ZUMYGBXZ.js";
10
+ import "../chunk-YAZLCEAU.js";
11
+
12
+ // src/cli/index.ts
13
+ import { Command, Option } from "commander";
14
+ import { pathToFileURL } from "url";
15
+ var AVAILABLE_RUNTIMES = getAvailableRuntimeNames();
16
+ var RUNTIME_SELECTION_ENV = "CODE_AGENT_KIT_RUNTIME";
17
+ var FALLBACK_RUNTIME = "claude";
18
+ function isRuntimeName(value) {
19
+ return AVAILABLE_RUNTIMES.includes(value);
20
+ }
21
+ function getDefaultRuntime(env = process.env) {
22
+ if (isRuntimeName(env[RUNTIME_SELECTION_ENV])) {
23
+ return env[RUNTIME_SELECTION_ENV];
24
+ }
25
+ if (isRuntimeName(env.DEFAULT_RUNTIME)) {
26
+ return env.DEFAULT_RUNTIME;
27
+ }
28
+ return FALLBACK_RUNTIME;
29
+ }
30
+ function createCliProgram() {
31
+ const defaultRuntime = getDefaultRuntime();
32
+ return new Command().name("code-agent-kit").description("Run a prompt against a supported coding-agent runtime").version("0.1.0").argument("<prompt>", "Task description or prompt for the agent").addOption(
33
+ new Option("-t, --runtime <name>", "Agent runtime to use").choices(AVAILABLE_RUNTIMES).default(defaultRuntime)
34
+ ).option("-d, --directory <path>", "Working directory", process.cwd()).option("-r, --resume <sessionId>", "Resume a previous session by ID").option("--timeout <ms>", "Timeout in milliseconds").option("-s, --system <text>", "System prompt text").option(
35
+ "-f, --file <path>",
36
+ "Attach a text file (can be used multiple times)",
37
+ (value, previous) => previous.concat(value),
38
+ []
39
+ ).action(
40
+ async (prompt, opts, command) => {
41
+ const runtimeOptionSource = command.getOptionValueSource("runtime");
42
+ const runtime = createRuntime({
43
+ name: opts.runtime,
44
+ defaultRuntime
45
+ });
46
+ const result = await runtime.run({
47
+ workingDirectory: opts.directory,
48
+ prompt,
49
+ systemPrompt: opts.system,
50
+ attachments: opts.file.map((filePath) => ({ path: filePath })),
51
+ env: runtimeOptionSource === "cli" ? { [RUNTIME_SELECTION_ENV]: opts.runtime } : void 0,
52
+ timeoutMs: opts.timeout ? Number.parseInt(opts.timeout, 10) : void 0,
53
+ session: opts.resume ? { mode: "resume", sessionId: opts.resume } : void 0
54
+ });
55
+ if (result.sessionId) {
56
+ console.error(`Session ID: ${result.sessionId}`);
57
+ }
58
+ if (!result.success) {
59
+ console.error(result.error ?? "Runtime execution failed.");
60
+ process.exitCode = 1;
61
+ return;
62
+ }
63
+ if (result.output) {
64
+ console.log(result.output);
65
+ }
66
+ }
67
+ );
68
+ }
69
+ if (process.argv[1]) {
70
+ const entryUrl = pathToFileURL(process.argv[1]).href;
71
+ if (import.meta.url === entryUrl) {
72
+ createCliProgram().parseAsync().catch((error) => {
73
+ const message = error instanceof Error ? error.message : String(error);
74
+ console.error(message);
75
+ process.exit(1);
76
+ });
77
+ }
78
+ }
79
+ export {
80
+ RUNTIME_SELECTION_ENV,
81
+ createCliProgram,
82
+ getDefaultRuntime
83
+ };
84
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/cli/index.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport { Command, Option } from \"commander\";\nimport { pathToFileURL } from \"node:url\";\nimport {\n createRuntime,\n getAvailableRuntimeNames,\n type RuntimeName,\n} from \"../runtimes/registry.js\";\n\nconst AVAILABLE_RUNTIMES = getAvailableRuntimeNames();\nexport const RUNTIME_SELECTION_ENV = \"CODE_AGENT_KIT_RUNTIME\";\nconst FALLBACK_RUNTIME: RuntimeName = \"claude\";\n\nfunction isRuntimeName(value: string | undefined): value is RuntimeName {\n return AVAILABLE_RUNTIMES.includes(value as RuntimeName);\n}\n\nexport function getDefaultRuntime(\n env: NodeJS.ProcessEnv = process.env,\n): RuntimeName {\n if (isRuntimeName(env[RUNTIME_SELECTION_ENV])) {\n return env[RUNTIME_SELECTION_ENV];\n }\n\n if (isRuntimeName(env.DEFAULT_RUNTIME)) {\n return env.DEFAULT_RUNTIME;\n }\n\n return FALLBACK_RUNTIME;\n}\n\nexport function createCliProgram(): Command {\n const defaultRuntime = getDefaultRuntime();\n\n return new Command()\n .name(\"code-agent-kit\")\n .description(\"Run a prompt against a supported coding-agent runtime\")\n .version(\"0.1.0\")\n .argument(\"<prompt>\", \"Task description or prompt for the agent\")\n .addOption(\n new Option(\"-t, --runtime <name>\", \"Agent runtime to use\")\n .choices(AVAILABLE_RUNTIMES)\n .default(defaultRuntime),\n )\n .option(\"-d, --directory <path>\", \"Working directory\", process.cwd())\n .option(\"-r, --resume <sessionId>\", \"Resume a previous session by ID\")\n .option(\"--timeout <ms>\", \"Timeout in milliseconds\")\n .option(\"-s, --system <text>\", \"System prompt text\")\n .option(\n \"-f, --file <path>\",\n \"Attach a text file (can be used multiple times)\",\n (value: string, previous: string[]) => previous.concat(value),\n [] as string[],\n )\n .action(\n async (\n prompt: string,\n opts: {\n runtime: RuntimeName;\n directory: string;\n resume?: string;\n timeout?: string;\n system?: string;\n file: string[];\n },\n command: Command,\n ) => {\n const runtimeOptionSource = command.getOptionValueSource(\"runtime\");\n const runtime = createRuntime({\n name: opts.runtime,\n defaultRuntime,\n });\n\n const result = await runtime.run({\n workingDirectory: opts.directory,\n prompt,\n systemPrompt: opts.system,\n attachments: opts.file.map((filePath) => ({ path: filePath })),\n env:\n runtimeOptionSource === \"cli\"\n ? { [RUNTIME_SELECTION_ENV]: opts.runtime }\n : undefined,\n timeoutMs: opts.timeout ? Number.parseInt(opts.timeout, 10) : undefined,\n session: opts.resume\n ? { mode: \"resume\", sessionId: opts.resume }\n : undefined,\n });\n\n if (result.sessionId) {\n console.error(`Session ID: ${result.sessionId}`);\n }\n\n if (!result.success) {\n console.error(result.error ?? \"Runtime execution failed.\");\n process.exitCode = 1;\n return;\n }\n\n if (result.output) {\n console.log(result.output);\n }\n },\n );\n}\n\nif (process.argv[1]) {\n const entryUrl = pathToFileURL(process.argv[1]).href;\n if (import.meta.url === entryUrl) {\n createCliProgram().parseAsync().catch((error: unknown) => {\n const message = error instanceof Error ? error.message : String(error);\n console.error(message);\n process.exit(1);\n });\n }\n}\n"],"mappings":";;;;;;;;;;;;AAEA,SAAS,SAAS,cAAc;AAChC,SAAS,qBAAqB;AAO9B,IAAM,qBAAqB,yBAAyB;AAC7C,IAAM,wBAAwB;AACrC,IAAM,mBAAgC;AAEtC,SAAS,cAAc,OAAiD;AACtE,SAAO,mBAAmB,SAAS,KAAoB;AACzD;AAEO,SAAS,kBACd,MAAyB,QAAQ,KACpB;AACb,MAAI,cAAc,IAAI,qBAAqB,CAAC,GAAG;AAC7C,WAAO,IAAI,qBAAqB;AAAA,EAClC;AAEA,MAAI,cAAc,IAAI,eAAe,GAAG;AACtC,WAAO,IAAI;AAAA,EACb;AAEA,SAAO;AACT;AAEO,SAAS,mBAA4B;AAC1C,QAAM,iBAAiB,kBAAkB;AAEzC,SAAO,IAAI,QAAQ,EAChB,KAAK,gBAAgB,EACrB,YAAY,uDAAuD,EACnE,QAAQ,OAAO,EACf,SAAS,YAAY,0CAA0C,EAC/D;AAAA,IACC,IAAI,OAAO,wBAAwB,sBAAsB,EACtD,QAAQ,kBAAkB,EAC1B,QAAQ,cAAc;AAAA,EAC3B,EACC,OAAO,0BAA0B,qBAAqB,QAAQ,IAAI,CAAC,EACnE,OAAO,4BAA4B,iCAAiC,EACpE,OAAO,kBAAkB,yBAAyB,EAClD,OAAO,uBAAuB,oBAAoB,EAClD;AAAA,IACC;AAAA,IACA;AAAA,IACA,CAAC,OAAe,aAAuB,SAAS,OAAO,KAAK;AAAA,IAC5D,CAAC;AAAA,EACH,EACC;AAAA,IACC,OACE,QACA,MAQA,YACG;AACH,YAAM,sBAAsB,QAAQ,qBAAqB,SAAS;AAClE,YAAM,UAAU,cAAc;AAAA,QAC5B,MAAM,KAAK;AAAA,QACX;AAAA,MACF,CAAC;AAED,YAAM,SAAS,MAAM,QAAQ,IAAI;AAAA,QAC/B,kBAAkB,KAAK;AAAA,QACvB;AAAA,QACA,cAAc,KAAK;AAAA,QACnB,aAAa,KAAK,KAAK,IAAI,CAAC,cAAc,EAAE,MAAM,SAAS,EAAE;AAAA,QAC7D,KACE,wBAAwB,QACpB,EAAE,CAAC,qBAAqB,GAAG,KAAK,QAAQ,IACxC;AAAA,QACN,WAAW,KAAK,UAAU,OAAO,SAAS,KAAK,SAAS,EAAE,IAAI;AAAA,QAC9D,SAAS,KAAK,SACV,EAAE,MAAM,UAAU,WAAW,KAAK,OAAO,IACzC;AAAA,MACN,CAAC;AAED,UAAI,OAAO,WAAW;AACpB,gBAAQ,MAAM,eAAe,OAAO,SAAS,EAAE;AAAA,MACjD;AAEA,UAAI,CAAC,OAAO,SAAS;AACnB,gBAAQ,MAAM,OAAO,SAAS,2BAA2B;AACzD,gBAAQ,WAAW;AACnB;AAAA,MACF;AAEA,UAAI,OAAO,QAAQ;AACjB,gBAAQ,IAAI,OAAO,MAAM;AAAA,MAC3B;AAAA,IACF;AAAA,EACF;AACJ;AAEA,IAAI,QAAQ,KAAK,CAAC,GAAG;AACnB,QAAM,WAAW,cAAc,QAAQ,KAAK,CAAC,CAAC,EAAE;AAChD,MAAI,YAAY,QAAQ,UAAU;AAChC,qBAAiB,EAAE,WAAW,EAAE,MAAM,CAAC,UAAmB;AACxD,YAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AACrE,cAAQ,MAAM,OAAO;AACrB,cAAQ,KAAK,CAAC;AAAA,IAChB,CAAC;AAAA,EACH;AACF;","names":[]}
@@ -0,0 +1,17 @@
1
+ import { b as RuntimeFeature, A as AgentRuntime, c as RuntimeClass, d as RuntimeCapabilities } from './runtime-DxAkSUZk.js';
2
+ export { a as AgentResult, e as RuntimeAttachment, f as RuntimeEvent, R as RuntimeRunOptions, g as RuntimeSession, U as UnsupportedRuntimeFeatureError, h as assertRuntimeRunOptionsSupported, i as assertRuntimeSupports, j as buildRuntimePrompt, k as getRequestedRuntimeFeatures } from './runtime-DxAkSUZk.js';
3
+
4
+ type RuntimeName = "claude" | "codex" | "copilot" | "gemini";
5
+ type RegisteredRuntimeClass = RuntimeClass<AgentRuntime> & {
6
+ readonly runtimeName: RuntimeName;
7
+ };
8
+ declare function getAvailableRuntimeClasses(requiredCapabilities?: readonly RuntimeFeature[]): RegisteredRuntimeClass[];
9
+ declare function getAvailableRuntimeNames(requiredCapabilities?: readonly RuntimeFeature[]): RuntimeName[];
10
+ declare function createRuntime(options?: {
11
+ name?: string;
12
+ requiredCapabilities?: readonly RuntimeFeature[];
13
+ defaultRuntime?: RuntimeName;
14
+ }): AgentRuntime;
15
+ declare function getRuntimeCapabilities(runtime: AgentRuntime): RuntimeCapabilities;
16
+
17
+ export { AgentRuntime, RuntimeCapabilities, RuntimeFeature, type RuntimeName, createRuntime, getAvailableRuntimeClasses, getAvailableRuntimeNames, getRuntimeCapabilities };
package/dist/index.js ADDED
@@ -0,0 +1,29 @@
1
+ import {
2
+ createRuntime,
3
+ getAvailableRuntimeClasses,
4
+ getAvailableRuntimeNames,
5
+ getRuntimeCapabilities
6
+ } from "./chunk-NKMHTQVX.js";
7
+ import "./chunk-EN5WJJ2G.js";
8
+ import "./chunk-CGK4TBZD.js";
9
+ import "./chunk-AVSJQKCD.js";
10
+ import "./chunk-ZUMYGBXZ.js";
11
+ import {
12
+ UnsupportedRuntimeFeatureError,
13
+ assertRuntimeRunOptionsSupported,
14
+ assertRuntimeSupports,
15
+ buildRuntimePrompt,
16
+ getRequestedRuntimeFeatures
17
+ } from "./chunk-YAZLCEAU.js";
18
+ export {
19
+ UnsupportedRuntimeFeatureError,
20
+ assertRuntimeRunOptionsSupported,
21
+ assertRuntimeSupports,
22
+ buildRuntimePrompt,
23
+ createRuntime,
24
+ getAvailableRuntimeClasses,
25
+ getAvailableRuntimeNames,
26
+ getRequestedRuntimeFeatures,
27
+ getRuntimeCapabilities
28
+ };
29
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1,97 @@
1
+ /** Core runtime abstractions for running a coding agent on a task. */
2
+ /** Event emitted during agent execution for real-time progress streaming. */
3
+ type RuntimeEvent = {
4
+ type: "text";
5
+ content: string;
6
+ } | {
7
+ type: "tool_use";
8
+ tool: string;
9
+ input?: unknown;
10
+ } | {
11
+ type: "tool_result";
12
+ tool: string;
13
+ output?: string;
14
+ isError?: boolean;
15
+ } | {
16
+ type: "thinking";
17
+ content: string;
18
+ } | {
19
+ type: "error";
20
+ message: string;
21
+ };
22
+ type RuntimeFeature = "resumeSession" | "eventStreaming";
23
+ interface RuntimeCapabilities {
24
+ readonly resumeSession: boolean;
25
+ readonly eventStreaming: boolean;
26
+ }
27
+ interface RuntimeClass<T extends AgentRuntime = AgentRuntime> {
28
+ new (): T;
29
+ readonly runtimeName: string;
30
+ readonly capabilities: RuntimeCapabilities;
31
+ }
32
+ type RuntimeSession = {
33
+ mode: "new";
34
+ } | {
35
+ mode: "resume";
36
+ sessionId: string;
37
+ };
38
+ /** Options passed to AgentRuntime.run(). */
39
+ interface RuntimeRunOptions {
40
+ /** Directory the agent operates in. */
41
+ workingDirectory: string;
42
+ /** The task/instructions for the agent. */
43
+ prompt: string;
44
+ /** Optional system prompt text for the run. */
45
+ systemPrompt?: string;
46
+ /** Optional text file attachments included alongside the prompt. */
47
+ attachments?: RuntimeAttachment[];
48
+ /** Environment variables injected into the agent process. */
49
+ env?: Record<string, string>;
50
+ /** Session behavior for the run. */
51
+ session?: RuntimeSession;
52
+ /** Timeout in milliseconds. */
53
+ timeoutMs?: number;
54
+ /** Abort signal for cancellation. */
55
+ signal?: AbortSignal;
56
+ /** Optional streaming callback for real-time progress. */
57
+ onEvent?: (event: RuntimeEvent) => void;
58
+ }
59
+ /** Result returned by AgentRuntime.run(). */
60
+ interface AgentResult {
61
+ success: boolean;
62
+ output: string;
63
+ error?: string;
64
+ sessionId?: string;
65
+ }
66
+ interface RuntimeAttachment {
67
+ /** File path to attach. Relative paths resolve from workingDirectory. */
68
+ path: string;
69
+ /** Optional inline content. When omitted, the file is read from disk. */
70
+ content?: string;
71
+ }
72
+ declare class UnsupportedRuntimeFeatureError extends Error {
73
+ readonly runtime: string;
74
+ readonly feature: RuntimeFeature;
75
+ readonly operation: string;
76
+ readonly details?: string;
77
+ constructor(options: {
78
+ runtime: string;
79
+ feature: RuntimeFeature;
80
+ operation: string;
81
+ details?: string;
82
+ });
83
+ }
84
+ declare function getRequestedRuntimeFeatures(options: Pick<RuntimeRunOptions, "onEvent" | "session">): RuntimeFeature[];
85
+ /** The core abstraction: run a coding agent on a task. */
86
+ interface AgentRuntime {
87
+ readonly name: string;
88
+ /** Run the agent on a prompt in a directory, return when done. */
89
+ run(options: RuntimeRunOptions): Promise<AgentResult>;
90
+ /** Optional cleanup. */
91
+ dispose?(): Promise<void>;
92
+ }
93
+ declare function assertRuntimeSupports(runtime: AgentRuntime | RuntimeClass, features: readonly RuntimeFeature[], operation: string): void;
94
+ declare function assertRuntimeRunOptionsSupported(runtime: AgentRuntime | RuntimeClass, options: Pick<RuntimeRunOptions, "onEvent" | "session">, operation: string): void;
95
+ declare function buildRuntimePrompt(options: Pick<RuntimeRunOptions, "workingDirectory" | "prompt" | "attachments">): Promise<string>;
96
+
97
+ export { type AgentRuntime as A, type RuntimeRunOptions as R, UnsupportedRuntimeFeatureError as U, type AgentResult as a, type RuntimeFeature as b, type RuntimeClass as c, type RuntimeCapabilities as d, type RuntimeAttachment as e, type RuntimeEvent as f, type RuntimeSession as g, assertRuntimeRunOptionsSupported as h, assertRuntimeSupports as i, buildRuntimePrompt as j, getRequestedRuntimeFeatures as k };