claude-overnight 1.25.21 → 1.25.23

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.
@@ -1 +1 @@
1
- export declare const VERSION = "1.25.21";
1
+ export declare const VERSION = "1.25.23";
package/dist/_version.js CHANGED
@@ -1,2 +1,2 @@
1
1
  // Auto-generated by build — do not edit manually.
2
- export const VERSION = "1.25.21";
2
+ export const VERSION = "1.25.23";
@@ -5,7 +5,7 @@
5
5
  // segfaults on some setups — the proxy inherits this bug).
6
6
  //
7
7
  // Update this list when Cursor adds/removes models. Run:
8
- // node ~/.local/share/cursor-agent/versions/*/index.js --list-models
8
+ // agent --list-models
9
9
  // to get the current list.
10
10
  //
11
11
  // The `priority` models always appear at the top of the picker in this order.
@@ -13,11 +13,19 @@
13
13
  // that isn't in this list goes into a "more..." sub-menu.
14
14
  import { modelDisplayName, formatContextWindow } from "./models.js";
15
15
  export const CURSOR_PRIORITY_MODELS = [
16
- { id: "composer-2", label: "composer-2", hint: "Cursor Composer 2 — latest, strongest Cursor model" },
16
+ { id: "claude-opus-4-7", label: "claude-opus-4-7", hint: "Claude Opus 4.7 — latest Anthropic flagship, best agentic coder" },
17
+ { id: "gpt-5.4", label: "gpt-5.4", hint: "GPT-5.4 — latest OpenAI flagship, 1M context" },
18
+ { id: "gemini-3.1-pro", label: "gemini-3.1-pro", hint: "Gemini 3.1 Pro — latest Google flagship" },
19
+ { id: "claude-sonnet-4-6", label: "claude-sonnet-4-6", hint: "Claude Sonnet 4.6 — best speed/intelligence balance" },
20
+ { id: "composer-2", label: "composer-2", hint: "Cursor Composer 2 — latest Cursor-native model" },
17
21
  { id: "auto", label: "auto", hint: "auto-delegates to the best available model" },
18
22
  ];
19
23
  export const CURSOR_KNOWN_MODELS = [
20
- { id: "composer", label: "composer", hint: "Cursor Composer — previous generation" },
24
+ { id: "composer-2-fast", label: "composer-2-fast", hint: "Cursor Composer 2 Fast faster, cheaper variant" },
25
+ { id: "composer-1.5", label: "composer-1.5", hint: "Cursor Composer 1.5 — previous generation" },
26
+ { id: "gpt-5.3-codex", label: "gpt-5.3-codex", hint: "Codex 5.3 — OpenAI's best agentic coder" },
27
+ { id: "grok-4-20", label: "grok-4-20", hint: "Grok 4.20 — xAI model" },
28
+ { id: "kimi-k2.5", label: "kimi-k2.5", hint: "Kimi K2.5 — Moonshot model" },
21
29
  ];
22
30
  /** All known model IDs as a Set for quick membership checks. */
