claude-overnight 1.25.22 → 1.25.24
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.
- package/dist/_version.d.ts +1 -1
- package/dist/_version.js +1 -1
- package/dist/cursor-models.js +15 -3
- package/dist/interactive-panel.d.ts +40 -0
- package/dist/interactive-panel.js +111 -0
- package/dist/models.js +63 -6
- package/dist/planner-query.d.ts +9 -3
- package/dist/planner-query.js +25 -20
- package/dist/providers.js +44 -15
- package/dist/render.d.ts +10 -10
- package/dist/render.js +135 -26
- package/dist/run.js +26 -1
- package/dist/state.js +18 -0
- package/dist/swarm.d.ts +1 -0
- package/dist/swarm.js +21 -8
- package/dist/types.d.ts +20 -1
- package/dist/types.js +16 -0
- package/dist/ui.d.ts +5 -13
- package/dist/ui.js +66 -41
- package/package.json +2 -2
- package/plugins/claude-overnight/.claude-plugin/plugin.json +1 -1
package/dist/_version.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const VERSION = "1.25.
|
|
1
|
+
export declare const VERSION = "1.25.24";
|
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.
|
|
2
|
+
export const VERSION = "1.25.24";
|
package/dist/cursor-models.js
CHANGED
|
@@ -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
|
-
//
|
|
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: "
|
|
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 —
|
|
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
|
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
export type PanelMode = "debrief" | "ask" | "custom" | "none";
|
|
2
|
+
/** Mutable state of the interactive panel. */
|
|
3
|
+
export interface PanelState {
|
|
4
|
+
mode: PanelMode;
|
|
5
|
+
expanded: boolean;
|
|
6
|
+
scrollOffset: number;
|
|
7
|
+
/** Short title shown in the header bar. */
|
|
8
|
+
header: string;
|
|
9
|
+
/** One-line summary shown when collapsed. */
|
|
10
|
+
preview: string;
|
|
11
|
+
/** Multi-line body shown when expanded. */
|
|
12
|
+
body: string;
|
|
13
|
+
/** Whether to show a text input at the bottom (ask/steer). */
|
|
14
|
+
inputActive: boolean;
|
|
15
|
+
inputPlaceholder?: string;
|
|
16
|
+
}
|
|
17
|
+
export declare class InteractivePanel {
|
|
18
|
+
state: PanelState;
|
|
19
|
+
/** Cached non-empty body lines — rebuilt when body changes. */
|
|
20
|
+
private _bodyLines;
|
|
21
|
+
/** Set or clear the panel content. Mode "none" hides it. */
|
|
22
|
+
set(params: {
|
|
23
|
+
mode: PanelMode;
|
|
24
|
+
header: string;
|
|
25
|
+
preview: string;
|
|
26
|
+
body: string;
|
|
27
|
+
}): void;
|
|
28
|
+
/** Collapse the panel back to the compact bar. */
|
|
29
|
+
collapse(): void;
|
|
30
|
+
/** Toggle expanded/collapsed state. */
|
|
31
|
+
toggle(): void;
|
|
32
|
+
/** Scroll up/down within the expanded body. */
|
|
33
|
+
scroll(direction: "up" | "down", visibleRows: number): void;
|
|
34
|
+
/** Whether the panel is currently visible (any mode other than none). */
|
|
35
|
+
get visible(): boolean;
|
|
36
|
+
/** Render the collapsed compact bar. Returns empty string if no content. */
|
|
37
|
+
renderCollapsed(width: number): string;
|
|
38
|
+
/** Render the expanded panel as an array of lines for the content area. */
|
|
39
|
+
renderExpanded(width: number, maxRows: number): string[];
|
|
40
|
+
}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import chalk from "chalk";
|
|
2
|
+
const DARK_GREEN_BG = "\x1B[48;5;22m";
|
|
3
|
+
const LIGHT_GREEN_FG = "\x1B[38;5;156m";
|
|
4
|
+
const RESET = "\x1B[0m";
|
|
5
|
+
function greenBg(text) {
|
|
6
|
+
return `${DARK_GREEN_BG}${LIGHT_GREEN_FG} ${text} ${RESET}`;
|
|
7
|
+
}
|
|
8
|
+
function greenBgLine(text, width) {
|
|
9
|
+
const padded = text.padEnd(Math.max(0, width));
|
|
10
|
+
return `${DARK_GREEN_BG}${LIGHT_GREEN_FG}${padded}${RESET}`;
|
|
11
|
+
}
|
|
12
|
+
function truncate(s, max) {
|
|
13
|
+
return s.length <= max ? s : s.slice(0, max - 1) + "\u2026";
|
|
14
|
+
}
|
|
15
|
+
export class InteractivePanel {
|
|
16
|
+
state = {
|
|
17
|
+
mode: "none",
|
|
18
|
+
expanded: false,
|
|
19
|
+
scrollOffset: 0,
|
|
20
|
+
header: "",
|
|
21
|
+
preview: "",
|
|
22
|
+
body: "",
|
|
23
|
+
inputActive: false,
|
|
24
|
+
};
|
|
25
|
+
/** Cached non-empty body lines — rebuilt when body changes. */
|
|
26
|
+
_bodyLines = [];
|
|
27
|
+
/** Set or clear the panel content. Mode "none" hides it. */
|
|
28
|
+
set(params) {
|
|
29
|
+
this.state.mode = params.mode;
|
|
30
|
+
this.state.header = params.header;
|
|
31
|
+
this.state.preview = params.preview;
|
|
32
|
+
this.state.body = params.body;
|
|
33
|
+
// Rebuild cached lines and reset scroll only when content changes
|
|
34
|
+
this._bodyLines = params.body.split("\n").filter(l => l.length > 0);
|
|
35
|
+
this.state.scrollOffset = 0;
|
|
36
|
+
}
|
|
37
|
+
/** Collapse the panel back to the compact bar. */
|
|
38
|
+
collapse() {
|
|
39
|
+
this.state.expanded = false;
|
|
40
|
+
this.state.scrollOffset = 0;
|
|
41
|
+
}
|
|
42
|
+
/** Toggle expanded/collapsed state. */
|
|
43
|
+
toggle() {
|
|
44
|
+
if (this.state.mode === "none")
|
|
45
|
+
return;
|
|
46
|
+
this.state.expanded = !this.state.expanded;
|
|
47
|
+
if (!this.state.expanded)
|
|
48
|
+
this.state.scrollOffset = 0;
|
|
49
|
+
}
|
|
50
|
+
/** Scroll up/down within the expanded body. */
|
|
51
|
+
scroll(direction, visibleRows) {
|
|
52
|
+
if (!this.state.expanded)
|
|
53
|
+
return;
|
|
54
|
+
const maxScroll = Math.max(0, this._bodyLines.length - visibleRows);
|
|
55
|
+
if (direction === "up") {
|
|
56
|
+
this.state.scrollOffset = Math.max(0, this.state.scrollOffset - 1);
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
this.state.scrollOffset = Math.min(maxScroll, this.state.scrollOffset + 1);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
/** Whether the panel is currently visible (any mode other than none). */
|
|
63
|
+
get visible() {
|
|
64
|
+
return this.state.mode !== "none";
|
|
65
|
+
}
|
|
66
|
+
/** Render the collapsed compact bar. Returns empty string if no content. */
|
|
67
|
+
renderCollapsed(width) {
|
|
68
|
+
if (this.state.mode === "none" || !this.state.preview)
|
|
69
|
+
return "";
|
|
70
|
+
const icon = this.state.expanded ? "\u25BC" : "\u25B6";
|
|
71
|
+
const modeLabel = this.state.header;
|
|
72
|
+
const hint = chalk.dim(`[Ctrl-O expand]`);
|
|
73
|
+
const content = truncate(this.state.preview, width - modeLabel.length - hint.length - 8);
|
|
74
|
+
return ` ${greenBg(`${icon} ${modeLabel}`)} ${content} ${hint}`;
|
|
75
|
+
}
|
|
76
|
+
/** Render the expanded panel as an array of lines for the content area. */
|
|
77
|
+
renderExpanded(width, maxRows) {
|
|
78
|
+
if (this.state.mode === "none")
|
|
79
|
+
return [];
|
|
80
|
+
const innerW = Math.max(20, width - 6);
|
|
81
|
+
const lines = [];
|
|
82
|
+
// Header bar — full-width dark green bg
|
|
83
|
+
const headerText = ` ${this.state.header} ${chalk.dim("[Ctrl-O] collapse")}${this.state.inputActive ? chalk.dim(" [Esc] cancel") : ""}`;
|
|
84
|
+
lines.push(greenBgLine(headerText, Math.min(width - 4, innerW + 2)));
|
|
85
|
+
// Body content — scrolled
|
|
86
|
+
const headerSpace = this.state.inputActive ? 3 : 2; // header + footer + optional input
|
|
87
|
+
const visibleRows = Math.max(2, maxRows - headerSpace);
|
|
88
|
+
const start = this.state.scrollOffset;
|
|
89
|
+
const end = Math.min(start + visibleRows, this._bodyLines.length);
|
|
90
|
+
for (let i = start; i < end; i++) {
|
|
91
|
+
const ln = truncate(this._bodyLines[i], innerW);
|
|
92
|
+
lines.push(` ${chalk.greenBright(ln)}`);
|
|
93
|
+
}
|
|
94
|
+
if (end < this._bodyLines.length) {
|
|
95
|
+
lines.push(chalk.dim(` \u2026 +${this._bodyLines.length - end} more`));
|
|
96
|
+
}
|
|
97
|
+
if (this._bodyLines.length === 0) {
|
|
98
|
+
lines.push(chalk.dim(" (empty)"));
|
|
99
|
+
}
|
|
100
|
+
// Footer hint
|
|
101
|
+
if (this.state.inputActive && this.state.inputPlaceholder) {
|
|
102
|
+
lines.push("");
|
|
103
|
+
lines.push(` ${chalk.cyan(">")} ${this.state.inputPlaceholder}`);
|
|
104
|
+
}
|
|
105
|
+
else if (!this.state.inputActive) {
|
|
106
|
+
lines.push("");
|
|
107
|
+
lines.push(chalk.dim(" \u2191\u2193 scroll [Ctrl-O] collapse"));
|
|
108
|
+
}
|
|
109
|
+
return lines;
|
|
110
|
+
}
|
|
111
|
+
}
|
package/dist/models.js
CHANGED
|
@@ -19,20 +19,70 @@
|
|
|
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-
|
|
25
|
-
|
|
26
|
-
"claude-
|
|
27
|
-
|
|
25
|
+
"claude-opus-4-7-low": { contextWindow: 1_000_000, safeContext: 400_000, contextConstraint: "moderate", displayName: "Opus 4.7 Low" },
|
|
26
|
+
"claude-opus-4-7-medium": { contextWindow: 1_000_000, safeContext: 400_000, contextConstraint: "relaxed", displayName: "Opus 4.7 Medium" },
|
|
27
|
+
"claude-opus-4-7-high": { contextWindow: 1_000_000, safeContext: 400_000, contextConstraint: "relaxed", displayName: "Opus 4.7 High" },
|
|
28
|
+
"claude-opus-4-7-xhigh": { contextWindow: 1_000_000, safeContext: 400_000, contextConstraint: "relaxed", displayName: "Opus 4.7 Extra High" },
|
|
29
|
+
"claude-opus-4-7-max": { contextWindow: 1_000_000, safeContext: 400_000, contextConstraint: "relaxed", displayName: "Opus 4.7 Max" },
|
|
30
|
+
"claude-opus-4-7-thinking": { contextWindow: 1_000_000, safeContext: 400_000, contextConstraint: "relaxed", displayName: "Opus 4.7 Thinking" },
|
|
31
|
+
"claude-opus-4-7-thinking-low": { contextWindow: 1_000_000, safeContext: 400_000, contextConstraint: "moderate", displayName: "Opus 4.7 Low Thinking" },
|
|
32
|
+
"claude-opus-4-7-thinking-medium": { contextWindow: 1_000_000, safeContext: 400_000, contextConstraint: "relaxed", displayName: "Opus 4.7 Medium Thinking" },
|
|
33
|
+
"claude-opus-4-7-thinking-high": { contextWindow: 1_000_000, safeContext: 400_000, contextConstraint: "relaxed", displayName: "Opus 4.7 High Thinking" },
|
|
34
|
+
"claude-opus-4-7-thinking-xhigh": { contextWindow: 1_000_000, safeContext: 400_000, contextConstraint: "relaxed", displayName: "Opus 4.7 Extra High Thinking" },
|
|
35
|
+
"claude-opus-4-7-thinking-max": { contextWindow: 1_000_000, safeContext: 400_000, contextConstraint: "relaxed", displayName: "Opus 4.7 Max Thinking" },
|
|
36
|
+
// Sonnet 4.6: 200K context, tight constraint.
|
|
37
|
+
"claude-sonnet-4-6": { contextWindow: 200_000, safeContext: 60_000, contextConstraint: "tight", displayName: "Sonnet 4.6" },
|
|
38
|
+
"claude-4.6-sonnet-medium": { contextWindow: 200_000, safeContext: 60_000, contextConstraint: "tight", displayName: "Sonnet 4.6 Medium" },
|
|
39
|
+
"claude-sonnet-4-6-thinking": { contextWindow: 200_000, safeContext: 60_000, contextConstraint: "tight", displayName: "Sonnet 4.6 Thinking" },
|
|
40
|
+
"claude-4.6-sonnet-medium-thinking": { contextWindow: 200_000, safeContext: 60_000, contextConstraint: "tight", displayName: "Sonnet 4.6 Medium Thinking" },
|
|
41
|
+
// Sonnet 4.5: 200K context.
|
|
42
|
+
"claude-sonnet-4-5": { contextWindow: 200_000, safeContext: 60_000, contextConstraint: "moderate", displayName: "Sonnet 4.5" },
|
|
43
|
+
"claude-4.5-sonnet": { contextWindow: 200_000, safeContext: 60_000, contextConstraint: "moderate", displayName: "Sonnet 4.5" },
|
|
44
|
+
"claude-sonnet-4-5-thinking": { contextWindow: 200_000, safeContext: 60_000, contextConstraint: "moderate", displayName: "Sonnet 4.5 Thinking" },
|
|
45
|
+
"claude-4.5-sonnet-thinking": { contextWindow: 200_000, safeContext: 60_000, contextConstraint: "moderate", displayName: "Sonnet 4.5 Thinking" },
|
|
46
|
+
// Claude 4 Opus/Sonnet (original): deprecated June 2026. 200K context.
|
|
47
|
+
"claude-opus-4": { contextWindow: 200_000, safeContext: 80_000, contextConstraint: "moderate", displayName: "Opus 4.0" },
|
|
48
|
+
"claude-sonnet-4": { contextWindow: 200_000, safeContext: 60_000, contextConstraint: "moderate", displayName: "Sonnet 4.0" },
|
|
49
|
+
"claude-4-sonnet": { contextWindow: 200_000, safeContext: 60_000, contextConstraint: "moderate", displayName: "Sonnet 4" },
|
|
50
|
+
"claude-4-sonnet-1m": { contextWindow: 1_000_000, safeContext: 300_000, contextConstraint: "moderate", displayName: "Sonnet 4 1M" },
|
|
51
|
+
"claude-sonnet-4-thinking": { contextWindow: 200_000, safeContext: 60_000, contextConstraint: "moderate", displayName: "Sonnet 4 Thinking" },
|
|
52
|
+
"claude-4-sonnet-thinking": { contextWindow: 200_000, safeContext: 60_000, contextConstraint: "moderate", displayName: "Sonnet 4 Thinking" },
|
|
53
|
+
"claude-4-sonnet-1m-thinking": { contextWindow: 1_000_000, safeContext: 300_000, contextConstraint: "moderate", displayName: "Sonnet 4 1M Thinking" },
|
|
54
|
+
// Haiku 4.5: cheapest Claude. 200K context, near-frontier smarts.
|
|
28
55
|
"claude-haiku-4-5": { contextWindow: 200_000, safeContext: 60_000, contextConstraint: "moderate", displayName: "Haiku 4.5" },
|
|
29
56
|
"claude-haiku-4-5-20251001": { contextWindow: 200_000, safeContext: 60_000, contextConstraint: "moderate", displayName: "Haiku 4.5" },
|
|
57
|
+
"claude-haiku-4-6": { contextWindow: 200_000, safeContext: 60_000, contextConstraint: "moderate", displayName: "Haiku 4.6" },
|
|
58
|
+
"claude-haiku-4": { contextWindow: 200_000, safeContext: 60_000, contextConstraint: "moderate", displayName: "Haiku 4" },
|
|
30
59
|
// ── OpenAI (Apr 2026 — GPT-4.1/o3/o4-mini retired Feb 2026) ──
|
|
31
60
|
// GPT-5.4: current flagship. 1M context, 128K output. Good but literal.
|
|
32
61
|
"gpt-5.4": { contextWindow: 1_050_000, safeContext: 300_000, contextConstraint: "moderate", displayName: "GPT-5.4" },
|
|
33
|
-
"gpt-5.4-
|
|
62
|
+
"gpt-5.4-low": { contextWindow: 1_050_000, safeContext: 300_000, contextConstraint: "moderate", displayName: "GPT-5.4 Low" },
|
|
63
|
+
"gpt-5.4-medium": { contextWindow: 1_050_000, safeContext: 300_000, contextConstraint: "moderate", displayName: "GPT-5.4 Medium" },
|
|
64
|
+
"gpt-5.4-medium-fast": { contextWindow: 1_050_000, safeContext: 300_000, contextConstraint: "moderate", displayName: "GPT-5.4 Fast" },
|
|
65
|
+
"gpt-5.4-high": { contextWindow: 1_050_000, safeContext: 300_000, contextConstraint: "moderate", displayName: "GPT-5.4 High" },
|
|
66
|
+
"gpt-5.4-high-fast": { contextWindow: 1_050_000, safeContext: 300_000, contextConstraint: "moderate", displayName: "GPT-5.4 High Fast" },
|
|
67
|
+
"gpt-5.4-xhigh": { contextWindow: 1_050_000, safeContext: 300_000, contextConstraint: "moderate", displayName: "GPT-5.4 Extra High" },
|
|
68
|
+
"gpt-5.4-xhigh-fast": { contextWindow: 1_050_000, safeContext: 300_000, contextConstraint: "moderate", displayName: "GPT-5.4 Extra High Fast" },
|
|
69
|
+
"gpt-5.4-mini": { contextWindow: 1_050_000, safeContext: 200_000, contextConstraint: "tight", displayName: "GPT-5.4 Mini" },
|
|
70
|
+
"gpt-5.4-mini-low": { contextWindow: 1_050_000, safeContext: 200_000, contextConstraint: "tight", displayName: "GPT-5.4 Mini Low" },
|
|
71
|
+
"gpt-5.4-mini-medium": { contextWindow: 1_050_000, safeContext: 200_000, contextConstraint: "tight", displayName: "GPT-5.4 Mini Medium" },
|
|
72
|
+
"gpt-5.4-mini-high": { contextWindow: 1_050_000, safeContext: 200_000, contextConstraint: "tight", displayName: "GPT-5.4 Mini High" },
|
|
73
|
+
"gpt-5.4-mini-xhigh": { contextWindow: 1_050_000, safeContext: 200_000, contextConstraint: "tight", displayName: "GPT-5.4 Mini Extra High" },
|
|
34
74
|
// Codex 5.3: best agentic coder from OpenAI. 400K context, 128K output.
|
|
35
75
|
"gpt-5.3-codex": { contextWindow: 400_000, safeContext: 160_000, contextConstraint: "moderate", displayName: "Codex 5.3" },
|
|
76
|
+
"gpt-5.3-codex-low": { contextWindow: 400_000, safeContext: 160_000, contextConstraint: "moderate", displayName: "Codex 5.3 Low" },
|
|
77
|
+
"gpt-5.3-codex-high": { contextWindow: 400_000, safeContext: 160_000, contextConstraint: "moderate", displayName: "Codex 5.3 High" },
|
|
78
|
+
"gpt-5.3-codex-xhigh": { contextWindow: 400_000, safeContext: 160_000, contextConstraint: "moderate", displayName: "Codex 5.3 Extra High" },
|
|
79
|
+
"gpt-5.3-codex-fast": { contextWindow: 400_000, safeContext: 160_000, contextConstraint: "moderate", displayName: "Codex 5.3 Fast" },
|
|
80
|
+
// Older OpenAI
|
|
81
|
+
"gpt-5.2": { contextWindow: 400_000, safeContext: 160_000, contextConstraint: "moderate", displayName: "GPT-5.2" },
|
|
82
|
+
"gpt-5.2-codex": { contextWindow: 400_000, safeContext: 160_000, contextConstraint: "moderate", displayName: "Codex 5.2" },
|
|
83
|
+
"gpt-5.1": { contextWindow: 400_000, safeContext: 160_000, contextConstraint: "moderate", displayName: "GPT-5.1" },
|
|
84
|
+
"gpt-5": { contextWindow: 400_000, safeContext: 160_000, contextConstraint: "moderate", displayName: "GPT-5" },
|
|
85
|
+
"gpt-5.1-codex-mini": { contextWindow: 400_000, safeContext: 160_000, contextConstraint: "moderate", displayName: "Codex 5.1 Mini" },
|
|
36
86
|
// ── Google Gemini 3 (Apr 2026 — Gemini 2.5 deprecated June 2026) ──
|
|
37
87
|
// Large context but terrible at agentic coding: 13.5% SWE-bench (vs Sonnet 31.2%).
|
|
38
88
|
// Good for reading lots of code, bad at following through. Needs surgical tasks.
|
|
@@ -40,6 +90,11 @@ export const MODEL_CAPABILITIES = {
|
|
|
40
90
|
"gemini-3-pro": { contextWindow: 1_000_000, safeContext: 350_000, contextConstraint: "tight", displayName: "Gemini 3 Pro" },
|
|
41
91
|
// Flash: 8.2% SWE-bench. Essentially unusable for autonomous agent work.
|
|
42
92
|
"gemini-3-flash": { contextWindow: 1_000_000, safeContext: 250_000, contextConstraint: "tight", displayName: "Gemini 3 Flash" },
|
|
93
|
+
// ── xAI Grok ──
|
|
94
|
+
"grok-4-20": { contextWindow: 256_000, safeContext: 80_000, contextConstraint: "moderate", displayName: "Grok 4.20" },
|
|
95
|
+
"grok-4-20-thinking": { contextWindow: 256_000, safeContext: 80_000, contextConstraint: "moderate", displayName: "Grok 4.20 Thinking" },
|
|
96
|
+
// ── Moonshot ──
|
|
97
|
+
"kimi-k2.5": { contextWindow: 128_000, safeContext: 40_000, contextConstraint: "tight", displayName: "Kimi K2.5" },
|
|
43
98
|
// ── DeepSeek V3.2 (Apr 2026 — V3/R1 superseded, V4 not yet out) ──
|
|
44
99
|
"deepseek-chat": { contextWindow: 128_000, safeContext: 40_000, contextConstraint: "tight", displayName: "DeepSeek V3.2" },
|
|
45
100
|
"deepseek-reasoner": { contextWindow: 128_000, safeContext: 45_000, contextConstraint: "moderate", displayName: "DeepSeek V3.2 Reasoner" },
|
|
@@ -50,7 +105,9 @@ export const MODEL_CAPABILITIES = {
|
|
|
50
105
|
// ── Cursor models (opaque routing) ──
|
|
51
106
|
"auto": { contextWindow: 256_000, safeContext: 60_000, contextConstraint: "moderate", displayName: "Cursor Auto" },
|
|
52
107
|
"composer-2": { contextWindow: 200_000, safeContext: 40_000, contextConstraint: "tight", displayName: "Composer 2" },
|
|
108
|
+
"composer-2-fast": { contextWindow: 200_000, safeContext: 40_000, contextConstraint: "tight", displayName: "Composer 2 Fast" },
|
|
53
109
|
"composer": { contextWindow: 128_000, safeContext: 30_000, contextConstraint: "tight", displayName: "Composer" },
|
|
110
|
+
"composer-1.5": { contextWindow: 128_000, safeContext: 30_000, contextConstraint: "tight", displayName: "Composer 1.5" },
|
|
54
111
|
// ── Qwen (Apr 2026 — qwen3.6-plus is newest flagship) ──
|
|
55
112
|
"qwen3.6-plus": { contextWindow: 1_000_000, safeContext: 200_000, contextConstraint: "moderate", displayName: "Qwen 3.6 Plus" },
|
|
56
113
|
"qwen3-coder-plus": { contextWindow: 1_000_000, safeContext: 200_000, contextConstraint: "moderate", displayName: "Qwen 3 Coder Plus" },
|
package/dist/planner-query.d.ts
CHANGED
|
@@ -13,6 +13,10 @@ export interface PlannerRateLimitInfo {
|
|
|
13
13
|
windows: Map<string, RateLimitWindow>;
|
|
14
14
|
resetsAt?: number;
|
|
15
15
|
costUsd: number;
|
|
16
|
+
/** Peak total input tokens (input + cache) in any single planner turn — proxy for context-window occupancy. */
|
|
17
|
+
contextTokens?: number;
|
|
18
|
+
/** Model used by the current planner query (for safeContext lookup). */
|
|
19
|
+
model?: string;
|
|
16
20
|
}
|
|
17
21
|
export interface PlannerOpts {
|
|
18
22
|
cwd: string;
|
|
@@ -30,14 +34,16 @@ export interface PlannerOpts {
|
|
|
30
34
|
*/
|
|
31
35
|
maxTurns?: number;
|
|
32
36
|
/**
|
|
33
|
-
* Tools the planner agent may use. Defaults to
|
|
34
|
-
* resilience). Deliberately excludes Bash/Agent/TodoWrite/WebFetch to prevent
|
|
35
|
-
* the multi-turn tool loops that cause error_max_turns with thinking models.
|
|
37
|
+
* Tools the planner agent may use. Defaults to the full Claude tool suite.
|
|
36
38
|
*/
|
|
37
39
|
tools?: string[];
|
|
38
40
|
}
|
|
39
41
|
export declare function setPlannerEnvResolver(fn: ((model?: string) => Record<string, string> | undefined) | undefined): void;
|
|
40
42
|
export declare function getTotalPlannerCost(): number;
|
|
43
|
+
export declare function getPeakPlannerContext(): {
|
|
44
|
+
tokens: number;
|
|
45
|
+
model?: string;
|
|
46
|
+
};
|
|
41
47
|
export declare function getPlannerRateLimitInfo(): PlannerRateLimitInfo;
|
|
42
48
|
export declare function runPlannerQuery(prompt: string, opts: PlannerOpts, onLog: PlannerLog): Promise<string>;
|
|
43
49
|
export declare function postProcess(raw: Task[], budget: number | undefined, onLog: (text: string) => void): Task[];
|
package/dist/planner-query.js
CHANGED
|
@@ -1,7 +1,13 @@
|
|
|
1
1
|
import { query } from "@anthropic-ai/claude-agent-sdk";
|
|
2
2
|
import { readFileSync } from "fs";
|
|
3
|
-
import { NudgeError } from "./types.js";
|
|
3
|
+
import { NudgeError, extractToolTarget, sumUsageTokens } from "./types.js";
|
|
4
4
|
import { writeTranscriptEvent } from "./transcripts.js";
|
|
5
|
+
/** Log a tool invocation with a short target for planner queries. */
|
|
6
|
+
const logTool = (label, input) => {
|
|
7
|
+
const target = extractToolTarget(input);
|
|
8
|
+
return target ? `${label} \u2192 ${target}` : label;
|
|
9
|
+
};
|
|
10
|
+
const DEFAULT_TOOLS = ["Read", "Glob", "Grep", "Write", "Bash", "WebFetch", "WebSearch", "TodoWrite", "Agent"];
|
|
5
11
|
const DEFAULT_MAX_TURNS = 20;
|
|
6
12
|
// ── Shared env resolver (set once at run start, used by every planner query) ──
|
|
7
13
|
//
|
|
@@ -20,6 +26,11 @@ function isRateLimitError(err) {
|
|
|
20
26
|
}
|
|
21
27
|
let _totalPlannerCostUsd = 0;
|
|
22
28
|
export function getTotalPlannerCost() { return _totalPlannerCostUsd; }
|
|
29
|
+
let _peakPlannerContextTokens = 0;
|
|
30
|
+
let _peakPlannerContextModel;
|
|
31
|
+
export function getPeakPlannerContext() {
|
|
32
|
+
return { tokens: _peakPlannerContextTokens, model: _peakPlannerContextModel };
|
|
33
|
+
}
|
|
23
34
|
let _plannerRateLimitInfo = {
|
|
24
35
|
utilization: 0, status: "", isUsingOverage: false, windows: new Map(), costUsd: 0,
|
|
25
36
|
};
|
|
@@ -65,22 +76,6 @@ async function throttlePlanner(onLog, aborted) {
|
|
|
65
76
|
}
|
|
66
77
|
// Exhausted backoffs — proceed anyway, the retry loop will catch a rejection.
|
|
67
78
|
}
|
|
68
|
-
/**
|
|
69
|
-
* Pick a short, human-readable target for a tool invocation (Read/Grep/Bash/…).
|
|
70
|
-
* Prefers explicit file paths; falls back to the first few tokens of a shell
|
|
71
|
-
* command. Returns `""` when the input has no useful identifier.
|
|
72
|
-
*/
|
|
73
|
-
function extractToolTarget(input) {
|
|
74
|
-
if (!input)
|
|
75
|
-
return "";
|
|
76
|
-
const p = input.path ?? input.file_path ?? input.pattern;
|
|
77
|
-
if (typeof p === "string" && p)
|
|
78
|
-
return p;
|
|
79
|
-
if (typeof input.command === "string" && input.command) {
|
|
80
|
-
return input.command.split(" ").slice(0, 3).join(" ");
|
|
81
|
-
}
|
|
82
|
-
return "";
|
|
83
|
-
}
|
|
84
79
|
// ── Query execution ──
|
|
85
80
|
const NUDGE_MS = 15 * 60 * 1000;
|
|
86
81
|
const HARD_TIMEOUT_MS = 30 * 60 * 1000;
|
|
@@ -122,7 +117,7 @@ export async function runPlannerQuery(prompt, opts, onLog) {
|
|
|
122
117
|
throw new Error("Planner query failed after retries");
|
|
123
118
|
}
|
|
124
119
|
async function runPlannerQueryOnce(prompt, opts, onLog) {
|
|
125
|
-
_plannerRateLimitInfo = { utilization: 0, status: "", isUsingOverage: false, windows: new Map(), costUsd: 0 };
|
|
120
|
+
_plannerRateLimitInfo = { utilization: 0, status: "", isUsingOverage: false, windows: new Map(), costUsd: 0, contextTokens: 0, model: opts.model };
|
|
126
121
|
let resultText = "";
|
|
127
122
|
let structuredOutput;
|
|
128
123
|
const startedAt = Date.now();
|
|
@@ -144,8 +139,8 @@ async function runPlannerQueryOnce(prompt, opts, onLog) {
|
|
|
144
139
|
options: {
|
|
145
140
|
cwd: opts.cwd,
|
|
146
141
|
model: opts.model,
|
|
147
|
-
tools: opts.tools ??
|
|
148
|
-
allowedTools: opts.tools ??
|
|
142
|
+
tools: opts.tools ?? DEFAULT_TOOLS,
|
|
143
|
+
allowedTools: opts.tools ?? DEFAULT_TOOLS,
|
|
149
144
|
permissionMode: opts.permissionMode,
|
|
150
145
|
...(opts.permissionMode === "bypassPermissions" && { allowDangerouslySkipPermissions: true }),
|
|
151
146
|
persistSession: true,
|
|
@@ -309,6 +304,16 @@ async function runPlannerQueryOnce(prompt, opts, onLog) {
|
|
|
309
304
|
// turn message for tool_use / thinking / text so the ticker still moves
|
|
310
305
|
// every ~6-15s instead of sitting silent for minutes.
|
|
311
306
|
if (msg.type === "assistant") {
|
|
307
|
+
const u = msg.message?.usage;
|
|
308
|
+
if (u) {
|
|
309
|
+
const turnTotal = sumUsageTokens(u);
|
|
310
|
+
if (turnTotal > (_plannerRateLimitInfo.contextTokens ?? 0))
|
|
311
|
+
_plannerRateLimitInfo.contextTokens = turnTotal;
|
|
312
|
+
if (turnTotal > _peakPlannerContextTokens) {
|
|
313
|
+
_peakPlannerContextTokens = turnTotal;
|
|
314
|
+
_peakPlannerContextModel = opts.model;
|
|
315
|
+
}
|
|
316
|
+
}
|
|
312
317
|
const content = msg.message?.content;
|
|
313
318
|
if (Array.isArray(content)) {
|
|
314
319
|
for (const part of content) {
|
package/dist/providers.js
CHANGED
|
@@ -11,6 +11,28 @@ import { getBearerToken, clearTokenCache } from "./auth.js";
|
|
|
11
11
|
import { DEFAULT_MODEL } from "./models.js";
|
|
12
12
|
import { CURSOR_PRIORITY_MODELS, CURSOR_KNOWN_MODELS, KNOWN_CURSOR_MODEL_IDS, cursorModelHint, } from "./cursor-models.js";
|
|
13
13
|
import { VERSION } from "./_version.js";
|
|
14
|
+
/** Cached system Node.js and agent script paths — resolved once, reused across envFor calls. */
|
|
15
|
+
let _cachedAgentNode = null;
|
|
16
|
+
let _cachedAgentScript = null;
|
|
17
|
+
/** Resolve system Node.js and agent index.js paths. Returns [nodePath, scriptPath] or [null, null]. */
|
|
18
|
+
function resolveAgentPaths(timeoutMs = 2_000) {
|
|
19
|
+
let nodePath = null;
|
|
20
|
+
let agentJs = null;
|
|
21
|
+
try {
|
|
22
|
+
nodePath = execSync("which node 2>/dev/null", { timeout: timeoutMs, encoding: "utf-8", shell: "bash" }).trim() || null;
|
|
23
|
+
const agentPath = execSync("command -v agent 2>/dev/null || command -v cursor-agent 2>/dev/null", {
|
|
24
|
+
timeout: timeoutMs, encoding: "utf-8", shell: "bash",
|
|
25
|
+
}).trim();
|
|
26
|
+
if (agentPath) {
|
|
27
|
+
const agentDir = dirname(realpathSync(agentPath));
|
|
28
|
+
const indexPath = `${agentDir}/index.js`;
|
|
29
|
+
if (existsSync(indexPath))
|
|
30
|
+
agentJs = indexPath;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
catch { }
|
|
34
|
+
return [nodePath, agentJs];
|
|
35
|
+
}
|
|
14
36
|
/** Run the installed package CLI with `node` (avoids npx/npm invoking extra tooling on macOS). */
|
|
15
37
|
function resolveCursorComposerCli() {
|
|
16
38
|
try {
|
|
@@ -124,6 +146,23 @@ export function envFor(p) {
|
|
|
124
146
|
// SDK replaces env for subprocesses — force these so nothing inherits a bad CI / skip flag.
|
|
125
147
|
base.CI = "true";
|
|
126
148
|
base.CURSOR_SKIP_KEYCHAIN = "1";
|
|
149
|
+
// Bridge mode controls the agent behavior: "plan" enables tool use (Read,
|
|
150
|
+
// Glob, Grep, Write, Bash), "ask" gives a chat-only assistant. Planner
|
|
151
|
+
// agents and workers must use "plan" so they actually interact with the codebase.
|
|
152
|
+
base.CURSOR_BRIDGE_MODE = "plan";
|
|
153
|
+
// Use system Node.js for agent subprocess to avoid macOS segfaults with
|
|
154
|
+
// bundled Node.js. Resolve lazily.
|
|
155
|
+
if (!_cachedAgentNode || !_cachedAgentScript) {
|
|
156
|
+
const [node, script] = resolveAgentPaths(2_000);
|
|
157
|
+
_cachedAgentNode = node;
|
|
158
|
+
_cachedAgentScript = script;
|
|
159
|
+
}
|
|
160
|
+
if (_cachedAgentNode) {
|
|
161
|
+
base.CURSOR_AGENT_NODE = _cachedAgentNode;
|
|
162
|
+
}
|
|
163
|
+
if (_cachedAgentScript) {
|
|
164
|
+
base.CURSOR_AGENT_SCRIPT = _cachedAgentScript;
|
|
165
|
+
}
|
|
127
166
|
return base;
|
|
128
167
|
}
|
|
129
168
|
const key = resolveKey(p);
|
|
@@ -814,21 +853,7 @@ async function startProxyProcess(baseUrl, url, port) {
|
|
|
814
853
|
console.log(chalk.yellow(`\n Proxy not running at ${baseUrl} — starting it for you…`));
|
|
815
854
|
// Resolve system node and agent index.js so the proxy uses system Node.js
|
|
816
855
|
// for the agent subprocess (avoids segfaults with --list-models on macOS).
|
|
817
|
-
|
|
818
|
-
let agentJs = null;
|
|
819
|
-
try {
|
|
820
|
-
sysNode = execSync("which node 2>/dev/null", { timeout: 3_000, encoding: "utf-8", shell: "bash" }).trim() || null;
|
|
821
|
-
const agentPath = execSync("command -v agent 2>/dev/null || command -v cursor-agent 2>/dev/null", {
|
|
822
|
-
timeout: 3_000, encoding: "utf-8", shell: "bash",
|
|
823
|
-
}).trim();
|
|
824
|
-
if (agentPath) {
|
|
825
|
-
const agentDir = dirname(realpathSync(agentPath));
|
|
826
|
-
const indexPath = `${agentDir}/index.js`;
|
|
827
|
-
if (existsSync(indexPath))
|
|
828
|
-
agentJs = indexPath;
|
|
829
|
-
}
|
|
830
|
-
}
|
|
831
|
-
catch { }
|
|
856
|
+
const [sysNode, agentJs] = resolveAgentPaths(3_000);
|
|
832
857
|
const apiKeyStored = loadProviders().find(p => p.cursorProxy)?.cursorApiKey;
|
|
833
858
|
const agentToken = resolveCursorAgentToken();
|
|
834
859
|
if (!agentToken) {
|
|
@@ -878,6 +903,9 @@ async function startProxyProcess(baseUrl, url, port) {
|
|
|
878
903
|
// the CLI path injects keychain-shim-inject.js via NODE_OPTIONS which no-ops
|
|
879
904
|
// /usr/bin/security calls on macOS (cursor-composer/dist/lib/process.js).
|
|
880
905
|
CURSOR_BRIDGE_USE_ACP: "0",
|
|
906
|
+
// Default bridge mode: "plan" enables tool use (Read, Glob, Grep, Write, Bash).
|
|
907
|
+
// "ask" gives a chat-only assistant that doesn't interact with the codebase.
|
|
908
|
+
CURSOR_BRIDGE_MODE: "plan",
|
|
881
909
|
// cursor-composer chat-only mode fakes HOME to a temp dir; on macOS the agent still waits on
|
|
882
910
|
// Keychain (~30s) for `cursor-user` despite CURSOR_API_KEY. Use the real workspace profile.
|
|
883
911
|
CURSOR_BRIDGE_CHAT_ONLY_WORKSPACE: "false",
|
|
@@ -905,6 +933,7 @@ async function startProxyProcess(baseUrl, url, port) {
|
|
|
905
933
|
childEnv: {
|
|
906
934
|
CI: proxyEnv.CI,
|
|
907
935
|
CURSOR_SKIP_KEYCHAIN: proxyEnv.CURSOR_SKIP_KEYCHAIN,
|
|
936
|
+
CURSOR_BRIDGE_MODE: proxyEnv.CURSOR_BRIDGE_MODE,
|
|
908
937
|
CURSOR_BRIDGE_USE_ACP: proxyEnv.CURSOR_BRIDGE_USE_ACP,
|
|
909
938
|
CURSOR_BRIDGE_CHAT_ONLY_WORKSPACE: proxyEnv.CURSOR_BRIDGE_CHAT_ONLY_WORKSPACE,
|
|
910
939
|
CURSOR_API_KEY: "(set)",
|
package/dist/render.d.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
|
+
import chalk from "chalk";
|
|
1
2
|
import type { Swarm } from "./swarm.js";
|
|
2
|
-
import type {
|
|
3
|
+
import type { RLGetter } from "./types.js";
|
|
3
4
|
import type { RunInfo, SteeringContext, SteeringEvent } from "./ui.js";
|
|
5
|
+
import { InteractivePanel } from "./interactive-panel.js";
|
|
4
6
|
export interface Section {
|
|
5
7
|
title: string;
|
|
6
8
|
rows: string[];
|
|
@@ -14,6 +16,11 @@ export interface ContentRenderer {
|
|
|
14
16
|
export declare function truncate(s: string, max: number): string;
|
|
15
17
|
export declare function fmtTokens(n: number): string;
|
|
16
18
|
export declare function fmtDur(ms: number): string;
|
|
19
|
+
/** Context-fill percentage and color function for a token count vs safe limit. */
|
|
20
|
+
export declare function contextFillInfo(tokens: number, safe: number): {
|
|
21
|
+
pct: number;
|
|
22
|
+
color: typeof chalk;
|
|
23
|
+
};
|
|
17
24
|
export declare function renderUnifiedFrame(params: {
|
|
18
25
|
model?: string;
|
|
19
26
|
phase: string;
|
|
@@ -36,13 +43,7 @@ export declare function renderUnifiedFrame(params: {
|
|
|
36
43
|
extraFooterRows?: string[];
|
|
37
44
|
maxRows?: number;
|
|
38
45
|
}): string;
|
|
39
|
-
|
|
40
|
-
utilization: number;
|
|
41
|
-
isUsingOverage: boolean;
|
|
42
|
-
windows: Map<string, RateLimitWindow>;
|
|
43
|
-
resetsAt?: number;
|
|
44
|
-
};
|
|
45
|
-
export declare function renderFrame(swarm: Swarm, showHotkeys: boolean, runInfo?: RunInfo, selectedAgentId?: number, maxRows?: number, debrief?: string): string;
|
|
46
|
+
export declare function renderFrame(swarm: Swarm, showHotkeys: boolean, runInfo?: RunInfo, selectedAgentId?: number, maxRows?: number, panel?: InteractivePanel): string;
|
|
46
47
|
export interface SteeringViewData {
|
|
47
48
|
/** The ephemeral ticker heartbeat -- elapsed, tool count, cost, current reasoning snippet. */
|
|
48
49
|
statusLine: string;
|
|
@@ -51,6 +52,5 @@ export interface SteeringViewData {
|
|
|
51
52
|
/** Optional context read from disk at setSteering() time. */
|
|
52
53
|
context?: SteeringContext;
|
|
53
54
|
}
|
|
54
|
-
export declare function renderSteeringFrame(runInfo: RunInfo, data: SteeringViewData, showHotkeys: boolean, rlGetter?: RLGetter, maxRows?: number,
|
|
55
|
+
export declare function renderSteeringFrame(runInfo: RunInfo, data: SteeringViewData, showHotkeys: boolean, rlGetter?: RLGetter, maxRows?: number, panel?: InteractivePanel): string;
|
|
55
56
|
export declare function renderSummary(swarm: Swarm): string;
|
|
56
|
-
export {};
|