@cochon123/cli2api 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.
Files changed (57) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +252 -0
  3. package/dist/adapters/claude.d.ts +27 -0
  4. package/dist/adapters/claude.js +253 -0
  5. package/dist/adapters/claude.js.map +1 -0
  6. package/dist/adapters/codex.d.ts +51 -0
  7. package/dist/adapters/codex.js +491 -0
  8. package/dist/adapters/codex.js.map +1 -0
  9. package/dist/adapters/cursor.d.ts +31 -0
  10. package/dist/adapters/cursor.js +231 -0
  11. package/dist/adapters/cursor.js.map +1 -0
  12. package/dist/adapters/mock.d.ts +2 -0
  13. package/dist/adapters/mock.js +101 -0
  14. package/dist/adapters/mock.js.map +1 -0
  15. package/dist/adapters/opencode.d.ts +27 -0
  16. package/dist/adapters/opencode.js +208 -0
  17. package/dist/adapters/opencode.js.map +1 -0
  18. package/dist/adapters/registry.d.ts +33 -0
  19. package/dist/adapters/registry.js +99 -0
  20. package/dist/adapters/registry.js.map +1 -0
  21. package/dist/adapters/types.d.ts +18 -0
  22. package/dist/adapters/types.js +35 -0
  23. package/dist/adapters/types.js.map +1 -0
  24. package/dist/config.d.ts +126 -0
  25. package/dist/config.js +121 -0
  26. package/dist/config.js.map +1 -0
  27. package/dist/index.d.ts +2 -0
  28. package/dist/index.js +253 -0
  29. package/dist/index.js.map +1 -0
  30. package/dist/openrouter/catalog.d.ts +28 -0
  31. package/dist/openrouter/catalog.js +162 -0
  32. package/dist/openrouter/catalog.js.map +1 -0
  33. package/dist/protocol/openai.d.ts +48 -0
  34. package/dist/protocol/openai.js +236 -0
  35. package/dist/protocol/openai.js.map +1 -0
  36. package/dist/protocol/responses.d.ts +57 -0
  37. package/dist/protocol/responses.js +142 -0
  38. package/dist/protocol/responses.js.map +1 -0
  39. package/dist/protocol/tools.d.ts +7 -0
  40. package/dist/protocol/tools.js +143 -0
  41. package/dist/protocol/tools.js.map +1 -0
  42. package/dist/server/app.d.ts +25 -0
  43. package/dist/server/app.js +425 -0
  44. package/dist/server/app.js.map +1 -0
  45. package/dist/server/listen.d.ts +18 -0
  46. package/dist/server/listen.js +30 -0
  47. package/dist/server/listen.js.map +1 -0
  48. package/dist/session.d.ts +9 -0
  49. package/dist/session.js +39 -0
  50. package/dist/session.js.map +1 -0
  51. package/dist/types.d.ts +192 -0
  52. package/dist/types.js +3 -0
  53. package/dist/types.js.map +1 -0
  54. package/dist/util/process.d.ts +38 -0
  55. package/dist/util/process.js +292 -0
  56. package/dist/util/process.js.map +1 -0
  57. package/package.json +65 -0
