@playwo/opencode-cursor-oauth 0.0.0-dev.4696faa690e4 → 0.0.0-dev.4a26f78d4622
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.
|
@@ -6,7 +6,6 @@ import { startBridge } from "./bridge-session";
|
|
|
6
6
|
import { updateConversationCheckpoint, syncStoredBlobStore, } from "./state-sync";
|
|
7
7
|
import { computeUsage, createConnectFrameParser, createThinkingTagFilter, parseConnectEndStream, processServerMessage, scheduleBridgeEnd, } from "./stream-dispatch";
|
|
8
8
|
import { createBridgeCloseController } from "./bridge-close-controller";
|
|
9
|
-
const MCP_TOOL_BATCH_WINDOW_MS = 150;
|
|
10
9
|
export async function handleNonStreamingResponse(payload, accessToken, modelId, convKey, metadata) {
|
|
11
10
|
const completionId = `chatcmpl-${crypto.randomUUID().replace(/-/g, "").slice(0, 28)}`;
|
|
12
11
|
const created = Math.floor(Date.now() / 1000);
|
|
@@ -34,19 +33,8 @@ async function collectFullResponse(payload, accessToken, modelId, convKey, metad
|
|
|
34
33
|
let fullText = "";
|
|
35
34
|
let endStreamError = null;
|
|
36
35
|
const pendingToolCalls = [];
|
|
37
|
-
let toolCallEndTimer;
|
|
38
36
|
const { bridge, heartbeatTimer } = await startBridge(accessToken, payload.requestBytes);
|
|
39
37
|
const bridgeCloseController = createBridgeCloseController(bridge);
|
|
40
|
-
const stopToolCallEndTimer = () => {
|
|
41
|
-
if (!toolCallEndTimer)
|
|
42
|
-
return;
|
|
43
|
-
clearTimeout(toolCallEndTimer);
|
|
44
|
-
toolCallEndTimer = undefined;
|
|
45
|
-
};
|
|
46
|
-
const scheduleToolCallBridgeEnd = () => {
|
|
47
|
-
stopToolCallEndTimer();
|
|
48
|
-
toolCallEndTimer = setTimeout(() => scheduleBridgeEnd(bridge), MCP_TOOL_BATCH_WINDOW_MS);
|
|
49
|
-
};
|
|
50
38
|
const state = {
|
|
51
39
|
toolCallIndex: 0,
|
|
52
40
|
pendingExecs: [],
|
|
@@ -78,11 +66,18 @@ async function collectFullResponse(payload, accessToken, modelId, convKey, metad
|
|
|
78
66
|
else {
|
|
79
67
|
pendingToolCalls.push(toolCall);
|
|
80
68
|
}
|
|
81
|
-
|
|
82
|
-
}, (_info) => { }, (checkpointBytes) => {
|
|
69
|
+
}, (_info) => { }, undefined, (checkpointBytes) => {
|
|
83
70
|
updateConversationCheckpoint(convKey, checkpointBytes);
|
|
84
71
|
bridgeCloseController.noteCheckpoint();
|
|
85
|
-
|
|
72
|
+
if (pendingToolCalls.length > 0) {
|
|
73
|
+
scheduleBridgeEnd(bridge);
|
|
74
|
+
}
|
|
75
|
+
}, () => {
|
|
76
|
+
bridgeCloseController.noteTurnEnded();
|
|
77
|
+
if (pendingToolCalls.length > 0) {
|
|
78
|
+
scheduleBridgeEnd(bridge);
|
|
79
|
+
}
|
|
80
|
+
}, (info) => {
|
|
86
81
|
endStreamError = new Error(`Cursor returned unsupported ${info.category}: ${info.caseName}${info.detail ? ` (${info.detail})` : ""}`);
|
|
87
82
|
logPluginError("Closing non-streaming Cursor bridge after unsupported message", {
|
|
88
83
|
modelId,
|
|
@@ -120,7 +115,6 @@ async function collectFullResponse(payload, accessToken, modelId, convKey, metad
|
|
|
120
115
|
}));
|
|
121
116
|
bridge.onClose(() => {
|
|
122
117
|
bridgeCloseController.dispose();
|
|
123
|
-
stopToolCallEndTimer();
|
|
124
118
|
clearInterval(heartbeatTimer);
|
|
125
119
|
syncStoredBlobStore(convKey, payload.blobStore);
|
|
126
120
|
const flushed = tagFilter.flush();
|
|
@@ -9,7 +9,6 @@ import { SSE_HEADERS } from "./sse";
|
|
|
9
9
|
import { computeUsage, createConnectFrameParser, createThinkingTagFilter, parseConnectEndStream, processServerMessage, scheduleBridgeEnd, } from "./stream-dispatch";
|
|
10
10
|
import { createBridgeCloseController } from "./bridge-close-controller";
|
|
11
11
|
const SSE_KEEPALIVE_INTERVAL_MS = 15_000;
|
|
12
|
-
const MCP_TOOL_BATCH_WINDOW_MS = 150;
|
|
13
12
|
function sortedIds(values) {
|
|
14
13
|
return [...values].sort();
|
|
15
14
|
}
|
|
@@ -17,7 +16,6 @@ function createBridgeStreamResponse(bridge, heartbeatTimer, blobStore, cloudRule
|
|
|
17
16
|
const completionId = `chatcmpl-${crypto.randomUUID().replace(/-/g, "").slice(0, 28)}`;
|
|
18
17
|
const created = Math.floor(Date.now() / 1000);
|
|
19
18
|
let keepaliveTimer;
|
|
20
|
-
let toolCallFlushTimer;
|
|
21
19
|
const bridgeCloseController = createBridgeCloseController(bridge);
|
|
22
20
|
const stopKeepalive = () => {
|
|
23
21
|
if (!keepaliveTimer)
|
|
@@ -25,12 +23,6 @@ function createBridgeStreamResponse(bridge, heartbeatTimer, blobStore, cloudRule
|
|
|
25
23
|
clearInterval(keepaliveTimer);
|
|
26
24
|
keepaliveTimer = undefined;
|
|
27
25
|
};
|
|
28
|
-
const stopToolCallFlushTimer = () => {
|
|
29
|
-
if (!toolCallFlushTimer)
|
|
30
|
-
return;
|
|
31
|
-
clearTimeout(toolCallFlushTimer);
|
|
32
|
-
toolCallFlushTimer = undefined;
|
|
33
|
-
};
|
|
34
26
|
const stream = new ReadableStream({
|
|
35
27
|
start(controller) {
|
|
36
28
|
const encoder = new TextEncoder();
|
|
@@ -80,7 +72,6 @@ function createBridgeStreamResponse(bridge, heartbeatTimer, blobStore, cloudRule
|
|
|
80
72
|
return;
|
|
81
73
|
closed = true;
|
|
82
74
|
stopKeepalive();
|
|
83
|
-
stopToolCallFlushTimer();
|
|
84
75
|
controller.close();
|
|
85
76
|
};
|
|
86
77
|
const makeChunk = (delta, finishReason = null) => ({
|
|
@@ -147,20 +138,20 @@ function createBridgeStreamResponse(bridge, heartbeatTimer, blobStore, cloudRule
|
|
|
147
138
|
],
|
|
148
139
|
}));
|
|
149
140
|
};
|
|
150
|
-
const publishPendingToolCalls = () => {
|
|
141
|
+
const publishPendingToolCalls = (source) => {
|
|
151
142
|
if (closed || toolCallsFlushed || state.pendingExecs.length === 0)
|
|
152
143
|
return;
|
|
153
144
|
logPluginInfo("Evaluating Cursor tool-call publish", {
|
|
154
145
|
modelId,
|
|
155
146
|
bridgeKey,
|
|
156
147
|
convKey,
|
|
148
|
+
source,
|
|
157
149
|
pendingExecToolCallIds: sortedIds(state.pendingExecs.map((exec) => exec.toolCallId)),
|
|
158
150
|
toolCallsFlushed,
|
|
159
151
|
mcpExecReceived,
|
|
160
152
|
nowMs: Date.now(),
|
|
161
153
|
});
|
|
162
154
|
toolCallsFlushed = true;
|
|
163
|
-
stopToolCallFlushTimer();
|
|
164
155
|
const flushed = tagFilter.flush();
|
|
165
156
|
if (flushed.reasoning)
|
|
166
157
|
sendSSE(makeChunk({ reasoning_content: flushed.reasoning }));
|
|
@@ -206,6 +197,7 @@ function createBridgeStreamResponse(bridge, heartbeatTimer, blobStore, cloudRule
|
|
|
206
197
|
modelId,
|
|
207
198
|
bridgeKey,
|
|
208
199
|
convKey,
|
|
200
|
+
source,
|
|
209
201
|
pendingExecToolCallIds: sortedIds(state.pendingExecs.map((exec) => exec.toolCallId)),
|
|
210
202
|
emittedToolCallIds: state.pendingExecs.map((exec) => exec.toolCallId),
|
|
211
203
|
assistantSeedTextLength: assistantSeedText.length,
|
|
@@ -235,19 +227,6 @@ function createBridgeStreamResponse(bridge, heartbeatTimer, blobStore, cloudRule
|
|
|
235
227
|
sendDone();
|
|
236
228
|
closeController();
|
|
237
229
|
};
|
|
238
|
-
const schedulePendingToolCallPublish = () => {
|
|
239
|
-
if (toolCallsFlushed)
|
|
240
|
-
return;
|
|
241
|
-
stopToolCallFlushTimer();
|
|
242
|
-
logPluginInfo("Scheduling Cursor tool-call publish", {
|
|
243
|
-
modelId,
|
|
244
|
-
bridgeKey,
|
|
245
|
-
convKey,
|
|
246
|
-
delayMs: MCP_TOOL_BATCH_WINDOW_MS,
|
|
247
|
-
pendingExecToolCallIds: sortedIds(state.pendingExecs.map((exec) => exec.toolCallId)),
|
|
248
|
-
});
|
|
249
|
-
toolCallFlushTimer = setTimeout(publishPendingToolCalls, MCP_TOOL_BATCH_WINDOW_MS);
|
|
250
|
-
};
|
|
251
230
|
const processChunk = createConnectFrameParser((messageBytes) => {
|
|
252
231
|
try {
|
|
253
232
|
const serverMessage = fromBinary(AgentServerMessageSchema, messageBytes);
|
|
@@ -309,7 +288,6 @@ function createBridgeStreamResponse(bridge, heartbeatTimer, blobStore, cloudRule
|
|
|
309
288
|
? sortedIds(existingActiveBridge.pendingExecs.map((candidate) => candidate.toolCallId))
|
|
310
289
|
: [],
|
|
311
290
|
});
|
|
312
|
-
schedulePendingToolCallPublish();
|
|
313
291
|
}, (info) => {
|
|
314
292
|
if (toolCallsFlushed) {
|
|
315
293
|
logPluginWarn("Received Cursor MCP interaction update after tool-call envelope was already published", {
|
|
@@ -335,20 +313,62 @@ function createBridgeStreamResponse(bridge, heartbeatTimer, blobStore, cloudRule
|
|
|
335
313
|
lastResumeAttemptAtMs: existingActiveBridge.diagnostics?.lastResumeAttemptAtMs,
|
|
336
314
|
};
|
|
337
315
|
}
|
|
338
|
-
|
|
316
|
+
}, (info) => {
|
|
317
|
+
const existingActiveBridge = activeBridges.get(bridgeKey);
|
|
318
|
+
if (existingActiveBridge) {
|
|
319
|
+
existingActiveBridge.diagnostics = {
|
|
320
|
+
announcedToolCallIds: existingActiveBridge.diagnostics?.announcedToolCallIds ?? [],
|
|
321
|
+
publishedToolCallIds: existingActiveBridge.diagnostics?.publishedToolCallIds ?? [],
|
|
322
|
+
lastMcpUpdate: info.updateCase === "stepCompleted"
|
|
323
|
+
? `${info.updateCase}:${info.stepId}:${info.stepDurationMs ?? "unknown"}`
|
|
324
|
+
: `${info.updateCase}:${info.stepId}`,
|
|
325
|
+
publishedAtMs: existingActiveBridge.diagnostics?.publishedAtMs,
|
|
326
|
+
lastResumeAttemptAtMs: existingActiveBridge.diagnostics?.lastResumeAttemptAtMs,
|
|
327
|
+
};
|
|
328
|
+
}
|
|
329
|
+
logPluginInfo("Tracking Cursor step boundary in streaming bridge", {
|
|
339
330
|
modelId,
|
|
340
331
|
bridgeKey,
|
|
341
332
|
convKey,
|
|
342
333
|
updateCase: info.updateCase,
|
|
343
|
-
|
|
334
|
+
stepId: info.stepId,
|
|
335
|
+
stepDurationMs: info.stepDurationMs,
|
|
336
|
+
toolCallsFlushed,
|
|
337
|
+
mcpExecReceived,
|
|
344
338
|
pendingExecToolCallIds: sortedIds(state.pendingExecs.map((candidate) => candidate.toolCallId)),
|
|
339
|
+
streamedToolCallIds: sortedIds(streamedToolCalls.keys()),
|
|
345
340
|
hasStoredActiveBridge: Boolean(existingActiveBridge),
|
|
341
|
+
storedActiveBridgePendingExecToolCallIds: existingActiveBridge
|
|
342
|
+
? sortedIds(existingActiveBridge.pendingExecs.map((candidate) => candidate.toolCallId))
|
|
343
|
+
: [],
|
|
346
344
|
storedActiveBridgeDiagnostics: existingActiveBridge?.diagnostics,
|
|
347
345
|
});
|
|
348
346
|
}, (checkpointBytes) => {
|
|
347
|
+
logPluginInfo("Received Cursor conversation checkpoint", {
|
|
348
|
+
modelId,
|
|
349
|
+
bridgeKey,
|
|
350
|
+
convKey,
|
|
351
|
+
toolCallsFlushed,
|
|
352
|
+
pendingExecToolCallIds: sortedIds(state.pendingExecs.map((candidate) => candidate.toolCallId)),
|
|
353
|
+
});
|
|
349
354
|
updateConversationCheckpoint(convKey, checkpointBytes);
|
|
350
355
|
bridgeCloseController.noteCheckpoint();
|
|
351
|
-
|
|
356
|
+
if (state.pendingExecs.length > 0 && !toolCallsFlushed) {
|
|
357
|
+
publishPendingToolCalls("checkpoint");
|
|
358
|
+
}
|
|
359
|
+
}, () => {
|
|
360
|
+
logPluginInfo("Received Cursor turn-ended signal", {
|
|
361
|
+
modelId,
|
|
362
|
+
bridgeKey,
|
|
363
|
+
convKey,
|
|
364
|
+
toolCallsFlushed,
|
|
365
|
+
pendingExecToolCallIds: sortedIds(state.pendingExecs.map((candidate) => candidate.toolCallId)),
|
|
366
|
+
});
|
|
367
|
+
bridgeCloseController.noteTurnEnded();
|
|
368
|
+
if (state.pendingExecs.length > 0 && !toolCallsFlushed) {
|
|
369
|
+
publishPendingToolCalls("turnEnded");
|
|
370
|
+
}
|
|
371
|
+
}, (info) => {
|
|
352
372
|
endStreamError = new Error(`Cursor returned unsupported ${info.category}: ${info.caseName}${info.detail ? ` (${info.detail})` : ""}`);
|
|
353
373
|
logPluginError("Closing Cursor bridge after unsupported message", {
|
|
354
374
|
modelId,
|
|
@@ -376,6 +396,15 @@ function createBridgeStreamResponse(bridge, heartbeatTimer, blobStore, cloudRule
|
|
|
376
396
|
// Skip unparseable messages.
|
|
377
397
|
}
|
|
378
398
|
}, (endStreamBytes) => {
|
|
399
|
+
logPluginInfo("Received Cursor end-of-stream signal", {
|
|
400
|
+
modelId,
|
|
401
|
+
bridgeKey,
|
|
402
|
+
convKey,
|
|
403
|
+
byteLength: endStreamBytes.length,
|
|
404
|
+
});
|
|
405
|
+
if (state.pendingExecs.length > 0 && !toolCallsFlushed) {
|
|
406
|
+
publishPendingToolCalls("endStream");
|
|
407
|
+
}
|
|
379
408
|
endStreamError = parseConnectEndStream(endStreamBytes);
|
|
380
409
|
if (endStreamError) {
|
|
381
410
|
logPluginError("Cursor stream returned Connect end-stream error", {
|
|
@@ -423,7 +452,6 @@ function createBridgeStreamResponse(bridge, heartbeatTimer, blobStore, cloudRule
|
|
|
423
452
|
bridgeCloseController.dispose();
|
|
424
453
|
clearInterval(heartbeatTimer);
|
|
425
454
|
stopKeepalive();
|
|
426
|
-
stopToolCallFlushTimer();
|
|
427
455
|
syncStoredBlobStore(convKey, blobStore);
|
|
428
456
|
if (endStreamError) {
|
|
429
457
|
activeBridges.delete(bridgeKey);
|
|
@@ -454,7 +482,6 @@ function createBridgeStreamResponse(bridge, heartbeatTimer, blobStore, cloudRule
|
|
|
454
482
|
cancel(reason) {
|
|
455
483
|
bridgeCloseController.dispose();
|
|
456
484
|
stopKeepalive();
|
|
457
|
-
stopToolCallFlushTimer();
|
|
458
485
|
clearInterval(heartbeatTimer);
|
|
459
486
|
syncStoredBlobStore(convKey, blobStore);
|
|
460
487
|
const active = activeBridges.get(bridgeKey);
|
|
@@ -18,6 +18,11 @@ export interface McpToolCallUpdateInfo {
|
|
|
18
18
|
modelCallId?: string;
|
|
19
19
|
toolName?: string;
|
|
20
20
|
}
|
|
21
|
+
export interface StepUpdateInfo {
|
|
22
|
+
updateCase: "stepStarted" | "stepCompleted";
|
|
23
|
+
stepId: string;
|
|
24
|
+
stepDurationMs?: string;
|
|
25
|
+
}
|
|
21
26
|
export declare function parseConnectEndStream(data: Uint8Array): Error | null;
|
|
22
27
|
export declare function makeHeartbeatBytes(): Uint8Array;
|
|
23
28
|
export declare function scheduleBridgeEnd(bridge: CursorSession): void;
|
|
@@ -45,4 +50,4 @@ export declare function computeUsage(state: StreamState): {
|
|
|
45
50
|
completion_tokens: number;
|
|
46
51
|
total_tokens: number;
|
|
47
52
|
};
|
|
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;
|
|
53
|
+
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, onStepUpdate?: (info: StepUpdateInfo) => void, onCheckpoint?: (checkpointBytes: Uint8Array) => void, onTurnEnded?: () => void, onUnsupportedMessage?: (info: UnsupportedServerMessageInfo) => void, onUnhandledExec?: (info: UnhandledExecInfo) => void): void;
|
|
@@ -128,10 +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, cloudRule, mcpTools, sendFrame, state, onText, onMcpExec, onMcpToolCallUpdate, onCheckpoint, onTurnEnded, onUnsupportedMessage, onUnhandledExec) {
|
|
131
|
+
export function processServerMessage(msg, blobStore, cloudRule, mcpTools, sendFrame, state, onText, onMcpExec, onMcpToolCallUpdate, onStepUpdate, onCheckpoint, onTurnEnded, onUnsupportedMessage, onUnhandledExec) {
|
|
132
132
|
const msgCase = msg.message.case;
|
|
133
|
+
logPluginInfo("Received Cursor server signal", {
|
|
134
|
+
messageCase: msgCase ?? "undefined",
|
|
135
|
+
interactionCase: msgCase === "interactionUpdate"
|
|
136
|
+
? msg.message.value.message?.case ?? "undefined"
|
|
137
|
+
: undefined,
|
|
138
|
+
execCase: msgCase === "execServerMessage"
|
|
139
|
+
? msg.message.value.message?.case ?? "undefined"
|
|
140
|
+
: undefined,
|
|
141
|
+
interactionQueryCase: msgCase === "interactionQuery"
|
|
142
|
+
? msg.message.value.query?.case ?? "undefined"
|
|
143
|
+
: undefined,
|
|
144
|
+
kvCase: msgCase === "kvServerMessage"
|
|
145
|
+
? msg.message.value.message?.case ?? "undefined"
|
|
146
|
+
: undefined,
|
|
147
|
+
});
|
|
133
148
|
if (msgCase === "interactionUpdate") {
|
|
134
|
-
handleInteractionUpdate(msg.message.value, state, onText, onMcpToolCallUpdate, onTurnEnded, onUnsupportedMessage);
|
|
149
|
+
handleInteractionUpdate(msg.message.value, state, onText, onMcpToolCallUpdate, onStepUpdate, onTurnEnded, onUnsupportedMessage);
|
|
135
150
|
}
|
|
136
151
|
else if (msgCase === "kvServerMessage") {
|
|
137
152
|
handleKvMessage(msg.message.value, blobStore, sendFrame);
|
|
@@ -164,19 +179,8 @@ export function processServerMessage(msg, blobStore, cloudRule, mcpTools, sendFr
|
|
|
164
179
|
});
|
|
165
180
|
}
|
|
166
181
|
}
|
|
167
|
-
function handleInteractionUpdate(update, state, onText, onMcpToolCallUpdate, onTurnEnded, onUnsupportedMessage) {
|
|
182
|
+
function handleInteractionUpdate(update, state, onText, onMcpToolCallUpdate, onStepUpdate, onTurnEnded, onUnsupportedMessage) {
|
|
168
183
|
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
184
|
if ((updateCase === "partialToolCall" ||
|
|
181
185
|
updateCase === "toolCallStarted" ||
|
|
182
186
|
updateCase === "toolCallCompleted") &&
|
|
@@ -193,6 +197,19 @@ function handleInteractionUpdate(update, state, onText, onMcpToolCallUpdate, onT
|
|
|
193
197
|
});
|
|
194
198
|
}
|
|
195
199
|
}
|
|
200
|
+
if (updateCase === "stepStarted" || updateCase === "stepCompleted") {
|
|
201
|
+
const stepValue = update.message?.value;
|
|
202
|
+
const stepId = stepValue?.stepId;
|
|
203
|
+
if (stepId !== undefined && stepId !== null) {
|
|
204
|
+
onStepUpdate?.({
|
|
205
|
+
updateCase,
|
|
206
|
+
stepId: String(stepId),
|
|
207
|
+
stepDurationMs: updateCase === "stepCompleted" && stepValue?.stepDurationMs !== undefined
|
|
208
|
+
? String(stepValue.stepDurationMs)
|
|
209
|
+
: undefined,
|
|
210
|
+
});
|
|
211
|
+
}
|
|
212
|
+
}
|
|
196
213
|
if (updateCase === "textDelta") {
|
|
197
214
|
const delta = update.message.value.text || "";
|
|
198
215
|
if (delta)
|
|
@@ -372,11 +389,6 @@ function handleKvMessage(kvMsg, blobStore, sendFrame) {
|
|
|
372
389
|
}
|
|
373
390
|
function handleExecMessage(execMsg, cloudRule, mcpTools, sendFrame, state, onMcpExec, onUnhandledExec) {
|
|
374
391
|
const execCase = execMsg.message.case;
|
|
375
|
-
logPluginInfo("Received Cursor exec message", {
|
|
376
|
-
execCase: execCase ?? "undefined",
|
|
377
|
-
execId: execMsg.execId,
|
|
378
|
-
execMsgId: execMsg.id,
|
|
379
|
-
});
|
|
380
392
|
if (execCase === "requestContextArgs") {
|
|
381
393
|
logPluginInfo("Responding to Cursor requestContextArgs", {
|
|
382
394
|
execId: execMsg.execId,
|
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.4a26f78d4622",
|
|
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",
|