path = '/mnt/NVME/Docker/opencode-build/opencode/packages/opencode/src/provider/provider.ts' with open(path, 'r') as f: src = f.read() MARKER_1 = 'statusText: res.statusText,\n })\n}\n\nfunction googleVertexAnthropicBaseURL' PATCH_FN = r"""statusText: res.statusText, }) } // Fix missing/null tool_call ids in SSE streams from OpenAI-compatible providers. // Some proxies (e.g. 9Router/LiteLLM forwarding Anthropic) emit tool-call chunks // without an `id` field, causing @ai-sdk/openai-compatible to throw // "Expected 'id' to be a string." Inject a stable synthetic id per tool-call index. function patchToolCallIds(res: Response, npm: string): Response { if (npm !== "@ai-sdk/openai-compatible" && npm !== "@ai-sdk/openai") return res if (!res.body) return res if (!res.headers.get("content-type")?.includes("text/event-stream")) return res const reader = res.body.getReader() const encoder = new TextEncoder() const decoder = new TextDecoder() const idByIndex = new Map() let buf = "" const body = new ReadableStream({ async pull(ctrl) { const { done, value } = await reader.read() if (done) { if (buf) ctrl.enqueue(encoder.encode(buf)); ctrl.close(); return } buf += decoder.decode(value, { stream: true }) const nl = buf.lastIndexOf("\n") if (nl === -1) return const complete = buf.slice(0, nl + 1) buf = buf.slice(nl + 1) const lines = complete.split("\n") const out: string[] = [] for (const line of lines) { if (!line.startsWith("data: ")) { out.push(line); continue } const payload = line.slice(6) if (payload === "[DONE]") { out.push(line); continue } try { const parsed = JSON.parse(payload) let dirty = false for (const choice of parsed?.choices ?? []) { for (const tc of choice?.delta?.tool_calls ?? []) { if (typeof tc.id !== "string" || tc.id === "") { const idx: number = tc.index ?? 0 if (!idByIndex.has(idx)) idByIndex.set(idx, `call_${crypto.randomUUID().replace(/-/g,"").slice(0,24)}`) tc.id = idByIndex.get(idx); dirty = true } } } out.push(dirty ? `data: ${JSON.stringify(parsed)}` : line) } catch { out.push(line) } } ctrl.enqueue(encoder.encode(out.join("\n"))) }, async cancel(reason) { await reader.cancel(reason) }, }) return new Response(body, { headers: new Headers(res.headers), status: res.status, statusText: res.statusText, }) } function googleVertexAnthropicBaseURL""" if MARKER_1 in src: src = src.replace(MARKER_1, PATCH_FN, 1) print('OK: inserted patchToolCallIds()') else: print('ERROR: marker 1 not found') raise SystemExit(1) MARKER_2 = ' if (!chunkAbortCtl) return res\n return wrapSSE(res, chunkTimeout, chunkAbortCtl)' PATCH_RETURN = ' const patched = patchToolCallIds(res, model.api.npm)\n if (!chunkAbortCtl) return patched\n return wrapSSE(patched, chunkTimeout, chunkAbortCtl)' if MARKER_2 in src: src = src.replace(MARKER_2, PATCH_RETURN, 1) print('OK: patched fetch return') else: print('ERROR: marker 2 not found') raise SystemExit(1) with open(path, 'w') as f: f.write(src) print('DONE')