@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/plugin-entry.js
CHANGED
|
@@ -520,6 +520,15 @@ function resolveCursorAgentBinary(deps = {}) {
|
|
|
520
520
|
log.warn("cursor-agent not found at known paths, falling back to PATH", { checkedPaths: knownPaths });
|
|
521
521
|
return "cursor-agent";
|
|
522
522
|
}
|
|
523
|
+
function formatShellCommandForPlatform(command, platform = process.platform) {
|
|
524
|
+
if (platform !== "win32") {
|
|
525
|
+
return command;
|
|
526
|
+
}
|
|
527
|
+
if (command.startsWith('"') && command.endsWith('"')) {
|
|
528
|
+
return command;
|
|
529
|
+
}
|
|
530
|
+
return `"${command}"`;
|
|
531
|
+
}
|
|
523
532
|
var log;
|
|
524
533
|
var init_binary = __esm(() => {
|
|
525
534
|
init_logger();
|
|
@@ -569,7 +578,7 @@ async function pollForAuthFile(timeoutMs = AUTH_POLL_TIMEOUT, intervalMs = AUTH_
|
|
|
569
578
|
async function startCursorOAuth() {
|
|
570
579
|
return new Promise((resolve2, reject) => {
|
|
571
580
|
log2.info("Starting cursor-cli login process");
|
|
572
|
-
const proc = spawn(resolveCursorAgentBinary(), ["login"], {
|
|
581
|
+
const proc = spawn(formatShellCommandForPlatform(resolveCursorAgentBinary()), ["login"], {
|
|
573
582
|
stdio: ["pipe", "pipe", "pipe"],
|
|
574
583
|
shell: process.platform === "win32"
|
|
575
584
|
});
|
|
@@ -763,29 +772,6 @@ class LineBuffer {
|
|
|
763
772
|
}
|
|
764
773
|
}
|
|
765
774
|
|
|
766
|
-
// src/streaming/types.ts
|
|
767
|
-
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) => {
|
|
768
|
-
if (event.type === "thinking") {
|
|
769
|
-
return true;
|
|
770
|
-
}
|
|
771
|
-
return event.type === "assistant" && hasThinkingContent(event);
|
|
772
|
-
}, 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) => {
|
|
773
|
-
if (event.type === "thinking") {
|
|
774
|
-
return event.text ?? "";
|
|
775
|
-
}
|
|
776
|
-
return event.message.content.filter((content) => content.type === "thinking").map((content) => content.thinking).join("");
|
|
777
|
-
}, inferToolName = (event) => {
|
|
778
|
-
const [key] = Object.keys(event.tool_call ?? {});
|
|
779
|
-
if (!key) {
|
|
780
|
-
return "";
|
|
781
|
-
}
|
|
782
|
-
if (key.endsWith("ToolCall")) {
|
|
783
|
-
const base = key.slice(0, -"ToolCall".length);
|
|
784
|
-
return base.charAt(0).toLowerCase() + base.slice(1);
|
|
785
|
-
}
|
|
786
|
-
return key;
|
|
787
|
-
};
|
|
788
|
-
|
|
789
775
|
// src/streaming/delta-tracker.ts
|
|
790
776
|
class DeltaTracker {
|
|
791
777
|
lastText = "";
|
|
@@ -823,14 +809,70 @@ class DeltaTracker {
|
|
|
823
809
|
}
|
|
824
810
|
}
|
|
825
811
|
|
|
812
|
+
class MixedDeltaTracker {
|
|
813
|
+
emittedText = "";
|
|
814
|
+
emittedThinking = "";
|
|
815
|
+
nextText(value) {
|
|
816
|
+
const delta = this.diff(this.emittedText, value);
|
|
817
|
+
if (delta) {
|
|
818
|
+
this.emittedText += delta;
|
|
819
|
+
}
|
|
820
|
+
return delta;
|
|
821
|
+
}
|
|
822
|
+
nextThinking(value) {
|
|
823
|
+
const delta = this.diff(this.emittedThinking, value);
|
|
824
|
+
if (delta) {
|
|
825
|
+
this.emittedThinking += delta;
|
|
826
|
+
}
|
|
827
|
+
return delta;
|
|
828
|
+
}
|
|
829
|
+
reset() {
|
|
830
|
+
this.emittedText = "";
|
|
831
|
+
this.emittedThinking = "";
|
|
832
|
+
}
|
|
833
|
+
diff(emitted, current) {
|
|
834
|
+
if (!emitted) {
|
|
835
|
+
return current;
|
|
836
|
+
}
|
|
837
|
+
if (current.startsWith(emitted)) {
|
|
838
|
+
return current.slice(emitted.length);
|
|
839
|
+
}
|
|
840
|
+
if (emitted.startsWith(current)) {
|
|
841
|
+
return "";
|
|
842
|
+
}
|
|
843
|
+
return current;
|
|
844
|
+
}
|
|
845
|
+
}
|
|
846
|
+
|
|
847
|
+
// src/streaming/types.ts
|
|
848
|
+
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) => {
|
|
849
|
+
if (event.type === "thinking") {
|
|
850
|
+
return true;
|
|
851
|
+
}
|
|
852
|
+
return event.type === "assistant" && hasThinkingContent(event);
|
|
853
|
+
}, 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) => {
|
|
854
|
+
if (event.type === "thinking") {
|
|
855
|
+
return event.text ?? "";
|
|
856
|
+
}
|
|
857
|
+
return event.message.content.filter((content) => content.type === "thinking").map((content) => content.thinking).join("");
|
|
858
|
+
}, inferToolName = (event) => {
|
|
859
|
+
const [key] = Object.keys(event.tool_call ?? {});
|
|
860
|
+
if (!key) {
|
|
861
|
+
return "";
|
|
862
|
+
}
|
|
863
|
+
if (key.endsWith("ToolCall")) {
|
|
864
|
+
const base = key.slice(0, -"ToolCall".length);
|
|
865
|
+
return base.charAt(0).toLowerCase() + base.slice(1);
|
|
866
|
+
}
|
|
867
|
+
return key;
|
|
868
|
+
};
|
|
869
|
+
|
|
826
870
|
// src/streaming/openai-sse.ts
|
|
827
871
|
class StreamToSseConverter {
|
|
828
872
|
id;
|
|
829
873
|
created;
|
|
830
874
|
model;
|
|
831
|
-
tracker = new
|
|
832
|
-
sawAssistantPartials = false;
|
|
833
|
-
sawThinkingPartials = false;
|
|
875
|
+
tracker = new MixedDeltaTracker;
|
|
834
876
|
constructor(model, options) {
|
|
835
877
|
this.model = model;
|
|
836
878
|
this.id = options?.id ?? `cursor-acp-${Date.now()}`;
|
|
@@ -838,35 +880,17 @@ class StreamToSseConverter {
|
|
|
838
880
|
}
|
|
839
881
|
handleEvent(event) {
|
|
840
882
|
if (isAssistantText(event)) {
|
|
841
|
-
const
|
|
842
|
-
if (
|
|
843
|
-
const text = extractText(event);
|
|
844
|
-
if (text) {
|
|
845
|
-
this.sawAssistantPartials = true;
|
|
846
|
-
return [this.chunkWith({ content: text })];
|
|
847
|
-
}
|
|
848
|
-
return [];
|
|
849
|
-
}
|
|
850
|
-
if (this.sawAssistantPartials) {
|
|
883
|
+
const text = extractText(event);
|
|
884
|
+
if (!text)
|
|
851
885
|
return [];
|
|
852
|
-
|
|
853
|
-
const delta = this.tracker.nextText(extractText(event));
|
|
886
|
+
const delta = this.tracker.nextText(text);
|
|
854
887
|
return delta ? [this.chunkWith({ content: delta })] : [];
|
|
855
888
|
}
|
|
856
889
|
if (isThinking(event)) {
|
|
857
|
-
const
|
|
858
|
-
if (
|
|
859
|
-
const text = extractThinking(event);
|
|
860
|
-
if (text) {
|
|
861
|
-
this.sawThinkingPartials = true;
|
|
862
|
-
return [this.chunkWith({ reasoning_content: text })];
|
|
863
|
-
}
|
|
864
|
-
return [];
|
|
865
|
-
}
|
|
866
|
-
if (this.sawThinkingPartials) {
|
|
890
|
+
const text = extractThinking(event);
|
|
891
|
+
if (!text)
|
|
867
892
|
return [];
|
|
868
|
-
|
|
869
|
-
const delta = this.tracker.nextThinking(extractThinking(event));
|
|
893
|
+
const delta = this.tracker.nextThinking(text);
|
|
870
894
|
return delta ? [this.chunkWith({ reasoning_content: delta })] : [];
|
|
871
895
|
}
|
|
872
896
|
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
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rama_nigg/open-cursor",
|
|
3
|
-
"version": "2.4.
|
|
3
|
+
"version": "2.4.5",
|
|
4
4
|
"description": "No prompt limits. No broken streams. Full thinking + tool support. Your Cursor subscription, properly integrated.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/plugin-entry.js",
|
package/src/auth.ts
CHANGED
|
@@ -6,7 +6,7 @@ import { homedir, platform } from "os";
|
|
|
6
6
|
import { join } from "path";
|
|
7
7
|
import { createLogger } from "./utils/logger";
|
|
8
8
|
import { stripAnsi } from "./utils/errors";
|
|
9
|
-
import { resolveCursorAgentBinary } from "./utils/binary.js";
|
|
9
|
+
import { formatShellCommandForPlatform, resolveCursorAgentBinary } from "./utils/binary.js";
|
|
10
10
|
|
|
11
11
|
const log = createLogger("auth");
|
|
12
12
|
|
|
@@ -76,7 +76,7 @@ export async function startCursorOAuth(): Promise<{
|
|
|
76
76
|
return new Promise((resolve, reject) => {
|
|
77
77
|
log.info("Starting cursor-cli login process");
|
|
78
78
|
|
|
79
|
-
const proc = spawn(resolveCursorAgentBinary(), ["login"], {
|
|
79
|
+
const proc = spawn(formatShellCommandForPlatform(resolveCursorAgentBinary()), ["login"], {
|
|
80
80
|
stdio: ["pipe", "pipe", "pipe"],
|
|
81
81
|
shell: process.platform === "win32",
|
|
82
82
|
});
|
package/src/client/simple.ts
CHANGED
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
type StreamJsonEvent,
|
|
8
8
|
} from '../streaming/types.js';
|
|
9
9
|
import { createLogger } from '../utils/logger.js';
|
|
10
|
-
import { resolveCursorAgentBinary } from '../utils/binary.js';
|
|
10
|
+
import { formatShellCommandForPlatform, resolveCursorAgentBinary } from '../utils/binary.js';
|
|
11
11
|
|
|
12
12
|
export interface CursorClientConfig {
|
|
13
13
|
timeout?: number;
|
|
@@ -77,7 +77,7 @@ export class SimpleCursorClient {
|
|
|
77
77
|
|
|
78
78
|
this.log.debug('Executing prompt stream', { promptLength: prompt.length, mode, model });
|
|
79
79
|
|
|
80
|
-
const child = spawn(this.config.cursorAgentPath, args, {
|
|
80
|
+
const child = spawn(formatShellCommandForPlatform(this.config.cursorAgentPath), args, {
|
|
81
81
|
cwd,
|
|
82
82
|
stdio: ['pipe', 'pipe', 'pipe'],
|
|
83
83
|
shell: process.platform === 'win32',
|
|
@@ -189,7 +189,7 @@ export class SimpleCursorClient {
|
|
|
189
189
|
this.log.debug('Executing prompt', { promptLength: prompt.length, mode, model });
|
|
190
190
|
|
|
191
191
|
return new Promise((resolve, reject) => {
|
|
192
|
-
const child = spawn(this.config.cursorAgentPath, args, {
|
|
192
|
+
const child = spawn(formatShellCommandForPlatform(this.config.cursorAgentPath), args, {
|
|
193
193
|
cwd,
|
|
194
194
|
stdio: ['pipe', 'pipe', 'pipe'],
|
|
195
195
|
shell: process.platform === 'win32',
|