@playwo/opencode-cursor-oauth 0.0.0-dev.12f4642b8f6b → 0.0.0-dev.14c6316643ec
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/cursor/bidi-session.d.ts +1 -2
- package/dist/cursor/bidi-session.js +153 -138
- package/dist/cursor/index.d.ts +1 -1
- package/dist/cursor/index.js +1 -1
- package/dist/cursor/unary-rpc.d.ts +0 -1
- package/dist/cursor/unary-rpc.js +2 -59
- package/dist/logger.d.ts +1 -0
- package/dist/logger.js +3 -0
- package/dist/openai/messages.js +5 -0
- package/dist/plugin/cursor-auth-plugin.js +0 -1
- 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 +18 -2
- package/dist/proxy/bridge-session.js +1 -3
- package/dist/proxy/bridge-streaming.d.ts +1 -1
- package/dist/proxy/bridge-streaming.js +129 -18
- package/dist/proxy/chat-completion.js +43 -3
- package/dist/proxy/cursor-request.d.ts +1 -0
- package/dist/proxy/cursor-request.js +23 -8
- package/dist/proxy/server.js +23 -5
- package/dist/proxy/stream-dispatch.d.ts +6 -1
- package/dist/proxy/stream-dispatch.js +241 -11
- package/dist/proxy/types.d.ts +6 -1
- package/package.json +1 -2
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { create, toBinary } from "@bufbuild/protobuf";
|
|
2
|
-
import { AgentClientMessageSchema, ClientHeartbeatSchema, ConversationStateStructureSchema, BackgroundShellSpawnResultSchema, DeleteResultSchema, DeleteRejectedSchema, DiagnosticsResultSchema, ExecClientMessageSchema, FetchErrorSchema, FetchResultSchema, GetBlobResultSchema, GrepErrorSchema, GrepResultSchema, KvClientMessageSchema, LsRejectedSchema, LsResultSchema, McpResultSchema, ReadRejectedSchema, ReadResultSchema, RequestContextResultSchema, RequestContextSchema, RequestContextSuccessSchema, SetBlobResultSchema, ShellRejectedSchema, ShellResultSchema, 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, 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,25 @@ 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, onUnhandledExec) {
|
|
131
|
+
export function processServerMessage(msg, blobStore, cloudRule, mcpTools, sendFrame, state, onText, onMcpExec, onCheckpoint, onTurnEnded, onUnsupportedMessage, onUnhandledExec) {
|
|
132
132
|
const msgCase = msg.message.case;
|
|
133
133
|
if (msgCase === "interactionUpdate") {
|
|
134
|
-
handleInteractionUpdate(msg.message.value, state, onText, onTurnEnded);
|
|
134
|
+
handleInteractionUpdate(msg.message.value, state, onText, 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
|
+
}
|
|
142
|
+
else if (msgCase === "execServerControlMessage") {
|
|
143
|
+
onUnsupportedMessage?.({
|
|
144
|
+
category: "execServerControl",
|
|
145
|
+
caseName: msg.message.value.message.case ?? "undefined",
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
else if (msgCase === "interactionQuery") {
|
|
149
|
+
handleInteractionQuery(msg.message.value, sendFrame, onUnsupportedMessage);
|
|
141
150
|
}
|
|
142
151
|
else if (msgCase === "conversationCheckpointUpdate") {
|
|
143
152
|
const stateStructure = msg.message.value;
|
|
@@ -148,9 +157,26 @@ export function processServerMessage(msg, blobStore, mcpTools, sendFrame, state,
|
|
|
148
157
|
onCheckpoint(toBinary(ConversationStateStructureSchema, stateStructure));
|
|
149
158
|
}
|
|
150
159
|
}
|
|
160
|
+
else {
|
|
161
|
+
onUnsupportedMessage?.({
|
|
162
|
+
category: "agentMessage",
|
|
163
|
+
caseName: msgCase ?? "undefined",
|
|
164
|
+
});
|
|
165
|
+
}
|
|
151
166
|
}
|
|
152
|
-
function handleInteractionUpdate(update, state, onText, onTurnEnded) {
|
|
167
|
+
function handleInteractionUpdate(update, state, onText, onTurnEnded, onUnsupportedMessage) {
|
|
153
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
|
+
}
|
|
154
180
|
if (updateCase === "textDelta") {
|
|
155
181
|
const delta = update.message.value.text || "";
|
|
156
182
|
if (delta)
|
|
@@ -164,12 +190,128 @@ function handleInteractionUpdate(update, state, onText, onTurnEnded) {
|
|
|
164
190
|
else if (updateCase === "tokenDelta") {
|
|
165
191
|
state.outputTokens += update.message.value.tokens ?? 0;
|
|
166
192
|
}
|
|
193
|
+
else if (updateCase === "partialToolCall") {
|
|
194
|
+
return;
|
|
195
|
+
}
|
|
196
|
+
else if (updateCase === "toolCallCompleted") {
|
|
197
|
+
const toolValue = update.message.value;
|
|
198
|
+
if (toolValue?.toolCall?.tool?.case === "mcpToolCall") {
|
|
199
|
+
logPluginInfo("Ignoring Cursor interaction MCP tool completion", {
|
|
200
|
+
callId: toolValue.callId,
|
|
201
|
+
modelCallId: toolValue.modelCallId,
|
|
202
|
+
toolCallId: toolValue.toolCall.tool.value?.args?.toolCallId || toolValue.callId,
|
|
203
|
+
toolName: toolValue.toolCall.tool.value?.args?.toolName ||
|
|
204
|
+
toolValue.toolCall.tool.value?.args?.name,
|
|
205
|
+
});
|
|
206
|
+
}
|
|
207
|
+
}
|
|
167
208
|
else if (updateCase === "turnEnded") {
|
|
168
209
|
onTurnEnded?.();
|
|
169
210
|
}
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
211
|
+
else if (updateCase === "toolCallStarted" ||
|
|
212
|
+
updateCase === "toolCallDelta" ||
|
|
213
|
+
updateCase === "thinkingCompleted" ||
|
|
214
|
+
updateCase === "userMessageAppended" ||
|
|
215
|
+
updateCase === "summary" ||
|
|
216
|
+
updateCase === "summaryStarted" ||
|
|
217
|
+
updateCase === "summaryCompleted" ||
|
|
218
|
+
updateCase === "heartbeat" ||
|
|
219
|
+
updateCase === "stepStarted" ||
|
|
220
|
+
updateCase === "stepCompleted") {
|
|
221
|
+
return;
|
|
222
|
+
}
|
|
223
|
+
else {
|
|
224
|
+
onUnsupportedMessage?.({
|
|
225
|
+
category: "interactionUpdate",
|
|
226
|
+
caseName: updateCase ?? "undefined",
|
|
227
|
+
});
|
|
228
|
+
}
|
|
229
|
+
// Interaction tool-call updates are informational only. Resumable MCP tool
|
|
230
|
+
// execution comes from execServerMessage.mcpArgs.
|
|
231
|
+
}
|
|
232
|
+
function handleInteractionQuery(query, sendFrame, onUnsupportedMessage) {
|
|
233
|
+
const queryCase = query.query.case;
|
|
234
|
+
if (queryCase === "webSearchRequestQuery") {
|
|
235
|
+
const response = create(WebSearchRequestResponseSchema, {
|
|
236
|
+
result: {
|
|
237
|
+
case: "rejected",
|
|
238
|
+
value: create(WebSearchRequestResponse_RejectedSchema, {
|
|
239
|
+
reason: "Native Cursor web search is not available in this environment. Use the provided MCP tool `websearch` instead.",
|
|
240
|
+
}),
|
|
241
|
+
},
|
|
242
|
+
});
|
|
243
|
+
sendInteractionResponse(query.id, "webSearchRequestResponse", response, sendFrame);
|
|
244
|
+
return;
|
|
245
|
+
}
|
|
246
|
+
if (queryCase === "askQuestionInteractionQuery") {
|
|
247
|
+
const response = create(AskQuestionInteractionResponseSchema, {
|
|
248
|
+
result: create(AskQuestionResultSchema, {
|
|
249
|
+
result: {
|
|
250
|
+
case: "rejected",
|
|
251
|
+
value: create(AskQuestionRejectedSchema, {
|
|
252
|
+
reason: "Native Cursor question prompts are not available in this environment. Use the provided MCP tool `question` instead.",
|
|
253
|
+
}),
|
|
254
|
+
},
|
|
255
|
+
}),
|
|
256
|
+
});
|
|
257
|
+
sendInteractionResponse(query.id, "askQuestionInteractionResponse", response, sendFrame);
|
|
258
|
+
return;
|
|
259
|
+
}
|
|
260
|
+
if (queryCase === "switchModeRequestQuery") {
|
|
261
|
+
const response = create(SwitchModeRequestResponseSchema, {
|
|
262
|
+
result: {
|
|
263
|
+
case: "rejected",
|
|
264
|
+
value: create(SwitchModeRequestResponse_RejectedSchema, {
|
|
265
|
+
reason: "Cursor mode switching is not available in this environment. Continue using the current agent and the provided MCP tools.",
|
|
266
|
+
}),
|
|
267
|
+
},
|
|
268
|
+
});
|
|
269
|
+
sendInteractionResponse(query.id, "switchModeRequestResponse", response, sendFrame);
|
|
270
|
+
return;
|
|
271
|
+
}
|
|
272
|
+
if (queryCase === "exaSearchRequestQuery") {
|
|
273
|
+
const response = create(ExaSearchRequestResponseSchema, {
|
|
274
|
+
result: {
|
|
275
|
+
case: "rejected",
|
|
276
|
+
value: create(ExaSearchRequestResponse_RejectedSchema, {
|
|
277
|
+
reason: "Native Cursor Exa search is not available in this environment. Use the provided MCP tool `websearch` instead.",
|
|
278
|
+
}),
|
|
279
|
+
},
|
|
280
|
+
});
|
|
281
|
+
sendInteractionResponse(query.id, "exaSearchRequestResponse", response, sendFrame);
|
|
282
|
+
return;
|
|
283
|
+
}
|
|
284
|
+
if (queryCase === "exaFetchRequestQuery") {
|
|
285
|
+
const response = create(ExaFetchRequestResponseSchema, {
|
|
286
|
+
result: {
|
|
287
|
+
case: "rejected",
|
|
288
|
+
value: create(ExaFetchRequestResponse_RejectedSchema, {
|
|
289
|
+
reason: "Native Cursor Exa fetch is not available in this environment. Use the provided MCP tools `websearch` and `webfetch` instead.",
|
|
290
|
+
}),
|
|
291
|
+
},
|
|
292
|
+
});
|
|
293
|
+
sendInteractionResponse(query.id, "exaFetchRequestResponse", response, sendFrame);
|
|
294
|
+
return;
|
|
295
|
+
}
|
|
296
|
+
if (queryCase === "createPlanRequestQuery") {
|
|
297
|
+
const response = create(CreatePlanRequestResponseSchema, {
|
|
298
|
+
result: create(CreatePlanResultSchema, {
|
|
299
|
+
planUri: "",
|
|
300
|
+
result: {
|
|
301
|
+
case: "error",
|
|
302
|
+
value: create(CreatePlanErrorSchema, {
|
|
303
|
+
error: "Native Cursor plan creation is not available in this environment. Use the provided MCP planning tools instead.",
|
|
304
|
+
}),
|
|
305
|
+
},
|
|
306
|
+
}),
|
|
307
|
+
});
|
|
308
|
+
sendInteractionResponse(query.id, "createPlanRequestResponse", response, sendFrame);
|
|
309
|
+
return;
|
|
310
|
+
}
|
|
311
|
+
onUnsupportedMessage?.({
|
|
312
|
+
category: "interactionQuery",
|
|
313
|
+
caseName: queryCase ?? "undefined",
|
|
314
|
+
});
|
|
173
315
|
}
|
|
174
316
|
/** Send a KV client response back to Cursor. */
|
|
175
317
|
function sendKvResponse(kvMsg, messageCase, value, sendFrame) {
|
|
@@ -182,6 +324,16 @@ function sendKvResponse(kvMsg, messageCase, value, sendFrame) {
|
|
|
182
324
|
});
|
|
183
325
|
sendFrame(toBinary(AgentClientMessageSchema, clientMsg));
|
|
184
326
|
}
|
|
327
|
+
function sendInteractionResponse(queryId, messageCase, value, sendFrame) {
|
|
328
|
+
const response = create(InteractionResponseSchema, {
|
|
329
|
+
id: queryId,
|
|
330
|
+
result: { case: messageCase, value: value },
|
|
331
|
+
});
|
|
332
|
+
const clientMessage = create(AgentClientMessageSchema, {
|
|
333
|
+
message: { case: "interactionResponse", value: response },
|
|
334
|
+
});
|
|
335
|
+
sendFrame(toBinary(AgentClientMessageSchema, clientMessage));
|
|
336
|
+
}
|
|
185
337
|
function handleKvMessage(kvMsg, blobStore, sendFrame) {
|
|
186
338
|
const kvCase = kvMsg.message.case;
|
|
187
339
|
if (kvCase === "getBlobArgs") {
|
|
@@ -202,9 +354,19 @@ function handleKvMessage(kvMsg, blobStore, sendFrame) {
|
|
|
202
354
|
sendKvResponse(kvMsg, "setBlobResult", create(SetBlobResultSchema, {}), sendFrame);
|
|
203
355
|
}
|
|
204
356
|
}
|
|
205
|
-
function handleExecMessage(execMsg, mcpTools, sendFrame, onMcpExec, onUnhandledExec) {
|
|
357
|
+
function handleExecMessage(execMsg, cloudRule, mcpTools, sendFrame, state, onMcpExec, onUnhandledExec) {
|
|
206
358
|
const execCase = execMsg.message.case;
|
|
359
|
+
logPluginInfo("Received Cursor exec message", {
|
|
360
|
+
execCase: execCase ?? "undefined",
|
|
361
|
+
execId: execMsg.execId,
|
|
362
|
+
execMsgId: execMsg.id,
|
|
363
|
+
});
|
|
207
364
|
if (execCase === "requestContextArgs") {
|
|
365
|
+
logPluginInfo("Responding to Cursor requestContextArgs", {
|
|
366
|
+
execId: execMsg.execId,
|
|
367
|
+
execMsgId: execMsg.id,
|
|
368
|
+
mcpToolCount: mcpTools.length,
|
|
369
|
+
});
|
|
208
370
|
const requestContext = create(RequestContextSchema, {
|
|
209
371
|
rules: [],
|
|
210
372
|
repositoryInfo: [],
|
|
@@ -212,6 +374,7 @@ function handleExecMessage(execMsg, mcpTools, sendFrame, onMcpExec, onUnhandledE
|
|
|
212
374
|
gitRepos: [],
|
|
213
375
|
projectLayouts: [],
|
|
214
376
|
mcpInstructions: [],
|
|
377
|
+
cloudRule,
|
|
215
378
|
fileContents: {},
|
|
216
379
|
customSubagents: [],
|
|
217
380
|
});
|
|
@@ -227,13 +390,23 @@ function handleExecMessage(execMsg, mcpTools, sendFrame, onMcpExec, onUnhandledE
|
|
|
227
390
|
if (execCase === "mcpArgs") {
|
|
228
391
|
const mcpArgs = execMsg.message.value;
|
|
229
392
|
const decoded = decodeMcpArgsMap(mcpArgs.args ?? {});
|
|
230
|
-
|
|
393
|
+
const exec = {
|
|
231
394
|
execId: execMsg.execId,
|
|
232
395
|
execMsgId: execMsg.id,
|
|
233
396
|
toolCallId: mcpArgs.toolCallId || crypto.randomUUID(),
|
|
234
397
|
toolName: mcpArgs.toolName || mcpArgs.name,
|
|
235
398
|
decodedArgs: JSON.stringify(decoded),
|
|
399
|
+
source: "exec",
|
|
400
|
+
};
|
|
401
|
+
logPluginInfo("Received Cursor exec MCP tool metadata", {
|
|
402
|
+
toolCallId: exec.toolCallId,
|
|
403
|
+
toolName: exec.toolName,
|
|
404
|
+
source: exec.source,
|
|
405
|
+
execId: exec.execId,
|
|
406
|
+
execMsgId: exec.execMsgId,
|
|
407
|
+
decodedArgs: exec.decodedArgs,
|
|
236
408
|
});
|
|
409
|
+
onMcpExec(exec);
|
|
237
410
|
return;
|
|
238
411
|
}
|
|
239
412
|
// --- Reject native Cursor tools ---
|
|
@@ -241,6 +414,11 @@ function handleExecMessage(execMsg, mcpTools, sendFrame, onMcpExec, onUnhandledE
|
|
|
241
414
|
// so it falls back to our MCP tools (registered via RequestContext).
|
|
242
415
|
const REJECT_REASON = "Tool not available in this environment. Use the MCP tools provided instead.";
|
|
243
416
|
if (execCase === "readArgs") {
|
|
417
|
+
logPluginInfo("Rejecting native Cursor read tool in favor of MCP", {
|
|
418
|
+
execId: execMsg.execId,
|
|
419
|
+
execMsgId: execMsg.id,
|
|
420
|
+
path: execMsg.message.value.path,
|
|
421
|
+
});
|
|
244
422
|
const args = execMsg.message.value;
|
|
245
423
|
const result = create(ReadResultSchema, {
|
|
246
424
|
result: {
|
|
@@ -255,6 +433,11 @@ function handleExecMessage(execMsg, mcpTools, sendFrame, onMcpExec, onUnhandledE
|
|
|
255
433
|
return;
|
|
256
434
|
}
|
|
257
435
|
if (execCase === "lsArgs") {
|
|
436
|
+
logPluginInfo("Rejecting native Cursor ls tool in favor of MCP", {
|
|
437
|
+
execId: execMsg.execId,
|
|
438
|
+
execMsgId: execMsg.id,
|
|
439
|
+
path: execMsg.message.value.path,
|
|
440
|
+
});
|
|
258
441
|
const args = execMsg.message.value;
|
|
259
442
|
const result = create(LsResultSchema, {
|
|
260
443
|
result: {
|
|
@@ -269,6 +452,10 @@ function handleExecMessage(execMsg, mcpTools, sendFrame, onMcpExec, onUnhandledE
|
|
|
269
452
|
return;
|
|
270
453
|
}
|
|
271
454
|
if (execCase === "grepArgs") {
|
|
455
|
+
logPluginInfo("Rejecting native Cursor grep tool in favor of MCP", {
|
|
456
|
+
execId: execMsg.execId,
|
|
457
|
+
execMsgId: execMsg.id,
|
|
458
|
+
});
|
|
272
459
|
const result = create(GrepResultSchema, {
|
|
273
460
|
result: {
|
|
274
461
|
case: "error",
|
|
@@ -279,6 +466,11 @@ function handleExecMessage(execMsg, mcpTools, sendFrame, onMcpExec, onUnhandledE
|
|
|
279
466
|
return;
|
|
280
467
|
}
|
|
281
468
|
if (execCase === "writeArgs") {
|
|
469
|
+
logPluginInfo("Rejecting native Cursor write tool in favor of MCP", {
|
|
470
|
+
execId: execMsg.execId,
|
|
471
|
+
execMsgId: execMsg.id,
|
|
472
|
+
path: execMsg.message.value.path,
|
|
473
|
+
});
|
|
282
474
|
const args = execMsg.message.value;
|
|
283
475
|
const result = create(WriteResultSchema, {
|
|
284
476
|
result: {
|
|
@@ -293,6 +485,11 @@ function handleExecMessage(execMsg, mcpTools, sendFrame, onMcpExec, onUnhandledE
|
|
|
293
485
|
return;
|
|
294
486
|
}
|
|
295
487
|
if (execCase === "deleteArgs") {
|
|
488
|
+
logPluginInfo("Rejecting native Cursor delete tool in favor of MCP", {
|
|
489
|
+
execId: execMsg.execId,
|
|
490
|
+
execMsgId: execMsg.id,
|
|
491
|
+
path: execMsg.message.value.path,
|
|
492
|
+
});
|
|
296
493
|
const args = execMsg.message.value;
|
|
297
494
|
const result = create(DeleteResultSchema, {
|
|
298
495
|
result: {
|
|
@@ -307,6 +504,13 @@ function handleExecMessage(execMsg, mcpTools, sendFrame, onMcpExec, onUnhandledE
|
|
|
307
504
|
return;
|
|
308
505
|
}
|
|
309
506
|
if (execCase === "shellArgs" || execCase === "shellStreamArgs") {
|
|
507
|
+
logPluginInfo("Rejecting native Cursor shell tool in favor of MCP", {
|
|
508
|
+
execId: execMsg.execId,
|
|
509
|
+
execMsgId: execMsg.id,
|
|
510
|
+
command: execMsg.message.value.command ?? "",
|
|
511
|
+
workingDirectory: execMsg.message.value.workingDirectory ?? "",
|
|
512
|
+
execCase,
|
|
513
|
+
});
|
|
310
514
|
const args = execMsg.message.value;
|
|
311
515
|
const result = create(ShellResultSchema, {
|
|
312
516
|
result: {
|
|
@@ -323,6 +527,12 @@ function handleExecMessage(execMsg, mcpTools, sendFrame, onMcpExec, onUnhandledE
|
|
|
323
527
|
return;
|
|
324
528
|
}
|
|
325
529
|
if (execCase === "backgroundShellSpawnArgs") {
|
|
530
|
+
logPluginInfo("Rejecting native Cursor background 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
|
+
});
|
|
326
536
|
const args = execMsg.message.value;
|
|
327
537
|
const result = create(BackgroundShellSpawnResultSchema, {
|
|
328
538
|
result: {
|
|
@@ -339,6 +549,10 @@ function handleExecMessage(execMsg, mcpTools, sendFrame, onMcpExec, onUnhandledE
|
|
|
339
549
|
return;
|
|
340
550
|
}
|
|
341
551
|
if (execCase === "writeShellStdinArgs") {
|
|
552
|
+
logPluginInfo("Rejecting native Cursor shell stdin tool in favor of MCP", {
|
|
553
|
+
execId: execMsg.execId,
|
|
554
|
+
execMsgId: execMsg.id,
|
|
555
|
+
});
|
|
342
556
|
const result = create(WriteShellStdinResultSchema, {
|
|
343
557
|
result: {
|
|
344
558
|
case: "error",
|
|
@@ -349,6 +563,11 @@ function handleExecMessage(execMsg, mcpTools, sendFrame, onMcpExec, onUnhandledE
|
|
|
349
563
|
return;
|
|
350
564
|
}
|
|
351
565
|
if (execCase === "fetchArgs") {
|
|
566
|
+
logPluginInfo("Rejecting native Cursor fetch tool in favor of MCP", {
|
|
567
|
+
execId: execMsg.execId,
|
|
568
|
+
execMsgId: execMsg.id,
|
|
569
|
+
url: execMsg.message.value.url,
|
|
570
|
+
});
|
|
352
571
|
const args = execMsg.message.value;
|
|
353
572
|
const result = create(FetchResultSchema, {
|
|
354
573
|
result: {
|
|
@@ -363,6 +582,11 @@ function handleExecMessage(execMsg, mcpTools, sendFrame, onMcpExec, onUnhandledE
|
|
|
363
582
|
return;
|
|
364
583
|
}
|
|
365
584
|
if (execCase === "diagnosticsArgs") {
|
|
585
|
+
logPluginInfo("Rejecting native Cursor diagnostics tool in favor of MCP", {
|
|
586
|
+
execId: execMsg.execId,
|
|
587
|
+
execMsgId: execMsg.id,
|
|
588
|
+
path: execMsg.message.value.path,
|
|
589
|
+
});
|
|
366
590
|
const result = create(DiagnosticsResultSchema, {});
|
|
367
591
|
sendExecResult(execMsg, "diagnosticsResult", result, sendFrame);
|
|
368
592
|
return;
|
|
@@ -376,6 +600,12 @@ function handleExecMessage(execMsg, mcpTools, sendFrame, onMcpExec, onUnhandledE
|
|
|
376
600
|
};
|
|
377
601
|
const resultCase = miscCaseMap[execCase];
|
|
378
602
|
if (resultCase) {
|
|
603
|
+
logPluginInfo("Responding to miscellaneous Cursor exec message", {
|
|
604
|
+
execCase,
|
|
605
|
+
execId: execMsg.execId,
|
|
606
|
+
execMsgId: execMsg.id,
|
|
607
|
+
resultCase,
|
|
608
|
+
});
|
|
379
609
|
sendExecResult(execMsg, resultCase, create(McpResultSchema, {}), sendFrame);
|
|
380
610
|
return;
|
|
381
611
|
}
|
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,12 +15,16 @@ 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;
|
|
17
21
|
}
|
|
18
22
|
/** A live Cursor session kept alive across requests for tool result continuation. */
|
|
19
23
|
export interface ActiveBridge {
|
|
20
24
|
bridge: CursorSession;
|
|
21
25
|
heartbeatTimer: NodeJS.Timeout;
|
|
22
26
|
blobStore: Map<string, Uint8Array>;
|
|
27
|
+
cloudRule?: string;
|
|
23
28
|
mcpTools: McpToolDefinition[];
|
|
24
29
|
pendingExecs: PendingExec[];
|
|
25
30
|
modelId: string;
|
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.14c6316643ec",
|
|
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",
|
|
@@ -19,7 +19,6 @@
|
|
|
19
19
|
],
|
|
20
20
|
"scripts": {
|
|
21
21
|
"build": "tsc -p tsconfig.json",
|
|
22
|
-
"test": "bun test/smoke.ts",
|
|
23
22
|
"prepublishOnly": "npm run build"
|
|
24
23
|
},
|
|
25
24
|
"repository": {
|