@rama_nigg/open-cursor 2.4.4 → 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 +171 -218
- package/dist/plugin-entry.js +162 -189
- package/package.json +1 -1
- package/src/auth.ts +2 -2
- package/src/client/simple.ts +3 -3
- package/src/plugin.ts +90 -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/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)) {
|
|
@@ -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
|
-
}
|
|
17080
|
+
await processLines(lineBuffer.push(chunk));
|
|
17114
17081
|
}
|
|
17115
|
-
if (streamTerminated
|
|
17116
|
-
|
|
17117
|
-
|
|
17118
|
-
|
|
17119
|
-
|
|
17120
|
-
|
|
17121
|
-
|
|
17122
|
-
|
|
17123
|
-
|
|
17124
|
-
|
|
17125
|
-
|
|
17126
|
-
|
|
17127
|
-
|
|
17128
|
-
|
|
17129
|
-
|
|
17130
|
-
|
|
17131
|
-
|
|
17132
|
-
|
|
17133
|
-
const errSource = stderrText || `cursor-agent exited with code ${String(code ?? "unknown")} and no output`;
|
|
17134
|
-
const parsed = parseAgentError(errSource);
|
|
17135
|
-
const msg = formatErrorForUser(parsed);
|
|
17136
|
-
const errChunk = createChatCompletionChunk(id, created, model, msg, true);
|
|
17137
|
-
res.write(`data: ${JSON.stringify(errChunk)}
|
|
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) {
|
|
@@ -17727,7 +17700,7 @@ class SimpleCursorClient {
|
|
|
17727
17700
|
args.push("--resume", resumeId);
|
|
17728
17701
|
}
|
|
17729
17702
|
this.log.debug("Executing prompt stream", { promptLength: prompt.length, mode, model });
|
|
17730
|
-
const child = spawn3(this.config.cursorAgentPath, args, {
|
|
17703
|
+
const child = spawn3(formatShellCommandForPlatform(this.config.cursorAgentPath), args, {
|
|
17731
17704
|
cwd,
|
|
17732
17705
|
stdio: ["pipe", "pipe", "pipe"],
|
|
17733
17706
|
shell: process.platform === "win32"
|
|
@@ -17814,7 +17787,7 @@ class SimpleCursorClient {
|
|
|
17814
17787
|
}
|
|
17815
17788
|
this.log.debug("Executing prompt", { promptLength: prompt.length, mode, model });
|
|
17816
17789
|
return new Promise((resolve3, reject) => {
|
|
17817
|
-
const child = spawn3(this.config.cursorAgentPath, args, {
|
|
17790
|
+
const child = spawn3(formatShellCommandForPlatform(this.config.cursorAgentPath), args, {
|
|
17818
17791
|
cwd,
|
|
17819
17792
|
stdio: ["pipe", "pipe", "pipe"],
|
|
17820
17793
|
shell: process.platform === "win32"
|
|
@@ -18063,42 +18036,22 @@ function createProxyServer(config) {
|
|
|
18063
18036
|
|
|
18064
18037
|
// src/streaming/ai-sdk-parts.ts
|
|
18065
18038
|
class StreamToAiSdkParts {
|
|
18066
|
-
tracker = new DeltaTracker;
|
|
18067
18039
|
toolArgsById = new Map;
|
|
18068
18040
|
startedToolIds = new Set;
|
|
18069
|
-
|
|
18070
|
-
sawThinkingPartials = false;
|
|
18041
|
+
tracker = new MixedDeltaTracker;
|
|
18071
18042
|
handleEvent(event) {
|
|
18072
18043
|
if (isAssistantText(event)) {
|
|
18073
|
-
const
|
|
18074
|
-
if (
|
|
18075
|
-
const text = extractText(event);
|
|
18076
|
-
if (text) {
|
|
18077
|
-
this.sawAssistantPartials = true;
|
|
18078
|
-
return [{ type: "text-delta", textDelta: text }];
|
|
18079
|
-
}
|
|
18080
|
-
return [];
|
|
18081
|
-
}
|
|
18082
|
-
if (this.sawAssistantPartials) {
|
|
18044
|
+
const text = extractText(event);
|
|
18045
|
+
if (!text)
|
|
18083
18046
|
return [];
|
|
18084
|
-
|
|
18085
|
-
const delta = this.tracker.nextText(extractText(event));
|
|
18047
|
+
const delta = this.tracker.nextText(text);
|
|
18086
18048
|
return delta ? [{ type: "text-delta", textDelta: delta }] : [];
|
|
18087
18049
|
}
|
|
18088
18050
|
if (isThinking(event)) {
|
|
18089
|
-
const
|
|
18090
|
-
if (
|
|
18091
|
-
const text = extractThinking(event);
|
|
18092
|
-
if (text) {
|
|
18093
|
-
this.sawThinkingPartials = true;
|
|
18094
|
-
return [{ type: "text-delta", textDelta: text }];
|
|
18095
|
-
}
|
|
18096
|
-
return [];
|
|
18097
|
-
}
|
|
18098
|
-
if (this.sawThinkingPartials) {
|
|
18051
|
+
const text = extractThinking(event);
|
|
18052
|
+
if (!text)
|
|
18099
18053
|
return [];
|
|
18100
|
-
|
|
18101
|
-
const delta = this.tracker.nextThinking(extractThinking(event));
|
|
18054
|
+
const delta = this.tracker.nextThinking(text);
|
|
18102
18055
|
return delta ? [{ type: "text-delta", textDelta: delta }] : [];
|
|
18103
18056
|
}
|
|
18104
18057
|
if (isToolCall(event)) {
|