@rama_nigg/open-cursor 2.4.3 → 2.4.5
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/cli/discover.js +9 -0
- package/dist/cli/opencode-cursor.js +9 -0
- package/dist/index.js +176 -220
- package/dist/plugin-entry.js +167 -191
- package/package.json +1 -1
- package/src/auth.ts +2 -2
- package/src/client/simple.ts +3 -3
- package/src/plugin.ts +94 -142
- package/src/streaming/ai-sdk-parts.ts +8 -30
- package/src/streaming/delta-tracker.ts +42 -0
- package/src/streaming/openai-sse.ts +8 -33
- package/src/tools/defaults.ts +1 -1
- package/src/utils/binary.ts +17 -3
package/dist/cli/discover.js
CHANGED
|
@@ -298,6 +298,15 @@ function resolveCursorAgentBinary(deps = {}) {
|
|
|
298
298
|
log.warn("cursor-agent not found at known paths, falling back to PATH", { checkedPaths: knownPaths });
|
|
299
299
|
return "cursor-agent";
|
|
300
300
|
}
|
|
301
|
+
function formatShellCommandForPlatform(command, platform = process.platform) {
|
|
302
|
+
if (platform !== "win32") {
|
|
303
|
+
return command;
|
|
304
|
+
}
|
|
305
|
+
if (command.startsWith('"') && command.endsWith('"')) {
|
|
306
|
+
return command;
|
|
307
|
+
}
|
|
308
|
+
return `"${command}"`;
|
|
309
|
+
}
|
|
301
310
|
var log;
|
|
302
311
|
var init_binary = __esm(() => {
|
|
303
312
|
init_logger();
|
|
@@ -298,6 +298,15 @@ function resolveCursorAgentBinary(deps = {}) {
|
|
|
298
298
|
log.warn("cursor-agent not found at known paths, falling back to PATH", { checkedPaths: knownPaths });
|
|
299
299
|
return "cursor-agent";
|
|
300
300
|
}
|
|
301
|
+
function formatShellCommandForPlatform(command, platform = process.platform) {
|
|
302
|
+
if (platform !== "win32") {
|
|
303
|
+
return command;
|
|
304
|
+
}
|
|
305
|
+
if (command.startsWith('"') && command.endsWith('"')) {
|
|
306
|
+
return command;
|
|
307
|
+
}
|
|
308
|
+
return `"${command}"`;
|
|
309
|
+
}
|
|
301
310
|
var log;
|
|
302
311
|
var init_binary = __esm(() => {
|
|
303
312
|
init_logger();
|
package/dist/index.js
CHANGED
|
@@ -456,6 +456,15 @@ function resolveCursorAgentBinary(deps = {}) {
|
|
|
456
456
|
log.warn("cursor-agent not found at known paths, falling back to PATH", { checkedPaths: knownPaths });
|
|
457
457
|
return "cursor-agent";
|
|
458
458
|
}
|
|
459
|
+
function formatShellCommandForPlatform(command, platform = process.platform) {
|
|
460
|
+
if (platform !== "win32") {
|
|
461
|
+
return command;
|
|
462
|
+
}
|
|
463
|
+
if (command.startsWith('"') && command.endsWith('"')) {
|
|
464
|
+
return command;
|
|
465
|
+
}
|
|
466
|
+
return `"${command}"`;
|
|
467
|
+
}
|
|
459
468
|
var log;
|
|
460
469
|
var init_binary = __esm(() => {
|
|
461
470
|
init_logger();
|
|
@@ -505,7 +514,7 @@ async function pollForAuthFile(timeoutMs = AUTH_POLL_TIMEOUT, intervalMs = AUTH_
|
|
|
505
514
|
async function startCursorOAuth() {
|
|
506
515
|
return new Promise((resolve, reject) => {
|
|
507
516
|
log2.info("Starting cursor-cli login process");
|
|
508
|
-
const proc = spawn(resolveCursorAgentBinary(), ["login"], {
|
|
517
|
+
const proc = spawn(formatShellCommandForPlatform(resolveCursorAgentBinary()), ["login"], {
|
|
509
518
|
stdio: ["pipe", "pipe", "pipe"],
|
|
510
519
|
shell: process.platform === "win32"
|
|
511
520
|
});
|
|
@@ -699,29 +708,6 @@ class LineBuffer {
|
|
|
699
708
|
}
|
|
700
709
|
}
|
|
701
710
|
|
|
702
|
-
// src/streaming/types.ts
|
|
703
|
-
var hasTextContent = (event) => event.message.content.some((content) => content.type === "text"), hasThinkingContent = (event) => event.message.content.some((content) => content.type === "thinking"), isAssistantText = (event) => event.type === "assistant" && hasTextContent(event), isThinking = (event) => {
|
|
704
|
-
if (event.type === "thinking") {
|
|
705
|
-
return true;
|
|
706
|
-
}
|
|
707
|
-
return event.type === "assistant" && hasThinkingContent(event);
|
|
708
|
-
}, isToolCall = (event) => event.type === "tool_call", isResult = (event) => event.type === "result", extractText = (event) => event.message.content.filter((content) => content.type === "text").map((content) => content.text).join(""), extractThinking = (event) => {
|
|
709
|
-
if (event.type === "thinking") {
|
|
710
|
-
return event.text ?? "";
|
|
711
|
-
}
|
|
712
|
-
return event.message.content.filter((content) => content.type === "thinking").map((content) => content.thinking).join("");
|
|
713
|
-
}, inferToolName = (event) => {
|
|
714
|
-
const [key] = Object.keys(event.tool_call ?? {});
|
|
715
|
-
if (!key) {
|
|
716
|
-
return "";
|
|
717
|
-
}
|
|
718
|
-
if (key.endsWith("ToolCall")) {
|
|
719
|
-
const base = key.slice(0, -"ToolCall".length);
|
|
720
|
-
return base.charAt(0).toLowerCase() + base.slice(1);
|
|
721
|
-
}
|
|
722
|
-
return key;
|
|
723
|
-
};
|
|
724
|
-
|
|
725
711
|
// src/streaming/delta-tracker.ts
|
|
726
712
|
class DeltaTracker {
|
|
727
713
|
lastText = "";
|
|
@@ -759,14 +745,70 @@ class DeltaTracker {
|
|
|
759
745
|
}
|
|
760
746
|
}
|
|
761
747
|
|
|
748
|
+
class MixedDeltaTracker {
|
|
749
|
+
emittedText = "";
|
|
750
|
+
emittedThinking = "";
|
|
751
|
+
nextText(value) {
|
|
752
|
+
const delta = this.diff(this.emittedText, value);
|
|
753
|
+
if (delta) {
|
|
754
|
+
this.emittedText += delta;
|
|
755
|
+
}
|
|
756
|
+
return delta;
|
|
757
|
+
}
|
|
758
|
+
nextThinking(value) {
|
|
759
|
+
const delta = this.diff(this.emittedThinking, value);
|
|
760
|
+
if (delta) {
|
|
761
|
+
this.emittedThinking += delta;
|
|
762
|
+
}
|
|
763
|
+
return delta;
|
|
764
|
+
}
|
|
765
|
+
reset() {
|
|
766
|
+
this.emittedText = "";
|
|
767
|
+
this.emittedThinking = "";
|
|
768
|
+
}
|
|
769
|
+
diff(emitted, current) {
|
|
770
|
+
if (!emitted) {
|
|
771
|
+
return current;
|
|
772
|
+
}
|
|
773
|
+
if (current.startsWith(emitted)) {
|
|
774
|
+
return current.slice(emitted.length);
|
|
775
|
+
}
|
|
776
|
+
if (emitted.startsWith(current)) {
|
|
777
|
+
return "";
|
|
778
|
+
}
|
|
779
|
+
return current;
|
|
780
|
+
}
|
|
781
|
+
}
|
|
782
|
+
|
|
783
|
+
// src/streaming/types.ts
|
|
784
|
+
var hasTextContent = (event) => event.message.content.some((content) => content.type === "text"), hasThinkingContent = (event) => event.message.content.some((content) => content.type === "thinking"), isAssistantText = (event) => event.type === "assistant" && hasTextContent(event), isThinking = (event) => {
|
|
785
|
+
if (event.type === "thinking") {
|
|
786
|
+
return true;
|
|
787
|
+
}
|
|
788
|
+
return event.type === "assistant" && hasThinkingContent(event);
|
|
789
|
+
}, isToolCall = (event) => event.type === "tool_call", isResult = (event) => event.type === "result", extractText = (event) => event.message.content.filter((content) => content.type === "text").map((content) => content.text).join(""), extractThinking = (event) => {
|
|
790
|
+
if (event.type === "thinking") {
|
|
791
|
+
return event.text ?? "";
|
|
792
|
+
}
|
|
793
|
+
return event.message.content.filter((content) => content.type === "thinking").map((content) => content.thinking).join("");
|
|
794
|
+
}, inferToolName = (event) => {
|
|
795
|
+
const [key] = Object.keys(event.tool_call ?? {});
|
|
796
|
+
if (!key) {
|
|
797
|
+
return "";
|
|
798
|
+
}
|
|
799
|
+
if (key.endsWith("ToolCall")) {
|
|
800
|
+
const base = key.slice(0, -"ToolCall".length);
|
|
801
|
+
return base.charAt(0).toLowerCase() + base.slice(1);
|
|
802
|
+
}
|
|
803
|
+
return key;
|
|
804
|
+
};
|
|
805
|
+
|
|
762
806
|
// src/streaming/openai-sse.ts
|
|
763
807
|
class StreamToSseConverter {
|
|
764
808
|
id;
|
|
765
809
|
created;
|
|
766
810
|
model;
|
|
767
|
-
tracker = new
|
|
768
|
-
sawAssistantPartials = false;
|
|
769
|
-
sawThinkingPartials = false;
|
|
811
|
+
tracker = new MixedDeltaTracker;
|
|
770
812
|
constructor(model, options) {
|
|
771
813
|
this.model = model;
|
|
772
814
|
this.id = options?.id ?? `cursor-acp-${Date.now()}`;
|
|
@@ -774,35 +816,17 @@ class StreamToSseConverter {
|
|
|
774
816
|
}
|
|
775
817
|
handleEvent(event) {
|
|
776
818
|
if (isAssistantText(event)) {
|
|
777
|
-
const
|
|
778
|
-
if (
|
|
779
|
-
const text = extractText(event);
|
|
780
|
-
if (text) {
|
|
781
|
-
this.sawAssistantPartials = true;
|
|
782
|
-
return [this.chunkWith({ content: text })];
|
|
783
|
-
}
|
|
784
|
-
return [];
|
|
785
|
-
}
|
|
786
|
-
if (this.sawAssistantPartials) {
|
|
819
|
+
const text = extractText(event);
|
|
820
|
+
if (!text)
|
|
787
821
|
return [];
|
|
788
|
-
|
|
789
|
-
const delta = this.tracker.nextText(extractText(event));
|
|
822
|
+
const delta = this.tracker.nextText(text);
|
|
790
823
|
return delta ? [this.chunkWith({ content: delta })] : [];
|
|
791
824
|
}
|
|
792
825
|
if (isThinking(event)) {
|
|
793
|
-
const
|
|
794
|
-
if (
|
|
795
|
-
const text = extractThinking(event);
|
|
796
|
-
if (text) {
|
|
797
|
-
this.sawThinkingPartials = true;
|
|
798
|
-
return [this.chunkWith({ reasoning_content: text })];
|
|
799
|
-
}
|
|
800
|
-
return [];
|
|
801
|
-
}
|
|
802
|
-
if (this.sawThinkingPartials) {
|
|
826
|
+
const text = extractThinking(event);
|
|
827
|
+
if (!text)
|
|
803
828
|
return [];
|
|
804
|
-
|
|
805
|
-
const delta = this.tracker.nextThinking(extractThinking(event));
|
|
829
|
+
const delta = this.tracker.nextThinking(text);
|
|
806
830
|
return delta ? [this.chunkWith({ reasoning_content: delta })] : [];
|
|
807
831
|
}
|
|
808
832
|
if (isToolCall(event)) {
|
|
@@ -13796,7 +13820,7 @@ ${output}`);
|
|
|
13796
13820
|
if (include) {
|
|
13797
13821
|
grepArgs.push(`--include=${include}`);
|
|
13798
13822
|
}
|
|
13799
|
-
grepArgs.push(pattern, path2);
|
|
13823
|
+
grepArgs.push("-e", pattern, path2);
|
|
13800
13824
|
const runGrep = async (extraArgs = []) => {
|
|
13801
13825
|
return execFileAsync("grep", [...extraArgs, ...grepArgs], { timeout: 30000 });
|
|
13802
13826
|
};
|
|
@@ -16110,6 +16134,7 @@ function extractCompletionFromStream(output) {
|
|
|
16110
16134
|
let usage;
|
|
16111
16135
|
let sawAssistantPartials = false;
|
|
16112
16136
|
let sawThinkingPartials = false;
|
|
16137
|
+
const tracker = new MixedDeltaTracker;
|
|
16113
16138
|
for (const line of lines) {
|
|
16114
16139
|
const event = parseStreamJsonLine(line);
|
|
16115
16140
|
if (!event) {
|
|
@@ -16121,8 +16146,8 @@ function extractCompletionFromStream(output) {
|
|
|
16121
16146
|
continue;
|
|
16122
16147
|
const isPartial = typeof event.timestamp_ms === "number";
|
|
16123
16148
|
if (isPartial) {
|
|
16124
|
-
assistantText += text;
|
|
16125
16149
|
sawAssistantPartials = true;
|
|
16150
|
+
assistantText += tracker.nextText(text);
|
|
16126
16151
|
} else if (!sawAssistantPartials) {
|
|
16127
16152
|
assistantText = text;
|
|
16128
16153
|
}
|
|
@@ -16132,8 +16157,8 @@ function extractCompletionFromStream(output) {
|
|
|
16132
16157
|
if (thinking) {
|
|
16133
16158
|
const isPartial = typeof event.timestamp_ms === "number";
|
|
16134
16159
|
if (isPartial) {
|
|
16135
|
-
reasoningText += thinking;
|
|
16136
16160
|
sawThinkingPartials = true;
|
|
16161
|
+
reasoningText += tracker.nextThinking(thinking);
|
|
16137
16162
|
} else if (!sawThinkingPartials) {
|
|
16138
16163
|
reasoningText = thinking;
|
|
16139
16164
|
}
|
|
@@ -16820,7 +16845,7 @@ async function ensureCursorProxyServer(workspaceDirectory, toolRouter) {
|
|
|
16820
16845
|
if (FORCE_TOOL_MODE) {
|
|
16821
16846
|
cmd.push("--force");
|
|
16822
16847
|
}
|
|
16823
|
-
const child = spawn3(cmd[0], cmd.slice(1), {
|
|
16848
|
+
const child = spawn3(formatShellCommandForPlatform(cmd[0]), cmd.slice(1), {
|
|
16824
16849
|
stdio: ["pipe", "pipe", "pipe"],
|
|
16825
16850
|
shell: process.platform === "win32"
|
|
16826
16851
|
});
|
|
@@ -16967,22 +16992,18 @@ async function ensureCursorProxyServer(workspaceDirectory, toolRouter) {
|
|
|
16967
16992
|
child.kill();
|
|
16968
16993
|
} catch {}
|
|
16969
16994
|
};
|
|
16970
|
-
|
|
16971
|
-
|
|
16972
|
-
|
|
16973
|
-
|
|
16974
|
-
|
|
16975
|
-
|
|
16976
|
-
|
|
16977
|
-
|
|
16978
|
-
for (const line of lineBuffer.push(chunk)) {
|
|
16979
|
-
if (streamTerminated || res.writableEnded) {
|
|
16995
|
+
const chunkQueue = [];
|
|
16996
|
+
let draining = false;
|
|
16997
|
+
let childClosed = false;
|
|
16998
|
+
let childCloseHandled = false;
|
|
16999
|
+
let childExitCode = null;
|
|
17000
|
+
const processLines = async (lines) => {
|
|
17001
|
+
for (const line of lines) {
|
|
17002
|
+
if (streamTerminated || res.writableEnded)
|
|
16980
17003
|
break;
|
|
16981
|
-
}
|
|
16982
17004
|
const event = parseStreamJsonLine(line);
|
|
16983
|
-
if (!event)
|
|
17005
|
+
if (!event)
|
|
16984
17006
|
continue;
|
|
16985
|
-
}
|
|
16986
17007
|
if (isResult(event)) {
|
|
16987
17008
|
usage = extractOpenAiUsageFromResult(event) ?? usage;
|
|
16988
17009
|
}
|
|
@@ -17031,148 +17052,100 @@ async function ensureCursorProxyServer(workspaceDirectory, toolRouter) {
|
|
|
17031
17052
|
}
|
|
17032
17053
|
break;
|
|
17033
17054
|
}
|
|
17034
|
-
if (result.intercepted)
|
|
17055
|
+
if (result.intercepted)
|
|
17035
17056
|
break;
|
|
17036
|
-
|
|
17037
|
-
if (result.skipConverter) {
|
|
17057
|
+
if (result.skipConverter)
|
|
17038
17058
|
continue;
|
|
17039
|
-
}
|
|
17040
17059
|
}
|
|
17041
|
-
if (streamTerminated || res.writableEnded)
|
|
17060
|
+
if (streamTerminated || res.writableEnded)
|
|
17042
17061
|
break;
|
|
17043
|
-
}
|
|
17044
17062
|
for (const sse of converter.handleEvent(event)) {
|
|
17045
17063
|
res.write(sse);
|
|
17046
17064
|
}
|
|
17047
17065
|
}
|
|
17048
|
-
}
|
|
17049
|
-
|
|
17050
|
-
if (
|
|
17066
|
+
};
|
|
17067
|
+
const drainQueue = async () => {
|
|
17068
|
+
if (draining)
|
|
17051
17069
|
return;
|
|
17052
|
-
|
|
17053
|
-
|
|
17054
|
-
|
|
17055
|
-
|
|
17056
|
-
}
|
|
17057
|
-
const event = parseStreamJsonLine(line);
|
|
17058
|
-
if (!event) {
|
|
17059
|
-
continue;
|
|
17060
|
-
}
|
|
17061
|
-
if (isResult(event)) {
|
|
17062
|
-
usage = extractOpenAiUsageFromResult(event) ?? usage;
|
|
17063
|
-
}
|
|
17064
|
-
if (event.type === "tool_call") {
|
|
17065
|
-
const result = await handleToolLoopEventWithFallback({
|
|
17066
|
-
event,
|
|
17067
|
-
boundary: boundaryContext.getBoundary(),
|
|
17068
|
-
boundaryMode: boundaryContext.getBoundary().mode,
|
|
17069
|
-
autoFallbackToLegacy: ENABLE_PROVIDER_BOUNDARY_AUTOFALLBACK,
|
|
17070
|
-
toolLoopMode: TOOL_LOOP_MODE,
|
|
17071
|
-
allowedToolNames,
|
|
17072
|
-
toolSchemaMap,
|
|
17073
|
-
toolLoopGuard,
|
|
17074
|
-
toolMapper,
|
|
17075
|
-
toolSessionId,
|
|
17076
|
-
shouldEmitToolUpdates: SHOULD_EMIT_TOOL_UPDATES,
|
|
17077
|
-
proxyExecuteToolCalls: PROXY_EXECUTE_TOOL_CALLS,
|
|
17078
|
-
suppressConverterToolEvents: SUPPRESS_CONVERTER_TOOL_EVENTS,
|
|
17079
|
-
toolRouter,
|
|
17080
|
-
responseMeta: { id, created, model },
|
|
17081
|
-
passThroughTracker,
|
|
17082
|
-
onToolUpdate: (update) => {
|
|
17083
|
-
res.write(formatToolUpdateEvent(update));
|
|
17084
|
-
},
|
|
17085
|
-
onToolResult: (toolResult) => {
|
|
17086
|
-
res.write(`data: ${JSON.stringify(toolResult)}
|
|
17087
|
-
|
|
17088
|
-
`);
|
|
17089
|
-
},
|
|
17090
|
-
onInterceptedToolCall: (toolCall) => {
|
|
17091
|
-
emitToolCallAndTerminate(toolCall);
|
|
17092
|
-
},
|
|
17093
|
-
onFallbackToLegacy: (error) => {
|
|
17094
|
-
boundaryContext.activateLegacyFallback("handleToolLoopEvent.close", error);
|
|
17095
|
-
}
|
|
17096
|
-
});
|
|
17097
|
-
if (result.terminate) {
|
|
17098
|
-
if (!result.terminate.silent) {
|
|
17099
|
-
emitTerminalAssistantErrorAndTerminate(result.terminate.message);
|
|
17100
|
-
} else {
|
|
17101
|
-
streamTerminated = true;
|
|
17102
|
-
try {
|
|
17103
|
-
child.kill();
|
|
17104
|
-
} catch {}
|
|
17105
|
-
}
|
|
17106
|
-
break;
|
|
17107
|
-
}
|
|
17108
|
-
if (result.intercepted) {
|
|
17070
|
+
draining = true;
|
|
17071
|
+
try {
|
|
17072
|
+
while (chunkQueue.length > 0) {
|
|
17073
|
+
if (streamTerminated || res.writableEnded)
|
|
17109
17074
|
break;
|
|
17075
|
+
const chunk = chunkQueue.shift();
|
|
17076
|
+
if (!firstTokenReceived) {
|
|
17077
|
+
perf.mark("first-token");
|
|
17078
|
+
firstTokenReceived = true;
|
|
17110
17079
|
}
|
|
17111
|
-
|
|
17112
|
-
continue;
|
|
17113
|
-
}
|
|
17114
|
-
}
|
|
17115
|
-
if (streamTerminated || res.writableEnded) {
|
|
17116
|
-
break;
|
|
17117
|
-
}
|
|
17118
|
-
for (const sse of converter.handleEvent(event)) {
|
|
17119
|
-
res.write(sse);
|
|
17080
|
+
await processLines(lineBuffer.push(chunk));
|
|
17120
17081
|
}
|
|
17121
|
-
|
|
17122
|
-
|
|
17123
|
-
|
|
17124
|
-
|
|
17125
|
-
|
|
17126
|
-
|
|
17127
|
-
|
|
17128
|
-
|
|
17129
|
-
|
|
17130
|
-
|
|
17131
|
-
|
|
17132
|
-
|
|
17133
|
-
|
|
17134
|
-
|
|
17135
|
-
|
|
17136
|
-
|
|
17137
|
-
|
|
17082
|
+
if (childClosed && !childCloseHandled && !streamTerminated && !res.writableEnded) {
|
|
17083
|
+
childCloseHandled = true;
|
|
17084
|
+
await processLines(lineBuffer.flush());
|
|
17085
|
+
if (streamTerminated || res.writableEnded)
|
|
17086
|
+
return;
|
|
17087
|
+
perf.mark("request:done");
|
|
17088
|
+
perf.summarize();
|
|
17089
|
+
const stderrText = Buffer.concat(stderrChunks).toString().trim();
|
|
17090
|
+
log20.debug("cursor-agent completed (node stream)", {
|
|
17091
|
+
code: childExitCode,
|
|
17092
|
+
stderrChars: stderrText.length
|
|
17093
|
+
});
|
|
17094
|
+
if (childExitCode !== 0) {
|
|
17095
|
+
const errSource = stderrText || `cursor-agent exited with code ${String(childExitCode ?? "unknown")} and no output`;
|
|
17096
|
+
const parsed = parseAgentError(errSource);
|
|
17097
|
+
const msg = formatErrorForUser(parsed);
|
|
17098
|
+
const errChunk = createChatCompletionChunk(id, created, model, msg, true);
|
|
17099
|
+
res.write(`data: ${JSON.stringify(errChunk)}
|
|
17138
17100
|
|
|
17139
17101
|
`);
|
|
17140
|
-
|
|
17141
|
-
|
|
17142
|
-
|
|
17143
|
-
|
|
17144
|
-
}
|
|
17145
|
-
const passThroughSummary = passThroughTracker.getSummary();
|
|
17146
|
-
if (passThroughSummary.hasActivity) {
|
|
17147
|
-
await toastService.showPassThroughSummary(passThroughSummary.tools);
|
|
17148
|
-
}
|
|
17149
|
-
if (passThroughSummary.errors.length > 0) {
|
|
17150
|
-
await toastService.showErrorSummary(passThroughSummary.errors);
|
|
17151
|
-
}
|
|
17152
|
-
const doneChunk = {
|
|
17153
|
-
id,
|
|
17154
|
-
object: "chat.completion.chunk",
|
|
17155
|
-
created,
|
|
17156
|
-
model,
|
|
17157
|
-
choices: [
|
|
17158
|
-
{
|
|
17159
|
-
index: 0,
|
|
17160
|
-
delta: {},
|
|
17161
|
-
finish_reason: "stop"
|
|
17102
|
+
res.write(formatSseDone());
|
|
17103
|
+
streamTerminated = true;
|
|
17104
|
+
res.end();
|
|
17105
|
+
return;
|
|
17162
17106
|
}
|
|
17163
|
-
|
|
17164
|
-
|
|
17165
|
-
|
|
17107
|
+
const passThroughSummary = passThroughTracker.getSummary();
|
|
17108
|
+
if (passThroughSummary.hasActivity) {
|
|
17109
|
+
await toastService.showPassThroughSummary(passThroughSummary.tools);
|
|
17110
|
+
}
|
|
17111
|
+
if (passThroughSummary.errors.length > 0) {
|
|
17112
|
+
await toastService.showErrorSummary(passThroughSummary.errors);
|
|
17113
|
+
}
|
|
17114
|
+
const doneChunk = {
|
|
17115
|
+
id,
|
|
17116
|
+
object: "chat.completion.chunk",
|
|
17117
|
+
created,
|
|
17118
|
+
model,
|
|
17119
|
+
choices: [{ index: 0, delta: {}, finish_reason: "stop" }]
|
|
17120
|
+
};
|
|
17121
|
+
res.write(`data: ${JSON.stringify(doneChunk)}
|
|
17166
17122
|
|
|
17167
17123
|
`);
|
|
17168
|
-
|
|
17169
|
-
|
|
17170
|
-
|
|
17124
|
+
if (usage) {
|
|
17125
|
+
const usageChunk = createChatCompletionUsageChunk(id, created, model, usage);
|
|
17126
|
+
res.write(`data: ${JSON.stringify(usageChunk)}
|
|
17171
17127
|
|
|
17172
17128
|
`);
|
|
17129
|
+
}
|
|
17130
|
+
res.write(formatSseDone());
|
|
17131
|
+
streamTerminated = true;
|
|
17132
|
+
res.end();
|
|
17133
|
+
}
|
|
17134
|
+
} finally {
|
|
17135
|
+
draining = false;
|
|
17136
|
+
if (!streamTerminated && !res.writableEnded && (chunkQueue.length > 0 || childClosed && !childCloseHandled)) {
|
|
17137
|
+
drainQueue();
|
|
17138
|
+
}
|
|
17173
17139
|
}
|
|
17174
|
-
|
|
17175
|
-
|
|
17140
|
+
};
|
|
17141
|
+
child.stdout.on("data", (chunk) => {
|
|
17142
|
+
chunkQueue.push(Buffer.from(chunk));
|
|
17143
|
+
drainQueue();
|
|
17144
|
+
});
|
|
17145
|
+
child.on("close", (code) => {
|
|
17146
|
+
childClosed = true;
|
|
17147
|
+
childExitCode = code;
|
|
17148
|
+
drainQueue();
|
|
17176
17149
|
});
|
|
17177
17150
|
}
|
|
17178
17151
|
} catch (error) {
|
|
@@ -17347,6 +17320,8 @@ function buildToolHookEntries(registry, fallbackBaseDir) {
|
|
|
17347
17320
|
const sessionWorkspaceBySession = new Map;
|
|
17348
17321
|
const tools = registry.list();
|
|
17349
17322
|
for (const t of tools) {
|
|
17323
|
+
if (NATIVE_TOOL_HOOK_EXCLUSIONS.has(t.name))
|
|
17324
|
+
continue;
|
|
17350
17325
|
const handler = registry.getHandler(t.name);
|
|
17351
17326
|
if (!handler)
|
|
17352
17327
|
continue;
|
|
@@ -17371,7 +17346,7 @@ function buildToolHookEntries(registry, fallbackBaseDir) {
|
|
|
17371
17346
|
}
|
|
17372
17347
|
return entries;
|
|
17373
17348
|
}
|
|
17374
|
-
var log20, DEBUG_LOG_DIR2, DEBUG_LOG_FILE2, CURSOR_PROVIDER_ID2 = "cursor-acp", CURSOR_PROVIDER_PREFIX, CURSOR_PROXY_HOST = "127.0.0.1", CURSOR_PROXY_DEFAULT_PORT = 32124, CURSOR_PROXY_DEFAULT_BASE_URL, REUSE_EXISTING_PROXY, SESSION_WORKSPACE_CACHE_LIMIT = 200, FORCE_TOOL_MODE, EMIT_TOOL_UPDATES, FORWARD_TOOL_CALLS, TOOL_LOOP_MODE_RAW, TOOL_LOOP_MODE, TOOL_LOOP_MODE_VALID, PROVIDER_BOUNDARY_MODE_RAW, PROVIDER_BOUNDARY_MODE, PROVIDER_BOUNDARY_MODE_VALID, LEGACY_PROVIDER_BOUNDARY, PROVIDER_BOUNDARY, ENABLE_PROVIDER_BOUNDARY_AUTOFALLBACK, TOOL_LOOP_MAX_REPEAT_RAW, TOOL_LOOP_MAX_REPEAT, TOOL_LOOP_MAX_REPEAT_VALID, PROXY_EXECUTE_TOOL_CALLS, SUPPRESS_CONVERTER_TOOL_EVENTS, SHOULD_EMIT_TOOL_UPDATES, CursorPlugin = async ({ $, directory, worktree, client: client3, serverUrl }) => {
|
|
17349
|
+
var log20, DEBUG_LOG_DIR2, DEBUG_LOG_FILE2, CURSOR_PROVIDER_ID2 = "cursor-acp", CURSOR_PROVIDER_PREFIX, CURSOR_PROXY_HOST = "127.0.0.1", CURSOR_PROXY_DEFAULT_PORT = 32124, CURSOR_PROXY_DEFAULT_BASE_URL, REUSE_EXISTING_PROXY, SESSION_WORKSPACE_CACHE_LIMIT = 200, FORCE_TOOL_MODE, EMIT_TOOL_UPDATES, FORWARD_TOOL_CALLS, TOOL_LOOP_MODE_RAW, TOOL_LOOP_MODE, TOOL_LOOP_MODE_VALID, PROVIDER_BOUNDARY_MODE_RAW, PROVIDER_BOUNDARY_MODE, PROVIDER_BOUNDARY_MODE_VALID, LEGACY_PROVIDER_BOUNDARY, PROVIDER_BOUNDARY, ENABLE_PROVIDER_BOUNDARY_AUTOFALLBACK, TOOL_LOOP_MAX_REPEAT_RAW, TOOL_LOOP_MAX_REPEAT, TOOL_LOOP_MAX_REPEAT_VALID, PROXY_EXECUTE_TOOL_CALLS, SUPPRESS_CONVERTER_TOOL_EVENTS, SHOULD_EMIT_TOOL_UPDATES, NATIVE_TOOL_HOOK_EXCLUSIONS, CursorPlugin = async ({ $, directory, worktree, client: client3, serverUrl }) => {
|
|
17375
17350
|
const workspaceDirectory = resolveWorkspaceDirectory(worktree, directory);
|
|
17376
17351
|
log20.debug("Plugin initializing", {
|
|
17377
17352
|
directory,
|
|
@@ -17672,6 +17647,7 @@ var init_plugin = __esm(() => {
|
|
|
17672
17647
|
suppressConverterToolEvents: SUPPRESS_CONVERTER_TOOL_EVENTS,
|
|
17673
17648
|
shouldEmitToolUpdates: SHOULD_EMIT_TOOL_UPDATES
|
|
17674
17649
|
} = PROVIDER_BOUNDARY.computeToolLoopFlags(TOOL_LOOP_MODE, FORWARD_TOOL_CALLS, EMIT_TOOL_UPDATES));
|
|
17650
|
+
NATIVE_TOOL_HOOK_EXCLUSIONS = new Set(["grep"]);
|
|
17675
17651
|
plugin_default = CursorPlugin;
|
|
17676
17652
|
});
|
|
17677
17653
|
|
|
@@ -17724,7 +17700,7 @@ class SimpleCursorClient {
|
|
|
17724
17700
|
args.push("--resume", resumeId);
|
|
17725
17701
|
}
|
|
17726
17702
|
this.log.debug("Executing prompt stream", { promptLength: prompt.length, mode, model });
|
|
17727
|
-
const child = spawn3(this.config.cursorAgentPath, args, {
|
|
17703
|
+
const child = spawn3(formatShellCommandForPlatform(this.config.cursorAgentPath), args, {
|
|
17728
17704
|
cwd,
|
|
17729
17705
|
stdio: ["pipe", "pipe", "pipe"],
|
|
17730
17706
|
shell: process.platform === "win32"
|
|
@@ -17811,7 +17787,7 @@ class SimpleCursorClient {
|
|
|
17811
17787
|
}
|
|
17812
17788
|
this.log.debug("Executing prompt", { promptLength: prompt.length, mode, model });
|
|
17813
17789
|
return new Promise((resolve3, reject) => {
|
|
17814
|
-
const child = spawn3(this.config.cursorAgentPath, args, {
|
|
17790
|
+
const child = spawn3(formatShellCommandForPlatform(this.config.cursorAgentPath), args, {
|
|
17815
17791
|
cwd,
|
|
17816
17792
|
stdio: ["pipe", "pipe", "pipe"],
|
|
17817
17793
|
shell: process.platform === "win32"
|
|
@@ -18060,42 +18036,22 @@ function createProxyServer(config) {
|
|
|
18060
18036
|
|
|
18061
18037
|
// src/streaming/ai-sdk-parts.ts
|
|
18062
18038
|
class StreamToAiSdkParts {
|
|
18063
|
-
tracker = new DeltaTracker;
|
|
18064
18039
|
toolArgsById = new Map;
|
|
18065
18040
|
startedToolIds = new Set;
|
|
18066
|
-
|
|
18067
|
-
sawThinkingPartials = false;
|
|
18041
|
+
tracker = new MixedDeltaTracker;
|
|
18068
18042
|
handleEvent(event) {
|
|
18069
18043
|
if (isAssistantText(event)) {
|
|
18070
|
-
const
|
|
18071
|
-
if (
|
|
18072
|
-
const text = extractText(event);
|
|
18073
|
-
if (text) {
|
|
18074
|
-
this.sawAssistantPartials = true;
|
|
18075
|
-
return [{ type: "text-delta", textDelta: text }];
|
|
18076
|
-
}
|
|
18077
|
-
return [];
|
|
18078
|
-
}
|
|
18079
|
-
if (this.sawAssistantPartials) {
|
|
18044
|
+
const text = extractText(event);
|
|
18045
|
+
if (!text)
|
|
18080
18046
|
return [];
|
|
18081
|
-
|
|
18082
|
-
const delta = this.tracker.nextText(extractText(event));
|
|
18047
|
+
const delta = this.tracker.nextText(text);
|
|
18083
18048
|
return delta ? [{ type: "text-delta", textDelta: delta }] : [];
|
|
18084
18049
|
}
|
|
18085
18050
|
if (isThinking(event)) {
|
|
18086
|
-
const
|
|
18087
|
-
if (
|
|
18088
|
-
const text = extractThinking(event);
|
|
18089
|
-
if (text) {
|
|
18090
|
-
this.sawThinkingPartials = true;
|
|
18091
|
-
return [{ type: "text-delta", textDelta: text }];
|
|
18092
|
-
}
|
|
18093
|
-
return [];
|
|
18094
|
-
}
|
|
18095
|
-
if (this.sawThinkingPartials) {
|
|
18051
|
+
const text = extractThinking(event);
|
|
18052
|
+
if (!text)
|
|
18096
18053
|
return [];
|
|
18097
|
-
|
|
18098
|
-
const delta = this.tracker.nextThinking(extractThinking(event));
|
|
18054
|
+
const delta = this.tracker.nextThinking(text);
|
|
18099
18055
|
return delta ? [{ type: "text-delta", textDelta: delta }] : [];
|
|
18100
18056
|
}
|
|
18101
18057
|
if (isToolCall(event)) {
|