aitable-workflow-cli 0.1.28 → 0.1.29-beta.1790736949347
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/assistant/assets/index-BA6il19d.css +1 -0
- package/dist/assistant/assets/{index-B3LvYfRW.js → index-BMzAOp70.js} +31 -31
- package/dist/assistant/index.html +2 -2
- package/dist/chunk-BBP5RVFU.js +15 -0
- package/dist/cli.js +180 -73
- package/dist/{config-ui-server-4SVD42Z3.js → config-ui-server-UWELHUH4.js} +1 -1
- package/dist/web/assets/index-Bnmnydwk.css +1 -0
- package/dist/web/assets/index-Dbs1xWB9.js +331 -0
- package/dist/web/index.html +2 -2
- package/dist/web/install.ps1 +173 -0
- package/dist/web/install.sh +188 -0
- package/package.json +3 -3
- package/templates/ai-native-sdlc/.env.example +11 -0
- package/templates/ai-native-sdlc/aitable-workflow.config.yml +47 -0
- package/templates/ai-native-sdlc/coding-agents.config.json +17 -0
- package/templates/ai-native-sdlc/docs/plans/2026-09-15-ai-native-sdlc-dual-staff-implementation-plan.md +150 -0
- package/templates/ai-native-sdlc/docs/plans/2026-09-15-ai-native-sdlc-dual-staff.md +213 -0
- package/templates/ai-native-sdlc/docs/plans/2026-09-16-domain-role-notification-routing.md +36 -0
- package/templates/ai-native-sdlc/docs/plans/2026-09-16-execution-resume-and-cr-loop.md +29 -0
- package/templates/ai-native-sdlc/docs/plans/2026-09-16-project-handoff.md +148 -0
- package/templates/ai-native-sdlc/docs/plans/2026-09-17-prd-code-context-and-readable-prompts.md +37 -0
- package/templates/ai-native-sdlc/docs/plans/2026-09-21-plan-merge-sync-and-agent-source.md +19 -0
- package/templates/ai-native-sdlc/docs/plans/2026-09-21-sdlc-base-ref-and-review-notification.md +18 -0
- package/templates/ai-native-sdlc/docs/plans/2026-09-29-borrow-from-joe-design.md +943 -0
- package/templates/ai-native-sdlc/lib/artifacts.ts +126 -0
- package/templates/ai-native-sdlc/lib/recipe-config.ts +34 -0
- package/templates/ai-native-sdlc/lib/recipe-helpers.ts +595 -0
- package/templates/ai-native-sdlc/npmrc +1 -0
- package/templates/ai-native-sdlc/package.json +19 -0
- package/templates/ai-native-sdlc/profile/profile.yml +115 -0
- package/templates/ai-native-sdlc/setup/module-config.seed.json +37 -0
- package/templates/ai-native-sdlc/test/artifacts.test.ts +72 -0
- package/templates/ai-native-sdlc/test/recipe-helpers.test.ts +931 -0
- package/templates/ai-native-sdlc/tsconfig.json +17 -0
- package/templates/ai-native-sdlc/workflows/.gitkeep +3 -0
- package/templates/ai-native-sdlc/workflows/execution/automations/blocked-questions-dev.json +91 -0
- package/templates/ai-native-sdlc/workflows/execution/automations/blocked-questions.json +91 -0
- package/templates/ai-native-sdlc/workflows/execution/automations/cr-review-dev.json +80 -0
- package/templates/ai-native-sdlc/workflows/execution/automations/cr-review.json +81 -0
- package/templates/ai-native-sdlc/workflows/execution/automations/resume-answers.json +42 -0
- package/templates/ai-native-sdlc/workflows/execution/automations/spec-review-dev.json +138 -0
- package/templates/ai-native-sdlc/workflows/execution/recipes/coding.recipe.ts +161 -0
- package/templates/ai-native-sdlc/workflows/execution/recipes/prd-review.recipe.ts +200 -0
- package/templates/ai-native-sdlc/workflows/execution/recipes/prd.recipe.ts +163 -0
- package/templates/ai-native-sdlc/workflows/execution/recipes/review.recipe.ts +257 -0
- package/templates/ai-native-sdlc/workflows/execution/recipes/spec-review.recipe.ts +242 -0
- package/templates/ai-native-sdlc/workflows/execution/recipes/spec.recipe.ts +173 -0
- package/templates/ai-native-sdlc/workflows/execution/workflow.yml +79 -0
- package/templates/ai-native-sdlc/workflows/intake/automations/accept-intake.json +101 -0
- package/templates/ai-native-sdlc/workflows/intake/recipes/classify-module.recipe.ts +133 -0
- package/templates/ai-native-sdlc/workflows/intake/recipes/create-change.recipe.ts +94 -0
- package/templates/ai-native-sdlc/workflows/intake/recipes/mechanical-deduplicate.recipe.ts +33 -0
- package/templates/ai-native-sdlc/workflows/intake/workflow.yml +62 -0
- package/templates/ai-native-sdlc/workspaces/dev/AGENTS.md +69 -0
- package/templates/ai-native-sdlc/workspaces/pm/AGENTS.md +48 -0
- package/templates/ai-native-sdlc/workspaces/reviewer/AGENTS.md +79 -0
- package/dist/assistant/assets/index-CCEHOkkJ.css +0 -1
- package/dist/chunk-YDJTCQW4.js +0 -15
- package/dist/web/assets/index-DPc2WOdp.css +0 -1
- package/dist/web/assets/index-HTw8K38o.js +0 -332
package/dist/cli.js
CHANGED
|
@@ -1,24 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import{a as
|
|
2
|
+
import{a as Ct,b as re,m as At}from"./chunk-BBP5RVFU.js";import"./chunk-4B6V7VHM.js";import{b as ne,d as J,e as We,f as xt,g as oe}from"./chunk-N2ATMPTO.js";import{a}from"./chunk-EI7MMDWY.js";import{config as Cn}from"dotenv";import{Command as xa}from"commander";import{logger as bn,activateGlobalDwsOnPath as Ta,initSlsReport as Ea}from"aitable-workflow-core";import{createRequire as En}from"module";var Tt="aitable-workflow-",Sn=/^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?$/;function Et(){try{return En(import.meta.url)("../package.json")}catch{return{}}}a(Et,"loadCliPackageManifest");function Ue(n){return n.version??"0.0.0"}a(Ue,"resolveCliVersion");function St(n){let e=Ue(n),t={};n.name?.startsWith(Tt)&&(t[n.name]=e);for(let[r,o]of Object.entries(n.dependencies??{}))r.startsWith(Tt)&&(t[r]=Sn.test(o)?o:e);return t}a(St,"resolveMonorepoPackageVersions");import An from"path";import{fileURLToPath as Sa}from"url";var It="./aitable-workflow.config.yml";import{runInit as In,logger as Pn}from"aitable-workflow-core";import _n from"path";function Pt(n,e){n.command("init").description("\u4EA4\u4E92\u5F0F\u521D\u59CB\u5316 \u2014 \u9009\u62E9 Coding Agent\u3001\u914D\u7F6E\u5DE5\u4F5C\u76EE\u5F55\u3001\u63CF\u8FF0\u4E1A\u52A1\u573A\u666F\uFF1B\u6216\u7528 --template \u4ECE\u53EF\u7528\u6A21\u677F\u811A\u624B\u67B6").option("-c, --config <path>","\u76EE\u6807\u76EE\u5F55\u6216\u914D\u7F6E\u6587\u4EF6\u8DEF\u5F84\uFF08\u9ED8\u8BA4\u5F53\u524D\u76EE\u5F55\uFF09").option("-f, --force","\u8986\u76D6\u5DF2\u6709\u914D\u7F6E\u6587\u4EF6").option("-y, --yes","\u4F7F\u7528\u9ED8\u8BA4\u503C\u8DF3\u8FC7\u4EA4\u4E92\u5F0F\u5411\u5BFC").option("-t, --template <name>","\u4ECE\u5F53\u524D\u53D1\u884C\u5305\u63D0\u4F9B\u7684\u6A21\u677F\u811A\u624B\u67B6\uFF0C\u62F7\u8D1D\u5B8C\u6574\u53EF\u8FD0\u884C\u9879\u76EE\u5230\u76EE\u6807\u76EE\u5F55").option("--profile <name>","\u9009\u5B9A\u6A21\u677F\u4E0B\u7684 profile \u4E1A\u52A1\u5305\uFF0C\u8986\u76D6\u5F0F\u53E0\u52A0\u5230\u5B9E\u4F8B").action(async t=>{try{await In({config:t.config,force:!!t.force,yes:!!t.yes,template:t.template,profile:t.profile,templatesDir:_n.resolve(e.cliDir,"..","templates"),templatePackageVersions:e.packageVersions,cliVersion:e.version})}catch(r){r instanceof Error&&r.message.includes("cancelled")&&process.exit(0),Pn.error("cli","\u521D\u59CB\u5316\u5931\u8D25",{error:r instanceof Error?r.message:String(r)}),process.exit(1)}})}a(Pt,"registerInitCommand");import{runMigrate as $n,logger as On}from"aitable-workflow-core";import jn from"path";function _t(n,e){n.command("migrate").description("\u5347\u7EA7\u9879\u76EE\u76EE\u5F55\u5230\u6700\u65B0\u6A21\u677F\u7248\u672C\uFF0C\u81EA\u52A8\u4FDD\u7559\u7528\u6237\u914D\u7F6E\uFF1B\u6216\u7528 --from/--to \u5728\u4E24\u4E2A\u76EE\u5F55\u95F4\u505A\u5408\u5E76\u8FC1\u79FB").option("-c, --config <path>","\u9879\u76EE\u76EE\u5F55\u8DEF\u5F84",e.defaultConfig).option("--from <dir>","\u6E90\u76EE\u5F55\uFF1A\u4EE5\u8BE5\u76EE\u5F55\u4E3A\u8FC1\u79FB\u57FA\u51C6\uFF08\u4E0D\u6309\u540D scaffold \u6A21\u677F\uFF09\uFF0C\u4E0E --template/--profile \u4E92\u65A5").option("--to <dir>","\u76EE\u6807\u9879\u76EE\u76EE\u5F55\uFF08--config \u7684\u540C\u4E49\u53C2\u6570\uFF0C\u4F18\u5148\u751F\u6548\uFF09").option("--dry-run","\u4EC5\u9884\u89C8\u53D8\u66F4\uFF0C\u4E0D\u5B9E\u9645\u5199\u5165").option("--no-backup","\u8DF3\u8FC7\u81EA\u52A8\u5907\u4EFD").option("--force","\u8DF3\u8FC7\u786E\u8BA4\u63D0\u793A").option("--template <name>","\u6307\u5B9A\u76EE\u6807\u6A21\u677F").option("--profile <name>","\u6307\u5B9A\u76EE\u6807 profile").option("--rollback","\u56DE\u6EDA\u5230\u4E0A\u4E00\u6B21\u8FC1\u79FB\u524D\u7684\u72B6\u6001").option("--list","\u5217\u51FA\u6240\u6709\u5907\u4EFD").action(async t=>{try{await $n({config:t.config,from:t.from,to:t.to,dryRun:t.dryRun,noBackup:t.backup===!1,force:t.force,template:t.template,profile:t.profile,rollback:t.rollback,list:t.list,templatesDir:jn.resolve(e.cliDir,"..","templates"),templatePackageVersions:e.packageVersions,cliVersion:e.version})}catch(r){r instanceof Error&&r.message.includes("cancelled")&&process.exit(0),On.error("cli","migrate \u5931\u8D25",{error:r instanceof Error?r.message:String(r)}),process.exit(1)}})}a(_t,"registerMigrateCommand");import{runDesignCommand as Mn,logger as Dn}from"aitable-workflow-core";function $t(n,e){n.command("design").description("\u8BA9 Coding Agent \u6839\u636E\u573A\u666F\u63CF\u8FF0\u751F\u6210\u5B8C\u6574\u7684 workflow \u548C recipes").option("-c, --config <path>","\u914D\u7F6E\u6587\u4EF6\u8DEF\u5F84",e.defaultConfig).option("-y, --yes","\u8DF3\u8FC7\u4EA4\u4E92\u5F0F\u8865\u5145\uFF0C\u76F4\u63A5\u4F7F\u7528 config \u4E2D\u7684 scene").option("--skip-questions","\u4E0D\u56DE\u7B54 Agent \u7684\u6F84\u6E05\u63D0\u95EE\uFF08Agent \u6309\u5047\u8BBE\u751F\u6210\u5E76\u5217\u51FA\u5F85\u786E\u8BA4\u9879\uFF09").action(async t=>{try{await Mn(t)}catch(r){r instanceof Error&&r.message.includes("cancelled")&&process.exit(0),Dn.error("cli","design \u5931\u8D25",{error:r instanceof Error?r.message:String(r)}),process.exit(1)}})}a($t,"registerDesignCommand");import{runCheck as Ln,runSetupCommand as Bn,checkMigrateHint as Hn,logger as Fn,reportCliEvent as se,setReportProject as Nn}from"aitable-workflow-core";import jt from"path";function Ge(n){return n.skipConfig||n.skipConfigIfValid&&n.configValid===!0}a(Ge,"canSkipSetupConfig");function Ot(n){return Ge(n)?"setup":n.uiEnabled&&n.webAvailable?"web":"cli"}a(Ot,"resolveSetupConfigRoute");function Mt(n,e){n.command("setup").description("\u6821\u9A8C\u5E76\u8865\u9F50\u9879\u76EE\u914D\u7F6E\uFF0C\u518D\u521D\u59CB\u5316 AI \u8868\u683C\u7ED3\u6784 + \u51C6\u5907\u77E5\u8BC6\u5E93 \u2014 \u4E00\u6B21\u5B8C\u6210 config + \u5EFA\u8868").option("-c, --config <path>","\u914D\u7F6E\u6587\u4EF6\u8DEF\u5F84",e.defaultConfig).option("--no-clean","\u4E0D\u6E05\u7406\u7A7A\u767D\u884C").option("--no-kb","\u8DF3\u8FC7\u77E5\u8BC6\u5E93\u51C6\u5907/\u7F16\u8BD1").option("--kb-full","\u5F3A\u5236\u5168\u91CF\u91CD\u7F16\u8BD1\u77E5\u8BC6\u5E93").option("--skip-config","\u8DF3\u8FC7\u524D\u7F6E\u7684\u4EA4\u4E92\u5F0F\u914D\u7F6E\u6821\u9A8C\uFF08CI/\u5DF2\u786E\u8BA4\u914D\u7F6E\u65F6\u4F7F\u7528\uFF09").option("--skip-config-if-valid","\u5148\u6821\u9A8C\u914D\u7F6E\uFF1B\u65E0\u963B\u65AD\u9879\u65F6\u8DF3\u8FC7\u914D\u7F6E\u754C\u9762\u5E76\u76F4\u63A5\u5F00\u59CB\u642D\u5EFA").option("--no-ui","\u5F3A\u5236\u4F7F\u7528\u547D\u4EE4\u884C\u4EA4\u4E92\uFF08\u8DF3\u8FC7\u53EF\u89C6\u5316\u914D\u7F6E\u754C\u9762\uFF09").option("--only <round>","\u53EA\u6267\u884C\u6307\u5B9A\u73AF\u8282\uFF1B\u5F53\u524D\u4EC5\u652F\u6301 automations\uFF08\u6309 profile \u5F00\u5173\u5BF9\u9F50\u81EA\u52A8\u5316\uFF0C\u4E0D\u5EFA\u8868\u3001\u4E0D\u7F16\u77E5\u8BC6\u5E93\uFF09").action(async t=>{t.only!==void 0&&t.only!=="automations"&&(console.error(`\u2717 --only \u4E0D\u652F\u6301\u300C${t.only}\u300D\uFF0C\u5F53\u524D\u552F\u4E00\u5408\u6CD5\u503C\uFF1Aautomations`),process.exit(1));let r=t.only==="automations";Nn(t.config);let o=Date.now();se("setup.start",{skipConfig:t.skipConfig===!0,clean:t.clean,kb:t.kb,kbFull:t.kbFull===!0,ui:t.ui!==!1,...r?{only:"automations"}:{}});try{if(await Hn(jt.dirname(jt.resolve(t.config)),e.version),!t.skipConfig&&!r){let s=t.ui!==!1,i=!1;if(t.skipConfigIfValid){console.log("\u{1F4CB} \u6B65\u9AA4 1/2\uFF1A\u6821\u9A8C\u9879\u76EE\u914D\u7F6E");let c=await Ln({configPath:t.config});if(i=Ge({skipConfig:!1,skipConfigIfValid:!0,configValid:c.ok}),i){let l=[];c.summary.warnings>0&&l.push(`${c.summary.warnings} \u9879\u8B66\u544A`),c.summary.suggestions>0&&l.push(`${c.summary.suggestions} \u9879\u5EFA\u8BAE`);let d=l.length>0?`\uFF08${l.join("\uFF0C")}\uFF0C\u5747\u4E0D\u963B\u65AD\uFF09`:"";console.log(`\u2713 \u914D\u7F6E\u65E0\u963B\u65AD\u9879${d}\uFF0C\u8DF3\u8FC7\u914D\u7F6E\u754C\u9762\u5E76\u7EE7\u7EED\u642D\u5EFA\u3002`)}else console.log(`\u2139 \u68C0\u6D4B\u5230 ${c.summary.errors} \u9879\u963B\u65AD\uFF0C\u8FDB\u5165\u914D\u7F6E\u73AF\u8282\u3002`)}if(!i&&s){let{hasWebRoot:c,runConfigUI:l}=await import("./config-ui-server-UWELHUH4.js");if(Ot({skipConfig:!1,skipConfigIfValid:t.skipConfigIfValid===!0,uiEnabled:s,webAvailable:c(),configValid:i})==="web"){console.log("\u{1F4CB} \u6B65\u9AA4 1/2\uFF1A\u53EF\u89C6\u5316\u914D\u7F6E\u754C\u9762");try{await l({configPath:t.config,setupOptions:{clean:t.clean,kb:t.kb,kbFull:t.kbFull}}),se("setup.finish",{success:!0,route:"web",durationMs:Date.now()-o});return}catch(p){console.warn(`
|
|
3
3
|
\u26A0 \u53EF\u89C6\u5316\u754C\u9762\u5F02\u5E38\uFF0C\u56DE\u9000\u5230\u547D\u4EE4\u884C\u4EA4\u4E92: ${p instanceof Error?p.message:String(p)}
|
|
4
|
-
`)}}}if(!i){console.log("\u{1F4CB} \u6B65\u9AA4 1/2\uFF1A\u6821\u9A8C\u5E76\u8865\u9F50\u9879\u76EE\u914D\u7F6E");let{runConfigCommand:
|
|
4
|
+
`)}}}if(!i){console.log("\u{1F4CB} \u6B65\u9AA4 1/2\uFF1A\u6821\u9A8C\u5E76\u8865\u9F50\u9879\u76EE\u914D\u7F6E");let{runConfigCommand:c}=await import("./config-command-7ECUJOEU.js");(await c({configPath:t.config,interactive:!0,offerSkipToBuild:!0})).ok||(console.error(`
|
|
5
5
|
\u2717 \u9879\u76EE\u914D\u7F6E\u4ECD\u4E0D\u5B8C\u6574\uFF0C\u5DF2\u4E2D\u6B62 setup\u3002\u8BF7\u8865\u9F50\u5FC5\u586B\u9879\u540E\u91CD\u8BD5\uFF08\u6216\u7528 --skip-config \u8DF3\u8FC7\uFF09\u3002`),process.exit(1))}console.log(`
|
|
6
6
|
\u{1F527} \u6B65\u9AA4 2/2\uFF1A\u521D\u59CB\u5316\u8868\u7ED3\u6784 + \u51C6\u5907\u77E5\u8BC6\u5E93
|
|
7
|
-
`)}await Kn({config:t.config,clean:t.clean,kb:t.kb,...t.kbFull?{kbFull:!0}:{},...n?{only:"automations"}:{}}),await te("setup.finish",{success:!0,durationMs:Date.now()-r})}catch(s){Zn.error("cli","setup \u5931\u8D25",{error:s instanceof Error?s.message:String(s)}),await te("setup.finish",{success:!1,error:(s instanceof Error?s.message:String(s)).slice(0,500),durationMs:Date.now()-r}),process.exit(1)}})}c(wt,"registerSetupCommand");import yt from"path";import{createApp as kt,ensureTsxRegistered as er,checkMigrateHint as tr,logger as C,runCheck as nr}from"aitable-workflow-core";function rr(){let t=[],n=c(()=>{let r=Date.now();for(t.push(r);t.length>0&&r-t[0]>6e4;)t.shift();t.length>=10&&(C.error("cli",`60000ms \u5185\u53D1\u751F ${t.length} \u6B21\u672A\u6355\u83B7\u5F02\u5E38\uFF0C\u7591\u4F3C\u975E\u5076\u53D1\u9519\u8BEF\uFF0C\u4E3B\u52A8\u9000\u51FA`),process.exit(1))},"recordCrashAndMaybeExit");process.on("uncaughtException",r=>{C.error("cli","\u6355\u83B7\u5230\u672A\u5904\u7406\u5F02\u5E38\uFF08\u5DF2\u5B58\u6D3B\uFF0C\u4EA4\u7531\u91CD\u8FDE/\u91CD\u8BD5\u903B\u8F91\u81EA\u6108\uFF09",{error:r instanceof Error?r.message:String(r),stack:r instanceof Error?r.stack:void 0}),n()}),process.on("unhandledRejection",r=>{C.error("cli","\u6355\u83B7\u5230\u672A\u5904\u7406 Promise \u62D2\u7EDD\uFF08\u5DF2\u5B58\u6D3B\uFF09",{error:r instanceof Error?r.message:String(r),stack:r instanceof Error?r.stack:void 0}),n()})}c(rr,"installLongRunningCrashGuards");function bt(o,e){o.command("start").description("\u542F\u52A8\u7EDF\u4E00\u63A7\u5236\u53F0\uFF1A\u914D\u7F6E\u68C0\u6D4B + \u642D\u5EFA + \u8FD0\u884C\u4E00\u4F53\u5316").option("-c, --config <path>","\u914D\u7F6E\u6587\u4EF6\u8DEF\u5F84",e.defaultConfig).option("-p, --port <number>","\u63A7\u5236\u53F0\u7AEF\u53E3\u9996\u9009\u503C\uFF08\u7F3A\u7701 8788\uFF0C\u4E0D\u53EF\u7528\u65F6\u5411\u4E0A\u907F\u8BA9 13 \u4E2A\u7AEF\u53E3\uFF1B\u591A\u9879\u76EE\u5E76\u884C\u65F6\u5EFA\u8BAE\u663E\u5F0F\u6307\u5B9A\uFF09").option("--no-open","\u542F\u52A8\u540E\u4E0D\u8981\u81EA\u52A8\u6253\u5F00\u6D4F\u89C8\u5668").option("--skip-config-if-valid","\u914D\u7F6E\u5DF2\u5B8C\u6574\u65F6\u76F4\u63A5\u542F\u52A8\u8FD0\u884C").action(async t=>{let n;if(t.port!==void 0){let r=Number.parseInt(t.port,10);(!Number.isFinite(r)||r<=0||r>65535)&&(C.error("cli",`--port \u53D6\u503C\u975E\u6CD5: "${t.port}"\uFF08\u9700\u4E3A 1-65535 \u6574\u6570\uFF09`),process.exit(1)),n=r}try{await tr(yt.dirname(yt.resolve(t.config)),e.version),rr(),await er();let r=await nr({configPath:t.config}),s=!r.ok||r.summary.errors>0,i,a="setup";if(!s)try{a="runtime",i=await kt(t.config,{})}catch(p){C.warn("cli","\u914D\u7F6E\u6821\u9A8C\u901A\u8FC7\u4F46\u88C5\u914D\u5931\u8D25\uFF0C\u56DE\u9000\u5230\u642D\u5EFA\u6A21\u5F0F",{error:p instanceof Error?p.message:String(p)}),a="setup",i=void 0}a==="runtime"&&i?t.skipConfigIfValid?(C.info("cli","\u914D\u7F6E\u5DF2\u5B8C\u6574\uFF0C\u76F4\u63A5\u542F\u52A8\u8FD0\u884C"),i.start().catch(p=>{C.error("cli","\u8FD0\u884C\u542F\u52A8\u5931\u8D25\uFF0C\u53EF\u5728\u63A7\u5236\u53F0\u91CD\u8BD5\u542F\u52A8",{error:p instanceof Error?p.message:String(p)})})):C.info("cli","\u914D\u7F6E\u5DF2\u5B8C\u6574\uFF0C\u8BF7\u5728\u63A7\u5236\u53F0\u70B9\u51FB\u300C\u5F00\u59CB\u8FD0\u884C\u300D\u542F\u52A8\u670D\u52A1"):C.info("cli","\u914D\u7F6E\u4E0D\u5B8C\u6574\uFF0C\u63A7\u5236\u53F0\u5C06\u5F15\u5BFC\u5B8C\u6210\u642D\u5EFA");let l=!1,d=c(async()=>{l&&(C.warn("cli","\u518D\u6B21\u6536\u5230\u9000\u51FA\u4FE1\u53F7\uFF0C\u5F3A\u5236\u9000\u51FA"),process.exit(1)),l=!0,C.info("cli","\u6536\u5230\u9000\u51FA\u4FE1\u53F7\uFF0C\u6B63\u5728\u505C\u6B62\u8FD0\u884C...");try{await i?.stop()}finally{process.exit(0)}},"shutdown");process.on("SIGINT",d),process.on("SIGTERM",d),await at({configPath:t.config,mode:a,app:i,port:n,open:t.open,exitOnSetupError:!1,...a==="runtime"&&t.skipConfigIfValid?{initialRunStatus:{status:"running",since:new Date().toISOString(),lastError:null}}:{},...a==="setup"?{assembleApp:c(p=>kt(p,{}),"assembleApp"),onAppAssembled:c(p=>{i=p,C.info("cli","\u63A7\u5236\u53F0\u5DF2\u5B8C\u6210 setup\u2192runtime \u664B\u5347\uFF0C\u53EF\u5728\u63A7\u5236\u53F0\u542F\u52A8\u8FD0\u884C")},"onAppAssembled")}:{}})}catch(r){C.error("cli","start \u547D\u4EE4\u5931\u8D25",{error:r instanceof Error?r.message:String(r)}),process.exit(1)}})}c(bt,"registerStartCommand");import{createApp as or,ensureTsxRegistered as sr,checkMigrateHint as ir,logger as F,reportCliEvent as ne,setReportProject as ar}from"aitable-workflow-core";import Rt from"path";function cr(){let t=[],n=c(async()=>{let r=Date.now();for(t.push(r);t.length>0&&r-t[0]>6e4;)t.shift();t.length>=10&&(F.error("cli",`60000ms \u5185\u53D1\u751F ${t.length} \u6B21\u672A\u6355\u83B7\u5F02\u5E38\uFF0C\u7591\u4F3C\u975E\u5076\u53D1\u9519\u8BEF\uFF0C\u4E3B\u52A8\u9000\u51FA`),await ne("run.exit",{reason:"crash-loop",crashes:t.length}),process.exit(1))},"recordCrashAndMaybeExit");process.on("uncaughtException",r=>{F.error("cli","\u6355\u83B7\u5230\u672A\u5904\u7406\u5F02\u5E38\uFF08\u5DF2\u5B58\u6D3B\uFF0C\u4EA4\u7531\u91CD\u8FDE/\u91CD\u8BD5\u903B\u8F91\u81EA\u6108\uFF09",{error:r instanceof Error?r.message:String(r),stack:r instanceof Error?r.stack:void 0}),n()}),process.on("unhandledRejection",r=>{F.error("cli","\u6355\u83B7\u5230\u672A\u5904\u7406 Promise \u62D2\u7EDD\uFF08\u5DF2\u5B58\u6D3B\uFF09",{error:r instanceof Error?r.message:String(r),stack:r instanceof Error?r.stack:void 0}),n()})}c(cr,"installLongRunningCrashGuards");function Ct(o,e){o.command("run").description("\u542F\u52A8\u7F16\u6392\u5F15\u64CE\uFF0C\u5F00\u59CB\u8F6E\u8BE2\u5904\u7406\u5DE5\u5355").option("-c, --config <path>","\u914D\u7F6E\u6587\u4EF6\u8DEF\u5F84",e.defaultConfig).option("--emit-events <channel>","\u8FD0\u884C\u4E8B\u4EF6\u4E0A\u629B\u901A\u9053\uFF1Aipc = \u7ECF process.send \u53D1\u7ED9\u7236\u8FDB\u7A0B\uFF08daemon runner \u7528\uFF09\uFF0C\u7F3A\u7701\u4E0D\u4E0A\u629B").option("-p, --port <number>","\uFF08\u4EC5\u517C\u5BB9 launcher \u900F\u4F20\uFF0Crun \u547D\u4EE4\u4E0D\u4F7F\u7528\u6B64\u53C2\u6570\uFF09").action(async t=>{ar(t.config);try{await ir(Rt.dirname(Rt.resolve(t.config)),e.version),cr(),await sr();let n=t.emitEvents==="ipc"&&typeof process.send=="function",r=await or(t.config,n?{onRunEvent:c(a=>{process.send?.({type:"run-event",event:a})},"onRunEvent")}:{});ne("run.start",{emitEvents:t.emitEvents??null});let s=!1,i=c(async()=>{s&&(F.warn("cli","\u518D\u6B21\u6536\u5230\u9000\u51FA\u4FE1\u53F7\uFF0C\u5F3A\u5236\u9000\u51FA"),process.exit(1)),s=!0,F.info("cli","\u6536\u5230\u9000\u51FA\u4FE1\u53F7\uFF0C\u6B63\u5728\u7B49\u5F85\u8FDB\u884C\u4E2D\u7684\u4EFB\u52A1\u5B8C\u6210...");try{await r.stop()}finally{await ne("run.exit",{reason:"signal"}),process.exit(0)}},"shutdown");process.on("SIGINT",i),process.on("SIGTERM",i),await r.start()}catch(n){F.error("cli","\u542F\u52A8\u5931\u8D25",{error:n instanceof Error?n.message:String(n)}),await ne("run.exit",{reason:"start-failure",error:(n instanceof Error?n.message:String(n)).slice(0,500)}),process.exit(1)}})}c(Ct,"registerRunCommand");import{readFile as lr}from"fs/promises";import St from"path";import{createApp as dr,ensureTsxRegistered as pr,logger as _e,resolveConfigPath as ur}from"aitable-workflow-core";function mr(o,e){let t=`\u5DE5\u4F5C\u6D41 ${o} / \u4E8B\u4EF6\u6E90 ${e.sourceName}\uFF08handler: ${e.handlerRecipe}\uFF09`;return e.actions===0?`${t}\uFF1A\u5DF2\u89E6\u53D1\u4F46\u6CA1\u6709\u4EA7\u51FA\u52A8\u4F5C\uFF08\u8017\u65F6 ${e.durationMs}ms\uFF09\u3002\u8BF7\u68C0\u67E5\u6570\u636E\u6E90\u662F\u5426\u6709\u53EF\u7528\u884C\u3002`:`${t}\uFF1A\u4EA7\u51FA ${e.actions} \u4E2A\u52A8\u4F5C\uFF08\u843D\u5E93 ${e.applied}\uFF0C\u77AC\u6001 ${e.transient}\uFF09\uFF0C\u8017\u65F6 ${e.durationMs}ms\u3002`}c(mr,"formatTriggerOnceResult");function xt(o){return new Promise(e=>{o.write("",()=>e())})}c(xt,"flushStream");function At(){return Promise.all([xt(process.stdout),xt(process.stderr)])}c(At,"flushOutputs");function Et(o){let e;try{e=JSON.parse(o)}catch(n){throw new Error(`\u81EA\u5B9A\u4E49\u4E8B\u4EF6 JSON \u89E3\u6790\u5931\u8D25: ${n instanceof Error?n.message:String(n)}`)}if(!e||typeof e!="object"||Array.isArray(e))throw new Error("\u81EA\u5B9A\u4E49\u4E8B\u4EF6\u5FC5\u987B\u662F JSON \u5BF9\u8C61");let t=e;if(typeof t.type!="string"||t.type.trim().length===0)throw new Error("\u81EA\u5B9A\u4E49\u4E8B\u4EF6 type \u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32");if(!t.payload||typeof t.payload!="object"||Array.isArray(t.payload))throw new Error("\u81EA\u5B9A\u4E49\u4E8B\u4EF6 payload \u5FC5\u987B\u662F\u5BF9\u8C61");if(t.timestamp!==void 0&&(typeof t.timestamp!="string"||t.timestamp.trim().length===0))throw new Error("\u81EA\u5B9A\u4E49\u4E8B\u4EF6 timestamp \u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32");if(t.itemId!==void 0&&t.itemId!==null&&typeof t.itemId!="string")throw new Error("\u81EA\u5B9A\u4E49\u4E8B\u4EF6 itemId \u5FC5\u987B\u662F\u5B57\u7B26\u4E32\u6216 null");return{type:t.type,payload:t.payload,...typeof t.timestamp=="string"?{timestamp:t.timestamp}:{},...t.itemId!==void 0?{itemId:t.itemId}:{}}}c(Et,"parseTriggerEventJson");async function fr(){let o=[];for await(let e of process.stdin)o.push(Buffer.isBuffer(e)?e:Buffer.from(String(e)));return Buffer.concat(o).toString("utf8")}c(fr,"readStdin");async function gr(o,e=process.cwd()){if(o.eventJson&&o.eventStdin)throw new Error("--event-json \u4E0E --event-stdin \u53EA\u80FD\u4E8C\u9009\u4E00");if(o.eventJson){let t=St.resolve(e,o.eventJson);return Et(await lr(t,"utf8"))}if(o.eventStdin)return Et(await fr())}c(gr,"loadTriggerEvent");function It(o,e){o.command("trigger-once").description("\u5355\u6B21\u89E6\u53D1\u67D0\u4E2A\u5DE5\u4F5C\u6D41\u7684\u4E8B\u4EF6\u6E90 handler \u8DD1\u4E00\u904D\uFF08\u53EA\u8DD1\u4E8B\u4EF6\u6E90 handler\uFF0C\u4E0D\u542F\u52A8\u5E38\u9A7B\u5F15\u64CE\uFF1B\u6B65\u9AA4\u94FE\u7531\u8FD0\u884C\u4E2D\u7684\u5F15\u64CE\u63A8\u8FDB\uFF09").requiredOption("-w, --workflow <id>","\u5DE5\u4F5C\u6D41 ID\uFF08\u591A\u5DE5\u4F5C\u6D41\u9879\u76EE\u91CC\u7684\u76EE\u5F55\u540D\uFF09").option("-c, --config <path>","\u914D\u7F6E\u6587\u4EF6\u8DEF\u5F84",e.defaultConfig).option("-s, --source <name>","\u53EA\u89E6\u53D1\u6307\u5B9A\u4E8B\u4EF6\u6E90\uFF1B\u7F3A\u7701\u7528\u8BE5\u5DE5\u4F5C\u6D41\u7684\u7B2C\u4E00\u4E2A\u4E8B\u4EF6\u6E90").option("--event-json <path>","\u4ECE JSON \u6587\u4EF6\u8BFB\u53D6\u81EA\u5B9A\u4E49 ExternalEvent\uFF08\u53EA\u89E6\u53D1 handler\uFF0C\u4E0D\u6A21\u62DF\u5B8C\u6574\u6B65\u9AA4\u94FE\uFF09").option("--event-stdin","\u4ECE stdin \u8BFB\u53D6\u81EA\u5B9A\u4E49 ExternalEvent JSON").option("--json","\u4EE5 JSON \u8F93\u51FA\u7ED3\u679C\uFF08\u4F9B\u811A\u672C\u6D88\u8D39\uFF09").action(async t=>{t.json&&_e.setSink((n,r)=>process.stderr.write(`${r}
|
|
8
|
-
`));try{await pr();let n=await ur(t.config),r=await gr(t,St.dirname(n)),s=await dr(t.config),i={...t.source?{sourceName:t.source}:{},...r?{event:r}:{}},a=await s.triggerWorkflowOnce(t.workflow,i);t.json?process.stdout.write(`${JSON.stringify({ok:!0,workflowId:t.workflow,...a})}
|
|
9
|
-
`):_e.info("cli",mr(t.workflow,a)),await At(),process.exit(0)}catch(n){let r=n instanceof Error?n.message:String(n);t.json?process.stdout.write(`${JSON.stringify({ok:!1,error:r})}
|
|
10
|
-
`):_e.error("cli","\u89E6\u53D1\u5931\u8D25",{error:r}),await At(),process.exit(1)}})}c(It,"registerTriggerCommand");import{readFile as Tt}from"fs/promises";import oe from"path";import _t from"yaml";import{logger as hr,loadSettings as Pt,loadWorkflowTemplate as vr,resolveConfigPath as wr,scanWorkflowDirs as yr,buildEnvSource as kr,loadProfileConfig as br,resetProfileCache as Rr,runWorkflowGates as Cr}from"aitable-workflow-core";function $t(o,e){o.command("validate").description("\u9A8C\u8BC1\u914D\u7F6E\u6587\u4EF6\u548C\u5DE5\u4F5C\u6D41\u95E8\u7981\uFF08\u7ED3\u6784 / recipe \u7ED1\u5B9A / \u7C7B\u578B / \u914D\u7F6E\u5951\u7EA6 / \u53C2\u6570\u6D41\u8F6C\uFF09").option("-c, --config <path>","\u914D\u7F6E\u6587\u4EF6\u8DEF\u5F84",e.defaultConfig).option("--workflow <id>","\u53EA\u6821\u9A8C\u6307\u5B9A\u5DE5\u4F5C\u6D41\uFF08\u591A\u5DE5\u4F5C\u6D41\u6A21\u5F0F\uFF09").option("--strict","warning \u7EA7\u95EE\u9898\u5347\u7EA7\u4E3A error").option("--no-typecheck","\u8DF3\u8FC7 recipe TS \u7C7B\u578B\u68C0\u67E5\uFF08\u6279\u91CF\u573A\u666F\u63D0\u901F\uFF09").option("--json","\u8F93\u51FA\u673A\u5668\u53EF\u8BFB GateReport JSON").action(async t=>{try{await xr(t.config,t)}catch(n){console.error(`\u2717 \u9A8C\u8BC1\u5931\u8D25: ${n instanceof Error?n.message:String(n)}`),process.exit(1)}})}c($t,"registerValidateCommand");async function xr(o,e){e.json&&hr.setSink((a,l)=>process.stderr.write(`${l}
|
|
11
|
-
`));let t=await wr(o),n=oe.dirname(t),r=await Er(t,e.workflow);r.length===0&&(console.error("\u2717 \u672A\u627E\u5230\u4EFB\u4F55\u5DE5\u4F5C\u6D41"),process.exit(1));let s=await Ir(n),i=await Cr(r,{strict:e.strict===!0,includeTypecheck:e.typecheck!==!1,profile:s});i.configPath=t,e.json?console.log(JSON.stringify(i,null,2)):(await Ar(t),_r(i)),process.exit(i.ok?0:1)}c(xr,"runValidateWorkflow");async function Ar(o){let e=await Pt(o,{lenientEnv:!0});console.log("\u2713 \u914D\u7F6E\u6587\u4EF6\u9A8C\u8BC1\u901A\u8FC7");let t=await vr(e.workflowTemplatePath,{envSource:e.envSource});console.log(`\u2713 \u5DE5\u4F5C\u6D41\u6A21\u677F\u9A8C\u8BC1\u901A\u8FC7: ${t.meta.name} (${t.orderedStepIds.length} \u6B65)`),console.log(`
|
|
12
|
-
\u6B65\u9AA4\u94FE:`);for(let[l,d]of t.orderedStepIds.entries()){let p=t.steps.find(m=>m.id===d),u=l<t.orderedStepIds.length-1?" \u2192":" \u2713";console.log(` ${l+1}. [${d}] ${p?.name??"?"}${u}`)}let n=await Tt(o,"utf8"),r=_t.parse(n),s=re(r.agent)?r.agent:{},a=typeof s.engine=="string"&&s.engine!==""?e.agent.engine:`\u672A\u914D\u7F6E\uFF08\u9ED8\u8BA4 ${e.agent.engine}\uFF09`;console.log(`
|
|
13
|
-
\u914D\u7F6E\u6458\u8981:`),console.log(` AI \u8868\u683C: base=${e.tracker.base_id} table=${e.tracker.table_id}`),console.log(` \u5F15\u64CE: ${a}`),console.log(` \u8F6E\u8BE2\u95F4\u9694: ${e.polling.interval_ms}ms`),console.log()}c(Ar,"printConfigSummary");async function Er(o,e){let t=oe.dirname(o),n;try{n=(await Pt(o,{lenientEnv:!0})).workflowEntries}catch{n=await Sr(o,t)}if(e&&(n=n.filter(r=>r.id===e),n.length===0))throw new Error(`\u672A\u627E\u5230\u5DE5\u4F5C\u6D41\u300C${e}\u300D`);return n}c(Er,"resolveWorkflowEntries");function re(o){return typeof o=="object"&&o!==null&&!Array.isArray(o)}c(re,"isRecord");async function Sr(o,e){let t=await Tt(o,"utf8"),n=_t.parse(t);if(!re(n))throw new Error("\u914D\u7F6E\u6587\u4EF6\u5FC5\u987B\u662F\u4E00\u4E2A\u5BF9\u8C61");if(re(n.workflow)){let r=n.workflow.template,s=n.workflow.recipe_dir??"./recipes";if(typeof r=="string")return[{id:"default",templatePath:oe.resolve(e,r),recipeDir:oe.resolve(e,String(s))}]}if(re(n.workflows)&&typeof n.workflows.dir=="string")return await yr(e,n.workflows.dir);throw new Error("\u914D\u7F6E\u4E2D\u672A\u627E\u5230 workflow / workflows \u6BB5")}c(Sr,"inferEntriesFromRawYaml");async function Ir(o){try{Rr();let e=await kr(o);return br(o,e,{lenientEnv:!0})}catch{return null}}c(Ir,"tryLoadProfile");var Tr={structure:"\u7ED3\u6784\u5B8C\u6574\u6027",recipe_bind:"Recipe \u7ED1\u5B9A",recipe_typecheck:"\u7C7B\u578B\u68C0\u67E5",config_contract:"\u914D\u7F6E\u5951\u7EA6",dataflow:"\u53C2\u6570\u6D41\u8F6C"};function _r(o){console.log(`\u5DE5\u4F5C\u6D41\u95E8\u7981\u6821\u9A8C${o.strict?"\uFF08--strict\uFF09":""}`),console.log("\u2550".repeat(56));for(let t of o.workflows){console.log(`
|
|
14
|
-
\u5DE5\u4F5C\u6D41: ${t.id} ${t.ok?"\u2713 \u901A\u8FC7":"\u2717 \u672A\u901A\u8FC7"}`);for(let n of t.gates)Pr(n)}console.log(`
|
|
15
|
-
`+"\u2500".repeat(56));let e=Lr(o);console.log(`${o.workflows.length} \u4E2A\u5DE5\u4F5C\u6D41\uFF1A${o.ok?"\u5168\u90E8\u901A\u8FC7 \u2713":"\u5B58\u5728\u9519\u8BEF \u2717"}\uFF5Cerror ${e.errors}\uFF5Cwarning ${e.warnings}\uFF5Csuggestion ${e.suggestions}`),o.ok||console.log("\u4FEE\u590D\u4E0A\u8FF0 error \u540E\u91CD\u65B0\u8FD0\u884C\uFF1Berror \u8BA1\u5165\u9000\u51FA\u7801\uFF08CI \u53EF\u4F5C\u95E8\u7981\uFF09\u3002")}c(_r,"printReport");function Pr(o){let e=Tr[o.gate]??o.gate;if(o.status==="skipped"){console.log(` \u25CB ${e}: \u8DF3\u8FC7\uFF08${o.skipReason??""}\uFF09`);return}let t=o.status==="passed"?"\u2713":"\u2717",n=o.issues.filter(s=>s.severity==="error").length,r=o.status==="passed"?o.issues.length>0?`\uFF08${o.issues.length} \u6761\u63D0\u793A\uFF09`:"":`\uFF08${n} \u4E2A\u9519\u8BEF\uFF09`;console.log(` ${t} ${e}${r} [${o.durationMs}ms]`);for(let s of o.issues)$r(s)}c(Pr,"printGate");function $r(o){let e=o.severity==="error"?"\u2717":o.severity==="warning"?"\u25B3":"\xB7",t=o.location?[o.location.file,o.location.stepId,o.location.key].filter(Boolean).join(" \u203A "):"";console.log(` ${e} [${o.code}]${t?` ${t}`:""}`),console.log(` ${o.message}`)}c($r,"printIssue");function Lr(o){let e=0,t=0,n=0;for(let r of o.workflows)for(let s of r.gates)for(let i of s.issues)i.severity==="error"?e++:i.severity==="warning"?t++:n++;return{errors:e,warnings:t,suggestions:n}}c(Lr,"summarize");import{logger as Or}from"aitable-workflow-core";function jr(o,e){if(o.getOptionValueSource("config")!=="default")return e;let t=o.parent?.getOptionValue("config");return typeof t=="string"?t:e}c(jr,"effectiveConfigPath");function Lt(o,e){o.command("config").description("\u6821\u9A8C\u9879\u76EE\u914D\u7F6E\u5B8C\u6574\u6027\uFF0C\u5E76\u53EF\u4EA4\u4E92\u5F0F\u4FEE\u6539\u53C2\u6570").option("-c, --config <path>","\u9879\u76EE\u76EE\u5F55\u6216\u914D\u7F6E\u6587\u4EF6\u8DEF\u5F84",e.defaultConfig).option("-w, --workflow <id>","\u591A\u5DE5\u4F5C\u6D41\u6A21\u5F0F\uFF1A\u6307\u5B9A\u6821\u9A8C\u7684\u5DE5\u4F5C\u6D41 ID\uFF08\u7F3A\u7701\u6821\u9A8C\u5168\u90E8\uFF09").option("--json","JSON \u683C\u5F0F\u8F93\u51FA\u6821\u9A8C\u7ED3\u679C").option("--summary","\u4E0E --json \u5408\u7528\uFF1A\u53EA\u8F93\u51FA ok \u4E0E summary").option("--errors-only","\u4E0E --json \u5408\u7528\uFF1A\u53EA\u8F93\u51FA status \u4E3A error \u7684\u9879").option("--no-interactive","\u4EC5\u6821\u9A8C\uFF0C\u8DF3\u8FC7\u4EA4\u4E92\u5F0F\u4FEE\u6539").action(async n=>{try{let{runConfigCommand:r}=await import("./config-command-7ECUJOEU.js");await r({configPath:n.config,workflowId:n.workflow,json:n.json,interactive:n.interactive,summary:n.summary,errorsOnly:n.errorsOnly})}catch(r){r instanceof Error&&r.message.includes("cancelled")&&process.exit(0),Or.error("cli","config \u547D\u4EE4\u5931\u8D25",{error:r instanceof Error?r.message:String(r)}),process.exit(1)}}).command("set").description("\u975E\u4EA4\u4E92\u5199\u914D\u7F6E\u9879\uFF08key \u53D6\u81EA config --json \u7684 item.key\uFF09").option("-c, --config <path>","\u9879\u76EE\u76EE\u5F55\u6216\u914D\u7F6E\u6587\u4EF6\u8DEF\u5F84",e.defaultConfig).option("-w, --workflow <id>","\u591A\u5DE5\u4F5C\u6D41\u9879\u76EE\u91CC\u7ED9 key \u6D88\u6B67\uFF08\u540C\u540D key \u547D\u4E2D\u591A\u4E2A\u5DE5\u4F5C\u6D41\u65F6\u5FC5\u586B\uFF09").option("--set <key=value>","\u5199\u4E00\u9879\uFF1B\u53EF\u91CD\u590D\u3002\u654F\u611F\u9879\u62D2\u6536\uFF08\u503C\u4F1A\u8FDB argv\uFF09\uFF0C\u6539\u7528 --set-stdin",(n,r)=>[...r,n],[]).option("--set-stdin <key>","\u5199\u4E00\u9879\uFF0C\u503C\u4ECE stdin \u9010\u884C\u6309\u987A\u5E8F\u8BFB\uFF1B\u53EF\u91CD\u590D\u3002\u654F\u611F\u9879\u8D70\u8FD9\u6761",(n,r)=>[...r,n],[]).option("--dry-run","\u53EA\u6253\u5370\u5C06\u5199\u54EA\u4E2A\u6587\u4EF6\u7684\u54EA\u4E2A\u8DEF\u5F84\uFF0C\u4E0D\u5199\u76D8\uFF08\u654F\u611F\u503C\u53EA\u6253\u952E\u540D\uFF09").option("--json","JSON \u683C\u5F0F\u8F93\u51FA\u7ED3\u679C").action(async(n,r)=>{try{let{runConfigSet:s,printConfigSetResult:i}=await import("./config-set-FBOQBRSJ.js"),a=await s({configPath:jr(r,n.config),...n.workflow?{workflowId:n.workflow}:{},set:n.set,setStdin:n.setStdin,...n.dryRun?{dryRun:!0}:{},...n.json?{json:!0}:{}});i(a,n.json===!0)}catch(s){let i=s instanceof Error?s.message:String(s);n.json?process.stdout.write(JSON.stringify({ok:!1,error:i},null,2)+`
|
|
16
|
-
`):console.error(`
|
|
17
|
-
\u2717 ${i}
|
|
18
|
-
`),process.exit(1)}})}c(Lt,"registerConfigCommand");import{runSync as Mr,logger as Dr}from"aitable-workflow-core";function Ot(o,e){o.command("sync").description("\u68C0\u6D4B\u914D\u7F6E\u4E0E\u8868\u7684\u504F\u5DEE\uFF08\u5B57\u6BB5\u7C7B\u578B/\u9009\u9879 drift\uFF09\uFF0C\u8F93\u51FA\u8BCA\u65AD\u62A5\u544A\u548C\u4FEE\u590D\u5EFA\u8BAE").option("-c, --config <path>","\u914D\u7F6E\u6587\u4EF6\u8DEF\u5F84",e.defaultConfig).option("-y, --yes","\u975E\u4EA4\u4E92\u6A21\u5F0F").action(async t=>{try{await Mr({configPath:t.config,yes:t.yes})}catch(n){Dr.error("cli","sync \u5931\u8D25",{error:n instanceof Error?n.message:String(n)}),process.exit(1)}})}c(Ot,"registerSyncCommand");import{listCodingAgents as Br,logger as Hr}from"aitable-workflow-core";function jt(o,e){o.command("agents").description("\u5217\u51FA\u5168\u90E8\u652F\u6301\u7684 Coding Agent \u9002\u914D\u5668\uFF0C\u5E76\u6807\u6CE8\u672C\u673A\u5DF2\u63A2\u6D4B\u5230\u5B89\u88C5\u7684").option("--json","\u4EE5 JSON \u683C\u5F0F\u8F93\u51FA").action(t=>{try{let n=Br();if(t.json){process.stdout.write(JSON.stringify(n,null,2)+`
|
|
19
|
-
`);return}let r=n.filter(s=>s.installed).length;console.log(`
|
|
20
|
-
\u652F\u6301 ${n.length} \u4E2A Coding Agent\uFF0C\u672C\u673A\u5DF2\u63A2\u6D4B\u5230 ${r} \u4E2A\uFF1A
|
|
21
|
-
`);for(let s of n){let i=s.installed?"\u2713":"\u2717",a=[s.bin,...s.fallbackBins].join(" / "),l=s.installed?`\u5DF2\u5B89\u88C5 (${s.detectedCmd}${s.detectedVersion?` ${s.detectedVersion}`:""})`:"\u672A\u63A2\u6D4B\u5230";console.log(` ${i} ${s.name.padEnd(16)} [${s.id}] bin: ${a.padEnd(24)} ${l}`)}console.log("")}catch(n){Hr.error("cli","\u5217\u51FA agents \u5931\u8D25",{error:n instanceof Error?n.message:String(n)}),process.exit(1)}})}c(jt,"registerAgentsCommand");import{logger as Fr}from"aitable-workflow-core";import{startServer as Nr,resolveServeConfig as Ur}from"aitable-workflow-server";import se from"path";import{existsSync as Mt}from"fs";function Dt(o,e){o.command("serve").description("\u542F\u52A8\u672C\u5730 HTTP API \u670D\u52A1\u5E76\u6258\u7BA1 Web \u524D\u7AEF\u9875\u9762\uFF08local \u6A21\u5F0F\u81EA\u52A8\u6253\u5F00\u6D4F\u89C8\u5668\uFF09").option("-p, --port <number>","\u76D1\u542C\u7AEF\u53E3\uFF08\u9ED8\u8BA4 8787\uFF0C\u53EF\u7528 AITABLE_WORKFLOW_PORT \u8986\u76D6\uFF09").option("--host <host>","\u76D1\u542C\u5730\u5740\uFF08\u9ED8\u8BA4 127.0.0.1\uFF0C\u53EF\u7528 AITABLE_WORKFLOW_HOST \u8986\u76D6\uFF09").option("--data-root <path>","\u9879\u76EE\u5DE5\u4F5C\u533A\u6570\u636E\u76EE\u5F55\uFF08\u9ED8\u8BA4 .sandbox/aitable-workflow-server\uFF0C\u53EF\u7528 AITABLE_WORKFLOW_DATA_DIR \u8986\u76D6\uFF09").option("--web-root <path>","Web \u524D\u7AEF\u9759\u6001\u8D44\u6E90\u76EE\u5F55\uFF08\u9ED8\u8BA4\u4F7F\u7528\u968F CLI \u6253\u5305\u7684 dist/web\uFF09").option("--no-open","\u542F\u52A8\u540E\u4E0D\u81EA\u52A8\u6253\u5F00\u6D4F\u89C8\u5668\uFF08\u9ED8\u8BA4\u81EA\u52A8\u6253\u5F00\uFF09").action(async t=>{try{let n={};if(t.port!==void 0){let s=Number.parseInt(t.port,10);Number.isFinite(s)&&s>0&&(n.port=s)}if(t.host!==void 0&&(n.host=t.host),t.dataRoot!==void 0&&(n.dataRoot=t.dataRoot),t.webRoot!==void 0)n.webRoot=t.webRoot;else{let s=se.join(e.cliDir,"web");if(Mt(se.join(s,"index.html")))n.webRoot=s;else{let i=se.resolve(e.cliDir,"..","..","web","dist");Mt(se.join(i,"index.html"))&&(n.webRoot=i)}}let r=Ur(n);if(await Nr(r),r.webRoot&&t.open!==!1){let s=r.host==="0.0.0.0"?"127.0.0.1":r.host;it(`http://${s}:${r.port}`)}}catch(n){Fr.error("cli","HTTP \u670D\u52A1\u542F\u52A8\u5931\u8D25",{error:n instanceof Error?n.message:String(n)}),process.exit(1)}})}c(Dt,"registerServeCommand");import{Command as Ze}from"commander";import{logger as T,listCredentials as hn,getActiveCredential as B,maskSecret as Ss}from"aitable-workflow-core";import M from"os";import I from"path";import{fileURLToPath as Bo}from"url";import{createServer as Ho}from"http";import{mkdir as Fo,readFile as sn,mkdtemp as No,writeFile as Uo,rm as Wo}from"fs/promises";import{mkdirSync as Go,existsSync as qo}from"fs";import{logger as w,detectInstalledAgents as zo,projectAgentEvents as rn,runCodingAgent as Jo,DwsClient as Yo,getActiveCredential as Vo,assertPortableId as Ko,probeCommand as Xo,dwsCommandOptions as Zo,substituteArgPath as Qo}from"aitable-workflow-core";var Bt=`<!doctype html>
|
|
7
|
+
`)}await Bn({config:t.config,clean:t.clean,kb:t.kb,...t.kbFull?{kbFull:!0}:{},...r?{only:"automations"}:{}}),await se("setup.finish",{success:!0,durationMs:Date.now()-o})}catch(s){Fn.error("cli","setup \u5931\u8D25",{error:s instanceof Error?s.message:String(s)}),await se("setup.finish",{success:!1,error:(s instanceof Error?s.message:String(s)).slice(0,500),durationMs:Date.now()-o}),process.exit(1)}})}a(Mt,"registerSetupCommand");import $r from"path";import{createApp as Or,ensureTsxRegistered as zs,checkMigrateHint as Js,logger as A,runCheck as Vs}from"aitable-workflow-core";import Pe from"path";import{logger as _e,runCodingAgent as Ws,detectInstalledAgents as Us}from"aitable-workflow-core";import lt from"os";import _s from"path";import{mkdir as $s,readFile as Os}from"fs/promises";import{logger as R,detectInstalledAgents as js,runCodingAgent as Ms,DwsClient as Ds,probeCommand as Ls,dwsCommandOptions as Bs,defaultCommandRunner as Sr}from"aitable-workflow-core";import{mkdir as Gn}from"fs/promises";import{logger as ze}from"aitable-workflow-core";import Dt from"path";import{logger as Wn,assertPortableId as Lt,resolveInsideRoot as qe}from"aitable-workflow-core";var Un="relay:daemon";function Bt(n,e){return Dt.join(n,"projects",Lt(e,{label:"projectId"}))}a(Bt,"relayProjectDir");function Ht(n,e){return qe(n,e,{allowRoot:!1})}a(Ht,"resolveRelayProjectPath");function ie(n,e,t){if(t&&t.trim()!=="")if(Dt.isAbsolute(t))Wn.warn(Un,"\u5FFD\u7565\u7EDD\u5BF9\u8DEF\u5F84 workDir\uFF0C\u56DE\u9000\u5230 workspaceRoot/projectId",{workDir:t,projectId:e});else return qe(n,t,{allowRoot:!1});return qe(n,Lt(e,{label:"projectId"}),{allowRoot:!1})}a(ie,"resolveRelayWorkDir");var Je="relay:chat",Ve="local-chat",qn=128,Ft=32e3,N=class{constructor(e){this.deps=e}deps;static{a(this,"ChatTurnManager")}active=new Map;listAgents(){return this.deps.detectAgents().map(e=>e.type)}start(e){if(typeof e.requestId!="string"||e.requestId.trim()===""||e.requestId.length>qn)return{ok:!1,status:400,error:"requestId \u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32\u4E14\u4E0D\u8D85\u8FC7 128 \u5B57\u7B26"};if(this.active.has(e.requestId))return{ok:!1,status:409,error:"\u8BE5 requestId \u4ECD\u6709\u6D3B\u8DC3\u8F6E\u6B21\u672A\u7ED3\u675F"};if(typeof e.prompt!="string"||e.prompt.trim()==="")return{ok:!1,status:400,error:"prompt \u4E0D\u80FD\u4E3A\u7A7A"};if(e.prompt.length>Ft)return{ok:!1,status:400,error:`prompt \u8D85\u8FC7\u957F\u5EA6\u4E0A\u9650 ${Ft}`};let t=new AbortController;return this.active.set(e.requestId,t),this.deps.enqueue(()=>this.runTurn(e,t)),{ok:!0}}stop(e){let t=this.active.get(e);return t?(t.abort(),!0):!1}activeCount(){return this.active.size}async runTurn(e,t){let{requestId:r}=e;try{let o=e.agent??this.listAgents()[0];if(!o){this.fail(r,"\u672C\u673A\u672A\u68C0\u6D4B\u5230\u53EF\u7528\u7684\u7F16\u7A0B Agent");return}let s;try{s=ie(this.deps.workspaceRoot,Ve,e.workDir)}catch(d){let p=d instanceof Error?d.message:String(d);this.fail(r,`workDir \u8D8A\u754C\u6216\u975E\u6CD5\uFF1A${p}`);return}await Gn(s,{recursive:!0}),this.deps.store.startRun({requestId:r,projectId:Ve,agent:o,workDir:s,source:"chat"});let i={agent:o,workDir:s,signal:t.signal,onEvent:a(d=>this.deps.store.appendEvent(r,d),"onEvent")};e.sessionId&&(i.sessionId=e.sessionId);let c=e.timeoutMs??this.deps.defaultTimeoutMs;c!=null&&(i.timeoutMs=c);let l;try{l=await this.deps.runAgent(e.prompt,i)}catch(d){let p=d instanceof Error?d.message:String(d),f=t.signal.aborted?"aborted":"failed";this.deps.store.finishRun(r,{status:f,error:p}),ze.warn(Je,"chat turn ended with error",{requestId:r,status:f,error:p});return}this.deps.store.finishRun(r,{status:"succeeded",response:l.response,sessionId:l.sessionId}),ze.info(Je,"chat turn succeeded",{requestId:r,sessionId:l.sessionId})}finally{this.active.delete(r)}}fail(e,t){this.deps.store.startRun({requestId:e,projectId:Ve,agent:"qoder",workDir:"",source:"chat"}),this.deps.store.finishRun(e,{status:"failed",error:t}),ze.warn(Je,"chat turn rejected before agent run",{requestId:e,error:t})}};import zn from"path";import{AITableTracker as Jn,loadSettings as Vn,logger as P,resolveWorkflowTracker as Yn,createPerWorkflowSettings as Kn,loadWorkflowTemplate as Xn}from"aitable-workflow-core";var _="relay:ask-reply",Nt=32e3,Zn=128,Qn={attempts:3,delayMs:400};function eo(n){return new Promise(e=>setTimeout(e,n))}a(eo,"sleep");var W=class{constructor(e){this.deps=e;this.loadContext=e.loadProjectContext??to}deps;static{a(this,"AskReplyService")}cache=new Map;loadContext;resetCache(){this.cache.clear()}async reply(e){let t=typeof e.projectId=="string"?e.projectId.trim():"",r=typeof e.itemId=="string"?e.itemId.trim():"",o=typeof e.answer=="string"?e.answer:"";if(!t||t.length>Zn||t.includes("/")||t.includes(".."))return{ok:!1,status:400,error:"projectId \u5FC5\u987B\u662F\u4E0D\u542B\u8DEF\u5F84\u5206\u9694\u7684\u77ED\u5B57\u7B26\u4E32"};if(!r)return{ok:!1,status:400,error:"itemId \u4E0D\u80FD\u4E3A\u7A7A"};if(o.trim()==="")return{ok:!1,status:400,error:"answer \u4E0D\u80FD\u4E3A\u7A7A"};if(o.length>Nt)return{ok:!1,status:400,error:`answer \u8D85\u8FC7\u957F\u5EA6\u4E0A\u9650 ${Nt}`};let s;try{s=await this.getProjectContext(t)}catch(m){let h=m instanceof Error?m.message:String(m);return/ENOENT|no such file|无法读取配置文件/.test(h)?{ok:!1,status:404,error:`\u9879\u76EE\u5DE5\u4F5C\u533A\u4E0D\u53EF\u7528: ${h}`}:(P.warn(_,"tracker \u88C5\u914D\u5931\u8D25",{projectId:t,error:h}),{ok:!1,status:500,error:`\u5DE5\u4F5C\u6D41\u88C5\u914D\u5931\u8D25: ${h}`})}let i=[];for(let m of s.handles)try{let v=(await m.fetchItemsByIds([r])).find(g=>g.id===r);v&&i.push({handle:m,item:v})}catch(h){let v=h instanceof Error?h.message:String(h);P.warn(_,"\u6309 id \u67E5\u8BB0\u5F55\u5931\u8D25\uFF0C\u8DF3\u8FC7\u8BE5\u5DE5\u4F5C\u6D41",{projectId:t,itemId:r,workflowId:m.workflowId,error:v})}if(i.length===0)return{ok:!1,status:404,error:"\u5728\u8BE5\u9879\u76EE\u7684\u5404\u5DE5\u4F5C\u6D41\u4E2D\u5747\u672A\u627E\u5230\u8BE5\u8BB0\u5F55"};if(i.length>1)return{ok:!1,status:409,error:`\u8BB0\u5F55\u540C\u65F6\u547D\u4E2D\u591A\u6761\u5DE5\u4F5C\u6D41\uFF08${i.map(m=>m.handle.workflowId).join(", ")}\uFF09\uFF0C\u8BF7\u5728\u8868\u5185\u76F4\u63A5\u56DE\u7B54`};let{handle:c,item:l}=i[0];try{await c.updateFields(r,{\u4EBA\u5DE5\u56DE\u590D:o})}catch(m){return{ok:!1,status:502,error:`\u5199\u5165\u4EBA\u5DE5\u56DE\u590D\u5217\u5931\u8D25: ${m instanceof Error?m.message:String(m)}`}}let d=!1,p=c.states?.blocked,f=c.states?.active?.[0],u=!!p&&l.state===p;if(p&&!u&&(u=await this.recheckUntilBlocked(c,r,p)),u)if(!f)P.warn(_,"\u72B6\u6001\u914D\u7F6E\u7F3A active[0]\uFF0C\u56DE\u7B54\u5DF2\u5199\u5165\u4F46\u5DE5\u5355\u4ECD\u5904 blocked",{projectId:t,itemId:r,workflowId:c.workflowId});else try{await c.updateState(r,f),d=!0}catch(m){let h=m instanceof Error?m.message:String(m);P.warn(_,"\u6062\u590D active \u72B6\u6001\u5931\u8D25\uFF08\u56DE\u7B54\u5DF2\u5199\u5165\uFF09",{projectId:t,itemId:r,error:h})}try{await c.appendEvent(r,"[\u95EE\u8BE2#\u9762\u677F] \u5DF2\u901A\u8FC7 Workbench \u9762\u677F\u63D0\u4EA4\u56DE\u7B54"+(d?"\uFF0C\u5DE5\u5355\u5DF2\u6062\u590D\u8F6E\u8BE2":"\uFF0C\u7B49\u5F85\u72B6\u6001\u6062\u590D"))}catch{}return P.info(_,"\u9762\u677F\u56DE\u7B54\u5DF2\u5199\u8868",{projectId:t,itemId:r,workflowId:c.workflowId,restoredToActive:d}),{ok:!0,workflowId:c.workflowId,stateBefore:l.state,restoredToActive:d}}async getProjectContext(e){let t=this.cache.get(e);if(t)return t;let r=zn.join(this.deps.workspaceRoot,e),o=await this.loadContext(r);return this.cache.set(e,o),o}async recheckUntilBlocked(e,t,r){let{attempts:o,delayMs:s}=this.deps.stateRecheck??Qn;for(let i=0;i<o;i++){s>0&&await eo(s);try{if((await e.fetchItemsByIds([t])).find(l=>l.id===t)?.state===r)return!0}catch(c){let l=c instanceof Error?c.message:String(c);P.warn(_,"\u62E8\u56DE\u524D\u91CD\u8BFB\u72B6\u6001\u5931\u8D25\uFF0C\u51C6\u5907\u91CD\u8BD5",{itemId:t,attempt:i+1,error:l})}}return!1}};async function to(n){let e=await Vn(n),t=[],r=[];for(let o of e.workflowEntries)try{let s=await Xn(o.templatePath,{envSource:e.envSource}),i=Yn(e,s.tracker);if(!i){r.push(`${o.id}: \u7F3A\u5C11 tracker \u914D\u7F6E`);continue}let c=Kn(e,o,i),l=new Jn(c.tracker,void 0,c.identity);await l.init(),t.push({workflowId:o.id,states:c.tracker.states,fetchItemsByIds:a(d=>l.fetchItemsByIds(d),"fetchItemsByIds"),updateFields:a((d,p)=>l.updateFields(d,p),"updateFields"),updateState:a((d,p)=>l.updateState(d,p),"updateState"),appendEvent:a((d,p)=>l.appendEvent(d,p),"appendEvent")})}catch(s){let i=s instanceof Error?s.message:String(s);r.push(`${o.id}: ${i}`),P.warn(_,"\u5DE5\u4F5C\u6D41 tracker \u88C5\u914D\u5931\u8D25",{configDir:n,workflowId:o.id,error:i})}if(t.length===0)throw new Error(`\u9879\u76EE ${n} \u672A\u88C5\u914D\u51FA\u4EFB\u4F55\u53EF\u7528\u5DE5\u4F5C\u6D41 tracker${r.length?`\uFF08${r.join("; ")}\uFF09`:""}`);return{handles:t}}a(to,"defaultLoadProjectContext");import ro from"os";import Wt from"path";import{mkdtemp as no,rm as oo,writeFile as so}from"fs/promises";import{logger as ae,substituteArgPath as io}from"aitable-workflow-core";var Ye=["aitable"],ce="relay:daemon";function Ut(n,e=Ye){if(!Array.isArray(n)||n.length===0)return{ok:!1,reason:"dws args must be a non-empty array"};for(let r of n){if(typeof r!="string")return{ok:!1,reason:"dws args must all be strings"};if(r.length===0)return{ok:!1,reason:"dws args must not contain empty tokens"};if(/[\u0000-\u001f]/.test(r))return{ok:!1,reason:"dws args must not contain control characters"}}let t=n[0];return t.startsWith("-")?{ok:!1,reason:"first dws arg must be a subcommand, not a flag"}:e.length>0&&!e.includes(t)?{ok:!1,reason:`dws command "${t}" is not allowed`}:{ok:!0}}a(Ut,"validateDwsArgs");async function Gt(n,e){let{requestId:t}=n,r=Ut(n.args,e.allowedCommands);if(!r.ok){ae.warn(ce,"run:dws rejected",{requestId:t,reason:r.reason}),e.send({type:"error",requestId:t,code:"dws_rejected",message:r.reason});return}ae.info(ce,"run:dws received",{requestId:t,command:n.args[0]});let o;try{let s=n.args,i=Object.entries(n.inlineFiles??{});if(i.length>0){o=await no(Wt.join(ro.tmpdir(),"aitable-dws-records-"));for(let[l,[d,p]]of i.entries()){let f=Wt.join(o,`records-${l}.json`);await so(f,p,"utf8"),s=io(s,d,f)}}let c=await e.createDwsClient(n.timeoutMs).runJson(s,n.timeoutMs!=null?{timeoutMs:n.timeoutMs}:void 0);e.send({type:"result",requestId:t,ok:!0,response:JSON.stringify(c)}),ae.info(ce,"run:dws done",{requestId:t})}catch(s){let i=s instanceof Error?s.message:String(s);ae.error(ce,"run:dws failed",{requestId:t,error:i}),e.send({type:"error",requestId:t,code:"dws_failed",message:i})}finally{o&&await oo(o,{recursive:!0,force:!0}).catch(()=>{})}}a(Gt,"handleRunDws");import{logger as le}from"aitable-workflow-core";var de="relay:daemon";async function qt(n,e){let{requestId:t}=n;le.info(de,"run:agent received",{requestId:t,projectId:n.projectId,agent:n.agent});try{let r=e.resolveWorkDir(n.projectId,n.workDir);e.trace.startRun({requestId:t,projectId:n.projectId,agent:n.agent,workDir:r}),await e.ensureDirectory(r);let o=e.rewritePrompt(n.prompt,n.workDir,r),s={agent:n.agent,workDir:r,onEvent:a(l=>{e.trace.appendEvent(t,l),e.send({type:"event",requestId:t,event:l})},"onEvent")};n.sessionId&&(s.sessionId=n.sessionId),n.permissionMode&&(s.adapterOptions={permissionMode:n.permissionMode}),n.timeoutMs!==void 0?s.timeoutMs=n.timeoutMs:e.agentTimeoutMs!=null&&(s.timeoutMs=e.agentTimeoutMs);let i=await e.runAgent(o,s),c;try{c=await e.collectArtifacts(t,n.projectId,r)}catch(l){let d=l instanceof Error?l.message:String(l);le.error(de,"artifact upload failed",{requestId:t,error:d}),e.trace.finishRun(t,{status:"failed",error:d,sessionId:i.sessionId}),e.send({type:"error",requestId:t,code:"artifact_upload_failed",message:d});return}e.trace.finishRun(t,{status:"succeeded",response:i.response,sessionId:i.sessionId}),e.send({type:"result",requestId:t,ok:!0,response:i.response,sessionId:i.sessionId,...c?{artifacts:c}:{}}),le.info(de,"run:agent done",{requestId:t,sessionId:i.sessionId,artifacts:c?.files.length??0})}catch(r){let o=r instanceof Error?r.message:String(r);le.error(de,"run:agent failed",{requestId:t,error:o}),e.trace.finishRun(t,{status:"failed",error:o}),e.send({type:"error",requestId:t,code:"agent_failed",message:o})}}a(qt,"handleRunAgent");import zt from"path";import{logger as Jt,loadRecipeDefinitionResult as ao,ToolkitError as co,AITableTracker as lo,createCodeReviewToolkitFromConfig as uo,createCodingToolkit as po,createGitToolkitFromConfig as fo,createTableToolkit as mo,workspaceAgentConfigPath as go,resolveCodingWorkspaceDir as ho}from"aitable-workflow-core";var Vt="relay:daemon",Yt=29*6e4;function Kt(n,e){return Math.min(n??e??5*6e4,Yt)}a(Kt,"resolveRecipeTimeoutMs");async function Xt(n,e){let{requestId:t}=n,r=`recipe:${n.projectId}:${n.itemId}:${n.stepId}`;e.trace.startRun({requestId:r,projectId:n.projectId,agent:n.codingConfig?.engine??"recipe",workDir:e.projectDir});try{let o=Ht(e.projectDir,n.recipePath);await e.ensureWorkspace();let s=await ao(zt.dirname(o),zt.basename(o,".recipe.ts"),{cacheBust:n.requestId});if(!s.definition)throw new Error(`recipe definition not loadable: ${n.recipePath}\uFF1B${s.failure.message}`);let i=s.definition,c=new Map(Object.entries(n.globalVars??{})),l={},d=[],p={itemId:n.itemId,stepId:n.stepId,input:n.input,variables:n.variables,toolkit:await e.buildToolkit(r,i.meta.role),signal:AbortSignal.timeout(Kt(i.meta.timeoutMs,n.timeoutMs)),log:a(u=>{d.push(u),e.trace.appendEvent(r,{type:"text",content:u}),Jt.info(Vt,`[recipe ${n.stepId}] ${u}`,{requestId:t})},"log"),config:n.stepConfig??{},configDir:e.projectDir,trackerRef:n.trackerRef??{baseId:"",tableId:""},setGlobalVar:a((u,m)=>{c.set(u,m),l[u]=m},"setGlobalVar"),getGlobalVar:a(u=>vo(c,u),"getGlobalVar"),report:a(()=>{},"report")},f=await i.execute(p);e.trace.finishRun(r,{status:"succeeded",response:JSON.stringify(f)}),e.send({type:"result",requestId:t,ok:!0,response:JSON.stringify({...f,logs:d,globalVarWrites:l})})}catch(o){let s=o instanceof Error?o.message:String(o);e.trace.finishRun(r,{status:"failed",error:s}),Jt.error(Vt,"run:recipe failed",{requestId:t,message:s});let i=o instanceof co&&o.retryable===!1;e.send({type:"error",requestId:t,code:"run_recipe_failed",message:s,...i?{retryable:!1}:{}})}}a(Xt,"handleRunRecipe");async function Zt(n,e,t,r,o){let s={};if(n.trackerConfig){let i=r.createDwsClient(n.timeoutMs),c=new lo(n.trackerConfig,i);await c.init();let l={id:n.itemId,fields:{...n.input}};s.table=mo(c,l,i,n.trackerConfig.base_id)}if(n.codingConfig){let i=n.codingConfig,c=po({engine:i.engine,workDir:ho(o,i.workspaceDir??"."),projectRoot:e,...i.model?{model:i.model}:{},...i.timeoutMs!=null?{timeoutMs:i.timeoutMs}:{},configPath:go(e),runAgent:a(async(l,d)=>{let p=d?.onEvent;return r.runAgent(l,{...d,onEvent:a(f=>{r.appendTrace(t,f),p?.(f)},"onEvent")})},"runAgent")});s.coding={activeAgent:a(()=>c.activeAgent(),"activeAgent"),available:a(()=>c.available(),"available"),run:a((l,d)=>c.run(l,d),"run")}}if(n.gitConfig){let i=n.gitConfig;s.git=fo({gitBin:"git",timeoutMs:12e4,cloneDepth:i.cloneDepth??1,workspaceRoot:i.workspaceRoot??".workspace",projectRoot:e,defaultBranch:i.defaultBranch??"master",runner:r.gitRunner})}return n.codeReviewConfig&&(s.codeReview=uo({a1Bin:"a1",timeoutMs:3e4,runner:r.codeReviewRunner})),new Proxy(s,{get(i,c){if(typeof c=="symbol"||c==="then"||c in i)return i[c];throw new Error(`RECIPE_SNAPSHOT_GAP: ctx.toolkit.${String(c)} \u672A\u5728 daemon \u4FA7\u672C\u5730\u91CD\u5EFA\uFF08\xA73.3 spike \u6E05\u5355\uFF09`)}})}a(Zt,"buildRecipeToolkit");function vo(n,e){if(n.has(e))return n.get(e);let t=n;for(let r of e.split(".")){if(t instanceof Map){if(!t.has(r))return;t=t.get(r)}else if(t&&typeof t=="object")t=t[r];else return;if(t===void 0)return}return t}a(vo,"readGlobalVarPath");import rr from"path";import{createServer as wo}from"http";import{readFile as yo}from"fs/promises";import{existsSync as ko}from"fs";import{fileURLToPath as Ro}from"url";import{logger as bo,projectAgentEvents as nr}from"aitable-workflow-core";var Qt=`<!doctype html>
|
|
22
8
|
<html lang="zh-CN">
|
|
23
9
|
<head>
|
|
24
10
|
<meta charset="utf-8" />
|
|
@@ -69,7 +55,7 @@ import{a as st,b as it,m as at}from"./chunk-YDJTCQW4.js";import"./chunk-4B6V7VHM
|
|
|
69
55
|
</main>
|
|
70
56
|
<script src="/assets/workbench.js"></script>
|
|
71
57
|
</body>
|
|
72
|
-
</html>`,
|
|
58
|
+
</html>`,er=`:root {
|
|
73
59
|
--bg: #0e1116;
|
|
74
60
|
--panel: #161b22;
|
|
75
61
|
--panel-2: #1c2230;
|
|
@@ -136,6 +122,7 @@ body {
|
|
|
136
122
|
.badge.succeeded { color: var(--ok); border-color: var(--ok); }
|
|
137
123
|
.badge.failed { color: var(--err); border-color: var(--err); }
|
|
138
124
|
.badge.aborted { color: var(--warn); border-color: var(--warn); }
|
|
125
|
+
.badge.blocked { color: var(--warn); border-color: var(--warn); }
|
|
139
126
|
.badge.agent { color: var(--tool); border-color: var(--tool); }
|
|
140
127
|
.badge.source { color: var(--muted); border-color: var(--border); }
|
|
141
128
|
.badge.source-chat { color: var(--accent); border-color: var(--accent); }
|
|
@@ -162,6 +149,15 @@ details[open] > summary { border-bottom: 1px solid var(--border); }
|
|
|
162
149
|
.item.ask .ask-head { display: flex; align-items: center; gap: 8px; font-weight: 600; color: var(--warn); }
|
|
163
150
|
.item.ask .ask-q { white-space: pre-wrap; word-break: break-word; }
|
|
164
151
|
.item.ask .ask-body { font-family: var(--mono); font-size: 12.5px; color: var(--muted); white-space: pre-wrap; word-break: break-word; }
|
|
152
|
+
.ask-form { display: flex; flex-direction: column; gap: 6px; margin-top: 4px; }
|
|
153
|
+
.ask-form textarea {
|
|
154
|
+
resize: vertical; min-height: 48px; background: var(--panel-2); color: var(--text);
|
|
155
|
+
border: 1px solid var(--border); border-radius: 8px; padding: 8px 10px; font: inherit; font-size: 13px;
|
|
156
|
+
}
|
|
157
|
+
.ask-form textarea:focus { outline: none; border-color: var(--accent); }
|
|
158
|
+
.ask-row { display: flex; align-items: center; gap: 10px; }
|
|
159
|
+
.ask-status { font-size: 12px; color: var(--muted); }
|
|
160
|
+
.ask-status.err { color: var(--err); }
|
|
165
161
|
.empty { color: var(--muted); padding: 40px; text-align: center; }
|
|
166
162
|
.mono { font-family: var(--mono); }
|
|
167
163
|
.hidden { display: none !important; }
|
|
@@ -188,7 +184,7 @@ button.primary {
|
|
|
188
184
|
}
|
|
189
185
|
button.primary:hover { filter: brightness(1.08); }
|
|
190
186
|
button.primary:disabled { opacity: .5; cursor: not-allowed; }
|
|
191
|
-
`,
|
|
187
|
+
`,tr=`(function () {
|
|
192
188
|
"use strict";
|
|
193
189
|
var REFRESH_MS = 1500;
|
|
194
190
|
var state = {
|
|
@@ -196,6 +192,10 @@ button.primary:disabled { opacity: .5; cursor: not-allowed; }
|
|
|
196
192
|
// chat \u76F8\u5173\uFF08Task D\uFF09\uFF1AchatEnabled \u7531 /health \u63A2\u6D4B\uFF0C\u672A\u5F00\u542F\u65F6\u4E0B\u9762\u5176\u4F59\u5B57\u6BB5\u5168\u90E8\u65E0\u610F\u4E49\u3002
|
|
197
193
|
chatEnabled: false, chatAgents: [], chatAgentsLoaded: false,
|
|
198
194
|
chatSessionId: null, activeChatId: null,
|
|
195
|
+
// ask \u56DE\u7B54\uFF08G2\uFF09\uFF1AaskReplyEnabled \u540C\u6837\u7531 /health \u63A2\u6D4B\uFF08\u4E0E chat \u540C --trace-chat \u95E8\u63A7\uFF09\u3002
|
|
196
|
+
// askForms \u6309 requestId \u6682\u5B58\u6A2A\u5E45\u8868\u5355\u72B6\u6001\uFF1A\u65F6\u95F4\u7EBF\u6BCF\u6B21 SSE update \u90FD\u6574\u6BB5 innerHTML \u91CD\u7ED8\uFF0C
|
|
197
|
+
// \u4E0D\u6682\u5B58\u7684\u8BDD\u8F93\u5165\u8349\u7A3F\u4E0E\u300C\u5DF2\u63D0\u4EA4\u300D\u63D0\u793A\u4F1A\u88AB\u5237\u6389\u3002
|
|
198
|
+
askReplyEnabled: false, askForms: {},
|
|
199
199
|
};
|
|
200
200
|
var el = function (id) { return document.getElementById(id); };
|
|
201
201
|
|
|
@@ -217,6 +217,7 @@ button.primary:disabled { opacity: .5; cursor: not-allowed; }
|
|
|
217
217
|
var h = await getJSON("/health");
|
|
218
218
|
dot.className = "dot " + (h && h.ok ? "ok" : "err");
|
|
219
219
|
applyChatCapability(h && h.chat === true);
|
|
220
|
+
state.askReplyEnabled = h && h.ask_reply === true;
|
|
220
221
|
} catch (e) {
|
|
221
222
|
dot.className = "dot err";
|
|
222
223
|
}
|
|
@@ -347,7 +348,7 @@ button.primary:disabled { opacity: .5; cursor: not-allowed; }
|
|
|
347
348
|
? '<span class="badge source source-chat">chat</span>'
|
|
348
349
|
: "";
|
|
349
350
|
return '<li class="run-item' + active + '" data-id="' + esc(r.id) + '">' +
|
|
350
|
-
'<div class="row1"><span class="badge ' + esc(r.status) + '">' + esc(r.status) + '</span>' +
|
|
351
|
+
'<div class="row1"><span class="badge ' + esc(r.status) + '">' + esc(r.status === "blocked" ? "\u7B49\u5F85\u4EBA\u5DE5" : r.status) + '</span>' +
|
|
351
352
|
'<span class="badge agent">' + esc(r.agent) + '</span>' + sourceBadge +
|
|
352
353
|
'<span class="rid">' + esc(r.requestId) + '</span></div>' +
|
|
353
354
|
'<div class="row2"><span>' + esc(r.projectId || "-") + '</span>' +
|
|
@@ -375,7 +376,9 @@ button.primary:disabled { opacity: .5; cursor: not-allowed; }
|
|
|
375
376
|
return '<div class="item status' + cls + '"><span>' + esc(it.text) + '</span><span class="line"></span></div>';
|
|
376
377
|
}
|
|
377
378
|
if (it.kind === "ask") {
|
|
378
|
-
|
|
379
|
+
// \u56DE\u7B54\u8F93\u5165\u533A\u4E0D\u5728\u6B64\u5904\u76F4\u51FA\uFF1A\u80FD\u5426\u56DE\u7B54\u53D6\u51B3\u4E8E\u5F53\u524D run \u7684 key \u53EF\u5426\u89E3\u6790\u51FA\u5DE5\u5355\u4E14\u975E\u7EC8\u6001\uFF0C
|
|
380
|
+
// \u8BE5\u5224\u5B9A\u5728 renderDetail \u4E4B\u540E\u7531 hydrateAskForms \u5BF9 [data-ask] \u8282\u70B9\u8865\u6302\u8868\u5355\u3002
|
|
381
|
+
var html = '<div class="item ask" data-ask><div class="ask-head"><span class="tag ask">ask</span>' +
|
|
379
382
|
"<span>\u23F8 \u7B49\u5F85\u4EBA\u5DE5\u56DE\u7B54</span></div>" +
|
|
380
383
|
'<div class="ask-q">' + esc(it.text) + "</div>";
|
|
381
384
|
if (it.fullText) html += '<div class="ask-body">' + esc(it.fullText) + "</div>";
|
|
@@ -394,6 +397,94 @@ button.primary:disabled { opacity: .5; cursor: not-allowed; }
|
|
|
394
397
|
return { thinking: "\u601D\u8003\u8FC7\u7A0B", tool: "\u5DE5\u5177\u8C03\u7528", tool_result: "\u8FD4\u56DE\u7ED3\u679C", permission: "\u5F85\u6388\u6743", ask: "\u5411\u4EBA\u63D0\u95EE" }[kind] || kind;
|
|
395
398
|
}
|
|
396
399
|
|
|
400
|
+
// \u2500\u2500 ask \u56DE\u7B54\uFF08G2\uFF09\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
|
|
401
|
+
// \u9762\u677F\u53EA\u662F\u8868\u901A\u9053\u7684\u663E\u793A\u7AEF+\u8F93\u5165\u7AEF\uFF1A\u63D0\u4EA4\u7ECF POST /api/ask/reply \u4EE3\u7B14\u5199\u300C\u4EBA\u5DE5\u56DE\u590D\u300D\u5217
|
|
402
|
+
// \uFF08blocked \u5DE5\u5355\u987A\u5E26\u6062\u590D active\uFF09\uFF0C\u884C\u4E3A\u4E0E\u771F\u4EBA\u76F4\u63A5\u5728\u8868\u91CC\u586B\u8BE5\u5217\u5B8C\u5168\u4E00\u81F4\u3002
|
|
403
|
+
//
|
|
404
|
+
// \u6CE8\u610F\u7EC8\u6001\uFF1Aask \u88AB\u68C0\u6D4B\u5230\u65F6\u5F15\u64CE\u5DF2 abort\u3001record.blocked \u628A\u8BE5 trace run \u8BB0\u6210\u7EC8\u6001
|
|
405
|
+
// \uFF08trace.ts toRunnerTraceProjection: record.blocked \u2192 op:"block"\u3001status:"blocked"\uFF0C
|
|
406
|
+
// \u975E\u95EE\u8BE2\u7C7B\u963B\u585E\u4E5F\u8D70\u6B64\u5206\u652F\u4F46 question=null \u4E0D\u4EA7\u51FA ask \u4E8B\u4EF6\uFF09\uFF0C\u4E14\u540E\u7EED\u91CD\u8DD1\u590D\u7528\u540C\u4E00 requestId
|
|
407
|
+
// \u4E0D\u91CD\u7F6E status\u3002\u6240\u4EE5\u300C\u53EF\u56DE\u7B54\u300D\u7684 ask \u6A2A\u5E45\u672C\u5C31\u843D\u5728\u7EC8\u6001 run \u4E0A\uFF0C\u4E0D\u80FD\u4EE5 run.status \u8FC7\u6EE4\u2014\u2014
|
|
408
|
+
// \u6B63\u786E\u6027\u7531\u5199\u8DEF\u7531 AskReplyService \u515C\u5E95\uFF08\u8BB0\u5F55\u987B\u5B58\u5728\u3001blocked \u624D\u6062\u590D\u72B6\u6001\uFF0C\u5199\u300C\u4EBA\u5DE5\u56DE\u590D\u300D\u5217\u5E42\u7B49\u5B89\u5168\uFF09\u3002
|
|
409
|
+
|
|
410
|
+
/** runner run \u7684 key \u5F62\u6001 run:<projectId>:<itemId>:<stepId>\uFF08daemon recordRunnerTrace\uFF09\uFF1B\u5176\u4F59\u5F62\u6001\u4E0D\u53EF\u56DE\u7B54\u3002 */
|
|
411
|
+
function parseRunKey(requestId) {
|
|
412
|
+
var parts = String(requestId || "").split(":");
|
|
413
|
+
// stepId \u7406\u8BBA\u4E0A\u53EF\u80FD\u542B\u5192\u53F7\uFF1AprojectId/itemId \u53D6\u7B2C 2\u30013 \u6BB5\uFF0C\u5176\u4F59\u5F52 stepId\u3002
|
|
414
|
+
if (parts.length < 4 || parts[0] !== "run" || !parts[1] || !parts[2]) return null;
|
|
415
|
+
return { projectId: parts[1], itemId: parts[2], stepId: parts.slice(3).join(":") };
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
function setAskFormState(rid, patch) {
|
|
419
|
+
var cur = state.askForms[rid] || { draft: "", status: "", error: "", submitting: false, done: false };
|
|
420
|
+
var next = Object.assign({}, cur, patch);
|
|
421
|
+
state.askForms[rid] = next;
|
|
422
|
+
return next;
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
/** SSE \u6BCF\u6B21\u6574\u6BB5\u91CD\u7ED8\u65F6\u95F4\u7EBF\u540E\u8C03\u7528\uFF1A\u7ED9\u53EF\u56DE\u7B54\u7684 ask \u6A2A\u5E45\u6302/\u5237\u65B0\u56DE\u7B54\u8F93\u5165\u533A\u3002 */
|
|
426
|
+
function hydrateAskForms(run) {
|
|
427
|
+
if (!run || !state.askReplyEnabled) return;
|
|
428
|
+
var key = parseRunKey(run.requestId);
|
|
429
|
+
if (!key) return;
|
|
430
|
+
var st = state.askForms[run.requestId] || { draft: "", status: "", error: "", submitting: false, done: false };
|
|
431
|
+
Array.prototype.forEach.call(el("timeline").querySelectorAll("[data-ask]"), function (node) {
|
|
432
|
+
var form = node.querySelector(".ask-form");
|
|
433
|
+
if (!form) {
|
|
434
|
+
form = document.createElement("div");
|
|
435
|
+
form.className = "ask-form";
|
|
436
|
+
form.innerHTML =
|
|
437
|
+
'<textarea placeholder="\u56DE\u7B54\u540E\u5C06\u4EE3\u7B14\u5199\u5165\u8868\u683C\u300C\u4EBA\u5DE5\u56DE\u590D\u300D\u5217\uFF1Bblocked \u5DE5\u5355\u4F1A\u6062\u590D\u4E3A\u53EF\u8F6E\u8BE2\u72B6\u6001\uFF0C\u7B49\u5F85\u5F15\u64CE\u4E0B\u4E00\u8F6E\u62FE\u53D6"></textarea>' +
|
|
438
|
+
'<div class="ask-row"><button class="primary" type="button">\u63D0\u4EA4\u56DE\u7B54</button>' +
|
|
439
|
+
'<span class="ask-status"></span></div>';
|
|
440
|
+
node.appendChild(form);
|
|
441
|
+
var ta = form.querySelector("textarea");
|
|
442
|
+
var btn = form.querySelector("button");
|
|
443
|
+
ta.addEventListener("input", function () { setAskFormState(run.requestId, { draft: ta.value }); });
|
|
444
|
+
btn.addEventListener("click", function () { submitAskReply(run, key, ta, btn); });
|
|
445
|
+
}
|
|
446
|
+
var ta2 = form.querySelector("textarea");
|
|
447
|
+
var btn2 = form.querySelector("button");
|
|
448
|
+
var statusEl = form.querySelector(".ask-status");
|
|
449
|
+
ta2.value = st.draft || "";
|
|
450
|
+
ta2.disabled = st.submitting || st.done;
|
|
451
|
+
btn2.disabled = st.submitting || st.done;
|
|
452
|
+
btn2.textContent = st.done ? "\u5DF2\u63D0\u4EA4" : "\u63D0\u4EA4\u56DE\u7B54";
|
|
453
|
+
statusEl.textContent = st.error || st.status;
|
|
454
|
+
statusEl.classList.toggle("err", Boolean(st.error));
|
|
455
|
+
});
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
async function submitAskReply(run, key, ta, btn) {
|
|
459
|
+
var answer = ta.value.trim();
|
|
460
|
+
if (!answer) { setAskFormState(run.requestId, { error: "\u56DE\u7B54\u4E0D\u80FD\u4E3A\u7A7A" }); return; }
|
|
461
|
+
setAskFormState(run.requestId, { submitting: true, error: "", status: "\u63D0\u4EA4\u4E2D\u2026" });
|
|
462
|
+
var res;
|
|
463
|
+
try {
|
|
464
|
+
res = await fetch("/api/ask/reply", {
|
|
465
|
+
method: "POST",
|
|
466
|
+
headers: { "content-type": "application/json" },
|
|
467
|
+
body: JSON.stringify({ projectId: key.projectId, itemId: key.itemId, answer: answer }),
|
|
468
|
+
});
|
|
469
|
+
} catch (e) {
|
|
470
|
+
setAskFormState(run.requestId, { submitting: false, error: "\u63D0\u4EA4\u5931\u8D25\uFF1A" + e.message });
|
|
471
|
+
return;
|
|
472
|
+
}
|
|
473
|
+
var body = await res.json().catch(function () { return {}; });
|
|
474
|
+
if (!res.ok || !body.ok) {
|
|
475
|
+
setAskFormState(run.requestId, { submitting: false, error: "\u63D0\u4EA4\u5931\u8D25\uFF08" + res.status + "\uFF09\uFF1A" + (body.error || "") });
|
|
476
|
+
return;
|
|
477
|
+
}
|
|
478
|
+
setAskFormState(run.requestId, {
|
|
479
|
+
submitting: false,
|
|
480
|
+
done: true,
|
|
481
|
+
error: "",
|
|
482
|
+
status: body.restoredToActive
|
|
483
|
+
? "\u5DF2\u63D0\u4EA4\u5E76\u6062\u590D\u8F6E\u8BE2\uFF0C\u7B49\u5F85\u5F15\u64CE\u4E0B\u4E00\u8F6E\u62FE\u53D6"
|
|
484
|
+
: "\u5DF2\u63D0\u4EA4\uFF1B\u5DE5\u5355\u5F53\u524D\u4E3A\u300C" + body.stateBefore + "\u300D\uFF0C\u5982\u672A\u88AB\u62C9\u8D77\u8BF7\u5728\u8868\u5185\u6062\u590D\u72B6\u6001",
|
|
485
|
+
});
|
|
486
|
+
}
|
|
487
|
+
|
|
397
488
|
function stopStream() {
|
|
398
489
|
if (state.es) {
|
|
399
490
|
try { state.es.close(); } catch (e) { /* noop */ }
|
|
@@ -418,6 +509,8 @@ button.primary:disabled { opacity: .5; cursor: not-allowed; }
|
|
|
418
509
|
}
|
|
419
510
|
var atBottom = body.scrollHeight - body.scrollTop - body.clientHeight < 80;
|
|
420
511
|
body.innerHTML = groups.map(renderGroup).join("");
|
|
512
|
+
// innerHTML \u91CD\u7ED8\u4F1A\u5E26\u8D70\u4EA4\u4E92\u8282\u70B9\uFF1Aask \u6A2A\u5E45\u7684\u56DE\u7B54\u8F93\u5165\u533A\u5728\u91CD\u7ED8\u540E\u6309 state.askForms \u6062\u590D\u3002
|
|
513
|
+
hydrateAskForms(data.run);
|
|
421
514
|
if (atBottom) body.scrollTop = body.scrollHeight;
|
|
422
515
|
}
|
|
423
516
|
|
|
@@ -499,33 +592,47 @@ button.primary:disabled { opacity: .5; cursor: not-allowed; }
|
|
|
499
592
|
|
|
500
593
|
document.addEventListener("DOMContentLoaded", start);
|
|
501
594
|
})();
|
|
502
|
-
`;import{mkdir as Jr}from"fs/promises";import{logger as Pe}from"aitable-workflow-core";import Wr from"path";import{logger as Gr,resolveInsideRoot as Nt,assertPortableId as qr}from"aitable-workflow-core";var zr="relay:daemon";function ie(o,e,t){if(t&&t.trim()!=="")if(Wr.isAbsolute(t))Gr.warn(zr,"\u5FFD\u7565\u7EDD\u5BF9\u8DEF\u5F84 workDir\uFF0C\u56DE\u9000\u5230 workspaceRoot/projectId",{workDir:t,projectId:e});else return Nt(o,t,{allowRoot:!1});return Nt(o,qr(e,{label:"projectId"}),{allowRoot:!1})}c(ie,"resolveRelayWorkDir");var $e="relay:chat",Le="local-chat",Yr=128,Ut=32e3,ae=class{constructor(e){this.deps=e}deps;static{c(this,"ChatTurnManager")}active=new Map;listAgents(){return this.deps.detectAgents().map(e=>e.type)}start(e){if(typeof e.requestId!="string"||e.requestId.trim()===""||e.requestId.length>Yr)return{ok:!1,status:400,error:"requestId \u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32\u4E14\u4E0D\u8D85\u8FC7 128 \u5B57\u7B26"};if(this.active.has(e.requestId))return{ok:!1,status:409,error:"\u8BE5 requestId \u4ECD\u6709\u6D3B\u8DC3\u8F6E\u6B21\u672A\u7ED3\u675F"};if(typeof e.prompt!="string"||e.prompt.trim()==="")return{ok:!1,status:400,error:"prompt \u4E0D\u80FD\u4E3A\u7A7A"};if(e.prompt.length>Ut)return{ok:!1,status:400,error:`prompt \u8D85\u8FC7\u957F\u5EA6\u4E0A\u9650 ${Ut}`};let t=new AbortController;return this.active.set(e.requestId,t),this.deps.enqueue(()=>this.runTurn(e,t)),{ok:!0}}stop(e){let t=this.active.get(e);return t?(t.abort(),!0):!1}activeCount(){return this.active.size}async runTurn(e,t){let{requestId:n}=e;try{let r=e.agent??this.listAgents()[0];if(!r){this.fail(n,"\u672C\u673A\u672A\u68C0\u6D4B\u5230\u53EF\u7528\u7684\u7F16\u7A0B Agent");return}let s;try{s=ie(this.deps.workspaceRoot,Le,e.workDir)}catch(d){let p=d instanceof Error?d.message:String(d);this.fail(n,`workDir \u8D8A\u754C\u6216\u975E\u6CD5\uFF1A${p}`);return}await Jr(s,{recursive:!0}),this.deps.store.startRun({requestId:n,projectId:Le,agent:r,workDir:s,source:"chat"});let i={agent:r,workDir:s,signal:t.signal,onEvent:c(d=>this.deps.store.appendEvent(n,d),"onEvent")};e.sessionId&&(i.sessionId=e.sessionId);let a=e.timeoutMs??this.deps.defaultTimeoutMs;a!=null&&(i.timeoutMs=a);let l;try{l=await this.deps.runAgent(e.prompt,i)}catch(d){let p=d instanceof Error?d.message:String(d),u=t.signal.aborted?"aborted":"failed";this.deps.store.finishRun(n,{status:u,error:p}),Pe.warn($e,"chat turn ended with error",{requestId:n,status:u,error:p});return}this.deps.store.finishRun(n,{status:"succeeded",response:l.response,sessionId:l.sessionId}),Pe.info($e,"chat turn succeeded",{requestId:n,sessionId:l.sessionId})}finally{this.active.delete(n)}}fail(e,t){this.deps.store.startRun({requestId:e,projectId:Le,agent:"qoder",workDir:"",source:"chat"}),this.deps.store.finishRun(e,{status:"failed",error:t}),Pe.warn($e,"chat turn rejected before agent run",{requestId:e,error:t})}};import Oe from"ws";import{logger as P,RELAY_REJECTED_CODE as Vr,isRelayMessage as Kr}from"aitable-workflow-core";var $="relay:conn",Wt=1e3,Xr=3e4,Zr=Number(process.env.AITABLE_RELAY_SERVER_STALE_MS??9e4),ce=class{static{c(this,"RelayConnection")}ws=null;delay=Wt;timer=null;watchdog=null;should=!0;permanentlyRejected=!1;accepted=!1;lastServerFrameAt=0;serverUrl;key;token;onMessage;onOpen;onAccepted;onPermanentReject;mkWs;staleMs;constructor(e){this.serverUrl=e.serverUrl,this.key=e.key??"",this.token=e.token??"",this.onMessage=e.onMessage,this.onOpen=e.onOpen,this.onAccepted=e.onAccepted,this.onPermanentReject=e.onPermanentReject,this.mkWs=e.mkWs??(t=>new Oe(t)),this.staleMs=e.staleMs??Zr}connect(){this.permanentlyRejected||(this.should=!0,this.doConnect())}send(e){this.ws&&this.ws.readyState===Oe.OPEN&&this.ws.send(JSON.stringify(e))}close(){this.should=!1,this.timer&&(clearTimeout(this.timer),this.timer=null),this.watchdog&&(clearTimeout(this.watchdog),this.watchdog=null),this.ws?.close()}isPermanentlyRejected(){return this.permanentlyRejected}currentSocket(){return this.ws}buildUrl(){let e=this.serverUrl.replace(/\/+$/,"").replace(/^http/,"ws"),t=this.token?`token=${encodeURIComponent(this.token)}`:`key=${encodeURIComponent(this.key)}`;return`${e}/api/relay/connect?${t}`}doConnect(){if(!this.should||this.permanentlyRejected)return;let e=this.buildUrl();P.info($,"connecting",{serverUrl:this.serverUrl}),this.watchdog&&(clearTimeout(this.watchdog),this.watchdog=null),this.accepted=!1,this.lastServerFrameAt=0;let t=this.mkWs(e);this.ws=t,t.on("open",()=>{P.info($,"connected"),this.onOpen?.(t)}),t.on("message",n=>{this.accepted||(this.accepted=!0,this.delay=Wt,this.onAccepted?.(t)),this.lastServerFrameAt=Date.now(),this.armWatchdog();let r;try{r=JSON.parse(typeof n=="string"?n:String(n))}catch{return}Kr(r)&&(r.type==="ping"&&this.send({type:"pong"}),this.onMessage(r))}),t.on("close",(n,r)=>{this.watchdog&&(clearTimeout(this.watchdog),this.watchdog=null);let s=r==null?"":String(r);if(n===Vr){this.permanentlyRejected=!0,this.should=!1,P.error($,"server permanently rejected this machine: its connection key is unknown or was removed; re-issue the relay connect command and restart with the new key",{code:n,reason:s}),this.onPermanentReject?.({code:n,reason:s});return}P.warn($,"disconnected",{code:n}),this.scheduleReconnect()}),t.on("error",n=>{P.error($,"ws error",{detail:n instanceof Error?n.message:String(n)})})}armWatchdog(){this.watchdog&&clearTimeout(this.watchdog),this.watchdog=setTimeout(()=>{if(!(!this.accepted||!this.lastServerFrameAt||this.ws?.readyState!==Oe.OPEN)){P.warn($,"server heartbeat stale; closing socket to reconnect",{staleMs:Date.now()-this.lastServerFrameAt});try{this.ws.close()}catch{}}},this.staleMs+1),this.watchdog.unref?.()}scheduleReconnect(){!this.should||this.permanentlyRejected||this.timer||(P.info($,"reconnecting",{ms:this.delay}),this.timer=setTimeout(()=>{this.timer=null,this.doConnect()},this.delay),this.timer.unref?.(),this.delay=Math.min(this.delay*2,Xr))}};import{createHash as Qr}from"crypto";import{readdir as eo,readFile as to,stat as no}from"fs/promises";import Gt from"path";import{isAllowedArtifactPath as ro,normalizeArtifactRelPath as oo}from"aitable-workflow-core";var qt={async upload(o,e,t){let n=await fetch(o,{method:"PUT",body:e,headers:{...t}});if(!n.ok)throw new Error(`artifact PUT failed: ${n.status} ${n.statusText}`)}};async function zt(o){let e=[];return await Jt(o,o,e),e.sort((t,n)=>t.relPath.localeCompare(n.relPath))}c(zt,"scanArtifacts");async function Jt(o,e,t){let n;try{n=await eo(e,{withFileTypes:!0})}catch{return}for(let r of n){if(r.name==="node_modules"||r.name.startsWith("."))continue;let s=Gt.join(e,r.name);if(r.isDirectory())await Jt(o,s,t);else if(r.isFile()){let i=Gt.relative(o,s).replace(/\\/g,"/");if(!ro(i))continue;let a=await no(s),l=await to(s),d=Qr("sha256").update(l).digest("hex");t.push({relPath:oo(i),absPath:s,size:a.size,sha256:d})}}}c(Jt,"walk");import nn from"path";import{logger as x}from"aitable-workflow-core";import{logger as L,spawnManagedProcess as so}from"aitable-workflow-core";var O="engine-supervisor",je=2e3,le=class{static{c(this,"EngineSupervisor")}options;doSpawn;setTimer;clearTimer;child=null;childGen=0;consecutiveFailures=0;lastExitCode=null;lastError=null;restartTimer=null;stopped=!0;constructor(e){this.options=e,this.doSpawn=e.spawnImpl??so,this.setTimer=e.setTimeoutImpl??((t,n)=>setTimeout(t,n)),this.clearTimer=e.clearTimeoutImpl??(t=>clearTimeout(t))}get status(){return{running:this.child!=null,pid:this.child?.managed.child.pid??null,generation:this.childGen,startedAt:this.child?new Date(this.child.startedAt).toISOString():null,consecutiveFailures:this.consecutiveFailures,lastExitCode:this.lastExitCode,lastError:this.lastError}}start(){this.stopped=!1,!this.child&&this.spawnChild()}async stop(){this.stopped=!0,this.restartTimer&&(this.clearTimer(this.restartTimer),this.restartTimer=null);let e=this.child;if(!e)return;e.stopping=!0;let t=e.managed.child.pid;if(t==null){this.child=null;return}let n=e.gen;await e.managed.terminateTree({gracePeriodMs:this.options.drainTimeoutMs??2e4}),e.managed.child.exitCode==null&&e.managed.child.signalCode==null&&(L.error(O,"\u5F15\u64CE\u8FDB\u7A0B\u672A\u54CD\u5E94\u5F3A\u5236\u7EC8\u6B62\uFF0C\u653E\u5F03\u7B49\u5F85\uFF08\u53EF\u80FD\u6B8B\u7559\u5B64\u513F\u8FDB\u7A0B\uFF09",{projectId:this.options.projectId,pid:t,generation:n}),this.child?.gen===n&&(this.child=null))}spawnChild(){this.childGen+=1;let e=this.childGen,t=["run","--config",this.options.workspaceDir,"--emit-events","ipc"],n=this.doSpawn({command:process.execPath,args:[this.options.cliPath,...t],cwd:this.options.workspaceDir,stdio:["ignore","pipe","pipe","ipc"],...this.options.env?{env:this.options.env}:{}}),r=n.child,s={managed:n,gen:e,startedAt:Date.now(),stopping:!1};this.child=s,L.info(O,"engine started",{projectId:this.options.projectId,pid:r.pid,generation:e}),r.on("message",i=>{io(i)&&this.options.onRunEvent?.(i.event)}),r.on("error",i=>{this.lastError=i.message,L.error(O,"engine spawn error",{projectId:this.options.projectId,error:i.message})}),r.on("exit",(i,a)=>this.handleExit(s,i,a)),this.forwardChildOutput(r.stdout,s,"stdout"),this.forwardChildOutput(r.stderr,s,"stderr")}forwardChildOutput(e,t,n){if(!e)return;e.setEncoding("utf8");let r="",s=c(i=>{let a=i.trim();if(!a)return;let l=a.length>je?`${a.slice(0,je)}\u2026[+${a.length-je}]`:a;L.info(O,l,{projectId:this.options.projectId,generation:t.gen,stream:n})},"emit");e.on("data",i=>{if(this.child?.gen!==t.gen)return;let l=(r+i).split(/\r?\n/);r=l.pop()??"";for(let d of l)s(d)}),e.on("end",()=>{r.trim()&&this.child?.gen===t.gen&&s(r),r=""})}handleExit(e,t,n){if(this.child?.gen===e.gen&&(this.child=null),this.lastExitCode=t,L.info(O,"engine exited",{projectId:this.options.projectId,generation:e.gen,code:t,signal:n}),e.stopping||this.stopped)return;this.consecutiveFailures+=1;let r=this.options.maxConsecutiveFailures??5;if(this.consecutiveFailures>=r){L.error(O,"engine crash loop\uFF0C\u505C\u6B62\u91CD\u542F\u5E76\u4E0A\u62A5",{projectId:this.options.projectId,failures:this.consecutiveFailures}),this.stopped=!0,this.options.onCrashLoop?.({projectId:this.options.projectId,failures:this.consecutiveFailures,lastExitCode:t});return}let s=this.options.restartBackoffMs??1e3,i=this.options.restartBackoffMaxMs??6e4,a=Math.min(i,s*2**(this.consecutiveFailures-1));L.warn(O,"engine \u5F02\u5E38\u9000\u51FA\uFF0C\u9000\u907F\u91CD\u542F",{projectId:this.options.projectId,failures:this.consecutiveFailures,delayMs:a}),this.restartTimer=this.setTimer(()=>{this.restartTimer=null,!this.stopped&&!this.child&&this.spawnChild()},a)}markHealthy(){this.consecutiveFailures=0}};function io(o){return typeof o=="object"&&o!==null&&o.type==="run-event"&&"event"in o}c(io,"isRunEventMessage");import{appendFile as ao,mkdir as co,rename as lo,stat as po}from"fs/promises";import uo from"path";import{logger as de}from"aitable-workflow-core";var pe="event-spool",ue=class{static{c(this,"EventSpool")}options;setInterval;clearInterval;now;buffer=[];pending=[];seq=0;timer=null;flushing=!1;constructor(e){this.options=e,this.setInterval=e.setIntervalImpl??((t,n)=>setInterval(t,n)),this.clearInterval=e.clearIntervalImpl??(t=>clearInterval(t)),this.now=e.now??Date.now}get lastSeq(){return this.seq}get pendingCount(){return this.pending.length}start(){this.timer||(this.timer=this.setInterval(()=>{this.flush()},this.options.flushIntervalMs??500))}async stop(){this.timer&&(this.clearInterval(this.timer),this.timer=null),await this.flush()}append(e){this.seq+=1;let t={seq:this.seq,ts:new Date(this.now()).toISOString(),event:e};this.pending.push(t),this.buffer.push(t);let n=this.options.maxPending??5e3;if(this.pending.length>n){let s=this.pending.splice(0,this.pending.length-n);de.warn(pe,"\u5F85\u53D1\u4E8B\u4EF6\u8D85\u4E0A\u9650\uFF0C\u4E22\u5F03\u6700\u65E7\u7684\u6279\u6B21",{projectId:this.options.projectId,dropped:s.length,untilSeq:s[s.length-1]?.seq})}let r=this.options.retain??2e3;this.buffer.length>r&&this.buffer.splice(0,this.buffer.length-r),this.options.persist!==!1&&this.persist(t)}async flush(){if(this.flushing||this.pending.length===0)return;this.flushing=!0;let e=this.pending.slice(0,this.options.maxBatch??200);try{await this.options.send(e);let t=new Set(e.map(n=>n.seq));this.pending=this.pending.filter(n=>!t.has(n.seq))}catch(t){de.warn(pe,"\u4E8B\u4EF6\u6279\u4E0A\u884C\u5931\u8D25\uFF08\u4FDD\u7559\u5F85\u4E0B\u8F6E\u91CD\u8BD5\uFF09",{projectId:this.options.projectId,count:e.length,error:t instanceof Error?t.message:String(t)})}finally{this.flushing=!1}}replayFrom(e){let t=new Set(this.pending.map(r=>r.seq)),n=this.buffer.filter(r=>r.seq>e&&!t.has(r.seq));return n.length===0?0:(this.pending=[...this.pending,...n].sort((r,s)=>r.seq-s.seq),de.info(pe,"\u8865\u4F20\u7F3A\u53E3\u4E8B\u4EF6",{projectId:this.options.projectId,serverLastSeq:e,replay:n.length}),n.length)}async persist(e){let t=uo.join(this.options.spoolDir,"run-events.jsonl");try{await co(this.options.spoolDir,{recursive:!0}),await po(t).then(r=>r.size).catch(()=>0)>(this.options.rotateBytes??10*1024*1024)&&await lo(t,`${t}.1`).catch(()=>{}),await ao(t,`${JSON.stringify(e)}
|
|
503
|
-
`,"utf8")}catch(n){de.warn(pe,"spool \u843D\u76D8\u5931\u8D25",{projectId:this.options.projectId,error:n instanceof Error?n.message:String(n)})}}};import{readdir as Fe,rm as He,stat as ge}from"fs/promises";import N from"path";import{logger as q}from"aitable-workflow-core";import{createHash as yo}from"crypto";import{mkdir as De,readFile as ko,rename as bo,rm as Ro,writeFile as Xt}from"fs/promises";import me from"path";import{decodeWorkspaceBundle as Co,logger as xo,resolveInsideRoot as Ao}from"aitable-workflow-core";import{chmod as mo,readFile as fo,rename as go,writeFile as ho}from"fs/promises";var Yt="# \u2500\u2500\u2500 aitable-workflow managed credentials (auto-generated, do not edit) \u2500\u2500\u2500",Vt="# \u2500\u2500\u2500 end managed credentials \u2500\u2500\u2500";function vo(o,e){let t=o.split(`
|
|
504
|
-
`),n=t.indexOf(Yt),r=t.indexOf(Vt),s;n!==-1&&r!==-1&&r>n?s=[...t.slice(0,n),...t.slice(r+1)].join(`
|
|
505
|
-
`):s=o,s=s.replace(/^\n+/,"");let i=Object.entries(e).sort(([l],[d])=>l.localeCompare(d));return i.length===0?s:`${[Yt,...i.map(([l,d])=>`${l}=${wo(d)}`),Vt].join(`
|
|
506
|
-
`)}
|
|
507
|
-
${s?`
|
|
508
|
-
${s}`:""}`}c(vo,"mergeEnvContent");function wo(o){return o===""||/[\s#'"`\\]/.test(o)?`"${o.replace(/\\/g,"\\\\").replace(/"/g,'\\"').replace(/\n/g,"\\n")}"`:o}c(wo,"quoteEnvValue");async function Kt(o,e){let t=await fo(o,"utf8").catch(()=>""),n=vo(t,e);if(n===t||n===""&&t==="")return!1;let r=`${o}.aitable-sync-tmp`;return await ho(r,n,{encoding:"utf8",mode:384}),await mo(r,384).catch(()=>{}),await go(r,o),!0}c(Kt,"mergeEnvFile");var Eo="workspace-sync",fe=".workspace-meta.json";function So(o){return yo("sha256").update(o).digest("hex")}c(So,"sha256Hex");async function Me(o,e){let n=await(o.fetchImpl??fetch)(`${o.gatewayUrl.replace(/\/+$/,"")}${e}`,{headers:{authorization:`Bearer ${o.machineKey}`}});if(!n.ok){let r=await n.text().catch(()=>"");throw new Error(`runner API ${e} \u5931\u8D25: HTTP ${n.status} ${r.slice(0,200)}`)}return n}c(Me,"apiGet");async function Io(o){try{let e=await ko(me.join(o,fe),"utf8"),t=JSON.parse(e);return t&&typeof t.projectId=="string"?t:null}catch{return null}}c(Io,"readWorkspaceMeta");function Be(o,e){return Ao(o,e,{allowRoot:!1})}c(Be,"resolveTracked");async function To(o,e){let t=Be(o,e.path);await De(me.dirname(t),{recursive:!0});let n=`${t}.aitable-sync-tmp`;await Xt(n,e.content,"utf8"),await bo(n,t)}c(To,"writeTracked");async function Zt(o,e,t){let n=await Io(t);if(n&&n.projectId!==e)throw new Error(`\u5DE5\u4F5C\u533A\u76EE\u5F55\u5F52\u5C5E\u4E0D\u7B26: \u76EE\u5F55\u8BB0\u5F55 projectId=${n.projectId}\uFF0C\u8BF7\u6C42\u540C\u6B65 ${e}\uFF08${t}\uFF09`);let s=await(await Me(o,`/api/runner/workspace/${e}`)).json(),i=0,a=0,l="up-to-date",d=n?.trackedManifest??{};if(!n||n.revision!==s.revision){l="synced";let R=await Me(o,`/api/runner/workspace/${e}/bundle`),S=Co(Buffer.from(await R.arrayBuffer()));if(S.projectId!==e)throw new Error(`\u5FEB\u7167\u5305\u5F52\u5C5E\u4E0D\u7B26: \u5305\u5185 projectId=${S.projectId}\uFF0C\u671F\u671B ${e}`);S.revision!==s.revision&&(s.revision=S.revision),await De(t,{recursive:!0});let E={};for(let g of S.files)E[g.path]=So(g.content);for(let g of S.files)Be(t,g.path);let H=n?.trackedManifest??{};for(let g of S.files)H[g.path]!==E[g.path]&&(await To(t,g),i+=1);for(let g of Object.keys(H))if(E[g]===void 0){let h;try{h=Be(t,g)}catch(Ee){xo.warn(Eo,"\u8DF3\u8FC7\u8D8A\u754C\u7684\u65E7 manifest \u6761\u76EE",{projectId:e,path:g,error:Ee instanceof Error?Ee.message:String(Ee)});continue}await Ro(h,{force:!0}).catch(()=>{}),a+=1}d=E}let u=await(await Me(o,`/api/runner/workspace/${e}/credentials`)).json();await De(t,{recursive:!0});let m=await Kt(me.join(t,".env"),u.credentials??{}),f={projectId:e,revision:s.revision,syncedAt:new Date().toISOString(),trackedManifest:d};return await Xt(me.join(t,fe),`${JSON.stringify(f,null,2)}
|
|
509
|
-
`,"utf8"),{projectId:e,revision:s.revision,action:l,written:i,deleted:a,envUpdated:m}}c(Zt,"syncWorkspace");var z="runner-gc";async function en(o){let e=0,t;try{t=await Fe(o,{withFileTypes:!0})}catch{return 0}for(let n of t){let r=N.join(o,n.name);if(!n.isSymbolicLink()){if(n.isDirectory()){e+=await en(r);continue}e+=await ge(r).then(s=>s.size).catch(()=>0)}}return e}c(en,"dirSize");async function _o(o){let e=N.join(o,"projects"),t;try{t=await Fe(e,{withFileTypes:!0})}catch{return[]}let n=[];for(let r of t){if(!r.isDirectory())continue;let s=N.join(e,r.name),i=await ge(N.join(s,fe)).then(l=>l.mtimeMs).catch(()=>null),a=await ge(s).then(l=>l.mtimeMs).catch(()=>0);n.push({projectId:r.name,dir:s,lastTouchedMs:i??a,sizeBytes:await en(s)})}return n}c(_o,"scanProjects");async function Qt(o,e){let t=N.join(o,"traces"),n;try{n=await Fe(t,{withFileTypes:!0})}catch{return 0}let r=[];for(let a of n){if(!a.isFile())continue;let l=N.join(t,a.name),d=await ge(l).catch(()=>null);d&&r.push({full:l,size:d.size,mtimeMs:d.mtimeMs})}let s=r.reduce((a,l)=>a+l.size,0);if(s<=e)return 0;r.sort((a,l)=>a.mtimeMs-l.mtimeMs);let i=0;for(let a of r){if(s<=e)break;await He(a.full,{force:!0}).catch(()=>{}),s-=a.size,i+=a.size}return i}c(Qt,"pruneTraces");async function tn(o){let e=(o.now??Date.now)(),t=(o.ttlDays??14)*24*60*60*1e3,n=o.tracesMaxBytes??500*1024*1024,r=o.maxDiskBytes??20*1024*1024*1024,s=new Set(o.activeProjectIds),i=await _o(o.workspaceRoot),a=[],l=0;for(let m of i){if(s.has(m.projectId)){l+=await Qt(m.dir,n);continue}if(e-m.lastTouchedMs>=t){await He(m.dir,{recursive:!0,force:!0}).catch(f=>{q.warn(z,"\u9879\u76EE\u76EE\u5F55\u56DE\u6536\u5931\u8D25",{projectId:m.projectId,error:f instanceof Error?f.message:String(f)})}),a.push(m.projectId),q.info(z,"\u56DE\u6536\u8FC7\u671F\u9879\u76EE\u76EE\u5F55",{projectId:m.projectId,idleDays:Math.floor((e-m.lastTouchedMs)/864e5)});continue}l+=await Qt(m.dir,n)}let d=i.filter(m=>!a.includes(m.projectId)),p=d.reduce((m,f)=>m+f.sizeBytes,0)-l,u=!1;if(p>r){u=!0,q.warn(z,"\u5DE5\u4F5C\u533A\u8D85\u78C1\u76D8\u6C34\u4F4D\uFF0C\u5F00\u59CB\u56DE\u6536\u6700\u4E45\u672A\u8BA4\u9886\u9879\u76EE",{totalBytes:p,maxDiskBytes:r});let m=d.filter(f=>!s.has(f.projectId)).sort((f,R)=>f.lastTouchedMs-R.lastTouchedMs);for(let f of m){if(p<=r)break;await He(f.dir,{recursive:!0,force:!0}).catch(()=>{}),a.push(f.projectId),p-=f.sizeBytes,q.warn(z,"\u6C34\u4F4D\u56DE\u6536\u9879\u76EE\u76EE\u5F55",{projectId:f.projectId,freedBytes:f.sizeBytes})}p>r&&q.error(z,"\u56DE\u6536\u540E\u4ECD\u8D85\u78C1\u76D8\u6C34\u4F4D\uFF08\u6D3B\u8DC3\u9879\u76EE\u5360\u7528\uFF09\uFF0C\u9700\u4EBA\u5DE5\u4ECB\u5165",{totalBytes:p,maxDiskBytes:r})}return{removedProjects:a,tracesFreedBytes:l,diskPressure:u,totalBytes:Math.max(0,p)}}c(tn,"runGc");var A="runner-loop";function Po(o){return!(typeof o=="object"&&o!==null&&o.type==="run.agent_event")}c(Po,"shouldUplinkRunEvent");var he=class{static{c(this,"RunnerLoop")}options;maxWorkflows;setTimer;clearTimer;doSync;holdings=new Map;pollTimer=null;gcTimer=null;running=!1;claiming=!1;constructor(e){this.options=e,this.maxWorkflows=Math.max(1,Math.floor(e.maxWorkflows??3)),this.setTimer=e.setTimeoutImpl??((t,n)=>setTimeout(t,n)),this.clearTimer=e.clearTimeoutImpl??(t=>clearTimeout(t)),this.doSync=e.syncImpl??Zt}get held(){return[...this.holdings.values()].map(e=>({projectId:e.projectId,generation:e.generation,revision:e.revision,engine:e.engine.status}))}get freeSlots(){return Math.max(0,this.maxWorkflows-this.holdings.size)}start(){this.running||(this.running=!0,x.info(A,"runner loop \u542F\u52A8",{maxWorkflows:this.maxWorkflows,workspaceRoot:this.options.workspaceRoot}),this.claimOnce(),this.scheduleGc(0))}async stop(){this.running=!1,this.pollTimer&&(this.clearTimer(this.pollTimer),this.pollTimer=null),this.gcTimer&&(this.clearTimer(this.gcTimer),this.gcTimer=null),await Promise.all([...this.holdings.keys()].map(e=>this.releaseHolding(e,"daemon_shutdown")))}scheduleGc(e){let t=this.options.gcIntervalMs??864e5;!this.running||t<=0||(this.gcTimer&&this.clearTimer(this.gcTimer),this.gcTimer=this.setTimer(()=>{this.gcTimer=null,this.gcOnce().finally(()=>this.scheduleGc(t))},e))}async gcOnce(){try{let e=await(this.options.gcImpl??tn)({workspaceRoot:this.options.workspaceRoot,activeProjectIds:[...this.holdings.keys()],...this.options.gcOptions??{}});(e.removedProjects.length>0||e.tracesFreedBytes>0)&&x.info(A,"\u672C\u673A\u56DE\u6536\u5B8C\u6210",{removed:e.removedProjects.length,tracesFreedBytes:e.tracesFreedBytes,totalBytes:e.totalBytes})}catch(e){x.warn(A,"\u672C\u673A\u56DE\u6536\u5931\u8D25",{error:j(e)})}}onWakeup(){this.running&&this.claimOnce()}async claimOnce(){if(!this.running||this.claiming)return;this.claiming=!0;let e=this.options.defaultPollMs??1e4;try{let t=this.freeSlots;if(t>0){let n=await this.post("/api/runner/workflows/claim",{capacity:t});typeof n.nextPollAfterMs=="number"&&n.nextPollAfterMs>0&&(e=n.nextPollAfterMs);for(let r of n.grants??[])await this.acceptGrant(r,n.heartbeatIntervalSeconds)}}catch(t){x.warn(A,"claim \u5931\u8D25\uFF08\u9000\u907F\u540E\u91CD\u8BD5\uFF09",{error:j(t)}),e=Math.max(e,5e3)}finally{this.claiming=!1,this.scheduleNextPoll(e)}}scheduleNextPoll(e){this.running&&(this.pollTimer&&this.clearTimer(this.pollTimer),this.pollTimer=this.setTimer(()=>{this.pollTimer=null,this.claimOnce()},e))}async acceptGrant(e,t){if(this.holdings.has(e.projectId))return;let n=nn.join(this.options.workspaceRoot,"projects",e.projectId);x.info(A,"\u8BA4\u9886\u9879\u76EE",{projectId:e.projectId,generation:e.generation,workspaceDir:n});let r;try{r=await this.doSync(this.clientConfig(),e.projectId,n)}catch(l){x.error(A,"\u5DE5\u4F5C\u533A\u540C\u6B65\u5931\u8D25\uFF0C\u4EA4\u8FD8\u79DF\u7EA6",{projectId:e.projectId,error:j(l)}),await this.postSafe(`/api/runner/workflows/${e.projectId}/release`,{generation:e.generation,reason:"workspace_sync_failed"});return}let s=(this.options.createSupervisor??$o)({projectId:e.projectId,workspaceDir:n,cliPath:this.options.cliPath,onRunEvent:c(l=>this.handleRunEvent(e.projectId,l),"onRunEvent"),onCrashLoop:c(()=>{this.releaseHolding(e.projectId,"engine_crash_loop")},"onCrashLoop")}),i=this.options.sendRunEvents?new ue({projectId:e.projectId,spoolDir:n,send:c(l=>this.options.sendRunEvents(e.projectId,l),"send")}):null;i?.start();let a={projectId:e.projectId,generation:e.generation,revision:r.revision,engine:s,spool:i,heartbeatTimer:null,busy:!1};this.holdings.set(e.projectId,a),s.start(),this.scheduleHeartbeat(a,(t??15)*1e3)}handleRunEvent(e,t){Po(t)&&this.holdings.get(e)?.spool?.append(t),this.options.onRunEvent?.(e,t)}scheduleHeartbeat(e,t){this.running&&(e.heartbeatTimer&&this.clearTimer(e.heartbeatTimer),e.heartbeatTimer=this.setTimer(()=>{e.heartbeatTimer=null,this.heartbeatOnce(e)},t))}async heartbeatOnce(e){if(!this.running||e.busy||!this.holdings.has(e.projectId))return;let t=this.options.defaultHeartbeatMs??15e3;try{let n=await this.post(`/api/runner/workflows/${e.projectId}/heartbeat`,{generation:e.generation,workspaceRevision:e.revision,engineStatus:e.engine.status,...e.spool?{lastEventSeq:e.spool.lastSeq}:{}}),r=typeof n.nextIntervalSeconds=="number"&&n.nextIntervalSeconds>0?n.nextIntervalSeconds*1e3:t;if(e.spool&&typeof n.lastEventSeq=="number"&&e.spool.replayFrom(n.lastEventSeq),n.action==="stop"){x.info(A,"\u5FC3\u8DF3\u4E0B\u53D1 stop\uFF0C\u505C\u6B62\u5F15\u64CE",{projectId:e.projectId}),await this.releaseHolding(e.projectId,"heartbeat_stop");return}if(n.action==="resync"){await this.resyncHolding(e)&&this.scheduleHeartbeat(e,r);return}e.engine.markHealthy(),this.scheduleHeartbeat(e,r)}catch(n){x.warn(A,"\u5FC3\u8DF3\u5931\u8D25\uFF08\u4FDD\u6301\u5F15\u64CE\u8FD0\u884C\uFF0C\u7B49\u5F85\u6062\u590D\u6216\u79DF\u7EA6\u8FC7\u671F\uFF09",{projectId:e.projectId,error:j(n)}),this.scheduleHeartbeat(e,Math.min(t,5e3))}}async resyncHolding(e){if(e.busy)return!0;e.busy=!0;let t=nn.join(this.options.workspaceRoot,"projects",e.projectId);try{x.info(A,"\u5DE5\u4F5C\u533A\u9700\u91CD\u540C\u6B65\uFF0C\u91CD\u542F\u5F15\u64CE",{projectId:e.projectId}),await e.engine.stop();let n=await this.doSync(this.clientConfig(),e.projectId,t);e.revision=n.revision,e.engine.start()}catch(n){return x.error(A,"\u91CD\u540C\u6B65\u5931\u8D25\uFF0C\u4EA4\u8FD8\u79DF\u7EA6",{projectId:e.projectId,error:j(n)}),e.busy=!1,await this.releaseHolding(e.projectId,"resync_failed"),!1}return e.busy=!1,!0}async releaseHolding(e,t){let n=this.holdings.get(e);n&&(this.holdings.delete(e),n.heartbeatTimer&&(this.clearTimer(n.heartbeatTimer),n.heartbeatTimer=null),await n.engine.stop().catch(r=>{x.warn(A,"\u505C\u6B62\u5F15\u64CE\u5F02\u5E38",{projectId:e,error:j(r)})}),await n.spool?.stop().catch(()=>{}),await this.postSafe(`/api/runner/workflows/${e}/release`,{generation:n.generation,reason:t}),x.info(A,"\u5DF2\u8BA9\u51FA\u79DF\u7EA6",{projectId:e,reason:t}),this.running&&this.scheduleNextPoll(this.options.defaultPollMs??1e4))}clientConfig(){return{gatewayUrl:this.options.gatewayUrl,machineKey:this.options.machineKey,...this.options.fetchImpl?{fetchImpl:this.options.fetchImpl}:{}}}async post(e,t){let r=await(this.options.fetchImpl??fetch)(`${this.options.gatewayUrl.replace(/\/+$/,"")}${e}`,{method:"POST",headers:{authorization:`Bearer ${this.options.machineKey}`,"content-type":"application/json"},body:JSON.stringify(t??{})});if(!r.ok){let s=await r.text().catch(()=>"");throw new Error(`runner API ${e} \u5931\u8D25: HTTP ${r.status} ${s.slice(0,200)}`)}return await r.json()}async postSafe(e,t){try{await this.post(e,t)}catch(n){x.warn(A,"\u6536\u5C3E\u8BF7\u6C42\u5931\u8D25\uFF08\u79DF\u7EA6\u5C06\u7531\u670D\u52A1\u7AEF\u8FC7\u671F\u56DE\u6536\uFF09",{pathname:e,error:j(n)})}}};function $o(o){return new le({projectId:o.projectId,workspaceDir:o.workspaceDir,cliPath:o.cliPath,...o.onRunEvent?{onRunEvent:o.onRunEvent}:{},...o.onCrashLoop?{onCrashLoop:c(()=>o.onCrashLoop(),"onCrashLoop")}:{}})}c($o,"defaultSupervisorFactory");function j(o){return o instanceof Error?o.message:String(o)}c(j,"describeError");import{spawn as Oo}from"child_process";import{existsSync as jo}from"fs";import Y from"path";import{fileURLToPath as Mo}from"url";import{appendFileSync as fc,statSync as gc,renameSync as hc,mkdirSync as vc,existsSync as wc}from"fs";import Lo from"path";var bc=10*1024*1024;function J(o){return Lo.join(Q(o),"daemon.log")}c(J,"logFilePath");var ve=Y.dirname(Mo(import.meta.url));function Ne(){let o=[Y.resolve(ve,"..","..","bin","aitable-workflow.mjs"),Y.resolve(ve,"..","bin","aitable-workflow.mjs"),Y.resolve(ve,"..","..","dist","cli.js"),Y.resolve(ve,"cli.js")];return o.find(e=>jo(e))??o[0]}c(Ne,"resolveDaemonEntry");var Do=Ne();async function V(o){await ct(o.agentId);let e=["relay"];o.serverUrl&&e.push("--server-url",o.serverUrl),o.token&&e.push("--token",o.token),o.key&&e.push("--key",o.key),o.name&&e.push("--name",o.name),o.workspaceRoot&&e.push("--workspace-root",o.workspaceRoot),o.machineId&&e.push("--machine-id",o.machineId),o.maxTasks&&e.push("--max-tasks",String(o.maxTasks));let t=await import("fs").then(i=>{let a=J(o.agentId);return i.openSync(a,"a")}),n=Oo(process.execPath,[Do,...e],{detached:!0,stdio:["ignore",t,t],env:{...process.env}});try{let{closeSync:i}=await import("fs");i(t)}catch{}n.unref();let{writeFile:r}=await import("fs/promises"),{pidFilePath:s}=await import("./pid-file-KT5KHCKU.js");return n.pid&&await r(s(o.agentId),String(n.pid),"utf8"),{pid:n.pid??0}}c(V,"startDaemon");async function we(o,e=5e3){let t=await Se(o);if(t===null||!G(t))return await ee(o),!1;try{process.kill(t,"SIGTERM")}catch{return await ee(o),!1}let n=Date.now()+e;for(;Date.now()<n&&G(t);)await new Promise(r=>setTimeout(r,200));if(G(t))try{process.kill(t,"SIGKILL")}catch{}return await ee(o),!0}c(we,"stopDaemon");async function K(o){let e=await Se(o),t=e!==null&&G(e),n=null;if(t&&e!==null)try{let{readFile:r}=await import("fs/promises"),s=await r(`/proc/${e}/stat`,"utf8"),i=parseInt(s.split(" ")[21]??"0",10),a=await r("/proc/uptime","utf8"),p=parseFloat(a.split(" ")[0]??"0")-i/100;n=Math.round(p*1e3)}catch{}return{agentId:o,running:t,pid:t?e:null,uptimeMs:n,logFile:J(o)}}c(K,"getDaemonStatus");function es(o){return o.replace(/\/+$/,"").replace(/^ws/,"http")}c(es,"toHttpBase");var b="relay:daemon",be="relay:trace",an=["aitable"],ts="dws",ns=20,rs=500,os=2e4,on=8e3,Ue="127.0.0.1",ss=200,is=15e3,We=class{static{c(this,"AgentTraceRingBuffer")}maxRuns;maxEventsPerRun;now;runs=new Map;order=[];listeners=new Map;constructor(e={}){this.maxRuns=Math.max(1,Math.floor(e.maxRuns??ns)),this.maxEventsPerRun=Math.max(1,Math.floor(e.maxEventsPerRun??rs)),this.now=e.now??(()=>new Date().toISOString())}subscribeRun(e,t){let n=this.listeners.get(e);return n||(n=new Set,this.listeners.set(e,n)),n.add(t),()=>{let r=this.listeners.get(e);r&&(r.delete(t),r.size===0&&this.listeners.delete(e))}}notify(e){let t=this.listeners.get(e);if(!(!t||t.size===0))for(let n of[...t])try{n()}catch{}}startRun(e){this.runs.delete(e.requestId);let t=this.order.indexOf(e.requestId);if(t>=0&&this.order.splice(t,1),this.order.length>=this.maxRuns){let n=this.order.shift();n&&(this.runs.delete(n),this.notify(n))}this.order.push(e.requestId),this.runs.set(e.requestId,{...e,startedAt:this.now(),status:"running",events:[],eventCount:0,droppedEvents:0})}appendEvent(e,t){let n=this.runs.get(e);if(n){for(n.eventCount+=1,n.events.push(ln(t));n.events.length>this.maxEventsPerRun;)n.events.shift(),n.droppedEvents+=1;this.notify(e)}}finishRun(e,t){let n=this.runs.get(e);n&&(n.status=t.status,n.endedAt=this.now(),t.error&&(n.error=ze(t.error,on)),t.response&&(n.responsePreview=ze(t.response,on)),t.sessionId&&(n.sessionId=t.sessionId),this.notify(e))}listRuns(){return[...this.order].reverse().map(e=>this.runs.get(e)).filter(e=>!!e).map(e=>({...cn(e),eventBufferSize:e.events.length}))}getRun(e){let t=this.runs.get(e);return t?ls(t):void 0}},Ge=class{constructor(e,t){this.store=e;this.options=t;this.server=Ho((n,r)=>{this.handle(n,r).catch(s=>{let i=s instanceof Error?s.message:String(s);w.error(be,"trace http handler error",{error:i}),r.headersSent?r.end():v(r,500,{error:"internal_error"})})})}store;options;static{c(this,"AgentTraceHttpServer")}server;started=!1;start(){if(this.started)return Promise.resolve();let e=this.options.host??Ue;return new Promise((t,n)=>{let r=c(i=>{this.server.off("listening",s),n(i)},"onError"),s=c(()=>{this.server.off("error",r),this.started=!0,t()},"onListening");this.server.once("error",r),this.server.once("listening",s),this.server.listen(this.options.port,e)})}stop(){return this.started?new Promise((e,t)=>{this.server.close(n=>{if(n){t(n);return}this.started=!1,e()})}):Promise.resolve()}address(){let e=this.server.address();return!e||typeof e=="string"?null:{host:this.options.host??Ue,port:e.port}}async handle(e,t){let n=new URL(e.url??"/","http://127.0.0.1"),r=e.method??"GET";if(r==="GET"){await this.handleGet(n,t);return}if(r==="POST"){await this.handlePost(e,n,t);return}v(t,405,{error:"method_not_allowed"})}async handleGet(e,t){if(e.pathname==="/"||e.pathname==="/index.html"||e.pathname==="/assistant"||e.pathname==="/assistant/"){await this.serveAssistantFile(t,"index.html","text/html; charset=utf-8");return}if(e.pathname==="/classic"||e.pathname==="/classic/"){ye(t,200,"text/html; charset=utf-8",Bt);return}if(e.pathname==="/assets/workbench.css"){ye(t,200,"text/css; charset=utf-8",Ht);return}if(e.pathname==="/assets/workbench.js"){ye(t,200,"application/javascript; charset=utf-8",Ft);return}let n=/^\/assistant\/assets\/([A-Za-z0-9._-]+)$/.exec(e.pathname);if(n){let l=n[1]??"",d=l.endsWith(".css")?"text/css; charset=utf-8":l.endsWith(".js")?"application/javascript; charset=utf-8":"application/octet-stream";await this.serveAssistantFile(t,`assets/${l}`,d);return}if(e.pathname==="/health"){v(t,200,{ok:!0,chat:!!this.options.chat});return}if(e.pathname==="/api/chat/agents"){if(!this.options.chat){v(t,404,{error:"not_found"});return}v(t,200,{agents:this.options.chat.listAgents()});return}if(e.pathname==="/runs"){v(t,200,{runs:this.store.listRuns()});return}let r=/^\/runs\/([^/]+)\/events$/.exec(e.pathname);if(r){let l=decodeURIComponent(r[1]??""),d=this.store.getRun(l);if(!d){v(t,404,{error:"run_not_found"});return}v(t,200,{run:d,events:d.events});return}if(e.pathname==="/api/runs"){v(t,200,{runs:this.store.listRuns().map(ke)});return}let s=/^\/api\/runs\/([^/]+)$/.exec(e.pathname);if(s){let l=this.store.getRun(decodeURIComponent(s[1]??""));if(!l){v(t,404,{error:"run_not_found"});return}v(t,200,{run:ke(l)});return}let i=/^\/api\/runs\/([^/]+)\/events$/.exec(e.pathname);if(i){let l=this.store.getRun(decodeURIComponent(i[1]??""));if(!l){v(t,404,{error:"run_not_found"});return}let d=rn(l.events);v(t,200,{run:ke(l),groups:d,eventCount:l.eventCount,droppedEvents:l.droppedEvents});return}let a=/^\/api\/runs\/([^/]+)\/stream$/.exec(e.pathname);if(a){this.handleSse(t,decodeURIComponent(a[1]??""));return}v(t,404,{error:"not_found"})}async handlePost(e,t,n){let r=this.options.chat;if(!r){v(n,404,{error:"not_found"});return}let s=/^\/api\/chat\/([^/]+)\/stop$/.exec(t.pathname);if(s){let i=decodeURIComponent(s[1]??"");if(!r.stop(i)){v(n,404,{error:"no_active_chat"});return}v(n,200,{ok:!0,requestId:i});return}if(t.pathname==="/api/chat"){let i=await cs(e);if(!i.ok){v(n,i.status,{error:i.error});return}let a=i.value,l=r.start({requestId:typeof a.requestId=="string"?a.requestId:"",prompt:typeof a.prompt=="string"?a.prompt:"",...typeof a.agent=="string"?{agent:a.agent}:{},...typeof a.workDir=="string"?{workDir:a.workDir}:{},...typeof a.sessionId=="string"?{sessionId:a.sessionId}:{},...typeof a.timeoutMs=="number"?{timeoutMs:a.timeoutMs}:{}});if(!l.ok){v(n,l.status,{error:l.error});return}v(n,202,{accepted:!0,stream:`/api/runs/${encodeURIComponent(a.requestId??"")}/stream`});return}v(n,404,{error:"not_found"})}buildSnapshot(e){let t=this.store.getRun(e);return t?{run:ke(t),groups:rn(t.events)}:{run:null,groups:[]}}async serveAssistantFile(e,t,n){let r=this.resolveAssistantDir();if(r)try{let s=await sn(I.join(r,t));e.statusCode=200,e.setHeader("content-type",n),e.setHeader("cache-control","no-store"),e.end(s);return}catch{}ye(e,404,"text/plain; charset=utf-8","assistant UI \u672A\u6784\u5EFA\uFF1A\u5728 packages/cli \u4E0B\u6267\u884C pnpm run build\uFF08\u6216\u5355\u72EC\u6784\u5EFA assistant-ui \u5B50\u5305\uFF09\u540E\u91CD\u8BD5\u3002")}resolveAssistantDir(){if(this.options.assistantDir)return this.options.assistantDir;let e=[new URL("./assistant/",import.meta.url),new URL("../../dist/assistant/",import.meta.url)];for(let t of e){let n=Bo(t);try{if(qo(I.join(n,"index.html")))return n}catch{}}return null}handleSse(e,t){if(!this.store.getRun(t)){v(e,404,{error:"run_not_found"});return}e.statusCode=200,e.setHeader("content-type","text/event-stream; charset=utf-8"),e.setHeader("cache-control","no-cache, no-transform"),e.setHeader("connection","keep-alive"),e.setHeader("x-accel-buffering","no"),e.write(`retry: 3000
|
|
595
|
+
`;var Co="relay:trace",Ao=20,xo=500,To=2e4,or=8e3,sr="127.0.0.1",Eo=200,So=15e3,U=class{static{a(this,"AgentTraceRingBuffer")}maxRuns;maxEventsPerRun;now;runs=new Map;order=[];listeners=new Map;constructor(e={}){this.maxRuns=Math.max(1,Math.floor(e.maxRuns??Ao)),this.maxEventsPerRun=Math.max(1,Math.floor(e.maxEventsPerRun??xo)),this.now=e.now??(()=>new Date().toISOString())}subscribeRun(e,t){let r=this.listeners.get(e);return r||(r=new Set,this.listeners.set(e,r)),r.add(t),()=>{let o=this.listeners.get(e);o&&(o.delete(t),o.size===0&&this.listeners.delete(e))}}notify(e){let t=this.listeners.get(e);if(!(!t||t.size===0))for(let r of[...t])try{r()}catch{}}startRun(e){this.runs.delete(e.requestId);let t=this.order.indexOf(e.requestId);if(t>=0&&this.order.splice(t,1),this.order.length>=this.maxRuns){let r=this.order.shift();r&&(this.runs.delete(r),this.notify(r))}this.order.push(e.requestId),this.runs.set(e.requestId,{...e,startedAt:this.now(),status:"running",events:[],eventCount:0,droppedEvents:0})}appendEvent(e,t){let r=this.runs.get(e);if(r){for(r.eventCount+=1,r.events.push(lr(t));r.events.length>this.maxEventsPerRun;)r.events.shift(),r.droppedEvents+=1;this.notify(e)}}finishRun(e,t){let r=this.runs.get(e);r&&(r.status=t.status,r.endedAt=this.now(),t.error&&(r.error=Xe(t.error,or)),t.response&&(r.responsePreview=Xe(t.response,or)),t.sessionId&&(r.sessionId=t.sessionId),this.notify(e))}resumeRun(e){let t=this.runs.get(e);return t?(t.status="running",delete t.endedAt,t.rounds=(t.rounds??1)+1,this.notify(e),t.rounds):null}listRuns(){return[...this.order].reverse().map(e=>this.runs.get(e)).filter(e=>!!e).map(e=>({...cr(e),eventBufferSize:e.events.length}))}getRun(e){let t=this.runs.get(e);return t?Po(t):void 0}},G=class{constructor(e,t){this.store=e;this.options=t;this.server=wo((r,o)=>{this.handle(r,o).catch(s=>{let i=s instanceof Error?s.message:String(s);bo.error(Co,"trace http handler error",{error:i}),o.headersSent?o.end():w(o,500,{error:"internal_error"})})})}store;options;static{a(this,"AgentTraceHttpServer")}server;started=!1;start(){if(this.started)return Promise.resolve();let e=this.options.host??sr;return new Promise((t,r)=>{let o=a(i=>{this.server.off("listening",s),r(i)},"onError"),s=a(()=>{this.server.off("error",o),this.started=!0,t()},"onListening");this.server.once("error",o),this.server.once("listening",s),this.server.listen(this.options.port,e)})}stop(){return this.started?new Promise((e,t)=>{this.server.close(r=>{if(r){t(r);return}this.started=!1,e()})}):Promise.resolve()}address(){let e=this.server.address();return!e||typeof e=="string"?null:{host:this.options.host??sr,port:e.port}}async handle(e,t){let r=new URL(e.url??"/","http://127.0.0.1"),o=e.method??"GET";if(o==="GET"){await this.handleGet(r,t);return}if(o==="POST"){await this.handlePost(e,r,t);return}w(t,405,{error:"method_not_allowed"})}async handleGet(e,t){if(e.pathname==="/"||e.pathname==="/index.html"||e.pathname==="/assistant"||e.pathname==="/assistant/"){await this.serveAssistantFile(t,"index.html","text/html; charset=utf-8");return}if(e.pathname==="/classic"||e.pathname==="/classic/"){ue(t,200,"text/html; charset=utf-8",Qt);return}if(e.pathname==="/assets/workbench.css"){ue(t,200,"text/css; charset=utf-8",er);return}if(e.pathname==="/assets/workbench.js"){ue(t,200,"application/javascript; charset=utf-8",tr);return}let r=/^\/assistant\/assets\/([A-Za-z0-9._-]+)$/.exec(e.pathname);if(r){let l=r[1]??"",d=l.endsWith(".css")?"text/css; charset=utf-8":l.endsWith(".js")?"application/javascript; charset=utf-8":"application/octet-stream";await this.serveAssistantFile(t,`assets/${l}`,d);return}if(e.pathname==="/health"){w(t,200,{ok:!0,chat:!!this.options.chat,ask_reply:!!this.options.askReply});return}if(e.pathname==="/api/chat/agents"){if(!this.options.chat){w(t,404,{error:"not_found"});return}w(t,200,{agents:this.options.chat.listAgents()});return}if(e.pathname==="/runs"){w(t,200,{runs:this.store.listRuns()});return}let o=/^\/runs\/([^/]+)\/events$/.exec(e.pathname);if(o){let l=decodeURIComponent(o[1]??""),d=this.store.getRun(l);if(!d){w(t,404,{error:"run_not_found"});return}w(t,200,{run:d,events:d.events});return}if(e.pathname==="/api/runs"){w(t,200,{runs:this.store.listRuns().map(pe)});return}let s=/^\/api\/runs\/([^/]+)$/.exec(e.pathname);if(s){let l=this.store.getRun(decodeURIComponent(s[1]??""));if(!l){w(t,404,{error:"run_not_found"});return}w(t,200,{run:pe(l)});return}let i=/^\/api\/runs\/([^/]+)\/events$/.exec(e.pathname);if(i){let l=this.store.getRun(decodeURIComponent(i[1]??""));if(!l){w(t,404,{error:"run_not_found"});return}let d=nr(l.events);w(t,200,{run:pe(l),groups:d,eventCount:l.eventCount,droppedEvents:l.droppedEvents});return}let c=/^\/api\/runs\/([^/]+)\/stream$/.exec(e.pathname);if(c){this.handleSse(t,decodeURIComponent(c[1]??""));return}w(t,404,{error:"not_found"})}async handlePost(e,t,r){let o=this.options.chat,s=this.options.askReply;if(!o&&!s){w(r,404,{error:"not_found"});return}if(t.pathname==="/api/ask/reply"){if(!s){w(r,404,{error:"not_found"});return}let c=await ir(e);if(!c.ok){w(r,c.status,{error:c.error});return}let l=c.value,d=await s.reply({projectId:typeof l.projectId=="string"?l.projectId:"",itemId:typeof l.itemId=="string"?l.itemId:"",answer:typeof l.answer=="string"?l.answer:""});if(!d.ok){w(r,d.status,{error:d.error});return}w(r,200,{ok:!0,workflowId:d.workflowId,stateBefore:d.stateBefore,restoredToActive:d.restoredToActive});return}if(!o){w(r,404,{error:"not_found"});return}let i=/^\/api\/chat\/([^/]+)\/stop$/.exec(t.pathname);if(i){let c=decodeURIComponent(i[1]??"");if(!o.stop(c)){w(r,404,{error:"no_active_chat"});return}w(r,200,{ok:!0,requestId:c});return}if(t.pathname==="/api/chat"){let c=await ir(e);if(!c.ok){w(r,c.status,{error:c.error});return}let l=c.value,d=o.start({requestId:typeof l.requestId=="string"?l.requestId:"",prompt:typeof l.prompt=="string"?l.prompt:"",...typeof l.agent=="string"?{agent:l.agent}:{},...typeof l.workDir=="string"?{workDir:l.workDir}:{},...typeof l.sessionId=="string"?{sessionId:l.sessionId}:{},...typeof l.timeoutMs=="number"?{timeoutMs:l.timeoutMs}:{}});if(!d.ok){w(r,d.status,{error:d.error});return}w(r,202,{accepted:!0,stream:`/api/runs/${encodeURIComponent(l.requestId??"")}/stream`});return}w(r,404,{error:"not_found"})}buildSnapshot(e){let t=this.store.getRun(e);return t?{run:pe(t),groups:nr(t.events)}:{run:null,groups:[]}}async serveAssistantFile(e,t,r){let o=this.resolveAssistantDir();if(o)try{let s=await yo(rr.join(o,t));e.statusCode=200,e.setHeader("content-type",r),e.setHeader("cache-control","no-store"),e.end(s);return}catch{}ue(e,404,"text/plain; charset=utf-8","assistant UI \u672A\u6784\u5EFA\uFF1A\u5728 packages/cli \u4E0B\u6267\u884C pnpm run build\uFF08\u6216\u5355\u72EC\u6784\u5EFA assistant-ui \u5B50\u5305\uFF09\u540E\u91CD\u8BD5\u3002")}resolveAssistantDir(){if(this.options.assistantDir)return this.options.assistantDir;let e=[new URL("./assistant/",import.meta.url),new URL("../../dist/assistant/",import.meta.url)];for(let t of e){let r=Ro(t);try{if(ko(rr.join(r,"index.html")))return r}catch{}}return null}handleSse(e,t){if(!this.store.getRun(t)){w(e,404,{error:"run_not_found"});return}e.statusCode=200,e.setHeader("content-type","text/event-stream; charset=utf-8"),e.setHeader("cache-control","no-cache, no-transform"),e.setHeader("connection","keep-alive"),e.setHeader("x-accel-buffering","no"),e.write(`retry: 3000
|
|
510
596
|
|
|
511
|
-
`);let
|
|
512
|
-
data: ${JSON.stringify(
|
|
597
|
+
`);let r=!1,o=null,s=a((u,m)=>{e.write(`event: ${u}
|
|
598
|
+
data: ${JSON.stringify(m)}
|
|
513
599
|
|
|
514
|
-
`)},"writeFrame"),i=
|
|
600
|
+
`)},"writeFrame"),i=a(()=>{r||(r=!0,o&&clearTimeout(o),clearInterval(p),d(),e.end())},"cleanup"),c=a(()=>{if(o=null,r)return;let u=this.buildSnapshot(t);if(!u.run){s("finish",{run:null,groups:[]}),i();return}s("update",u),u.run.status!=="running"&&(s("finish",u),i())},"flush"),l=a(()=>{r||o||(o=setTimeout(c,Eo))},"schedule"),d=this.store.subscribeRun(t,l),p=setInterval(()=>{r||e.write(`: ping
|
|
515
601
|
|
|
516
|
-
`)},is);p.unref?.(),e.on("close",i);let u=this.buildSnapshot(t);s("snapshot",u),(!u.run||u.run.status!=="running")&&(s("finish",u),i())}};function ye(o,e,t,n){o.statusCode=e,o.setHeader("content-type",t),o.setHeader("cache-control","no-store"),o.end(n)}c(ye,"sendTraceText");function ke(o){let{events:e,eventBufferSize:t,...n}=o;return{...n,id:o.requestId,source:o.source??"server_workflow"}}c(ke,"toWorkbenchRunSummary");function v(o,e,t){o.statusCode=e,o.setHeader("content-type","application/json; charset=utf-8"),o.end(JSON.stringify(t))}c(v,"sendTraceJson");var as=64e3;async function cs(o){let e=[],t=0;for await(let s of o){let i=Buffer.isBuffer(s)?s:Buffer.from(s);if(t+=i.length,t>as)return{ok:!1,status:413,error:"request_body_too_large"};e.push(i)}let n=Buffer.concat(e).toString("utf8").trim();if(n==="")return{ok:!1,status:400,error:"request_body_required"};let r;try{r=JSON.parse(n)}catch{return{ok:!1,status:400,error:"invalid_json"}}return typeof r!="object"||r===null||Array.isArray(r)?{ok:!1,status:400,error:"request_body_must_be_object"}:{ok:!0,value:r}}c(cs,"readJsonBody");function ls(o){return{...cn(o),events:o.events.map(e=>ln(e))}}c(ls,"cloneTraceRun");function cn(o){let{events:e,...t}=o;return{...t}}c(cn,"cloneRunWithoutEvents");function ln(o){return qe(o)}c(ln,"cloneTraceEvent");function qe(o){if(typeof o=="string")return ze(o,os);if(Array.isArray(o))return o.map(e=>qe(e));if(o&&typeof o=="object"){let e={};for(let[t,n]of Object.entries(o))e[t]=qe(n);return e}return o}c(qe,"clipTraceValue");function ze(o,e){return o.length<=e?o:`${o.slice(0,e)}... [truncated ${o.length-e} chars]`}c(ze,"clipTraceText");function ds(o){if(typeof o!="object"||o===null)return null;let e=o,t=typeof e.itemId=="string"?e.itemId:null,n=typeof e.stepId=="string"?e.stepId:null;if(!t||!n)return null;switch(e.type){case"step.started":return{op:"start",itemId:t,stepId:n};case"run.agent_event":{let r=typeof e.text=="string"?e.text:void 0,s=typeof e.tool=="string"?e.tool:void 0,i=typeof e.args=="string"?e.args:void 0,a=null;return e.kind==="text"?a={type:"text",content:r}:e.kind==="thinking"?a={type:"thinking",content:r}:e.kind==="tool_use"?a={type:"tool_use",toolName:s,toolInput:i}:e.kind==="tool_result"?a={type:"tool_result",content:r}:e.kind==="result"&&(a={type:"result",content:r}),a?{op:"event",itemId:t,stepId:n,event:a}:null}case"step.succeeded":return{op:"finish",itemId:t,stepId:n,status:"succeeded"};case"step.failed":return{op:"finish",itemId:t,stepId:n,status:"failed",error:typeof e.error=="string"?e.error:void 0};case"record.blocked":return{op:"finish",itemId:t,stepId:n,status:"failed",error:typeof e.reason=="string"?e.reason:void 0};default:return null}}c(ds,"toRunnerTraceProjection");function ps(o,e=an){if(!Array.isArray(o)||o.length===0)return{ok:!1,reason:"dws args must be a non-empty array"};for(let n of o){if(typeof n!="string")return{ok:!1,reason:"dws args must all be strings"};if(n.length===0)return{ok:!1,reason:"dws args must not contain empty tokens"};if(/[\u0000-\u001f]/.test(n))return{ok:!1,reason:"dws args must not contain control characters"}}let t=o[0];return t.startsWith("-")?{ok:!1,reason:"first dws arg must be a subcommand, not a flag"}:e.length>0&&!e.includes(t)?{ok:!1,reason:`dws command "${t}" is not allowed`}:{ok:!0}}c(ps,"validateDwsArgs");function us(o){return Xo(o,["--version"],Zo({timeoutMs:5e3})).ok}c(us,"detectDwsAvailable");var Je=class{static{c(this,"RelayDaemon")}config;allowedDwsCommands;conn;runAgent;createDwsClient;detectAgents;detectDws;hostname;osString;onPermanentReject;artifactUploader;grantTimeoutMs;pendingGrants=new Map;maxTasks;inflight=0;taskQueue=[];runnerLoop;traceStore;traceHttpServer;chatManager;machineId;constructor(e,t={}){this.config={...e,dwsBin:e.dwsBin??ts},this.machineId=e.machineId,this.allowedDwsCommands=e.allowedDwsCommands??an,this.runAgent=t.runAgent??Jo,this.createDwsClient=t.createDwsClient??((r,s)=>new Yo({bin:r,timeoutMs:s})),this.detectAgents=t.detectAgents??(()=>zo()),this.detectDws=t.detectDws??(r=>us(r)),this.hostname=t.hostname??(()=>M.hostname()),this.osString=t.osString??(()=>`${M.platform()} ${M.arch()}`),this.onPermanentReject=t.onPermanentReject,this.artifactUploader=t.artifactUploader??qt,this.grantTimeoutMs=t.grantTimeoutMs??3e4,this.maxTasks=Math.max(1,Math.floor(e.maxTasks??1)),this.traceStore=t.traceStore??new We({maxRuns:e.traceRunBufferSize,maxEventsPerRun:e.traceEventBufferSize}),this.chatManager=e.traceChat&&e.traceHttpPort!=null?new ae({workspaceRoot:this.config.workspaceRoot,store:this.traceStore,runAgent:this.runAgent,detectAgents:this.detectAgents,enqueue:c(r=>this.enqueueTask(r),"enqueue"),defaultTimeoutMs:e.agentTimeoutMs}):null,this.traceHttpServer=e.traceHttpPort!=null?new Ge(this.traceStore,{host:e.traceHttpHost??Ue,port:e.traceHttpPort,...this.chatManager?{chat:this.chatManager}:{}}):null;let n=t.createConnection??(r=>new ce(r));this.conn=n({serverUrl:this.config.serverUrl,key:this.config.key,token:this.config.token,onMessage:c(r=>this.handleMessage(r),"onMessage"),onOpen:c(()=>this.handleOpen(),"onOpen"),onPermanentReject:c(r=>this.handlePermanentReject(r),"onPermanentReject")}),this.runnerLoop=this.buildRunnerLoop(t)}buildRunnerLoop(e){let t=Math.max(0,Math.floor(this.config.maxWorkflows??3));if(t===0)return null;let n=this.config.key??this.config.token;if(!n)return w.warn(b,"\u65E0 machine key/owner-token\uFF0C\u8DF3\u8FC7 RunnerLoop\uFF08run \u9636\u6BB5\u4E0D\u8BA4\u9886\u9879\u76EE\uFF09"),null;let r={gatewayUrl:es(this.config.serverUrl),machineKey:n,workspaceRoot:this.config.workspaceRoot,cliPath:Ne(),maxWorkflows:t,sendRunEvents:c((s,i)=>this.sendRunEvents(s,i),"sendRunEvents"),onRunEvent:c((s,i)=>this.recordRunnerTrace(s,i),"onRunEvent")};return(e.createRunnerLoop??(s=>new he(s)))(r)}recordRunnerTrace(e,t){let n=ds(t);if(!n)return;let r=`run:${e}:${n.itemId}:${n.stepId}`;if(n.op==="start"){this.traceStore.getRun(r)||this.traceStore.startRun({requestId:r,projectId:e,agent:"engine",workDir:this.config.workspaceRoot??e});return}if(n.op==="event"){this.traceStore.getRun(r)||this.traceStore.startRun({requestId:r,projectId:e,agent:"engine",workDir:this.config.workspaceRoot??e}),this.traceStore.appendEvent(r,n.event);return}this.traceStore.finishRun(r,{status:n.status,...n.error?{error:n.error}:{}})}sendRunEvents(e,t){t.length!==0&&this.conn.send({type:"run:events",projectId:e,entries:t})}start(){w.info(b,"starting",{serverUrl:this.config.serverUrl,workspaceRoot:this.config.workspaceRoot}),this.config.name||w.warn(b,"\u672A\u6307\u5B9A --name\uFF0C\u5C06\u4F7F\u7528\u4E3B\u673A\u540D\u4F5C\u4E3A\u673A\u5668\u6CE8\u518C\u540D\uFF1B\u591A\u673A\u573A\u666F\u4E0B hostname \u82E5\u91CD\u590D\u4F1A\u5BFC\u81F4\u8FDE\u63A5\u4E92\u76F8\u9876\u66FF\uFF0C\u5EFA\u8BAE\u663E\u5F0F\u6307\u5B9A --name",{hostname:this.hostname()}),this.startTraceHttpServer(),this.conn.connect(),this.runnerLoop?.start()}stop(){w.info(b,"stopping"),this.conn.close();let e=[];return this.runnerLoop&&e.push(this.runnerLoop.stop().catch(t=>{w.warn(b,"runner loop \u505C\u6B62\u5F02\u5E38",{error:t instanceof Error?t.message:String(t)})})),this.traceHttpServer&&e.push(this.traceHttpServer.stop().catch(t=>{w.warn(be,"trace http \u505C\u6B62\u5F02\u5E38",{error:t instanceof Error?t.message:String(t)})})),Promise.all(e).then(()=>{})}startTraceHttpServer(){this.traceHttpServer&&this.traceHttpServer.start().then(()=>{let e=this.traceHttpServer?.address();e&&w.info(be,"trace http listening",{url:`http://${e.host}:${e.port}`})}).catch(e=>{w.warn(be,"trace http \u542F\u52A8\u5931\u8D25\uFF0C\u672C\u5730\u4E8B\u4EF6\u4ECD\u4FDD\u7559\u5728\u5185\u5B58\u4F46\u65E0\u6CD5 HTTP \u67E5\u770B",{error:e instanceof Error?e.message:String(e)})})}buildReady(){let t={type:"ready",runtimes:Array.from(new Set(this.detectAgents().map(n=>n.type))),hasDws:this.detectDws(this.config.dwsBin),hostname:this.hostname(),os:this.osString()};return this.machineId&&(t.machineId=this.machineId),this.config.name&&(t.name=this.config.name),this.config.displayName&&(t.displayName=this.config.displayName),this.config.description&&(t.description=this.config.description),this.maxTasks>1&&(t.maxTasks=this.maxTasks),t}handleOpen(){let e=this.buildReady();w.info(b,"connected; sending ready",{runtimes:e.runtimes,hasDws:e.hasDws}),this.conn.send(e)}handlePermanentReject(e){w.error(b,"permanently rejected by gateway",{...e}),this.onPermanentReject?.(e)}handleMessage(e){switch(e.type){case"run:agent":this.enqueueTask(()=>this.handleRunAgent(e));break;case"run:dws":this.enqueueTask(()=>this.handleRunDws(e));break;case"upload:grant":this.resolveGrant(e);break;case"wf:available":this.runnerLoop?.onWakeup();break;case"ready:ack":e.machineId&&(this.machineId=e.machineId,w.info(b,"machine id assigned",{machineId:e.machineId}));break;default:break}}enqueueTask(e){let t=c(()=>{this.inflight+=1,e().finally(()=>{this.inflight-=1;let n=this.taskQueue.shift();n&&n()})},"exec");this.inflight<this.maxTasks?t():this.taskQueue.push(t)}async handleRunAgent(e){let{requestId:t}=e;w.info(b,"run:agent received",{requestId:t,projectId:e.projectId,agent:e.agent});try{let n=this.resolveWorkDir(e.projectId,e.workDir);this.traceStore.startRun({requestId:t,projectId:e.projectId,agent:e.agent,workDir:n}),await Fo(n,{recursive:!0});let r=this.rewritePromptWorkDir(e.prompt,e.workDir,n),s={agent:e.agent,workDir:n,onEvent:c(l=>{this.traceStore.appendEvent(t,l),this.conn.send({type:"event",requestId:t,event:l})},"onEvent")};e.sessionId&&(s.sessionId=e.sessionId),e.permissionMode&&(s.adapterOptions={permissionMode:e.permissionMode}),e.timeoutMs!==void 0?s.timeoutMs=e.timeoutMs:this.config.agentTimeoutMs!=null&&(s.timeoutMs=this.config.agentTimeoutMs);let i=await this.runAgent(r,s),a;try{a=await this.collectAndUploadArtifacts(t,e.projectId,n)}catch(l){let d=l instanceof Error?l.message:String(l);w.error(b,"artifact upload failed",{requestId:t,error:d}),this.traceStore.finishRun(t,{status:"failed",error:d,sessionId:i.sessionId}),this.conn.send({type:"error",requestId:t,code:"artifact_upload_failed",message:d});return}this.traceStore.finishRun(t,{status:"succeeded",response:i.response,sessionId:i.sessionId}),this.conn.send({type:"result",requestId:t,ok:!0,response:i.response,sessionId:i.sessionId,...a?{artifacts:a}:{}}),w.info(b,"run:agent done",{requestId:t,sessionId:i.sessionId,artifacts:a?a.files.length:0})}catch(n){let r=n instanceof Error?n.message:String(n);w.error(b,"run:agent failed",{requestId:t,error:r}),this.traceStore.finishRun(t,{status:"failed",error:r}),this.conn.send({type:"error",requestId:t,code:"agent_failed",message:r})}}async collectAndUploadArtifacts(e,t,n){let r=await zt(n);if(r.length===0)return;this.conn.send({type:"upload:request",requestId:e,projectId:t,files:r.map(a=>({path:a.relPath,size:a.size,sha256:a.sha256}))});let s=await this.awaitGrant(e);if(!s)throw new Error("upload:grant \u7B49\u5F85\u8D85\u65F6");if(s.grants.length===0){w.warn(b,"upload:grant \u65E0\u6388\u6743\u9879\uFF08gateway \u672A\u914D\u7F6E store \u6216\u5168\u88AB\u62D2\uFF09",{requestId:e,rejected:(s.rejected??[]).length});return}let i=[];for(let a of s.grants){let l=r.find(p=>p.relPath===a.path);if(!l)continue;let d=await sn(l.absPath);await this.artifactUploader.upload(a.url,d,a.headers),i.push({path:a.path,key:a.key,sha256:l.sha256,size:l.size})}return{store:"oss",files:i}}awaitGrant(e){return new Promise(t=>{let n=setTimeout(()=>{this.pendingGrants.delete(e),t(void 0)},this.grantTimeoutMs);n.unref?.(),this.pendingGrants.set(e,r=>{clearTimeout(n),t(r)})})}resolveGrant(e){let t=this.pendingGrants.get(e.requestId);t&&(this.pendingGrants.delete(e.requestId),t(e))}async handleRunDws(e){let{requestId:t}=e,n=ps(e.args,this.allowedDwsCommands);if(!n.ok){w.warn(b,"run:dws rejected",{requestId:t,reason:n.reason}),this.conn.send({type:"error",requestId:t,code:"dws_rejected",message:n.reason});return}w.info(b,"run:dws received",{requestId:t,command:e.args[0]});let r=e.args,s;try{let i=await this.materializeInlineFiles(e.args,e.inlineFiles);r=i.args,s=i.tmpDir;let l=await this.createDwsClient(this.config.dwsBin,e.timeoutMs).runJson(r,e.timeoutMs!=null?{timeoutMs:e.timeoutMs}:void 0);this.conn.send({type:"result",requestId:t,ok:!0,response:JSON.stringify(l)}),w.info(b,"run:dws done",{requestId:t})}catch(i){let a=i instanceof Error?i.message:String(i);w.error(b,"run:dws failed",{requestId:t,error:a}),this.conn.send({type:"error",requestId:t,code:"dws_failed",message:a})}finally{s&&await Wo(s,{recursive:!0,force:!0}).catch(()=>{})}}async materializeInlineFiles(e,t){let n=t?Object.entries(t):[];if(n.length===0)return{args:e};let r=await No(I.join(M.tmpdir(),"aitable-dws-records-")),s=e,i=0;for(let[a,l]of n){let d=I.join(r,`records-${i++}.json`);await Uo(d,l,"utf8"),s=Qo(s,a,d)}return{args:s,tmpDir:r}}resolveWorkDir(e,t){return ie(this.config.workspaceRoot,e,t)}rewritePromptWorkDir(e,t,n){let r=t?.trim();return!r||!I.isAbsolute(r)||r===n?e:e.split(r).join(n)}};function Ye(o,e){let t,n=o?.trim();if(n)t=I.isAbsolute(n)?I.resolve(n):I.resolve(M.homedir(),n);else{let r=e?.trim()?e.trim():"default";t=I.join(M.homedir(),".aitable-workflow","workspaces",Ko(r,{label:"agentId"}))}return Go(t,{recursive:!0}),t}c(Ye,"resolveWorkspaceRoot");function ms(o,e=process.env){let t=o.serverUrl??e.AITABLE_RELAY_SERVER_URL,n=o.key??e.AITABLE_RELAY_BOOTSTRAP_KEY,r=o.token??e.AITABLE_RELAY_TOKEN,s=o.workspaceRoot??e.AITABLE_RELAY_WORKSPACE_ROOT,i=o.machineId??e.AITABLE_RELAY_MACHINE_ID,a=o.name??e.AITABLE_RELAY_NAME,l=o.desc??e.AITABLE_RELAY_DESC,d=o.maxTasks??e.AITABLE_RELAY_MAX_TASKS,p=o.maxWorkflows??e.AITABLE_RELAY_MAX_WORKFLOWS,u=o.traceHttpPort??e.AITABLE_RELAY_TRACE_HTTP_PORT,m=o.traceHttpHost??e.AITABLE_RELAY_TRACE_HTTP_HOST,f=o.traceBufferSize??e.AITABLE_RELAY_TRACE_BUFFER_SIZE,R=o.traceEventsPerRun??e.AITABLE_RELAY_TRACE_EVENTS_PER_RUN,S=o.traceChat??e.AITABLE_RELAY_TRACE_CHAT,E=[];if(t||E.push("--server-url (\u6216 AITABLE_RELAY_SERVER_URL)"),!n&&!r&&E.push("--key/--token (\u6216 AITABLE_RELAY_BOOTSTRAP_KEY/AITABLE_RELAY_TOKEN)"),E.length>0)throw new Error(`relay \u7F3A\u5C11\u5FC5\u8981\u53C2\u6570: ${E.join(", ")}
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
602
|
+
`)},So);p.unref?.(),e.on("close",i);let f=this.buildSnapshot(t);s("snapshot",f),(!f.run||f.run.status!=="running")&&(s("finish",f),i())}};function ue(n,e,t,r){n.statusCode=e,n.setHeader("content-type",t),n.setHeader("cache-control","no-store"),n.end(r)}a(ue,"sendTraceText");function pe(n){let{events:e,eventBufferSize:t,...r}=n;return{...r,id:n.requestId,source:n.source??"server_workflow"}}a(pe,"toWorkbenchRunSummary");function w(n,e,t){n.statusCode=e,n.setHeader("content-type","application/json; charset=utf-8"),n.end(JSON.stringify(t))}a(w,"sendTraceJson");var Io=64e3;async function ir(n){let e=[],t=0;for await(let s of n){let i=Buffer.isBuffer(s)?s:Buffer.from(s);if(t+=i.length,t>Io)return{ok:!1,status:413,error:"request_body_too_large"};e.push(i)}let r=Buffer.concat(e).toString("utf8").trim();if(r==="")return{ok:!1,status:400,error:"request_body_required"};let o;try{o=JSON.parse(r)}catch{return{ok:!1,status:400,error:"invalid_json"}}return typeof o!="object"||o===null||Array.isArray(o)?{ok:!1,status:400,error:"request_body_must_be_object"}:{ok:!0,value:o}}a(ir,"readJsonBody");function Po(n){return{...cr(n),events:n.events.map(e=>lr(e))}}a(Po,"cloneTraceRun");function cr(n){let{events:e,...t}=n;return{...t}}a(cr,"cloneRunWithoutEvents");function lr(n){return Ke(n)}a(lr,"cloneTraceEvent");function Ke(n){if(typeof n=="string")return Xe(n,To);if(Array.isArray(n))return n.map(e=>Ke(e));if(n&&typeof n=="object"){let e={};for(let[t,r]of Object.entries(n))e[t]=Ke(r);return e}return n}a(Ke,"clipTraceValue");function Xe(n,e){return n.length<=e?n:`${n.slice(0,e)}... [truncated ${n.length-e} chars]`}a(Xe,"clipTraceText");var ar="ASK_HUMAN_DETECTED:";function _o(n){if(!n)return null;let e=n.indexOf(ar);if(e<0)return null;let t=n.slice(e+ar.length).trim();return t.length>0?t:null}a(_o,"extractAskHumanQuestion");function $o(n){if(typeof n!="object"||n===null)return null;let e=n,t=typeof e.itemId=="string"?e.itemId:null,r=typeof e.stepId=="string"?e.stepId:null;if(!t||!r)return null;switch(e.type){case"step.started":return{op:"start",itemId:t,stepId:r};case"run.agent_event":{let o=typeof e.text=="string"?e.text:void 0,s=typeof e.tool=="string"?e.tool:void 0,i=typeof e.args=="string"?e.args:void 0,c=null;return e.kind==="text"?c={type:"text",content:o}:e.kind==="thinking"?c={type:"thinking",content:o}:e.kind==="tool_use"?c={type:"tool_use",toolName:s,toolInput:i}:e.kind==="tool_result"?c={type:"tool_result",content:o}:e.kind==="result"&&(c={type:"result",content:o}),c?{op:"event",itemId:t,stepId:r,event:c}:null}case"step.succeeded":return{op:"finish",itemId:t,stepId:r,status:"succeeded"};case"step.failed":return{op:"finish",itemId:t,stepId:r,status:"failed",error:typeof e.error=="string"?e.error:void 0};case"record.blocked":{let o=typeof e.reason=="string"?e.reason:void 0;return{op:"block",itemId:t,stepId:r,question:_o(o),reason:o}}default:return null}}a($o,"toRunnerTraceProjection");function fe(n,e,t,r){let o=$o(t);if(!o)return;let s=`run:${e}:${o.itemId}:${o.stepId}`,i=a(()=>{n.getRun(s)||n.startRun({requestId:s,projectId:e,agent:"engine",workDir:r??e})},"ensureRun");if(o.op==="start"){if(n.getRun(s)){let c=n.resumeRun(s);c&&c>=2&&n.appendEvent(s,{type:"result",content:`\u25B6 \u7B2C ${c} \u8F6E\u7EED\u8DD1`})}return}if(o.op==="event"){i(),n.appendEvent(s,o.event);return}if(o.op==="block"){if(o.question)i(),n.appendEvent(s,{type:"tool_use",toolName:"AskUserQuestion",toolInput:o.question});else if(!n.getRun(s))return;n.finishRun(s,{status:"blocked",...o.reason?{error:o.reason}:{}});return}n.finishRun(s,{status:o.status,...o.error?{error:o.error}:{}})}a(fe,"recordTraceEvent");function dr(n){let e=null,t=a(()=>{e&&(n.startRun(e),e=null)},"flush");return{startRun:a(r=>{e=r},"startRun"),appendEvent:a((r,o)=>{t(),n.appendEvent(r,o)},"appendEvent"),finishRun:a((r,o)=>{if(o.status==="failed"&&t(),e){e=null;return}n.finishRun(r,o)},"finishRun")}}a(dr,"createLazyTraceSink");import Ze from"ws";import{logger as $,RELAY_REJECTED_CODE as Oo,isRelayMessage as jo}from"aitable-workflow-core";var O="relay:conn",ur=1e3,Mo=3e4,Do=Number(process.env.AITABLE_RELAY_SERVER_STALE_MS??9e4),me=class{static{a(this,"RelayConnection")}ws=null;delay=ur;timer=null;watchdog=null;should=!0;permanentlyRejected=!1;accepted=!1;lastServerFrameAt=0;serverUrl;token;onMessage;onOpen;onAccepted;onPermanentReject;mkWs;staleMs;constructor(e){this.serverUrl=e.serverUrl,this.token=e.token,this.onMessage=e.onMessage,this.onOpen=e.onOpen,this.onAccepted=e.onAccepted,this.onPermanentReject=e.onPermanentReject,this.mkWs=e.mkWs??(t=>new Ze(t)),this.staleMs=e.staleMs??Do}connect(){this.permanentlyRejected||(this.should=!0,this.doConnect())}send(e){this.ws&&this.ws.readyState===Ze.OPEN&&this.ws.send(JSON.stringify(e))}close(){this.should=!1,this.timer&&(clearTimeout(this.timer),this.timer=null),this.watchdog&&(clearTimeout(this.watchdog),this.watchdog=null),this.ws?.close()}isPermanentlyRejected(){return this.permanentlyRejected}currentSocket(){return this.ws}buildUrl(){return`${this.serverUrl.replace(/\/+$/,"").replace(/^http/,"ws")}/api/relay/connect?token=${encodeURIComponent(this.token)}`}doConnect(){if(!this.should||this.permanentlyRejected)return;let e=this.buildUrl();$.info(O,"connecting",{serverUrl:this.serverUrl}),this.watchdog&&(clearTimeout(this.watchdog),this.watchdog=null),this.accepted=!1,this.lastServerFrameAt=0;let t=this.mkWs(e);this.ws=t,t.on("open",()=>{$.info(O,"connected"),this.onOpen?.(t)}),t.on("message",r=>{this.accepted||(this.accepted=!0,this.delay=ur,this.onAccepted?.(t)),this.lastServerFrameAt=Date.now(),this.armWatchdog();let o;try{o=JSON.parse(typeof r=="string"?r:String(r))}catch{return}jo(o)&&(o.type==="ping"&&this.send({type:"pong"}),this.onMessage(o))}),t.on("close",(r,o)=>{this.watchdog&&(clearTimeout(this.watchdog),this.watchdog=null);let s=o==null?"":String(o);if(r===Oo){this.permanentlyRejected=!0,this.should=!1,$.error(O,"server permanently rejected this execution engine: its token is unknown or was revoked; copy its current token and restart the relay daemon",{code:r,reason:s}),this.onPermanentReject?.({code:r,reason:s});return}$.warn(O,"disconnected",{code:r}),this.scheduleReconnect()}),t.on("error",r=>{$.error(O,"ws error",{detail:r instanceof Error?r.message:String(r)})})}armWatchdog(){this.watchdog&&clearTimeout(this.watchdog),this.watchdog=setTimeout(()=>{if(!(!this.accepted||!this.lastServerFrameAt||this.ws?.readyState!==Ze.OPEN)){$.warn(O,"server heartbeat stale; closing socket to reconnect",{staleMs:Date.now()-this.lastServerFrameAt});try{this.ws.close()}catch{}}},this.staleMs+1),this.watchdog.unref?.()}scheduleReconnect(){!this.should||this.permanentlyRejected||this.timer||($.info(O,"reconnecting",{ms:this.delay}),this.timer=setTimeout(()=>{this.timer=null,this.doConnect()},this.delay),this.timer.unref?.(),this.delay=Math.min(this.delay*2,Mo))}};import{createHash as Lo}from"crypto";import{readdir as Bo,readFile as Ho,stat as Fo}from"fs/promises";import pr from"path";import{isAllowedArtifactPath as No,normalizeArtifactRelPath as Wo}from"aitable-workflow-core";var fr={async upload(n,e,t){let r=await fetch(n,{method:"PUT",body:e,headers:{...t}});if(!r.ok)throw new Error(`artifact PUT failed: ${r.status} ${r.statusText}`)}};async function mr(n){let e=[];return await gr(n,n,e),e.sort((t,r)=>t.relPath.localeCompare(r.relPath))}a(mr,"scanArtifacts");async function gr(n,e,t){let r;try{r=await Bo(e,{withFileTypes:!0})}catch{return}for(let o of r){if(o.name==="node_modules"||o.name.startsWith("."))continue;let s=pr.join(e,o.name);if(o.isDirectory())await gr(n,s,t);else if(o.isFile()){let i=pr.relative(n,s).replace(/\\/g,"/");if(!No(i))continue;let c=await Fo(s),l=await Ho(s),d=Lo("sha256").update(l).digest("hex");t.push({relPath:Wo(i),absPath:s,size:c.size,sha256:d})}}}a(gr,"walk");import Tr from"path";import{logger as b}from"aitable-workflow-core";import{logger as j,spawnManagedProcess as Uo}from"aitable-workflow-core";var M="engine-supervisor",Qe=2e3,ge=class{static{a(this,"EngineSupervisor")}options;doSpawn;setTimer;clearTimer;child=null;childGen=0;consecutiveFailures=0;lastExitCode=null;lastError=null;restartTimer=null;stopped=!0;constructor(e){this.options=e,this.doSpawn=e.spawnImpl??Uo,this.setTimer=e.setTimeoutImpl??((t,r)=>setTimeout(t,r)),this.clearTimer=e.clearTimeoutImpl??(t=>clearTimeout(t))}get status(){return{running:this.child!=null,pid:this.child?.managed.child.pid??null,generation:this.childGen,startedAt:this.child?new Date(this.child.startedAt).toISOString():null,consecutiveFailures:this.consecutiveFailures,lastExitCode:this.lastExitCode,lastError:this.lastError}}start(){this.stopped=!1,!this.child&&this.spawnChild()}async stop(){this.stopped=!0,this.restartTimer&&(this.clearTimer(this.restartTimer),this.restartTimer=null);let e=this.child;if(!e)return;e.stopping=!0;let t=e.managed.child.pid;if(t==null){this.child=null;return}let r=e.gen;await e.managed.terminateTree({gracePeriodMs:this.options.drainTimeoutMs??2e4}),e.managed.child.exitCode==null&&e.managed.child.signalCode==null&&(j.error(M,"\u5F15\u64CE\u8FDB\u7A0B\u672A\u54CD\u5E94\u5F3A\u5236\u7EC8\u6B62\uFF0C\u653E\u5F03\u7B49\u5F85\uFF08\u53EF\u80FD\u6B8B\u7559\u5B64\u513F\u8FDB\u7A0B\uFF09",{projectId:this.options.projectId,pid:t,generation:r}),this.child?.gen===r&&(this.child=null))}spawnChild(){this.childGen+=1;let e=this.childGen,t=["run","--config",this.options.workspaceDir,"--emit-events","ipc"],r=this.doSpawn({command:process.execPath,args:[this.options.cliPath,...t],cwd:this.options.workspaceDir,stdio:["ignore","pipe","pipe","ipc"],...this.options.env?{env:this.options.env}:{}}),o=r.child,s={managed:r,gen:e,startedAt:Date.now(),stopping:!1};this.child=s,j.info(M,"engine started",{projectId:this.options.projectId,pid:o.pid,generation:e}),o.on("message",i=>{Go(i)&&this.options.onRunEvent?.(i.event)}),o.on("error",i=>{this.lastError=i.message,j.error(M,"engine spawn error",{projectId:this.options.projectId,error:i.message})}),o.on("exit",(i,c)=>this.handleExit(s,i,c)),this.forwardChildOutput(o.stdout,s,"stdout"),this.forwardChildOutput(o.stderr,s,"stderr")}forwardChildOutput(e,t,r){if(!e)return;e.setEncoding("utf8");let o="",s=a(i=>{let c=i.trim();if(!c)return;let l=c.length>Qe?`${c.slice(0,Qe)}\u2026[+${c.length-Qe}]`:c;j.info(M,l,{projectId:this.options.projectId,generation:t.gen,stream:r})},"emit");e.on("data",i=>{if(this.child?.gen!==t.gen)return;let l=(o+i).split(/\r?\n/);o=l.pop()??"";for(let d of l)s(d)}),e.on("end",()=>{o.trim()&&this.child?.gen===t.gen&&s(o),o=""})}handleExit(e,t,r){if(this.child?.gen===e.gen&&(this.child=null),this.lastExitCode=t,j.info(M,"engine exited",{projectId:this.options.projectId,generation:e.gen,code:t,signal:r}),e.stopping||this.stopped)return;this.consecutiveFailures+=1;let o=this.options.maxConsecutiveFailures??5;if(this.consecutiveFailures>=o){j.error(M,"engine crash loop\uFF0C\u505C\u6B62\u91CD\u542F\u5E76\u4E0A\u62A5",{projectId:this.options.projectId,failures:this.consecutiveFailures}),this.stopped=!0,this.options.onCrashLoop?.({projectId:this.options.projectId,failures:this.consecutiveFailures,lastExitCode:t});return}let s=this.options.restartBackoffMs??1e3,i=this.options.restartBackoffMaxMs??6e4,c=Math.min(i,s*2**(this.consecutiveFailures-1));j.warn(M,"engine \u5F02\u5E38\u9000\u51FA\uFF0C\u9000\u907F\u91CD\u542F",{projectId:this.options.projectId,failures:this.consecutiveFailures,delayMs:c}),this.restartTimer=this.setTimer(()=>{this.restartTimer=null,!this.stopped&&!this.child&&this.spawnChild()},c)}markHealthy(){this.consecutiveFailures=0}};function Go(n){return typeof n=="object"&&n!==null&&n.type==="run-event"&&"event"in n}a(Go,"isRunEventMessage");import{appendFile as qo,mkdir as zo,rename as Jo,stat as Vo}from"fs/promises";import Yo from"path";import{logger as he}from"aitable-workflow-core";var ve="event-spool",we=class{static{a(this,"EventSpool")}options;setInterval;clearInterval;now;buffer=[];pending=[];seq=0;timer=null;flushing=!1;constructor(e){this.options=e,this.setInterval=e.setIntervalImpl??((t,r)=>setInterval(t,r)),this.clearInterval=e.clearIntervalImpl??(t=>clearInterval(t)),this.now=e.now??Date.now}get lastSeq(){return this.seq}get pendingCount(){return this.pending.length}start(){this.timer||(this.timer=this.setInterval(()=>{this.flush()},this.options.flushIntervalMs??500))}async stop(){this.timer&&(this.clearInterval(this.timer),this.timer=null),await this.flush()}append(e){this.seq+=1;let t={seq:this.seq,ts:new Date(this.now()).toISOString(),event:e};this.pending.push(t),this.buffer.push(t);let r=this.options.maxPending??5e3;if(this.pending.length>r){let s=this.pending.splice(0,this.pending.length-r);he.warn(ve,"\u5F85\u53D1\u4E8B\u4EF6\u8D85\u4E0A\u9650\uFF0C\u4E22\u5F03\u6700\u65E7\u7684\u6279\u6B21",{projectId:this.options.projectId,dropped:s.length,untilSeq:s[s.length-1]?.seq})}let o=this.options.retain??2e3;this.buffer.length>o&&this.buffer.splice(0,this.buffer.length-o),this.options.persist!==!1&&this.persist(t)}async flush(){if(this.flushing||this.pending.length===0)return;this.flushing=!0;let e=this.pending.slice(0,this.options.maxBatch??200);try{await this.options.send(e);let t=new Set(e.map(r=>r.seq));this.pending=this.pending.filter(r=>!t.has(r.seq))}catch(t){he.warn(ve,"\u4E8B\u4EF6\u6279\u4E0A\u884C\u5931\u8D25\uFF08\u4FDD\u7559\u5F85\u4E0B\u8F6E\u91CD\u8BD5\uFF09",{projectId:this.options.projectId,count:e.length,error:t instanceof Error?t.message:String(t)})}finally{this.flushing=!1}}replayFrom(e){let t=new Set(this.pending.map(o=>o.seq)),r=this.buffer.filter(o=>o.seq>e&&!t.has(o.seq));return r.length===0?0:(this.pending=[...this.pending,...r].sort((o,s)=>o.seq-s.seq),he.info(ve,"\u8865\u4F20\u7F3A\u53E3\u4E8B\u4EF6",{projectId:this.options.projectId,serverLastSeq:e,replay:r.length}),r.length)}async persist(e){let t=Yo.join(this.options.spoolDir,"run-events.jsonl");try{await zo(this.options.spoolDir,{recursive:!0}),await Vo(t).then(o=>o.size).catch(()=>0)>(this.options.rotateBytes??10*1024*1024)&&await Jo(t,`${t}.1`).catch(()=>{}),await qo(t,`${JSON.stringify(e)}
|
|
603
|
+
`,"utf8")}catch(r){he.warn(ve,"spool \u843D\u76D8\u5931\u8D25",{projectId:this.options.projectId,error:r instanceof Error?r.message:String(r)})}}};import{readdir as st,rm as ot,stat as be}from"fs/promises";import q from"path";import{logger as V}from"aitable-workflow-core";import{createHash as as}from"crypto";import{mkdir as rt,readFile as cs,rename as ls,rm as ds,writeFile as br}from"fs/promises";import ye from"path";import{decodeWorkspaceBundle as us,logger as ps,resolveInsideRoot as fs}from"aitable-workflow-core";import{chmod as Ko,readFile as Xo,rename as Zo,writeFile as Qo}from"fs/promises";var hr="# \u2500\u2500\u2500 aitable-workflow managed credentials (auto-generated, do not edit) \u2500\u2500\u2500",vr="# \u2500\u2500\u2500 end managed credentials \u2500\u2500\u2500";function es(n,e){let t=n.split(`
|
|
604
|
+
`),r=t.indexOf(hr),o=t.indexOf(vr),s;r!==-1&&o!==-1&&o>r?s=[...t.slice(0,r),...t.slice(o+1)].join(`
|
|
605
|
+
`):s=n,s=s.replace(/^\n+/,"");let i=Object.entries(e).sort(([l],[d])=>l.localeCompare(d));return i.length===0?s:`${[hr,...i.map(([l,d])=>`${l}=${ts(d)}`),vr].join(`
|
|
606
|
+
`)}
|
|
607
|
+
${s?`
|
|
608
|
+
${s}`:""}`}a(es,"mergeEnvContent");function ts(n){return n===""||/[\s#'"`\\]/.test(n)?`"${n.replace(/\\/g,"\\\\").replace(/"/g,'\\"').replace(/\n/g,"\\n")}"`:n}a(ts,"quoteEnvValue");async function wr(n,e){let t=await Xo(n,"utf8").catch(()=>""),r=es(t,e);if(r===t||r===""&&t==="")return!1;let o=`${n}.aitable-sync-tmp`;return await Qo(o,r,{encoding:"utf8",mode:384}),await Ko(o,384).catch(()=>{}),await Zo(o,n),!0}a(wr,"mergeEnvFile");import{access as rs}from"fs/promises";import ns from"path";import{defaultCommandRunner as os,logger as yr}from"aitable-workflow-core";var kr="workspace-sync",ss=20*6e4,et=new Map;async function is(n,e){try{await rs(ns.join(n,"package.json"))}catch(r){if(r.code==="ENOENT")return;throw r}yr.info(kr,"\u5B89\u88C5\u9879\u76EE\u4F9D\u8D56",{projectDir:n,command:"npm install"});let t;try{t=await e("npm",["install","--no-audit","--no-fund"],{cwd:n,timeoutMs:ss,maxOutputBytes:256*1024})}catch(r){throw new Error(`\u9879\u76EE\u4F9D\u8D56\u5B89\u88C5\u5931\u8D25\uFF08${n}\uFF0Cnpm install\uFF09\uFF1A${r instanceof Error?r.message:String(r)}`)}if(t.exitCode!==0)throw new Error(`\u9879\u76EE\u4F9D\u8D56\u5B89\u88C5\u5931\u8D25\uFF08${n}\uFF0Cnpm install\uFF0Cexit ${t.exitCode??"unknown"}\uFF09\uFF1B\u8BF7\u5728\u8BE5\u76EE\u5F55\u624B\u52A8\u6267\u884C\u76F8\u540C\u547D\u4EE4\u67E5\u770B npm \u9519\u8BEF`);yr.info(kr,"\u9879\u76EE\u4F9D\u8D56\u5B89\u88C5\u5B8C\u6210",{projectDir:n,command:"npm install"})}a(is,"install");function Rr(n,e=os){let t=et.get(n);if(t)return t;let r=is(n,e).finally(()=>{et.delete(n)});return et.set(n,r),r}a(Rr,"ensureProjectDependencies");var ms="workspace-sync",ke=".workspace-meta.json";function gs(n){return as("sha256").update(n).digest("hex")}a(gs,"sha256Hex");async function tt(n,e){let r=await(n.fetchImpl??fetch)(`${n.gatewayUrl.replace(/\/+$/,"")}${e}`,{headers:{authorization:`Bearer ${n.machineToken}`}});if(!r.ok){let o=await r.text().catch(()=>"");throw new Error(`runner API ${e} \u5931\u8D25: HTTP ${r.status} ${o.slice(0,200)}`)}return r}a(tt,"apiGet");async function hs(n){try{let e=await cs(ye.join(n,ke),"utf8"),t=JSON.parse(e);return t&&typeof t.projectId=="string"?t:null}catch{return null}}a(hs,"readWorkspaceMeta");function nt(n,e){return fs(n,e,{allowRoot:!1})}a(nt,"resolveTracked");async function vs(n,e){let t=nt(n,e.path);await rt(ye.dirname(t),{recursive:!0});let r=`${t}.aitable-sync-tmp`;await br(r,e.content,"utf8"),await ls(r,t)}a(vs,"writeTracked");async function Re(n,e,t){let r=await hs(t);if(r&&r.projectId!==e)throw new Error(`\u5DE5\u4F5C\u533A\u76EE\u5F55\u5F52\u5C5E\u4E0D\u7B26: \u76EE\u5F55\u8BB0\u5F55 projectId=${r.projectId}\uFF0C\u8BF7\u6C42\u540C\u6B65 ${e}\uFF08${t}\uFF09`);let s=await(await tt(n,`/api/runner/workspace/${e}`)).json(),i=0,c=0,l="up-to-date",d=r?.trackedManifest??{};if(!r||r.revision!==s.revision){l="synced";let h=await tt(n,`/api/runner/workspace/${e}/bundle`),v=us(Buffer.from(await h.arrayBuffer()));if(v.projectId!==e)throw new Error(`\u5FEB\u7167\u5305\u5F52\u5C5E\u4E0D\u7B26: \u5305\u5185 projectId=${v.projectId}\uFF0C\u671F\u671B ${e}`);v.revision!==s.revision&&(s.revision=v.revision),await rt(t,{recursive:!0});let g={};for(let x of v.files)g[x.path]=gs(x.content);for(let x of v.files)nt(t,x.path);let E=r?.trackedManifest??{};for(let x of v.files)E[x.path]!==g[x.path]&&(await vs(t,x),i+=1);for(let x of Object.keys(E))if(g[x]===void 0){let bt;try{bt=nt(t,x)}catch(Ne){ps.warn(ms,"\u8DF3\u8FC7\u8D8A\u754C\u7684\u65E7 manifest \u6761\u76EE",{projectId:e,path:x,error:Ne instanceof Error?Ne.message:String(Ne)});continue}await ds(bt,{force:!0}).catch(()=>{}),c+=1}d=g}let f=await(await tt(n,`/api/runner/workspace/${e}/credentials`)).json();await rt(t,{recursive:!0});let u=await wr(ye.join(t,".env"),f.credentials??{}),m={projectId:e,revision:s.revision,syncedAt:new Date().toISOString(),trackedManifest:d};return await br(ye.join(t,ke),`${JSON.stringify(m,null,2)}
|
|
609
|
+
`,"utf8"),await Rr(t,n.commandRunner),{projectId:e,revision:s.revision,action:l,written:i,deleted:c,envUpdated:u}}a(Re,"syncWorkspace");var Y="runner-gc";async function Ar(n){let e=0,t;try{t=await st(n,{withFileTypes:!0})}catch{return 0}for(let r of t){let o=q.join(n,r.name);if(!r.isSymbolicLink()){if(r.isDirectory()){e+=await Ar(o);continue}e+=await be(o).then(s=>s.size).catch(()=>0)}}return e}a(Ar,"dirSize");async function ws(n){let e=q.join(n,"projects"),t;try{t=await st(e,{withFileTypes:!0})}catch{return[]}let r=[];for(let o of t){if(!o.isDirectory())continue;let s=q.join(e,o.name),i=await be(q.join(s,ke)).then(l=>l.mtimeMs).catch(()=>null),c=await be(s).then(l=>l.mtimeMs).catch(()=>0);r.push({projectId:o.name,dir:s,lastTouchedMs:i??c,sizeBytes:await Ar(s)})}return r}a(ws,"scanProjects");async function Cr(n,e){let t=q.join(n,"traces"),r;try{r=await st(t,{withFileTypes:!0})}catch{return 0}let o=[];for(let c of r){if(!c.isFile())continue;let l=q.join(t,c.name),d=await be(l).catch(()=>null);d&&o.push({full:l,size:d.size,mtimeMs:d.mtimeMs})}let s=o.reduce((c,l)=>c+l.size,0);if(s<=e)return 0;o.sort((c,l)=>c.mtimeMs-l.mtimeMs);let i=0;for(let c of o){if(s<=e)break;await ot(c.full,{force:!0}).catch(()=>{}),s-=c.size,i+=c.size}return i}a(Cr,"pruneTraces");async function xr(n){let e=(n.now??Date.now)(),t=(n.ttlDays??14)*24*60*60*1e3,r=n.tracesMaxBytes??500*1024*1024,o=n.maxDiskBytes??20*1024*1024*1024,s=new Set(n.activeProjectIds),i=await ws(n.workspaceRoot),c=[],l=0;for(let u of i){if(s.has(u.projectId)){l+=await Cr(u.dir,r);continue}if(e-u.lastTouchedMs>=t){await ot(u.dir,{recursive:!0,force:!0}).catch(m=>{V.warn(Y,"\u9879\u76EE\u76EE\u5F55\u56DE\u6536\u5931\u8D25",{projectId:u.projectId,error:m instanceof Error?m.message:String(m)})}),c.push(u.projectId),V.info(Y,"\u56DE\u6536\u8FC7\u671F\u9879\u76EE\u76EE\u5F55",{projectId:u.projectId,idleDays:Math.floor((e-u.lastTouchedMs)/864e5)});continue}l+=await Cr(u.dir,r)}let d=i.filter(u=>!c.includes(u.projectId)),p=d.reduce((u,m)=>u+m.sizeBytes,0)-l,f=!1;if(p>o){f=!0,V.warn(Y,"\u5DE5\u4F5C\u533A\u8D85\u78C1\u76D8\u6C34\u4F4D\uFF0C\u5F00\u59CB\u56DE\u6536\u6700\u4E45\u672A\u8BA4\u9886\u9879\u76EE",{totalBytes:p,maxDiskBytes:o});let u=d.filter(m=>!s.has(m.projectId)).sort((m,h)=>m.lastTouchedMs-h.lastTouchedMs);for(let m of u){if(p<=o)break;await ot(m.dir,{recursive:!0,force:!0}).catch(()=>{}),c.push(m.projectId),p-=m.sizeBytes,V.warn(Y,"\u6C34\u4F4D\u56DE\u6536\u9879\u76EE\u76EE\u5F55",{projectId:m.projectId,freedBytes:m.sizeBytes})}p>o&&V.error(Y,"\u56DE\u6536\u540E\u4ECD\u8D85\u78C1\u76D8\u6C34\u4F4D\uFF08\u6D3B\u8DC3\u9879\u76EE\u5360\u7528\uFF09\uFF0C\u9700\u4EBA\u5DE5\u4ECB\u5165",{totalBytes:p,maxDiskBytes:o})}return{removedProjects:c,tracesFreedBytes:l,diskPressure:f,totalBytes:Math.max(0,p)}}a(xr,"runGc");var C="runner-loop";function ys(n){return!(typeof n=="object"&&n!==null&&n.type==="run.agent_event")}a(ys,"shouldUplinkRunEvent");var Ce=class{static{a(this,"RunnerLoop")}options;maxWorkflows;setTimer;clearTimer;doSync;holdings=new Map;pollTimer=null;gcTimer=null;running=!1;claiming=!1;constructor(e){this.options=e,this.maxWorkflows=Math.max(1,Math.floor(e.maxWorkflows??3)),this.setTimer=e.setTimeoutImpl??((t,r)=>setTimeout(t,r)),this.clearTimer=e.clearTimeoutImpl??(t=>clearTimeout(t)),this.doSync=e.syncImpl??Re}get held(){return[...this.holdings.values()].map(e=>({projectId:e.projectId,generation:e.generation,revision:e.revision,engine:e.engine.status}))}get freeSlots(){return Math.max(0,this.maxWorkflows-this.holdings.size)}start(){this.running||(this.running=!0,b.info(C,"runner loop \u542F\u52A8",{maxWorkflows:this.maxWorkflows,workspaceRoot:this.options.workspaceRoot}),this.claimOnce(),this.scheduleGc(0))}async stop(){this.running=!1,this.pollTimer&&(this.clearTimer(this.pollTimer),this.pollTimer=null),this.gcTimer&&(this.clearTimer(this.gcTimer),this.gcTimer=null),await Promise.all([...this.holdings.keys()].map(e=>this.releaseHolding(e,"daemon_shutdown")))}scheduleGc(e){let t=this.options.gcIntervalMs??864e5;!this.running||t<=0||(this.gcTimer&&this.clearTimer(this.gcTimer),this.gcTimer=this.setTimer(()=>{this.gcTimer=null,this.gcOnce().finally(()=>this.scheduleGc(t))},e))}async gcOnce(){try{let e=await(this.options.gcImpl??xr)({workspaceRoot:this.options.workspaceRoot,activeProjectIds:[...this.holdings.keys()],...this.options.gcOptions??{}});(e.removedProjects.length>0||e.tracesFreedBytes>0)&&b.info(C,"\u672C\u673A\u56DE\u6536\u5B8C\u6210",{removed:e.removedProjects.length,tracesFreedBytes:e.tracesFreedBytes,totalBytes:e.totalBytes})}catch(e){b.warn(C,"\u672C\u673A\u56DE\u6536\u5931\u8D25",{error:D(e)})}}onWakeup(){this.running&&this.claimOnce()}async claimOnce(){if(!this.running||this.claiming)return;this.claiming=!0;let e=this.options.defaultPollMs??1e4;try{let t=this.freeSlots;if(t>0){let r=await this.post("/api/runner/workflows/claim",{capacity:t});typeof r.nextPollAfterMs=="number"&&r.nextPollAfterMs>0&&(e=r.nextPollAfterMs);for(let o of r.grants??[])await this.acceptGrant(o,r.heartbeatIntervalSeconds)}}catch(t){b.warn(C,"claim \u5931\u8D25\uFF08\u9000\u907F\u540E\u91CD\u8BD5\uFF09",{error:D(t)}),e=Math.max(e,5e3)}finally{this.claiming=!1,this.scheduleNextPoll(e)}}scheduleNextPoll(e){this.running&&(this.pollTimer&&this.clearTimer(this.pollTimer),this.pollTimer=this.setTimer(()=>{this.pollTimer=null,this.claimOnce()},e))}async acceptGrant(e,t){if(this.holdings.has(e.projectId))return;let r=Tr.join(this.options.workspaceRoot,"projects",e.projectId);b.info(C,"\u8BA4\u9886\u9879\u76EE",{projectId:e.projectId,generation:e.generation,workspaceDir:r});let o;try{o=await this.doSync(this.clientConfig(),e.projectId,r)}catch(l){b.error(C,"\u5DE5\u4F5C\u533A\u540C\u6B65\u5931\u8D25\uFF0C\u4EA4\u8FD8\u79DF\u7EA6",{projectId:e.projectId,error:D(l)}),await this.postSafe(`/api/runner/workflows/${e.projectId}/release`,{generation:e.generation,reason:"workspace_sync_failed"});return}let s=(this.options.createSupervisor??ks)({projectId:e.projectId,workspaceDir:r,cliPath:this.options.cliPath,onRunEvent:a(l=>this.handleRunEvent(e.projectId,l),"onRunEvent"),onCrashLoop:a(()=>{this.releaseHolding(e.projectId,"engine_crash_loop")},"onCrashLoop")}),i=this.options.sendRunEvents?new we({projectId:e.projectId,spoolDir:r,send:a(l=>this.options.sendRunEvents(e.projectId,l),"send")}):null;i?.start();let c={projectId:e.projectId,generation:e.generation,revision:o.revision,engine:s,spool:i,heartbeatTimer:null,busy:!1};this.holdings.set(e.projectId,c),s.start(),this.scheduleHeartbeat(c,(t??15)*1e3)}handleRunEvent(e,t){ys(t)&&this.holdings.get(e)?.spool?.append(t),this.options.onRunEvent?.(e,t)}scheduleHeartbeat(e,t){this.running&&(e.heartbeatTimer&&this.clearTimer(e.heartbeatTimer),e.heartbeatTimer=this.setTimer(()=>{e.heartbeatTimer=null,this.heartbeatOnce(e)},t))}async heartbeatOnce(e){if(!this.running||e.busy||!this.holdings.has(e.projectId))return;let t=this.options.defaultHeartbeatMs??15e3;try{let r=await this.post(`/api/runner/workflows/${e.projectId}/heartbeat`,{generation:e.generation,workspaceRevision:e.revision,engineStatus:e.engine.status,...e.spool?{lastEventSeq:e.spool.lastSeq}:{}}),o=typeof r.nextIntervalSeconds=="number"&&r.nextIntervalSeconds>0?r.nextIntervalSeconds*1e3:t;if(e.spool&&typeof r.lastEventSeq=="number"&&e.spool.replayFrom(r.lastEventSeq),r.action==="stop"){b.info(C,"\u5FC3\u8DF3\u4E0B\u53D1 stop\uFF0C\u505C\u6B62\u5F15\u64CE",{projectId:e.projectId}),await this.releaseHolding(e.projectId,"heartbeat_stop");return}if(r.action==="resync"){await this.resyncHolding(e)&&this.scheduleHeartbeat(e,o);return}e.engine.markHealthy(),this.scheduleHeartbeat(e,o)}catch(r){b.warn(C,"\u5FC3\u8DF3\u5931\u8D25\uFF08\u4FDD\u6301\u5F15\u64CE\u8FD0\u884C\uFF0C\u7B49\u5F85\u6062\u590D\u6216\u79DF\u7EA6\u8FC7\u671F\uFF09",{projectId:e.projectId,error:D(r)}),this.scheduleHeartbeat(e,Math.min(t,5e3))}}async resyncHolding(e){if(e.busy)return!0;e.busy=!0;let t=Tr.join(this.options.workspaceRoot,"projects",e.projectId);try{b.info(C,"\u5DE5\u4F5C\u533A\u9700\u91CD\u540C\u6B65\uFF0C\u91CD\u542F\u5F15\u64CE",{projectId:e.projectId}),await e.engine.stop();let r=await this.doSync(this.clientConfig(),e.projectId,t);e.revision=r.revision,e.engine.start()}catch(r){return b.error(C,"\u91CD\u540C\u6B65\u5931\u8D25\uFF0C\u4EA4\u8FD8\u79DF\u7EA6",{projectId:e.projectId,error:D(r)}),e.busy=!1,await this.releaseHolding(e.projectId,"resync_failed"),!1}return e.busy=!1,!0}async releaseHolding(e,t){let r=this.holdings.get(e);r&&(this.holdings.delete(e),r.heartbeatTimer&&(this.clearTimer(r.heartbeatTimer),r.heartbeatTimer=null),await r.engine.stop().catch(o=>{b.warn(C,"\u505C\u6B62\u5F15\u64CE\u5F02\u5E38",{projectId:e,error:D(o)})}),await r.spool?.stop().catch(()=>{}),await this.postSafe(`/api/runner/workflows/${e}/release`,{generation:r.generation,reason:t}),b.info(C,"\u5DF2\u8BA9\u51FA\u79DF\u7EA6",{projectId:e,reason:t}),this.running&&this.scheduleNextPoll(this.options.defaultPollMs??1e4))}clientConfig(){return{gatewayUrl:this.options.gatewayUrl,machineToken:this.options.machineToken,...this.options.fetchImpl?{fetchImpl:this.options.fetchImpl}:{}}}async post(e,t){let o=await(this.options.fetchImpl??fetch)(`${this.options.gatewayUrl.replace(/\/+$/,"")}${e}`,{method:"POST",headers:{authorization:`Bearer ${this.options.machineToken}`,"content-type":"application/json"},body:JSON.stringify(t??{})});if(!o.ok){let s=await o.text().catch(()=>"");throw new Error(`runner API ${e} \u5931\u8D25: HTTP ${o.status} ${s.slice(0,200)}`)}return await o.json()}async postSafe(e,t){try{await this.post(e,t)}catch(r){b.warn(C,"\u6536\u5C3E\u8BF7\u6C42\u5931\u8D25\uFF08\u79DF\u7EA6\u5C06\u7531\u670D\u52A1\u7AEF\u8FC7\u671F\u56DE\u6536\uFF09",{pathname:e,error:D(r)})}}};function ks(n){return new ge({projectId:n.projectId,workspaceDir:n.workspaceDir,cliPath:n.cliPath,...n.onRunEvent?{onRunEvent:n.onRunEvent}:{},...n.onCrashLoop?{onCrashLoop:a(()=>n.onCrashLoop(),"onCrashLoop")}:{}})}a(ks,"defaultSupervisorFactory");function D(n){return n instanceof Error?n.message:String(n)}a(D,"describeError");import{spawn as bs}from"child_process";import{existsSync as Cs}from"fs";import X from"path";import{fileURLToPath as As}from"url";import{appendFileSync as _l,statSync as $l,renameSync as Ol,mkdirSync as jl,existsSync as Ml}from"fs";import Rs from"path";var Bl=10*1024*1024;function K(n){return Rs.join(ne(n),"daemon.log")}a(K,"logFilePath");var Ae=X.dirname(As(import.meta.url));function it(){let n=[X.resolve(Ae,"..","..","bin","aitable-workflow.mjs"),X.resolve(Ae,"..","bin","aitable-workflow.mjs"),X.resolve(Ae,"..","..","dist","cli.js"),X.resolve(Ae,"cli.js")];return n.find(e=>Cs(e))??n[0]}a(it,"resolveDaemonEntry");var xs=it();async function Z(n){await xt(n.agentId);let e=["relay"];n.serverUrl&&e.push("--server-url",n.serverUrl),n.token&&e.push("--token",n.token),n.name&&e.push("--name",n.name),n.workspaceRoot&&e.push("--workspace-root",n.workspaceRoot),n.maxTasks&&e.push("--max-tasks",String(n.maxTasks)),n.traceHttpPort!=null&&String(n.traceHttpPort).trim()!==""&&e.push("--trace-http-port",String(n.traceHttpPort));let t=await import("fs").then(i=>{let c=K(n.agentId);return i.openSync(c,"a")}),r=bs(process.execPath,[xs,...e],{detached:!0,stdio:["ignore",t,t],env:{...process.env}});try{let{closeSync:i}=await import("fs");i(t)}catch{}r.unref();let{writeFile:o}=await import("fs/promises"),{pidFilePath:s}=await import("./pid-file-KT5KHCKU.js");return r.pid&&await o(s(n.agentId),String(r.pid),"utf8"),{pid:r.pid??0}}a(Z,"startDaemon");async function xe(n,e=5e3){let t=await We(n);if(t===null||!J(t))return await oe(n),!1;try{process.kill(t,"SIGTERM")}catch{return await oe(n),!1}let r=Date.now()+e;for(;Date.now()<r&&J(t);)await new Promise(o=>setTimeout(o,200));if(J(t))try{process.kill(t,"SIGKILL")}catch{}return await oe(n),!0}a(xe,"stopDaemon");async function Q(n){let e=await We(n),t=e!==null&&J(e),r=null;if(t&&e!==null)try{let{readFile:o}=await import("fs/promises"),s=await o(`/proc/${e}/stat`,"utf8"),i=parseInt(s.split(" ")[21]??"0",10),c=await o("/proc/uptime","utf8"),p=parseFloat(c.split(" ")[0]??"0")-i/100;r=Math.round(p*1e3)}catch{}return{agentId:n,running:t,pid:t?e:null,uptimeMs:r,logFile:K(n)}}a(Q,"getDaemonStatus");import at from"os";import Te from"path";import{mkdirSync as Ts}from"fs";import{assertPortableId as Es,getActiveCredential as Ss}from"aitable-workflow-core";var ct=8790,Is=new Set(["0","off","none","false"]);function Ee(n,e){let t,r=n?.trim();if(r)t=Te.isAbsolute(r)?Te.resolve(r):Te.resolve(at.homedir(),r);else{let o=e?.trim()?e.trim():"default";t=Te.join(at.homedir(),".aitable-workflow","workspaces",Es(o,{label:"agentId"}))}return Ts(t,{recursive:!0}),t}a(Ee,"resolveWorkspaceRoot");function Er(n,e=process.env){let t=n.serverUrl??e.AITABLE_RELAY_SERVER_URL,r=n.token??e.AITABLE_RELAY_TOKEN,o=n.workspaceRoot??e.AITABLE_RELAY_WORKSPACE_ROOT,s=n.name??e.AITABLE_RELAY_NAME,i=n.maxTasks??e.AITABLE_RELAY_MAX_TASKS,c=n.maxWorkflows??e.AITABLE_RELAY_MAX_WORKFLOWS,l=n.traceHttpPort??e.AITABLE_RELAY_TRACE_HTTP_PORT,d=n.traceHttpHost??e.AITABLE_RELAY_TRACE_HTTP_HOST,p=n.traceBufferSize??e.AITABLE_RELAY_TRACE_BUFFER_SIZE,f=n.traceEventsPerRun??e.AITABLE_RELAY_TRACE_EVENTS_PER_RUN,u=n.traceChat??e.AITABLE_RELAY_TRACE_CHAT,m=[];if(t||m.push("--server-url (\u6216 AITABLE_RELAY_SERVER_URL)"),r||m.push("--token (\u6216 AITABLE_RELAY_TOKEN)"),m.length>0)throw new Error(`relay \u7F3A\u5C11\u5FC5\u8981\u53C2\u6570: ${m.join(", ")}
|
|
610
|
+
\u{1F4A1} \u63D0\u793A: \u4F7F\u7528 \`aitable-workflow connect\` \u6CE8\u518C\u540E\u53EF\u7701\u7565\u8FD9\u4E9B\u53C2\u6570`);let h=s??at.hostname()??"default",v={serverUrl:t,workspaceRoot:Ee(o,h)};if(v.token=r,s&&(v.name=s),i!=null&&i!==""){let g=Math.floor(Number(i));Number.isFinite(g)&&g>=1&&(v.maxTasks=g)}if(c!=null&&c!==""){let g=Math.floor(Number(c));Number.isFinite(g)&&g>=0&&(v.maxWorkflows=g)}if(l==null||l==="")v.traceHttpPort=ct;else{let g=String(l).trim().toLowerCase();if(!Is.has(g)){let E=Math.floor(Number(g));v.traceHttpPort=Number.isFinite(E)&&E>0?E:ct}}if(d?.trim()&&(v.traceHttpHost=d.trim()),p!=null&&p!==""){let g=Math.floor(Number(p));Number.isFinite(g)&&g>=1&&(v.traceRunBufferSize=g)}if(f!=null&&f!==""){let g=Math.floor(Number(f));Number.isFinite(g)&&g>=1&&(v.traceEventBufferSize=g)}return Ps(u)&&(v.traceChat=!0),v}a(Er,"resolveRelayCliConfig");function Ps(n){return typeof n=="boolean"?n:typeof n!="string"?!1:["1","true","yes","on"].includes(n.trim().toLowerCase())}a(Ps,"isTruthyFlag");async function L(n,e=process.env){let t=null;try{t=await Ss()}catch{t=null}let r={serverUrl:n.serverUrl??e.AITABLE_RELAY_SERVER_URL??t?.serverUrl,token:n.token??e.AITABLE_RELAY_TOKEN??t?.token,name:n.name??e.AITABLE_RELAY_NAME??t?.name,workspaceRoot:n.workspaceRoot??e.AITABLE_RELAY_WORKSPACE_ROOT??t?.workspaceRoot,maxTasks:n.maxTasks??e.AITABLE_RELAY_MAX_TASKS,maxWorkflows:n.maxWorkflows??e.AITABLE_RELAY_MAX_WORKFLOWS,traceHttpPort:n.traceHttpPort??e.AITABLE_RELAY_TRACE_HTTP_PORT,traceHttpHost:n.traceHttpHost??e.AITABLE_RELAY_TRACE_HTTP_HOST,traceBufferSize:n.traceBufferSize??e.AITABLE_RELAY_TRACE_BUFFER_SIZE,traceEventsPerRun:n.traceEventsPerRun??e.AITABLE_RELAY_TRACE_EVENTS_PER_RUN,traceChat:n.traceChat??e.AITABLE_RELAY_TRACE_CHAT};return Er(r,e)}a(L,"resolveDaemonConfig");function Ir(n){return n.replace(/\/+$/,"").replace(/^ws/,"http")}a(Ir,"toHttpBase");var T="relay:daemon",Se="relay:trace",Hs="127.0.0.1",Pr=13;var Fs="dws";function Ns(n){return Ls(n,["--version"],Bs({timeoutMs:5e3})).ok}a(Ns,"detectDwsAvailable");var dt=class{static{a(this,"RelayDaemon")}config;allowedDwsCommands;conn;runAgent;gitRunner;codeReviewRunner;createDwsClient;detectAgents;detectDws;hostname;osString;onPermanentReject;artifactUploader;grantTimeoutMs;pendingGrants=new Map;maxTasks;inflight=0;taskQueue=[];runnerLoop;doSyncWorkspace;traceStore;traceHttpServer;traceBoundPort=null;chatManager;askReplyBridge;constructor(e,t={}){this.config={...e,dwsBin:e.dwsBin??Fs},this.allowedDwsCommands=e.allowedDwsCommands??Ye,this.runAgent=t.runAgent??Ms,this.gitRunner=t.gitRunner??Sr,this.codeReviewRunner=t.codeReviewRunner??Sr,this.createDwsClient=t.createDwsClient??((o,s)=>new Ds({bin:o,timeoutMs:s})),this.detectAgents=t.detectAgents??(()=>js()),this.detectDws=t.detectDws??(o=>Ns(o)),this.hostname=t.hostname??(()=>lt.hostname()),this.osString=t.osString??(()=>`${lt.platform()} ${lt.arch()}`),this.onPermanentReject=t.onPermanentReject,this.artifactUploader=t.artifactUploader??fr,this.grantTimeoutMs=t.grantTimeoutMs??3e4,this.doSyncWorkspace=t.syncWorkspaceImpl??Re,this.maxTasks=Math.max(1,Math.floor(e.maxTasks??1)),this.traceStore=t.traceStore??new U({maxRuns:e.traceRunBufferSize,maxEventsPerRun:e.traceEventBufferSize}),this.chatManager=e.traceChat&&e.traceHttpPort!=null?new N({workspaceRoot:this.config.workspaceRoot,store:this.traceStore,runAgent:this.runAgent,detectAgents:this.detectAgents,enqueue:a(o=>this.enqueueTask(o),"enqueue"),defaultTimeoutMs:e.agentTimeoutMs}):null,this.askReplyBridge=e.traceChat&&e.traceHttpPort!=null?(t.createAskReplyService??(o=>new W(o)))({workspaceRoot:this.config.workspaceRoot}):null,this.traceHttpServer=null;let r=t.createConnection??(o=>new me(o));this.conn=r({serverUrl:this.config.serverUrl,token:this.config.token??"",onMessage:a(o=>this.handleMessage(o),"onMessage"),onOpen:a(()=>this.handleOpen(),"onOpen"),onPermanentReject:a(o=>this.handlePermanentReject(o),"onPermanentReject")}),this.runnerLoop=this.buildRunnerLoop(t)}buildRunnerLoop(e){let t=Math.max(0,Math.floor(this.config.maxWorkflows??3));if(t===0)return null;let r=this.config.token;if(!r)return R.warn(T,"\u65E0\u6267\u884C\u5F15\u64CE token\uFF0C\u8DF3\u8FC7 RunnerLoop\uFF08run \u9636\u6BB5\u4E0D\u8BA4\u9886\u9879\u76EE\uFF09"),null;let o={gatewayUrl:Ir(this.config.serverUrl),machineToken:r,workspaceRoot:this.config.workspaceRoot,cliPath:it(),maxWorkflows:t,sendRunEvents:a((s,i)=>this.sendRunEvents(s,i),"sendRunEvents"),onRunEvent:a((s,i)=>this.recordRunnerTrace(s,i),"onRunEvent")};return(e.createRunnerLoop??(s=>new Ce(s)))(o)}recordRunnerTrace(e,t){fe(this.traceStore,e,t,this.config.workspaceRoot??void 0)}sendRunEvents(e,t){t.length!==0&&this.conn.send({type:"run:events",projectId:e,entries:t})}start(){R.info(T,"starting",{serverUrl:this.config.serverUrl,workspaceRoot:this.config.workspaceRoot}),this.config.name||R.warn(T,"\u672A\u6307\u5B9A --name\uFF0C\u5C06\u4F7F\u7528\u4E3B\u673A\u540D\u4F5C\u4E3A\u672C\u673A daemon \u522B\u540D",{hostname:this.hostname()}),this.startTraceHttpServer(),this.conn.connect(),this.runnerLoop?.start()}stop(){R.info(T,"stopping"),this.conn.close();let e=[];return this.runnerLoop&&e.push(this.runnerLoop.stop().catch(t=>{R.warn(T,"runner loop \u505C\u6B62\u5F02\u5E38",{error:t instanceof Error?t.message:String(t)})})),this.traceHttpServer&&e.push(this.traceHttpServer.stop().catch(t=>{R.warn(Se,"trace http \u505C\u6B62\u5F02\u5E38",{error:t instanceof Error?t.message:String(t)})})),Promise.all(e).then(()=>{})}async startTraceHttpServer(){let e=this.config.traceHttpPort;if(e==null)return;let t=this.config.traceHttpHost??Hs;for(let r=0;r<Pr;r++){let o=e+r,s=new G(this.traceStore,{host:t,port:o,...this.chatManager?{chat:this.chatManager}:{},...this.askReplyBridge?{askReply:this.askReplyBridge}:{}});try{await s.start()}catch(i){let c=i instanceof Error?i.message:String(i);R.warn(Se,`trace http \u7AEF\u53E3 ${o} \u8D77\u5931\u8D25\uFF0C\u5C1D\u8BD5\u4E0B\u4E00\u4E2A`,{error:c});continue}this.traceHttpServer=s,this.traceBoundPort=s.address()?.port??o,R.info(Se,"trace http listening",{url:`http://${t}:${this.traceBoundPort}`,...r>0?{basePort:e,avoidedAfter:r}:{}});return}R.warn(Se,`trace http \u7AEF\u53E3 ${e}~${e+Pr-1} \u5747\u88AB\u5360\uFF0C\u672C\u5730\u4E8B\u4EF6\u4ECD\u5B58\u5185\u5B58\u4F46\u65E0\u6CD5 HTTP \u67E5\u770B`)}buildReady(){let t={type:"ready",runtimes:Array.from(new Set(this.detectAgents().map(r=>r.type))),hasDws:this.detectDws(this.config.dwsBin),hostname:this.hostname(),os:this.osString()};return this.maxTasks>1&&(t.maxTasks=this.maxTasks),this.config.traceHttpPort!=null&&(t.tracePort=this.traceBoundPort??this.config.traceHttpPort),t}handleOpen(){let e=this.buildReady();R.info(T,"connected; sending ready",{runtimes:e.runtimes,hasDws:e.hasDws}),this.conn.send(e)}handlePermanentReject(e){R.error(T,"permanently rejected by gateway",{...e}),this.onPermanentReject?.(e)}handleMessage(e){switch(e.type){case"run:agent":this.enqueueTask(()=>this.handleRunAgent(e));break;case"run:recipe":this.enqueueTask(()=>this.handleRunRecipe(e));break;case"run:dws":this.enqueueTask(()=>this.handleRunDws(e));break;case"upload:grant":this.resolveGrant(e);break;case"wf:available":this.runnerLoop?.onWakeup();break;case"ready:ack":break;default:break}}enqueueTask(e){let t=a(()=>{this.inflight+=1,e().finally(()=>{this.inflight-=1;let r=this.taskQueue.shift();r&&r()})},"exec");this.inflight<this.maxTasks?t():this.taskQueue.push(t)}async handleRunAgent(e){await qt(e,{trace:this.traceStore,resolveWorkDir:a((t,r)=>this.resolveWorkDir(t,r),"resolveWorkDir"),rewritePrompt:a((t,r,o)=>this.rewritePromptWorkDir(t,r,o),"rewritePrompt"),ensureDirectory:a(t=>$s(t,{recursive:!0}).then(()=>{}),"ensureDirectory"),runAgent:this.runAgent,collectArtifacts:a((t,r,o)=>this.collectAndUploadArtifacts(t,r,o),"collectArtifacts"),agentTimeoutMs:this.config.agentTimeoutMs,send:a(t=>this.conn.send(t),"send")})}async collectAndUploadArtifacts(e,t,r){let o=await mr(r);if(o.length===0)return;this.conn.send({type:"upload:request",requestId:e,projectId:t,files:o.map(c=>({path:c.relPath,size:c.size,sha256:c.sha256}))});let s=await this.awaitGrant(e);if(!s)throw new Error("upload:grant \u7B49\u5F85\u8D85\u65F6");if(s.grants.length===0){R.warn(T,"upload:grant \u65E0\u6388\u6743\u9879\uFF08gateway \u672A\u914D\u7F6E store \u6216\u5168\u88AB\u62D2\uFF09",{requestId:e,rejected:(s.rejected??[]).length});return}let i=[];for(let c of s.grants){let l=o.find(p=>p.relPath===c.path);if(!l)continue;let d=await Os(l.absPath);await this.artifactUploader.upload(c.url,d,c.headers),i.push({path:c.path,key:c.key,sha256:l.sha256,size:l.size})}return{store:"oss",files:i}}awaitGrant(e){return new Promise(t=>{let r=setTimeout(()=>{this.pendingGrants.delete(e),t(void 0)},this.grantTimeoutMs);r.unref?.(),this.pendingGrants.set(e,o=>{clearTimeout(r),t(o)})})}resolveGrant(e){let t=this.pendingGrants.get(e.requestId);t&&(this.pendingGrants.delete(e.requestId),t(e))}recipeProjectDir(e){return Bt(this.config.workspaceRoot,e)}async ensureRecipeWorkspace(e,t){let r=this.config.token;if(!r){R.warn(T,"\u65E0\u6267\u884C\u5F15\u64CE token\uFF0Crun:recipe \u4F7F\u7528\u672C\u673A\u5DF2\u6709\u5DE5\u4F5C\u533A\uFF08\u624B\u5DE5\u540C\u6B65\u6A21\u5F0F\uFF09",{projectId:e});return}let o={gatewayUrl:Ir(this.config.serverUrl),machineToken:r},s=await this.doSyncWorkspace(o,e,t);return R.info(T,"run:recipe \u5DE5\u4F5C\u533A\u540C\u6B65\u5B8C\u6210",{projectId:e,action:s.action,written:s.written,deleted:s.deleted}),s}async handleRunRecipe(e){let t=this.recipeProjectDir(e.projectId),r=dr(this.traceStore);await Xt(e,{projectDir:t,ensureWorkspace:a(async()=>{await this.ensureRecipeWorkspace(e.projectId,t)},"ensureWorkspace"),buildToolkit:a((o,s)=>Zt(e,t,o,{createDwsClient:a(i=>this.createDwsClient(this.config.dwsBin,i),"createDwsClient"),runAgent:a((i,c)=>this.runAgent(i,c),"runAgent"),appendTrace:a((i,c)=>r.appendEvent(i,c),"appendTrace"),gitRunner:this.gitRunner,codeReviewRunner:this.codeReviewRunner},s),"buildToolkit"),send:a(o=>this.conn.send(o),"send"),trace:r})}async handleRunDws(e){await Gt(e,{allowedCommands:this.allowedDwsCommands,createDwsClient:a(t=>this.createDwsClient(this.config.dwsBin,t),"createDwsClient"),send:a(t=>this.conn.send(t),"send")})}resolveWorkDir(e,t){return ie(this.config.workspaceRoot,e,t)}rewritePromptWorkDir(e,t,r){let o=t?.trim();return!o||!_s.isAbsolute(o)||o===r?e:e.split(o).join(r)}};async function Ie(n){let e=await L(n),t=new dt(e,{onPermanentReject:a(()=>{process.exit(1)},"onPermanentReject")}),r=!1,o=a(()=>{r&&(R.warn(T,"\u518D\u6B21\u6536\u5230\u9000\u51FA\u4FE1\u53F7\uFF0C\u5F3A\u5236\u9000\u51FA"),process.exit(1)),r=!0,t.stop().catch(()=>{}).finally(()=>process.exit(0))},"shutdown");return process.on("SIGINT",o),process.on("SIGTERM",o),t.start(),t}a(Ie,"runRelayDaemon");var $e="cli:local-trace-server",Gs=8789,_r=13,qs=3e5;async function Oe(n){let e=Pe.dirname(Pe.resolve(n.configPath)),t=Pe.basename(e),r=Pe.dirname(e),o=n.host??"127.0.0.1",s=n.preferredPort??Gs,i=new U({maxRuns:50,maxEventsPerRun:2e3}),c=Promise.resolve(),l=a(f=>{c=c.then(()=>f()).catch(u=>{_e.error($e,"chat turn \u6267\u884C\u5F02\u5E38",{error:u instanceof Error?u.message:String(u)})})},"enqueue"),d=new N({workspaceRoot:e,store:i,runAgent:Ws,detectAgents:a(()=>Us(),"detectAgents"),enqueue:l,defaultTimeoutMs:qs}),p=new W({workspaceRoot:r});for(let f=0;f<_r;f++){let u=s+f,m=new G(i,{host:o,port:u,chat:d,askReply:p});try{await m.start()}catch(g){let E=g instanceof Error?g.message:String(g);_e.warn($e,`trace server \u7AEF\u53E3 ${u} \u8D77\u5931\u8D25\uFF0C\u5C1D\u8BD5\u4E0B\u4E00\u4E2A`,{error:E});continue}let h=m.address()??{host:o,port:u},v=`http://${h.host}:${h.port}/`;return _e.info($e,`\u672C\u673A\u8FD0\u884C\u89C2\u6D4B\u5DF2\u5C31\u7EEA\uFF1A${v}`),{url:v,port:h.port,record:a(g=>fe(i,t,g),"record"),stop:a(()=>m.stop(),"stop")}}return _e.warn($e,`\u7AEF\u53E3 ${s}~${s+_r-1} \u5747\u88AB\u5360\uFF0C\u8DF3\u8FC7\u672C\u673A\u8FD0\u884C\u89C2\u6D4B\u670D\u52A1`),null}a(Oe,"startLocalTraceServer");function Ys(){let t=[],r=a(()=>{let o=Date.now();for(t.push(o);t.length>0&&o-t[0]>6e4;)t.shift();t.length>=10&&(A.error("cli",`60000ms \u5185\u53D1\u751F ${t.length} \u6B21\u672A\u6355\u83B7\u5F02\u5E38\uFF0C\u7591\u4F3C\u975E\u5076\u53D1\u9519\u8BEF\uFF0C\u4E3B\u52A8\u9000\u51FA`),process.exit(1))},"recordCrashAndMaybeExit");process.on("uncaughtException",o=>{A.error("cli","\u6355\u83B7\u5230\u672A\u5904\u7406\u5F02\u5E38\uFF08\u5DF2\u5B58\u6D3B\uFF0C\u4EA4\u7531\u91CD\u8FDE/\u91CD\u8BD5\u903B\u8F91\u81EA\u6108\uFF09",{error:o instanceof Error?o.message:String(o),stack:o instanceof Error?o.stack:void 0}),r()}),process.on("unhandledRejection",o=>{A.error("cli","\u6355\u83B7\u5230\u672A\u5904\u7406 Promise \u62D2\u7EDD\uFF08\u5DF2\u5B58\u6D3B\uFF09",{error:o instanceof Error?o.message:String(o),stack:o instanceof Error?o.stack:void 0}),r()})}a(Ys,"installLongRunningCrashGuards");function jr(n,e){n.command("start").description("\u542F\u52A8\u7EDF\u4E00\u63A7\u5236\u53F0\uFF1A\u914D\u7F6E\u68C0\u6D4B + \u642D\u5EFA + \u8FD0\u884C\u4E00\u4F53\u5316").option("-c, --config <path>","\u914D\u7F6E\u6587\u4EF6\u8DEF\u5F84",e.defaultConfig).option("-p, --port <number>","\u63A7\u5236\u53F0\u7AEF\u53E3\u9996\u9009\u503C\uFF08\u7F3A\u7701 8788\uFF0C\u4E0D\u53EF\u7528\u65F6\u5411\u4E0A\u907F\u8BA9 13 \u4E2A\u7AEF\u53E3\uFF1B\u591A\u9879\u76EE\u5E76\u884C\u65F6\u5EFA\u8BAE\u663E\u5F0F\u6307\u5B9A\uFF09").option("--no-open","\u542F\u52A8\u540E\u4E0D\u8981\u81EA\u52A8\u6253\u5F00\u6D4F\u89C8\u5668").option("--skip-config-if-valid","\u914D\u7F6E\u5DF2\u5B8C\u6574\u65F6\u76F4\u63A5\u542F\u52A8\u8FD0\u884C").action(async t=>{let r;if(t.port!==void 0){let o=Number.parseInt(t.port,10);(!Number.isFinite(o)||o<=0||o>65535)&&(A.error("cli",`--port \u53D6\u503C\u975E\u6CD5: "${t.port}"\uFF08\u9700\u4E3A 1-65535 \u6574\u6570\uFF09`),process.exit(1)),r=o}try{await Js($r.dirname($r.resolve(t.config)),e.version),Ys(),await zs();let o=await Vs({configPath:t.config}),s=!o.ok||o.summary.errors>0,i=await Oe({configPath:t.config}),c=a(u=>i?.record(u),"recordLocal"),l,d="setup";if(!s)try{d="runtime",l=await Or(t.config,{onRunEvent:c})}catch(u){A.warn("cli","\u914D\u7F6E\u6821\u9A8C\u901A\u8FC7\u4F46\u88C5\u914D\u5931\u8D25\uFF0C\u56DE\u9000\u5230\u642D\u5EFA\u6A21\u5F0F",{error:u instanceof Error?u.message:String(u)}),d="setup",l=void 0}d==="runtime"&&l?t.skipConfigIfValid?(A.info("cli","\u914D\u7F6E\u5DF2\u5B8C\u6574\uFF0C\u76F4\u63A5\u542F\u52A8\u8FD0\u884C"),l.start().catch(u=>{A.error("cli","\u8FD0\u884C\u542F\u52A8\u5931\u8D25\uFF0C\u53EF\u5728\u63A7\u5236\u53F0\u91CD\u8BD5\u542F\u52A8",{error:u instanceof Error?u.message:String(u)})})):A.info("cli","\u914D\u7F6E\u5DF2\u5B8C\u6574\uFF0C\u8BF7\u5728\u63A7\u5236\u53F0\u70B9\u51FB\u300C\u5F00\u59CB\u8FD0\u884C\u300D\u542F\u52A8\u670D\u52A1"):A.info("cli","\u914D\u7F6E\u4E0D\u5B8C\u6574\uFF0C\u63A7\u5236\u53F0\u5C06\u5F15\u5BFC\u5B8C\u6210\u642D\u5EFA");let p=!1,f=a(async()=>{p&&(A.warn("cli","\u518D\u6B21\u6536\u5230\u9000\u51FA\u4FE1\u53F7\uFF0C\u5F3A\u5236\u9000\u51FA"),process.exit(1)),p=!0,A.info("cli","\u6536\u5230\u9000\u51FA\u4FE1\u53F7\uFF0C\u6B63\u5728\u505C\u6B62\u8FD0\u884C...");try{await l?.stop(),await i?.stop().catch(()=>{})}finally{process.exit(0)}},"shutdown");process.on("SIGINT",f),process.on("SIGTERM",f),await At({configPath:t.config,mode:d,app:l,port:r,open:t.open,traceUrl:i?.url??null,exitOnSetupError:!1,...d==="runtime"&&t.skipConfigIfValid?{initialRunStatus:{status:"running",since:new Date().toISOString(),lastError:null}}:{},...d==="setup"?{assembleApp:a(u=>Or(u,{onRunEvent:c}),"assembleApp"),onAppAssembled:a(u=>{l=u,A.info("cli","\u63A7\u5236\u53F0\u5DF2\u5B8C\u6210 setup\u2192runtime \u664B\u5347\uFF0C\u53EF\u5728\u63A7\u5236\u53F0\u542F\u52A8\u8FD0\u884C")},"onAppAssembled")}:{}})}catch(o){A.error("cli","start \u547D\u4EE4\u5931\u8D25",{error:o instanceof Error?o.message:String(o)}),process.exit(1)}})}a(jr,"registerStartCommand");import{createApp as Ks,ensureTsxRegistered as Xs,checkMigrateHint as Zs,logger as B,reportCliEvent as je,setReportProject as Qs}from"aitable-workflow-core";import Mr from"path";function ei(){let t=[],r=a(async()=>{let o=Date.now();for(t.push(o);t.length>0&&o-t[0]>6e4;)t.shift();t.length>=10&&(B.error("cli",`60000ms \u5185\u53D1\u751F ${t.length} \u6B21\u672A\u6355\u83B7\u5F02\u5E38\uFF0C\u7591\u4F3C\u975E\u5076\u53D1\u9519\u8BEF\uFF0C\u4E3B\u52A8\u9000\u51FA`),await je("run.exit",{reason:"crash-loop",crashes:t.length}),process.exit(1))},"recordCrashAndMaybeExit");process.on("uncaughtException",o=>{B.error("cli","\u6355\u83B7\u5230\u672A\u5904\u7406\u5F02\u5E38\uFF08\u5DF2\u5B58\u6D3B\uFF0C\u4EA4\u7531\u91CD\u8FDE/\u91CD\u8BD5\u903B\u8F91\u81EA\u6108\uFF09",{error:o instanceof Error?o.message:String(o),stack:o instanceof Error?o.stack:void 0}),r()}),process.on("unhandledRejection",o=>{B.error("cli","\u6355\u83B7\u5230\u672A\u5904\u7406 Promise \u62D2\u7EDD\uFF08\u5DF2\u5B58\u6D3B\uFF09",{error:o instanceof Error?o.message:String(o),stack:o instanceof Error?o.stack:void 0}),r()})}a(ei,"installLongRunningCrashGuards");function Dr(n,e){n.command("run").description("\u542F\u52A8\u7F16\u6392\u5F15\u64CE\uFF0C\u5F00\u59CB\u8F6E\u8BE2\u5904\u7406\u5DE5\u5355").option("-c, --config <path>","\u914D\u7F6E\u6587\u4EF6\u8DEF\u5F84",e.defaultConfig).option("--emit-events <channel>","\u8FD0\u884C\u4E8B\u4EF6\u4E0A\u629B\u901A\u9053\uFF1Aipc = \u7ECF process.send \u53D1\u7ED9\u7236\u8FDB\u7A0B\uFF08daemon runner \u7528\uFF09\uFF0C\u7F3A\u7701\u4E0D\u4E0A\u629B").option("-p, --port <number>","\uFF08\u4EC5\u517C\u5BB9 launcher \u900F\u4F20\uFF0Crun \u547D\u4EE4\u4E0D\u4F7F\u7528\u6B64\u53C2\u6570\uFF09").option("--no-open","\u672C\u673A\u72EC\u7ACB\u8FD0\u884C\u65F6\u4E0D\u81EA\u52A8\u6253\u5F00\u8FD0\u884C\u89C2\u6D4B\u9875\uFF08\u9ED8\u8BA4\u81EA\u52A8\u6253\u5F00\uFF09").action(async t=>{Qs(t.config);try{await Zs(Mr.dirname(Mr.resolve(t.config)),e.version),ei(),await Xs();let r=t.emitEvents==="ipc"&&typeof process.send=="function",o=r?null:await Oe({configPath:t.config}),s=await Ks(t.config,r?{onRunEvent:a(l=>{process.send?.({type:"run-event",event:l})},"onRunEvent")}:{onRunEvent:a(l=>o?.record(l),"onRunEvent")});o&&(B.info("cli",`\u672C\u673A\u8FD0\u884C\u89C2\u6D4B\u5DF2\u5C31\u7EEA\uFF1A${o.url}`),t.open!==!1&&re(o.url)),je("run.start",{emitEvents:t.emitEvents??null});let i=!1,c=a(async()=>{i&&(B.warn("cli","\u518D\u6B21\u6536\u5230\u9000\u51FA\u4FE1\u53F7\uFF0C\u5F3A\u5236\u9000\u51FA"),process.exit(1)),i=!0,B.info("cli","\u6536\u5230\u9000\u51FA\u4FE1\u53F7\uFF0C\u6B63\u5728\u7B49\u5F85\u8FDB\u884C\u4E2D\u7684\u4EFB\u52A1\u5B8C\u6210...");try{await s.stop(),await o?.stop().catch(()=>{})}finally{await je("run.exit",{reason:"signal"}),process.exit(0)}},"shutdown");process.on("SIGINT",c),process.on("SIGTERM",c),await s.start()}catch(r){B.error("cli","\u542F\u52A8\u5931\u8D25",{error:r instanceof Error?r.message:String(r)}),await je("run.exit",{reason:"start-failure",error:(r instanceof Error?r.message:String(r)).slice(0,500)}),process.exit(1)}})}a(Dr,"registerRunCommand");import{readFile as ti}from"fs/promises";import Fr from"path";import{createApp as ri,ensureTsxRegistered as ni,logger as ut,resolveConfigPath as oi}from"aitable-workflow-core";function si(n,e){let t=`\u5DE5\u4F5C\u6D41 ${n} / \u4E8B\u4EF6\u6E90 ${e.sourceName}\uFF08handler: ${e.handlerRecipe}\uFF09`;return e.actions===0?`${t}\uFF1A\u5DF2\u89E6\u53D1\u4F46\u6CA1\u6709\u4EA7\u51FA\u52A8\u4F5C\uFF08\u8017\u65F6 ${e.durationMs}ms\uFF09\u3002\u8BF7\u68C0\u67E5\u6570\u636E\u6E90\u662F\u5426\u6709\u53EF\u7528\u884C\u3002`:`${t}\uFF1A\u4EA7\u51FA ${e.actions} \u4E2A\u52A8\u4F5C\uFF08\u843D\u5E93 ${e.applied}\uFF0C\u77AC\u6001 ${e.transient}\uFF09\uFF0C\u8017\u65F6 ${e.durationMs}ms\u3002`}a(si,"formatTriggerOnceResult");function Lr(n){return new Promise(e=>{n.write("",()=>e())})}a(Lr,"flushStream");function Br(){return Promise.all([Lr(process.stdout),Lr(process.stderr)])}a(Br,"flushOutputs");function Hr(n){let e;try{e=JSON.parse(n)}catch(r){throw new Error(`\u81EA\u5B9A\u4E49\u4E8B\u4EF6 JSON \u89E3\u6790\u5931\u8D25: ${r instanceof Error?r.message:String(r)}`)}if(!e||typeof e!="object"||Array.isArray(e))throw new Error("\u81EA\u5B9A\u4E49\u4E8B\u4EF6\u5FC5\u987B\u662F JSON \u5BF9\u8C61");let t=e;if(typeof t.type!="string"||t.type.trim().length===0)throw new Error("\u81EA\u5B9A\u4E49\u4E8B\u4EF6 type \u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32");if(!t.payload||typeof t.payload!="object"||Array.isArray(t.payload))throw new Error("\u81EA\u5B9A\u4E49\u4E8B\u4EF6 payload \u5FC5\u987B\u662F\u5BF9\u8C61");if(t.timestamp!==void 0&&(typeof t.timestamp!="string"||t.timestamp.trim().length===0))throw new Error("\u81EA\u5B9A\u4E49\u4E8B\u4EF6 timestamp \u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32");if(t.itemId!==void 0&&t.itemId!==null&&typeof t.itemId!="string")throw new Error("\u81EA\u5B9A\u4E49\u4E8B\u4EF6 itemId \u5FC5\u987B\u662F\u5B57\u7B26\u4E32\u6216 null");return{type:t.type,payload:t.payload,...typeof t.timestamp=="string"?{timestamp:t.timestamp}:{},...t.itemId!==void 0?{itemId:t.itemId}:{}}}a(Hr,"parseTriggerEventJson");async function ii(){let n=[];for await(let e of process.stdin)n.push(Buffer.isBuffer(e)?e:Buffer.from(String(e)));return Buffer.concat(n).toString("utf8")}a(ii,"readStdin");async function ai(n,e=process.cwd()){if(n.eventJson&&n.eventStdin)throw new Error("--event-json \u4E0E --event-stdin \u53EA\u80FD\u4E8C\u9009\u4E00");if(n.eventJson){let t=Fr.resolve(e,n.eventJson);return Hr(await ti(t,"utf8"))}if(n.eventStdin)return Hr(await ii())}a(ai,"loadTriggerEvent");function Nr(n,e){n.command("trigger-once").description("\u5355\u6B21\u89E6\u53D1\u67D0\u4E2A\u5DE5\u4F5C\u6D41\u7684\u4E8B\u4EF6\u6E90 handler \u8DD1\u4E00\u904D\uFF08\u53EA\u8DD1\u4E8B\u4EF6\u6E90 handler\uFF0C\u4E0D\u542F\u52A8\u5E38\u9A7B\u5F15\u64CE\uFF1B\u6B65\u9AA4\u94FE\u7531\u8FD0\u884C\u4E2D\u7684\u5F15\u64CE\u63A8\u8FDB\uFF09").requiredOption("-w, --workflow <id>","\u5DE5\u4F5C\u6D41 ID\uFF08\u591A\u5DE5\u4F5C\u6D41\u9879\u76EE\u91CC\u7684\u76EE\u5F55\u540D\uFF09").option("-c, --config <path>","\u914D\u7F6E\u6587\u4EF6\u8DEF\u5F84",e.defaultConfig).option("-s, --source <name>","\u53EA\u89E6\u53D1\u6307\u5B9A\u4E8B\u4EF6\u6E90\uFF1B\u7F3A\u7701\u7528\u8BE5\u5DE5\u4F5C\u6D41\u7684\u7B2C\u4E00\u4E2A\u4E8B\u4EF6\u6E90").option("--event-json <path>","\u4ECE JSON \u6587\u4EF6\u8BFB\u53D6\u81EA\u5B9A\u4E49 ExternalEvent\uFF08\u53EA\u89E6\u53D1 handler\uFF0C\u4E0D\u6A21\u62DF\u5B8C\u6574\u6B65\u9AA4\u94FE\uFF09").option("--event-stdin","\u4ECE stdin \u8BFB\u53D6\u81EA\u5B9A\u4E49 ExternalEvent JSON").option("--json","\u4EE5 JSON \u8F93\u51FA\u7ED3\u679C\uFF08\u4F9B\u811A\u672C\u6D88\u8D39\uFF09").action(async t=>{t.json&&ut.setSink((r,o)=>process.stderr.write(`${o}
|
|
611
|
+
`));try{await ni();let r=await oi(t.config),o=await ai(t,Fr.dirname(r)),s=await ri(t.config),i={...t.source?{sourceName:t.source}:{},...o?{event:o}:{}},c=await s.triggerWorkflowOnce(t.workflow,i);t.json?process.stdout.write(`${JSON.stringify({ok:!0,workflowId:t.workflow,...c})}
|
|
612
|
+
`):ut.info("cli",si(t.workflow,c)),await Br(),process.exit(0)}catch(r){let o=r instanceof Error?r.message:String(r);t.json?process.stdout.write(`${JSON.stringify({ok:!1,error:o})}
|
|
613
|
+
`):ut.error("cli","\u89E6\u53D1\u5931\u8D25",{error:o}),await Br(),process.exit(1)}})}a(Nr,"registerTriggerCommand");import{readFile as Wr}from"fs/promises";import De from"path";import Ur from"yaml";import{logger as ci,loadSettings as Gr,loadWorkflowTemplate as li,resolveConfigPath as di,scanWorkflowDirs as ui,buildEnvSource as pi,loadProfileConfig as fi,resetProfileCache as mi,runWorkflowGates as gi}from"aitable-workflow-core";function qr(n,e){n.command("validate").description("\u9A8C\u8BC1\u914D\u7F6E\u6587\u4EF6\u548C\u5DE5\u4F5C\u6D41\u95E8\u7981\uFF08\u7ED3\u6784 / recipe \u7ED1\u5B9A / \u7C7B\u578B / \u914D\u7F6E\u5951\u7EA6 / \u53C2\u6570\u6D41\u8F6C\uFF09").option("-c, --config <path>","\u914D\u7F6E\u6587\u4EF6\u8DEF\u5F84",e.defaultConfig).option("--workflow <id>","\u53EA\u6821\u9A8C\u6307\u5B9A\u5DE5\u4F5C\u6D41\uFF08\u591A\u5DE5\u4F5C\u6D41\u6A21\u5F0F\uFF09").option("--strict","warning \u7EA7\u95EE\u9898\u5347\u7EA7\u4E3A error").option("--no-typecheck","\u8DF3\u8FC7 recipe TS \u7C7B\u578B\u68C0\u67E5\uFF08\u6279\u91CF\u573A\u666F\u63D0\u901F\uFF09").option("--json","\u8F93\u51FA\u673A\u5668\u53EF\u8BFB GateReport JSON").action(async t=>{try{await hi(t.config,t)}catch(r){console.error(`\u2717 \u9A8C\u8BC1\u5931\u8D25: ${r instanceof Error?r.message:String(r)}`),process.exit(1)}})}a(qr,"registerValidateCommand");async function hi(n,e){e.json&&ci.setSink((c,l)=>process.stderr.write(`${l}
|
|
614
|
+
`));let t=await di(n),r=De.dirname(t),o=await wi(t,e.workflow);o.length===0&&(console.error("\u2717 \u672A\u627E\u5230\u4EFB\u4F55\u5DE5\u4F5C\u6D41"),process.exit(1));let s=await ki(r),i=await gi(o,{strict:e.strict===!0,includeTypecheck:e.typecheck!==!1,profile:s});i.configPath=t,e.json?console.log(JSON.stringify(i,null,2)):(await vi(t),bi(i)),process.exit(i.ok?0:1)}a(hi,"runValidateWorkflow");async function vi(n){let e=await Gr(n,{lenientEnv:!0});console.log("\u2713 \u914D\u7F6E\u6587\u4EF6\u9A8C\u8BC1\u901A\u8FC7");let t=await li(e.workflowTemplatePath,{envSource:e.envSource});console.log(`\u2713 \u5DE5\u4F5C\u6D41\u6A21\u677F\u9A8C\u8BC1\u901A\u8FC7: ${t.meta.name} (${t.orderedStepIds.length} \u6B65)`),console.log(`
|
|
615
|
+
\u6B65\u9AA4\u94FE:`);for(let[l,d]of t.orderedStepIds.entries()){let p=t.steps.find(u=>u.id===d),f=l<t.orderedStepIds.length-1?" \u2192":" \u2713";console.log(` ${l+1}. [${d}] ${p?.name??"?"}${f}`)}let r=await Wr(n,"utf8"),o=Ur.parse(r),s=Me(o.agent)?o.agent:{},c=typeof s.engine=="string"&&s.engine!==""?e.agent.engine:`\u672A\u914D\u7F6E\uFF08\u9ED8\u8BA4 ${e.agent.engine}\uFF09`;console.log(`
|
|
616
|
+
\u914D\u7F6E\u6458\u8981:`),console.log(` AI \u8868\u683C: base=${e.tracker.base_id} table=${e.tracker.table_id}`),console.log(` \u5F15\u64CE: ${c}`),console.log(` \u8F6E\u8BE2\u95F4\u9694: ${e.polling.interval_ms}ms`),console.log()}a(vi,"printConfigSummary");async function wi(n,e){let t=De.dirname(n),r;try{r=(await Gr(n,{lenientEnv:!0})).workflowEntries}catch{r=await yi(n,t)}if(e&&(r=r.filter(o=>o.id===e),r.length===0))throw new Error(`\u672A\u627E\u5230\u5DE5\u4F5C\u6D41\u300C${e}\u300D`);return r}a(wi,"resolveWorkflowEntries");function Me(n){return typeof n=="object"&&n!==null&&!Array.isArray(n)}a(Me,"isRecord");async function yi(n,e){let t=await Wr(n,"utf8"),r=Ur.parse(t);if(!Me(r))throw new Error("\u914D\u7F6E\u6587\u4EF6\u5FC5\u987B\u662F\u4E00\u4E2A\u5BF9\u8C61");if(Me(r.workflow)){let o=r.workflow.template,s=r.workflow.recipe_dir??"./recipes";if(typeof o=="string")return[{id:"default",templatePath:De.resolve(e,o),recipeDir:De.resolve(e,String(s))}]}if(Me(r.workflows)&&typeof r.workflows.dir=="string")return await ui(e,r.workflows.dir);throw new Error("\u914D\u7F6E\u4E2D\u672A\u627E\u5230 workflow / workflows \u6BB5")}a(yi,"inferEntriesFromRawYaml");async function ki(n){try{mi();let e=await pi(n);return fi(n,e,{lenientEnv:!0})}catch{return null}}a(ki,"tryLoadProfile");var Ri={structure:"\u7ED3\u6784\u5B8C\u6574\u6027",recipe_bind:"Recipe \u7ED1\u5B9A",recipe_typecheck:"\u7C7B\u578B\u68C0\u67E5",config_contract:"\u914D\u7F6E\u5951\u7EA6",dataflow:"\u53C2\u6570\u6D41\u8F6C"};function bi(n){console.log(`\u5DE5\u4F5C\u6D41\u95E8\u7981\u6821\u9A8C${n.strict?"\uFF08--strict\uFF09":""}`),console.log("\u2550".repeat(56));for(let t of n.workflows){console.log(`
|
|
617
|
+
\u5DE5\u4F5C\u6D41: ${t.id} ${t.ok?"\u2713 \u901A\u8FC7":"\u2717 \u672A\u901A\u8FC7"}`);for(let r of t.gates)Ci(r)}console.log(`
|
|
618
|
+
`+"\u2500".repeat(56));let e=xi(n);console.log(`${n.workflows.length} \u4E2A\u5DE5\u4F5C\u6D41\uFF1A${n.ok?"\u5168\u90E8\u901A\u8FC7 \u2713":"\u5B58\u5728\u9519\u8BEF \u2717"}\uFF5Cerror ${e.errors}\uFF5Cwarning ${e.warnings}\uFF5Csuggestion ${e.suggestions}`),n.ok||console.log("\u4FEE\u590D\u4E0A\u8FF0 error \u540E\u91CD\u65B0\u8FD0\u884C\uFF1Berror \u8BA1\u5165\u9000\u51FA\u7801\uFF08CI \u53EF\u4F5C\u95E8\u7981\uFF09\u3002")}a(bi,"printReport");function Ci(n){let e=Ri[n.gate]??n.gate;if(n.status==="skipped"){console.log(` \u25CB ${e}: \u8DF3\u8FC7\uFF08${n.skipReason??""}\uFF09`);return}let t=n.status==="passed"?"\u2713":"\u2717",r=n.issues.filter(s=>s.severity==="error").length,o=n.status==="passed"?n.issues.length>0?`\uFF08${n.issues.length} \u6761\u63D0\u793A\uFF09`:"":`\uFF08${r} \u4E2A\u9519\u8BEF\uFF09`;console.log(` ${t} ${e}${o} [${n.durationMs}ms]`);for(let s of n.issues)Ai(s)}a(Ci,"printGate");function Ai(n){let e=n.severity==="error"?"\u2717":n.severity==="warning"?"\u25B3":"\xB7",t=n.location?[n.location.file,n.location.stepId,n.location.key].filter(Boolean).join(" \u203A "):"";console.log(` ${e} [${n.code}]${t?` ${t}`:""}`),console.log(` ${n.message}`)}a(Ai,"printIssue");function xi(n){let e=0,t=0,r=0;for(let o of n.workflows)for(let s of o.gates)for(let i of s.issues)i.severity==="error"?e++:i.severity==="warning"?t++:r++;return{errors:e,warnings:t,suggestions:r}}a(xi,"summarize");import{logger as Ti}from"aitable-workflow-core";function Ei(n,e){if(n.getOptionValueSource("config")!=="default")return e;let t=n.parent?.getOptionValue("config");return typeof t=="string"?t:e}a(Ei,"effectiveConfigPath");function zr(n,e){n.command("config").description("\u6821\u9A8C\u9879\u76EE\u914D\u7F6E\u5B8C\u6574\u6027\uFF0C\u5E76\u53EF\u4EA4\u4E92\u5F0F\u4FEE\u6539\u53C2\u6570").option("-c, --config <path>","\u9879\u76EE\u76EE\u5F55\u6216\u914D\u7F6E\u6587\u4EF6\u8DEF\u5F84",e.defaultConfig).option("-w, --workflow <id>","\u591A\u5DE5\u4F5C\u6D41\u6A21\u5F0F\uFF1A\u6307\u5B9A\u6821\u9A8C\u7684\u5DE5\u4F5C\u6D41 ID\uFF08\u7F3A\u7701\u6821\u9A8C\u5168\u90E8\uFF09").option("--json","JSON \u683C\u5F0F\u8F93\u51FA\u6821\u9A8C\u7ED3\u679C").option("--summary","\u4E0E --json \u5408\u7528\uFF1A\u53EA\u8F93\u51FA ok \u4E0E summary").option("--errors-only","\u4E0E --json \u5408\u7528\uFF1A\u53EA\u8F93\u51FA status \u4E3A error \u7684\u9879").option("--no-interactive","\u4EC5\u6821\u9A8C\uFF0C\u8DF3\u8FC7\u4EA4\u4E92\u5F0F\u4FEE\u6539").action(async r=>{try{let{runConfigCommand:o}=await import("./config-command-7ECUJOEU.js");await o({configPath:r.config,workflowId:r.workflow,json:r.json,interactive:r.interactive,summary:r.summary,errorsOnly:r.errorsOnly})}catch(o){o instanceof Error&&o.message.includes("cancelled")&&process.exit(0),Ti.error("cli","config \u547D\u4EE4\u5931\u8D25",{error:o instanceof Error?o.message:String(o)}),process.exit(1)}}).command("set").description("\u975E\u4EA4\u4E92\u5199\u914D\u7F6E\u9879\uFF08key \u53D6\u81EA config --json \u7684 item.key\uFF09").option("-c, --config <path>","\u9879\u76EE\u76EE\u5F55\u6216\u914D\u7F6E\u6587\u4EF6\u8DEF\u5F84",e.defaultConfig).option("-w, --workflow <id>","\u591A\u5DE5\u4F5C\u6D41\u9879\u76EE\u91CC\u7ED9 key \u6D88\u6B67\uFF08\u540C\u540D key \u547D\u4E2D\u591A\u4E2A\u5DE5\u4F5C\u6D41\u65F6\u5FC5\u586B\uFF09").option("--set <key=value>","\u5199\u4E00\u9879\uFF1B\u53EF\u91CD\u590D\u3002\u654F\u611F\u9879\u62D2\u6536\uFF08\u503C\u4F1A\u8FDB argv\uFF09\uFF0C\u6539\u7528 --set-stdin",(r,o)=>[...o,r],[]).option("--set-stdin <key>","\u5199\u4E00\u9879\uFF0C\u503C\u4ECE stdin \u9010\u884C\u6309\u987A\u5E8F\u8BFB\uFF1B\u53EF\u91CD\u590D\u3002\u654F\u611F\u9879\u8D70\u8FD9\u6761",(r,o)=>[...o,r],[]).option("--dry-run","\u53EA\u6253\u5370\u5C06\u5199\u54EA\u4E2A\u6587\u4EF6\u7684\u54EA\u4E2A\u8DEF\u5F84\uFF0C\u4E0D\u5199\u76D8\uFF08\u654F\u611F\u503C\u53EA\u6253\u952E\u540D\uFF09").option("--json","JSON \u683C\u5F0F\u8F93\u51FA\u7ED3\u679C").action(async(r,o)=>{try{let{runConfigSet:s,printConfigSetResult:i}=await import("./config-set-FBOQBRSJ.js"),c=await s({configPath:Ei(o,r.config),...r.workflow?{workflowId:r.workflow}:{},set:r.set,setStdin:r.setStdin,...r.dryRun?{dryRun:!0}:{},...r.json?{json:!0}:{}});i(c,r.json===!0)}catch(s){let i=s instanceof Error?s.message:String(s);r.json?process.stdout.write(JSON.stringify({ok:!1,error:i},null,2)+`
|
|
619
|
+
`):console.error(`
|
|
620
|
+
\u2717 ${i}
|
|
621
|
+
`),process.exit(1)}})}a(zr,"registerConfigCommand");import{runSync as Si,logger as Ii}from"aitable-workflow-core";function Jr(n,e){n.command("sync").description("\u68C0\u6D4B\u914D\u7F6E\u4E0E\u8868\u7684\u504F\u5DEE\uFF08\u5B57\u6BB5\u7C7B\u578B/\u9009\u9879 drift\uFF09\uFF0C\u8F93\u51FA\u8BCA\u65AD\u62A5\u544A\u548C\u4FEE\u590D\u5EFA\u8BAE").option("-c, --config <path>","\u914D\u7F6E\u6587\u4EF6\u8DEF\u5F84",e.defaultConfig).option("-y, --yes","\u975E\u4EA4\u4E92\u6A21\u5F0F").action(async t=>{try{await Si({configPath:t.config,yes:t.yes})}catch(r){Ii.error("cli","sync \u5931\u8D25",{error:r instanceof Error?r.message:String(r)}),process.exit(1)}})}a(Jr,"registerSyncCommand");import{listCodingAgents as Pi,logger as _i}from"aitable-workflow-core";function Vr(n,e){n.command("agents").description("\u5217\u51FA\u5168\u90E8\u652F\u6301\u7684 Coding Agent \u9002\u914D\u5668\uFF0C\u5E76\u6807\u6CE8\u672C\u673A\u5DF2\u63A2\u6D4B\u5230\u5B89\u88C5\u7684").option("--json","\u4EE5 JSON \u683C\u5F0F\u8F93\u51FA").action(t=>{try{let r=Pi();if(t.json){process.stdout.write(JSON.stringify(r,null,2)+`
|
|
622
|
+
`);return}let o=r.filter(s=>s.installed).length;console.log(`
|
|
623
|
+
\u652F\u6301 ${r.length} \u4E2A Coding Agent\uFF0C\u672C\u673A\u5DF2\u63A2\u6D4B\u5230 ${o} \u4E2A\uFF1A
|
|
624
|
+
`);for(let s of r){let i=s.installed?"\u2713":"\u2717",c=[s.bin,...s.fallbackBins].join(" / "),l=s.installed?`\u5DF2\u5B89\u88C5 (${s.detectedCmd}${s.detectedVersion?` ${s.detectedVersion}`:""})`:"\u672A\u63A2\u6D4B\u5230";console.log(` ${i} ${s.name.padEnd(16)} [${s.id}] bin: ${c.padEnd(24)} ${l}`)}console.log("")}catch(r){_i.error("cli","\u5217\u51FA agents \u5931\u8D25",{error:r instanceof Error?r.message:String(r)}),process.exit(1)}})}a(Vr,"registerAgentsCommand");import{logger as $i}from"aitable-workflow-core";import{startServer as Oi,resolveServeConfig as ji}from"aitable-workflow-server";import Le from"path";import{existsSync as Yr}from"fs";function Kr(n,e){n.command("serve").description("\u542F\u52A8\u672C\u5730 HTTP API \u670D\u52A1\u5E76\u6258\u7BA1 Web \u524D\u7AEF\u9875\u9762\uFF08local \u6A21\u5F0F\u81EA\u52A8\u6253\u5F00\u6D4F\u89C8\u5668\uFF09").option("-p, --port <number>","\u76D1\u542C\u7AEF\u53E3\uFF08\u9ED8\u8BA4 8787\uFF0C\u53EF\u7528 AITABLE_WORKFLOW_PORT \u8986\u76D6\uFF09").option("--host <host>","\u76D1\u542C\u5730\u5740\uFF08\u9ED8\u8BA4 127.0.0.1\uFF0C\u53EF\u7528 AITABLE_WORKFLOW_HOST \u8986\u76D6\uFF09").option("--data-root <path>","\u9879\u76EE\u5DE5\u4F5C\u533A\u6570\u636E\u76EE\u5F55\uFF08\u9ED8\u8BA4 .sandbox/aitable-workflow-server\uFF0C\u53EF\u7528 AITABLE_WORKFLOW_DATA_DIR \u8986\u76D6\uFF09").option("--web-root <path>","Web \u524D\u7AEF\u9759\u6001\u8D44\u6E90\u76EE\u5F55\uFF08\u9ED8\u8BA4\u4F7F\u7528\u968F CLI \u6253\u5305\u7684 dist/web\uFF09").option("--no-open","\u542F\u52A8\u540E\u4E0D\u81EA\u52A8\u6253\u5F00\u6D4F\u89C8\u5668\uFF08\u9ED8\u8BA4\u81EA\u52A8\u6253\u5F00\uFF09").action(async t=>{try{let r={};if(t.port!==void 0){let s=Number.parseInt(t.port,10);Number.isFinite(s)&&s>0&&(r.port=s)}if(t.host!==void 0&&(r.host=t.host),t.dataRoot!==void 0&&(r.dataRoot=t.dataRoot),t.webRoot!==void 0)r.webRoot=t.webRoot;else{let s=Le.join(e.cliDir,"web");if(Yr(Le.join(s,"index.html")))r.webRoot=s;else{let i=Le.resolve(e.cliDir,"..","..","web","dist");Yr(Le.join(i,"index.html"))&&(r.webRoot=i)}}let o=ji(r);if(await Oi(o),o.webRoot&&t.open!==!1){let s=o.host==="0.0.0.0"?"127.0.0.1":o.host;re(`http://${s}:${o.port}`)}}catch(r){$i.error("cli","HTTP \u670D\u52A1\u542F\u52A8\u5931\u8D25",{error:r instanceof Error?r.message:String(r)}),process.exit(1)}})}a(Kr,"registerServeCommand");import{Command as gt}from"commander";import{logger as S,listCredentials as nn,getActiveCredential as F,maskSecret as Ji}from"aitable-workflow-core";import{readFile as Mi,writeFile as vu,mkdir as wu}from"fs/promises";import Di from"path";var Xr={connectionState:"disconnected",lastHeartbeatAt:null,serverUrl:"",runningTasks:0,queuedTasks:0,lastDisconnectReason:null,updatedAt:new Date().toISOString()};function Li(n){return Di.join(ne(n),"state.json")}a(Li,"stateFilePath");async function Be(n){try{let e=await Mi(Li(n),"utf8");return{...Xr,...JSON.parse(e)}}catch{return{...Xr}}}a(Be,"readState");import{execSync as ee}from"child_process";import{writeFile as Bi,rm as Hi,mkdir as Fi,access as Ni}from"fs/promises";import I from"path";import Zr from"os";import{assertPortableId as Wi,readCredentials as Ui}from"aitable-workflow-core";var Gi="com.alibaba.aitable-workflow.daemon",pt="\u8BF7\u5148\u5168\u5C40\u5B89\u88C5\uFF1Anpm i -g @ali/aitable-workflow";function te(n){return`${Gi}.${Wi(n,{label:"agentId"})}`}a(te,"plistLabel");function ft(n){return I.join(Zr.homedir(),"Library","LaunchAgents",`${te(n)}.plist`)}a(ft,"plistPath");function H(){return process.platform==="darwin"}a(H,"isMacOS");function Qr(){try{return ee("which aitable-workflow",{encoding:"utf8"}).trim()||null}catch{return null}}a(Qr,"resolveGlobalCliEntry");function en(n){if(!n||!n.trim())throw new Error(`\u672A\u627E\u5230\u5168\u5C40\u5B89\u88C5\u7684 aitable-workflow CLI \u5165\u53E3\uFF0C\u65E0\u6CD5\u914D\u7F6E\u5F00\u673A\u81EA\u542F\u3002
|
|
625
|
+
\u{1F4A1} ${pt}`);if(n.includes("/_npx/")||n.includes(`${I.sep}_npx${I.sep}`))throw new Error(`\u68C0\u6D4B\u5230 CLI \u5165\u53E3\u4F4D\u4E8E npx \u4E34\u65F6\u7F13\u5B58\uFF0C\u5F00\u673A\u81EA\u542F\u4F1A\u5931\u6548\uFF1A${n}
|
|
626
|
+
\u{1F4A1} ${pt}`);if(!I.isAbsolute(n))throw new Error(`CLI \u5165\u53E3\u4E0D\u662F\u7A33\u5B9A\u7684\u5168\u5C40\u7EDD\u5BF9\u8DEF\u5F84\uFF1A${n}
|
|
627
|
+
\u{1F4A1} ${pt}`)}a(en,"assertStableCliEntry");async function qi(n){let e={};e.AITABLE_RELAY_NAME=n;let t;try{let r=await Ui();t=r.agents.find(o=>o.name===n)??r.agents.find(o=>o.name===r.activeAgent)??void 0}catch{t=void 0}return t&&(t.serverUrl&&(e.AITABLE_RELAY_SERVER_URL=t.serverUrl),t.token&&(e.AITABLE_RELAY_TOKEN=t.token),t.workspaceRoot&&(e.AITABLE_RELAY_WORKSPACE_ROOT=t.workspaceRoot)),e}a(qi,"buildRelayEnv");function zi(n,e){let t=te(n),r=e?.cliEntry??Qr();en(r);let o=["relay"];e?.maxTasks&&o.push("--max-tasks",String(e.maxTasks));let s=I.join(Zr.homedir(),".aitable-workflow","daemons",n),i=I.join(s,"launchd.log"),c=I.join(s,"launchd.err.log"),l=[r,...o].map(f=>` <string>${z(f)}</string>`).join(`
|
|
628
|
+
`),d={PATH:process.env.PATH??"/usr/local/bin:/usr/bin:/bin",...e?.relayEnv??{}},p=Object.entries(d).map(([f,u])=>` <key>${z(f)}</key>
|
|
629
|
+
<string>${z(u)}</string>`).join(`
|
|
523
630
|
`);return`<?xml version="1.0" encoding="UTF-8"?>
|
|
524
631
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
525
632
|
<plist version="1.0">
|
|
526
633
|
<dict>
|
|
527
634
|
<key>Label</key>
|
|
528
|
-
<string>${
|
|
635
|
+
<string>${z(t)}</string>
|
|
529
636
|
<key>ProgramArguments</key>
|
|
530
637
|
<array>
|
|
531
638
|
${l}
|
|
@@ -539,49 +646,49 @@ ${p}
|
|
|
539
646
|
<key>RunAtLoad</key>
|
|
540
647
|
<true/>
|
|
541
648
|
<key>StandardOutPath</key>
|
|
542
|
-
<string>${
|
|
649
|
+
<string>${z(i)}</string>
|
|
543
650
|
<key>StandardErrorPath</key>
|
|
544
|
-
<string>${
|
|
651
|
+
<string>${z(c)}</string>
|
|
545
652
|
</dict>
|
|
546
653
|
</plist>
|
|
547
|
-
`}
|
|
548
|
-
Agent: ${s.agentId}`),console.log(`Running: ${s.running?"\u2705 yes":"\u274C no"}`),s.pid&&console.log(`PID: ${s.pid}`),s.uptimeMs!==null){let
|
|
549
|
-
--- Configuration ---`),console.log(`Server: ${i.serverUrl}`),console.log(`Token: ${
|
|
654
|
+
`}a(zi,"generatePlist");function z(n){return n.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""")}a(z,"escapeXml");function He(){let n=process.getuid?.();if(n===void 0)throw new Error("\u65E0\u6CD5\u83B7\u53D6\u7528\u6237 UID\uFF08\u4EC5\u652F\u6301 macOS/Linux\uFF09");return n}a(He,"getUid");async function tn(n,e){if(!H())throw new Error("\u5F00\u673A\u81EA\u542F\u5F53\u524D\u4EC5\u652F\u6301 macOS");let t=Qr();en(t);let r=await qi(n),o=ft(n),s=te(n);try{ee(`launchctl bootout gui/${He()}/${s} 2>/dev/null`,{encoding:"utf8"})}catch{}await Fi(I.dirname(o),{recursive:!0});let i=zi(n,{maxTasks:e?.maxTasks,relayEnv:r,cliEntry:t});await Bi(o,i,"utf8"),ee(`launchctl bootstrap gui/${He()} ${o}`,{encoding:"utf8"})}a(tn,"enableAutostart");async function rn(n){if(!H())throw new Error("\u5F00\u673A\u81EA\u542F\u5F53\u524D\u4EC5\u652F\u6301 macOS");let e=te(n),t=ft(n);try{ee(`launchctl bootout gui/${He()}/${e} 2>/dev/null`,{encoding:"utf8"})}catch{}await Hi(t,{force:!0})}a(rn,"disableAutostart");async function mt(n){if(!H())throw new Error("\u5F00\u673A\u81EA\u542F\u5F53\u524D\u4EC5\u652F\u6301 macOS");let e=te(n),t=ft(n),r=!1;try{await Ni(t),r=!0}catch{r=!1}let o=!1,s=!1,i=null;try{let c=ee(`launchctl print gui/${He()}/${e} 2>/dev/null`,{encoding:"utf8"});o=!0;let l=c.match(/pid\s*=\s*(\d+)/);l&&(i=parseInt(l[1],10),s=!0)}catch{o=!1}return{installed:r,loaded:o,running:s,pid:i}}a(mt,"getAutostartStatus");import{watchFile as Vi,statSync as Yi,openSync as Ki,readSync as Xi,closeSync as Zi}from"fs";import{readFile as on}from"fs/promises";function sn(n,e){let t=n.command("daemon").description("\u540E\u53F0 relay daemon \u751F\u547D\u5468\u671F\u7BA1\u7406");t.command("start").description("\u4EE5\u540E\u53F0\u8FDB\u7A0B\u542F\u52A8 relay daemon").option("--agent <name>","Agent \u540D\u79F0\uFF08\u9ED8\u8BA4\u4F7F\u7528 activeAgent\uFF09").option("--server-url <url>","Gateway \u5730\u5740").option("--token <machineToken>","\u6267\u884C\u5F15\u64CE token").option("--workspace-root <dir>","\u5DE5\u4F5C\u533A\u6839\u76EE\u5F55").option("--max-tasks <n>","\u5E76\u53D1\u4E0A\u9650","1").action(async r=>{try{let o=r.agent;if(!o){let c=await F();if(!c)throw new Error("\u672A\u6307\u5B9A --agent \u4E14\u65E0\u6D3B\u8DC3 Agent\u3002\u4F7F\u7528 `aitable-workflow connect` \u6CE8\u518C\u6216 `--agent <name>` \u6307\u5B9A\u3002");o=c.name}let s=await L({serverUrl:r.serverUrl,token:r.token,workspaceRoot:r.workspaceRoot,name:o,maxTasks:r.maxTasks}),i=await Z({agentId:o,serverUrl:s.serverUrl,token:s.token,name:s.name??o,workspaceRoot:s.workspaceRoot,maxTasks:s.maxTasks});console.log("\u2705 Daemon \u5DF2\u542F\u52A8"),console.log(` Agent: ${o}`),console.log(` PID: ${i.pid}`),console.log(` Log: ~/.aitable-workflow/daemons/${o}/daemon.log`)}catch(o){S.error("cli","start \u5931\u8D25",{error:o instanceof Error?o.message:String(o)}),process.exit(1)}}),t.command("stop").description("\u505C\u6B62\u540E\u53F0 daemon").option("--agent <name>","Agent \u540D\u79F0").option("--all","\u505C\u6B62\u6240\u6709 daemon").action(async r=>{try{if(r.all){let o=await nn(),s=0;for(let i of o)await xe(i.name)&&s++;console.log(`\u2705 \u5DF2\u505C\u6B62 ${s} \u4E2A daemon`)}else{let o=r.agent;if(!o){let i=await F();if(!i)throw new Error("\u672A\u6307\u5B9A --agent \u4E14\u65E0\u6D3B\u8DC3 Agent");o=i.name}let s=await xe(o);console.log(s?`\u2705 Daemon "${o}" \u5DF2\u505C\u6B62`:`\u26A0\uFE0F Daemon "${o}" \u672A\u5728\u8FD0\u884C`)}}catch(o){S.error("cli","stop \u5931\u8D25",{error:o instanceof Error?o.message:String(o)}),process.exit(1)}}),t.command("restart").description("\u91CD\u542F\u540E\u53F0 daemon").option("--agent <name>","Agent \u540D\u79F0").option("--max-tasks <n>","\u5E76\u53D1\u4E0A\u9650","1").action(async r=>{try{let o=r.agent;if(!o){let c=await F();if(!c)throw new Error("\u672A\u6307\u5B9A --agent \u4E14\u65E0\u6D3B\u8DC3 Agent");o=c.name}console.log(`\u{1F504} \u6B63\u5728\u91CD\u542F "${o}"...`),await xe(o);let s=await L({name:o,maxTasks:r.maxTasks}),i=await Z({agentId:o,serverUrl:s.serverUrl,token:s.token,name:s.name??o,workspaceRoot:s.workspaceRoot,maxTasks:s.maxTasks});console.log(`\u2705 Daemon \u5DF2\u91CD\u542F (PID: ${i.pid})`)}catch(o){S.error("cli","restart \u5931\u8D25",{error:o instanceof Error?o.message:String(o)}),process.exit(1)}}),t.command("status").description("\u67E5\u770B daemon \u72B6\u6001").option("--agent <name>","Agent \u540D\u79F0").option("-v, --verbose","\u5C55\u793A\u5B8C\u6574\u914D\u7F6E").action(async r=>{try{let o=r.agent;if(!o){let c=await F();if(!c){console.log("\u65E0\u6D3B\u8DC3 Agent");return}o=c.name}let s=await Q(o),i=await F();if(console.log(`
|
|
655
|
+
Agent: ${s.agentId}`),console.log(`Running: ${s.running?"\u2705 yes":"\u274C no"}`),s.pid&&console.log(`PID: ${s.pid}`),s.uptimeMs!==null){let c=Math.floor(s.uptimeMs/1e3),l=Math.floor(c/60),d=Math.floor(l/60);console.log(`Uptime: ${d}h ${l%60}m ${c%60}s`)}console.log(`Log file: ${s.logFile}`),r.verbose&&i&&(console.log(`
|
|
656
|
+
--- Configuration ---`),console.log(`Server: ${i.serverUrl}`),console.log(`Token: ${Ji(i.token)}`),i.workspaceRoot&&console.log(`Workspace: ${i.workspaceRoot}`)),console.log("")}catch(o){S.error("cli","status \u5931\u8D25",{error:o instanceof Error?o.message:String(o)}),process.exit(1)}}),t.command("logs").description("\u67E5\u770B daemon \u65E5\u5FD7").option("--agent <name>","Agent \u540D\u79F0").option("-f, --follow","\u6301\u7EED\u8DDF\u8E2A\u65E5\u5FD7\u8F93\u51FA").option("-n <lines>","\u663E\u793A\u6700\u8FD1 N \u884C","50").action(async r=>{try{let o=r.agent;if(!o){let c=await F();if(!c)throw new Error("\u672A\u6307\u5B9A --agent \u4E14\u65E0\u6D3B\u8DC3 Agent");o=c.name}let s=K(o),i=parseInt(r.n,10)||50;if(r.follow){let c=await on(s,"utf8").catch(()=>"");if(c){let d=c.trimEnd().split(`
|
|
550
657
|
`);console.log(d.slice(-i).join(`
|
|
551
|
-
`))}let l=
|
|
658
|
+
`))}let l=c.length;Vi(s,{interval:500},()=>{try{let d=Yi(s);if(d.size>l){let p=Ki(s,"r"),f=Buffer.alloc(d.size-l);Xi(p,f,0,f.length,l),Zi(p),process.stdout.write(f.toString("utf8")),l=d.size}}catch{}})}else{let c=await on(s,"utf8").catch(()=>"");if(!c){console.log(`\u6682\u65E0\u65E5\u5FD7 (${s})`);return}let l=c.trimEnd().split(`
|
|
552
659
|
`);console.log(l.slice(-i).join(`
|
|
553
|
-
`))}}catch(
|
|
554
|
-
Agent: ${
|
|
660
|
+
`))}}catch(o){S.error("cli","logs \u5931\u8D25",{error:o instanceof Error?o.message:String(o)}),process.exit(1)}}),t.command("autostart").description("macOS \u5F00\u673A\u81EA\u542F\u7BA1\u7406").addCommand(new gt("enable").description("\u542F\u7528 macOS \u767B\u5F55\u81EA\u542F\u52A8").requiredOption("--agent-id <id>","Agent ID / \u540D\u79F0").option("--max-tasks <n>","\u5E76\u53D1\u4E0A\u9650").action(async r=>{try{H()||(console.error("\u274C \u5F00\u673A\u81EA\u542F\u5F53\u524D\u4EC5\u652F\u6301 macOS"),process.exit(1)),await tn(r.agentId,{maxTasks:r.maxTasks?parseInt(r.maxTasks,10):void 0}),console.log("\u2705 \u81EA\u542F\u52A8\u5DF2\u542F\u7528"),console.log(` Agent: ${r.agentId}`),console.log(` Plist: ~/Library/LaunchAgents/com.alibaba.aitable-workflow.daemon.${r.agentId}.plist`)}catch(o){S.error("cli","autostart enable \u5931\u8D25",{error:o instanceof Error?o.message:String(o)}),process.exit(1)}})).addCommand(new gt("disable").description("\u5173\u95ED macOS \u767B\u5F55\u81EA\u542F\u52A8").requiredOption("--agent-id <id>","Agent ID / \u540D\u79F0").action(async r=>{try{H()||(console.error("\u274C \u5F00\u673A\u81EA\u542F\u5F53\u524D\u4EC5\u652F\u6301 macOS"),process.exit(1)),await rn(r.agentId),console.log(`\u2705 \u81EA\u542F\u52A8\u5DF2\u5173\u95ED (${r.agentId})`)}catch(o){S.error("cli","autostart disable \u5931\u8D25",{error:o instanceof Error?o.message:String(o)}),process.exit(1)}})).addCommand(new gt("status").description("\u67E5\u770B macOS \u81EA\u542F\u52A8\u72B6\u6001").option("--agent-id <id>","Agent ID / \u540D\u79F0\uFF08\u4E0D\u6307\u5B9A\u5219\u5217\u51FA\u6240\u6709\uFF09").action(async r=>{try{if(H()||(console.error("\u274C \u5F00\u673A\u81EA\u542F\u5F53\u524D\u4EC5\u652F\u6301 macOS"),process.exit(1)),r.agentId){let o=await mt(r.agentId);console.log(`
|
|
661
|
+
Agent: ${r.agentId}`),console.log(`Installed: ${o.installed?"yes":"no"}`),console.log(`Loaded: ${o.loaded?"yes":"no"}`),console.log(`Running: ${o.running?`yes (PID: ${o.pid})`:"no"}`),console.log("")}else{let o=await nn();if(o.length===0){console.log("\u65E0\u5DF2\u6CE8\u518C\u7684 Agent");return}for(let s of o){let i=await mt(s.name),c=i.running?`running (PID: ${i.pid})`:i.loaded?"loaded":i.installed?"installed":"not installed";console.log(` ${s.name}: ${c}`)}}}catch(o){S.error("cli","autostart status \u5931\u8D25",{error:o instanceof Error?o.message:String(o)}),process.exit(1)}}))}a(sn,"registerDaemonCommands");function an(n,e){n.command("heartbeat").description("\u5411\u670D\u52A1\u7AEF\u53D1\u9001\u5FC3\u8DF3\u5E76\u8FD4\u56DE\u4EFB\u52A1\u5206\u914D\u60C5\u51B5").action(async()=>{try{let t=await F();if(!t)throw new Error("\u65E0\u6D3B\u8DC3 Agent");if(!(await Q(t.name)).running){console.log("\u26A0\uFE0F Daemon \u672A\u5728\u8FD0\u884C\u3002\u4F7F\u7528 `aitable-workflow daemon start` \u542F\u52A8\u3002");return}let o=await Be(t.name);console.log("\u2705 Heartbeat OK"),console.log(` Agent: ${t.name}`),console.log(` Connection: ${o.connectionState}`),console.log(` Running: ${o.runningTasks} tasks`),console.log(` Queued: ${o.queuedTasks} tasks`),o.lastHeartbeatAt&&console.log(` Last HB: ${o.lastHeartbeatAt}`)}catch(t){S.error("cli","heartbeat \u5931\u8D25",{error:t instanceof Error?t.message:String(t)}),process.exit(1)}})}a(an,"registerHeartbeatCommand");import{logger as Qi,saveCredential as ea,findConflictingCredential as ta,maskSecret as ra}from"aitable-workflow-core";function cn(n,e){n.command("connect").description("\u914D\u7F6E\u6267\u884C\u5F15\u64CE token + \u4FDD\u5B58\u672C\u673A\u51ED\u8BC1 + \u540E\u53F0\u542F\u52A8 daemon").requiredOption("--server-url <url>","Gateway / \u5E73\u53F0\u5730\u5740").requiredOption("--token <machineToken>","\u8BE5\u6267\u884C\u5F15\u64CE\u7684 token\uFF08sk_machine_*\uFF09").requiredOption("--name <name>","\u672C\u673A credentials/daemon \u522B\u540D").option("--workspace-root <dir>","\u5DE5\u4F5C\u533A\u6839\u76EE\u5F55\uFF08\u53EF\u9009\uFF09").option("--trace-http-port <port>","\u672C\u673A trace HTTP \u7AEF\u53E3\uFF08\u7F3A\u7701 8790\uFF1B0/off \u5173\u95ED\uFF09").option("--no-start","\u53EA\u6CE8\u518C\u4E0D\u542F\u52A8 daemon").option("--foreground","\u6CE8\u518C\u540E\u5728\u524D\u53F0\u8FD0\u884C relay\uFF08\u963B\u585E\u7EC8\u7AEF\uFF0C\u4FBF\u4E8E\u8C03\u8BD5\uFF09").option("--force","\u8986\u76D6\u540C\u540D\u4F46\u7F51\u5173\u4E0D\u540C\u7684\u5DF2\u6709\u51ED\u8BC1").action(async t=>{try{if(!t.force){let l=await ta(t.name,t.serverUrl);l&&(console.error(`\u26A0\uFE0F \u62D2\u7EDD\u8986\u76D6\uFF1AAgent \u540D\u79F0 "${t.name}" \u5DF2\u7ED1\u5B9A\u5230\u53E6\u4E00\u4E2A\u7F51\u5173\u3002`),console.error(` \u65E7\u7F51\u5173: ${l.serverUrl}`),console.error(` \u65B0\u7F51\u5173: ${t.serverUrl}`),console.error(" \u7EE7\u7EED\u5C06\u8986\u76D6\u672C\u673A\u8BE5\u51ED\u8BC1\uFF0C\u4E14\u65E7\u7F51\u5173\u7684 daemon \u65E0\u6CD5\u4E0E\u65B0\u7684\u5171\u5B58\uFF08PID \u4E92\u65A5\uFF09\u3002"),console.error(" \u8BF7\u9009\u62E9\u5176\u4E00\uFF1A"),console.error(" 1) \u6362\u4E00\u4E2A --name\uFF08\u591A\u7F51\u5173\u5EFA\u8BAE\u6BCF\u4E2A\u7F51\u5173\u7528\u4E0D\u540C\u540D\u79F0\uFF09"),console.error(" 2) \u786E\u5B9E\u8981\u6539\u7ED1\uFF0C\u52A0 --force \u5F3A\u5236\u8986\u76D6"),process.exit(1))}let r=t.workspaceRoot?Ee(t.workspaceRoot,t.name):void 0,o={name:t.name,serverUrl:t.serverUrl,token:t.token,workspaceRoot:r,createdAt:new Date().toISOString()};if(await ea(o),console.log(`\u2705 Agent "${t.name}" \u5DF2\u6CE8\u518C\u5E76\u4FDD\u5B58\u51ED\u8BC1`),console.log(` Server: ${t.serverUrl}`),console.log(` Token: ${ra(t.token)}`),r&&console.log(` Workspace: ${r}`),console.log(" \u51ED\u8BC1\u6587\u4EF6: ~/.aitable-workflow/credentials.json"),!t.start){t.foreground&&console.log(`
|
|
555
662
|
\u{1F4A1} --no-start \u4E0E --foreground \u540C\u65F6\u6307\u5B9A\uFF0C\u6309 --no-start \u4F18\u5148\uFF1A\u4EC5\u6CE8\u518C\u4E0D\u542F\u52A8\u3002`),console.log(`
|
|
556
663
|
\u{1F4A1} \u542F\u52A8 daemon: aitable-workflow daemon start \u6216 aitable-workflow relay`);return}if(t.foreground){console.log(`
|
|
557
|
-
\u{1F680} \u524D\u53F0\u542F\u52A8 relay\uFF08Ctrl-C \u9000\u51FA\uFF09...`),await
|
|
558
|
-
\u{1F680} Daemon \u5DF2\u540E\u53F0\u542F\u52A8`),console.log(` Agent: ${s}`),console.log(` PID: ${
|
|
559
|
-
\u{1F4CB} \u5E38\u7528\u547D\u4EE4\uFF1A`),console.log(` \u67E5\u770B\u72B6\u6001: aitable-workflow daemon status --agent ${s}`),console.log(` \u8DDF\u8E2A\u65E5\u5FD7: aitable-workflow daemon logs -f --agent ${s}`),console.log(` \u505C\u6B62: aitable-workflow daemon stop --agent ${s}`),console.log(` \u91CD\u542F: aitable-workflow daemon restart --agent ${s}`),console.log(" \u5217\u51FA Agent: aitable-workflow agent list"),console.log(" \u5207\u6362 Agent: aitable-workflow agent use <name>"),console.log(` \u5F00\u673A\u81EA\u542F: aitable-workflow daemon autostart enable --agent-id ${s}`)}catch(
|
|
560
|
-
\u5DF2\u4FDD\u5B58 ${
|
|
561
|
-
`);for(let s of
|
|
562
|
-
`);return}let l=
|
|
563
|
-
${l} Agent: ${
|
|
664
|
+
\u{1F680} \u524D\u53F0\u542F\u52A8 relay\uFF08Ctrl-C \u9000\u51FA\uFF09...`),await Ie({serverUrl:t.serverUrl,token:t.token,name:t.name,workspaceRoot:r,...t.traceHttpPort?{traceHttpPort:t.traceHttpPort}:{}});return}let s=t.name,i=await L({serverUrl:t.serverUrl,token:t.token,workspaceRoot:t.workspaceRoot,name:s}),c=await Z({agentId:s,serverUrl:i.serverUrl,token:i.token,name:i.name??s,workspaceRoot:i.workspaceRoot,maxTasks:i.maxTasks,...t.traceHttpPort?{traceHttpPort:t.traceHttpPort}:{}});console.log(`
|
|
665
|
+
\u{1F680} Daemon \u5DF2\u540E\u53F0\u542F\u52A8`),console.log(` Agent: ${s}`),console.log(` PID: ${c.pid}`),console.log(` Log: ~/.aitable-workflow/daemons/${s}/daemon.log`),console.log(`
|
|
666
|
+
\u{1F4CB} \u5E38\u7528\u547D\u4EE4\uFF1A`),console.log(` \u67E5\u770B\u72B6\u6001: aitable-workflow daemon status --agent ${s}`),console.log(` \u8DDF\u8E2A\u65E5\u5FD7: aitable-workflow daemon logs -f --agent ${s}`),console.log(` \u505C\u6B62: aitable-workflow daemon stop --agent ${s}`),console.log(` \u91CD\u542F: aitable-workflow daemon restart --agent ${s}`),console.log(" \u5217\u51FA Agent: aitable-workflow agent list"),console.log(" \u5207\u6362 Agent: aitable-workflow agent use <name>"),console.log(` \u5F00\u673A\u81EA\u542F: aitable-workflow daemon autostart enable --agent-id ${s}`)}catch(r){Qi.error("cli","connect \u5931\u8D25",{error:r instanceof Error?r.message:String(r)}),process.exit(1)}})}a(cn,"registerConnectCommand");import{logger as Fe,listCredentials as na,setActiveAgent as oa,getActiveCredential as ln,readCredentials as sa,maskSecret as dn}from"aitable-workflow-core";function un(n,e){let t=n.command("agent").description("Agent \u51ED\u8BC1\u7BA1\u7406");t.command("list").description("\u5217\u51FA\u6240\u6709\u5DF2\u4FDD\u5B58\u7684 Agent \u51ED\u8BC1").action(async()=>{try{let r=await na();if(r.length===0){console.log("\u6682\u65E0\u5DF2\u4FDD\u5B58\u7684 Agent\u3002\u4F7F\u7528 `aitable-workflow connect` \u6CE8\u518C\u3002");return}let o=await sa();console.log(`
|
|
667
|
+
\u5DF2\u4FDD\u5B58 ${r.length} \u4E2A Agent\uFF08\u6D3B\u8DC3: ${o.activeAgent??"\u65E0"}\uFF09:
|
|
668
|
+
`);for(let s of r){let i=s.name===o.activeAgent?" \u2190 active":"";console.log(` \u2022 ${s.name}${i}`),console.log(` Server: ${s.serverUrl}`),console.log(` Token: ${dn(s.token)}`),s.workspaceRoot&&console.log(` Workspace: ${s.workspaceRoot}`),console.log(` Created: ${s.createdAt}`)}console.log("")}catch(r){Fe.error("cli","agent list \u5931\u8D25",{error:r instanceof Error?r.message:String(r)}),process.exit(1)}}),t.command("use <name>").description("\u5207\u6362\u6D3B\u8DC3 Agent").action(async r=>{try{let o=await oa(r);console.log(`\u2705 \u5DF2\u5207\u6362\u5230 Agent "${o.activeAgent}"`)}catch(o){Fe.error("cli","agent use \u5931\u8D25",{error:o instanceof Error?o.message:String(o)}),process.exit(1)}}),t.command("whoami").description("\u663E\u793A\u5F53\u524D\u6D3B\u8DC3 Agent").action(async()=>{try{let r=await ln();if(!r){console.log("\u5F53\u524D\u65E0\u6D3B\u8DC3 Agent\u3002\u4F7F\u7528 `aitable-workflow connect` \u6CE8\u518C\u6216 `aitable-workflow agent use <name>` \u5207\u6362\u3002");return}console.log(`Agent: ${r.name}`),console.log(`Server: ${r.serverUrl}`),console.log(`Token: ${dn(r.token)}`),r.workspaceRoot&&console.log(`Workspace: ${r.workspaceRoot}`)}catch(r){Fe.error("cli","agent whoami \u5931\u8D25",{error:r instanceof Error?r.message:String(r)}),process.exit(1)}}),t.command("status").description("\u67E5\u770B Agent \u8FDE\u63A5\u72B6\u6001\u4E0E\u8FD0\u884C\u65F6\u4FE1\u606F").option("--json","JSON \u683C\u5F0F\u8F93\u51FA").action(async r=>{try{let o=await ln();if(!o){console.log("\u65E0\u6D3B\u8DC3 Agent\u3002\u4F7F\u7528 `aitable-workflow connect` \u6CE8\u518C\u3002");return}let s=await Q(o.name),i=await Be(o.name),c={agent:o.name,serverUrl:o.serverUrl,connectionState:s.running?i.connectionState:"stopped",lastHeartbeatAt:i.lastHeartbeatAt,runningTasks:i.runningTasks,queuedTasks:i.queuedTasks,lastDisconnectReason:i.lastDisconnectReason,pid:s.pid};if(r.json){process.stdout.write(JSON.stringify(c,null,2)+`
|
|
669
|
+
`);return}let l=c.connectionState==="connected"?"\u{1F7E2}":c.connectionState==="reconnecting"?"\u{1F7E1}":"\u{1F534}";console.log(`
|
|
670
|
+
${l} Agent: ${c.agent}`),console.log(` Server: ${c.serverUrl}`),console.log(` Connection: ${c.connectionState}`),c.lastHeartbeatAt&&console.log(` Last HB: ${c.lastHeartbeatAt}`),s.running&&(console.log(` PID: ${c.pid}`),console.log(` Tasks: ${c.runningTasks} running, ${c.queuedTasks} queued`)),c.lastDisconnectReason&&console.log(` Last Error: ${c.lastDisconnectReason}`),console.log("")}catch(o){Fe.error("cli","agent status \u5931\u8D25",{error:o instanceof Error?o.message:String(o)}),process.exit(1)}})}a(un,"registerAgentCommands");import{logger as ia}from"aitable-workflow-core";function pn(n,e){n.command("relay").description("\u4EE5\u672C\u673A relay \u5B88\u62A4\u8EAB\u4EFD\u53CD\u8FDE RelayGateway\uFF0C\u6309\u9700\u5728\u672C\u673A\u6267\u884C Agent/dws \u4EFB\u52A1").option("--server-url <url>","Gateway \u5730\u5740\uFF08\u4E5F\u53EF\u7528 AITABLE_RELAY_SERVER_URL\uFF09").option("--token <machineToken>","\u8BE5\u6267\u884C\u5F15\u64CE\u7684 token\uFF08\u4E5F\u53EF\u7528 AITABLE_RELAY_TOKEN\uFF09").option("--name <name>","\u672C\u673A credentials/daemon \u522B\u540D\uFF08\u4E5F\u53EF\u7528 AITABLE_RELAY_NAME\uFF09").option("--workspace-root <dir>","\u5DE5\u4F5C\u533A\u6839\u76EE\u5F55\uFF08\u4E5F\u53EF\u7528 AITABLE_RELAY_WORKSPACE_ROOT\uFF09").option("--max-tasks <n>","\u672C\u673A\u5E76\u53D1\u6267\u884C\u4E0A\u9650\uFF0C\u9ED8\u8BA4 1\uFF08\u4E5F\u53EF\u7528 AITABLE_RELAY_MAX_TASKS\uFF09").option("--max-workflows <n>","\u672C\u673A\u53EF\u540C\u65F6\u8FD0\u884C\u7684\u5DE5\u4F5C\u6D41\u5F15\u64CE\u6570\uFF0C\u9ED8\u8BA4 3\uFF1B0 = \u4E0D\u8BA4\u9886\u5DE5\u4F5C\u6D41\uFF08\u4E5F\u53EF\u7528 AITABLE_RELAY_MAX_WORKFLOWS\uFF09").option("--trace-http-port <port>","\u672C\u673A\u53EA\u8BFB trace HTTP \u7AEF\u53E3\uFF0C\u9ED8\u8BA4 8790\uFF08\u88AB\u5360\u81EA\u52A8\u5411\u4E0A\u907F\u8BA9\uFF09\uFF1B0/off \u5173\u95ED\uFF08\u4E5F\u53EF\u7528 AITABLE_RELAY_TRACE_HTTP_PORT\uFF09").option("--trace-http-host <host>","\u672C\u5730 trace HTTP \u76D1\u542C\u5730\u5740\uFF0C\u9ED8\u8BA4 127.0.0.1\uFF08\u4E5F\u53EF\u7528 AITABLE_RELAY_TRACE_HTTP_HOST\uFF09").option("--trace-buffer-size <n>","\u672C\u5730 trace \u4FDD\u7559\u6700\u8FD1 run \u6570\uFF0C\u9ED8\u8BA4 20\uFF08\u4E5F\u53EF\u7528 AITABLE_RELAY_TRACE_BUFFER_SIZE\uFF09").option("--trace-events-per-run <n>","\u6BCF\u4E2A run \u4FDD\u7559\u6700\u8FD1 agent event \u6570\uFF0C\u9ED8\u8BA4 500\uFF08\u4E5F\u53EF\u7528 AITABLE_RELAY_TRACE_EVENTS_PER_RUN\uFF09").option("--trace-chat","\u5728\u672C\u673A trace HTTP \u670D\u52A1\u4E0A\u5F00\u542F Local Chat \u5199\u63A5\u53E3\uFF08Task D\uFF0C\u9ED8\u8BA4\u5173\uFF1B\u4E5F\u53EF\u7528 AITABLE_RELAY_TRACE_CHAT=1\uFF09").action(t=>{try{Ie(t)}catch(r){ia.error("cli","relay \u542F\u52A8\u5931\u8D25",{error:r instanceof Error?r.message:String(r)}),process.exit(1)}})}a(pn,"registerRelayCommand");import{loadSettings as fn,loadWorkflowTemplate as aa,checkWorkflowRecipes as ca,Tracer as la}from"aitable-workflow-core";import da from"path";function mn(n,e){n.command("inspect [recordId]").description("\u67E5\u770B\u5DE5\u5355\u6267\u884C trace\uFF1B\u6216\u7528 --recipes / --validate \u67E5\u770B\u6821\u9A8C recipe schema \u4E0E workflow \u5BF9\u9F50").option("-c, --config <path>","\u914D\u7F6E\u6587\u4EF6\u8DEF\u5F84",e.defaultConfig).option("-s, --step <stepId>","\u67E5\u770B\u7279\u5B9A\u6B65\u9AA4").option("-l, --latest","\u67E5\u770B\u6700\u8FD1\u6267\u884C").option("-n, --limit <number>","\u6700\u591A\u663E\u793A\u6761\u6570","10").option("--recipes","\u5217\u51FA\u5404\u6B65\u9AA4 recipe \u7684 input / output / config schema\u4E0E step \u914D\u7F6E").option("--validate","\u6821\u9A8C step.config / input_mapping / output_mapping \u662F\u5426\u7B26\u5408 recipe schema").option("-w, --workflow <id>","\u591A\u5DE5\u4F5C\u6D41\u6A21\u5F0F\uFF1A\u6307\u5B9A\u5DE5\u4F5C\u6D41 ID\uFF08\u7F3A\u7701\u53D6\u7B2C\u4E00\u4E2A\uFF09").action(async(t,r)=>{try{if(r.recipes||r.validate){await ua(r);return}let o=await fn(r.config),s=da.resolve(o.configDir,o.agent.trace_dir),i=new la(s),c=parseInt(r.limit,10)||10,l;if(r.latest||!t){if(l=await i.getLatestTraces(c),l.length===0){console.log("\u26A0\uFE0F \u6682\u65E0 trace \u8BB0\u5F55\u3002\u8FD0\u884C `run` \u547D\u4EE4\u540E\u518D\u67E5\u770B\u3002");return}console.log(`
|
|
564
671
|
\u{1F4C4} \u6700\u8FD1 ${l.length} \u6761\u6267\u884C\u8BB0\u5F55:
|
|
565
|
-
`)}else{if(l=await i.getTraces(t),l.length===0){console.log(`\u26A0\uFE0F \u672A\u627E\u5230\u5DE5\u5355 ${t} \u7684 trace \u8BB0\u5F55\u3002`);return}
|
|
672
|
+
`)}else{if(l=await i.getTraces(t),l.length===0){console.log(`\u26A0\uFE0F \u672A\u627E\u5230\u5DE5\u5355 ${t} \u7684 trace \u8BB0\u5F55\u3002`);return}r.step&&(l=l.filter(d=>d.step_id===r.step)),console.log(`
|
|
566
673
|
\u{1F4C4} \u5DE5\u5355 ${t} \u7684\u6267\u884C\u5386\u53F2 (${l.length} \u6B65):
|
|
567
|
-
`)}for(let d of l){let p=d.status==="success"?"\u2705":d.status==="failed"?"\u274C":"\u23F8\uFE0F",
|
|
568
|
-
\u{1F4CB} \u5DE5\u4F5C\u6D41\u300C${
|
|
569
|
-
`);for(let i of s){let
|
|
570
|
-
\u2705 \u5DE5\u4F5C\u6D41\u300C${
|
|
571
|
-
`);else{let i=
|
|
572
|
-
\u6821\u9A8C\u7ED3\u679C\uFF1A${i.length} \u4E2A\u9519\u8BEF\uFF0C${
|
|
573
|
-
`);for(let l of
|
|
674
|
+
`)}for(let d of l){let p=d.status==="success"?"\u2705":d.status==="failed"?"\u274C":"\u23F8\uFE0F",f=(d.duration_ms/1e3).toFixed(1);console.log(`${p} [${d.step_id}] ${d.step_name} \u2014 ${f}s \u2014 ${d.status.toUpperCase()}`);for(let[u,m]of d.llm_calls.entries()){let h=u===d.llm_calls.length-1,v=h?" \u2514\u2500":" \u251C\u2500",g=h?" ":" \u2502 ",E=(m.duration_ms/1e3).toFixed(1);console.log(`${v} LLM: ${m.model} (${E}s)`),console.log(`${g}Input: ${m.prompt_summary.slice(0,80)}${m.prompt_summary.length>80?"...":""}`),console.log(`${g}Output: ${m.response_summary.slice(0,100)}${m.response_summary.length>100?"...":""}`)}if(Object.keys(d.outputs).length>0){let u=Object.entries(d.outputs).map(([m,h])=>`${m}=${typeof h=="string"?h.slice(0,50):JSON.stringify(h)}`).join(", ");console.log(` \u2514\u2500 Outputs: ${u}`)}d.error&&console.log(` \u2514\u2500 Error: ${d.error}`),console.log()}}catch(o){console.error(`\u2717 inspect \u5931\u8D25: ${o instanceof Error?o.message:String(o)}`),process.exit(1)}})}a(mn,"registerInspectCommand");async function ua(n){let e=await fn(n.config),t=n.workflow?e.workflowEntries.find(i=>i.id===n.workflow):e.workflowEntries[0];t||(console.error(`\u2717 \u672A\u627E\u5230\u5DE5\u4F5C\u6D41\u300C${n.workflow}\u300D\u3002\u53EF\u7528\uFF1A${e.workflowEntries.map(i=>i.id).join(", ")}`),process.exit(1));let r=await aa(t.templatePath,{envSource:e.envSource}),{issues:o,rows:s}=await ca(t.recipeDir,r);if(n.recipes){console.log(`
|
|
675
|
+
\u{1F4CB} \u5DE5\u4F5C\u6D41\u300C${r.meta.name}\u300D(${t.id}) \u7684 recipe schema:
|
|
676
|
+
`);for(let i of s){let c=i.configSummary.length>0?i.configSummary.join(", "):"(none)",l=i.loaded?"":" \u26A0 \u52A0\u8F7D\u5931\u8D25";console.log(` [${i.stepId} \u2192 ${i.recipeId}]${l}`),console.log(` config: ${c}`),console.log()}}if(n.validate)if(o.length===0)console.log(`
|
|
677
|
+
\u2705 \u5DE5\u4F5C\u6D41\u300C${r.meta.name}\u300D(${t.id}) \u5168\u90E8\u6B65\u9AA4\u6821\u9A8C\u901A\u8FC7
|
|
678
|
+
`);else{let i=o.filter(l=>l.level==="error"),c=o.filter(l=>l.level==="warn");console.log(`
|
|
679
|
+
\u6821\u9A8C\u7ED3\u679C\uFF1A${i.length} \u4E2A\u9519\u8BEF\uFF0C${c.length} \u4E2A\u8B66\u544A
|
|
680
|
+
`);for(let l of o){let d=l.level==="error"?"\u274C":"\u26A0\uFE0F ";console.log(` ${d} [${l.stepId} \u2192 ${l.recipeId}] ${l.message}`)}console.log(),i.length>0&&process.exit(1)}}a(ua,"runRecipeInspect");import{runKbCompileCommand as pa,runKbUpdateCommand as fa,runKbStatusCommand as ma,runKbIngestCommand as ga,runKbCleanupCommand as ha}from"aitable-workflow-core";function gn(n,e){let t=n.command("kb").description("\u77E5\u8BC6\u5E93(LLM-Wiki)\u7F16\u8BD1\u4E0E\u72B6\u6001\u7BA1\u7406");t.command("compile [collections...]").description("\u7F16\u8BD1\u77E5\u8BC6\u5E93\u4E3A wiki\uFF08\u4E0D\u6307\u5B9A collection \u65F6\u7F16\u8BD1\u89D2\u8272\u58F0\u660E\u7684\u5168\u90E8\uFF09").option("-c, --config <path>","\u914D\u7F6E\u6587\u4EF6\u8DEF\u5F84",e.defaultConfig).option("--full","\u5F3A\u5236\u5168\u91CF\u91CD\u7F16\u8BD1").action(async(r,o)=>{try{await pa(r,o)}catch(s){console.error(`\u2717 kb compile \u5931\u8D25: ${s instanceof Error?s.message:String(s)}`),process.exit(1)}}),t.command("update [collections...]").description("\u6E90\u6587\u6863\u53D8\u66F4\u540E\u89E6\u53D1\u589E\u91CF\u7F16\u8BD1\uFF08\u672A\u53D8\u66F4\u5219\u8DF3\u8FC7\uFF09").option("-c, --config <path>","\u914D\u7F6E\u6587\u4EF6\u8DEF\u5F84",e.defaultConfig).action(async(r,o)=>{try{await fa(r,o)}catch(s){console.error(`\u2717 kb update \u5931\u8D25: ${s instanceof Error?s.message:String(s)}`),process.exit(1)}}),t.command("status [collections...]").description("\u67E5\u770B\u77E5\u8BC6\u5E93\u7F16\u8BD1\u72B6\u6001\uFF08\u7F16\u8BD1\u4E2D/\u5B8C\u6210/\u5931\u8D25 + \u6E90\u662F\u5426\u5DF2\u53D8\u66F4\uFF09").option("-c, --config <path>","\u914D\u7F6E\u6587\u4EF6\u8DEF\u5F84",e.defaultConfig).action(async(r,o)=>{try{await ma(r,o)}catch(s){console.error(`\u2717 kb status \u5931\u8D25: ${s instanceof Error?s.message:String(s)}`),process.exit(1)}}),t.command("ingest <url-or-path>").description("\u5BFC\u5165\u6587\u6863\u5230 wiki \u76EE\u5F55\uFF08\u652F\u6301\u9489\u9489 URL \u6216\u672C\u5730\u8DEF\u5F84\uFF0Cdocx/pdf \u81EA\u52A8\u8F6C md\uFF09").option("-o, --output <dir>","\u8F93\u51FA\u76EE\u5F55\uFF08\u9ED8\u8BA4 ./wiki\uFF09").option("-t, --type <type>","\u6E90\u7C7B\u578B: dingtalk-doc\uFF08\u4E0D\u4F20\u5219\u81EA\u52A8\u8BC6\u522B\uFF09").option("--flat","\u4E0D\u4FDD\u7559\u8FDC\u7AEF\u76EE\u5F55\u7ED3\u6784\uFF08\u6240\u6709\u6587\u6863\u5E73\u94FA\u5230\u8F93\u51FA\u76EE\u5F55\uFF09").option("--force","\u5F3A\u5236\u91CD\u65B0\u62C9\u53D6\u6240\u6709\u6587\u6863\uFF08\u5FFD\u7565\u589E\u91CF\u5224\u65AD\uFF09").option("--compile","\u5BFC\u5165\u540E\u81EA\u52A8\u89E6\u53D1 kb compile").option("-c, --config <path>","\u914D\u7F6E\u6587\u4EF6\u8DEF\u5F84",e.defaultConfig).option("--timeout <ms>","\u5355\u6587\u6863\u8BF7\u6C42\u8D85\u65F6\uFF08\u6BEB\u79D2\uFF09").action(async(r,o)=>{try{await ga(r,o)}catch(s){console.error(`\u2717 kb ingest \u5931\u8D25: ${s instanceof Error?s.message:String(s)}`),process.exit(1)}}),t.command("cleanup <collection>").description("\u6E05\u7406\u77E5\u8BC6\u5E93\u4E2D\u7684\u5B64\u513F\u6587\u7AE0\uFF08\u6E90\u884C\u5DF2\u5220\u4F46 articles/ \u8FD8\u5728\uFF09").option("-c, --config <path>","\u914D\u7F6E\u6587\u4EF6\u8DEF\u5F84",e.defaultConfig).action(async(r,o)=>{try{await ha(r,o)}catch(s){console.error(`\u2717 kb cleanup \u5931\u8D25: ${s instanceof Error?s.message:String(s)}`),process.exit(1)}})}a(gn,"registerKbCommands");import vt from"path";import{BotProvisioner as va,BotProvisionError as yn,DwsDevRunner as wt,buildBotApprovalReportLines as wa,defaultProvisionStatePath as yt,groupEntriesOf as ya,loadProvisionState as kn,resolveConfigPath as kt,validateProvisionName as ka}from"aitable-workflow-core";import{logger as hn}from"aitable-workflow-core";function vn(n){for(let e of n){let t=e.title?`\u300C${e.title}\u300D${e.openConversationId}`:e.openConversationId;e.outcome==="added"?console.log(`
|
|
574
681
|
\u2705 \u7FA4 ${t}\uFF1A\u672C\u6B21\u5DF2\u771F\u5B9E\u8C03\u7528 add-bot \u5165\u7FA4${e.robotName?`\uFF08\u673A\u5668\u4EBA\u663E\u793A\u540D=${e.robotName}\uFF09`:""}\u3002`):e.source==="server"?console.log(`
|
|
575
682
|
\u2139\uFE0F \u7FA4 ${t}\uFF1A\u670D\u52A1\u7AEF\u786E\u8BA4\u8BE5\u7FA4\u5DF2\u5B89\u88C5\u6B64\u673A\u5668\u4EBA\uFF08500043\uFF09\uFF0C\u89C6\u540C\u5165\u7FA4\u6210\u529F\u3002`):(console.log(`
|
|
576
|
-
\u2139\uFE0F \u7FA4 ${t}\uFF1A\u5DF2\u5728\u7FA4\u53F0\u8D26\uFF08addedAt=${e.addedAt??"?"}\uFF09\uFF0C\u672C\u6B21\u672A\u53D1\u8D77\u4EFB\u4F55 API \u8C03\u7528\u3002`),console.log(" \u6CE8\u610F\uFF1A\u82E5\u673A\u5668\u4EBA\u66FE\u88AB\u624B\u52A8\u79FB\u51FA\u7FA4\uFF0C\u91CD\u8DD1\u672C\u547D\u4EE4\u4E0D\u4F1A\u91CD\u65B0\u6DFB\u52A0\uFF1B\u4EE5\u7FA4\u8BBE\u7F6E\u9875\u6216\u7FA4\u91CC @ \u5B9E\u6D4B\u4E3A\u51C6\u3002"))}}
|
|
577
|
-
\u2705 \u51ED\u636E\u5DF2\u7ED1\u5B9A\uFF08bound \u76F8\uFF09\u3002`),console.log(` appKey=${
|
|
683
|
+
\u2139\uFE0F \u7FA4 ${t}\uFF1A\u5DF2\u5728\u7FA4\u53F0\u8D26\uFF08addedAt=${e.addedAt??"?"}\uFF09\uFF0C\u672C\u6B21\u672A\u53D1\u8D77\u4EFB\u4F55 API \u8C03\u7528\u3002`),console.log(" \u6CE8\u610F\uFF1A\u82E5\u673A\u5668\u4EBA\u66FE\u88AB\u624B\u52A8\u79FB\u51FA\u7FA4\uFF0C\u91CD\u8DD1\u672C\u547D\u4EE4\u4E0D\u4F1A\u91CD\u65B0\u6DFB\u52A0\uFF1B\u4EE5\u7FA4\u8BBE\u7F6E\u9875\u6216\u7FA4\u91CC @ \u5B9E\u6D4B\u4E3A\u51C6\u3002"))}}a(vn,"printGroupOutcomes");function Rn(n,e,t={}){let r=t.exit??(s=>process.exit(s)),o=n.command("bot").description("\u9489\u9489\u673A\u5668\u4EBA provisioning\uFF08\u5EFA\u53F7 / \u51ED\u636E\u7ED1\u5B9A / \u53D1\u5E03\u5BA1\u6279 / \u62C9\u7FA4\uFF09");o.command("provision").description("\u786E\u5B9A\u6027\u5EFA\u53F7\u5E76\u7ED1\u5B9A\u51ED\u636E\uFF08\u5E42\u7B49\u3001\u53EF\u65AD\u70B9\u7EED\u8DD1\uFF1B--publish/--group \u8D70\u4EBA\u5BA1\u4E0E\u62C9\u7FA4\u76F8\uFF09").requiredOption("--name <name>","\u5E94\u7528\u540D\uFF08\u4F01\u4E1A\u5185\u552F\u4E00\uFF0C2-20 \u5B57\uFF09").option("--robot-name <robotName>","\u673A\u5668\u4EBA\u663E\u793A\u540D\uFF08\u7F3A\u7701\u540C --name\uFF09").option("--desc <desc>","\u5E94\u7528\u63CF\u8FF0\uFF08\u2264200 \u5B57\uFF09").option("--group <group>","\u62C9\u7FA4\u76EE\u6807\uFF1AopenConversationId \u6216\u7FA4\u540D\uFF0C\u9017\u53F7\u5206\u9694\u591A\u7FA4\uFF08\u9700\u5DF2\u5B8C\u6210 publish \u76F8\uFF1B\u5DF2\u5728\u7FA4\u53F0\u8D26\u7684\u7FA4\u96F6\u8C03\u7528\u8DF3\u8FC7\uFF09").option("--publish","\u8FDB\u5165\u53D1\u5E03\u76F8\uFF08\u771F\u5B9E\u6253\u6270\u7BA1\u7406\u5458\u5BA1\u6279\uFF0C\u9700\u914D\u5408 --approver-user-id \u786E\u8BA4\uFF09").option("--approver-user-id <userId>","\u5BA1\u6279\u4EBA userId\uFF08\u5019\u9009\u7531 check-approval \u5217\u51FA\uFF1B\u4EBA\u5BA1\u95E8\u4E0D\u5F97\u9759\u9ED8\u4EE3\u9009\uFF09").option("--state-file <path>","\u72B6\u6001\u6587\u4EF6\u8DEF\u5F84\uFF08\u7F3A\u7701 <configDir>/.aitable/provision-state.json\uFF09").option("-c, --config <path>","\u914D\u7F6E\u6587\u4EF6\u8DEF\u5F84\uFF08\u7528\u4E8E\u5B9A\u4F4D configDir\uFF09",e.defaultConfig).option("--yes","\u4E0E dws \u8BED\u4E49\u5BF9\u9F50\uFF1A\u8DF3\u8FC7\u786E\u8BA4\uFF08provision \u5168\u7A0B\u975E\u4EA4\u4E92\uFF0C\u5199\u64CD\u4F5C\u5DF2\u5E26 --yes\uFF09").action(async s=>{try{let i=await Ra(s,e,t);i!==0&&r(i)}catch(i){ht(i),r(1)}}),o.command("status").description("\u67E5\u770B provision \u76F8\u4F4D / \u53D1\u5E03\u5BA1\u6279\u72B6\u6001 / \u5BA1\u6279\u4EBA\u5019\u9009\u4E0E\u50AC\u529E\u547D\u4EE4\u6A21\u677F").option("--state-file <path>","\u72B6\u6001\u6587\u4EF6\u8DEF\u5F84\uFF08\u7F3A\u7701 <configDir>/.aitable/provision-state.json\uFF09").option("-c, --config <path>","\u914D\u7F6E\u6587\u4EF6\u8DEF\u5F84\uFF08\u7528\u4E8E\u5B9A\u4F4D configDir\uFF09",e.defaultConfig).option("--refresh","\u5B9E\u65F6\u67E5\u8BE2 dws\uFF08version status + check-approval\uFF09\uFF0C\u800C\u975E\u53EA\u8BFB\u72B6\u6001\u6587\u4EF6").action(async s=>{try{let i=await Ca(s,e,t);i!==0&&r(i)}catch(i){ht(i),r(1)}});for(let[s,i]of[["disable","\u505C\u7528"],["enable","\u542F\u7528"]])o.command(s).description(`${i}\u673A\u5668\u4EBA\u80FD\u529B\u6216\u6574\u4E2A\u5E94\u7528\uFF08\u53EF\u9006\uFF1B--scope app \u4F5C\u7528\u4E8E\u6574\u4E2A\u5E94\u7528\uFF09`).option("--scope <scope>","\u4F5C\u7528\u8303\u56F4\uFF1Arobot\uFF08\u9ED8\u8BA4\uFF0C\u4EC5\u673A\u5668\u4EBA\u80FD\u529B\uFF09| app\uFF08\u6574\u4E2A\u5E94\u7528\uFF09","robot").option("--unified-app-id <id>","\u76EE\u6807\u5E94\u7528 unifiedAppId\uFF08\u7F3A\u7701\u4ECE\u72B6\u6001\u6587\u4EF6\u8BFB\uFF09").option("--state-file <path>","\u72B6\u6001\u6587\u4EF6\u8DEF\u5F84\uFF08\u7F3A\u7701 <configDir>/.aitable/provision-state.json\uFF09").option("-c, --config <path>","\u914D\u7F6E\u6587\u4EF6\u8DEF\u5F84\uFF08\u7528\u4E8E\u5B9A\u4F4D configDir\uFF09",e.defaultConfig).action(async c=>{try{let l=await Aa(s,c,e,t);l!==0&&r(l)}catch(l){ht(l),r(1)}})}a(Rn,"registerBotCommands");async function Ra(n,e,t){let r=ka(n.name);if(r)return console.error(`\u274C ${r}`),1;let o=vt.dirname(await kt(n.config??e.defaultConfig)),s=n.stateFile??yt(o);n.publish&&!n.approverUserId&&console.log("\u2139 --publish \u672A\u6307\u5B9A --approver-user-id\uFF1A\u82E5\u7EC4\u7EC7\u5BA1\u6279\u7B56\u7565\u9700\u9009\u4EBA\uFF0C\u5C06\u5217\u51FA\u5019\u9009\u540E\u505C\u4E0B\uFF0C\u7531\u4F60\u663E\u5F0F\u786E\u8BA4\u3002");let i=t.createProvisioner?.()??new va({runner:new wt}),c={name:n.name,robotName:n.robotName,desc:n.desc,stateFile:s,publish:n.publish,approverUserId:n.approverUserId,group:n.group};console.log(`\u{1F916} \u5F00\u59CB provision\u300C${n.name}\u300D\uFF08\u72B6\u6001\u6587\u4EF6: ${s}\uFF09`);let l=await i.provision(c);return ba(l,{stateFile:s})}a(Ra,"runProvision");function ba(n,e){switch(n.status){case"bound":{console.log(`
|
|
684
|
+
\u2705 \u51ED\u636E\u5DF2\u7ED1\u5B9A\uFF08bound \u76F8\uFF09\u3002`),console.log(` appKey=${n.state.clientId??"?"}`),console.log(` AppSecret \u4E0D\u56DE\u663E\uFF0C\u590D\u53D6: dws dev app credentials get --unified-app-id ${n.state.unifiedAppId??"<unifiedAppId>"}`),console.log(" \u51ED\u636E\u843D\u6CD5\u4E8C\u9009\u4E00\uFF08\u4E0D\u8981\u4E24\u5904\u90FD\u5199\uFF09\uFF1A"),console.log(" \xB7 \u5355\u4E00\u673A\u5668\u4EBA \u2192 \u5199\u5165 `.env`\uFF0C\u914D\u7F6E\u91CC\u7528 `${env.X}` \u5F15\u7528\uFF1B"),console.log(" \xB7 \u591A\u7FA4/\u591A\u673A\u5668\u4EBA/\u9700\u8FD0\u8425\u81EA\u7EF4\u62A4 \u2192 \u5199\u5165 AI \u8868\u683C\u7FA4\u914D\u7F6E\u8868\uFF0C\u7531 config-sync \u53D1\u5E03\u6210 `globalVar.robot_creds`\u3002"),console.log(" \u72B6\u6001\u6587\u4EF6:",e.stateFile),console.log("\n\u26A0\uFE0F Stream \u5355\u6D3E\u53D1\u4E92\u65A5\uFF1A\u52FF\u5BF9\u540C\u4E00\u673A\u5668\u4EBA\u540C\u65F6\u8FD0\u884C `dws dev connect`\uFF0C\u5426\u5219\u6D88\u606F\u53EA\u6D3E\u53D1\u5176\u4E00\u3002"),console.log("\u{1F4A1} \u771F\u5B9E\u7528\u6237\u6D41\u91CF\uFF08\u7FA4\u91CC @bot / \u5355\u804A\u53D1\u73B0\uFF09\u9700\u516C\u5F00\u53D1\u5E03\uFF1A`aitable-workflow bot provision --name <\u540C\u540D> --publish`");break}case"publish_pending":{console.log(`
|
|
578
685
|
\u23F3 \u53D1\u5E03\u5DF2\u63D0\u4EA4\uFF0C\u7B49\u5F85\u7BA1\u7406\u5458\u5BA1\u6279\uFF08publish_pending \u76F8\uFF09\u3002`),console.log(" \u67E5\u770B\u8FDB\u5EA6\u4E0E\u50AC\u529E: aitable-workflow bot status --refresh");break}case"published":{console.log(`
|
|
579
|
-
\u2705 \u5DF2\u53D1\u5E03\uFF08published \u76F8\uFF09\u2014\u2014\u771F\u5B9E\u7528\u6237\u6D41\u91CF\u53EF\u7528\u3002`),console.log("\u{1F4A1} \u62C9\u7FA4: `aitable-workflow bot provision --name <\u540C\u540D> --group <openConversationId|\u7FA4\u540D>`\uFF08\u591A\u7FA4\u9017\u53F7\u5206\u9694\uFF09");break}case"grouped":{if(
|
|
580
|
-
\u2705 grouped \u76F8\uFF1A\u7FA4\u53F0\u8D26\u5DF2\u6709 ${t} \u4E2A\u7FA4\u3002\u672C\u6B21\u672A\u4F20 --group\uFF0C\u672A\u53D1\u8D77\u4EFB\u4F55\u62C9\u7FA4\u8C03\u7528\u3002`);break}
|
|
581
|
-
\u26D4 \u516C\u5F00\u53D1\u5E03\u9700\u771F\u4EBA\u5BA1\u6279\uFF0C\u4E14\u672C\u7EC4\u7EC7\u7B56\u7565\u8981\u6C42\u663E\u5F0F\u9009\u5BA1\u6279\u4EBA\uFF08\u4EBA\u5BA1\u95E8\u4E0D\u5F97\u9759\u9ED8\u4EE3\u9009\uFF09\u3002`),console.error(" \u5BA1\u6279\u4EBA\u5019\u9009\uFF08\u6765\u81EA check-approval\uFF09:");for(let t of
|
|
582
|
-
\u274C provision \u5931\u8D25: ${
|
|
686
|
+
\u2705 \u5DF2\u53D1\u5E03\uFF08published \u76F8\uFF09\u2014\u2014\u771F\u5B9E\u7528\u6237\u6D41\u91CF\u53EF\u7528\u3002`),console.log("\u{1F4A1} \u62C9\u7FA4: `aitable-workflow bot provision --name <\u540C\u540D> --group <openConversationId|\u7FA4\u540D>`\uFF08\u591A\u7FA4\u9017\u53F7\u5206\u9694\uFF09");break}case"grouped":{if(n.groups.length===0){let t=Object.keys(ya(n.state)).length;console.log(`
|
|
687
|
+
\u2705 grouped \u76F8\uFF1A\u7FA4\u53F0\u8D26\u5DF2\u6709 ${t} \u4E2A\u7FA4\u3002\u672C\u6B21\u672A\u4F20 --group\uFF0C\u672A\u53D1\u8D77\u4EFB\u4F55\u62C9\u7FA4\u8C03\u7528\u3002`);break}vn(n.groups),console.log("\u{1F4A1} add-bot \u7684 success \u53EA\u662F\u53D7\u7406\u4FE1\u53F7\uFF08dws \u65E0\u5728\u7FA4\u5217\u8868\u67E5\u8BE2\u63A5\u53E3\uFF09\uFF1A\u8BF7\u5230\u7FA4\u8BBE\u7F6E\u6838\u5BF9\u673A\u5668\u4EBA\u5728\u7FA4\u3002");break}case"approver_required":{console.error(`
|
|
688
|
+
\u26D4 \u516C\u5F00\u53D1\u5E03\u9700\u771F\u4EBA\u5BA1\u6279\uFF0C\u4E14\u672C\u7EC4\u7EC7\u7B56\u7565\u8981\u6C42\u663E\u5F0F\u9009\u5BA1\u6279\u4EBA\uFF08\u4EBA\u5BA1\u95E8\u4E0D\u5F97\u9759\u9ED8\u4EE3\u9009\uFF09\u3002`),console.error(" \u5BA1\u6279\u4EBA\u5019\u9009\uFF08\u6765\u81EA check-approval\uFF09:");for(let t of n.candidates)console.error(` - ${t.name??"(\u672A\u77E5)"} userId=${t.userId}${t.mainAdmin?"\uFF08\u4E3B\u7BA1\u7406\u5458\uFF09":""}`);return console.error(" \u786E\u8BA4\u540E\u91CD\u8DD1: aitable-workflow bot provision --name <\u540C\u540D> --publish --approver-user-id <userId>"),2}case"failed":return n.groups&&n.groups.length>0&&vn(n.groups),console.error(`
|
|
689
|
+
\u274C provision \u5931\u8D25: ${n.message}`),console.error(" \uFF08\u72B6\u6001\u6587\u4EF6\u5DF2\u4FDD\u7559\u8FDB\u5EA6\uFF0C\u4FEE\u590D\u540E\u53EF\u65AD\u70B9\u7EED\u8DD1: \u91CD\u8DD1\u540C\u4E00\u547D\u4EE4\uFF09"),1}return 0}a(ba,"printProvisionResult");async function Ca(n,e,t){let r=vt.dirname(await kt(n.config??e.defaultConfig)),o=n.stateFile??yt(r),s=await kn(o),i,c=null,l=null;if(n.refresh&&s?.unifiedAppId&&s.versionId){let p=t.createRunner?.()??new wt;try{i=(await p.versionStatus(s.unifiedAppId,s.versionId)).versionStatus}catch(f){l=wn(f)}if(!l)try{c=await p.checkApproval(s.unifiedAppId,s.versionId)}catch(f){l=wn(f)}}let d=wa({state:s,versionStatus:i,approval:c,error:l});return console.log(d.map(p=>` ${p}`).join(`
|
|
583
690
|
`)),console.log(`
|
|
584
|
-
\u72B6\u6001\u6587\u4EF6: ${
|
|
585
|
-
\u2705 \u5DF2${i}${l}\u3002`),
|
|
586
|
-
\u274C ${
|
|
587
|
-
\u274C ${e}`)}}
|
|
691
|
+
\u72B6\u6001\u6587\u4EF6: ${o}`),s&&!n.refresh&&(s.phase==="publish_pending"||s.phase==="version_created")&&console.log(" \u63D0\u793A: \u52A0 --refresh \u5B9E\u65F6\u67E5\u8BE2\u5BA1\u6279\u72B6\u6001\u4E0E\u5019\u9009\u3002"),s?0:1}a(Ca,"runStatus");function wn(n){return n instanceof yn?`${n.message}\uFF08${n.guidance}\uFF09`:n instanceof Error?n.message:String(n)}a(wn,"describeError");async function Aa(n,e,t,r){let o=e.scope??"robot";if(o!=="robot"&&o!=="app")return console.error(`\u274C --scope \u53EA\u652F\u6301 robot | app\uFF0C\u6536\u5230: ${o}`),1;let s=e.unifiedAppId?.trim();if(!s){let p=vt.dirname(await kt(e.config??t.defaultConfig)),f=e.stateFile??yt(p);if(s=(await kn(f))?.unifiedAppId??void 0,!s)return console.error(`\u274C \u65E0\u6CD5\u786E\u5B9A\u76EE\u6807\u5E94\u7528\uFF1A\u72B6\u6001\u6587\u4EF6\u65E0 unifiedAppId\uFF08${f}\uFF09\uFF0C\u8BF7\u7528 --unified-app-id \u663E\u5F0F\u6307\u5B9A\u3002`),1}let i=n==="disable"?"\u505C\u7528":"\u542F\u7528",c=r.createRunner?.()??new wt,l=o==="app"?"\u6574\u4E2A\u5E94\u7528":"\u673A\u5668\u4EBA\u80FD\u529B";return console.log(`\u{1F916} ${i}${l}\uFF08unifiedAppId=${s}\uFF09`),o==="app"&&n==="disable"&&console.log("\u2139 --scope app \u4F1A\u505C\u7528\u6574\u4E2A\u5E94\u7528\uFF08\u673A\u5668\u4EBA/\u7F51\u9875\u5E94\u7528\u7B49\u5168\u90E8\u4E0D\u53EF\u7528\uFF09\uFF1B\u53EA\u60F3\u505C\u673A\u5668\u4EBA\u7528\u9ED8\u8BA4 --scope robot\u3002"),await{disable:{robot:c.disableRobot.bind(c),app:c.disableApp.bind(c)},enable:{robot:c.enableRobot.bind(c),app:c.enableApp.bind(c)}}[n][o](s),console.log(`
|
|
692
|
+
\u2705 \u5DF2${i}${l}\u3002`),n==="disable"&&(console.log(` \u6062\u590D: ${o==="app"?"aitable-workflow bot enable --scope app":"aitable-workflow bot enable"}\uFF08\u542F\u505C\u53EF\u9006\uFF1B.env \u51ED\u636E\u4E0E\u72B6\u6001\u6587\u4EF6\u4E0D\u53D7\u5F71\u54CD\uFF09`),console.log(" \u26A0\uFE0F \u505C\u7528\u540E Stream \u5EFA\u8054/\u6D88\u606F\u6536\u53D1\u4F1A\u5931\u8D25\uFF1B\u8FD0\u884C\u4E2D\u7684\u5F15\u64CE\u4F1A\u6301\u7EED\u62A5\u9519\u76F4\u5230\u6062\u590D\u3002")),0}a(Aa,"runToggle");function ht(n){if(n instanceof yn)hn.error("cli","bot \u547D\u4EE4\u5931\u8D25",{kind:n.kind}),console.error(`
|
|
693
|
+
\u274C ${n.message}`),console.error(` \u21B3 ${n.guidance}`);else{let e=n instanceof Error?n.message:String(n);hn.error("cli","bot \u547D\u4EE4\u5931\u8D25",{error:e}),console.error(`
|
|
694
|
+
\u274C ${e}`)}}a(ht,"failWithDiagnostics");var xn=An.dirname(Sa(import.meta.url));Cn({override:!1,quiet:!0});Cn({path:An.resolve(xn,"..",".env"),override:!1,quiet:!0});var Tn=Et(),Rt=Ue(Tn),Ia=St(Tn);Ea({version:Rt});var y=new xa().name("aitable-workflow").description("\u901A\u7528\u4E1A\u52A1\u6D41\u7A0B\u5F15\u64CE \u2014 \u914D\u7F6E\u9A71\u52A8\u7684 AI \u8868\u683C\u5DE5\u4F5C\u6D41\u81EA\u52A8\u5316").version(Rt).enablePositionalOptions().option("-d, --debug","\u8F93\u51FA debug \u7EA7\u522B\u65E5\u5FD7\uFF08\u542B recipe \u5185\u90E8 log\uFF09\uFF1B\u9700\u5199\u5728\u547D\u4EE4\u540D\u4E4B\u524D").hook("preAction",(n,e)=>{n.opts().debug?bn.setLevel("debug"):(e.name()==="config"||e.parent?.name()==="config")&&bn.setLevel("warn")}).hook("preAction",async(n,e)=>{e.name()!=="init"&&await Ta()}),k={cliDir:xn,version:Rt,packageVersions:Ia,defaultConfig:It};Pt(y,k);_t(y,k);$t(y,k);Mt(y,k);jr(y,k);Dr(y,k);Nr(y,k);qr(y,k);Ct(y,k);zr(y,k);Jr(y,k);Vr(y,k);Kr(y,k);sn(y,k);cn(y,k);un(y,k);an(y,k);pn(y,k);mn(y,k);gn(y,k);Rn(y,k);await y.parseAsync();
|