From 5f5c0bc94a286edca7369dd9e07569a6194a3127 Mon Sep 17 00:00:00 2001 From: backryun Date: Wed, 12 Aug 2026 20:28:13 +0900 Subject: [PATCH] fix(tinycms): align executor and signer contracts (#10087) --- open-sse/executors/tinycms.ts | 9 ++--- open-sse/executors/tinycmsSigner.ts | 11 ------ tests/unit/provider-tinycms-web.test.ts | 45 +++++++++++++++++++++++++ 3 files changed, 50 insertions(+), 15 deletions(-) diff --git a/open-sse/executors/tinycms.ts b/open-sse/executors/tinycms.ts index 4cbb0bf8f8..62657e364f 100644 --- a/open-sse/executors/tinycms.ts +++ b/open-sse/executors/tinycms.ts @@ -1,4 +1,4 @@ -import { BaseExecutor, type ExecuteInput } from "./base.ts"; +import { BaseExecutor, type ExecuteInput, type ExecutorExecuteResult } from "./base.ts"; import { makeExecutorErrorResult as makeErrorResult } from "../utils/error.ts"; import { initTinyCmsWasm, generateSecurePayload } from "./tinycmsSigner.ts"; @@ -45,7 +45,7 @@ export class TinyCmsExecutor extends BaseExecutor { super("tinycms-web", { id: "tinycms-web", baseUrl: CHAT_URL }); } - async execute(input: ExecuteInput) { + async execute(input: ExecuteInput): Promise { const { body, credentials, signal } = input; const bodyObj = (body || {}) as Record; @@ -116,9 +116,10 @@ export class TinyCmsExecutor extends BaseExecutor { const response = await fetch(CHAT_URL, fetchOptions); return { - status: response.status, + response, + url: CHAT_URL, headers: Object.fromEntries(response.headers.entries()), - body: response.body, + transformedBody: bodyObj, }; } catch (err: any) { return makeErrorResult( diff --git a/open-sse/executors/tinycmsSigner.ts b/open-sse/executors/tinycmsSigner.ts index 61c0a22469..cf9084ce9c 100644 --- a/open-sse/executors/tinycmsSigner.ts +++ b/open-sse/executors/tinycmsSigner.ts @@ -358,17 +358,6 @@ function decodeText(ptr, len) { const cachedTextEncoder = new TextEncoder(); -if (!('encodeInto' in cachedTextEncoder)) { - cachedTextEncoder.encodeInto = function (arg, view) { - const buf = cachedTextEncoder.encode(arg); - view.set(buf); - return { - read: arg.length, - written: buf.length - }; - }; -} - let WASM_VECTOR_LEN = 0; let wasmModule, wasm; diff --git a/tests/unit/provider-tinycms-web.test.ts b/tests/unit/provider-tinycms-web.test.ts index 0731d742db..82b76f2167 100644 --- a/tests/unit/provider-tinycms-web.test.ts +++ b/tests/unit/provider-tinycms-web.test.ts @@ -168,6 +168,51 @@ test("TinyCmsExecutor returns 401 when UUID does not start with 'R'", async () = assert.ok(!errMsg.includes("at /"), "error must not contain a stack trace path"); }); +test("TinyCmsExecutor returns the standard executor response envelope on success", async () => { + const originalFetch = globalThis.fetch; + globalThis.fetch = async (input) => { + const url = String(input); + if (url.includes("api64.ipify.org")) { + return new Response(JSON.stringify({ ip: "127.0.0.1" }), { + headers: { "Content-Type": "application/json" }, + }); + } + if (url.includes("/api/challenge")) { + return new Response( + JSON.stringify({ + challenge: "test", + challengeId: "challenge-id", + expiresAt: Date.now() + 60_000, + version: "1", + difficulty: 0, + }), + { headers: { "Content-Type": "application/json" } } + ); + } + return new Response("upstream body", { + status: 200, + headers: { "X-TinyCMS-Test": "yes" }, + }); + }; + + try { + const requestBody = { messages: [{ role: "user", content: "hi" }] }; + const result = await new TinyCmsExecutor().execute({ + model: "gpt-5-free", + body: requestBody, + stream: false, + credentials: { apiKey: "Rtest-device" }, + }); + + assert.ok(!(result instanceof Response), "TinyCMS must preserve executor metadata"); + assert.equal(result.response.status, 200); + assert.equal(result.headers?.["x-tinycms-test"], "yes"); + assert.deepEqual(result.transformedBody, requestBody); + } finally { + globalThis.fetch = originalFetch; + } +}); + // ── WASM initialization ─────────────────────────────────────────────────────── test("initTinyCmsWasm module exports expected functions", async () => {