@@ -0,0 +1,231 @@
1
+ import { requestToPrompt } from "../protocol/openai.js";
2
+ import { runCommand, runCommandLines, which } from "../util/process.js";
3
+ const DEFAULT_MODELS = ["default", "composer-2.5", "composer-2.5-fast"];
4
+ function record(value) {
5
+ return value && typeof value === "object" ? value : null;
6
+ }
7
+ function contentText(value) {
8
+ if (typeof value === "string")
9
+ return value;
10
+ if (!Array.isArray(value))
11
+ return "";
12
+ return value
13
+ .map((block) => {
14
+ const item = record(block);
15
+ return item?.type === "text" && typeof item.text === "string" ? item.text : "";
16
+ })
17
+ .join("");
18
+ }
19
+ export function parseCursorLine(line) {
20
+ const trimmed = line.trim();
21
+ if (!trimmed)
22
+ return { kind: "ignore" };
23
+ let parsed;
24
+ try {
25
+ parsed = JSON.parse(trimmed);
26
+ }
27
+ catch {
28
+ return trimmed.startsWith("{") ? { kind: "ignore" } : { kind: "content", text: trimmed, partial: false };
29
+ }
30
+ const event = record(parsed);
31
+ if (!event)
32
+ return { kind: "ignore" };
33
+ const type = typeof event.type === "string" ? event.type : "";
34
+ if (type === "system" && event.subtype === "init" && typeof event.session_id === "string") {
35
+ return { kind: "session", id: event.session_id };
36
+ }
37
+ if (type === "thinking" && event.subtype === "delta" && typeof event.text === "string") {
38
+ return { kind: "reasoning", text: event.text, partial: true };
39
+ }
40
+ if (type === "assistant") {
41
+ const message = record(event.message);
42
+ const text = contentText(message?.content);
43
+ if (text)
44
+ return { kind: "content", text, partial: typeof event.timestamp_ms === "number" };
45
+ }
46
+ if (type === "result") {
47
+ if (event.is_error === true || event.subtype === "error") {
48
+ return { kind: "error", message: typeof event.result === "string" ? event.result : "Cursor agent failed" };
49
+ }
50
+ const rawUsage = record(event.usage);
51
+ let usage;
52
+ if (rawUsage) {
53
+ const prompt = typeof rawUsage.inputTokens === "number" ? rawUsage.inputTokens : 0;
54
+ const completion = typeof rawUsage.outputTokens === "number" ? rawUsage.outputTokens : 0;
55
+ usage = { prompt_tokens: prompt, completion_tokens: completion, total_tokens: prompt + completion };
56
+ }
57
+ return {
58
+ kind: "result",
59
+ text: typeof event.result === "string" ? event.result : undefined,
60
+ usage,
61
+ };
62
+ }
63
+ if (type === "error") {
64
+ return { kind: "error", message: typeof event.message === "string" ? event.message : "Cursor agent stream error" };
65
+ }
66
+ return { kind: "ignore" };
67
+ }
68
+ export function createCursorAdapter(opts = {}) {
69
+ const binary = opts.binary ?? "cursor-agent";
70
+ const timeoutMs = opts.timeoutMs ?? 180_000;
71
+ const mode = opts.mode ?? "ask";
72
+ const trust = opts.trust ?? true;
73
+ return {
74
+ id: "cursor",
75
+ description: "Cursor Agent CLI via native partial stream-json (read-only ask mode)",
76
+ async listModels() {
77
+ return DEFAULT_MODELS.map((model) => ({
78
+ id: `cursor/${model}`,
79
+ object: "model",
80
+ created: 0,
81
+ owned_by: "cursor",
82
+ description: model === "default" ? "Uses the Cursor Agent default model" : undefined,
83
+ }));
84
+ },
85
+ async *chat(req, signal) {
86
+ const path = await which(binary);
87
+ if (!path) {
88
+ yield {
89
+ type: "error",
90
+ message: `cursor-agent binary not found on PATH (looked for "${binary}"). Install Cursor Agent or set CLI2API_CURSOR_BIN.`,
91
+ code: "binary_missing",
92
+ };
93
+ return;
94
+ }
95
+ const args = [
96
+ "-p",
97
+ "--output-format",
98
+ "stream-json",
99
+ "--stream-partial-output",
100
+ "--mode",
101
+ mode,
102
+ "--sandbox",
103
+ "enabled",
104
+ ];
105
+ if (trust)
106
+ args.push("--trust");
107
+ if (req.nativeSessionId)
108
+ args.push("--resume", req.nativeSessionId);
109
+ if (req.modelLocal && req.modelLocal !== "default")
110
+ args.push("--model", req.modelLocal);
111
+ if (opts.extraArgs?.length)
112
+ args.push(...opts.extraArgs);
113
+ args.push(requestToPrompt(req));
114
+ let sawContent = false;
115
+ let sawPartialContent = false;
116
+ let fallbackResult = "";
117
+ let usage;
118
+ let exitCode = null;
119
+ let timedOut = false;
120
+ let stderr = "";
121
+ try {
122
+ for await (const event of runCommandLines(path, args, {
123
+ cwd: opts.cwd,
124
+ timeoutMs,
125
+ signal,
126
+ inheritEnv: ["CURSOR_API_KEY"],
127
+ })) {
128
+ if (event.type === "stdout_line") {
129
+ const parsed = parseCursorLine(event.line);
130
+ if (parsed.kind === "session") {
131
+ yield { type: "session", id: parsed.id };
132
+ }
133
+ else if (parsed.kind === "reasoning") {
134
+ yield { type: "delta", text: parsed.text, channel: "reasoning" };
135
+ }
136
+ else if (parsed.kind === "content") {
137
+ // Cursor emits partial deltas, then repeats the full answer without a timestamp.
138
+ if (parsed.partial) {
139
+ sawPartialContent = true;
140
+ sawContent = true;
141
+ yield { type: "delta", text: parsed.text, channel: "content" };
142
+ }
143
+ else if (!sawPartialContent) {
144
+ sawContent = true;
145
+ yield { type: "delta", text: parsed.text, channel: "content" };
146
+ }
147
+ }
148
+ else if (parsed.kind === "result") {
149
+ fallbackResult = parsed.text ?? fallbackResult;
150
+ usage = parsed.usage ?? usage;
151
+ }
152
+ else if (parsed.kind === "error") {
153
+ yield { type: "error", message: parsed.message, code: "cli_error" };
154
+ return;
155
+ }
156
+ }
157
+ else if (event.type === "exit") {
158
+ exitCode = event.code;
159
+ timedOut = event.timedOut;
160
+ stderr = event.stderr;
161
+ }
162
+ }
163
+ }
164
+ catch (error) {
165
+ yield {
166
+ type: "error",
167
+ message: `Failed to spawn cursor-agent: ${error instanceof Error ? error.message : String(error)}`,
168
+ code: "spawn_error",
169
+ };
170
+ return;
171
+ }
172
+ if (!sawContent && fallbackResult) {
173
+ sawContent = true;
174
+ yield { type: "delta", text: fallbackResult, channel: "content" };
175
+ }
176
+ if (timedOut) {
177
+ yield { type: "error", message: `cursor-agent timed out after ${timeoutMs}ms`, code: "timeout" };
178
+ }
179
+ else if (signal.aborted) {
180
+ yield { type: "error", message: "Aborted", code: "abort" };
181
+ }
182
+ else if (exitCode !== 0) {
183
+ yield {
184
+ type: "error",
185
+ message: `cursor-agent exited with code ${exitCode}${stderr.trim() ? `: ${stderr.trim().slice(0, 2000)}` : ""}`,
186
+ code: "cli_error",
187
+ };
188
+ }
189
+ else if (!sawContent) {
190
+ yield { type: "error", message: "cursor-agent returned empty output", code: "empty_output" };
191
+ }
192
+ else {
193
+ yield { type: "done", finishReason: "stop", usage };
194
+ }
195
+ },
196
+ async health() {
197
+ const path = await which(binary);
198
+ if (!path)
199
+ return { ok: false, adapter: "cursor", details: { binary }, message: "cursor-agent binary not found on PATH" };
200
+ const version = await runCommand(path, ["--version"], { timeoutMs: 8_000 });
201
+ return {
202
+ ok: version.code === 0,
203
+ adapter: "cursor",
204
+ details: {
205
+ binary: path,
206
+ version: (version.stdout || version.stderr).trim() || "not emitted without a TTY",
207
+ mode,
208
+ sandbox: "enabled",
209
+ },
210
+ message: version.code === 0 ? "cursor-agent available" : "cursor-agent --version failed",
211
+ };
212
+ },
213
+ async doctor() {
214
+ const path = await which(binary);
215
+ const checks = [{ name: "binary-on-path", ok: Boolean(path), detail: path ?? `missing: ${binary}` }];
216
+ let version;
217
+ if (path) {
218
+ const result = await runCommand(path, ["--version"], { timeoutMs: 8_000 });
219
+ version = (result.stdout || result.stderr).trim() || undefined;
220
+ checks.push({
221
+ name: "version",
222
+ ok: result.code === 0,
223
+ detail: version ?? (result.code === 0 ? "available; CLI emitted no version without a TTY" : `exit ${result.code}`),
224
+ });
225
+ }
226
+ checks.push({ name: "restrictive-default", ok: mode === "ask" || mode === "plan", detail: `mode=${mode}; sandbox=enabled` });
227
+ return { adapter: "cursor", ok: checks.every((check) => check.ok), binary: path ?? binary, version, checks };
228
+ },
229
+ };
230
+ }
231
+ //# sourceMappingURL=cursor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cursor.js","sourceRoot":"","sources":["../../src/adapters/cursor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import type { Adapter } from "./types.js";
2
+ export declare function createMockAdapter(): Adapter;
@@ -0,0 +1,101 @@
1
+ import { lastUserMessage, messagesToPrompt } from "../protocol/openai.js";
2
+ const MODELS = [
3
+ {
4
+ id: "mock/echo",
5
+ object: "model",
6
+ created: 0,
7
+ owned_by: "cli2api",
8
+ description: "Echoes the last user message (instant)",
9
+ },
10
+ {
11
+ id: "mock/slow",
12
+ object: "model",
13
+ created: 0,
14
+ owned_by: "cli2api",
15
+ description: "Streams a short canned reply with delays",
16
+ },
17
+ ];
18
+ async function* echoChat(req) {
19
+ const last = lastUserMessage(req.messages) || messagesToPrompt(req.messages);
20
+ if (req.tools.length && req.toolChoice !== "none") {
21
+ const forced = typeof req.toolChoice === "object" ? req.toolChoice.function.name : undefined;
22
+ const tool = req.tools.find((item) => item.function.name === forced) ?? req.tools[0];
23
+ yield {
24
+ type: "tool_call",
25
+ call: {
26
+ id: "call_mock0000000000000000000",
27
+ type: "function",
28
+ function: { name: tool.function.name, arguments: JSON.stringify({ input: last }) },
29
+ },
30
+ };
31
+ yield { type: "done", finishReason: "tool_calls" };
32
+ return;
33
+ }
34
+ if (req.raw.include_reasoning === true || (req.raw.reasoning && req.raw.reasoning.enabled !== false)) {
35
+ yield { type: "delta", text: "mock reasoning", channel: "reasoning" };
36
+ }
37
+ const reply = `[mock/echo] ${last}`;
38
+ // Fake-stream in small chunks so clients exercise SSE path
39
+ const chunkSize = 24;
40
+ for (let i = 0; i < reply.length; i += chunkSize) {
41
+ yield { type: "delta", text: reply.slice(i, i + chunkSize) };
42
+ }
43
+ yield {
44
+ type: "done",
45
+ finishReason: "stop",
46
+ usage: {
47
+ prompt_tokens: Math.ceil(last.length / 4),
48
+ completion_tokens: Math.ceil(reply.length / 4),
49
+ total_tokens: Math.ceil((last.length + reply.length) / 4),
50
+ },
51
+ };
52
+ }
53
+ async function* slowChat(_req) {
54
+ const reply = "Hello from cli2api mock/slow. This is a streamed canned response.";
55
+ for (const word of reply.split(" ")) {
56
+ yield { type: "delta", text: word + " " };
57
+ await new Promise((r) => setTimeout(r, 40));
58
+ }
59
+ yield { type: "done", finishReason: "stop" };
60
+ }
61
+ export function createMockAdapter() {
62
+ return {
63
+ id: "mock",
64
+ description: "Deterministic local adapter for smoke tests (no CLI required)",
65
+ async listModels() {
66
+ return MODELS;
67
+ },
68
+ async *chat(req, signal) {
69
+ if (signal.aborted) {
70
+ yield { type: "error", message: "Aborted", code: "abort" };
71
+ return;
72
+ }
73
+ yield { type: "session", id: req.nativeSessionId ?? "mock_native_session" };
74
+ if (req.modelLocal === "slow" || req.model === "mock/slow") {
75
+ yield* slowChat(req);
76
+ return;
77
+ }
78
+ yield* echoChat(req);
79
+ },
80
+ async health() {
81
+ return {
82
+ ok: true,
83
+ adapter: "mock",
84
+ details: { models: MODELS.map((m) => m.id) },
85
+ message: "mock adapter ready",
86
+ };
87
+ },
88
+ async doctor() {
89
+ return {
90
+ adapter: "mock",
91
+ ok: true,
92
+ checks: [
93
+ { name: "always-available", ok: true, detail: "no binary required" },
94
+ { name: "echo-model", ok: true, detail: "mock/echo" },
95
+ { name: "slow-model", ok: true, detail: "mock/slow" },
96
+ ],
97
+ };
98
+ },
99
+ };
100
+ }
101
+ //# sourceMappingURL=mock.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mock.js","sourceRoot":"","sources":["../../src/adapters/mock.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ import type { Adapter } from "./types.js";
2
+ import type { ChatCompletionResponse } from "../types.js";
3
+ export interface OpenCodeAdapterOptions {
4
+ binary?: string;
5
+ cwd?: string;
6
+ timeoutMs?: number;
7
+ extraArgs?: string[];
8
+ /** OpenCode agent. `plan` is the safe, read-only default. */
9
+ agent?: string;
10
+ contentWordDelayMs?: number;
11
+ }
12
+ export type OpenCodeParsedLine = {
13
+ kind: "content" | "reasoning";
14
+ text: string;
15
+ } | {
16
+ kind: "finish";
17
+ finishReason: "stop" | "length" | "error";
18
+ usage?: ChatCompletionResponse["usage"];
19
+ } | {
20
+ kind: "error";
21
+ message: string;
22
+ } | {
23
+ kind: "ignore";
24
+ };
25
+ export declare function openCodeSessionId(line: string): string | undefined;
26
+ export declare function parseOpenCodeLine(line: string): OpenCodeParsedLine;
27
+ export declare function createOpenCodeAdapter(opts?: OpenCodeAdapterOptions): Adapter;
@@ -0,0 +1,208 @@
1
+ import { requestToPrompt } from "../protocol/openai.js";
2
+ import { runCommand, runCommandLines, which } from "../util/process.js";
3
+ import { fakeStreamWords } from "./codex.js";
4
+ const DEFAULT_MODELS = ["default", "deepseek-v4-flash-free"];
5
+ const DEFAULT_WORD_DELAY_MS = 28;
6
+ function record(value) {
7
+ return value && typeof value === "object" ? value : null;
8
+ }
9
+ export function openCodeSessionId(line) {
10
+ try {
11
+ const event = record(JSON.parse(line));
12
+ return event && typeof event.sessionID === "string" && event.sessionID ? event.sessionID : undefined;
13
+ }
14
+ catch {
15
+ return undefined;
16
+ }
17
+ }
18
+ export function parseOpenCodeLine(line) {
19
+ const trimmed = line.trim();
20
+ if (!trimmed)
21
+ return { kind: "ignore" };
22
+ let parsed;
23
+ try {
24
+ parsed = JSON.parse(trimmed);
25
+ }
26
+ catch {
27
+ return trimmed.startsWith("{") ? { kind: "ignore" } : { kind: "content", text: trimmed };
28
+ }
29
+ const event = record(parsed);
30
+ if (!event)
31
+ return { kind: "ignore" };
32
+ const type = typeof event.type === "string" ? event.type : "";
33
+ const part = record(event.part);
34
+ const text = (part && typeof part.text === "string" && part.text) ||
35
+ (typeof event.text === "string" && event.text) ||
36
+ "";
37
+ if (type === "text" && text)
38
+ return { kind: "content", text };
39
+ if (type === "reasoning" && text)
40
+ return { kind: "reasoning", text };
41
+ if (type === "step_finish" || type === "step-finish") {
42
+ const reason = part && typeof part.reason === "string" ? part.reason : "stop";
43
+ const tokens = record(part?.tokens);
44
+ let usage;
45
+ if (tokens) {
46
+ const prompt = typeof tokens.input === "number" ? tokens.input : 0;
47
+ const completion = typeof tokens.output === "number" ? tokens.output : 0;
48
+ const total = typeof tokens.total === "number" ? tokens.total : prompt + completion;
49
+ usage = { prompt_tokens: prompt, completion_tokens: completion, total_tokens: total };
50
+ }
51
+ return {
52
+ kind: "finish",
53
+ finishReason: reason === "length" ? "length" : reason === "error" ? "error" : "stop",
54
+ usage,
55
+ };
56
+ }
57
+ if (type === "error") {
58
+ const error = record(event.error);
59
+ const message = (typeof event.message === "string" && event.message) ||
60
+ (error && typeof error.message === "string" && error.message) ||
61
+ "OpenCode stream error";
62
+ return { kind: "error", message };
63
+ }
64
+ return { kind: "ignore" };
65
+ }
66
+ function localModel(model) {
67
+ if (!model || model === "default")
68
+ return null;
69
+ return model.includes("/") ? model : `opencode/${model}`;
70
+ }
71
+ export function createOpenCodeAdapter(opts = {}) {
72
+ const binary = opts.binary ?? "opencode";
73
+ const timeoutMs = opts.timeoutMs ?? 180_000;
74
+ const agent = opts.agent ?? "plan";
75
+ const wordDelay = opts.contentWordDelayMs ?? DEFAULT_WORD_DELAY_MS;
76
+ return {
77
+ id: "opencode",
78
+ description: "OpenCode CLI via `opencode run --format json` (plan agent)",
79
+ async listModels() {
80
+ return DEFAULT_MODELS.map((model) => ({
81
+ id: `opencode/${model}`,
82
+ object: "model",
83
+ created: 0,
84
+ owned_by: "opencode",
85
+ description: model === "default" ? "Uses the OpenCode default model" : undefined,
86
+ }));
87
+ },
88
+ async *chat(req, signal) {
89
+ const path = await which(binary);
90
+ if (!path) {
91
+ yield {
92
+ type: "error",
93
+ message: `opencode binary not found on PATH (looked for "${binary}"). Install OpenCode or set CLI2API_OPENCODE_BIN.`,
94
+ code: "binary_missing",
95
+ };
96
+ return;
97
+ }
98
+ const args = ["run", "--pure", "--format", "json", "--thinking", "--agent", agent];
99
+ if (req.nativeSessionId)
100
+ args.push("--session", req.nativeSessionId);
101
+ const model = localModel(req.modelLocal);
102
+ if (model)
103
+ args.push("--model", model);
104
+ if (opts.extraArgs?.length)
105
+ args.push(...opts.extraArgs);
106
+ args.push(requestToPrompt(req));
107
+ let sawContent = false;
108
+ let exitCode = null;
109
+ let timedOut = false;
110
+ let stderr = "";
111
+ let finishReason = "stop";
112
+ let usage;
113
+ let emittedSessionId;
114
+ const delay = req.stream ? wordDelay : 0;
115
+ try {
116
+ for await (const event of runCommandLines(path, args, {
117
+ cwd: opts.cwd,
118
+ timeoutMs,
119
+ signal,
120
+ inheritEnv: ["OPENCODE_CONFIG", "OPENCODE_CONFIG_DIR", "OPENCODE_CONFIG_CONTENT"],
121
+ })) {
122
+ if (event.type === "stdout_line") {
123
+ const sessionId = openCodeSessionId(event.line);
124
+ if (sessionId && sessionId !== emittedSessionId) {
125
+ emittedSessionId = sessionId;
126
+ yield { type: "session", id: sessionId };
127
+ }
128
+ const parsed = parseOpenCodeLine(event.line);
129
+ if (parsed.kind === "content" || parsed.kind === "reasoning") {
130
+ if (parsed.kind === "content")
131
+ sawContent = true;
132
+ for await (const delta of fakeStreamWords(parsed.text, delay, signal, parsed.kind)) {
133
+ yield delta;
134
+ if (delta.type === "error")
135
+ return;
136
+ }
137
+ }
138
+ else if (parsed.kind === "finish") {
139
+ finishReason = parsed.finishReason;
140
+ usage = parsed.usage ?? usage;
141
+ }
142
+ else if (parsed.kind === "error") {
143
+ yield { type: "error", message: parsed.message, code: "cli_error" };
144
+ return;
145
+ }
146
+ }
147
+ else if (event.type === "exit") {
148
+ exitCode = event.code;
149
+ timedOut = event.timedOut;
150
+ stderr = event.stderr;
151
+ }
152
+ }
153
+ }
154
+ catch (error) {
155
+ yield {
156
+ type: "error",
157
+ message: `Failed to spawn opencode: ${error instanceof Error ? error.message : String(error)}`,
158
+ code: "spawn_error",
159
+ };
160
+ return;
161
+ }
162
+ if (timedOut) {
163
+ yield { type: "error", message: `opencode timed out after ${timeoutMs}ms`, code: "timeout" };
164
+ }
165
+ else if (signal.aborted) {
166
+ yield { type: "error", message: "Aborted", code: "abort" };
167
+ }
168
+ else if (exitCode !== 0) {
169
+ yield {
170
+ type: "error",
171
+ message: `opencode exited with code ${exitCode}${stderr.trim() ? `: ${stderr.trim().slice(0, 2000)}` : ""}`,
172
+ code: "cli_error",
173
+ };
174
+ }
175
+ else if (!sawContent) {
176
+ yield { type: "error", message: "opencode returned empty output", code: "empty_output" };
177
+ }
178
+ else {
179
+ yield { type: "done", finishReason, usage };
180
+ }
181
+ },
182
+ async health() {
183
+ const path = await which(binary);
184
+ if (!path)
185
+ return { ok: false, adapter: "opencode", details: { binary }, message: "opencode binary not found on PATH" };
186
+ const version = await runCommand(path, ["--version"], { timeoutMs: 8_000 });
187
+ return {
188
+ ok: version.code === 0,
189
+ adapter: "opencode",
190
+ details: { binary: path, version: (version.stdout || version.stderr).trim(), agent },
191
+ message: version.code === 0 ? "opencode available" : "opencode --version failed",
192
+ };
193
+ },
194
+ async doctor() {
195
+ const path = await which(binary);
196
+ const checks = [{ name: "binary-on-path", ok: Boolean(path), detail: path ?? `missing: ${binary}` }];
197
+ let version;
198
+ if (path) {
199
+ const result = await runCommand(path, ["--version"], { timeoutMs: 8_000 });
200
+ version = (result.stdout || result.stderr).trim();
201
+ checks.push({ name: "version", ok: result.code === 0, detail: version || `exit ${result.code}` });
202
+ }
203
+ checks.push({ name: "restrictive-default", ok: agent === "plan", detail: `agent=${agent}; external plugins disabled` });
204
+ return { adapter: "opencode", ok: checks.every((check) => check.ok), binary: path ?? binary, version, checks };
205
+ },
206
+ };
207
+ }
208
+ //# sourceMappingURL=opencode.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"opencode.js","sourceRoot":"","sources":["../../src/adapters/opencode.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,33 @@
1
+ import type { Adapter } from "./types.js";
2
+ import { type CodexAdapterOptions } from "./codex.js";
3
+ import { type OpenCodeAdapterOptions } from "./opencode.js";
4
+ import { type CursorAdapterOptions } from "./cursor.js";
5
+ import { type ClaudeAdapterOptions } from "./claude.js";
6
+ import type { ModelRoute, NormalizedChatRequest } from "../types.js";
7
+ export type AdapterId = "mock" | "codex" | "opencode" | "cursor" | "claude";
8
+ export interface CreateRegistryOptions {
9
+ defaultAdapter?: AdapterId;
10
+ codex?: CodexAdapterOptions;
11
+ opencode?: OpenCodeAdapterOptions;
12
+ cursor?: CursorAdapterOptions;
13
+ claude?: ClaudeAdapterOptions;
14
+ modelAliases?: Record<string, string>;
15
+ modelRoutes?: Record<string, ModelRoute>;
16
+ }
17
+ export declare class AdapterRegistry {
18
+ private adapters;
19
+ readonly defaultAdapterId: string;
20
+ readonly modelAliases: Readonly<Record<string, string>>;
21
+ readonly modelRoutes: Readonly<Record<string, ModelRoute>>;
22
+ constructor(opts?: CreateRegistryOptions);
23
+ register(adapter: Adapter): void;
24
+ get(id: string): Adapter | undefined;
25
+ list(): Adapter[];
26
+ resolveModelId(model: string): string;
27
+ normalizeRequest(req: NormalizedChatRequest): NormalizedChatRequest;
28
+ listModels(): Promise<import("../types.js").ModelInfo[]>;
29
+ isExplicitlyRoutable(model: string): boolean;
30
+ /** Resolve adapter from model id (`codex/o3`) or explicit --adapter. */
31
+ resolve(model: string, preferredAdapter?: string): Adapter;
32
+ }
33
+ export declare function createRegistry(opts?: CreateRegistryOptions): AdapterRegistry;