23
31
  export const KNOWN_CURSOR_MODEL_IDS = new Set([
@@ -43,5 +51,9 @@ export function cursorModelHint(modelId) {
43
51
  return "Gemini model via Cursor";
44
52
  if (m.startsWith("grok"))
45
53
  return "Grok model via Cursor";
54
+ if (m.startsWith("kimi"))
55
+ return "Kimi model via Cursor";
56
+ if (m.startsWith("claude"))
57
+ return "Claude model via Cursor";
46
58
  return "Cursor model";
47
59
  }
package/dist/index.js CHANGED
@@ -822,14 +822,44 @@ async function main() {
822
822
  // proxy now uses an account pool (`CURSOR_CONFIG_DIRS`) — each parallel
823
823
  // cursor-agent subprocess gets its own config dir, eliminating the race.
824
824
  // See ensureCursorAccountPool() in providers.ts.
825
- const progress = (msg) => process.stdout.write(chalk.dim(` ${msg}\n`));
825
+ //
826
+ // Single in-place status line collapses N parallel progress streams (one
827
+ // per provider) into one tty line updated via `\r` + ANSI clear. Keeps the
828
+ // "window head" calm instead of appending 3 lines per 3s tick.
829
+ const statuses = new Map();
830
+ const isTTY = process.stdout.isTTY;
831
+ let statusLineActive = false;
832
+ const renderStatus = () => {
833
+ if (!isTTY)
834
+ return;
835
+ const parts = [...statuses.entries()].map(([r, s]) => `${r} ${chalk.dim(s)}`);
836
+ process.stdout.write(`\x1B[2K\r`);
837
+ if (parts.length === 0) {
838
+ statusLineActive = false;
839
+ return;
840
+ }
841
+ process.stdout.write(chalk.dim(" " + parts.join(" · ")));
842
+ statusLineActive = true;
843
+ };
844
+ const clearStatusLine = () => {
845
+ if (isTTY && statusLineActive) {
846
+ process.stdout.write(`\x1B[2K\r`);
847
+ statusLineActive = false;
848
+ }
849
+ };
826
850
  /** Cursor agent cold start + thinking-variant model latency can exceed 20s; API providers stay tight. */
827
851
  const preflightMs = (p) => isCursorProxyProvider(p) ? 60_000 : 20_000;
828
- const results = await Promise.all(pending.map(async ([role, p]) => ({
829
- role,
830
- provider: p,
831
- result: await preflightProvider(p, cwd, preflightMs(p), { onProgress: progress }),
832
- })));
852
+ const results = await Promise.all(pending.map(async ([role, p]) => {
853
+ statuses.set(role, "connecting…");
854
+ renderStatus();
855
+ const result = await preflightProvider(p, cwd, preflightMs(p), {
856
+ onProgress: (msg) => { statuses.set(role, msg); renderStatus(); },
857
+ });
858
+ statuses.delete(role);
859
+ renderStatus();
860
+ return { role, provider: p, result };
861
+ }));
862
+ clearStatusLine();
833
863
  for (const { role, provider, result } of results) {
834
864
  if (!result.ok) {
835
865
  console.error(chalk.red(` ✗ ${role} preflight failed: ${chalk.dim(result.error)}`));
package/dist/models.js CHANGED
@@ -19,20 +19,73 @@
19
19
  // Chroma hallucination study. "relaxed" = 95%+ on all three axes.
20
20
  export const MODEL_CAPABILITIES = {
21
21
  // ── Anthropic Claude (Apr 2026) ──
22
- // Opus: only model that earns "relaxed". 100% on 38-task routing, 95%+ IFEval.
22
+ // Opus 4.7: only model that earns "relaxed". 100% on 38-task routing, 95%+ IFEval.
23
+ // Step-change agentic coding over Opus 4.6. 1M tokens, 128K output.
23
24
  "claude-opus-4-7": { contextWindow: 1_000_000, safeContext: 400_000, contextConstraint: "relaxed", displayName: "Opus 4.7" },
24
- "claude-opus-4-6": { contextWindow: 1_000_000, safeContext: 400_000, contextConstraint: "relaxed", displayName: "Opus 4.6" },
25
- // Sonnet: good but loses thread more than Opus on autonomous multi-file work.
26
- "claude-sonnet-4-6": { contextWindow: 1_000_000, safeContext: 300_000, contextConstraint: "moderate", displayName: "Sonnet 4.6" },
27
- // Haiku: cheapest Claude. Skips steps more often. No 1M upgrade.
25
+ "claude-opus-4.7": { contextWindow: 1_000_000, safeContext: 400_000, contextConstraint: "relaxed", displayName: "Opus 4.7" },
26
+ "claude-opus-4-7-low": { contextWindow: 1_000_000, safeContext: 400_000, contextConstraint: "moderate", displayName: "Opus 4.7 Low" },
27
+ "claude-opus-4-7-medium": { contextWindow: 1_000_000, safeContext: 400_000, contextConstraint: "relaxed", displayName: "Opus 4.7 Medium" },
28
+ "claude-opus-4-7-high": { contextWindow: 1_000_000, safeContext: 400_000, contextConstraint: "relaxed", displayName: "Opus 4.7 High" },
29
+ "claude-opus-4-7-xhigh": { contextWindow: 1_000_000, safeContext: 400_000, contextConstraint: "relaxed", displayName: "Opus 4.7 Extra High" },
30
+ "claude-opus-4-7-max": { contextWindow: 1_000_000, safeContext: 400_000, contextConstraint: "relaxed", displayName: "Opus 4.7 Max" },
31
+ "claude-opus-4-7-thinking": { contextWindow: 1_000_000, safeContext: 400_000, contextConstraint: "relaxed", displayName: "Opus 4.7 Thinking" },
32
+ "claude-opus-4-7-thinking-low": { contextWindow: 1_000_000, safeContext: 400_000, contextConstraint: "moderate", displayName: "Opus 4.7 Low Thinking" },
33
+ "claude-opus-4-7-thinking-medium": { contextWindow: 1_000_000, safeContext: 400_000, contextConstraint: "relaxed", displayName: "Opus 4.7 Medium Thinking" },
34
+ "claude-opus-4-7-thinking-high": { contextWindow: 1_000_000, safeContext: 400_000, contextConstraint: "relaxed", displayName: "Opus 4.7 High Thinking" },
35
+ "claude-opus-4-7-thinking-xhigh": { contextWindow: 1_000_000, safeContext: 400_000, contextConstraint: "relaxed", displayName: "Opus 4.7 Extra High Thinking" },
36
+ "claude-opus-4-7-thinking-max": { contextWindow: 1_000_000, safeContext: 400_000, contextConstraint: "relaxed", displayName: "Opus 4.7 Max Thinking" },
37
+ // Sonnet 4.6: 200K context, tight constraint.
38
+ "claude-sonnet-4-6": { contextWindow: 200_000, safeContext: 60_000, contextConstraint: "tight", displayName: "Sonnet 4.6" },
39
+ "claude-sonnet-4.6": { contextWindow: 200_000, safeContext: 60_000, contextConstraint: "tight", displayName: "Sonnet 4.6" },
40
+ "claude-4.6-sonnet-medium": { contextWindow: 200_000, safeContext: 60_000, contextConstraint: "tight", displayName: "Sonnet 4.6 Medium" },
41
+ "claude-sonnet-4-6-thinking": { contextWindow: 200_000, safeContext: 60_000, contextConstraint: "tight", displayName: "Sonnet 4.6 Thinking" },
42
+ "claude-4.6-sonnet-medium-thinking": { contextWindow: 200_000, safeContext: 60_000, contextConstraint: "tight", displayName: "Sonnet 4.6 Medium Thinking" },
43
+ // Sonnet 4.5: 200K context.
44
+ "claude-sonnet-4-5": { contextWindow: 200_000, safeContext: 60_000, contextConstraint: "moderate", displayName: "Sonnet 4.5" },
45
+ "claude-sonnet-4.5": { contextWindow: 200_000, safeContext: 60_000, contextConstraint: "moderate", displayName: "Sonnet 4.5" },
46
+ "claude-4.5-sonnet": { contextWindow: 200_000, safeContext: 60_000, contextConstraint: "moderate", displayName: "Sonnet 4.5" },
47
+ "claude-sonnet-4-5-thinking": { contextWindow: 200_000, safeContext: 60_000, contextConstraint: "moderate", displayName: "Sonnet 4.5 Thinking" },
48
+ "claude-4.5-sonnet-thinking": { contextWindow: 200_000, safeContext: 60_000, contextConstraint: "moderate", displayName: "Sonnet 4.5 Thinking" },
49
+ // Claude 4 Opus/Sonnet (original): deprecated June 2026. 200K context.
50
+ "claude-opus-4": { contextWindow: 200_000, safeContext: 80_000, contextConstraint: "moderate", displayName: "Opus 4.0" },
51
+ "claude-sonnet-4": { contextWindow: 200_000, safeContext: 60_000, contextConstraint: "moderate", displayName: "Sonnet 4.0" },
52
+ "claude-4-sonnet": { contextWindow: 200_000, safeContext: 60_000, contextConstraint: "moderate", displayName: "Sonnet 4" },
53
+ "claude-4-sonnet-1m": { contextWindow: 1_000_000, safeContext: 300_000, contextConstraint: "moderate", displayName: "Sonnet 4 1M" },
54
+ "claude-sonnet-4-thinking": { contextWindow: 200_000, safeContext: 60_000, contextConstraint: "moderate", displayName: "Sonnet 4 Thinking" },
55
+ "claude-4-sonnet-thinking": { contextWindow: 200_000, safeContext: 60_000, contextConstraint: "moderate", displayName: "Sonnet 4 Thinking" },
56
+ "claude-4-sonnet-1m-thinking": { contextWindow: 1_000_000, safeContext: 300_000, contextConstraint: "moderate", displayName: "Sonnet 4 1M Thinking" },
57
+ // Haiku 4.5: cheapest Claude. 200K context, near-frontier smarts.
28
58
  "claude-haiku-4-5": { contextWindow: 200_000, safeContext: 60_000, contextConstraint: "moderate", displayName: "Haiku 4.5" },
29
59
  "claude-haiku-4-5-20251001": { contextWindow: 200_000, safeContext: 60_000, contextConstraint: "moderate", displayName: "Haiku 4.5" },
60
+ "claude-haiku-4-6": { contextWindow: 200_000, safeContext: 60_000, contextConstraint: "moderate", displayName: "Haiku 4.6" },
61
+ "claude-haiku-4": { contextWindow: 200_000, safeContext: 60_000, contextConstraint: "moderate", displayName: "Haiku 4" },
30
62
  // ── OpenAI (Apr 2026 — GPT-4.1/o3/o4-mini retired Feb 2026) ──
31
63
  // GPT-5.4: current flagship. 1M context, 128K output. Good but literal.
32
64
  "gpt-5.4": { contextWindow: 1_050_000, safeContext: 300_000, contextConstraint: "moderate", displayName: "GPT-5.4" },
33
- "gpt-5.4-mini": { contextWindow: 1_050_000, safeContext: 200_000, contextConstraint: "moderate", displayName: "GPT-5.4 Mini" },
65
+ "gpt-5.4-low": { contextWindow: 1_050_000, safeContext: 300_000, contextConstraint: "moderate", displayName: "GPT-5.4 Low" },
66
+ "gpt-5.4-medium": { contextWindow: 1_050_000, safeContext: 300_000, contextConstraint: "moderate", displayName: "GPT-5.4 Medium" },
67
+ "gpt-5.4-medium-fast": { contextWindow: 1_050_000, safeContext: 300_000, contextConstraint: "moderate", displayName: "GPT-5.4 Fast" },
68
+ "gpt-5.4-high": { contextWindow: 1_050_000, safeContext: 300_000, contextConstraint: "moderate", displayName: "GPT-5.4 High" },
69
+ "gpt-5.4-high-fast": { contextWindow: 1_050_000, safeContext: 300_000, contextConstraint: "moderate", displayName: "GPT-5.4 High Fast" },
70
+ "gpt-5.4-xhigh": { contextWindow: 1_050_000, safeContext: 300_000, contextConstraint: "moderate", displayName: "GPT-5.4 Extra High" },
71
+ "gpt-5.4-xhigh-fast": { contextWindow: 1_050_000, safeContext: 300_000, contextConstraint: "moderate", displayName: "GPT-5.4 Extra High Fast" },
72
+ "gpt-5.4-mini": { contextWindow: 1_050_000, safeContext: 200_000, contextConstraint: "tight", displayName: "GPT-5.4 Mini" },
73
+ "gpt-5.4-mini-low": { contextWindow: 1_050_000, safeContext: 200_000, contextConstraint: "tight", displayName: "GPT-5.4 Mini Low" },
74
+ "gpt-5.4-mini-medium": { contextWindow: 1_050_000, safeContext: 200_000, contextConstraint: "tight", displayName: "GPT-5.4 Mini" },
75
+ "gpt-5.4-mini-high": { contextWindow: 1_050_000, safeContext: 200_000, contextConstraint: "tight", displayName: "GPT-5.4 Mini High" },
76
+ "gpt-5.4-mini-xhigh": { contextWindow: 1_050_000, safeContext: 200_000, contextConstraint: "tight", displayName: "GPT-5.4 Mini Extra High" },
34
77
  // Codex 5.3: best agentic coder from OpenAI. 400K context, 128K output.
35
78
  "gpt-5.3-codex": { contextWindow: 400_000, safeContext: 160_000, contextConstraint: "moderate", displayName: "Codex 5.3" },
79
+ "gpt-5.3-codex-low": { contextWindow: 400_000, safeContext: 160_000, contextConstraint: "moderate", displayName: "Codex 5.3 Low" },
80
+ "gpt-5.3-codex-high": { contextWindow: 400_000, safeContext: 160_000, contextConstraint: "moderate", displayName: "Codex 5.3 High" },
81
+ "gpt-5.3-codex-xhigh": { contextWindow: 400_000, safeContext: 160_000, contextConstraint: "moderate", displayName: "Codex 5.3 Extra High" },
82
+ "gpt-5.3-codex-fast": { contextWindow: 400_000, safeContext: 160_000, contextConstraint: "moderate", displayName: "Codex 5.3 Fast" },
83
+ // Older OpenAI
84
+ "gpt-5.2": { contextWindow: 400_000, safeContext: 160_000, contextConstraint: "moderate", displayName: "GPT-5.2" },
85
+ "gpt-5.2-codex": { contextWindow: 400_000, safeContext: 160_000, contextConstraint: "moderate", displayName: "Codex 5.2" },
86
+ "gpt-5.1": { contextWindow: 400_000, safeContext: 160_000, contextConstraint: "moderate", displayName: "GPT-5.1" },
87
+ "gpt-5": { contextWindow: 400_000, safeContext: 160_000, contextConstraint: "moderate", displayName: "GPT-5" },
88
+ "gpt-5.1-codex-mini": { contextWindow: 400_000, safeContext: 160_000, contextConstraint: "moderate", displayName: "Codex 5.1 Mini" },
36
89
  // ── Google Gemini 3 (Apr 2026 — Gemini 2.5 deprecated June 2026) ──
37
90
  // Large context but terrible at agentic coding: 13.5% SWE-bench (vs Sonnet 31.2%).
38
91
  // Good for reading lots of code, bad at following through. Needs surgical tasks.
@@ -40,6 +93,11 @@ export const MODEL_CAPABILITIES = {
40
93
  "gemini-3-pro": { contextWindow: 1_000_000, safeContext: 350_000, contextConstraint: "tight", displayName: "Gemini 3 Pro" },
41
94
  // Flash: 8.2% SWE-bench. Essentially unusable for autonomous agent work.
42
95
  "gemini-3-flash": { contextWindow: 1_000_000, safeContext: 250_000, contextConstraint: "tight", displayName: "Gemini 3 Flash" },
96
+ // ── xAI Grok ──
97
+ "grok-4-20": { contextWindow: 256_000, safeContext: 80_000, contextConstraint: "moderate", displayName: "Grok 4.20" },
98
+ "grok-4-20-thinking": { contextWindow: 256_000, safeContext: 80_000, contextConstraint: "moderate", displayName: "Grok 4.20 Thinking" },
99
+ // ── Moonshot ──
100
+ "kimi-k2.5": { contextWindow: 128_000, safeContext: 40_000, contextConstraint: "tight", displayName: "Kimi K2.5" },
43
101
  // ── DeepSeek V3.2 (Apr 2026 — V3/R1 superseded, V4 not yet out) ──
44
102
  "deepseek-chat": { contextWindow: 128_000, safeContext: 40_000, contextConstraint: "tight", displayName: "DeepSeek V3.2" },
45
103
  "deepseek-reasoner": { contextWindow: 128_000, safeContext: 45_000, contextConstraint: "moderate", displayName: "DeepSeek V3.2 Reasoner" },
@@ -50,7 +108,9 @@ export const MODEL_CAPABILITIES = {
50
108
  // ── Cursor models (opaque routing) ──
51
109
  "auto": { contextWindow: 256_000, safeContext: 60_000, contextConstraint: "moderate", displayName: "Cursor Auto" },
52
110
  "composer-2": { contextWindow: 200_000, safeContext: 40_000, contextConstraint: "tight", displayName: "Composer 2" },
111
+ "composer-2-fast": { contextWindow: 200_000, safeContext: 40_000, contextConstraint: "tight", displayName: "Composer 2 Fast" },
53
112
  "composer": { contextWindow: 128_000, safeContext: 30_000, contextConstraint: "tight", displayName: "Composer" },
113
+ "composer-1.5": { contextWindow: 128_000, safeContext: 30_000, contextConstraint: "tight", displayName: "Composer 1.5" },
54
114
  // ── Qwen (Apr 2026 — qwen3.6-plus is newest flagship) ──
55
115
  "qwen3.6-plus": { contextWindow: 1_000_000, safeContext: 200_000, contextConstraint: "moderate", displayName: "Qwen 3.6 Plus" },
56
116
  "qwen3-coder-plus": { contextWindow: 1_000_000, safeContext: 200_000, contextConstraint: "moderate", displayName: "Qwen 3 Coder Plus" },
@@ -26,12 +26,13 @@ export interface PlannerOpts {
26
26
  /** When set, stream events are appended to <runDir>/transcripts/<name>.ndjson */
27
27
  transcriptName?: string;
28
28
  /**
29
- * Hard cap on conversation turns. Protects against runaway exploration when
30
- * the underlying endpoint ignores `outputFormat` (e.g. the Cursor proxy
31
- * strips json_schema, leaving thinking models with no signal to stop).
32
- * Defaults to 20 — generous for recon, bounded against infinite loops.
29
+ * Hard cap on conversation turns. Defaults to 20.
33
30
  */
34
31
  maxTurns?: number;
32
+ /**
33
+ * Tools the planner agent may use. Defaults to the full Claude tool suite.
34
+ */
35
+ tools?: string[];
35
36
  }
36
37
  export declare function setPlannerEnvResolver(fn: ((model?: string) => Record<string, string> | undefined) | undefined): void;
37
38
  export declare function getTotalPlannerCost(): number;
@@ -2,6 +2,7 @@ import { query } from "@anthropic-ai/claude-agent-sdk";
2
2
  import { readFileSync } from "fs";
3
3
  import { NudgeError } from "./types.js";
4
4
  import { writeTranscriptEvent } from "./transcripts.js";
5
+ const DEFAULT_TOOLS = ["Read", "Glob", "Grep", "Write", "Bash", "WebFetch", "WebSearch", "TodoWrite", "Agent"];
5
6
  const DEFAULT_MAX_TURNS = 20;
6
7
  // ── Shared env resolver (set once at run start, used by every planner query) ──
7
8
  //
@@ -144,8 +145,8 @@ async function runPlannerQueryOnce(prompt, opts, onLog) {
144
145
  options: {
145
146
  cwd: opts.cwd,
146
147
  model: opts.model,
147
- tools: ["Read", "Glob", "Grep", "Write", "Bash", "WebFetch", "WebSearch", "TodoWrite", "Agent"],
148
- allowedTools: ["Read", "Glob", "Grep", "Write", "Bash", "WebFetch", "WebSearch", "TodoWrite", "Agent"],
148
+ tools: opts.tools ?? DEFAULT_TOOLS,
149
+ allowedTools: opts.tools ?? DEFAULT_TOOLS,
149
150
  permissionMode: opts.permissionMode,
150
151
  ...(opts.permissionMode === "bypassPermissions" && { allowDangerouslySkipPermissions: true }),
151
152
  persistSession: true,
@@ -156,9 +157,20 @@ async function runPlannerQueryOnce(prompt, opts, onLog) {
156
157
  ...(envOverride && { env: envOverride }),
157
158
  },
158
159
  });
159
- let lastLogText = "";
160
+ // Default to "thinking…" so the ticker conveys meaning during the pre-output
161
+ // reasoning phase. Thinking-variant models (e.g. claude-opus-4-7-thinking-*)
162
+ // can sit silent for 60-90s before emitting any tokens, and cursor-agent
163
+ // doesn't forward thinking deltas — without this, the ticker reads "4m 5s"
164
+ // with nothing else for a minute plus.
165
+ let lastLogText = "thinking…";
160
166
  let toolCount = 0;
161
167
  let costUsd = 0;
168
+ const jsonOutput = opts.outputFormat?.type === "json_schema";
169
+ let jsonCharCount = 0;
170
+ // Dedup identical text snippets: cursor-agent with json_schema-ignoring
171
+ // proxies causes the SDK to loop multiple turns, each re-emitting the same
172
+ // final JSON. We don't want to spam the ticker or transcript with it.
173
+ let lastTextSeen = "";
162
174
  const ticker = setInterval(() => {
163
175
  const elapsed = Math.round((Date.now() - startedAt) / 1000);
164
176
  const m = Math.floor(elapsed / 60);
@@ -261,9 +273,18 @@ async function runPlannerQueryOnce(prompt, opts, onLog) {
261
273
  : delta?.type === "thinking_delta" ? delta.thinking
262
274
  : undefined;
263
275
  if (typeof raw === "string" && raw) {
264
- const snippet = raw.trim().replace(/[{}"\\,[\]]+/g, " ").replace(/\s+/g, " ").trim();
265
- if (snippet.length > 5)
266
- lastLogText = snippet.slice(-60);
276
+ if (jsonOutput && delta.type === "text_delta") {
277
+ // Don't surface tail-of-JSON as "progress" — it reads as noise
278
+ // like `…ppression and optimistic-update rollback`. Show size
279
+ // growing instead, which is a genuine signal.
280
+ jsonCharCount += raw.length;
281
+ lastLogText = `writing JSON (${jsonCharCount} chars)…`;
282
+ }
283
+ else {
284
+ const snippet = raw.trim().replace(/[{}"\\,[\]]+/g, " ").replace(/\s+/g, " ").trim();
285
+ if (snippet.length > 5)
286
+ lastLogText = snippet.slice(-60);
287
+ }
267
288
  if (tname)
268
289
  writeTranscriptEvent(tname, { kind: delta.type, text: raw });
269
290
  }
@@ -308,9 +329,17 @@ async function runPlannerQueryOnce(prompt, opts, onLog) {
308
329
  writeTranscriptEvent(tname, { kind: "thinking", text: part.thinking });
309
330
  }
310
331
  else if (part?.type === "text" && typeof part.text === "string" && part.text) {
311
- const snippet = part.text.trim().replace(/[{}"\\,[\]]+/g, " ").replace(/\s+/g, " ").slice(-60);
312
- if (snippet.length > 5)
313
- lastLogText = snippet;
332
+ if (part.text === lastTextSeen)
333
+ continue; // dedup repeated turns
334
+ lastTextSeen = part.text;
335
+ if (jsonOutput) {
336
+ lastLogText = `writing JSON (${part.text.length} chars)…`;
337
+ }
338
+ else {
339
+ const snippet = part.text.trim().replace(/[{}"\\,[\]]+/g, " ").replace(/\s+/g, " ").slice(-60);
340
+ if (snippet.length > 5)
341
+ lastLogText = snippet;
342
+ }
314
343
  if (tname)
315
344
  writeTranscriptEvent(tname, { kind: "text", text: part.text });
316
345
  }
package/dist/planner.js CHANGED
@@ -158,7 +158,8 @@ export async function planTasks(objective, cwd, plannerModel, workerModel, permi
158
158
  const fileInstruction = outFile ? `\n\nAFTER generating the JSON, also write it to ${outFile} using the Write tool.` : "";
159
159
  let resultText;
160
160
  try {
161
- resultText = await runPlannerQuery(prompt + fileInstruction, { cwd, model: plannerModel, permissionMode, outputFormat: TASKS_SCHEMA, transcriptName, maxTurns: 40 }, onLog);
161
+ resultText = await runPlannerQuery(prompt + fileInstruction, { cwd, model: plannerModel, permissionMode, outputFormat: TASKS_SCHEMA, transcriptName, maxTurns: 40,
162
+ tools: ["Read", "Glob", "Grep", "Write"] }, onLog);
162
163
  }
163
164
  catch (err) {
164
165
  const salvaged = salvageFromFile(outFile, budget, onLog, err?.message ?? String(err));
@@ -259,7 +260,8 @@ Respond with ONLY a JSON object (no markdown fences):
259
260
  onLog("Synthesizing...");
260
261
  let resultText;
261
262
  try {
262
- resultText = await runPlannerQuery(prompt, { cwd, model: plannerModel, permissionMode, outputFormat: TASKS_SCHEMA, transcriptName, maxTurns: 25 }, onLog);
263
+ resultText = await runPlannerQuery(prompt, { cwd, model: plannerModel, permissionMode, outputFormat: TASKS_SCHEMA, transcriptName, maxTurns: 25,
264
+ tools: ["Write"] }, onLog);
263
265
  }
264
266
  catch (err) {
265
267
  const salvaged = salvageFromFile(outFile, budget, onLog, err?.message ?? String(err));
package/dist/providers.js CHANGED
@@ -124,6 +124,29 @@ export function envFor(p) {
124
124
  // SDK replaces env for subprocesses — force these so nothing inherits a bad CI / skip flag.
125
125
  base.CI = "true";
126
126
  base.CURSOR_SKIP_KEYCHAIN = "1";
127
+ // Bridge mode controls the agent behavior: "plan" enables tool use (Read,
128
+ // Glob, Grep, Write, Bash), "ask" gives a chat-only assistant. Planner
129
+ // agents and workers must use "plan" so they actually interact with the codebase.
130
+ base.CURSOR_BRIDGE_MODE = "plan";
131
+ // Use system Node.js for agent subprocess to avoid macOS segfaults with
132
+ // bundled Node.js. Resolve lazily — same logic as startProxyProcess().
133
+ if (!base.CURSOR_AGENT_NODE || !base.CURSOR_AGENT_SCRIPT) {
134
+ try {
135
+ const sysNode = execSync("which node 2>/dev/null", { timeout: 2_000, encoding: "utf-8", shell: "bash" }).trim();
136
+ const agentPath = execSync("command -v agent 2>/dev/null || command -v cursor-agent 2>/dev/null", {
137
+ timeout: 2_000, encoding: "utf-8", shell: "bash",
138
+ }).trim();
139
+ if (sysNode && agentPath) {
140
+ const agentDir = dirname(realpathSync(agentPath));
141
+ const indexPath = `${agentDir}/index.js`;
142
+ if (existsSync(indexPath)) {
143
+ base.CURSOR_AGENT_NODE = sysNode;
144
+ base.CURSOR_AGENT_SCRIPT = indexPath;
145
+ }
146
+ }
147
+ }
148
+ catch { }
149
+ }
127
150
  return base;
128
151
  }
129
152
  const key = resolveKey(p);
@@ -878,6 +901,9 @@ async function startProxyProcess(baseUrl, url, port) {
878
901
  // the CLI path injects keychain-shim-inject.js via NODE_OPTIONS which no-ops
879
902
  // /usr/bin/security calls on macOS (cursor-composer/dist/lib/process.js).
880
903
  CURSOR_BRIDGE_USE_ACP: "0",
904
+ // Default bridge mode: "plan" enables tool use (Read, Glob, Grep, Write, Bash).
905
+ // "ask" gives a chat-only assistant that doesn't interact with the codebase.
906
+ CURSOR_BRIDGE_MODE: "plan",
881
907
  // cursor-composer chat-only mode fakes HOME to a temp dir; on macOS the agent still waits on
882
908
  // Keychain (~30s) for `cursor-user` despite CURSOR_API_KEY. Use the real workspace profile.
883
909
  CURSOR_BRIDGE_CHAT_ONLY_WORKSPACE: "false",
@@ -905,6 +931,7 @@ async function startProxyProcess(baseUrl, url, port) {
905
931
  childEnv: {
906
932
  CI: proxyEnv.CI,
907
933
  CURSOR_SKIP_KEYCHAIN: proxyEnv.CURSOR_SKIP_KEYCHAIN,
934
+ CURSOR_BRIDGE_MODE: proxyEnv.CURSOR_BRIDGE_MODE,
908
935
  CURSOR_BRIDGE_USE_ACP: proxyEnv.CURSOR_BRIDGE_USE_ACP,
909
936
  CURSOR_BRIDGE_CHAT_ONLY_WORKSPACE: proxyEnv.CURSOR_BRIDGE_CHAT_ONLY_WORKSPACE,
910
937
  CURSOR_API_KEY: "(set)",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-overnight",
3
- "version": "1.25.21",
3
+ "version": "1.25.23",
4
4
  "description": "Parallel Claude agents in git worktrees with a usage cap that reserves headroom for your interactive Claude Code. Crash-safe resume. Provider-agnostic model catalog (Anthropic, Cursor, OpenAI, Gemini, DeepSeek, Llama, Qwen) with capability-based task scoping.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -17,7 +17,7 @@
17
17
  "dependencies": {
18
18
  "@anthropic-ai/claude-agent-sdk": "^0.2.92",
19
19
  "chalk": "^5.4.1",
20
- "cursor-composer-in-claude": "0.9.0",
20
+ "cursor-composer-in-claude": "0.9.1",
21
21
  "jsonwebtoken": "^9.0.2"
22
22
  },
23
23
  "devDependencies": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-overnight",
3
- "version": "1.25.21",
3
+ "version": "1.25.23",
4
4
  "description": "Claude Code skill for understanding, installing, and inspecting claude-overnight runs -- parallel Claude agents in git worktrees with thinking waves, multi-wave steering, and crash-safe resume. Supports Cursor API Proxy, Qwen, OpenRouter.",
5
5
  "author": {
6
6
  "name": "Francesco Fornace"