@playwo/opencode-cursor-oauth 0.0.0-dev.7fe465ca080f → 0.0.0-dev.825419c3fcde
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/proxy/bridge-non-streaming.js +1 -3
- package/dist/proxy/bridge-streaming.js +8 -8
- package/dist/proxy/cursor-request.js +12 -15
- package/dist/proxy/stream-dispatch.d.ts +1 -1
- package/dist/proxy/stream-dispatch.js +22 -145
- package/dist/proxy/stream-state.d.ts +0 -2
- package/dist/proxy/types.d.ts +3 -1
- package/package.json +1 -1
|
@@ -38,14 +38,12 @@ async function collectFullResponse(payload, accessToken, modelId, convKey, metad
|
|
|
38
38
|
pendingExecs: [],
|
|
39
39
|
outputTokens: 0,
|
|
40
40
|
totalTokens: 0,
|
|
41
|
-
interactionToolArgsText: new Map(),
|
|
42
|
-
emittedToolCallIds: new Set(),
|
|
43
41
|
};
|
|
44
42
|
const tagFilter = createThinkingTagFilter();
|
|
45
43
|
bridge.onData(createConnectFrameParser((messageBytes) => {
|
|
46
44
|
try {
|
|
47
45
|
const serverMessage = fromBinary(AgentServerMessageSchema, messageBytes);
|
|
48
|
-
processServerMessage(serverMessage, payload.blobStore, payload.mcpTools, (data) => bridge.write(data), state, (text, isThinking) => {
|
|
46
|
+
processServerMessage(serverMessage, payload.blobStore, payload.cloudRule, payload.mcpTools, (data) => bridge.write(data), state, (text, isThinking) => {
|
|
49
47
|
if (isThinking)
|
|
50
48
|
return;
|
|
51
49
|
const { content } = tagFilter.process(text);
|
|
@@ -8,7 +8,7 @@ import { updateConversationCheckpoint, syncStoredBlobStore, } from "./state-sync
|
|
|
8
8
|
import { SSE_HEADERS } from "./sse";
|
|
9
9
|
import { computeUsage, createConnectFrameParser, createThinkingTagFilter, parseConnectEndStream, processServerMessage, scheduleBridgeEnd, } from "./stream-dispatch";
|
|
10
10
|
const SSE_KEEPALIVE_INTERVAL_MS = 15_000;
|
|
11
|
-
function createBridgeStreamResponse(bridge, heartbeatTimer, blobStore, mcpTools, modelId, bridgeKey, convKey, metadata) {
|
|
11
|
+
function createBridgeStreamResponse(bridge, heartbeatTimer, blobStore, cloudRule, mcpTools, modelId, bridgeKey, convKey, metadata) {
|
|
12
12
|
const completionId = `chatcmpl-${crypto.randomUUID().replace(/-/g, "").slice(0, 28)}`;
|
|
13
13
|
const created = Math.floor(Date.now() / 1000);
|
|
14
14
|
let keepaliveTimer;
|
|
@@ -27,8 +27,6 @@ function createBridgeStreamResponse(bridge, heartbeatTimer, blobStore, mcpTools,
|
|
|
27
27
|
pendingExecs: [],
|
|
28
28
|
outputTokens: 0,
|
|
29
29
|
totalTokens: 0,
|
|
30
|
-
interactionToolArgsText: new Map(),
|
|
31
|
-
emittedToolCallIds: new Set(),
|
|
32
30
|
};
|
|
33
31
|
const tagFilter = createThinkingTagFilter();
|
|
34
32
|
let assistantText = metadata.assistantSeedText ?? "";
|
|
@@ -90,7 +88,7 @@ function createBridgeStreamResponse(bridge, heartbeatTimer, blobStore, mcpTools,
|
|
|
90
88
|
const processChunk = createConnectFrameParser((messageBytes) => {
|
|
91
89
|
try {
|
|
92
90
|
const serverMessage = fromBinary(AgentServerMessageSchema, messageBytes);
|
|
93
|
-
processServerMessage(serverMessage, blobStore, mcpTools, (data) => bridge.write(data), state, (text, isThinking) => {
|
|
91
|
+
processServerMessage(serverMessage, blobStore, cloudRule, mcpTools, (data) => bridge.write(data), state, (text, isThinking) => {
|
|
94
92
|
if (isThinking) {
|
|
95
93
|
sendSSE(makeChunk({ reasoning_content: text }));
|
|
96
94
|
return;
|
|
@@ -148,6 +146,7 @@ function createBridgeStreamResponse(bridge, heartbeatTimer, blobStore, mcpTools,
|
|
|
148
146
|
bridge,
|
|
149
147
|
heartbeatTimer,
|
|
150
148
|
blobStore,
|
|
149
|
+
cloudRule,
|
|
151
150
|
mcpTools,
|
|
152
151
|
pendingExecs: state.pendingExecs,
|
|
153
152
|
modelId,
|
|
@@ -217,6 +216,7 @@ function createBridgeStreamResponse(bridge, heartbeatTimer, blobStore, mcpTools,
|
|
|
217
216
|
bridgeKey,
|
|
218
217
|
convKey,
|
|
219
218
|
mcpToolCount: mcpTools.length,
|
|
219
|
+
hasCloudRule: Boolean(cloudRule),
|
|
220
220
|
});
|
|
221
221
|
bridge.onData(processChunk);
|
|
222
222
|
bridge.onClose((code) => {
|
|
@@ -284,7 +284,7 @@ export async function handleStreamingResponse(payload, accessToken, modelId, bri
|
|
|
284
284
|
mcpToolCount: payload.mcpTools.length,
|
|
285
285
|
});
|
|
286
286
|
const { bridge, heartbeatTimer } = await startBridge(accessToken, payload.requestBytes);
|
|
287
|
-
return createBridgeStreamResponse(bridge, heartbeatTimer, payload.blobStore, payload.mcpTools, modelId, bridgeKey, convKey, metadata);
|
|
287
|
+
return createBridgeStreamResponse(bridge, heartbeatTimer, payload.blobStore, payload.cloudRule, payload.mcpTools, modelId, bridgeKey, convKey, metadata);
|
|
288
288
|
}
|
|
289
289
|
async function waitForResolvablePendingExecs(active, toolResults, timeoutMs = 2_000) {
|
|
290
290
|
const pendingToolCallIds = new Set(toolResults.map((result) => result.toolCallId));
|
|
@@ -306,7 +306,7 @@ async function waitForResolvablePendingExecs(active, toolResults, timeoutMs = 2_
|
|
|
306
306
|
return unresolved;
|
|
307
307
|
}
|
|
308
308
|
export async function handleToolResultResume(active, toolResults, bridgeKey, convKey) {
|
|
309
|
-
const { bridge, heartbeatTimer, blobStore, mcpTools, pendingExecs, modelId, metadata, } = active;
|
|
309
|
+
const { bridge, heartbeatTimer, blobStore, cloudRule, mcpTools, pendingExecs, modelId, metadata, } = active;
|
|
310
310
|
const resumeMetadata = {
|
|
311
311
|
...metadata,
|
|
312
312
|
assistantSeedText: [
|
|
@@ -341,7 +341,7 @@ export async function handleToolResultResume(active, toolResults, bridgeKey, con
|
|
|
341
341
|
type: "invalid_request_error",
|
|
342
342
|
code: "cursor_missing_exec_metadata",
|
|
343
343
|
},
|
|
344
|
-
}), { status:
|
|
344
|
+
}), { status: 400, headers: { "Content-Type": "application/json" } });
|
|
345
345
|
}
|
|
346
346
|
for (const exec of pendingExecs) {
|
|
347
347
|
const result = toolResults.find((toolResult) => toolResult.toolCallId === exec.toolCallId);
|
|
@@ -398,5 +398,5 @@ export async function handleToolResultResume(active, toolResults, bridgeKey, con
|
|
|
398
398
|
});
|
|
399
399
|
bridge.write(toBinary(AgentClientMessageSchema, clientMessage));
|
|
400
400
|
}
|
|
401
|
-
return createBridgeStreamResponse(bridge, heartbeatTimer, blobStore, mcpTools, modelId, bridgeKey, convKey, resumeMetadata);
|
|
401
|
+
return createBridgeStreamResponse(bridge, heartbeatTimer, blobStore, cloudRule, mcpTools, modelId, bridgeKey, convKey, resumeMetadata);
|
|
402
402
|
}
|
|
@@ -1,13 +1,8 @@
|
|
|
1
1
|
import { create, fromBinary, toBinary } from "@bufbuild/protobuf";
|
|
2
|
-
import {
|
|
3
|
-
import { AgentClientMessageSchema, AgentRunRequestSchema, ConversationActionSchema, ConversationStateStructureSchema, ConversationStepSchema, AgentConversationTurnStructureSchema, ConversationTurnStructureSchema, AssistantMessageSchema, ModelDetailsSchema, ResumeActionSchema, UserMessageActionSchema, UserMessageSchema, } from "../proto/agent_pb";
|
|
2
|
+
import { AgentClientMessageSchema, AgentRunRequestSchema, AgentConversationTurnStructureSchema, AssistantMessageSchema, ConversationActionSchema, ConversationStateStructureSchema, ConversationTurnStructureSchema, ConversationStepSchema, ModelDetailsSchema, ResumeActionSchema, UserMessageActionSchema, UserMessageSchema, } from "../proto/agent_pb";
|
|
4
3
|
export function buildCursorRequest(modelId, systemPrompt, userText, turns, conversationId, checkpoint, existingBlobStore) {
|
|
5
4
|
const blobStore = new Map(existingBlobStore ?? []);
|
|
6
|
-
|
|
7
|
-
const systemJson = JSON.stringify({ role: "system", content: systemPrompt });
|
|
8
|
-
const systemBytes = new TextEncoder().encode(systemJson);
|
|
9
|
-
const systemBlobId = new Uint8Array(createHash("sha256").update(systemBytes).digest());
|
|
10
|
-
blobStore.set(Buffer.from(systemBlobId).toString("hex"), systemBytes);
|
|
5
|
+
const cloudRule = buildCloudRule(systemPrompt);
|
|
11
6
|
let conversationState;
|
|
12
7
|
if (checkpoint) {
|
|
13
8
|
conversationState = fromBinary(ConversationStateStructureSchema, checkpoint);
|
|
@@ -40,7 +35,7 @@ export function buildCursorRequest(modelId, systemPrompt, userText, turns, conve
|
|
|
40
35
|
turnBytes.push(toBinary(ConversationTurnStructureSchema, turnStructure));
|
|
41
36
|
}
|
|
42
37
|
conversationState = create(ConversationStateStructureSchema, {
|
|
43
|
-
rootPromptMessagesJson: [
|
|
38
|
+
rootPromptMessagesJson: [],
|
|
44
39
|
turns: turnBytes,
|
|
45
40
|
todos: [],
|
|
46
41
|
pendingToolCalls: [],
|
|
@@ -64,14 +59,11 @@ export function buildCursorRequest(modelId, systemPrompt, userText, turns, conve
|
|
|
64
59
|
value: create(UserMessageActionSchema, { userMessage }),
|
|
65
60
|
},
|
|
66
61
|
});
|
|
67
|
-
return buildRunRequest(modelId, conversationId, conversationState, action, blobStore);
|
|
62
|
+
return buildRunRequest(modelId, conversationId, conversationState, action, blobStore, cloudRule);
|
|
68
63
|
}
|
|
69
64
|
export function buildCursorResumeRequest(modelId, systemPrompt, conversationId, checkpoint, existingBlobStore) {
|
|
70
65
|
const blobStore = new Map(existingBlobStore ?? []);
|
|
71
|
-
const
|
|
72
|
-
const systemBytes = new TextEncoder().encode(systemJson);
|
|
73
|
-
const systemBlobId = new Uint8Array(createHash("sha256").update(systemBytes).digest());
|
|
74
|
-
blobStore.set(Buffer.from(systemBlobId).toString("hex"), systemBytes);
|
|
66
|
+
const cloudRule = buildCloudRule(systemPrompt);
|
|
75
67
|
const conversationState = fromBinary(ConversationStateStructureSchema, checkpoint);
|
|
76
68
|
const action = create(ConversationActionSchema, {
|
|
77
69
|
action: {
|
|
@@ -79,9 +71,9 @@ export function buildCursorResumeRequest(modelId, systemPrompt, conversationId,
|
|
|
79
71
|
value: create(ResumeActionSchema, {}),
|
|
80
72
|
},
|
|
81
73
|
});
|
|
82
|
-
return buildRunRequest(modelId, conversationId, conversationState, action, blobStore);
|
|
74
|
+
return buildRunRequest(modelId, conversationId, conversationState, action, blobStore, cloudRule);
|
|
83
75
|
}
|
|
84
|
-
function buildRunRequest(modelId, conversationId, conversationState, action, blobStore) {
|
|
76
|
+
function buildRunRequest(modelId, conversationId, conversationState, action, blobStore, cloudRule) {
|
|
85
77
|
const modelDetails = create(ModelDetailsSchema, {
|
|
86
78
|
modelId,
|
|
87
79
|
displayModelId: modelId,
|
|
@@ -99,6 +91,11 @@ function buildRunRequest(modelId, conversationId, conversationState, action, blo
|
|
|
99
91
|
return {
|
|
100
92
|
requestBytes: toBinary(AgentClientMessageSchema, clientMessage),
|
|
101
93
|
blobStore,
|
|
94
|
+
cloudRule,
|
|
102
95
|
mcpTools: [],
|
|
103
96
|
};
|
|
104
97
|
}
|
|
98
|
+
function buildCloudRule(systemPrompt) {
|
|
99
|
+
const content = systemPrompt.trim();
|
|
100
|
+
return content || undefined;
|
|
101
|
+
}
|
|
@@ -39,4 +39,4 @@ export declare function computeUsage(state: StreamState): {
|
|
|
39
39
|
completion_tokens: number;
|
|
40
40
|
total_tokens: number;
|
|
41
41
|
};
|
|
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;
|
|
42
|
+
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, onCheckpoint?: (checkpointBytes: Uint8Array) => void, onTurnEnded?: () => void, onUnsupportedMessage?: (info: UnsupportedServerMessageInfo) => void, onUnhandledExec?: (info: UnhandledExecInfo) => void): void;
|
|
@@ -128,98 +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
|
-
function
|
|
132
|
-
const existingIndex = state.pendingExecs.findIndex((candidate) => candidate.toolCallId === exec.toolCallId);
|
|
133
|
-
if (existingIndex >= 0) {
|
|
134
|
-
state.pendingExecs[existingIndex] = exec;
|
|
135
|
-
return;
|
|
136
|
-
}
|
|
137
|
-
state.pendingExecs.push(exec);
|
|
138
|
-
}
|
|
139
|
-
function hasUsableDecodedArgs(decodedArgs) {
|
|
140
|
-
const trimmed = decodedArgs.trim();
|
|
141
|
-
return trimmed !== "" && trimmed !== "{}";
|
|
142
|
-
}
|
|
143
|
-
function mergePendingExec(existing, incoming) {
|
|
144
|
-
const incomingHasExecMetadata = incoming.execMsgId !== 0;
|
|
145
|
-
const existingHasExecMetadata = existing.execMsgId !== 0;
|
|
146
|
-
return {
|
|
147
|
-
execId: incomingHasExecMetadata || !existing.execId ? incoming.execId : existing.execId,
|
|
148
|
-
execMsgId: incomingHasExecMetadata || !existingHasExecMetadata
|
|
149
|
-
? incoming.execMsgId
|
|
150
|
-
: existing.execMsgId,
|
|
151
|
-
toolCallId: existing.toolCallId || incoming.toolCallId,
|
|
152
|
-
toolName: incoming.toolName && incoming.toolName !== "unknown_mcp_tool"
|
|
153
|
-
? incoming.toolName
|
|
154
|
-
: existing.toolName,
|
|
155
|
-
decodedArgs: hasUsableDecodedArgs(incoming.decodedArgs)
|
|
156
|
-
? incoming.decodedArgs
|
|
157
|
-
: existing.decodedArgs,
|
|
158
|
-
source: incomingHasExecMetadata ? incoming.source : existing.source ?? incoming.source,
|
|
159
|
-
cursorCallId: existing.cursorCallId || incoming.cursorCallId,
|
|
160
|
-
modelCallId: existing.modelCallId || incoming.modelCallId,
|
|
161
|
-
};
|
|
162
|
-
}
|
|
163
|
-
function emitPendingExec(exec, state, onMcpExec) {
|
|
164
|
-
const existing = state.pendingExecs.find((candidate) => candidate.toolCallId === exec.toolCallId);
|
|
165
|
-
const nextExec = existing ? mergePendingExec(existing, exec) : exec;
|
|
166
|
-
const hadActionableMetadata = (existing?.execMsgId ?? 0) !== 0;
|
|
167
|
-
const hasActionableMetadata = nextExec.execMsgId !== 0;
|
|
168
|
-
if (state.emittedToolCallIds.has(nextExec.toolCallId)) {
|
|
169
|
-
replacePendingExec(state, nextExec);
|
|
170
|
-
if (!hadActionableMetadata && hasActionableMetadata) {
|
|
171
|
-
logPluginInfo("Cursor MCP tool call metadata upgraded", {
|
|
172
|
-
toolCallId: nextExec.toolCallId,
|
|
173
|
-
toolName: nextExec.toolName,
|
|
174
|
-
source: nextExec.source,
|
|
175
|
-
execId: nextExec.execId,
|
|
176
|
-
execMsgId: nextExec.execMsgId,
|
|
177
|
-
cursorCallId: nextExec.cursorCallId,
|
|
178
|
-
modelCallId: nextExec.modelCallId,
|
|
179
|
-
});
|
|
180
|
-
}
|
|
181
|
-
else {
|
|
182
|
-
logPluginInfo("Ignored duplicate Cursor MCP tool call event", {
|
|
183
|
-
toolCallId: nextExec.toolCallId,
|
|
184
|
-
toolName: nextExec.toolName,
|
|
185
|
-
source: nextExec.source,
|
|
186
|
-
execId: nextExec.execId,
|
|
187
|
-
execMsgId: nextExec.execMsgId,
|
|
188
|
-
cursorCallId: nextExec.cursorCallId,
|
|
189
|
-
modelCallId: nextExec.modelCallId,
|
|
190
|
-
});
|
|
191
|
-
}
|
|
192
|
-
return;
|
|
193
|
-
}
|
|
194
|
-
state.emittedToolCallIds.add(nextExec.toolCallId);
|
|
195
|
-
replacePendingExec(state, nextExec);
|
|
196
|
-
logPluginInfo("Emitting Cursor MCP tool call", {
|
|
197
|
-
toolCallId: nextExec.toolCallId,
|
|
198
|
-
toolName: nextExec.toolName,
|
|
199
|
-
source: nextExec.source,
|
|
200
|
-
execId: nextExec.execId,
|
|
201
|
-
execMsgId: nextExec.execMsgId,
|
|
202
|
-
cursorCallId: nextExec.cursorCallId,
|
|
203
|
-
modelCallId: nextExec.modelCallId,
|
|
204
|
-
decodedArgs: nextExec.decodedArgs,
|
|
205
|
-
});
|
|
206
|
-
onMcpExec(nextExec);
|
|
207
|
-
}
|
|
208
|
-
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) {
|
|
209
132
|
const msgCase = msg.message.case;
|
|
210
|
-
if (msgCase !== "conversationCheckpointUpdate") {
|
|
211
|
-
logPluginInfo("Received Cursor server message", {
|
|
212
|
-
messageCase: msgCase ?? "undefined",
|
|
213
|
-
});
|
|
214
|
-
}
|
|
215
133
|
if (msgCase === "interactionUpdate") {
|
|
216
|
-
handleInteractionUpdate(msg.message.value, state, onText,
|
|
134
|
+
handleInteractionUpdate(msg.message.value, state, onText, onTurnEnded, onUnsupportedMessage);
|
|
217
135
|
}
|
|
218
136
|
else if (msgCase === "kvServerMessage") {
|
|
219
137
|
handleKvMessage(msg.message.value, blobStore, sendFrame);
|
|
220
138
|
}
|
|
221
139
|
else if (msgCase === "execServerMessage") {
|
|
222
|
-
handleExecMessage(msg.message.value, mcpTools, sendFrame, state, onMcpExec, onUnhandledExec);
|
|
140
|
+
handleExecMessage(msg.message.value, cloudRule, mcpTools, sendFrame, state, onMcpExec, onUnhandledExec);
|
|
223
141
|
}
|
|
224
142
|
else if (msgCase === "execServerControlMessage") {
|
|
225
143
|
onUnsupportedMessage?.({
|
|
@@ -246,11 +164,12 @@ export function processServerMessage(msg, blobStore, mcpTools, sendFrame, state,
|
|
|
246
164
|
});
|
|
247
165
|
}
|
|
248
166
|
}
|
|
249
|
-
function handleInteractionUpdate(update, state, onText,
|
|
167
|
+
function handleInteractionUpdate(update, state, onText, onTurnEnded, onUnsupportedMessage) {
|
|
250
168
|
const updateCase = update.message?.case;
|
|
251
|
-
if (updateCase
|
|
252
|
-
updateCase
|
|
253
|
-
updateCase
|
|
169
|
+
if (updateCase === "partialToolCall" ||
|
|
170
|
+
updateCase === "toolCallStarted" ||
|
|
171
|
+
updateCase === "toolCallCompleted" ||
|
|
172
|
+
updateCase === "turnEnded") {
|
|
254
173
|
logPluginInfo("Received Cursor interaction update", {
|
|
255
174
|
updateCase: updateCase ?? "undefined",
|
|
256
175
|
callId: update.message?.value?.callId,
|
|
@@ -272,26 +191,18 @@ function handleInteractionUpdate(update, state, onText, onMcpExec, onTurnEnded,
|
|
|
272
191
|
state.outputTokens += update.message.value.tokens ?? 0;
|
|
273
192
|
}
|
|
274
193
|
else if (updateCase === "partialToolCall") {
|
|
275
|
-
|
|
276
|
-
if (partial.callId && partial.argsTextDelta) {
|
|
277
|
-
const existing = state.interactionToolArgsText.get(partial.callId) ?? "";
|
|
278
|
-
state.interactionToolArgsText.set(partial.callId, `${existing}${partial.argsTextDelta}`);
|
|
279
|
-
}
|
|
194
|
+
return;
|
|
280
195
|
}
|
|
281
196
|
else if (updateCase === "toolCallCompleted") {
|
|
282
|
-
const
|
|
283
|
-
if (
|
|
284
|
-
logPluginInfo("
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
cursorCallId: exec.cursorCallId,
|
|
291
|
-
modelCallId: exec.modelCallId,
|
|
292
|
-
decodedArgs: exec.decodedArgs,
|
|
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,
|
|
293
205
|
});
|
|
294
|
-
emitPendingExec(exec, state, onMcpExec);
|
|
295
206
|
}
|
|
296
207
|
}
|
|
297
208
|
else if (updateCase === "turnEnded") {
|
|
@@ -315,43 +226,8 @@ function handleInteractionUpdate(update, state, onText, onMcpExec, onTurnEnded,
|
|
|
315
226
|
caseName: updateCase ?? "undefined",
|
|
316
227
|
});
|
|
317
228
|
}
|
|
318
|
-
//
|
|
319
|
-
//
|
|
320
|
-
// calls may still appear here on some models, so we surface those, but we
|
|
321
|
-
// do not abort the bridge for native Cursor tool-call progress events.
|
|
322
|
-
}
|
|
323
|
-
function decodeInteractionToolCall(update, state) {
|
|
324
|
-
const callId = update.callId ?? "";
|
|
325
|
-
const toolCase = update.toolCall?.tool?.case;
|
|
326
|
-
if (toolCase !== "mcpToolCall")
|
|
327
|
-
return null;
|
|
328
|
-
const mcpArgs = update.toolCall?.tool?.value?.args;
|
|
329
|
-
if (!mcpArgs)
|
|
330
|
-
return null;
|
|
331
|
-
const toolCallId = mcpArgs.toolCallId || callId || crypto.randomUUID();
|
|
332
|
-
const decodedMap = decodeMcpArgsMap(mcpArgs.args ?? {});
|
|
333
|
-
const partialArgsText = callId
|
|
334
|
-
? state.interactionToolArgsText.get(callId)?.trim()
|
|
335
|
-
: undefined;
|
|
336
|
-
let decodedArgs = "{}";
|
|
337
|
-
if (Object.keys(decodedMap).length > 0) {
|
|
338
|
-
decodedArgs = JSON.stringify(decodedMap);
|
|
339
|
-
}
|
|
340
|
-
else if (partialArgsText) {
|
|
341
|
-
decodedArgs = partialArgsText;
|
|
342
|
-
}
|
|
343
|
-
if (callId)
|
|
344
|
-
state.interactionToolArgsText.delete(callId);
|
|
345
|
-
return {
|
|
346
|
-
execId: callId || toolCallId,
|
|
347
|
-
execMsgId: 0,
|
|
348
|
-
toolCallId,
|
|
349
|
-
toolName: mcpArgs.toolName || mcpArgs.name || "unknown_mcp_tool",
|
|
350
|
-
decodedArgs,
|
|
351
|
-
source: "interaction",
|
|
352
|
-
cursorCallId: callId || undefined,
|
|
353
|
-
modelCallId: update.modelCallId,
|
|
354
|
-
};
|
|
229
|
+
// Interaction tool-call updates are informational only. Resumable MCP tool
|
|
230
|
+
// execution comes from execServerMessage.mcpArgs.
|
|
355
231
|
}
|
|
356
232
|
function handleInteractionQuery(query, sendFrame, onUnsupportedMessage) {
|
|
357
233
|
const queryCase = query.query.case;
|
|
@@ -478,7 +354,7 @@ function handleKvMessage(kvMsg, blobStore, sendFrame) {
|
|
|
478
354
|
sendKvResponse(kvMsg, "setBlobResult", create(SetBlobResultSchema, {}), sendFrame);
|
|
479
355
|
}
|
|
480
356
|
}
|
|
481
|
-
function handleExecMessage(execMsg, mcpTools, sendFrame, state, onMcpExec, onUnhandledExec) {
|
|
357
|
+
function handleExecMessage(execMsg, cloudRule, mcpTools, sendFrame, state, onMcpExec, onUnhandledExec) {
|
|
482
358
|
const execCase = execMsg.message.case;
|
|
483
359
|
logPluginInfo("Received Cursor exec message", {
|
|
484
360
|
execCase: execCase ?? "undefined",
|
|
@@ -498,6 +374,7 @@ function handleExecMessage(execMsg, mcpTools, sendFrame, state, onMcpExec, onUnh
|
|
|
498
374
|
gitRepos: [],
|
|
499
375
|
projectLayouts: [],
|
|
500
376
|
mcpInstructions: [],
|
|
377
|
+
cloudRule,
|
|
501
378
|
fileContents: {},
|
|
502
379
|
customSubagents: [],
|
|
503
380
|
});
|
|
@@ -529,7 +406,7 @@ function handleExecMessage(execMsg, mcpTools, sendFrame, state, onMcpExec, onUnh
|
|
|
529
406
|
execMsgId: exec.execMsgId,
|
|
530
407
|
decodedArgs: exec.decodedArgs,
|
|
531
408
|
});
|
|
532
|
-
|
|
409
|
+
onMcpExec(exec);
|
|
533
410
|
return;
|
|
534
411
|
}
|
|
535
412
|
// --- Reject native Cursor tools ---
|
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. */
|
|
@@ -23,6 +24,7 @@ export interface ActiveBridge {
|
|
|
23
24
|
bridge: CursorSession;
|
|
24
25
|
heartbeatTimer: NodeJS.Timeout;
|
|
25
26
|
blobStore: Map<string, Uint8Array>;
|
|
27
|
+
cloudRule?: string;
|
|
26
28
|
mcpTools: McpToolDefinition[];
|
|
27
29
|
pendingExecs: PendingExec[];
|
|
28
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.825419c3fcde",
|
|
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",
|