Files
Arcrun/cypher-executor/scripts/seed-api-recipes.ts
T
Leo fb2d0b0c2d feat(self-hosted): acr init --self-hosted installer + recipe push 把關 + commit 部署 wasm
讓任何 CC 用自己的 CF 帳號一鍵 self-host arcrun(戰法轉 self-hosted 開源)。

Task 1 — acr init --self-hosted installer(用戶只給 CF Account ID + token,其餘自動):
- cli/src/lib/cf-api.ts: CfAccountClient(驗 token / 建 KV 冪等 / 建 R2 / 查 workers.dev subdomain)
- cli/src/lib/deploy.ts: 從 GitHub codeload tarball 拉部署物 → 注入用戶 KV id → wrangler deploy
  (tier1 component-builds 先、tier2 cypher-executor/registry 後;部分失敗誠實回報不假綠)
- cli/src/lib/api-recipe-seeds.ts: 10 個現役 API recipe 種子(KBDB 採 Supabase 模式)
- cli/src/commands/init.ts: initSelfHosted() 改寫成 installer 流程
- cli/src/commands/update.ts: acr update(拉新 ref 重部署)
- cypher-executor/scripts/seed-api-recipes.ts: prod 補灌腳本

Task 2 — recipe 入庫把關(封鎖自製零件後,CC 唯一能擴充的是 recipe):
- cli/src/commands/recipe.ts: 新增 probeRecipeEndpoint 打通檢查(提醒級不硬擋,
  含模板誠實說明待 run 才知,401/403 標多半缺 credential 非 bug)
- 資料外流提醒沿用既有 obtainExposureConsent(非 TTY 拒絕)

部署物產製:commit 預編譯 wasm 進 repo(推翻 rule 05「wasm 不 commit」):
- .gitignore: 放行 .component-builds/**/component.wasm(registry 中間產物仍排除)
- 只 commit 19 個正當零件 wasm;claude_api / km_writer / kbdb_upsert_block 排除
  (非薄殼、是把工作流硬塞進零件,違反 DECISIONS §1,待降級)
- rule 05 同步記錄此慣例變更 + 膨脹 trade-off

SDD: sdk-and-website/self-hosted-init.md(installer 定案)、
     component-gatekeeping/recipe-push-gatekeeping.md(recipe 把關)
README 重寫成單一 self-hosted 路徑。CLI typecheck exit 0。

未完(待 richblack):push 此 commit 到 GitHub 後 codeload 才拿得到 wasm;
用第二 CF 帳號端對端驗收 acr init --self-hosted。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-02 18:44:41 +08:00

79 lines
2.7 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.
/**
* seed-api-recipes.ts
*
* 將現役 API recipe 種子上傳至目標 cypher-executorprod 或 self-host)。
* 種子資料的單一來源在 CLI 端(cli/src/lib/api-recipe-seeds.ts),此腳本 import 它,
* 避免兩份種子定義漂移。
*
* 執行:
* npx tsx scripts/seed-api-recipes.ts
*
* 環境變數:
* ARCRUN_API_URL - 目標 cypher-executor,預設 https://cypher.arcrun.dev
* ARCRUN_API_KEY - X-Arcrun-API-KeyPOST /recipes 需要)
*
* 注意:API recipe 帶 endpoint(資料去向)→ POST /recipes 會要 exposure_consent
* data-exfil-warning)。seed 是平台預建、非用戶 push,腳本帶種子層級的 consent。
*
* 對應 SDD.agents/specs/arcrun/sdk-and-website/self-hosted-init.md §5
*/
import { API_RECIPE_SEEDS } from '../../cli/src/lib/api-recipe-seeds.js';
const BASE_URL = process.env.ARCRUN_API_URL ?? 'https://cypher.arcrun.dev';
const API_KEY = process.env.ARCRUN_API_KEY ?? '';
async function main() {
console.log(`\n Seeding ${API_RECIPE_SEEDS.length} API recipes → ${BASE_URL}\n`);
let ok = 0;
let fail = 0;
for (const recipe of API_RECIPE_SEEDS) {
process.stdout.write(` ${recipe.canonical_id.padEnd(24)} `);
try {
const res = await fetch(`${BASE_URL}/recipes`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
...(API_KEY ? { 'X-Arcrun-API-Key': API_KEY } : {}),
},
body: JSON.stringify({
canonical_id: recipe.canonical_id,
display_name: recipe.display_name,
description: recipe.description,
endpoint: recipe.endpoint,
method: recipe.method,
auth_service: recipe.auth_service,
// 種子層級的暴露同意:平台預建 recipe,非用戶互動 push。
// 格式須符合 cypher-executor ExposureConsentconfirmed_by_human + understood + confirmed_at)。
// 誠實標明來源是 seed,軌跡可審(mindset §7:機制價值是歸責+可審,非防偽)。
exposure_consent: {
confirmed_by_human: true,
understood: `platform seed recipe (api-recipe-seeds.ts): ${recipe.canonical_id}${recipe.endpoint}`,
confirmed_at: new Date().toISOString(),
},
}),
});
if (res.ok) {
console.log('✓');
ok++;
} else {
const err = await res.text().catch(() => '');
console.log(`✗ HTTP ${res.status}: ${err.slice(0, 120)}`);
fail++;
}
} catch (e) {
console.log(`✗ ${e instanceof Error ? e.message : String(e)}`);
fail++;
}
}
console.log(`\n 完成:${ok} 成功,${fail} 失敗\n`);
if (fail > 0) process.exit(1);
}
main();