docs: add SDD specs + user requirements + tests
- .agents/specs/: spec-driven-dev docs for arcrun MVP, auth-recipe, credential-primitives-wasm (active refactor), landing-page, sdk-and-website, u6u-core-mvp, u6u-platform-evolution. - .agents/steerings/tech.md: detailed tech stack rationale. - docs/user_requirements/: long-form requirements incl. credential primitives, pages spec, py strategy analysis. - tests/: end-to-end harness scaffolding. These are the durable context backing CLAUDE.md's SDD protocol. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,281 @@
|
||||
# Design Document: arcrun SDK Libraries + Website
|
||||
|
||||
## Overview
|
||||
|
||||
本設計涵蓋 arcrun 的三個新增交付物:
|
||||
1. Python SDK lib(`pip install arcrun`)
|
||||
2. JS/TS SDK lib(`npm install arcrun` 或 `@arcrun/sdk`)
|
||||
3. arcrun.dev 網站完善(零件列表、recipe 列表、登入管理)
|
||||
|
||||
**設計原則:修改不重建。** SDK 是 `cypher.arcrun.dev` HTTP API 的 thin wrapper。不在 client 端重新實作任何 server 端已有的邏輯(workflow 執行、credential 注入、auth recipe 解析)。唯一在 client 做的是 AES-GCM 加密(因為 server 的 POST /credentials 期望收到加密後的 payload)。
|
||||
|
||||
---
|
||||
|
||||
## Architecture
|
||||
|
||||
### 系統關係圖
|
||||
|
||||
```
|
||||
使用者程式碼
|
||||
├── CLI(acr) → cypher.arcrun.dev(HTTP API)
|
||||
├── Python SDK(arcrun) → cypher.arcrun.dev(HTTP API)
|
||||
└── JS SDK(arcrun / @arcrun/sdk) → cypher.arcrun.dev(HTTP API)
|
||||
|
||||
arcrun.dev 網站(Next.js / Cloudflare Pages)
|
||||
├── /login → /auth/google/start, /auth/github/start(cypher.arcrun.dev)
|
||||
├── /dashboard → /me, /me/api-key/rotate(cypher.arcrun.dev)
|
||||
├── /integrations → /auth-recipes(cypher.arcrun.dev)
|
||||
└── /components → /recipes + 靜態零件清單(embedded)
|
||||
|
||||
cypher.arcrun.dev(Cloudflare Worker — cypher-executor,不改)
|
||||
├── POST /credentials ← 接收 { name, encrypted, iv }
|
||||
├── GET /credentials ← 列出 credential 名稱
|
||||
├── DELETE /credentials/:name ← 刪除 credential
|
||||
├── GET /auth-recipes ← 列出 20 個 auth recipe
|
||||
├── GET /auth-recipes/:service ← 單一 recipe 詳情
|
||||
├── POST /webhooks/named ← 部署 workflow
|
||||
├── POST /webhooks/named/:name/trigger ← 觸發 workflow
|
||||
├── GET /webhooks/named ← 列出 workflow
|
||||
├── POST /register ← 註冊取得 API Key
|
||||
├── GET /me ← 當前用戶資訊
|
||||
└── /auth/* ← OAuth 流程
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Python SDK(`arcrun/python-sdk/`)
|
||||
|
||||
### 目錄結構
|
||||
|
||||
```
|
||||
arcrun/python-sdk/
|
||||
├── pyproject.toml ← hatchling build, name="arcrun", deps=[httpx>=0.27, cryptography>=42]
|
||||
├── README.md
|
||||
└── arcrun/
|
||||
├── __init__.py ← from .client import Arcrun
|
||||
├── client.py ← Arcrun class(主入口)
|
||||
├── crypto.py ← AES-GCM 加密(client 端,用 cryptography 套件)
|
||||
├── creds.py ← CredentialsClient(push/list/delete)
|
||||
├── auth.py ← AuthClient(setup/bind/get_token/list_services)
|
||||
└── workflows.py ← WorkflowClient(run/push/list/delete)
|
||||
```
|
||||
|
||||
### API 設計
|
||||
|
||||
```python
|
||||
from arcrun import Arcrun
|
||||
|
||||
# 建構 — api_key 從參數 > 環境變數 > ~/.arcrun/config.yaml 自動取得
|
||||
client = Arcrun()
|
||||
# 或明確指定
|
||||
client = Arcrun(api_key="ak_xxx", encryption_key="hexstring")
|
||||
|
||||
# Auth:設定並綁定服務
|
||||
client.auth.setup("openai", api_key="sk-xxx") # 加密 + 上傳
|
||||
openai_client = client.auth.bind("openai") # 取回 pre-auth client
|
||||
response = openai_client.get("/models") # httpx.Client
|
||||
token = client.auth.get_token("openai") # raw token string
|
||||
services = client.auth.list_services() # [{ service, display_name, ... }]
|
||||
|
||||
# Credentials:低階操作
|
||||
client.creds.push("my_token", "value123")
|
||||
names = client.creds.list()
|
||||
client.creds.delete("my_token")
|
||||
|
||||
# Workflows
|
||||
result = client.workflows.run("my-flow", {"email": "user@example.com"})
|
||||
url = client.workflows.push("my-flow", graph_dict)
|
||||
workflows = client.workflows.list()
|
||||
```
|
||||
|
||||
### Credential 加密流程
|
||||
|
||||
```
|
||||
setup("openai", api_key="sk-xxx")
|
||||
1. GET /auth-recipes/openai → recipe(含 required_secrets, inject)
|
||||
2. 對應 required_secrets[0].key = "openai_api_key"
|
||||
3. crypto.py 用 encryption_key AES-GCM 加密 "sk-xxx"
|
||||
4. POST /credentials → { name: "openai_api_key", encrypted, iv }
|
||||
5. 本地 _cred_cache["openai_api_key"] = "sk-xxx"(供 bind() 用)
|
||||
|
||||
bind("openai")
|
||||
1. GET /auth-recipes/openai → recipe.inject.header = { Authorization: "Bearer {{secret.openai_api_key}}" }
|
||||
2. 用 _cred_cache["openai_api_key"] 替換 template → "Bearer sk-xxx"
|
||||
3. 回傳 AuthenticatedClient(base_url="https://api.openai.com/v1", headers={"Authorization": "Bearer sk-xxx"})
|
||||
```
|
||||
|
||||
**注意**:`bind()` 依賴 `setup()` 在同一 session 建立的 `_cred_cache`。跨 session 使用時(credential 已上傳但 cache 不存在),`bind()` 無法解析 template — 此時 `get_token()` 也無法返回值。**這是已知限制,封測期間先接受。** 長期解法是 server 提供 `/credentials/:name/secret` 解密端點(u6u-core/credentials 已有)。
|
||||
|
||||
### 關鍵差異:crypto.py 的定位
|
||||
|
||||
`crypto.py` 只做 **加密**(encrypt),不做解密。
|
||||
功能等同 `u6u-core/credentials/src/actions/crypto.ts` 的 `encrypt()` 函數。
|
||||
解密只在 server 端發生(cypher-executor 的 `credential-injector.ts` 或 `u6u-core/credentials/getCredentialSecret.ts`)。
|
||||
|
||||
---
|
||||
|
||||
## JS/TS SDK(`arcrun/js-sdk/`)
|
||||
|
||||
### 目錄結構
|
||||
|
||||
```
|
||||
arcrun/js-sdk/
|
||||
├── package.json ← name TBD(arcrun vs @arcrun/sdk),tsup build
|
||||
├── tsconfig.json ← ES2020, NodeNext
|
||||
└── src/
|
||||
├── index.ts ← export class Arcrun
|
||||
├── crypto.ts ← Web Crypto API AES-GCM encrypt(client 端)
|
||||
├── creds.ts ← CredentialsClient(push/list/delete)
|
||||
├── auth.ts ← AuthClient(setup/bind/getToken/listServices)
|
||||
└── workflows.ts ← WorkflowClient(run/push/list/delete)
|
||||
```
|
||||
|
||||
### API 與 Python SDK 對等
|
||||
|
||||
```typescript
|
||||
import { Arcrun } from 'arcrun' // or '@arcrun/sdk'
|
||||
|
||||
const client = new Arcrun() // reads ARCRUN_API_KEY from env
|
||||
|
||||
await client.auth.setup('openai', { api_key: 'sk-xxx' })
|
||||
const oai = await client.auth.bind('openai')
|
||||
const models = await (await oai.get('/models')).json()
|
||||
|
||||
const token = await client.auth.getToken('openai')
|
||||
const services = await client.auth.listServices()
|
||||
|
||||
await client.creds.push('my_token', 'value')
|
||||
const names = await client.creds.list()
|
||||
|
||||
const result = await client.workflows.run('my-flow', { email: 'user@example.com' })
|
||||
```
|
||||
|
||||
### Build 產物
|
||||
|
||||
```
|
||||
dist/
|
||||
├── index.js ← ESM
|
||||
├── index.cjs ← CJS
|
||||
├── index.d.ts ← TypeScript 型別
|
||||
└── index.d.cts
|
||||
```
|
||||
|
||||
### Crypto 實作
|
||||
|
||||
使用 Web Crypto API(`crypto.subtle`),相容 Node 18+ / browsers / CF Workers / Deno:
|
||||
|
||||
```typescript
|
||||
async function encrypt(plaintext: string, hexKey: string): Promise<{ encrypted: string; iv: string }> {
|
||||
const key = await crypto.subtle.importKey('raw', hexToBytes(hexKey), { name: 'AES-GCM' }, false, ['encrypt']);
|
||||
const iv = crypto.getRandomValues(new Uint8Array(12));
|
||||
const ciphertext = await crypto.subtle.encrypt({ name: 'AES-GCM', iv }, key, new TextEncoder().encode(plaintext));
|
||||
return { encrypted: toBase64(ciphertext), iv: toBase64(iv.buffer) };
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## arcrun.dev 網站
|
||||
|
||||
### 現有狀態(`arcrun/landing/`)
|
||||
|
||||
已完成:
|
||||
- [x] `/` — Hero + Code Demo(Python/JS/HTTP tabs)
|
||||
- [x] `/login` — Google + GitHub OAuth 按鈕(前端 OK,需設 OAuth secrets)
|
||||
- [x] `/dashboard` — API Key 查看/Copy/Rotate/Revoke(依賴 `/me` API)
|
||||
- [x] `/integrations` — 20 個 recipe 靜態卡片
|
||||
- [x] `/api-docs` — Swagger UI CDN 嵌入
|
||||
- [x] `middleware.ts` — 保護 `/dashboard`(未登入 → `/login`)
|
||||
- [x] Cloudflare Pages 部署
|
||||
|
||||
待完成:
|
||||
- [ ] OAuth secrets 設定(`GOOGLE_CLIENT_ID` / `GOOGLE_CLIENT_SECRET` / `GITHUB_CLIENT_ID` / `GITHUB_CLIENT_SECRET`)
|
||||
- [ ] `/components` 頁面(零件列表 — 21 個 WASM 零件的 input/output/config_example)
|
||||
- [ ] 首頁 code demo 更新為三種使用方式(CLI / Python / JS)
|
||||
- [ ] 登入流程真實驗證
|
||||
|
||||
### 新增頁面:`/components`
|
||||
|
||||
```
|
||||
/components
|
||||
├── 零件卡片(21 個)
|
||||
│ ├── canonical_id
|
||||
│ ├── display_name
|
||||
│ ├── description
|
||||
│ ├── input_schema(required / optional 欄位)
|
||||
│ ├── output_schema
|
||||
│ ├── credentials_required(if any)
|
||||
│ └── config_example(YAML code block)
|
||||
└── 分類篩選(邏輯 / API / 控制流)
|
||||
```
|
||||
|
||||
資料來源:靜態嵌入(從 `registry/components/*/component.contract.yaml` 在 build 時讀取),不依賴 runtime API。
|
||||
|
||||
### OAuth 設定(待 richblack 操作)
|
||||
|
||||
需要在 Cloudflare Worker 設定以下 secrets:
|
||||
|
||||
```bash
|
||||
wrangler secret put GOOGLE_CLIENT_ID --name arcrun-cypher-executor
|
||||
wrangler secret put GOOGLE_CLIENT_SECRET --name arcrun-cypher-executor
|
||||
wrangler secret put GITHUB_CLIENT_ID --name arcrun-cypher-executor
|
||||
wrangler secret put GITHUB_CLIENT_SECRET --name arcrun-cypher-executor
|
||||
wrangler secret put SESSION_SIGNING_SECRET --name arcrun-cypher-executor
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## server 端需要的修改
|
||||
|
||||
### cypher-executor 修改(最小化)
|
||||
|
||||
目前 `POST /credentials` 端點(`routes/credentials.ts`)接收 `{ name, encrypted, iv }` 後直接存 KV。
|
||||
|
||||
SDK 需要的改動:
|
||||
|
||||
1. **`GET /auth-recipes` 回應格式**:目前 list 端點回 `{ recipes: [...] }` 但 recipe 的 `service` 欄位是 key — SDK 已在 list_services() 正確處理 ✅
|
||||
|
||||
2. **`GET /auth-recipes/:service` 回應格式**:目前回 `{ success: true, recipe: {...} }` — SDK 需讀 `body.recipe` 而非 body 本身 ✅
|
||||
|
||||
3. **`POST /credentials` 不需改動** — SDK 自己做 AES-GCM 加密後送 `{ name, encrypted, iv }` ✅
|
||||
|
||||
4. **未來**:新增 `GET /credentials/:name/secret` 端點(解密返回 plaintext),讓跨 session 的 `bind()` 能工作。但此端點在 `u6u-core/credentials/src/actions/getCredentialSecret.ts` 已有實作 — 需要在 cypher-executor 整合或 Service Binding 到 u6u-credentials Worker。**封測後再做。**
|
||||
|
||||
---
|
||||
|
||||
## 不做的事(明確排除)
|
||||
|
||||
- ❌ 不在 SDK 裡做 workflow 解析或 YAML 處理 — 那是 CLI 的職責
|
||||
- ❌ 不在 SDK 裡做 server-side 解密 — 解密只在 server 端
|
||||
- ❌ 不建新的 credentials Worker — 用現有的
|
||||
- ❌ 不建新的 KV namespace — 用現有的 CREDENTIALS_KV
|
||||
- ❌ 不改 cypher-executor 的 credential-injector.ts — 那已經完成且測試通過
|
||||
|
||||
---
|
||||
|
||||
## 實作順序
|
||||
|
||||
```
|
||||
Phase 1:Python SDK 重建 + 測試
|
||||
1.1 重建 arcrun/python-sdk/(按本 SDD 的結構)
|
||||
1.2 修正上次的 bug:recipe 回應 wrapper、inject key "header" vs "headers"、secret key mapping
|
||||
1.3 對 cypher.arcrun.dev live 測試全部 API
|
||||
1.4 本地安裝測試(pip install -e .)
|
||||
|
||||
Phase 2:JS SDK 重建 + 測試
|
||||
2.1 重建 arcrun/js-sdk/(按本 SDD 的結構)
|
||||
2.2 同步修正 Python SDK 發現的所有 recipe 格式問題
|
||||
2.3 build(tsup)+ 本地測試
|
||||
|
||||
Phase 3:arcrun.dev 網站補完
|
||||
3.1 新增 /components 頁面
|
||||
3.2 更新首頁 code demo(三種使用方式)
|
||||
3.3 OAuth secrets 設定(需 richblack 操作 GCP / GitHub)
|
||||
3.4 登入流程驗證
|
||||
|
||||
Phase 4:GitHub README + 發布
|
||||
4.1 更新 arcrun/README.md — 三種 Quick Start
|
||||
4.2 pip publish(arcrun)
|
||||
4.3 npm publish(TBD 套件名)
|
||||
4.4 最終驗證:從零開始 pip install / npm install / 打 API
|
||||
```
|
||||
@@ -0,0 +1,131 @@
|
||||
# Requirements: arcrun SDK Libraries + Website
|
||||
|
||||
## Introduction
|
||||
|
||||
arcrun 目前有三個使用介面:
|
||||
1. **CLI**(`acr` 指令)— 已完成,用 YAML 定義 workflow 並推送執行
|
||||
2. **Python / JS SDK lib**(本次新增)— `pip install arcrun` / `npm install arcrun`,讓開發者在寫程式時直接用 arcrun 功能
|
||||
3. **arcrun.dev 網站**(本次完成)— 登入取得 API Key、管理 Key、瀏覽零件 / recipe 列表
|
||||
|
||||
**核心原則**:SDK lib 是 `cypher.arcrun.dev` HTTP API 的 thin wrapper。所有業務邏輯(加解密、credential 注入、workflow 執行)都在 server 端完成。Client 端不重做 server 已有的邏輯。
|
||||
|
||||
**現有基礎設施**(不重建,直接使用):
|
||||
- `cypher.arcrun.dev`:cypher-executor Worker(workflow 執行、credential 管理、auth recipe、webhook)
|
||||
- `u6u-core/credentials`:credential Worker(AES-GCM 加解密)— arcrun/credentials 是其 cherry-pick
|
||||
- `arcrun/cli`:CLI 工具(已發布 npm `arcrun@1.1.0`)
|
||||
- `arcrun/landing`:Next.js 前端(已部署 Cloudflare Pages,有 hero/login/dashboard/integrations 骨架)
|
||||
|
||||
---
|
||||
|
||||
## Glossary
|
||||
|
||||
- **SDK lib**:Python / JS 套件,wrapping `cypher.arcrun.dev` HTTP API,安裝後可在程式碼中直接使用
|
||||
- **auth.setup()**:上傳一個服務的 credential(如 Notion token、OpenAI API Key)到 arcrun
|
||||
- **auth.bind()**:取回已設定服務的 pre-authenticated HTTP client
|
||||
- **auth.get_token()**:取回某服務的 raw token(escape hatch,給官方 SDK 用)
|
||||
- **workflows.run()**:觸發已部署的 workflow
|
||||
- **workflows.push()**:上傳 workflow 定義
|
||||
- **Recipe**:描述「如何對某服務認證」的 YAML 設定,存在 RECIPES KV
|
||||
|
||||
---
|
||||
|
||||
## Requirements
|
||||
|
||||
### Requirement 1:Python SDK(`pip install arcrun`)
|
||||
|
||||
**User Story:** As a Python 開發者, I want `pip install arcrun` 後在程式碼中使用 arcrun, so that 不用離開寫程式環境就能串接 20+ 服務。
|
||||
|
||||
#### Acceptance Criteria
|
||||
|
||||
1. THE Python SDK SHALL 以 `arcrun` 套件名發布到 PyPI,支援 Python 3.10+。
|
||||
2. THE SDK SHALL 提供以下 API:
|
||||
- `Arcrun(api_key=, base_url=)` — 建構 client,api_key 支援從環境變數 `ARCRUN_API_KEY` 或 `~/.arcrun/config.yaml` 自動讀取
|
||||
- `client.health()` — 健康檢查
|
||||
- `client.auth.list_services()` — 列出可用 auth recipe 服務
|
||||
- `client.auth.setup(service, **kwargs)` — 上傳 credential
|
||||
- `client.auth.bind(service)` — 取得 pre-authenticated HTTP client
|
||||
- `client.auth.get_token(service)` — 取得 raw token
|
||||
- `client.creds.push(name, value)` — 上傳加密 credential
|
||||
- `client.creds.list()` — 列出 credential 名稱
|
||||
- `client.creds.delete(name)` — 刪除 credential
|
||||
- `client.workflows.run(name, input)` — 觸發 workflow
|
||||
- `client.workflows.push(name, graph)` — 上傳 workflow
|
||||
- `client.workflows.list()` — 列出已部署 workflow
|
||||
3. THE SDK 的 credential 加密 SHALL 在 client 端完成(使用 `cryptography` 套件 AES-GCM),然後以 `POST /credentials` 上傳加密後的 `{ name, encrypted, iv }` 到 server。
|
||||
4. THE `auth.bind()` SHALL 從 server 取得 auth recipe 的 inject template,在 client 端用 cache 的 plaintext 值填入,回傳 pre-configured `httpx.Client`。
|
||||
5. THE SDK SHALL 使用 `httpx` 做 HTTP client(async 版使用 `httpx.AsyncClient`)。
|
||||
6. THE SDK 位置 SHALL 為 `arcrun/python-sdk/`,build 系統用 `hatchling`(`pyproject.toml`)。
|
||||
|
||||
---
|
||||
|
||||
### Requirement 2:JavaScript/TypeScript SDK(`npm install arcrun`)
|
||||
|
||||
**User Story:** As a JS/TS 開發者, I want `npm install arcrun` 後在程式碼中使用 arcrun, so that 可以嵌入現有 Node.js / Deno / Cloudflare Workers 專案。
|
||||
|
||||
#### Acceptance Criteria
|
||||
|
||||
1. THE JS SDK SHALL 以 `arcrun` 套件名發布到 npm,提供 ESM + CJS 雙格式 + TypeScript 型別定義。
|
||||
2. THE SDK SHALL 提供與 Python SDK 對等的 API(camelCase 版):
|
||||
- `new Arcrun({ apiKey?, baseUrl? })` — 讀 `process.env.ARCRUN_API_KEY`
|
||||
- `client.health()` — 回傳 `Promise<unknown>`
|
||||
- `client.auth.listServices()` / `setup()` / `bind()` / `getToken()`
|
||||
- `client.creds.push()` / `list()` / `delete()`
|
||||
- `client.workflows.run()` / `push()` / `list()` / `delete()`
|
||||
3. THE SDK 的 credential 加密 SHALL 使用 Web Crypto API(`crypto.subtle` AES-GCM),相容 Node 18+、browsers、Cloudflare Workers、Deno。
|
||||
4. THE `auth.bind()` SHALL 回傳一個有 `get/post/put/delete/patch` 方法的 `AuthenticatedClient`,base URL + auth headers 已配置。
|
||||
5. THE SDK SHALL 使用原生 `fetch()` API,不依賴外部 HTTP client 套件。
|
||||
6. THE SDK 位置 SHALL 為 `arcrun/js-sdk/`,build 用 `tsup`(ESM + CJS + DTS),`tsconfig.json` target ES2020 + NodeNext module。
|
||||
7. THE JS SDK 套件名與 CLI 套件名衝突(都叫 `arcrun`),SHALL 使用 `@arcrun/sdk` 或由 richblack 決定套件名。
|
||||
|
||||
---
|
||||
|
||||
### Requirement 3:arcrun.dev 網站完成
|
||||
|
||||
**User Story:** As a 潛在用戶, I want 在 arcrun.dev 上登入取得 API Key、瀏覽零件和 recipe 列表, so that 我可以評估 arcrun 是否符合需求並立即開始使用。
|
||||
|
||||
#### Acceptance Criteria
|
||||
|
||||
1. THE 網站 SHALL 在 `arcrun.dev` 提供以下頁面:
|
||||
- `/` — 首頁 Hero + 三種使用方式(CLI / Python / JS)
|
||||
- `/login` — Google + GitHub OAuth 登入
|
||||
- `/dashboard` — 登入後顯示 API Key(查看/Copy/Rotate/Revoke)
|
||||
- `/integrations` — 列出 20 個 auth recipe 服務,可按分類篩選
|
||||
- `/components` — 列出所有零件(21 個 WASM 零件),顯示 input/output schema、config_example
|
||||
- `/api-docs` — Swagger UI,可直接試打 API
|
||||
2. THE 登入 SHALL 使用 Google + GitHub OAuth,流程走 `cypher.arcrun.dev` 的 `/auth/*` 端點。
|
||||
3. THE 登入後 SHALL 自動對該 email 呼叫 `/register` 取得 API Key(若已有則取回現有 key)。
|
||||
4. THE `/dashboard` SHALL 允許 Rotate(生成新 key)、Revoke(標記失效)、Copy to clipboard。
|
||||
5. THE 網站 SHALL 部署在 Cloudflare Pages(現有 `arcrun/landing`),使用 Next.js App Router。
|
||||
6. THE 首頁 code demo 區 SHALL 包含三個 tab:Python、JavaScript、HTTP/curl,展示三種使用方式。
|
||||
|
||||
---
|
||||
|
||||
### Requirement 4:GitHub README 更新
|
||||
|
||||
**User Story:** As a GitHub 訪客, I want README 清楚說明三種使用方式, so that 我能選擇最適合的方式開始用 arcrun。
|
||||
|
||||
#### Acceptance Criteria
|
||||
|
||||
1. THE `arcrun/README.md` SHALL 包含三種 Quick Start:
|
||||
- **CLI**:`npm i -g arcrun && acr init && acr push workflow.yaml && acr run`
|
||||
- **Python**:`pip install arcrun && from arcrun import Arcrun && ...`
|
||||
- **JavaScript**:`npm install arcrun && import { Arcrun } from 'arcrun' && ...`
|
||||
2. THE README SHALL 包含完整零件列表(21 個)和 auth recipe 列表(20 個服務)。
|
||||
3. THE README SHALL 連結到 `arcrun.dev`(取得 API Key)和 Swagger UI(API 文件)。
|
||||
|
||||
---
|
||||
|
||||
### Requirement 5:SDK 發布
|
||||
|
||||
**User Story:** As a SDK 使用者, I want 公開安裝並直接使用, so that 不需要從原始碼 build。
|
||||
|
||||
#### Acceptance Criteria
|
||||
|
||||
1. THE Python SDK SHALL 發布到 PyPI,`pip install arcrun` 可安裝。
|
||||
2. THE JS SDK SHALL 發布到 npm,`npm install arcrun`(或 `@arcrun/sdk`)可安裝。
|
||||
3. THE 發布前 SHALL 完成以下測試(對 `cypher.arcrun.dev` live API):
|
||||
- `health()` ✅
|
||||
- `auth.list_services()` ✅
|
||||
- `auth.setup()` + `auth.bind()` ✅(至少一個 static_key 服務如 openai)
|
||||
- `creds.push()` + `creds.list()` ✅
|
||||
- `workflows.list()` ✅
|
||||
@@ -0,0 +1,120 @@
|
||||
# Implementation Plan: arcrun SDK Libraries + Website
|
||||
|
||||
## Overview
|
||||
|
||||
按 Design 的四個 Phase 實作。原則:修改不重建,SDK 是 HTTP API thin wrapper,加密只在 client 做 encrypt(不做 decrypt)。
|
||||
|
||||
**前置依賴**:必須先完成 `credential-primitives-wasm/tasks.md` 的 Phase 0-3(核心合併 + WASM primitives),確認核心穩定後才開始建三個介面。
|
||||
|
||||
---
|
||||
|
||||
## Phase 0(前置):核心合併 + WASM 改寫
|
||||
|
||||
> 詳見 `.agents/specs/arcrun/credential-primitives-wasm/tasks.md`
|
||||
>
|
||||
> 摘要:
|
||||
> - 合併 u6u-core → arcrun(搬 builtins、刪重複 credentials)
|
||||
> - credential-injector TS → auth_static_key / auth_service_account WASM
|
||||
> - 刪除 component-loader 內建 API recipes TS
|
||||
> - 驗證 20 個 auth recipe 正常運作
|
||||
|
||||
---
|
||||
|
||||
## Phase 1:Python SDK
|
||||
|
||||
- [ ] 1. 建立 `arcrun/python-sdk/` 目錄
|
||||
- [ ] 1.1 `pyproject.toml`:name=arcrun, deps=[httpx>=0.27, cryptography>=42], build-system=hatchling
|
||||
- [ ] 1.2 `arcrun/__init__.py`:`from .client import Arcrun`
|
||||
- [ ] 1.3 `arcrun/crypto.py`:AES-GCM encrypt only(使用 `cryptography` 套件)
|
||||
- [ ] 1.4 `arcrun/creds.py`:CredentialsClient — push(加密 + POST /credentials)、list(GET /credentials)、delete
|
||||
- [ ] 1.5 `arcrun/auth.py`:AuthClient — setup(fetch recipe → match secrets → encrypt → push)、bind(fetch recipe → resolve headers from cache → return AuthenticatedClient)、get_token、list_services
|
||||
- [ ] 1.6 `arcrun/workflows.py`:WorkflowClient — run(POST /webhooks/named/{name}/trigger)、push(POST /webhooks/named)、list(GET /webhooks/named)、delete
|
||||
- [ ] 1.7 `arcrun/client.py`:Arcrun class — 讀 api_key / encryption_key 從 param > env > config.yaml
|
||||
|
||||
- [ ] 2. 修正上次已知的 bug
|
||||
- [ ] 2.1 `_fetch_recipe()` 回應是 `{ success: true, recipe: {...} }`,需讀 `.recipe` 欄位
|
||||
- [ ] 2.2 `inject` 下的 key 是 `header`(singular),不是 `headers`
|
||||
- [ ] 2.3 `required_secrets[].key` 是 prefixed(如 `openai_api_key`),setup() 的 kwargs alias 要能對應
|
||||
- [ ] 2.4 `list_services()` 回應的 recipe 用 `service` 欄位(不是 `service_id`)
|
||||
|
||||
- [ ] 3. 測試(對 cypher.arcrun.dev live API)
|
||||
- [ ] 3.1 `health()` → `{"ok": true}`
|
||||
- [ ] 3.2 `auth.list_services()` → 20 個服務
|
||||
- [ ] 3.3 `auth.setup("openai", api_key="sk-test-dummy")` → 成功
|
||||
- [ ] 3.4 `auth.bind("openai")` → AuthenticatedClient with Authorization header
|
||||
- [ ] 3.5 `auth.get_token("openai")` → "sk-test-dummy"
|
||||
- [ ] 3.6 `creds.push("test_token", "value123")` → 成功
|
||||
- [ ] 3.7 `creds.list()` → 含 "test_token"(注意 KV eventual consistency)
|
||||
- [ ] 3.8 `workflows.list()` → []
|
||||
- [ ] 3.9 cleanup: `creds.delete("test_token")`
|
||||
|
||||
---
|
||||
|
||||
## Phase 2:JS/TS SDK
|
||||
|
||||
- [ ] 4. 建立 `arcrun/js-sdk/` 目錄
|
||||
- [ ] 4.1 `package.json`:name TBD(arcrun vs @arcrun/sdk),deps=devDeps only(tsup, typescript, @types/node)
|
||||
- [ ] 4.2 `tsconfig.json`:ES2020, NodeNext
|
||||
- [ ] 4.3 `src/crypto.ts`:Web Crypto API AES-GCM encrypt only
|
||||
- [ ] 4.4 `src/creds.ts`:CredentialsClient — push/list/delete via fetch
|
||||
- [ ] 4.5 `src/auth.ts`:AuthClient — setup/bind/getToken/listServices
|
||||
- [ ] 4.6 `src/workflows.ts`:WorkflowClient — run/push/list/delete
|
||||
- [ ] 4.7 `src/index.ts`:export class Arcrun + re-exports
|
||||
|
||||
- [ ] 5. 同步修正(與 Python SDK 同樣的 recipe 格式問題)
|
||||
- [ ] 5.1 `_fetchRecipe()` 讀 `body.recipe`
|
||||
- [ ] 5.2 inject key: `header` not `headers`
|
||||
- [ ] 5.3 setup() secret key alias matching
|
||||
- [ ] 5.4 listServices() 用 `service` 欄位
|
||||
|
||||
- [ ] 6. Build + 測試
|
||||
- [ ] 6.1 `tsup` build → dist/index.js + dist/index.cjs + dist/index.d.ts
|
||||
- [ ] 6.2 Node.js 腳本對 live API 測試(同 Python 測試項目)
|
||||
|
||||
---
|
||||
|
||||
## Phase 3:arcrun.dev 網站
|
||||
|
||||
- [ ] 7. 新增 `/components` 頁面
|
||||
- [ ] 7.1 從 `registry/components/*/component.contract.yaml` 讀取 21 個零件資料
|
||||
- [ ] 7.2 卡片顯示:canonical_id, display_name, description, input required/optional, credentials_required, config_example
|
||||
- [ ] 7.3 分類篩選:邏輯類 / API 類 / 控制流類
|
||||
|
||||
- [ ] 8. 更新首頁
|
||||
- [ ] 8.1 Code demo tabs 改為 CLI / Python / JS 三個
|
||||
- [ ] 8.2 CLI tab 展示 `acr init → acr push → acr run`
|
||||
- [ ] 8.3 Python tab 展示 `pip install arcrun → Arcrun() → auth.setup → auth.bind`
|
||||
- [ ] 8.4 JS tab 展示 `npm install arcrun → new Arcrun() → auth.setup → auth.bind`
|
||||
|
||||
- [ ] 9. OAuth 流程補完
|
||||
- [ ] 9.1 確認 cypher-executor 的 `/auth/google/start`、`/auth/github/start`、`/auth/callback` 路由正確
|
||||
- [ ] 9.2 提供 richblack OAuth secrets 設定指令清單
|
||||
- [ ] 9.3 richblack 設定 secrets 後驗證登入流程
|
||||
|
||||
- [ ] 10. 部署
|
||||
- [ ] 10.1 Cloudflare Pages build + deploy
|
||||
- [ ] 10.2 驗證所有頁面可存取
|
||||
|
||||
---
|
||||
|
||||
## Phase 4:README + 發布
|
||||
|
||||
- [ ] 11. 更新 `arcrun/README.md`
|
||||
- [ ] 11.1 三種 Quick Start(CLI / Python / JS)
|
||||
- [ ] 11.2 零件列表(21 個)
|
||||
- [ ] 11.3 Auth Recipe 列表(20 個服務)
|
||||
- [ ] 11.4 連結到 arcrun.dev 和 Swagger UI
|
||||
|
||||
- [ ] 12. 發布
|
||||
- [ ] 12.1 Python SDK:`pip install build && python -m build && twine upload dist/*`
|
||||
- [ ] 12.2 JS SDK:`npm run build && npm publish`
|
||||
- [ ] 12.3 驗證:從零開始 `pip install arcrun` / `npm install arcrun` + hello world
|
||||
|
||||
---
|
||||
|
||||
## Notes
|
||||
|
||||
- JS SDK 套件名需 richblack 決定(`arcrun` 已被 CLI 佔用 → 可能用 `@arcrun/sdk`)
|
||||
- OAuth secrets 設定需 richblack 手動操作(GCP Console + GitHub Settings)
|
||||
- `bind()` 跨 session 限制是已知的,封測期間先接受
|
||||
- credential 加密用的 `encryption_key` 目前由 `/register` 回傳,`acr init` 自動存入 config
|
||||
Reference in New Issue
Block a user