Files
Arcrun/registry/components/code/index.ts
T
Leo efa0b0578c feat(code): Workers 就緒化(裁定 A)—— singlefile variant + 純 JS SHA-256 prelude
- 沙箱改用 quickjs-emscripten singlefile variant(wasm 內嵌 base64、同步載入),
  CF Workers 相容;sandbox.mjs 成 Node/Worker 共用 runtime-agnostic 核心。
- sha256 curated builtin 改「純 JS SHA-256 prelude 字串注入」,去掉 node:crypto /
  async Web Crypto host-call,Node/Worker 皆決定性(card content_hash 逐字等價)。
- index.ts 成可部署 Worker host(Hono,POST /→runCode),自足不走 TinyGo 模板流程。
- 補 wrangler.toml(arcrun-code / code.arcrun.dev)、tsconfig、DEPLOY.md。
- contract stability 修為 floating(過 registry zod schema 驗證)。
- 單測 12/12 全綠(含 card→envelope 與原模組 planCard 逐欄全等)。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HJiLCRUU2o3aSpPEzVCt2o
2026-07-06 04:39:28 +00:00

51 lines
1.9 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 `code` 零件 —— Worker host(可部署)
*
* POST / → { code, input?, limits? }
* → QuickJS-wasm 沙箱(./sandbox.mjs 的 runCode
* → { success:true, data } | { success:false, error, error_type }
*
* 封裝=Aquickjs-emscripten singlefile variant):wasm 內嵌為 base64、同步載入,
* bundler 友善、無需 [[wasm_modules]] 綁定、無需 nodejs_compatsandbox 用 TextEncoder 計 bytes)。
*
* 與其他 logic 零件不同:`code` 是自足 Worker(自帶 index.ts + sandbox.mjs + quickjs variant),
* 不走 component-worker-template 的 TinyGo-wasm bundling 流程。部署見 DEPLOY.md。
*/
import { Hono } from 'hono';
import { cors } from 'hono/cors';
// @ts-expect-error —— sandbox.mjs 為 runtime-agnostic JS 核心(Node 測試與 Worker 共用同一份)
import { runCode } from './sandbox.mjs';
const app = new Hono();
app.use('*', cors());
app.get('/', (c) => c.json({ ok: true, component: 'code' }));
app.post('/', async (c) => {
let body: { code?: unknown; input?: unknown; limits?: Record<string, number> };
try {
body = await c.req.json();
} catch {
return c.json({ success: false, error: 'request body must be JSON', error_type: 'ContractError' }, 400);
}
if (typeof body.code !== 'string') {
return c.json({ success: false, error: 'code (string) is required', error_type: 'ContractError' }, 400);
}
try {
const result = await runCode(body.code, body.input, { limits: body.limits });
// sandbox 永遠回結構化 envelopesuccess=false 仍以 200 帶 error_type 回(零件語義層錯,非 HTTP 錯)
return c.json(result);
} catch (e) {
// 理論上 runCode 自己 try/catch;這層是最後保險,Worker 絕不掛。
return c.json(
{ success: false, error: e instanceof Error ? e.message : String(e), error_type: 'SandboxError' },
500,
);
}
});
export default app;