From ca0a51246bc0d8a5ac2278d041cf729cff334ce0 Mon Sep 17 00:00:00 2001 From: Wibias <37517432+Wibias@users.noreply.github.com> Date: Sat, 15 Aug 2026 04:13:12 +0200 Subject: [PATCH] test(adapters): derive routed tool conformance from registry --- tests/adapter-tool-conformance.test.ts | 441 ++++++++++++++++++ .../adapter-conformance/wire-drivers.ts | 282 +++++++++++ 2 files changed, 723 insertions(+) create mode 100644 tests/adapter-tool-conformance.test.ts create mode 100644 tests/helpers/adapter-conformance/wire-drivers.ts diff --git a/tests/adapter-tool-conformance.test.ts b/tests/adapter-tool-conformance.test.ts new file mode 100644 index 0000000000..54483543f7 --- /dev/null +++ b/tests/adapter-tool-conformance.test.ts @@ -0,0 +1,441 @@ +import { describe, expect, test } from "bun:test"; +import { + adapterDefinitions, + createRegisteredAdapter, + effectiveAdapterContract, + getAdapterDefinition, + type AdapterWire, +} from "../src/adapters/registry"; +import { resetMimoJwtCache } from "../src/adapters/mimo-free"; +import { bridgeToResponsesSSE } from "../src/bridge"; +import { PROVIDER_REGISTRY } from "../src/providers/registry"; +import { parseRequest } from "../src/responses/parser"; +import { buildToolBridgeMaps } from "../src/server/responses"; +import { MODEL_ADAPTER_OVERRIDE_ALLOWED, type OcxParsedRequest, type OcxProviderConfig } from "../src/types"; +import { TOOL_WIRE_DRIVERS } from "./helpers/adapter-conformance/wire-drivers"; +import { createTestTranslatorBudget } from "./helpers/translator-budget"; + +const PATCH = `*** Begin Patch +*** Add File: conformance-μ•ˆλ…•.txt ++quote: "double" ++slash: \\ path ++unicode: δΈ–η•Œ +*** End Patch`; + +const EXEC_DESCRIPTION = + "Run JavaScript. declare const tools: { apply_patch(input: string): Promise; };"; + +const WIRE_MODELS: Record = { + "openai-chat": "grok-4.6", + anthropic: "claude-haiku-4-5", + google: "gemini-3.5-flash", + "command-code": "deepseek/deepseek-v4-flash", + kiro: "claude-sonnet-4.5", + "openai-responses": "deepseek-v4-flash", + cursor: "cursor/auto", +}; + +function providerFixture(adapterId: string, wire: AdapterWire): OcxProviderConfig { + const baseUrls: Record = { + "openai-chat": "https://api.x.ai/v1", + anthropic: "https://api.anthropic.com", + google: "https://generativelanguage.googleapis.com", + "command-code": "https://api.commandcode.ai", + kiro: "https://runtime.us-east-1.kiro.dev", + "openai-responses": "https://api.deepseek.com", + cursor: "https://api2.cursor.sh", + }; + // Semantic wrappers with provider-specific URL shapes must override the wire-family default here. + const baseUrl = adapterId === "mimo-free" + ? "https://api.xiaomimimo.com/api/free-ai/openai" + : adapterId === "azure" || adapterId === "azure-openai" + ? "https://example.openai.azure.com/openai/v1" + : baseUrls[wire]; + return { + adapter: adapterId, + baseUrl, + authMode: wire === "anthropic" || wire === "command-code" ? "oauth" : "key", + apiKey: wire === "kiro" ? "ksk_test" : "test-key", + defaultMaxOutputTokens: 64_000, + googleMode: "ai-studio", + ...(wire === "openai-responses" ? { responsesPath: "/responses" } : {}), + } satisfies OcxProviderConfig; +} + +function prepareForWire(parsed: OcxParsedRequest, wire: AdapterWire): OcxParsedRequest { + if (wire !== "kiro") return parsed; + return { ...parsed, _kiroAuthContext: { apiRegion: "us-east-1" } }; +} + +function codeModeParsed(wire: AdapterWire): OcxParsedRequest { + const model = WIRE_MODELS[wire]; + return prepareForWire(parseRequest({ + model, + instructions: "Use apply_patch for local file edits.", + input: "Patch the requested file.", + stream: true, + tools: [ + { + type: "custom", + name: "exec", + description: EXEC_DESCRIPTION, + format: { type: "grammar", syntax: "lark" }, + }, + { + type: "function", + name: "wait", + description: "Wait for work.", + parameters: { type: "object", properties: {}, additionalProperties: false }, + }, + ], + }), wire); +} + +function freeformParsed(wire: AdapterWire): OcxParsedRequest { + return prepareForWire(parseRequest({ + model: WIRE_MODELS[wire], + input: "Apply the exact patch.", + stream: true, + tools: [{ type: "custom", name: "apply_patch", description: "Apply a patch" }], + }), wire); +} + +function toolChoiceParsed(wire: AdapterWire, toolChoice?: "none"): OcxParsedRequest { + return prepareForWire(parseRequest({ + model: WIRE_MODELS[wire], + input: "Do not call a tool.", + stream: true, + ...(toolChoice ? { tool_choice: toolChoice } : {}), + tools: [ + { type: "custom", name: "apply_patch", description: "Apply a patch" }, + { + type: "function", + name: "noop", + description: "No operation", + parameters: { type: "object", properties: {}, additionalProperties: false }, + }, + ], + }), wire); +} + +function continuationParsed(wire: AdapterWire): OcxParsedRequest { + return prepareForWire(parseRequest({ + model: WIRE_MODELS[wire], + input: [ + { + type: "message", + role: "user", + content: [{ type: "input_text", text: "Apply the patch exactly." }], + }, + { + type: "custom_tool_call", + id: "ctc_patch", + call_id: "call_continue_patch", + name: "apply_patch", + input: PATCH, + }, + { + type: "custom_tool_call_output", + call_id: "call_continue_patch", + output: "Done!", + }, + { + type: "message", + role: "user", + content: [{ type: "input_text", text: "Continue after patch." }], + }, + ], + stream: true, + tools: [{ type: "custom", name: "apply_patch", description: "Apply a patch" }], + }), wire); +} + +async function withMimoBootstrap(adapterId: string, run: () => Promise): Promise { + if (adapterId !== "mimo-free") return await run(); + const originalFetch = globalThis.fetch; + resetMimoJwtCache(); + let bootstrapCalls = 0; + globalThis.fetch = (async (input: RequestInfo | URL) => { + const url = typeof input === "string" + ? input + : input instanceof URL + ? input.href + : input.url; + if (url !== "https://api.xiaomimimo.com/api/free-ai/bootstrap") { + throw new Error(`mimo-free conformance made an unexpected request: ${url}`); + } + bootstrapCalls++; + return new Response(JSON.stringify({ + jwt: "e30.eyJleHAiOjQxMDI0NDQ4MDB9.x", + }), { + status: 200, + headers: { "content-type": "application/json" }, + }); + }) as typeof fetch; + try { + const result = await run(); + if (bootstrapCalls !== 1) { + throw new Error(`expected one MiMo bootstrap request, got ${bootstrapCalls}`); + } + return result; + } finally { + globalThis.fetch = originalFetch; + resetMimoJwtCache(); + } +} + +async function outbound(adapterId: string, parsed: OcxParsedRequest): Promise { + const contract = effectiveAdapterContract(adapterId); + const adapter = createRegisteredAdapter(providerFixture(adapterId, contract.wire)); + return await withMimoBootstrap(adapterId, () => TOOL_WIRE_DRIVERS[contract.wire].observeOutbound(adapter, parsed)); +} + +function advertisedToolNames(wire: AdapterWire, body: string): string[] { + const parsed = JSON.parse(body) as Record; + if (wire === "openai-chat") { + const tools = parsed.tools as Array<{ function?: { name?: string } }> | undefined; + return (tools ?? []).flatMap(tool => typeof tool.function?.name === "string" ? [tool.function.name] : []); + } + if (wire === "anthropic" || wire === "openai-responses" || wire === "cursor") { + const tools = parsed.tools as Array<{ name?: string }> | undefined; + return (tools ?? []).flatMap(tool => typeof tool.name === "string" ? [tool.name] : []); + } + if (wire === "google") { + const tools = parsed.tools as Array<{ functionDeclarations?: Array<{ name?: string }> }> | undefined; + return (tools ?? []).flatMap(group => + (group.functionDeclarations ?? []).flatMap(tool => typeof tool.name === "string" ? [tool.name] : [])); + } + if (wire === "command-code") { + const params = parsed.params as { tools?: Array<{ name?: string }> } | undefined; + return (params?.tools ?? []).flatMap(tool => typeof tool.name === "string" ? [tool.name] : []); + } + const state = parsed.conversationState as { + currentMessage?: { + userInputMessage?: { + userInputMessageContext?: { + tools?: Array<{ toolSpecification?: { name?: string } }>; + }; + }; + }; + } | undefined; + const tools = state?.currentMessage?.userInputMessage?.userInputMessageContext?.tools ?? []; + return tools.flatMap(tool => typeof tool.toolSpecification?.name === "string" ? [tool.toolSpecification.name] : []); +} + +function toolCallsDisabled(wire: AdapterWire, body: string): boolean { + if (advertisedToolNames(wire, body).length === 0) return true; + const parsed = JSON.parse(body) as Record; + if (wire === "openai-chat" || wire === "openai-responses") return parsed.tool_choice === "none"; + if (wire === "anthropic") { + const choice = parsed.tool_choice as { type?: unknown } | undefined; + return choice?.type === "none"; + } + if (wire === "google") { + const config = parsed.toolConfig as { functionCallingConfig?: { mode?: unknown } } | undefined; + return config?.functionCallingConfig?.mode === "NONE"; + } + return false; +} + +function inputFromValue(value: unknown): string | undefined { + if (typeof value === "string") { + try { + const row = JSON.parse(value) as { input?: unknown }; + return typeof row.input === "string" ? row.input : value; + } catch { + return value; + } + } + if (value && typeof value === "object" && !Array.isArray(value)) { + const input = (value as Record).input; + if (typeof input === "string") return input; + } + return undefined; +} + +function continuationInput(wire: AdapterWire, body: string): string | undefined { + const parsed = JSON.parse(body) as Record; + if (wire === "openai-chat") { + const messages = parsed.messages as Array<{ tool_calls?: Array<{ function?: { name?: string; arguments?: unknown } }> }> | undefined; + for (const message of messages ?? []) { + for (const call of message.tool_calls ?? []) { + if (call.function?.name?.includes("apply_patch")) return inputFromValue(call.function.arguments); + } + } + return undefined; + } + if (wire === "anthropic") { + const messages = parsed.messages as Array<{ content?: unknown }> | undefined; + for (const message of messages ?? []) { + if (!Array.isArray(message.content)) continue; + for (const block of message.content) { + if (!block || typeof block !== "object" || Array.isArray(block)) continue; + const row = block as Record; + if (row.type === "tool_use" && typeof row.name === "string" && row.name.includes("apply_patch")) { + return inputFromValue(row.input); + } + } + } + return undefined; + } + if (wire === "google") { + const contents = parsed.contents as Array<{ parts?: Array<{ functionCall?: { name?: string; args?: unknown } }> }> | undefined; + for (const content of contents ?? []) { + for (const part of content.parts ?? []) { + if (part.functionCall?.name?.includes("apply_patch")) return inputFromValue(part.functionCall.args); + } + } + return undefined; + } + if (wire === "command-code") { + const params = parsed.params as { messages?: Array<{ content?: Array> }> } | undefined; + for (const message of params?.messages ?? []) { + for (const part of message.content ?? []) { + if (part.type === "tool-call" && typeof part.toolName === "string" && part.toolName.includes("apply_patch")) { + return inputFromValue(part.input); + } + } + } + return undefined; + } + if (wire === "kiro") { + const state = parsed.conversationState as { + history?: Array<{ assistantResponseMessage?: { toolUses?: Array<{ name?: string; input?: unknown }> } }>; + currentMessage?: { assistantResponseMessage?: { toolUses?: Array<{ name?: string; input?: unknown }> } }; + } | undefined; + const entries = [...(state?.history ?? []), ...(state?.currentMessage ? [state.currentMessage] : [])]; + for (const entry of entries) { + for (const use of entry.assistantResponseMessage?.toolUses ?? []) { + if (use.name?.includes("apply_patch")) return inputFromValue(use.input); + } + } + return undefined; + } + if (wire === "openai-responses") { + const input = parsed.input as Array> | undefined; + for (const item of input ?? []) { + if (typeof item.name !== "string" || !item.name.includes("apply_patch")) continue; + if (item.type === "custom_tool_call") return inputFromValue(item.input); + if (item.type === "function_call") return inputFromValue(item.arguments); + } + return undefined; + } + const visit = (value: unknown): string | undefined => { + if (!value || typeof value !== "object") return undefined; + if (Array.isArray(value)) { + for (const item of value) { + const found = visit(item); + if (found !== undefined) return found; + } + return undefined; + } + const row = value as Record; + if (typeof row.name === "string" && row.name.includes("apply_patch")) { + const found = inputFromValue(row.input ?? row.arguments); + if (found !== undefined) return found; + } + for (const nested of Object.values(row)) { + const found = visit(nested); + if (found !== undefined) return found; + } + return undefined; + }; + return visit(parsed); +} + +function parseResponsesFrames(text: string): Array<{ event?: string; data: Record }> { + return text.split("\n\n") + .map(frame => frame.trim()) + .filter(frame => frame.length > 0 && frame !== "data: [DONE]") + .map(frame => { + const lines = frame.split("\n"); + const event = lines.find(line => line.startsWith("event: "))?.slice(7); + const data = lines.find(line => line.startsWith("data: "))?.slice(6) ?? "{}"; + return { event, data: JSON.parse(data) as Record }; + }); +} + +async function restoredStreamInput(adapterId: string, wire: AdapterWire): Promise { + const driver = TOOL_WIRE_DRIVERS[wire]; + if (!driver.streamingToolCall) return undefined; + const parsed = freeformParsed(wire); + const adapter = createRegisteredAdapter(providerFixture(adapterId, wire)); + const body = await withMimoBootstrap(adapterId, () => driver.observeOutbound(adapter, parsed)); + const wireName = driver.extractWireToolName?.(body, "apply_patch") ?? "apply_patch"; + const maps = buildToolBridgeMaps(parsed); + const bridged = bridgeToResponsesSSE( + adapter.parseStream( + driver.streamingToolCall(wireName, JSON.stringify({ input: PATCH })), + createTestTranslatorBudget(), + ), + parsed.modelId, + maps.toolNsMap, + maps.freeformToolNames, + maps.toolSearchToolNames, + undefined, + 2_000, + { declaredToolNames: maps.declaredToolNames }, + ); + const frames = parseResponsesFrames(await new Response(bridged).text()); + return frames.find(frame => frame.event === "response.custom_tool_call_input.done")?.data.input as string | undefined; +} + +describe("registry-derived routed tool conformance", () => { + test("provider and model-wire configuration ids are registry members", () => { + for (const provider of PROVIDER_REGISTRY) { + expect(getAdapterDefinition(provider.adapter), provider.id).toBeDefined(); + for (const value of Object.values(provider.modelWireDefaults ?? {})) { + const adapterId = typeof value === "string" ? value : value.wire; + expect(getAdapterDefinition(adapterId), `${provider.id}:${adapterId}`).toBeDefined(); + } + } + for (const adapterId of MODEL_ADAPTER_OVERRIDE_ALLOWED) { + expect(getAdapterDefinition(adapterId), adapterId).toBeDefined(); + } + }); + + test("every registered adapter keeps the nested apply_patch helper in its final request", async () => { + for (const [adapterId] of adapterDefinitions()) { + const contract = effectiveAdapterContract(adapterId); + const body = await outbound(adapterId, codeModeParsed(contract.wire)); + const advertised = advertisedToolNames(contract.wire, body); + expect(advertised.some(name => name === "exec" || name.endsWith("_exec")), adapterId).toBe(true); + const normalized = body.replace(/\\n/g, " ").replace(/\s+/g, " "); + expect(normalized, adapterId).toContain("apply_patch(input: string)"); + expect(normalized, adapterId).not.toMatch(/(?:do not|don't|never|must not|cannot|can't)[^.]{0,260}\bapply_patch\b/i); + expect(normalized, adapterId).not.toMatch(/\bapply_patch\b[^.]{0,180}\b(?:forbidden|unavailable|off-limits)\b/i); + } + }); + + test("tool_choice none disables every registered adapter's callable tool surface", async () => { + for (const [adapterId] of adapterDefinitions()) { + const contract = effectiveAdapterContract(adapterId); + const enabledBody = await outbound(adapterId, toolChoiceParsed(contract.wire)); + expect(advertisedToolNames(contract.wire, enabledBody).length, `${adapterId}:enabled`).toBeGreaterThan(0); + const disabledBody = await outbound(adapterId, toolChoiceParsed(contract.wire, "none")); + expect(toolCallsDisabled(contract.wire, disabledBody), adapterId).toBe(true); + } + }); + + test("every parsed streaming wire restores hostile freeform input exactly", async () => { + for (const [adapterId] of adapterDefinitions()) { + const contract = effectiveAdapterContract(adapterId); + const driver = TOOL_WIRE_DRIVERS[contract.wire]; + if (!driver.streamingToolCall) { + // OpenAI Responses is a normal passthrough here and only parses routed compaction; + // Cursor's proprietary runTurn stream has focused parser coverage elsewhere. + expect(["openai-responses", "cursor"]).toContain(contract.wire); + continue; + } + expect(await restoredStreamInput(adapterId, contract.wire), adapterId).toBe(PATCH); + } + }); + + test("every registered adapter replays the exact apply_patch input on continuation", async () => { + for (const [adapterId] of adapterDefinitions()) { + const contract = effectiveAdapterContract(adapterId); + const body = await outbound(adapterId, continuationParsed(contract.wire)); + expect(continuationInput(contract.wire, body), adapterId).toBe(PATCH); + } + }); +}); \ No newline at end of file diff --git a/tests/helpers/adapter-conformance/wire-drivers.ts b/tests/helpers/adapter-conformance/wire-drivers.ts new file mode 100644 index 0000000000..3abc7855eb --- /dev/null +++ b/tests/helpers/adapter-conformance/wire-drivers.ts @@ -0,0 +1,282 @@ +import { create, fromBinary } from "@bufbuild/protobuf"; +import type { ProviderAdapter } from "../../../src/adapters/base"; +import type { AdapterWire } from "../../../src/adapters/registry"; +import { decodeCursorArgsMap } from "../../../src/adapters/cursor/arg-codec"; +import { + AgentClientMessageSchema, + ConversationStepSchema, + ConversationTurnStructureSchema, + GetBlobArgsSchema, + KvServerMessageSchema, +} from "../../../src/adapters/cursor/gen/agent_pb"; +import { + handleCursorNativeKv, + releaseCursorBlobRequestScope, + type CursorBlobRequestScopeToken, +} from "../../../src/adapters/cursor/native-exec"; +import { prepareCursorRunRequest } from "../../../src/adapters/cursor/protobuf-request"; +import { createCursorRequest } from "../../../src/adapters/cursor/request-builder"; +import { encodeMessage } from "../../../src/lib/eventstream-decoder"; +import type { OcxParsedRequest } from "../../../src/types"; +import { withTestTranslatorBudget } from "../translator-budget"; + +export interface ToolWireDriver { + observeOutbound(adapter: ProviderAdapter, parsed: OcxParsedRequest): Promise; + extractWireToolName?(body: string, canonicalName: string): string; + streamingToolCall?(wireName: string, wrappedArguments: string): Response; +} + +async function observeHttpOutbound(adapter: ProviderAdapter, parsed: OcxParsedRequest): Promise { + const testAdapter = withTestTranslatorBudget(adapter); + const request = await testAdapter.buildRequest(parsed); + try { + return request.body; + } finally { + request.releaseBodyObservation?.(); + } +} + +function cursorBlobData(blobId: Uint8Array, scope: CursorBlobRequestScopeToken): Uint8Array { + const reply = fromBinary(AgentClientMessageSchema, handleCursorNativeKv(create(KvServerMessageSchema, { + id: 1, + message: { case: "getBlobArgs", value: create(GetBlobArgsSchema, { blobId }) }, + }), scope)); + if (reply.message.case !== "kvClientMessage") { + throw new Error(`Cursor conformance expected kvClientMessage, got ${reply.message.case || "empty"}`); + } + const kv = reply.message.value; + if (kv.message.case !== "getBlobResult" || !kv.message.value.blobData) { + throw new Error(`Cursor conformance could not hydrate blob ${Buffer.from(blobId).toString("hex")}`); + } + return kv.message.value.blobData; +} + +function splitInTwo(input: string): [string, string] { + const split = Math.max(1, Math.floor(input.length / 2)); + return [input.slice(0, split), input.slice(split)]; +} + +function openAiChatToolCall(wireName: string, wrappedArguments: string): Response { + const fragments = splitInTwo(wrappedArguments); + const frames = fragments.map((argumentsFragment, index) => ({ + choices: [{ + delta: { + tool_calls: [{ + index: 0, + ...(index === 0 ? { id: "call_patch", type: "function" } : {}), + function: { + ...(index === 0 ? { name: wireName } : {}), + arguments: argumentsFragment, + }, + }], + }, + finish_reason: index === fragments.length - 1 ? "tool_calls" : null, + }], + })); + return new Response(`${frames.map(frame => `data: ${JSON.stringify(frame)}`).join("\n\n")}\n\ndata: [DONE]\n\n`, { + headers: { "content-type": "text/event-stream" }, + }); +} + +function anthropicToolCall(wireName: string, wrappedArguments: string): Response { + const fragments = splitInTwo(wrappedArguments); + const frame = (event: string, data: unknown) => `event: ${event}\ndata: ${JSON.stringify(data)}\n\n`; + return new Response([ + frame("content_block_start", { + type: "content_block_start", + content_block: { type: "tool_use", id: "toolu_patch", name: wireName }, + }), + ...fragments.map(partialJson => frame("content_block_delta", { + type: "content_block_delta", + delta: { type: "input_json_delta", partial_json: partialJson }, + })), + frame("content_block_stop", { type: "content_block_stop" }), + frame("message_stop", { type: "message_stop" }), + ].join(""), { headers: { "content-type": "text/event-stream" } }); +} + +function googleToolCall(wireName: string, wrappedArguments: string): Response { + return new Response( + `data: ${JSON.stringify({ + candidates: [{ + content: { parts: [{ functionCall: { name: wireName, args: JSON.parse(wrappedArguments) } }] }, + finishReason: "STOP", + }], + })}\n\n`, + { headers: { "content-type": "text/event-stream" } }, + ); +} + +function commandCodeToolCall(wireName: string, wrappedArguments: string): Response { + return new Response([ + JSON.stringify({ + type: "tool-call", + toolCallId: "call_patch", + toolName: wireName, + input: JSON.parse(wrappedArguments), + }), + JSON.stringify({ type: "finish", rawFinishReason: "tool_use" }), + ].join("\n")); +} + +const kiroEncoder = new TextEncoder(); +function kiroFrame(payload: unknown): Uint8Array { + return encodeMessage( + { ":message-type": "event", ":event-type": "toolUseEvent" }, + kiroEncoder.encode(JSON.stringify(payload)), + ); +} + +function kiroToolCall(wireName: string, wrappedArguments: string): Response { + const fragments = splitInTwo(wrappedArguments); + const frames = [ + kiroFrame({ name: wireName, toolUseId: "call_patch" }), + ...fragments.map(input => kiroFrame({ input, name: wireName, toolUseId: "call_patch" })), + kiroFrame({ name: wireName, stop: true, toolUseId: "call_patch" }), + ]; + let index = 0; + return new Response(new ReadableStream({ + pull(controller) { + if (index < frames.length) controller.enqueue(frames[index++]!); + else controller.close(); + }, + })); +} + +function requireWireToolName( + match: string | undefined, + canonicalName: string, + wire: AdapterWire, +): string { + if (!match) throw new Error(`${wire} outbound body advertised no tool matching "${canonicalName}"`); + return match; +} + +const openAiChatDriver: ToolWireDriver = { + observeOutbound: observeHttpOutbound, + extractWireToolName(body, canonicalName) { + const parsed = JSON.parse(body) as { tools?: Array<{ function?: { name?: string } }> }; + const match = parsed.tools?.find(tool => tool.function?.name?.includes(canonicalName))?.function?.name; + return requireWireToolName(match, canonicalName, "openai-chat"); + }, + streamingToolCall: openAiChatToolCall, +}; + +const anthropicDriver: ToolWireDriver = { + observeOutbound: observeHttpOutbound, + extractWireToolName(body, canonicalName) { + const parsed = JSON.parse(body) as { tools?: Array<{ name?: string }> }; + const match = parsed.tools?.find(tool => tool.name?.includes(canonicalName))?.name; + return requireWireToolName(match, canonicalName, "anthropic"); + }, + streamingToolCall: anthropicToolCall, +}; + +const googleDriver: ToolWireDriver = { + observeOutbound: observeHttpOutbound, + extractWireToolName(body, canonicalName) { + const parsed = JSON.parse(body) as { + tools?: Array<{ functionDeclarations?: Array<{ name?: string }> }>; + }; + for (const toolGroup of parsed.tools ?? []) { + const match = toolGroup.functionDeclarations?.find(tool => tool.name?.includes(canonicalName))?.name; + if (match) return match; + } + return requireWireToolName(undefined, canonicalName, "google"); + }, + streamingToolCall: googleToolCall, +}; + +const commandCodeDriver: ToolWireDriver = { + observeOutbound: observeHttpOutbound, + extractWireToolName(body, canonicalName) { + const parsed = JSON.parse(body) as { params?: { tools?: Array<{ name?: string }> } }; + const match = parsed.params?.tools?.find(tool => tool.name?.includes(canonicalName))?.name; + return requireWireToolName(match, canonicalName, "command-code"); + }, + streamingToolCall: commandCodeToolCall, +}; + +const kiroDriver: ToolWireDriver = { + observeOutbound: observeHttpOutbound, + extractWireToolName(body, canonicalName) { + const parsed = JSON.parse(body) as { + conversationState?: { + currentMessage?: { + userInputMessage?: { + userInputMessageContext?: { + tools?: Array<{ toolSpecification?: { name?: string } }>; + }; + }; + }; + }; + }; + const tools = parsed.conversationState?.currentMessage?.userInputMessage?.userInputMessageContext?.tools ?? []; + const match = tools.find(tool => tool.toolSpecification?.name?.includes(canonicalName))?.toolSpecification?.name; + return requireWireToolName(match, canonicalName, "kiro"); + }, + streamingToolCall: kiroToolCall, +}; + +const responsesDriver: ToolWireDriver = { + observeOutbound: observeHttpOutbound, + extractWireToolName(body, canonicalName) { + const parsed = JSON.parse(body) as { tools?: Array<{ name?: string }> }; + const match = parsed.tools?.find(tool => tool.name?.includes(canonicalName))?.name; + return requireWireToolName(match, canonicalName, "openai-responses"); + }, +}; + +export const TOOL_WIRE_DRIVERS = { + "openai-chat": openAiChatDriver, + anthropic: anthropicDriver, + google: googleDriver, + "command-code": commandCodeDriver, + kiro: kiroDriver, + "openai-responses": responsesDriver, + cursor: { + async observeOutbound(_adapter, parsed) { + const request = createCursorRequest(parsed); + const prepared = prepareCursorRunRequest(request); + try { + const message = fromBinary(AgentClientMessageSchema, prepared.bytes); + if (message.message.case !== "runRequest") { + throw new Error(`Cursor conformance expected runRequest, got ${message.message.case || "empty"}`); + } + const runRequest = message.message.value; + const tools = runRequest.mcpTools?.mcpTools ?? []; + const continuationToolCalls: Array<{ name: string; arguments: Record }> = []; + for (const turnId of runRequest.conversationState?.turns ?? []) { + const turn = fromBinary( + ConversationTurnStructureSchema, + cursorBlobData(turnId, prepared.blobRequestScope), + ); + if (turn.turn.case !== "agentConversationTurn") continue; + for (const stepId of turn.turn.value.steps) { + const step = fromBinary( + ConversationStepSchema, + cursorBlobData(stepId, prepared.blobRequestScope), + ); + if (step.message.case !== "toolCall") continue; + const tool = step.message.value.tool; + if (tool.case !== "mcpToolCall") continue; + const args = tool.value.args; + continuationToolCalls.push({ + name: args?.toolName || args?.name || "", + arguments: decodeCursorArgsMap(args?.args), + }); + } + } + return JSON.stringify({ + tools: tools.map(tool => ({ + name: tool.toolName || tool.name, + description: tool.description, + })), + continuationToolCalls, + }); + } finally { + releaseCursorBlobRequestScope(prepared.blobRequestScope); + } + }, + }, +} satisfies Record;