@playwo/opencode-cursor-oauth 0.0.0-dev.4463bb589222 → 0.0.0-dev.6338d5591e37

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.
@@ -103,7 +103,6 @@ function createBridgeStreamResponse(bridge, heartbeatTimer, blobStore, mcpTools,
103
103
  sendSSE(makeChunk({ content }));
104
104
  }
105
105
  }, (exec) => {
106
- state.pendingExecs.push(exec);
107
106
  mcpExecReceived = true;
108
107
  const flushed = tagFilter.flush();
109
108
  if (flushed.reasoning)
@@ -128,6 +128,51 @@ 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
+ function getPendingExecKey(exec) {
132
+ return exec.toolCallId || `${exec.toolName}:${exec.decodedArgs}`;
133
+ }
134
+ function replacePendingExec(state, exec) {
135
+ const execKey = getPendingExecKey(exec);
136
+ const existingIndex = state.pendingExecs.findIndex((candidate) => getPendingExecKey(candidate) === execKey);
137
+ if (existingIndex >= 0) {
138
+ state.pendingExecs[existingIndex] = exec;
139
+ return;
140
+ }
141
+ state.pendingExecs.push(exec);
142
+ }
143
+ function hasUsableDecodedArgs(decodedArgs) {
144
+ const trimmed = decodedArgs.trim();
145
+ return trimmed !== "" && trimmed !== "{}";
146
+ }
147
+ function mergePendingExec(existing, incoming) {
148
+ const incomingHasExecMetadata = incoming.execMsgId !== 0;
149
+ const existingHasExecMetadata = existing.execMsgId !== 0;
150
+ return {
151
+ execId: incomingHasExecMetadata || !existing.execId ? incoming.execId : existing.execId,
152
+ execMsgId: incomingHasExecMetadata || !existingHasExecMetadata
153
+ ? incoming.execMsgId
154
+ : existing.execMsgId,
155
+ toolCallId: existing.toolCallId || incoming.toolCallId,
156
+ toolName: incoming.toolName && incoming.toolName !== "unknown_mcp_tool"
157
+ ? incoming.toolName
158
+ : existing.toolName,
159
+ decodedArgs: hasUsableDecodedArgs(incoming.decodedArgs)
160
+ ? incoming.decodedArgs
161
+ : existing.decodedArgs,
162
+ };
163
+ }
164
+ function emitPendingExec(exec, state, onMcpExec) {
165
+ const execKey = getPendingExecKey(exec);
166
+ const existing = state.pendingExecs.find((candidate) => getPendingExecKey(candidate) === execKey);
167
+ const nextExec = existing ? mergePendingExec(existing, exec) : exec;
168
+ if (state.emittedToolCallIds.has(execKey)) {
169
+ replacePendingExec(state, nextExec);
170
+ return;
171
+ }
172
+ state.emittedToolCallIds.add(execKey);
173
+ replacePendingExec(state, nextExec);
174
+ onMcpExec(nextExec);
175
+ }
131
176
  export function processServerMessage(msg, blobStore, mcpTools, sendFrame, state, onText, onMcpExec, onCheckpoint, onTurnEnded, onUnsupportedMessage, onUnhandledExec) {
132
177
  const msgCase = msg.message.case;
133
178
  if (msgCase === "interactionUpdate") {
@@ -137,7 +182,7 @@ export function processServerMessage(msg, blobStore, mcpTools, sendFrame, state,
137
182
  handleKvMessage(msg.message.value, blobStore, sendFrame);
138
183
  }
139
184
  else if (msgCase === "execServerMessage") {
140
- handleExecMessage(msg.message.value, mcpTools, sendFrame, onMcpExec, onUnhandledExec);
185
+ handleExecMessage(msg.message.value, mcpTools, sendFrame, state, onMcpExec, onUnhandledExec);
141
186
  }
142
187
  else if (msgCase === "execServerControlMessage") {
143
188
  onUnsupportedMessage?.({
@@ -182,13 +227,14 @@ function handleInteractionUpdate(update, state, onText, onMcpExec, onTurnEnded,
182
227
  else if (updateCase === "partialToolCall") {
183
228
  const partial = update.message.value;
184
229
  if (partial.callId && partial.argsTextDelta) {
185
- state.interactionToolArgsText.set(partial.callId, partial.argsTextDelta);
230
+ const existing = state.interactionToolArgsText.get(partial.callId) ?? "";
231
+ state.interactionToolArgsText.set(partial.callId, `${existing}${partial.argsTextDelta}`);
186
232
  }
187
233
  }
188
234
  else if (updateCase === "toolCallCompleted") {
189
235
  const exec = decodeInteractionToolCall(update.message.value, state);
190
236
  if (exec)
191
- onMcpExec(exec);
237
+ emitPendingExec(exec, state, onMcpExec);
192
238
  }
193
239
  else if (updateCase === "turnEnded") {
194
240
  onTurnEnded?.();
@@ -225,8 +271,6 @@ function decodeInteractionToolCall(update, state) {
225
271
  if (!mcpArgs)
226
272
  return null;
227
273
  const toolCallId = mcpArgs.toolCallId || callId || crypto.randomUUID();
228
- if (state.emittedToolCallIds.has(toolCallId))
229
- return null;
230
274
  const decodedMap = decodeMcpArgsMap(mcpArgs.args ?? {});
231
275
  const partialArgsText = callId
232
276
  ? state.interactionToolArgsText.get(callId)?.trim()
@@ -238,7 +282,6 @@ function decodeInteractionToolCall(update, state) {
238
282
  else if (partialArgsText) {
239
283
  decodedArgs = partialArgsText;
240
284
  }
241
- state.emittedToolCallIds.add(toolCallId);
242
285
  if (callId)
243
286
  state.interactionToolArgsText.delete(callId);
244
287
  return {
@@ -374,7 +417,7 @@ function handleKvMessage(kvMsg, blobStore, sendFrame) {
374
417
  sendKvResponse(kvMsg, "setBlobResult", create(SetBlobResultSchema, {}), sendFrame);
375
418
  }
376
419
  }
377
- function handleExecMessage(execMsg, mcpTools, sendFrame, onMcpExec, onUnhandledExec) {
420
+ function handleExecMessage(execMsg, mcpTools, sendFrame, state, onMcpExec, onUnhandledExec) {
378
421
  const execCase = execMsg.message.case;
379
422
  if (execCase === "requestContextArgs") {
380
423
  const requestContext = create(RequestContextSchema, {
@@ -399,13 +442,14 @@ function handleExecMessage(execMsg, mcpTools, sendFrame, onMcpExec, onUnhandledE
399
442
  if (execCase === "mcpArgs") {
400
443
  const mcpArgs = execMsg.message.value;
401
444
  const decoded = decodeMcpArgsMap(mcpArgs.args ?? {});
402
- onMcpExec({
445
+ const exec = {
403
446
  execId: execMsg.execId,
404
447
  execMsgId: execMsg.id,
405
448
  toolCallId: mcpArgs.toolCallId || crypto.randomUUID(),
406
449
  toolName: mcpArgs.toolName || mcpArgs.name,
407
450
  decodedArgs: JSON.stringify(decoded),
408
- });
451
+ };
452
+ emitPendingExec(exec, state, onMcpExec);
409
453
  return;
410
454
  }
411
455
  // --- Reject native Cursor tools ---
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@playwo/opencode-cursor-oauth",
3
- "version": "0.0.0-dev.4463bb589222",
3
+ "version": "0.0.0-dev.6338d5591e37",
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",