@euqns/nudge-mcp 1.5.0 → 1.7.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.
@@ -4,6 +4,7 @@
4
4
  import { Codex, } from "@openai/codex-sdk";
5
5
  import { spawnSync } from "node:child_process";
6
6
  import { companionCodexConfig, subscriptionEnvironment, } from "../codex-companion.js";
7
+ import { classifyEngineFailure, collapseRepeatedLines } from "./failures.js";
7
8
  import { ensureCodexShadowHome } from "./isolation.js";
8
9
  import { estimateCostUsd } from "./pricing.js";
9
10
  import { TRIAGE_SCHEMA, buildTriagePrompt, coerceVerdict, emptyUsage, } from "./types.js";
@@ -139,47 +140,104 @@ export class CodexEngine {
139
140
  ? { networkAccessEnabled: true }
140
141
  : {}),
141
142
  };
142
- const thread = options.threadId
143
- ? this.client().resumeThread(options.threadId, opts)
144
- : this.client().startThread(opts);
145
143
  const usage = emptyUsage();
146
144
  let summary = "";
147
145
  let threadId = options.threadId ?? undefined;
148
146
  let error;
149
- const streamed = await thread.runStreamed(options.prompt, {
150
- signal: options.signal,
151
- });
152
- for await (const event of streamed.events) {
153
- if (event.type === "thread.started") {
154
- threadId = event.thread_id;
155
- // Surfaced immediately so an aborted turn (steer) stays resumable —
156
- // a local capture alone is lost when the abort throws out of here.
157
- options.onThreadId?.(event.thread_id);
158
- }
159
- else if (event.type === "item.completed") {
160
- const line = describeItem(event.item);
161
- if (line)
162
- options.log("event", line);
163
- if (event.item.type === "agent_message")
164
- summary = event.item.text;
165
- }
166
- else if (event.type === "turn.failed") {
167
- error = event.error.message;
168
- options.log("stderr", `turn failed: ${event.error.message}`);
147
+ const MAX_ATTEMPTS = 3;
148
+ const BACKOFFS_MS = [3_000, 10_000];
149
+ // Retry is only safe while the turn has produced no real work — once a
150
+ // command ran or a file changed, re-sending the prompt could redo it.
151
+ const canRetry = (transient, sawWorkItem, attempt) => transient && !sawWorkItem && !options.signal.aborted && attempt < MAX_ATTEMPTS;
152
+ const backoffBeforeRetry = async (attempt, detail) => {
153
+ const backoff = BACKOFFS_MS[attempt - 1] ?? BACKOFFS_MS[BACKOFFS_MS.length - 1];
154
+ options.log("event", `codex transport failed before any work completed (${detail}) retrying in ${backoff / 1000}s (attempt ${attempt + 1}/${MAX_ATTEMPTS})`);
155
+ await new Promise((resolve) => setTimeout(resolve, backoff));
156
+ };
157
+ for (let attempt = 1; attempt <= MAX_ATTEMPTS; attempt++) {
158
+ // Codex emits thread.started before its first network call, so even a
159
+ // turn that never reached the model leaves a thread id behind. A retry
160
+ // resumes that (still-empty) thread rather than starting a fresh one —
161
+ // gating retry on "thread never started" would mean never retrying.
162
+ const resumeId = options.threadId ?? (attempt > 1 ? threadId : undefined);
163
+ const thread = resumeId
164
+ ? this.client().resumeThread(resumeId, opts)
165
+ : this.client().startThread(opts);
166
+ // A previous attempt's reconnect notices, partial summary, and
167
+ // turn.failed message must not survive into this attempt's result.
168
+ error = undefined;
169
+ summary = "";
170
+ // Transport fallbacks arrive as item.completed with type "error" —
171
+ // those don't count as work.
172
+ let sawWorkItem = false;
173
+ try {
174
+ const streamed = await thread.runStreamed(options.prompt, {
175
+ signal: options.signal,
176
+ });
177
+ for await (const event of streamed.events) {
178
+ if (event.type === "thread.started") {
179
+ threadId = event.thread_id;
180
+ // Surfaced immediately so an aborted turn (steer) stays resumable
181
+ // — a local capture alone is lost when the abort throws out of
182
+ // here.
183
+ options.onThreadId?.(event.thread_id);
184
+ }
185
+ else if (event.type === "item.completed") {
186
+ if (event.item.type !== "error")
187
+ sawWorkItem = true;
188
+ const line = describeItem(event.item);
189
+ if (line)
190
+ options.log("event", line);
191
+ if (event.item.type === "agent_message")
192
+ summary = event.item.text;
193
+ }
194
+ else if (event.type === "turn.failed") {
195
+ error = event.error.message;
196
+ options.log("stderr", `turn failed: ${event.error.message}`);
197
+ }
198
+ else if (event.type === "error") {
199
+ // Usually a recoverable reconnect notice ("Reconnecting... 2/5").
200
+ // Recorded as the failure-in-progress; cleared below if the turn
201
+ // completes anyway.
202
+ error = event.message;
203
+ options.log("stderr", event.message);
204
+ }
205
+ else if (event.type === "turn.completed") {
206
+ // The turn finished — any error event before this was a blip the
207
+ // stream recovered from, not a result-worthy failure.
208
+ error = undefined;
209
+ usage.inputTokens += event.usage.input_tokens;
210
+ usage.outputTokens += event.usage.output_tokens;
211
+ usage.cachedInputTokens =
212
+ (usage.cachedInputTokens ?? 0) + event.usage.cached_input_tokens;
213
+ usage.reasoningTokens =
214
+ (usage.reasoningTokens ?? 0) + event.usage.reasoning_output_tokens;
215
+ options.log("event", `turn complete — ${event.usage.input_tokens} in / ${event.usage.output_tokens} out tokens`);
216
+ }
217
+ }
169
218
  }
170
- else if (event.type === "error") {
171
- error = event.message;
172
- options.log("stderr", event.message);
219
+ catch (err) {
220
+ const message = err instanceof Error ? err.message : String(err);
221
+ const failure = classifyEngineFailure(message);
222
+ if (!canRetry(failure.transient, sawWorkItem, attempt)) {
223
+ options.log("stderr", collapseRepeatedLines(failure.raw));
224
+ throw new Error(failure.summary);
225
+ }
226
+ await backoffBeforeRetry(attempt, failure.summary);
227
+ continue;
173
228
  }
174
- else if (event.type === "turn.completed") {
175
- usage.inputTokens += event.usage.input_tokens;
176
- usage.outputTokens += event.usage.output_tokens;
177
- usage.cachedInputTokens =
178
- (usage.cachedInputTokens ?? 0) + event.usage.cached_input_tokens;
179
- usage.reasoningTokens =
180
- (usage.reasoningTokens ?? 0) + event.usage.reasoning_output_tokens;
181
- options.log("event", `turn complete — ${event.usage.input_tokens} in / ${event.usage.output_tokens} out tokens`);
229
+ // A transient turn.failed can end the stream without a throw — give it
230
+ // the same retry the thrown path gets, and the same readable one-liner
231
+ // when it stays terminal.
232
+ if (error) {
233
+ const failure = classifyEngineFailure(error);
234
+ if (canRetry(failure.transient, sawWorkItem, attempt)) {
235
+ await backoffBeforeRetry(attempt, failure.summary);
236
+ continue;
237
+ }
238
+ error = failure.summary;
182
239
  }
240
+ break;
183
241
  }
184
242
  // A ChatGPT-plan run isn't billed per token, but the tokens are real —
185
243
  // price them at list rates so a job still shows what it was worth. Flagged
@@ -1 +1 @@
1
- {"version":3,"file":"codex.js","sourceRoot":"","sources":["../../src/engines/codex.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"codex.js","sourceRoot":"","sources":["../../src/engines/codex.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,206 @@
1
+ import { spawn, spawnSync } from "node:child_process";
2
+ import { mkdtemp, mkdir, rm, writeFile } from "node:fs/promises";
3
+ import os from "node:os";
4
+ import path from "node:path";
5
+ import readline from "node:readline";
6
+ import { companionMcpTransport, parseCursorModels, subscriptionEnvironment } from "../codex-companion.js";
7
+ import { buildTriagePrompt, coerceVerdict, emptyUsage, } from "./types.js";
8
+ export const CURSOR_CLI = process.platform === "win32" ? "cursor-agent.cmd" : "cursor-agent";
9
+ export function parseCursorEvent(line) {
10
+ try {
11
+ const value = JSON.parse(line);
12
+ return value && typeof value === "object" ? value : null;
13
+ }
14
+ catch {
15
+ return null;
16
+ }
17
+ }
18
+ // Kept in sync with `cursorModelMatches` in convex/runners.ts — convex can't
19
+ // import this standalone package, so the matching rules are duplicated there.
20
+ // Exact match wins, then case-insensitive, then a `-latest`/family stem
21
+ // prefix (so "grok-4.6-latest" matches an installed "grok-4.6-fast").
22
+ export function cursorModelMatches(alias, available) {
23
+ const requested = alias.trim();
24
+ if (!requested)
25
+ return null;
26
+ const exact = available.find((model) => model === requested);
27
+ if (exact)
28
+ return exact;
29
+ const lower = requested.toLowerCase();
30
+ const insensitive = available.find((model) => model.toLowerCase() === lower);
31
+ if (insensitive)
32
+ return insensitive;
33
+ const stem = lower.endsWith("-latest") ? lower.slice(0, -"-latest".length) : lower;
34
+ const family = available.find((model) => model.toLowerCase().startsWith(stem));
35
+ return family ?? null;
36
+ }
37
+ export function resolveCursorModel(alias, available) {
38
+ const requested = alias?.trim();
39
+ if (!requested || requested === "auto")
40
+ return available[0] ?? "auto";
41
+ const matched = cursorModelMatches(requested, available);
42
+ if (matched)
43
+ return matched;
44
+ throw new Error(`Cursor model alias "${requested}" is unavailable. Available models: ${available.join(", ") || "none discovered"}. ` +
45
+ "Install/update cursor-agent and sign in with `cursor-agent login`, then retry.");
46
+ }
47
+ async function listModels() {
48
+ const result = await new Promise((resolve, reject) => {
49
+ const child = spawn(CURSOR_CLI, ["--list-models"], {
50
+ env: subscriptionEnvironment(),
51
+ stdio: ["ignore", "pipe", "pipe"],
52
+ });
53
+ let stdout = "";
54
+ let stderr = "";
55
+ child.stdout.on("data", (chunk) => { stdout += chunk.toString("utf8"); });
56
+ child.stderr.on("data", (chunk) => { stderr = `${stderr}${chunk.toString("utf8")}`.slice(-8_000); });
57
+ child.once("error", reject);
58
+ child.once("close", (code) => resolve({ stdout, stderr, code }));
59
+ });
60
+ if (result.code !== 0)
61
+ throw new Error(result.stderr.trim() || `Cursor model discovery exited ${result.code}`);
62
+ return parseCursorModels(result.stdout).map((model) => model.model);
63
+ }
64
+ async function isolatedCursorEnv(options) {
65
+ const home = await mkdtemp(path.join(os.tmpdir(), "nudge-cursor-"));
66
+ const cursorDir = path.join(home, ".cursor");
67
+ await mkdir(cursorDir, { recursive: true });
68
+ const transport = companionMcpTransport();
69
+ await writeFile(path.join(cursorDir, "mcp.json"), JSON.stringify({
70
+ mcpServers: {
71
+ nudge: {
72
+ command: transport.command,
73
+ args: transport.args,
74
+ env: options.env ?? {},
75
+ },
76
+ },
77
+ }));
78
+ const env = subscriptionEnvironment({ ...process.env, ...(options.env ?? {}) });
79
+ return {
80
+ env: { ...env, HOME: home, CURSOR_CONFIG_DIR: cursorDir, XDG_CONFIG_HOME: home },
81
+ cleanup: async () => { await rm(home, { recursive: true, force: true }); },
82
+ };
83
+ }
84
+ function usageFrom(value) {
85
+ const usage = value && typeof value === "object" ? value : {};
86
+ const number = (...keys) => {
87
+ for (const key of keys)
88
+ if (typeof usage[key] === "number")
89
+ return usage[key];
90
+ return 0;
91
+ };
92
+ return {
93
+ inputTokens: number("input_tokens", "inputTokens"),
94
+ outputTokens: number("output_tokens", "outputTokens"),
95
+ cachedInputTokens: number("cached_input_tokens", "cachedInputTokens") || undefined,
96
+ reasoningTokens: number("reasoning_output_tokens", "reasoningTokens") || undefined,
97
+ };
98
+ }
99
+ function eventText(event) {
100
+ if (typeof event.result === "string")
101
+ return event.result;
102
+ if (typeof event.text === "string")
103
+ return event.text;
104
+ const call = event.tool_call;
105
+ if (call && typeof call === "object")
106
+ return `Cursor tool: ${Object.keys(call)[0] ?? "unknown"}`;
107
+ if (event.type === "error" && typeof event.message === "string")
108
+ return `error: ${event.message}`;
109
+ return null;
110
+ }
111
+ export class CursorEngine {
112
+ id = "cursor";
113
+ displayName = "Cursor";
114
+ models = [];
115
+ async detect() {
116
+ const version = spawnSync(CURSOR_CLI, ["--version"], { encoding: "utf8", stdio: ["ignore", "pipe", "pipe"] });
117
+ if (version.error || version.status !== 0)
118
+ return { available: false, detail: "cursor-agent CLI not found" };
119
+ const help = spawnSync(CURSOR_CLI, ["--help"], { encoding: "utf8", stdio: ["ignore", "pipe", "pipe"] });
120
+ const helpText = `${help.stdout ?? ""}\n${help.stderr ?? ""}`;
121
+ const status = spawnSync(CURSOR_CLI, ["status"], { encoding: "utf8", stdio: ["ignore", "pipe", "pipe"] });
122
+ const authenticated = status.status === 0 && !/not logged|log in|unauthorized/i.test(`${status.stdout ?? ""}\n${status.stderr ?? ""}`);
123
+ if (!authenticated)
124
+ return { available: false, detail: "cursor-agent is installed but not authenticated" };
125
+ try {
126
+ this.models = await listModels();
127
+ }
128
+ catch (error) {
129
+ return { available: false, detail: error instanceof Error ? error.message : String(error) };
130
+ }
131
+ const capabilities = {
132
+ version: (version.stdout ?? version.stderr ?? "").trim(),
133
+ authenticated: true,
134
+ models: this.models,
135
+ modes: ["plan", "ask", "agent"].filter((mode) => mode === "agent" || helpText.includes(mode)),
136
+ resume: helpText.includes("--resume") || helpText.includes("--continue"),
137
+ };
138
+ return { available: true, detail: `${capabilities.version} · ${this.models.length} models`, capabilities };
139
+ }
140
+ async triage(options) {
141
+ const result = await this.execute({ ...options, prompt: buildTriagePrompt(options.prompt), readOnly: true, model: options.model ?? "auto" });
142
+ return { verdict: coerceVerdict(result.summary), usage: result.usage, threadId: result.threadId };
143
+ }
144
+ async execute(options) {
145
+ const models = this.models.length ? this.models : await listModels();
146
+ const resolvedModel = resolveCursorModel(options.model, models);
147
+ const runtime = await isolatedCursorEnv(options);
148
+ const args = [
149
+ "-p", "--output-format", "stream-json", "--model", resolvedModel,
150
+ "--workspace", options.cwd, "--trust", "--approve-mcps",
151
+ ...(options.readOnly ? ["--mode=plan"] : ["--force", "--sandbox", "disabled"]),
152
+ ...(options.threadId ? ["--resume", options.threadId] : []),
153
+ options.prompt,
154
+ ];
155
+ let summary = "";
156
+ let threadId = options.threadId ?? undefined;
157
+ let usage = emptyUsage();
158
+ let error;
159
+ try {
160
+ await new Promise((resolve, reject) => {
161
+ const child = spawn(CURSOR_CLI, args, { cwd: options.cwd, env: runtime.env, stdio: ["ignore", "pipe", "pipe"] });
162
+ let stderr = "";
163
+ const lines = readline.createInterface({ input: child.stdout, crlfDelay: Infinity });
164
+ lines.on("line", (line) => {
165
+ const event = parseCursorEvent(line);
166
+ if (!event)
167
+ return;
168
+ const id = event.session_id ?? event.chat_id;
169
+ if (typeof id === "string") {
170
+ threadId = id;
171
+ options.onThreadId?.(id);
172
+ }
173
+ const text = eventText(event);
174
+ if (text)
175
+ options.log(event.type === "error" ? "stderr" : "event", text);
176
+ if (typeof event.result === "string")
177
+ summary = event.result;
178
+ if (event.usage)
179
+ usage = { ...usage, ...usageFrom(event.usage) };
180
+ });
181
+ child.stderr.on("data", (chunk) => { stderr = `${stderr}${chunk.toString("utf8")}`.slice(-8_000); });
182
+ const abort = () => child.kill("SIGTERM");
183
+ options.signal.addEventListener("abort", abort, { once: true });
184
+ child.once("error", reject);
185
+ child.once("close", (code) => {
186
+ options.signal.removeEventListener("abort", abort);
187
+ if (options.signal.aborted)
188
+ return reject(new Error("Cursor turn cancelled"));
189
+ if (code !== 0)
190
+ return reject(new Error(`Cursor exited ${code}: ${stderr.trim() || "no error detail"}`));
191
+ resolve();
192
+ });
193
+ });
194
+ }
195
+ catch (caught) {
196
+ error = caught instanceof Error ? caught.message : String(caught);
197
+ if (!options.signal.aborted)
198
+ throw caught;
199
+ }
200
+ finally {
201
+ await runtime.cleanup();
202
+ }
203
+ return { summary, threadId, resolvedModel, usage, costBasis: "subscription", error };
204
+ }
205
+ }
206
+ //# sourceMappingURL=cursor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cursor.js","sourceRoot":"","sources":["../../src/engines/cursor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ import assert from "node:assert/strict";
2
+ import test from "node:test";
3
+ import { cursorModelMatches, parseCursorEvent, resolveCursorModel } from "./cursor.js";
4
+ test("Cursor resolves exact and latest family aliases", () => {
5
+ assert.equal(resolveCursorModel("grok-4.6", ["grok-4.6", "composer-1"]), "grok-4.6");
6
+ assert.equal(resolveCursorModel("composer-latest", ["composer-1", "gpt-5"]), "composer-1");
7
+ });
8
+ test("cursorModelMatches matches exact, case-insensitive, and family stem", () => {
9
+ assert.equal(cursorModelMatches("grok-4.6", ["grok-4.6", "composer-1"]), "grok-4.6");
10
+ assert.equal(cursorModelMatches("Grok-4.6", ["grok-4.6-fast"]), "grok-4.6-fast");
11
+ assert.equal(cursorModelMatches("grok-4.6", ["grok-4.6-fast"]), "grok-4.6-fast");
12
+ assert.equal(cursorModelMatches("composer-latest", ["composer-1", "gpt-5"]), "composer-1");
13
+ assert.equal(cursorModelMatches("gpt-6", ["grok-4.6", "composer-1"]), null);
14
+ assert.equal(cursorModelMatches("grok-4.6", []), null);
15
+ });
16
+ test("Cursor reports an actionable unavailable-model error", () => {
17
+ assert.throws(() => resolveCursorModel("grok-4.6", ["composer-1"]), /alias "grok-4\.6" is unavailable.*Available models: composer-1.*cursor-agent login/);
18
+ });
19
+ test("Cursor stream events are parsed defensively", () => {
20
+ assert.deepEqual(parseCursorEvent('{"type":"result","result":"done","session_id":"chat-1"}'), {
21
+ type: "result",
22
+ result: "done",
23
+ session_id: "chat-1",
24
+ });
25
+ assert.equal(parseCursorEvent("not json"), null);
26
+ });
27
+ //# sourceMappingURL=cursor.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cursor.test.js","sourceRoot":"","sources":["../../src/engines/cursor.test.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,oBAAoB,CAAC;AACxC,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,OAAO,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAEvF,IAAI,CAAC,iDAAiD,EAAE,GAAG,EAAE;IAC3D,MAAM,CAAC,KAAK,CAAC,kBAAkB,CAAC,UAAU,EAAE,CAAC,UAAU,EAAE,YAAY,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC;IACrF,MAAM,CAAC,KAAK,CAAC,kBAAkB,CAAC,iBAAiB,EAAE,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC,EAAE,YAAY,CAAC,CAAC;AAC7F,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,qEAAqE,EAAE,GAAG,EAAE;IAC/E,MAAM,CAAC,KAAK,CAAC,kBAAkB,CAAC,UAAU,EAAE,CAAC,UAAU,EAAE,YAAY,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC;IACrF,MAAM,CAAC,KAAK,CAAC,kBAAkB,CAAC,UAAU,EAAE,CAAC,eAAe,CAAC,CAAC,EAAE,eAAe,CAAC,CAAC;IACjF,MAAM,CAAC,KAAK,CAAC,kBAAkB,CAAC,UAAU,EAAE,CAAC,eAAe,CAAC,CAAC,EAAE,eAAe,CAAC,CAAC;IACjF,MAAM,CAAC,KAAK,CAAC,kBAAkB,CAAC,iBAAiB,EAAE,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC,EAAE,YAAY,CAAC,CAAC;IAC3F,MAAM,CAAC,KAAK,CAAC,kBAAkB,CAAC,OAAO,EAAE,CAAC,UAAU,EAAE,YAAY,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;IAC5E,MAAM,CAAC,KAAK,CAAC,kBAAkB,CAAC,UAAU,EAAE,EAAE,CAAC,EAAE,IAAI,CAAC,CAAC;AACzD,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,sDAAsD,EAAE,GAAG,EAAE;IAChE,MAAM,CAAC,MAAM,CACX,GAAG,EAAE,CAAC,kBAAkB,CAAC,UAAU,EAAE,CAAC,YAAY,CAAC,CAAC,EACpD,oFAAoF,CACrF,CAAC;AACJ,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,6CAA6C,EAAE,GAAG,EAAE;IACvD,MAAM,CAAC,SAAS,CAAC,gBAAgB,CAAC,yDAAyD,CAAC,EAAE;QAC5F,IAAI,EAAE,QAAQ;QACd,MAAM,EAAE,MAAM;QACd,UAAU,EAAE,QAAQ;KACrB,CAAC,CAAC;IACH,MAAM,CAAC,KAAK,CAAC,gBAAgB,CAAC,UAAU,CAAC,EAAE,IAAI,CAAC,CAAC;AACnD,CAAC,CAAC,CAAC"}
@@ -0,0 +1,59 @@
1
+ // Classifies an engine failure message so a transient transport blip (proxy
2
+ // down, DNS drop, mid-stream disconnect) can be retried and reported in one
3
+ // readable line, while auth/model/schema failures stay terminal and verbatim.
4
+ // Transport phrases only. Deliberately excludes auth/model/schema phrases
5
+ // (401, 403, "not logged in", "invalid model") — those must stay terminal so
6
+ // a bad credential doesn't burn the retry budget pretending to be a blip.
7
+ const TRANSIENT_PATTERNS = [
8
+ /failed to lookup address information/i,
9
+ /error sending request for url/i,
10
+ /stream disconnected before completion/i,
11
+ /dns error/i,
12
+ /connection refused/i,
13
+ /connection reset/i,
14
+ /tls handshake/i,
15
+ /nodename nor servname provided/i,
16
+ ];
17
+ export function classifyEngineFailure(message) {
18
+ const transient = TRANSIENT_PATTERNS.some((pattern) => pattern.test(message));
19
+ if (!transient) {
20
+ return { transient: false, summary: message, raw: message };
21
+ }
22
+ return {
23
+ transient: true,
24
+ summary: "Codex couldn't reach chatgpt.com (DNS/connection failure talking to the " +
25
+ "model backend). Check this machine's network connectivity, VPN, and any " +
26
+ "HTTP_PROXY/HTTPS_PROXY/ALL_PROXY environment variables, then retry.",
27
+ raw: message,
28
+ };
29
+ }
30
+ // Folds runs of identical (or near-identical, ignoring a leading ISO
31
+ // timestamp) lines into one line with a "(×N)" suffix, so a flood of retried
32
+ // log lines doesn't drown the one thing that changed between them.
33
+ export function collapseRepeatedLines(text) {
34
+ const lines = text.split(/\r?\n/);
35
+ const stripTimestamp = (line) => line.replace(/^\d{4}-\d{2}-\d{2}T[\d:.]+Z\s*/, "");
36
+ const collapsed = [];
37
+ let currentKey = null;
38
+ let currentLine = "";
39
+ let count = 0;
40
+ const flush = () => {
41
+ if (currentKey === null)
42
+ return;
43
+ collapsed.push(count > 1 ? `${currentLine} (×${count})` : currentLine);
44
+ };
45
+ for (const line of lines) {
46
+ const key = stripTimestamp(line);
47
+ if (key === currentKey) {
48
+ count += 1;
49
+ continue;
50
+ }
51
+ flush();
52
+ currentKey = key;
53
+ currentLine = line;
54
+ count = 1;
55
+ }
56
+ flush();
57
+ return collapsed.join("\n");
58
+ }
59
+ //# sourceMappingURL=failures.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"failures.js","sourceRoot":"","sources":["../../src/engines/failures.ts"],"names":[],"mappings":"AAAA,4EAA4E;AAC5E,4EAA4E;AAC5E,8EAA8E;AAW9E,0EAA0E;AAC1E,6EAA6E;AAC7E,0EAA0E;AAC1E,MAAM,kBAAkB,GAAa;IACnC,uCAAuC;IACvC,gCAAgC;IAChC,wCAAwC;IACxC,YAAY;IACZ,qBAAqB;IACrB,mBAAmB;IACnB,gBAAgB;IAChB,iCAAiC;CAClC,CAAC;AAEF,MAAM,UAAU,qBAAqB,CAAC,OAAe;IACnD,MAAM,SAAS,GAAG,kBAAkB,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;IAC9E,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC;IAC9D,CAAC;IACD,OAAO;QACL,SAAS,EAAE,IAAI;QACf,OAAO,EACL,0EAA0E;YAC1E,0EAA0E;YAC1E,qEAAqE;QACvE,GAAG,EAAE,OAAO;KACb,CAAC;AACJ,CAAC;AAED,qEAAqE;AACrE,6EAA6E;AAC7E,mEAAmE;AACnE,MAAM,UAAU,qBAAqB,CAAC,IAAY;IAChD,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAClC,MAAM,cAAc,GAAG,CAAC,IAAY,EAAE,EAAE,CACtC,IAAI,CAAC,OAAO,CAAC,gCAAgC,EAAE,EAAE,CAAC,CAAC;IAErD,MAAM,SAAS,GAAa,EAAE,CAAC;IAC/B,IAAI,UAAU,GAAkB,IAAI,CAAC;IACrC,IAAI,WAAW,GAAG,EAAE,CAAC;IACrB,IAAI,KAAK,GAAG,CAAC,CAAC;IAEd,MAAM,KAAK,GAAG,GAAG,EAAE;QACjB,IAAI,UAAU,KAAK,IAAI;YAAE,OAAO;QAChC,SAAS,CAAC,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,WAAW,MAAM,KAAK,GAAG,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC;IACzE,CAAC,CAAC;IAEF,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,GAAG,GAAG,cAAc,CAAC,IAAI,CAAC,CAAC;QACjC,IAAI,GAAG,KAAK,UAAU,EAAE,CAAC;YACvB,KAAK,IAAI,CAAC,CAAC;YACX,SAAS;QACX,CAAC;QACD,KAAK,EAAE,CAAC;QACR,UAAU,GAAG,GAAG,CAAC;QACjB,WAAW,GAAG,IAAI,CAAC;QACnB,KAAK,GAAG,CAAC,CAAC;IACZ,CAAC;IACD,KAAK,EAAE,CAAC;IAER,OAAO,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC9B,CAAC"}
@@ -0,0 +1,44 @@
1
+ import assert from "node:assert/strict";
2
+ import test from "node:test";
3
+ import { classifyEngineFailure, collapseRepeatedLines } from "./failures.js";
4
+ const CARD_STDERR = [
5
+ "Reading prompt from stdin...",
6
+ "2026-08-18T21:49:55.710430Z ERROR codex_models_manager::manager: failed to refresh available models: stream disconnected before completion: error sending request for url ( https://chatgpt.com/backend-api/codex/models?client_version=0.145.0 )",
7
+ "2026-08-18T21:49:55.893208Z ERROR rmcp::transport::worker: worker quit with fatal: Transport channel closed, when Client(HttpRequest(HttpRequest(\"http/request failed: error sending request for url ( https://chatgpt.com/backend-api/ps/mcp )\")))",
8
+ "2026-08-18T21:49:56.169036Z ERROR codex_api::endpoint::responses_websocket: failed to connect to websocket: IO error: failed to lookup address information: nodename nor servname provided, or not known, url: wss://chatgpt.com/backend-api/codex/responses",
9
+ ].join("\n");
10
+ test("classifies the chatgpt.com transport failure from the reported card as transient", () => {
11
+ const result = classifyEngineFailure(CARD_STDERR);
12
+ assert.equal(result.transient, true);
13
+ assert.match(result.summary, /chatgpt\.com/i);
14
+ assert.match(result.summary, /proxy/i);
15
+ assert.equal(result.raw, CARD_STDERR);
16
+ });
17
+ test("classifies a mid-turn reconnect notice as transient", () => {
18
+ // Emitted as a stream `error` event while Codex retries the transport; the
19
+ // turn often completes anyway, and when it doesn't the retry loop needs to
20
+ // recognize it.
21
+ const result = classifyEngineFailure("Reconnecting... 2/5 (stream disconnected before completion: Connection refused (os error 61))");
22
+ assert.equal(result.transient, true);
23
+ });
24
+ test("keeps an auth failure terminal", () => {
25
+ const message = "Codex Exec exited with code 1: Error: not logged in";
26
+ const result = classifyEngineFailure(message);
27
+ assert.equal(result.transient, false);
28
+ assert.equal(result.summary, message);
29
+ });
30
+ test("collapses repeated websocket retry lines", () => {
31
+ const lines = [
32
+ "2026-08-18T21:49:56.169036Z ERROR websocket: failed to connect",
33
+ "2026-08-18T21:49:56.264566Z ERROR websocket: failed to connect",
34
+ "2026-08-18T21:49:56.573724Z ERROR websocket: failed to connect",
35
+ "2026-08-18T21:49:57.081144Z ERROR websocket: failed to connect",
36
+ "2026-08-18T21:49:57.952586Z ERROR websocket: failed to connect",
37
+ "2026-08-18T21:49:59.810712Z ERROR websocket: failed to connect",
38
+ "2026-08-18T21:50:02.940448Z ERROR websocket: failed to connect",
39
+ ].join("\n");
40
+ const collapsed = collapseRepeatedLines(lines);
41
+ assert.equal(collapsed.split("\n").length, 1);
42
+ assert.match(collapsed, /\(×7\)$/);
43
+ });
44
+ //# sourceMappingURL=failures.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"failures.test.js","sourceRoot":"","sources":["../../src/engines/failures.test.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,oBAAoB,CAAC;AACxC,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,OAAO,EAAE,qBAAqB,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAC;AAE7E,MAAM,WAAW,GAAG;IAClB,8BAA8B;IAC9B,mPAAmP;IACnP,uPAAuP;IACvP,8PAA8P;CAC/P,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAEb,IAAI,CAAC,kFAAkF,EAAE,GAAG,EAAE;IAC5F,MAAM,MAAM,GAAG,qBAAqB,CAAC,WAAW,CAAC,CAAC;IAClD,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;IACrC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,OAAO,EAAE,eAAe,CAAC,CAAC;IAC9C,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;IACvC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,EAAE,WAAW,CAAC,CAAC;AACxC,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,qDAAqD,EAAE,GAAG,EAAE;IAC/D,2EAA2E;IAC3E,2EAA2E;IAC3E,gBAAgB;IAChB,MAAM,MAAM,GAAG,qBAAqB,CAClC,+FAA+F,CAChG,CAAC;IACF,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;AACvC,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,gCAAgC,EAAE,GAAG,EAAE;IAC1C,MAAM,OAAO,GAAG,qDAAqD,CAAC;IACtE,MAAM,MAAM,GAAG,qBAAqB,CAAC,OAAO,CAAC,CAAC;IAC9C,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;IACtC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;AACxC,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,0CAA0C,EAAE,GAAG,EAAE;IACpD,MAAM,KAAK,GAAG;QACZ,gEAAgE;QAChE,gEAAgE;QAChE,gEAAgE;QAChE,gEAAgE;QAChE,gEAAgE;QAChE,gEAAgE;QAChE,gEAAgE;KACjE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACb,MAAM,SAAS,GAAG,qBAAqB,CAAC,KAAK,CAAC,CAAC;IAC/C,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;IAC9C,MAAM,CAAC,KAAK,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;AACrC,CAAC,CAAC,CAAC"}
@@ -1,11 +1,14 @@
1
1
  // Engine registry and startup detection.
2
2
  import { ClaudeEngine } from "./claude.js";
3
3
  import { CodexEngine } from "./codex.js";
4
+ import { CursorEngine } from "./cursor.js";
4
5
  export * from "./types.js";
5
6
  export { CodexEngine } from "./codex.js";
6
7
  export { ClaudeEngine } from "./claude.js";
8
+ export { CursorEngine } from "./cursor.js";
9
+ export { classifyEngineFailure, collapseRepeatedLines } from "./failures.js";
7
10
  export function allEngines() {
8
- return [new CodexEngine(), new ClaudeEngine()];
11
+ return [new CodexEngine(), new ClaudeEngine(), new CursorEngine()];
9
12
  }
10
13
  // Probe every engine once at startup. The runner reports the available ids to
11
14
  // the server, which then only offers this machine jobs it can actually run —
@@ -14,8 +17,8 @@ export function allEngines() {
14
17
  export async function detectEngines() {
15
18
  return await Promise.all(allEngines().map(async (engine) => {
16
19
  try {
17
- const { available, detail } = await engine.detect();
18
- return { engine, available, detail };
20
+ const { available, detail, capabilities } = await engine.detect();
21
+ return { engine, available, detail, capabilities };
19
22
  }
20
23
  catch (err) {
21
24
  return {
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/engines/index.ts"],"names":[],"mappings":"AAAA,yCAAyC;AAEzC,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAGzC,cAAc,YAAY,CAAC;AAC3B,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACzC,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C,MAAM,UAAU,UAAU;IACxB,OAAO,CAAC,IAAI,WAAW,EAAE,EAAE,IAAI,YAAY,EAAE,CAAC,CAAC;AACjD,CAAC;AAQD,8EAA8E;AAC9E,6EAA6E;AAC7E,6EAA6E;AAC7E,4BAA4B;AAC5B,MAAM,CAAC,KAAK,UAAU,aAAa;IACjC,OAAO,MAAM,OAAO,CAAC,GAAG,CACtB,UAAU,EAAE,CAAC,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE;QAChC,IAAI,CAAC;YACH,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,MAAM,MAAM,CAAC,MAAM,EAAE,CAAC;YACpD,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,CAAC;QACvC,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO;gBACL,MAAM;gBACN,SAAS,EAAE,KAAK;gBAChB,MAAM,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;aACzD,CAAC;QACJ,CAAC;IACH,CAAC,CAAC,CACH,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,UAAU,CACxB,QAA0B,EAC1B,EAAY;IAEZ,MAAM,KAAK,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC,SAAS,CAAC,CAAC;IACtE,OAAO,KAAK,EAAE,MAAM,IAAI,IAAI,CAAC;AAC/B,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/engines/index.ts"],"names":[],"mappings":"AAAA,yCAAyC;AAEzC,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACzC,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAG3C,cAAc,YAAY,CAAC;AAC3B,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACzC,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,qBAAqB,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAC;AAE7E,MAAM,UAAU,UAAU;IACxB,OAAO,CAAC,IAAI,WAAW,EAAE,EAAE,IAAI,YAAY,EAAE,EAAE,IAAI,YAAY,EAAE,CAAC,CAAC;AACrE,CAAC;AASD,8EAA8E;AAC9E,6EAA6E;AAC7E,6EAA6E;AAC7E,4BAA4B;AAC5B,MAAM,CAAC,KAAK,UAAU,aAAa;IACjC,OAAO,MAAM,OAAO,CAAC,GAAG,CACtB,UAAU,EAAE,CAAC,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE;QAChC,IAAI,CAAC;YACH,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,YAAY,EAAE,GAAG,MAAM,MAAM,CAAC,MAAM,EAAE,CAAC;YAClE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,YAAY,EAAE,CAAC;QACrD,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO;gBACL,MAAM;gBACN,SAAS,EAAE,KAAK;gBAChB,MAAM,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;aACzD,CAAC;QACJ,CAAC;IACH,CAAC,CAAC,CACH,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,UAAU,CACxB,QAA0B,EAC1B,EAAY;IAEZ,MAAM,KAAK,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC,SAAS,CAAC,CAAC;IACtE,OAAO,KAAK,EAAE,MAAM,IAAI,IAAI,CAAC;AAC/B,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/engines/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/engines/types.ts"],"names":[],"mappings":"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"}