plugins: a plugin's fetch gets its body as a string, as OpenCode hands it — the host passed a Buffer, and the plugins that reshape a request (Grok, WorkBuddy, MiMo) touch only a string body, so a moved provider's requests went out as the gateway built them. A UTF-8 body now goes as a string; one that isn't stays bytes. TestFakePlugin fails without the change.

This commit is contained in:
yetone committed 2026-10-01 03:41:42 +08:00
1 parent a170b909c9
commit d8f2e17dd7
3 files changed
+19 -1

No files matched your search

+14 -1
View File
@@ -709,6 +709,19 @@ function sdkHeaders(npm, key) {
return { authorization: `Bearer ${key}` }
}
// bodyOf is the body as OpenCode hands it to a plugin's fetch: the string
// the AI SDK built, as the plugins reshape only a string body. One that
// isn't UTF-8 text stays bytes.
function bodyOf(b64) {
if (!b64) return undefined
const b = Buffer.from(b64, "base64")
try {
return new TextDecoder("utf-8", { fatal: true, ignoreBOM: true }).decode(b)
} catch {
return b
}
}
async function doFetch(id, params) {
const key = accountKey(params.provider, params.account)
return inScope(params.provider, key, () => fetchAs(id, key, params))
@@ -750,7 +763,7 @@ async function fetchAs(id, key, { provider, model, npm, url, method, headers, bo
const res = await f(url, {
method: method ?? "POST",
headers: h,
body: body ? Buffer.from(body, "base64") : undefined,
body: bodyOf(body),
signal: ctl.signal,
})
const rh = {}
+4
View File
@@ -145,6 +145,10 @@ func TestFakePlugin(t *testing.T) {
if h.Get("Authorization") != "Bearer fresh-r-blue" || h.Get("X-Plugin-Model") != "fake-1" || h.Get("X-Models") != "fake-1,fake-claude,fake-gemini" {
t.Fatalf("headers = %v", h)
}
// the plugin's fetch got the body as a string, as OpenCode hands it
if h.Get("X-Body-Type") != "string" {
t.Fatalf("the plugin got a %s body", h.Get("X-Body-Type"))
}
b, _ = os.ReadFile(AuthPath())
json.Unmarshal(b, &saved)
if saved["fakeco"]["access"] != "fresh-r-blue" {
+1
View File
@@ -50,6 +50,7 @@ export const FakePlugin = async ({ client }) => ({
const h = new Headers(init.headers)
h.set("authorization", "Bearer " + (a.type === "oauth" ? a.access : a.key))
h.set("x-models", Object.keys(provider.models).sort().join(","))
h.set("x-body-type", typeof init.body)
return fetch(url, { ...init, headers: h })
},
}),