# Skill: Add New WASM Component ## 何時用這個 skill `arcrun_list_components()` 沒有你需要的零件。要寫一個新的 TinyGo / AssemblyScript WASM。 **重要**:寫零件 = **改 arcrun 平台本身**,不是改 user workflow。 這 skill 預設你有 arcrun repo write access。沒有 → 告訴用戶「需要 X 零件,請聯絡平台維護者」,停手。 ## 7 步流程 ### 1. 確認真的需要新零件 先想:能不能用 `http_request` 加組合搞定? - 多數第三方 API → `http_request` 已夠(搭配 `auth_recipe` 處理 auth) - 簡單轉換 → 用 logic primitives(`set` / `filter` / `array_ops`) - 複雜流程編排 → cypher binding 多步而非單一大零件 真的需要新零件的場景: - 跟 cypher-executor host functions 互動(KV、加解密、簽 JWT) - 邏輯太複雜不適合多節點分解 - 為效能(一次 worker call 取代 10 次 fetch) ### 2. 讀規範 - `matrix/arcrun/.claude/rules/03-component-architecture.md` — 部署慣例 - `matrix/arcrun/.claude/rules/01-tech-stack.md` — TinyGo 限制 - 既有相似零件範例:`matrix/arcrun/registry/components/{name}/main.go` ### 3. 開新目錄 ``` matrix/arcrun/registry/components/{your_component}/ ├── main.go TinyGo source ├── component.contract.yaml input/output schema + 描述 └── (build 後產出 .wasm) ``` 合約格式(contract.yaml): ```yaml canonical_id: your_component display_name: 中文顯示名 category: data | auth | api | logic version: 0.1.0 description: | 做什麼用、限制、注意事項。AI 看這份決定要不要用你的零件 input_schema: type: object required: [foo, bar] properties: foo: { type: string, description: "..." } bar: { type: number, description: "..." } output_schema: type: object properties: result: { type: string } success: { type: boolean } gherkin_tests: - given: "input foo=hello" when: "component runs" then: "result contains hello" ``` ### 4. 寫 main.go ```go package main import ( "encoding/json" "io" "os" ) type Input struct { Foo string `json:"foo"` Bar int `json:"bar"` } type Output struct { Result string `json:"result"` Success bool `json:"success"` } func main() { bytes, _ := io.ReadAll(os.Stdin) var in Input json.Unmarshal(bytes, &in) // 你的邏輯 result := in.Foo + ":" + string(rune(in.Bar)) out := Output{Result: result, Success: true} json.NewEncoder(os.Stdout).Encode(out) } ``` 限制: - 只 import:`os`、`io`、`encoding/json`、`encoding/base64`、`strings`、`time` 等 stdlib - **禁用**:`net/http`(用 host function `u6u.http_request`)、`crypto/rsa`(用 host function) - 全部 logic 在 main(),stdin/stdout JSON I/O ### 5. 本地 build + 測 ```bash cd registry/components/your_component tinygo build -target=wasi -o your_component.wasm main.go echo '{"foo":"hello","bar":42}' | wasmtime your_component.wasm ``` ### 6. 部署成獨立 Worker ``` .component-builds/your_component/ ├── wrangler.toml name = "arcrun-your-component" ├── package.json ├── component.wasm 從上面 build 複製過來 └── src/index.ts 固定 WASI shim(複製 component-worker-template) ``` `wrangler.toml`: ```toml name = "arcrun-your-component" main = "src/index.ts" compatibility_date = "2025-02-19" workers_dev = true # 必須 true,cypher-executor 走 workers.dev 對內 URL [[routes]] pattern = "your-component.arcrun.dev/*" zone_name = "arcrun.dev" ``` push → CI 自動部署。 ### 7. 註冊到 cypher-executor 白名單 ⚠️ **目前的架構債**(M2 計畫修):每加零件要手動加 `cypher-executor/src/lib/component-loader.ts`: ```ts const WASM_HTTP_RUNNER_IDS: ReadonlySet = new Set([ // ... 既有 'your_component', // ← 加這行 ]); ``` 不加 → workflow 用你的零件會噴「找不到零件」。 未來會改成 registry KV 動態查(`cypher-executor-dynamic-component-discovery` SDD 待開)。 ## 驗證上線 ``` arcrun_list_components() → 應該看到 your_component arcrun_get_component_contract(canonical_id='your_component') → 看 schema ``` 寫個 test workflow 用你的零件,跑通就完成。