@playwo/opencode-cursor-oauth 0.0.0-dev.4258a6733133 → 0.0.0-dev.494d4e1cfa84

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.
@@ -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, 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, onCheckpoint, onTurnEnded, onUnsupportedMessage, onUnhandledExec) {
132
132
  const msgCase = msg.message.case;
133
133
  if (msgCase === "interactionUpdate") {
134
- handleInteractionUpdate(msg.message.value, state, onText, onMcpExec, onTurnEnded, onUnsupportedMessage);
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
141
  }
142
142
  else if (msgCase === "execServerControlMessage") {
143
143
  onUnsupportedMessage?.({
@@ -146,10 +146,7 @@ export function processServerMessage(msg, blobStore, mcpTools, sendFrame, state,
146
146
  });
147
147
  }
148
148
  else if (msgCase === "interactionQuery") {
149
- onUnsupportedMessage?.({
150
- category: "interactionQuery",
151
- caseName: msg.message.value.query.case ?? "undefined",
152
- });
149
+ handleInteractionQuery(msg.message.value, sendFrame, onUnsupportedMessage);
153
150
  }
154
151
  else if (msgCase === "conversationCheckpointUpdate") {
155
152
  const stateStructure = msg.message.value;
@@ -167,8 +164,19 @@ export function processServerMessage(msg, blobStore, mcpTools, sendFrame, state,
167
164
  });
168
165
  }
169
166
  }
170
- function handleInteractionUpdate(update, state, onText, onMcpExec, onTurnEnded, onUnsupportedMessage) {
167
+ function handleInteractionUpdate(update, state, onText, onTurnEnded, onUnsupportedMessage) {
171
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
+ }
172
180
  if (updateCase === "textDelta") {
173
181
  const delta = update.message.value.text || "";
174
182
  if (delta)
@@ -183,15 +191,19 @@ function handleInteractionUpdate(update, state, onText, onMcpExec, onTurnEnded,
183
191
  state.outputTokens += update.message.value.tokens ?? 0;
184
192
  }
185
193
  else if (updateCase === "partialToolCall") {
186
- const partial = update.message.value;
187
- if (partial.callId && partial.argsTextDelta) {
188
- state.interactionToolArgsText.set(partial.callId, partial.argsTextDelta);
189
- }
194
+ return;
190
195
  }
191
196
  else if (updateCase === "toolCallCompleted") {
192
- const exec = decodeInteractionToolCall(update.message.value, state);
193
- if (exec)
194
- onMcpExec(exec);
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
+ }
195
207
  }
196
208
  else if (updateCase === "turnEnded") {
197
209
  onTurnEnded?.();
@@ -214,43 +226,92 @@ function handleInteractionUpdate(update, state, onText, onMcpExec, onTurnEnded,
214
226
  caseName: updateCase ?? "undefined",
215
227
  });
216
228
  }
217
- // toolCallStarted, partialToolCall, toolCallDelta, and non-MCP
218
- // toolCallCompleted updates are informational only. Actionable MCP tool
219
- // calls may still appear here on some models, so we surface those, but we
220
- // do not abort the bridge for native Cursor tool-call progress events.
229
+ // Interaction tool-call updates are informational only. Resumable MCP tool
230
+ // execution comes from execServerMessage.mcpArgs.
221
231
  }
222
- function decodeInteractionToolCall(update, state) {
223
- const callId = update.callId ?? "";
224
- const toolCase = update.toolCall?.tool?.case;
225
- if (toolCase !== "mcpToolCall")
226
- return null;
227
- const mcpArgs = update.toolCall?.tool?.value?.args;
228
- if (!mcpArgs)
229
- return null;
230
- const toolCallId = mcpArgs.toolCallId || callId || crypto.randomUUID();
231
- if (state.emittedToolCallIds.has(toolCallId))
232
- return null;
233
- const decodedMap = decodeMcpArgsMap(mcpArgs.args ?? {});
234
- const partialArgsText = callId
235
- ? state.interactionToolArgsText.get(callId)?.trim()
236
- : undefined;
237
- let decodedArgs = "{}";
238
- if (Object.keys(decodedMap).length > 0) {
239
- decodedArgs = JSON.stringify(decodedMap);
240
- }
241
- else if (partialArgsText) {
242
- decodedArgs = partialArgsText;
243
- }
244
- state.emittedToolCallIds.add(toolCallId);
245
- if (callId)
246
- state.interactionToolArgsText.delete(callId);
247
- return {
248
- execId: callId || toolCallId,
249
- execMsgId: 0,
250
- toolCallId,
251
- toolName: mcpArgs.toolName || mcpArgs.name || "unknown_mcp_tool",
252
- decodedArgs,
253
- };
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
+ });
254
315
  }
255
316
  /** Send a KV client response back to Cursor. */
256
317
  function sendKvResponse(kvMsg, messageCase, value, sendFrame) {
@@ -263,6 +324,16 @@ function sendKvResponse(kvMsg, messageCase, value, sendFrame) {
263
324
  });
264
325
  sendFrame(toBinary(AgentClientMessageSchema, clientMsg));
