arcrun — AI workflow execution engine (clean history)
Self-hosted 開源:WASM 零件 + recipe + cypher-executor,跑在你自己的 Cloudflare。 此為重建的乾淨歷史起點(移除曾誤 commit 的 GCP SA 金鑰,舊歷史保留在 richblack/arcrun 與本地 backup 分支)。含: - acr init --self-hosted installer(建 KV/R2 + codeload 拉預編譯 wasm + wrangler deploy + seed recipe) - recipe push 把關(資料外流提醒 + 打通檢查) - 19 個正當零件預編譯 wasm(claude_api/km_writer/kbdb_upsert_block 排除:違反 DECISIONS §1) - CLI / cypher-executor / registry / 完整 SDD Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,521 @@
|
||||
# u6u-core 獨立開源 Repo 需求規格 v3
|
||||
|
||||
## 背景與定位
|
||||
|
||||
### 為什麼開源
|
||||
|
||||
u6u-core 是 AI 工作流執行引擎,開源的護城河邏輯如下:
|
||||
|
||||
```
|
||||
開源(u6u-core) 閉源(InkStone 付費服務)
|
||||
──────────────────────── ──────────────────────────────
|
||||
cypher-executor(執行引擎) KBDB 向量搜尋
|
||||
WASM 零件庫(Gmail / GSheets…) KBDB graph 查詢
|
||||
credentials Worker Persona SDK / Mini-me
|
||||
CLI MatchGPT
|
||||
→ 需要訂閱,不需要 YAML / KV
|
||||
```
|
||||
|
||||
用戶自架版:YAML + CF KV,完全免費。
|
||||
升級版:不需要 YAML,直接用自然語言查 KBDB 圖譜組 workflow,這是差異化。
|
||||
|
||||
### 目前 matrix repo 狀況
|
||||
|
||||
```
|
||||
matrix/
|
||||
├── cypher-executor/ ← 要搬進 u6u-core
|
||||
├── u6u-core/
|
||||
│ ├── builtins/
|
||||
│ ├── credentials/
|
||||
│ └── registry/
|
||||
│ └── components/(21 個 WASM 零件)
|
||||
└── ...(其他 InkStone 內部服務,不搬)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 任務一:搬移 cypher-executor 進 u6u-core
|
||||
|
||||
### 目標結構
|
||||
|
||||
```
|
||||
u6u-core/(新獨立 repo,開源)
|
||||
├── README.md
|
||||
├── cypher-executor/ ← 從 matrix/cypher-executor 搬入
|
||||
│ ├── src/
|
||||
│ ├── wrangler.toml ← 需要清理(移除 InkStone 內部 bindings)
|
||||
│ └── ...
|
||||
├── credentials/ ← 從 matrix/u6u-core/credentials 搬入
|
||||
├── builtins/ ← 從 matrix/u6u-core/builtins 搬入
|
||||
└── registry/
|
||||
└── components/ ← 從 matrix/u6u-core/registry/components 搬入
|
||||
```
|
||||
|
||||
### wrangler.toml 清理(重要)
|
||||
|
||||
現有 `cypher-executor/wrangler.toml` 有大量 InkStone 內部 Service Bindings,開源版要移除:
|
||||
|
||||
**移除(InkStone 專屬,不公開):**
|
||||
```toml
|
||||
# 移除這些 services bindings:
|
||||
KBDB → inkstone-kbdb-api
|
||||
REGISTRY → inkstone-component-registry
|
||||
CLINIC_GDRIVE → clinic-gdrive
|
||||
CLINIC_EXCEL → clinic-excel
|
||||
CLINIC_ANALYSIS
|
||||
CLINIC_RENDER
|
||||
CLINIC_GSHEETS
|
||||
AICEO → inkstone-aiceo-bot
|
||||
MINI_ME → inkstone-mini-me
|
||||
```
|
||||
|
||||
**保留(用戶自己部署需要的):**
|
||||
```toml
|
||||
[[kv_namespaces]]
|
||||
binding = "EXEC_CONTEXT" # 執行上下文暫存
|
||||
|
||||
[[kv_namespaces]]
|
||||
binding = "WEBHOOKS" # workflow YAML 儲存
|
||||
|
||||
[[r2_buckets]]
|
||||
binding = "WASM_BUCKET" # WASM 零件二進位
|
||||
|
||||
[ai]
|
||||
binding = "AI" # Workers AI(auto-publish 用)
|
||||
```
|
||||
|
||||
**新增(開源版用戶需要的):**
|
||||
```toml
|
||||
[[kv_namespaces]]
|
||||
binding = "CREDENTIALS_KV" # credential 加密存儲
|
||||
```
|
||||
|
||||
### 清理後的 component-loader
|
||||
|
||||
現有 component-loader 可能有 InkStone 內部查詢邏輯(KBDB HTTP fetch),
|
||||
開源版改為:**直接從 WASM_BUCKET R2 讀取 `.wasm` 檔案**,不依賴任何外部服務。
|
||||
|
||||
---
|
||||
|
||||
## 任務二:零件完成度審查與補充
|
||||
|
||||
### 完成度標準
|
||||
|
||||
每個零件的 `component.contract.yaml` 必須包含:
|
||||
|
||||
```yaml
|
||||
# 已有(現狀)
|
||||
canonical_id: "gmail"
|
||||
input_schema: ...
|
||||
output_schema: ...
|
||||
gherkin_tests: ...
|
||||
|
||||
# 需要補充
|
||||
credentials_required: # 需要 token 的零件才需要此欄位
|
||||
- key: gmail_token # 對應 credentials.yaml 的 key 名稱慣例
|
||||
type: google_oauth # token 類型
|
||||
description: "Google OAuth access token(gmail.send scope)"
|
||||
inject_as: access_token # 執行時自動注入到 input 的哪個欄位
|
||||
|
||||
config_example: | # scaffold 指令產出的範本,帶說明註解
|
||||
send_email: # 節點名稱(可自訂)
|
||||
to: "" # 收件人 Email(必填)
|
||||
subject: "" # 主旨(必填)
|
||||
body: "" # 內文(必填)
|
||||
# access_token 由 credentials.yaml 的 gmail_token 自動注入
|
||||
```
|
||||
|
||||
### 需要 credentials_required 的零件
|
||||
|
||||
| 零件 | 需要的 token | inject_as |
|
||||
|------|-------------|-----------|
|
||||
| gmail | google_oauth | access_token |
|
||||
| google_sheets | google_oauth | access_token |
|
||||
| telegram | telegram_bot_token | bot_token |
|
||||
| line_notify | line_token | token |
|
||||
| http_request | 不固定(用戶自訂) | 不適用 |
|
||||
|
||||
### 不需要 credentials_required 的零件
|
||||
|
||||
set, filter, merge, switch, wait, if_control, foreach_control,
|
||||
try_catch, validate_json, string_ops, number_ops, array_ops,
|
||||
date_ops, cron, ai_transform_compile, ai_transform_run
|
||||
|
||||
### 審查任務(給 CC)
|
||||
|
||||
對 21 個零件逐一檢查,**只回報,不修改**:
|
||||
|
||||
```
|
||||
路徑:u6u-core/registry/components/
|
||||
|
||||
檢查四項:
|
||||
1. contract.yaml 存在?
|
||||
2. 有 credentials_required?(需要 token 的才需要)
|
||||
3. 有 config_example?
|
||||
4. main.go required 欄位與 contract input_schema required[] 一致?
|
||||
|
||||
回報格式:表格(✓ / ✗ / N/A)+ 每個零件缺少什麼
|
||||
不修改任何檔案。
|
||||
```
|
||||
|
||||
審查完成後,再逐一補充缺少的欄位。
|
||||
|
||||
---
|
||||
|
||||
## 任務三:workflow YAML 格式定義
|
||||
|
||||
### 格式設計原則
|
||||
|
||||
- `flow:` 用 `>>` 三元組描述資料流,人類直接看懂
|
||||
- 關係詞使用有語意的詞,**不使用 PIPE**(PIPE 等於什麼都沒說)
|
||||
- `config:` 用零件名稱對應參數,欄位從 contract 的 config_example 來
|
||||
- credential 全部集中在 `credentials.yaml`,workflow 只寫 `{{creds.KEY}}`
|
||||
|
||||
### 可用關係詞
|
||||
|
||||
| 關係詞 | 語意 | 使用時機 |
|
||||
|--------|------|---------|
|
||||
| `完成後` | 前一個成功後執行 | 最常用的串接 |
|
||||
| `失敗時` | 前一個失敗後執行 | 錯誤處理 |
|
||||
| `對每個` | 對陣列每個元素執行 | 迭代 |
|
||||
| `條件滿足時` | 條件分支 | 判斷 |
|
||||
| `ON_SUCCESS` | 同「完成後」 | 英文版 |
|
||||
| `ON_FAIL` | 同「失敗時」 | 英文版 |
|
||||
| `FOREACH` | 同「對每個」 | 英文版 |
|
||||
| `IF` | 同「條件滿足時」 | 英文版 |
|
||||
| `ON_CLICK` | 前端按鈕觸發 | UI 互動 |
|
||||
| `CALLS_SUBFLOW` | 呼叫子工作流 | 模組化 |
|
||||
|
||||
**禁止使用 PIPE** — 任何串接都應該用有語意的關係詞。
|
||||
|
||||
### workflow.yaml 範例
|
||||
|
||||
```yaml
|
||||
name: newsletter_subscribe
|
||||
description: 訂閱電子報,發感謝信並記錄到 GSheets
|
||||
|
||||
flow:
|
||||
- "input >> 完成後 >> send_thanks"
|
||||
- "input >> 完成後 >> save_to_sheet"
|
||||
- "send_thanks >> 完成後 >> output"
|
||||
- "send_thanks >> 失敗時 >> notify_error"
|
||||
- "save_to_sheet >> 完成後 >> output"
|
||||
|
||||
config:
|
||||
send_thanks: # componentId: gmail(由 cypher-executor 語意搜尋對應)
|
||||
to: "{{input.email}}"
|
||||
subject: "感謝訂閱!"
|
||||
body: "歡迎加入!"
|
||||
# access_token 由 credentials.yaml 的 gmail_token 自動注入
|
||||
|
||||
save_to_sheet: # componentId: google_sheets
|
||||
action: write
|
||||
spreadsheet_id: "{{creds.sheet_id}}"
|
||||
range: "訂閱者!A:B"
|
||||
values: [["{{input.email}}", "{{input.timestamp}}"]]
|
||||
# access_token 由 credentials.yaml 的 google_oauth 自動注入
|
||||
|
||||
notify_error: # componentId: telegram
|
||||
chat_id: "{{creds.telegram_chat_id}}"
|
||||
text: "發信失敗:{{input.email}}"
|
||||
# bot_token 由 credentials.yaml 的 telegram_bot_token 自動注入
|
||||
```
|
||||
|
||||
### credentials.yaml 範例
|
||||
|
||||
```yaml
|
||||
# credentials.yaml — 類似 .env,加入 .gitignore,不進 git
|
||||
# u6u creds push 時逐一加密上傳到 CREDENTIALS_KV
|
||||
|
||||
gmail_token: "ya29.a0AfB_..."
|
||||
google_oauth: "ya29.a0AfB_..."
|
||||
sheet_id: "1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgVE2upms"
|
||||
telegram_bot_token: "123456:ABC-..."
|
||||
telegram_chat_id: "987654321"
|
||||
```
|
||||
|
||||
### 執行時 credential 注入流程
|
||||
|
||||
```
|
||||
u6u run newsletter_subscribe
|
||||
↓
|
||||
cypher-executor 讀 workflow YAML
|
||||
↓
|
||||
遇到節點 send_thanks → 查 contract:credentials_required.inject_as = access_token
|
||||
↓
|
||||
去 CREDENTIALS_KV 讀 gmail_token → 解密
|
||||
↓
|
||||
注入到 WASM input:{ to, subject, body, access_token: "ya29..." }
|
||||
↓
|
||||
WASM 執行,用戶的 config 裡完全不出現 token
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 任務四:CLI 開發
|
||||
|
||||
### 技術選型
|
||||
|
||||
- **語言**:Node.js(TypeScript)
|
||||
- **安裝**:`npm i -g u6u`
|
||||
- **依賴**:`commander`、`js-yaml`、`chalk`、`ora`
|
||||
|
||||
### 指令規格
|
||||
|
||||
#### `u6u init`
|
||||
|
||||
互動式初始化,產生 `~/.u6u/config.yaml` 和本機 `credentials.yaml`。
|
||||
|
||||
```
|
||||
$ u6u init
|
||||
? Cloudflare Account ID: abc123
|
||||
? KV Namespace ID (WEBHOOKS): xyz789
|
||||
? KV Namespace ID (CREDENTIALS_KV): abc456
|
||||
? R2 Bucket name (WASM_BUCKET): u6u-wasm
|
||||
? Cypher Executor Worker URL: https://cypher-executor.xxx.workers.dev
|
||||
? Credentials Worker URL: https://u6u-credentials.xxx.workers.dev
|
||||
? Cloudflare API Token: ***
|
||||
|
||||
✓ 設定完成 → ~/.u6u/config.yaml
|
||||
✓ 建立 credentials.yaml(已加入 .gitignore)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### `u6u creds push [credentials.yaml]`
|
||||
|
||||
讀取 credentials.yaml,逐一加密上傳到 CREDENTIALS_KV。
|
||||
|
||||
```
|
||||
$ u6u creds push
|
||||
讀取 ./credentials.yaml...
|
||||
✓ gmail_token → 已加密上傳
|
||||
✓ google_oauth → 已加密上傳
|
||||
✓ sheet_id → 已上傳
|
||||
✓ telegram_bot_token → 已加密上傳
|
||||
✓ telegram_chat_id → 已上傳
|
||||
共上傳 5 個 credentials
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### `u6u push <workflow.yaml>`
|
||||
|
||||
解析 `flow:` 三元組,轉換成 triplets 陣列,上傳到 WEBHOOKS KV。
|
||||
|
||||
```
|
||||
$ u6u push newsletter_subscribe.yaml
|
||||
✓ 已上傳 newsletter_subscribe → WEBHOOKS KV
|
||||
Webhook: https://cypher-executor.xxx.workers.dev/webhook/abc123
|
||||
```
|
||||
|
||||
轉換邏輯(CLI 負責):
|
||||
|
||||
```
|
||||
flow[] 三元組
|
||||
↓
|
||||
POST /cypher/search(取得 ExecutionGraph)
|
||||
↓
|
||||
連同 config 存入 WEBHOOKS KV
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### `u6u run <workflow_name> [--input key=value...]`
|
||||
|
||||
觸發執行,顯示結果。
|
||||
|
||||
```
|
||||
$ u6u run newsletter_subscribe --input email=test@example.com
|
||||
⏳ 執行中...
|
||||
✓ 完成(2.3s)
|
||||
|
||||
結果:
|
||||
send_thanks: { success: true, data: { message_id: "xxx" } }
|
||||
save_to_sheet: { success: true, data: { range: "訂閱者!A2" } }
|
||||
```
|
||||
|
||||
錯誤時給出具體修復步驟:
|
||||
|
||||
```
|
||||
✗ 執行失敗:節點 send_thanks
|
||||
原因: access_token 無效(401 Unauthorized)
|
||||
|
||||
修復方式:
|
||||
1. 更新 credentials.yaml 的 gmail_token
|
||||
2. 執行 u6u creds push
|
||||
3. 重新執行 u6u run newsletter_subscribe
|
||||
|
||||
取得 Google OAuth token:
|
||||
→ https://developers.google.com/oauthplayground
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### `u6u validate <workflow.yaml>`
|
||||
|
||||
執行前完整驗證,提前發現問題。
|
||||
|
||||
```
|
||||
$ u6u validate newsletter_subscribe.yaml
|
||||
✓ YAML 格式正確
|
||||
✓ flow 三元組語法正確
|
||||
✓ 所有關係詞有效(無 PIPE)
|
||||
✓ 所有節點名稱在 config 有對應
|
||||
✓ 所有零件存在於 WASM_BUCKET
|
||||
✓ credentials 對應:
|
||||
gmail_token ✓ 已上傳
|
||||
google_oauth ✓ 已上傳
|
||||
sheet_id ✓ 已上傳
|
||||
telegram_bot_token ✗ 缺少
|
||||
|
||||
⚠ 缺少 1 個 credential:
|
||||
telegram_bot_token → 請加入 credentials.yaml 並執行 u6u creds push
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### `u6u parts`
|
||||
|
||||
列出可用零件。
|
||||
|
||||
```
|
||||
$ u6u parts
|
||||
可用零件(21):
|
||||
|
||||
[整合]
|
||||
• gmail Gmail 發信
|
||||
需要: to, subject, body
|
||||
credential: gmail_token(google_oauth)
|
||||
• google_sheets 讀寫 Google 試算表
|
||||
需要: spreadsheet_id, range, action
|
||||
credential: google_oauth
|
||||
• telegram Telegram Bot 發訊息
|
||||
需要: chat_id, text
|
||||
credential: telegram_bot_token
|
||||
• line_notify LINE Notify
|
||||
需要: message
|
||||
credential: line_token
|
||||
• http_request 任意 HTTP 請求
|
||||
需要: url
|
||||
|
||||
[控制]
|
||||
• if_control 條件分支
|
||||
• foreach_control 迭代執行
|
||||
• try_catch 錯誤處理
|
||||
• switch 多路路由
|
||||
• wait 等待 N 毫秒
|
||||
|
||||
[資料]
|
||||
• set / filter / merge / string_ops / number_ops / array_ops / date_ops
|
||||
|
||||
[AI]
|
||||
• ai_transform_compile 自然語言 → JS 轉換函式
|
||||
• ai_transform_run 執行已編譯的轉換
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### `u6u parts scaffold <component>`
|
||||
|
||||
從 contract 的 config_example 產出可直接貼入 workflow 的 config 範本。
|
||||
|
||||
```
|
||||
$ u6u parts scaffold gmail
|
||||
|
||||
貼入 workflow.yaml 的 config 區塊:
|
||||
|
||||
send_email: # 節點名稱(可自訂)
|
||||
to: "" # 收件人 Email(必填)
|
||||
subject: "" # 主旨(必填)
|
||||
body: "" # 內文(必填)
|
||||
# access_token 由 credentials.yaml 的 gmail_token 自動注入
|
||||
|
||||
貼入 credentials.yaml:
|
||||
|
||||
gmail_token: "" # Google OAuth token
|
||||
# 取得方式:https://developers.google.com/oauthplayground
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### `u6u list`
|
||||
|
||||
列出 WEBHOOKS KV 中所有 workflow。
|
||||
|
||||
```
|
||||
$ u6u list
|
||||
• newsletter_subscribe (更新: 2026-04-16)
|
||||
• daily_summary (更新: 2026-04-15)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### `u6u logs <workflow_name>`
|
||||
|
||||
查看最近執行記錄。
|
||||
|
||||
```
|
||||
$ u6u logs newsletter_subscribe
|
||||
2026-04-16 14:30 ✓ 成功 2.1s
|
||||
2026-04-16 09:00 ✗ 失敗 send_thanks: 401 Unauthorized
|
||||
2026-04-15 09:00 ✓ 成功 1.8s
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 開發順序
|
||||
|
||||
### Phase 1:搬移與清理(先做)
|
||||
|
||||
```
|
||||
1. 建立新的獨立 repo:u6u-core
|
||||
2. 從 matrix 搬入:
|
||||
- cypher-executor/
|
||||
- u6u-core/credentials/
|
||||
- u6u-core/builtins/
|
||||
- u6u-core/registry/
|
||||
3. 清理 cypher-executor/wrangler.toml(移除 InkStone 內部 bindings)
|
||||
4. 確認 component-loader 只依賴 WASM_BUCKET,不依賴 KBDB / REGISTRY
|
||||
5. 本機部署測試
|
||||
```
|
||||
|
||||
### Phase 2:零件完成度(搬移後)
|
||||
|
||||
```
|
||||
6. 審查 21 個零件的 contract.yaml
|
||||
7. 補充 credentials_required(gmail, google_sheets, telegram, line_notify)
|
||||
8. 補充 config_example(全部 21 個)
|
||||
9. 驗證 main.go required 欄位與 contract 一致
|
||||
```
|
||||
|
||||
### Phase 3:CLI(完成度補充後)
|
||||
|
||||
```
|
||||
10. u6u init
|
||||
11. u6u creds push
|
||||
12. u6u push
|
||||
13. u6u run(含 credential 自動注入)
|
||||
14. u6u parts / u6u parts scaffold
|
||||
15. u6u validate
|
||||
16. u6u list / u6u logs
|
||||
```
|
||||
|
||||
### Phase 4:開源發布
|
||||
|
||||
```
|
||||
17. 撰寫 README.md(快速開始、零件列表、workflow 語法說明)
|
||||
18. 撰寫 CONTRIBUTING.md(如何新增零件)
|
||||
19. 發布到 GitHub
|
||||
20. npm publish(u6u CLI)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 不在此次範圍
|
||||
|
||||
- KBDB 整合(未來付費服務)
|
||||
- 向量搜尋 / graph 查詢
|
||||
- 前端管理介面
|
||||
- Webhook trigger 設定(用戶自行設定 CF Cron)
|
||||
- 新增 WASM 零件(現有 21 個先做完整,之後再擴充)
|
||||
Reference in New Issue
Block a user