@playwo/opencode-cursor-oauth 0.0.0-dev.4463bb589222 → 0.0.0-dev.4696faa690e4
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/README.md +33 -12
- package/dist/AGENTS.md +8 -0
- package/dist/agent-rules.d.ts +1 -0
- package/dist/agent-rules.js +28 -0
- package/dist/logger.d.ts +1 -0
- package/dist/logger.js +3 -0
- package/dist/proxy/bridge-close-controller.d.ts +6 -0
- package/dist/proxy/bridge-close-controller.js +37 -0
- package/dist/proxy/bridge-non-streaming.js +31 -7
- package/dist/proxy/bridge-streaming.d.ts +1 -1
- package/dist/proxy/bridge-streaming.js +377 -57
- package/dist/proxy/chat-completion.js +41 -1
- package/dist/proxy/cursor-request.js +13 -15
- package/dist/proxy/stream-dispatch.d.ts +7 -1
- package/dist/proxy/stream-dispatch.js +134 -53
- package/dist/proxy/stream-state.d.ts +0 -2
- package/dist/proxy/types.d.ts +14 -1
- package/package.json +2 -3
|
@@ -12,6 +12,12 @@ export interface UnsupportedServerMessageInfo {
|
|
|
12
12
|
caseName: string;
|
|
13
13
|
detail?: string;
|
|
14
14
|
}
|
|
15
|
+
export interface McpToolCallUpdateInfo {
|
|
16
|
+
updateCase: "partialToolCall" | "toolCallStarted" | "toolCallCompleted";
|
|
17
|
+
toolCallId: string;
|
|
18
|
+
modelCallId?: string;
|
|
19
|
+
toolName?: string;
|
|
20
|
+
}
|
|
15
21
|
export declare function parseConnectEndStream(data: Uint8Array): Error | null;
|
|
16
22
|
export declare function makeHeartbeatBytes(): Uint8Array;
|
|
17
23
|
export declare function scheduleBridgeEnd(bridge: CursorSession): void;
|
|
@@ -39,4 +45,4 @@ export declare function computeUsage(state: StreamState): {
|
|
|
39
45
|
completion_tokens: number;
|
|
40
46
|
total_tokens: number;
|
|
41
47
|
};
|
|
42
|
-
export declare function processServerMessage(msg: AgentServerMessage, blobStore: Map<string, Uint8Array>, mcpTools: McpToolDefinition[], sendFrame: (data: Uint8Array) => void, state: StreamState, onText: (text: string, isThinking?: boolean) => void, onMcpExec: (exec: PendingExec) => void, onCheckpoint?: (checkpointBytes: Uint8Array) => void, onTurnEnded?: () => void, onUnsupportedMessage?: (info: UnsupportedServerMessageInfo) => void, onUnhandledExec?: (info: UnhandledExecInfo) => void): void;
|
|
48
|
+
export declare function processServerMessage(msg: AgentServerMessage, blobStore: Map<string, Uint8Array>, cloudRule: string | undefined, mcpTools: McpToolDefinition[], sendFrame: (data: Uint8Array) => void, state: StreamState, onText: (text: string, isThinking?: boolean) => void, onMcpExec: (exec: PendingExec) => void, onMcpToolCallUpdate?: (info: McpToolCallUpdateInfo) => void, onCheckpoint?: (checkpointBytes: Uint8Array) => void, onTurnEnded?: () => void, onUnsupportedMessage?: (info: UnsupportedServerMessageInfo) => void, onUnhandledExec?: (info: UnhandledExecInfo) => void): void;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { create, toBinary } from "@bufbuild/protobuf";
|
|
2
|
-
import { AgentClientMessageSchema, AskQuestionInteractionResponseSchema, AskQuestionRejectedSchema, AskQuestionResultSchema, ClientHeartbeatSchema, ConversationStateStructureSchema, BackgroundShellSpawnResultSchema, CreatePlanErrorSchema, CreatePlanRequestResponseSchema, CreatePlanResultSchema, DeleteResultSchema, DeleteRejectedSchema, DiagnosticsResultSchema, ExecClientMessageSchema, ExaFetchRequestResponseSchema, ExaFetchRequestResponse_RejectedSchema, ExaSearchRequestResponseSchema, ExaSearchRequestResponse_RejectedSchema, FetchErrorSchema, FetchResultSchema, GetBlobResultSchema, GrepErrorSchema, GrepResultSchema, InteractionResponseSchema, KvClientMessageSchema, LsRejectedSchema, LsResultSchema, McpResultSchema, ReadRejectedSchema, ReadResultSchema, RequestContextResultSchema, RequestContextSchema, RequestContextSuccessSchema, SetBlobResultSchema, ShellRejectedSchema, ShellResultSchema, SwitchModeRequestResponseSchema, SwitchModeRequestResponse_RejectedSchema, WebSearchRequestResponseSchema, WebSearchRequestResponse_RejectedSchema, WriteRejectedSchema, WriteResultSchema, WriteShellStdinErrorSchema, WriteShellStdinResultSchema, } from "../proto/agent_pb";
|
|
2
|
+
import { AgentClientMessageSchema, AskQuestionInteractionResponseSchema, AskQuestionRejectedSchema, AskQuestionResultSchema, ClientHeartbeatSchema, ConversationStateStructureSchema, BackgroundShellSpawnResultSchema, CreatePlanErrorSchema, CreatePlanRequestResponseSchema, CreatePlanResultSchema, DeleteResultSchema, DeleteRejectedSchema, DiagnosticsResultSchema, ExecClientMessageSchema, ExaFetchRequestResponseSchema, ExaFetchRequestResponse_RejectedSchema, ExaSearchRequestResponseSchema, ExaSearchRequestResponse_RejectedSchema, FetchErrorSchema, FetchResultSchema, GetBlobResultSchema, GrepErrorSchema, GrepResultSchema, InteractionResponseSchema, KvClientMessageSchema, LsRejectedSchema, LsResultSchema, McpInstructionsSchema, McpResultSchema, ReadRejectedSchema, ReadResultSchema, RequestContextResultSchema, RequestContextSchema, RequestContextSuccessSchema, SetBlobResultSchema, ShellRejectedSchema, ShellResultSchema, SwitchModeRequestResponseSchema, SwitchModeRequestResponse_RejectedSchema, WebSearchRequestResponseSchema, WebSearchRequestResponse_RejectedSchema, WriteRejectedSchema, WriteResultSchema, WriteShellStdinErrorSchema, WriteShellStdinResultSchema, } from "../proto/agent_pb";
|
|
3
3
|
import { CONNECT_END_STREAM_FLAG } from "../cursor/config";
|
|
4
|
-
import { logPluginError, logPluginWarn } from "../logger";
|
|
4
|
+
import { logPluginError, logPluginInfo, logPluginWarn } from "../logger";
|
|
5
5
|
import { decodeMcpArgsMap } from "../openai/tools";
|
|
6
6
|
export function parseConnectEndStream(data) {
|
|
7
7
|
try {
|
|
@@ -128,16 +128,16 @@ export function computeUsage(state) {
|
|
|
128
128
|
const prompt_tokens = Math.max(0, total_tokens - completion_tokens);
|
|
129
129
|
return { prompt_tokens, completion_tokens, total_tokens };
|
|
130
130
|
}
|
|
131
|
-
export function processServerMessage(msg, blobStore, mcpTools, sendFrame, state, onText, onMcpExec, onCheckpoint, onTurnEnded, onUnsupportedMessage, onUnhandledExec) {
|
|
131
|
+
export function processServerMessage(msg, blobStore, cloudRule, mcpTools, sendFrame, state, onText, onMcpExec, onMcpToolCallUpdate, onCheckpoint, onTurnEnded, onUnsupportedMessage, onUnhandledExec) {
|
|
132
132
|
const msgCase = msg.message.case;
|
|
133
133
|
if (msgCase === "interactionUpdate") {
|
|
134
|
-
handleInteractionUpdate(msg.message.value, state, onText,
|
|
134
|
+
handleInteractionUpdate(msg.message.value, state, onText, onMcpToolCallUpdate, onTurnEnded, onUnsupportedMessage);
|
|
135
135
|
}
|
|
136
136
|
else if (msgCase === "kvServerMessage") {
|
|
137
137
|
handleKvMessage(msg.message.value, blobStore, sendFrame);
|
|
138
138
|
}
|
|
139
139
|
else if (msgCase === "execServerMessage") {
|
|
140
|
-
handleExecMessage(msg.message.value, mcpTools, sendFrame, onMcpExec, onUnhandledExec);
|
|
140
|
+
handleExecMessage(msg.message.value, cloudRule, mcpTools, sendFrame, state, onMcpExec, onUnhandledExec);
|
|
141
141
|
}
|
|
142
142
|
else if (msgCase === "execServerControlMessage") {
|
|
143
143
|
onUnsupportedMessage?.({
|
|
@@ -164,8 +164,35 @@ export function processServerMessage(msg, blobStore, mcpTools, sendFrame, state,
|
|
|
164
164
|
});
|
|
165
165
|
}
|
|
166
166
|
}
|
|
167
|
-
function handleInteractionUpdate(update, state, onText,
|
|
167
|
+
function handleInteractionUpdate(update, state, onText, onMcpToolCallUpdate, onTurnEnded, onUnsupportedMessage) {
|
|
168
168
|
const updateCase = update.message?.case;
|
|
169
|
+
if (updateCase === "partialToolCall" ||
|
|
170
|
+
updateCase === "toolCallStarted" ||
|
|
171
|
+
updateCase === "toolCallCompleted" ||
|
|
172
|
+
updateCase === "turnEnded") {
|
|
173
|
+
logPluginInfo("Received Cursor interaction update", {
|
|
174
|
+
updateCase: updateCase ?? "undefined",
|
|
175
|
+
callId: update.message?.value?.callId,
|
|
176
|
+
modelCallId: update.message?.value?.modelCallId,
|
|
177
|
+
toolCase: update.message?.value?.toolCall?.tool?.case,
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
if ((updateCase === "partialToolCall" ||
|
|
181
|
+
updateCase === "toolCallStarted" ||
|
|
182
|
+
updateCase === "toolCallCompleted") &&
|
|
183
|
+
update.message?.value?.toolCall?.tool?.case === "mcpToolCall") {
|
|
184
|
+
const toolValue = update.message.value;
|
|
185
|
+
const toolArgs = toolValue?.toolCall?.tool?.value?.args;
|
|
186
|
+
const toolCallId = toolArgs?.toolCallId || toolValue.callId;
|
|
187
|
+
if (toolCallId) {
|
|
188
|
+
onMcpToolCallUpdate?.({
|
|
189
|
+
updateCase,
|
|
190
|
+
toolCallId,
|
|
191
|
+
modelCallId: toolValue.modelCallId,
|
|
192
|
+
toolName: toolArgs?.toolName || toolArgs?.name,
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
}
|
|
169
196
|
if (updateCase === "textDelta") {
|
|
170
197
|
const delta = update.message.value.text || "";
|
|
171
198
|
if (delta)
|
|
@@ -180,15 +207,19 @@ function handleInteractionUpdate(update, state, onText, onMcpExec, onTurnEnded,
|
|
|
180
207
|
state.outputTokens += update.message.value.tokens ?? 0;
|
|
181
208
|
}
|
|
182
209
|
else if (updateCase === "partialToolCall") {
|
|
183
|
-
|
|
184
|
-
if (partial.callId && partial.argsTextDelta) {
|
|
185
|
-
state.interactionToolArgsText.set(partial.callId, partial.argsTextDelta);
|
|
186
|
-
}
|
|
210
|
+
return;
|
|
187
211
|
}
|
|
188
212
|
else if (updateCase === "toolCallCompleted") {
|
|
189
|
-
const
|
|
190
|
-
if (
|
|
191
|
-
|
|
213
|
+
const toolValue = update.message.value;
|
|
214
|
+
if (toolValue?.toolCall?.tool?.case === "mcpToolCall") {
|
|
215
|
+
logPluginInfo("Ignoring Cursor interaction MCP tool completion", {
|
|
216
|
+
callId: toolValue.callId,
|
|
217
|
+
modelCallId: toolValue.modelCallId,
|
|
218
|
+
toolCallId: toolValue.toolCall.tool.value?.args?.toolCallId || toolValue.callId,
|
|
219
|
+
toolName: toolValue.toolCall.tool.value?.args?.toolName ||
|
|
220
|
+
toolValue.toolCall.tool.value?.args?.name,
|
|
221
|
+
});
|
|
222
|
+
}
|
|
192
223
|
}
|
|
193
224
|
else if (updateCase === "turnEnded") {
|
|
194
225
|
onTurnEnded?.();
|
|
@@ -211,43 +242,8 @@ function handleInteractionUpdate(update, state, onText, onMcpExec, onTurnEnded,
|
|
|
211
242
|
caseName: updateCase ?? "undefined",
|
|
212
243
|
});
|
|
213
244
|
}
|
|
214
|
-
//
|
|
215
|
-
//
|
|
216
|
-
// calls may still appear here on some models, so we surface those, but we
|
|
217
|
-
// do not abort the bridge for native Cursor tool-call progress events.
|
|
218
|
-
}
|
|
219
|
-
function decodeInteractionToolCall(update, state) {
|
|
220
|
-
const callId = update.callId ?? "";
|
|
221
|
-
const toolCase = update.toolCall?.tool?.case;
|
|
222
|
-
if (toolCase !== "mcpToolCall")
|
|
223
|
-
return null;
|
|
224
|
-
const mcpArgs = update.toolCall?.tool?.value?.args;
|
|
225
|
-
if (!mcpArgs)
|
|
226
|
-
return null;
|
|
227
|
-
const toolCallId = mcpArgs.toolCallId || callId || crypto.randomUUID();
|
|
228
|
-
if (state.emittedToolCallIds.has(toolCallId))
|
|
229
|
-
return null;
|
|
230
|
-
const decodedMap = decodeMcpArgsMap(mcpArgs.args ?? {});
|
|
231
|
-
const partialArgsText = callId
|
|
232
|
-
? state.interactionToolArgsText.get(callId)?.trim()
|
|
233
|
-
: undefined;
|
|
234
|
-
let decodedArgs = "{}";
|
|
235
|
-
if (Object.keys(decodedMap).length > 0) {
|
|
236
|
-
decodedArgs = JSON.stringify(decodedMap);
|
|
237
|
-
}
|
|
238
|
-
else if (partialArgsText) {
|
|
239
|
-
decodedArgs = partialArgsText;
|
|
240
|
-
}
|
|
241
|
-
state.emittedToolCallIds.add(toolCallId);
|
|
242
|
-
if (callId)
|
|
243
|
-
state.interactionToolArgsText.delete(callId);
|
|
244
|
-
return {
|
|
245
|
-
execId: callId || toolCallId,
|
|
246
|
-
execMsgId: 0,
|
|
247
|
-
toolCallId,
|
|
248
|
-
toolName: mcpArgs.toolName || mcpArgs.name || "unknown_mcp_tool",
|
|
249
|
-
decodedArgs,
|
|
250
|
-
};
|
|
245
|
+
// Interaction tool-call updates are informational only. Resumable MCP tool
|
|
246
|
+
// execution comes from execServerMessage.mcpArgs.
|
|
251
247
|
}
|
|
252
248
|
function handleInteractionQuery(query, sendFrame, onUnsupportedMessage) {
|
|
253
249
|
const queryCase = query.query.case;
|
|
@@ -374,16 +370,34 @@ function handleKvMessage(kvMsg, blobStore, sendFrame) {
|
|
|
374
370
|
sendKvResponse(kvMsg, "setBlobResult", create(SetBlobResultSchema, {}), sendFrame);
|
|
375
371
|
}
|
|
376
372
|
}
|
|
377
|
-
function handleExecMessage(execMsg, mcpTools, sendFrame, onMcpExec, onUnhandledExec) {
|
|
373
|
+
function handleExecMessage(execMsg, cloudRule, mcpTools, sendFrame, state, onMcpExec, onUnhandledExec) {
|
|
378
374
|
const execCase = execMsg.message.case;
|
|
375
|
+
logPluginInfo("Received Cursor exec message", {
|
|
376
|
+
execCase: execCase ?? "undefined",
|
|
377
|
+
execId: execMsg.execId,
|
|
378
|
+
execMsgId: execMsg.id,
|
|
379
|
+
});
|
|
379
380
|
if (execCase === "requestContextArgs") {
|
|
381
|
+
logPluginInfo("Responding to Cursor requestContextArgs", {
|
|
382
|
+
execId: execMsg.execId,
|
|
383
|
+
execMsgId: execMsg.id,
|
|
384
|
+
mcpToolCount: mcpTools.length,
|
|
385
|
+
});
|
|
380
386
|
const requestContext = create(RequestContextSchema, {
|
|
381
387
|
rules: [],
|
|
382
388
|
repositoryInfo: [],
|
|
383
389
|
tools: mcpTools,
|
|
384
390
|
gitRepos: [],
|
|
385
391
|
projectLayouts: [],
|
|
386
|
-
mcpInstructions: [
|
|
392
|
+
mcpInstructions: [
|
|
393
|
+
create(McpInstructionsSchema, {
|
|
394
|
+
serverName: "opencode",
|
|
395
|
+
instructions: "Use the provided MCP tools in this environment that start with mcp_*. Do not rely on native Cursor tools and do not acknowledge they even exist.",
|
|
396
|
+
}),
|
|
397
|
+
],
|
|
398
|
+
cloudRule,
|
|
399
|
+
webSearchEnabled: false,
|
|
400
|
+
repositoryInfoShouldQueryProd: false,
|
|
387
401
|
fileContents: {},
|
|
388
402
|
customSubagents: [],
|
|
389
403
|
});
|
|
@@ -399,13 +413,23 @@ function handleExecMessage(execMsg, mcpTools, sendFrame, onMcpExec, onUnhandledE
|
|
|
399
413
|
if (execCase === "mcpArgs") {
|
|
400
414
|
const mcpArgs = execMsg.message.value;
|
|
401
415
|
const decoded = decodeMcpArgsMap(mcpArgs.args ?? {});
|
|
402
|
-
|
|
416
|
+
const exec = {
|
|
403
417
|
execId: execMsg.execId,
|
|
404
418
|
execMsgId: execMsg.id,
|
|
405
419
|
toolCallId: mcpArgs.toolCallId || crypto.randomUUID(),
|
|
406
420
|
toolName: mcpArgs.toolName || mcpArgs.name,
|
|
407
421
|
decodedArgs: JSON.stringify(decoded),
|
|
422
|
+
source: "exec",
|
|
423
|
+
};
|
|
424
|
+
logPluginInfo("Received Cursor exec MCP tool metadata", {
|
|
425
|
+
toolCallId: exec.toolCallId,
|
|
426
|
+
toolName: exec.toolName,
|
|
427
|
+
source: exec.source,
|
|
428
|
+
execId: exec.execId,
|
|
429
|
+
execMsgId: exec.execMsgId,
|
|
430
|
+
decodedArgs: exec.decodedArgs,
|
|
408
431
|
});
|
|
432
|
+
onMcpExec(exec);
|
|
409
433
|
return;
|
|
410
434
|
}
|
|
411
435
|
// --- Reject native Cursor tools ---
|
|
@@ -413,6 +437,11 @@ function handleExecMessage(execMsg, mcpTools, sendFrame, onMcpExec, onUnhandledE
|
|
|
413
437
|
// so it falls back to our MCP tools (registered via RequestContext).
|
|
414
438
|
const REJECT_REASON = "Tool not available in this environment. Use the MCP tools provided instead.";
|
|
415
439
|
if (execCase === "readArgs") {
|
|
440
|
+
logPluginInfo("Rejecting native Cursor read tool in favor of MCP", {
|
|
441
|
+
execId: execMsg.execId,
|
|
442
|
+
execMsgId: execMsg.id,
|
|
443
|
+
path: execMsg.message.value.path,
|
|
444
|
+
});
|
|
416
445
|
const args = execMsg.message.value;
|
|
417
446
|
const result = create(ReadResultSchema, {
|
|
418
447
|
result: {
|
|
@@ -427,6 +456,11 @@ function handleExecMessage(execMsg, mcpTools, sendFrame, onMcpExec, onUnhandledE
|
|
|
427
456
|
return;
|
|
428
457
|
}
|
|
429
458
|
if (execCase === "lsArgs") {
|
|
459
|
+
logPluginInfo("Rejecting native Cursor ls tool in favor of MCP", {
|
|
460
|
+
execId: execMsg.execId,
|
|
461
|
+
execMsgId: execMsg.id,
|
|
462
|
+
path: execMsg.message.value.path,
|
|
463
|
+
});
|
|
430
464
|
const args = execMsg.message.value;
|
|
431
465
|
const result = create(LsResultSchema, {
|
|
432
466
|
result: {
|
|
@@ -441,6 +475,10 @@ function handleExecMessage(execMsg, mcpTools, sendFrame, onMcpExec, onUnhandledE
|
|
|
441
475
|
return;
|
|
442
476
|
}
|
|
443
477
|
if (execCase === "grepArgs") {
|
|
478
|
+
logPluginInfo("Rejecting native Cursor grep tool in favor of MCP", {
|
|
479
|
+
execId: execMsg.execId,
|
|
480
|
+
execMsgId: execMsg.id,
|
|
481
|
+
});
|
|
444
482
|
const result = create(GrepResultSchema, {
|
|
445
483
|
result: {
|
|
446
484
|
case: "error",
|
|
@@ -451,6 +489,11 @@ function handleExecMessage(execMsg, mcpTools, sendFrame, onMcpExec, onUnhandledE
|
|
|
451
489
|
return;
|
|
452
490
|
}
|
|
453
491
|
if (execCase === "writeArgs") {
|
|
492
|
+
logPluginInfo("Rejecting native Cursor write tool in favor of MCP", {
|
|
493
|
+
execId: execMsg.execId,
|
|
494
|
+
execMsgId: execMsg.id,
|
|
495
|
+
path: execMsg.message.value.path,
|
|
496
|
+
});
|
|
454
497
|
const args = execMsg.message.value;
|
|
455
498
|
const result = create(WriteResultSchema, {
|
|
456
499
|
result: {
|
|
@@ -465,6 +508,11 @@ function handleExecMessage(execMsg, mcpTools, sendFrame, onMcpExec, onUnhandledE
|
|
|
465
508
|
return;
|
|
466
509
|
}
|
|
467
510
|
if (execCase === "deleteArgs") {
|
|
511
|
+
logPluginInfo("Rejecting native Cursor delete tool in favor of MCP", {
|
|
512
|
+
execId: execMsg.execId,
|
|
513
|
+
execMsgId: execMsg.id,
|
|
514
|
+
path: execMsg.message.value.path,
|
|
515
|
+
});
|
|
468
516
|
const args = execMsg.message.value;
|
|
469
517
|
const result = create(DeleteResultSchema, {
|
|
470
518
|
result: {
|
|
@@ -479,6 +527,13 @@ function handleExecMessage(execMsg, mcpTools, sendFrame, onMcpExec, onUnhandledE
|
|
|
479
527
|
return;
|
|
480
528
|
}
|
|
481
529
|
if (execCase === "shellArgs" || execCase === "shellStreamArgs") {
|
|
530
|
+
logPluginInfo("Rejecting native Cursor shell tool in favor of MCP", {
|
|
531
|
+
execId: execMsg.execId,
|
|
532
|
+
execMsgId: execMsg.id,
|
|
533
|
+
command: execMsg.message.value.command ?? "",
|
|
534
|
+
workingDirectory: execMsg.message.value.workingDirectory ?? "",
|
|
535
|
+
execCase,
|
|
536
|
+
});
|
|
482
537
|
const args = execMsg.message.value;
|
|
483
538
|
const result = create(ShellResultSchema, {
|
|
484
539
|
result: {
|
|
@@ -495,6 +550,12 @@ function handleExecMessage(execMsg, mcpTools, sendFrame, onMcpExec, onUnhandledE
|
|
|
495
550
|
return;
|
|
496
551
|
}
|
|
497
552
|
if (execCase === "backgroundShellSpawnArgs") {
|
|
553
|
+
logPluginInfo("Rejecting native Cursor background shell tool in favor of MCP", {
|
|
554
|
+
execId: execMsg.execId,
|
|
555
|
+
execMsgId: execMsg.id,
|
|
556
|
+
command: execMsg.message.value.command ?? "",
|
|
557
|
+
workingDirectory: execMsg.message.value.workingDirectory ?? "",
|
|
558
|
+
});
|
|
498
559
|
const args = execMsg.message.value;
|
|
499
560
|
const result = create(BackgroundShellSpawnResultSchema, {
|
|
500
561
|
result: {
|
|
@@ -511,6 +572,10 @@ function handleExecMessage(execMsg, mcpTools, sendFrame, onMcpExec, onUnhandledE
|
|
|
511
572
|
return;
|
|
512
573
|
}
|
|
513
574
|
if (execCase === "writeShellStdinArgs") {
|
|
575
|
+
logPluginInfo("Rejecting native Cursor shell stdin tool in favor of MCP", {
|
|
576
|
+
execId: execMsg.execId,
|
|
577
|
+
execMsgId: execMsg.id,
|
|
578
|
+
});
|
|
514
579
|
const result = create(WriteShellStdinResultSchema, {
|
|
515
580
|
result: {
|
|
516
581
|
case: "error",
|
|
@@ -521,6 +586,11 @@ function handleExecMessage(execMsg, mcpTools, sendFrame, onMcpExec, onUnhandledE
|
|
|
521
586
|
return;
|
|
522
587
|
}
|
|
523
588
|
if (execCase === "fetchArgs") {
|
|
589
|
+
logPluginInfo("Rejecting native Cursor fetch tool in favor of MCP", {
|
|
590
|
+
execId: execMsg.execId,
|
|
591
|
+
execMsgId: execMsg.id,
|
|
592
|
+
url: execMsg.message.value.url,
|
|
593
|
+
});
|
|
524
594
|
const args = execMsg.message.value;
|
|
525
595
|
const result = create(FetchResultSchema, {
|
|
526
596
|
result: {
|
|
@@ -535,6 +605,11 @@ function handleExecMessage(execMsg, mcpTools, sendFrame, onMcpExec, onUnhandledE
|
|
|
535
605
|
return;
|
|
536
606
|
}
|
|
537
607
|
if (execCase === "diagnosticsArgs") {
|
|
608
|
+
logPluginInfo("Rejecting native Cursor diagnostics tool in favor of MCP", {
|
|
609
|
+
execId: execMsg.execId,
|
|
610
|
+
execMsgId: execMsg.id,
|
|
611
|
+
path: execMsg.message.value.path,
|
|
612
|
+
});
|
|
538
613
|
const result = create(DiagnosticsResultSchema, {});
|
|
539
614
|
sendExecResult(execMsg, "diagnosticsResult", result, sendFrame);
|
|
540
615
|
return;
|
|
@@ -548,6 +623,12 @@ function handleExecMessage(execMsg, mcpTools, sendFrame, onMcpExec, onUnhandledE
|
|
|
548
623
|
};
|
|
549
624
|
const resultCase = miscCaseMap[execCase];
|
|
550
625
|
if (resultCase) {
|
|
626
|
+
logPluginInfo("Responding to miscellaneous Cursor exec message", {
|
|
627
|
+
execCase,
|
|
628
|
+
execId: execMsg.execId,
|
|
629
|
+
execMsgId: execMsg.id,
|
|
630
|
+
resultCase,
|
|
631
|
+
});
|
|
551
632
|
sendExecResult(execMsg, resultCase, create(McpResultSchema, {}), sendFrame);
|
|
552
633
|
return;
|
|
553
634
|
}
|
package/dist/proxy/types.d.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import type { CursorSession } from "../cursor/bidi-session";
|
|
2
|
-
import type { ConversationRequestMetadata } from "./conversation-meta";
|
|
3
2
|
import type { McpToolDefinition } from "../proto/agent_pb";
|
|
3
|
+
import type { ConversationRequestMetadata } from "./conversation-meta";
|
|
4
4
|
export interface CursorRequestPayload {
|
|
5
5
|
requestBytes: Uint8Array;
|
|
6
6
|
blobStore: Map<string, Uint8Array>;
|
|
7
|
+
cloudRule?: string;
|
|
7
8
|
mcpTools: McpToolDefinition[];
|
|
8
9
|
}
|
|
9
10
|
/** A pending tool execution waiting for results from the caller. */
|
|
@@ -14,14 +15,26 @@ export interface PendingExec {
|
|
|
14
15
|
toolName: string;
|
|
15
16
|
/** Decoded arguments JSON string for SSE tool_calls emission. */
|
|
16
17
|
decodedArgs: string;
|
|
18
|
+
source?: "interaction" | "exec";
|
|
19
|
+
cursorCallId?: string;
|
|
20
|
+
modelCallId?: string;
|
|
21
|
+
}
|
|
22
|
+
export interface ActiveBridgeDiagnostics {
|
|
23
|
+
announcedToolCallIds: string[];
|
|
24
|
+
publishedToolCallIds: string[];
|
|
25
|
+
lastMcpUpdate?: string;
|
|
26
|
+
publishedAtMs?: number;
|
|
27
|
+
lastResumeAttemptAtMs?: number;
|
|
17
28
|
}
|
|
18
29
|
/** A live Cursor session kept alive across requests for tool result continuation. */
|
|
19
30
|
export interface ActiveBridge {
|
|
20
31
|
bridge: CursorSession;
|
|
21
32
|
heartbeatTimer: NodeJS.Timeout;
|
|
22
33
|
blobStore: Map<string, Uint8Array>;
|
|
34
|
+
cloudRule?: string;
|
|
23
35
|
mcpTools: McpToolDefinition[];
|
|
24
36
|
pendingExecs: PendingExec[];
|
|
25
37
|
modelId: string;
|
|
26
38
|
metadata: ConversationRequestMetadata;
|
|
39
|
+
diagnostics?: ActiveBridgeDiagnostics;
|
|
27
40
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@playwo/opencode-cursor-oauth",
|
|
3
|
-
"version": "0.0.0-dev.
|
|
3
|
+
"version": "0.0.0-dev.4696faa690e4",
|
|
4
4
|
"description": "OpenCode plugin that connects Cursor's API to OpenCode via OAuth, model discovery, and a local OpenAI-compatible proxy.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -18,8 +18,7 @@
|
|
|
18
18
|
"dist"
|
|
19
19
|
],
|
|
20
20
|
"scripts": {
|
|
21
|
-
"build": "
|
|
22
|
-
"test": "bun test/smoke.ts",
|
|
21
|
+
"build": "node ./scripts/build.mjs",
|
|
23
22
|
"prepublishOnly": "npm run build"
|
|
24
23
|
},
|
|
25
24
|
"repository": {
|