265
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
+ }
266
337
  function handleKvMessage(kvMsg, blobStore, sendFrame) {
267
338
  const kvCase = kvMsg.message.case;
268
339
  if (kvCase === "getBlobArgs") {
@@ -283,16 +354,34 @@ function handleKvMessage(kvMsg, blobStore, sendFrame) {
283
354
  sendKvResponse(kvMsg, "setBlobResult", create(SetBlobResultSchema, {}), sendFrame);
284
355
  }
285
356
  }
286
- function handleExecMessage(execMsg, mcpTools, sendFrame, onMcpExec, onUnhandledExec) {
357
+ function handleExecMessage(execMsg, cloudRule, mcpTools, sendFrame, state, onMcpExec, onUnhandledExec) {
287
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
+ });
288
364
  if (execCase === "requestContextArgs") {
365
+ logPluginInfo("Responding to Cursor requestContextArgs", {
366
+ execId: execMsg.execId,
367
+ execMsgId: execMsg.id,
368
+ mcpToolCount: mcpTools.length,
369
+ });
289
370
  const requestContext = create(RequestContextSchema, {
290
371
  rules: [],
291
372
  repositoryInfo: [],
292
373
  tools: mcpTools,
293
374
  gitRepos: [],
294
375
  projectLayouts: [],
295
- mcpInstructions: [],
376
+ mcpInstructions: [
377
+ create(McpInstructionsSchema, {
378
+ serverName: "opencode",
379
+ 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.",
380
+ }),
381
+ ],
382
+ cloudRule,
383
+ webSearchEnabled: false,
384
+ repositoryInfoShouldQueryProd: false,
296
385
  fileContents: {},
297
386
  customSubagents: [],
298
387
  });
@@ -308,13 +397,23 @@ function handleExecMessage(execMsg, mcpTools, sendFrame, onMcpExec, onUnhandledE
308
397
  if (execCase === "mcpArgs") {
309
398
  const mcpArgs = execMsg.message.value;
310
399
  const decoded = decodeMcpArgsMap(mcpArgs.args ?? {});
311
- onMcpExec({
400
+ const exec = {
312
401
  execId: execMsg.execId,
313
402
  execMsgId: execMsg.id,
314
403
  toolCallId: mcpArgs.toolCallId || crypto.randomUUID(),
315
404
  toolName: mcpArgs.toolName || mcpArgs.name,
316
405
  decodedArgs: JSON.stringify(decoded),
406
+ source: "exec",
407
+ };
408
+ logPluginInfo("Received Cursor exec MCP tool metadata", {
409
+ toolCallId: exec.toolCallId,
410
+ toolName: exec.toolName,
411
+ source: exec.source,
412
+ execId: exec.execId,
413
+ execMsgId: exec.execMsgId,
414
+ decodedArgs: exec.decodedArgs,
317
415
  });
416
+ onMcpExec(exec);
318
417
  return;
319
418
  }
320
419
  // --- Reject native Cursor tools ---
@@ -322,6 +421,11 @@ function handleExecMessage(execMsg, mcpTools, sendFrame, onMcpExec, onUnhandledE
322
421
  // so it falls back to our MCP tools (registered via RequestContext).
323
422
  const REJECT_REASON = "Tool not available in this environment. Use the MCP tools provided instead.";
324
423
  if (execCase === "readArgs") {
424
+ logPluginInfo("Rejecting native Cursor read tool in favor of MCP", {
425
+ execId: execMsg.execId,
426
+ execMsgId: execMsg.id,
427
+ path: execMsg.message.value.path,
428
+ });
325
429
  const args = execMsg.message.value;
326
430
  const result = create(ReadResultSchema, {
327
431
  result: {
@@ -336,6 +440,11 @@ function handleExecMessage(execMsg, mcpTools, sendFrame, onMcpExec, onUnhandledE
336
440
  return;
337
441
  }
338
442
  if (execCase === "lsArgs") {
443
+ logPluginInfo("Rejecting native Cursor ls tool in favor of MCP", {
444
+ execId: execMsg.execId,
445
+ execMsgId: execMsg.id,
446
+ path: execMsg.message.value.path,
447
+ });
339
448
  const args = execMsg.message.value;
340
449
  const result = create(LsResultSchema, {
341
450
  result: {
@@ -350,6 +459,10 @@ function handleExecMessage(execMsg, mcpTools, sendFrame, onMcpExec, onUnhandledE
350
459
  return;
351
460
  }
352
461
  if (execCase === "grepArgs") {
462
+ logPluginInfo("Rejecting native Cursor grep tool in favor of MCP", {
463
+ execId: execMsg.execId,
464
+ execMsgId: execMsg.id,
465
+ });
353
466
  const result = create(GrepResultSchema, {
354
467
  result: {
355
468
  case: "error",
@@ -360,6 +473,11 @@ function handleExecMessage(execMsg, mcpTools, sendFrame, onMcpExec, onUnhandledE
360
473
  return;
361
474
  }
362
475
  if (execCase === "writeArgs") {
476
+ logPluginInfo("Rejecting native Cursor write tool in favor of MCP", {
477
+ execId: execMsg.execId,
478
+ execMsgId: execMsg.id,
479
+ path: execMsg.message.value.path,
480
+ });
363
481
  const args = execMsg.message.value;
364
482
  const result = create(WriteResultSchema, {
365
483
  result: {
@@ -374,6 +492,11 @@ function handleExecMessage(execMsg, mcpTools, sendFrame, onMcpExec, onUnhandledE
374
492
  return;
375
493
  }
376
494
  if (execCase === "deleteArgs") {
495
+ logPluginInfo("Rejecting native Cursor delete tool in favor of MCP", {
496
+ execId: execMsg.execId,
497
+ execMsgId: execMsg.id,
498
+ path: execMsg.message.value.path,
499
+ });
377
500
  const args = execMsg.message.value;
378
501
  const result = create(DeleteResultSchema, {
379
502
  result: {
@@ -388,6 +511,13 @@ function handleExecMessage(execMsg, mcpTools, sendFrame, onMcpExec, onUnhandledE
388
511
  return;
389
512
  }
390
513
  if (execCase === "shellArgs" || execCase === "shellStreamArgs") {
514
+ logPluginInfo("Rejecting native Cursor shell tool in favor of MCP", {
515
+ execId: execMsg.execId,
516
+ execMsgId: execMsg.id,
517
+ command: execMsg.message.value.command ?? "",
518
+ workingDirectory: execMsg.message.value.workingDirectory ?? "",
519
+ execCase,
520
+ });
391
521
  const args = execMsg.message.value;
392
522
  const result = create(ShellResultSchema, {
393
523
  result: {
@@ -404,6 +534,12 @@ function handleExecMessage(execMsg, mcpTools, sendFrame, onMcpExec, onUnhandledE
404
534
  return;
405
535
  }
406
536
  if (execCase === "backgroundShellSpawnArgs") {
537
+ logPluginInfo("Rejecting native Cursor background shell tool in favor of MCP", {
538
+ execId: execMsg.execId,
539
+ execMsgId: execMsg.id,
540
+ command: execMsg.message.value.command ?? "",
541
+ workingDirectory: execMsg.message.value.workingDirectory ?? "",
542
+ });
407
543
  const args = execMsg.message.value;
408
544
  const result = create(BackgroundShellSpawnResultSchema, {
409
545
  result: {
@@ -420,6 +556,10 @@ function handleExecMessage(execMsg, mcpTools, sendFrame, onMcpExec, onUnhandledE
420
556
  return;
421
557
  }
422
558
  if (execCase === "writeShellStdinArgs") {
559
+ logPluginInfo("Rejecting native Cursor shell stdin tool in favor of MCP", {
560
+ execId: execMsg.execId,
561
+ execMsgId: execMsg.id,
562
+ });
423
563
  const result = create(WriteShellStdinResultSchema, {
424
564
  result: {
425
565
  case: "error",
@@ -430,6 +570,11 @@ function handleExecMessage(execMsg, mcpTools, sendFrame, onMcpExec, onUnhandledE
430
570
  return;
431
571
  }
432
572
  if (execCase === "fetchArgs") {
573
+ logPluginInfo("Rejecting native Cursor fetch tool in favor of MCP", {
574
+ execId: execMsg.execId,
575
+ execMsgId: execMsg.id,
576
+ url: execMsg.message.value.url,
577
+ });
433
578
  const args = execMsg.message.value;
434
579
  const result = create(FetchResultSchema, {
435
580
  result: {
@@ -444,6 +589,11 @@ function handleExecMessage(execMsg, mcpTools, sendFrame, onMcpExec, onUnhandledE
444
589
  return;
445
590
  }
446
591
  if (execCase === "diagnosticsArgs") {
592
+ logPluginInfo("Rejecting native Cursor diagnostics tool in favor of MCP", {
593
+ execId: execMsg.execId,
594
+ execMsgId: execMsg.id,
595
+ path: execMsg.message.value.path,
596
+ });
447
597
  const result = create(DiagnosticsResultSchema, {});
448
598
  sendExecResult(execMsg, "diagnosticsResult", result, sendFrame);
449
599
  return;
@@ -457,6 +607,12 @@ function handleExecMessage(execMsg, mcpTools, sendFrame, onMcpExec, onUnhandledE
457
607
  };
458
608
  const resultCase = miscCaseMap[execCase];
459
609
  if (resultCase) {
610
+ logPluginInfo("Responding to miscellaneous Cursor exec message", {
611
+ execCase,
612
+ execId: execMsg.execId,
613
+ execMsgId: execMsg.id,
614
+ resultCase,
615
+ });
460
616
  sendExecResult(execMsg, resultCase, create(McpResultSchema, {}), sendFrame);
461
617
  return;
462
618
  }
@@ -4,6 +4,4 @@ export interface StreamState {
4
4
  pendingExecs: PendingExec[];
5
5
  outputTokens: number;
6
6
  totalTokens: number;
7
- interactionToolArgsText: Map<string, string>;
8
- emittedToolCallIds: Set<string>;
9
7
  }
@@ -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.4258a6733133",
3
+ "version": "0.0.0-dev.494d4e1cfa84",
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": {