Files
Arcrun/.component-builds/http_request/src/index.ts
T
uncle6me-web 465c505000 fix(execution-truth): 修系統對 401 假綠根因 + acr run self-hosted + D1-in-update
Haiku 自主壓測(test_arcrun/5)暴露的真 bug,逐一修復:

1. 假綠根因:http_request host function 丟掉 HTTP status code(main.go:112 架構債)
   → 非 2xx(如 Notion 401)被判 success → 引擎自己對失敗報成功。
   修:host fn 非 2xx 回 {error,status,body} envelope,既有判定鏈正確識別。
   http_request/claude_api/kbdb_upsert_block/km_writer 已修(4 worker deploy);
   auth_service_account 自有 OAuth 判定不套。

2. acr run self-hosted:原一律走 /webhooks/<name>(需先 push)→ 沒 push 回 404 純文字
   → res.json() 爆假錯誤。修:本機有 YAML 走玩法一 /cypher/execute 直接執行(三模式一致)
   + res.ok 擋非 2xx + findWorkflowYaml 容忍 .yaml 副檔名。

3. D1-in-update:D1 只在 init 建一次,update 漏建 → token 補權限後無冪等補建路徑。
   修:update 也 ensureD1Database(已驗證 D1 建起 count:1)。

4. CF token 教學漏 D1:llms.txt/.env.example 加「Account/D1/Edit」必勾 + init/preflight
   訊息指明 token 缺 D1 權限的修法。

CLI 1.3.4 publish。Haiku 壓測結論:onboarding 治好(裝+init 沒跳過、建 recipe 不建零件),
但仍會假綠(curl 繞過/D1 沒建謊報)→ 印證執行真相要系統能驗、不信 AI 自報。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-09 22:12:09 +08:00

95 lines
3.2 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* arcrun API component Worker (http_request)
*
* POST / → JSON input → WASM (WASI preview1 stdin/stdout) → JSON output
*
* host function: http_requestfetch → 回 response body 原文)
* 此 Worker 不做 credential 注入,只提供通用 HTTP 能力。
*/
import componentWasm from '../component.wasm' assert { type: 'webassembly' };
import { Hono } from 'hono';
import { cors } from 'hono/cors';
import { createWasiShim, type WasiHostFunctions } from '../../../cypher-executor/src/lib/wasi-shim';
const app = new Hono();
app.use('*', cors());
app.get('/', (c) => c.json({ ok: true, component: 'http_request' }));
app.post('/', async (c) => {
let input: unknown;
try {
input = await c.req.json();
} catch {
return c.json({ success: false, error: 'request body must be JSON' }, 400);
}
try {
const result = await runWasm(input);
return c.json(result);
} catch (e) {
return c.json(
{ success: false, error: e instanceof Error ? e.message : String(e) },
500,
);
}
});
export default app;
// ── WASM runner ──────────────────────────────────────────────────────────────
async function runWasm(input: unknown): Promise<unknown> {
const hostFunctions: WasiHostFunctions = {
http_request: async (url, method, headersJson, body) => {
const headers: Record<string, string> = {};
if (headersJson) {
try {
const parsed = JSON.parse(headersJson);
if (parsed && typeof parsed === 'object') {
for (const [k, v] of Object.entries(parsed as Record<string, unknown>)) {
if (typeof v === 'string') headers[k] = v;
}
}
} catch {
// ignore header parse errors
}
}
const init: RequestInit = { method, headers };
if (body && method.toUpperCase() !== 'GET' && method.toUpperCase() !== 'HEAD') {
init.body = body;
}
const res = await fetch(url, init);
const text = await res.text();
// 修架構債(main.go:112):host function 原本只回 body,丟掉 HTTP status code
// 導致 4xx/5xx(如 Notion 401)被零件判成 success → 引擎對失敗報告成功(系統假綠根因)。
// 修法:非 2xx 包成帶 "error" key 的 envelope,讓所有消費零件既有的 parsed["error"] 判定
// 鏈正確識別失敗(2xx 維持原樣回 body 原文,向後相容不破壞 happy path)。
if (!res.ok) {
return JSON.stringify({
error: `HTTP ${res.status}`,
status: res.status,
body: text,
});
}
return text;
},
};
const shim = createWasiShim(JSON.stringify(input), hostFunctions);
const instance = await WebAssembly.instantiate(
componentWasm as WebAssembly.Module,
shim.imports,
);
shim.setMemory(instance.exports.memory as WebAssembly.Memory);
await shim.run(instance);
const stdout = shim.getStdout().trim();
const stderr = shim.getStderr().trim();
if (stderr) console.error('[http_request wasm stderr]', stderr);
if (!stdout) throw new Error('WASM component produced no output');
return JSON.parse(stdout);
}