aitable-workflow-cli 0.1.18 → 0.1.19
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/{chunk-7OC4VJC5.js → chunk-H5ZBCT4K.js} +9 -9
- package/dist/cli.js +43 -43
- package/dist/config-ui-server-B7QFGMVV.js +1 -0
- package/dist/web/assets/{index-R-6AMiob.js → index-C1_J5I2E.js} +31 -31
- package/dist/web/assets/index-DQWzpxYZ.css +1 -0
- package/dist/web/index.html +2 -2
- package/package.json +3 -3
- package/dist/config-ui-server-FTJEAX2E.js +0 -1
- package/dist/web/assets/index-OEpyipM4.css +0 -1
package/dist/cli.js
CHANGED
|
@@ -1,32 +1,32 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import{a as
|
|
3
|
-
\u26A0 \u53EF\u89C6\u5316\u754C\u9762\u5F02\u5E38\uFF0C\u56DE\u9000\u5230\u547D\u4EE4\u884C\u4EA4\u4E92: ${
|
|
4
|
-
`)}}}if(!
|
|
2
|
+
import{a as Ne,b as Ge,l as He}from"./chunk-H5ZBCT4K.js";import"./chunk-XGHRD4FJ.js";import{b as X,d as W,e as ve,f as qe,g as Q}from"./chunk-N2ATMPTO.js";import{a as c}from"./chunk-EI7MMDWY.js";import{config as on}from"dotenv";import{Command as Lr}from"commander";import{logger as nn,activateGlobalDwsOnPath as Mr,initSlsReport as Fr}from"aitable-workflow-core";import{createRequire as cn}from"module";var Ke="aitable-workflow-",ln=/^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?$/;function Ve(){try{return cn(import.meta.url)("../package.json")}catch{return{}}}c(Ve,"loadCliPackageManifest");function ke(r){return r.version??"0.0.0"}c(ke,"resolveCliVersion");function Ye(r){let e=ke(r),t={};r.name?.startsWith(Ke)&&(t[r.name]=e);for(let[n,o]of Object.entries(r.dependencies??{}))n.startsWith(Ke)&&(t[n]=ln.test(o)?o:e);return t}c(Ye,"resolveMonorepoPackageVersions");import rn from"path";import{fileURLToPath as Br}from"url";var Je="./aitable-workflow.config.yml";import{runInit as mn,logger as pn}from"aitable-workflow-core";import dn from"path";function ze(r,e){r.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\u5185\u7F6E\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\u5185\u7F6E\u6A21\u677F\u811A\u624B\u67B6(\u5F53\u524D\u63A8\u8350 support-qa),\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(\u5982 support-qa \u7684 aitable),\u8986\u76D6\u5F0F\u53E0\u52A0\u5230\u5B9E\u4F8B").action(async t=>{try{await mn({config:t.config,force:!!t.force,yes:!!t.yes,template:t.template,profile:t.profile,templatesDir:dn.resolve(e.cliDir,"..","templates"),templatePackageVersions:e.packageVersions,cliVersion:e.version})}catch(n){n instanceof Error&&n.message.includes("cancelled")&&process.exit(0),pn.error("cli","\u521D\u59CB\u5316\u5931\u8D25",{error:n instanceof Error?n.message:String(n)}),process.exit(1)}})}c(ze,"registerInitCommand");import{runMigrate as gn,logger as un}from"aitable-workflow-core";import fn from"path";function Xe(r,e){r.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 gn({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:fn.resolve(e.cliDir,"..","templates"),templatePackageVersions:e.packageVersions,cliVersion:e.version})}catch(n){n instanceof Error&&n.message.includes("cancelled")&&process.exit(0),un.error("cli","migrate \u5931\u8D25",{error:n instanceof Error?n.message:String(n)}),process.exit(1)}})}c(Xe,"registerMigrateCommand");import{runDesignCommand as hn,logger as wn}from"aitable-workflow-core";function Qe(r,e){r.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 hn(t)}catch(n){n instanceof Error&&n.message.includes("cancelled")&&process.exit(0),wn.error("cli","design \u5931\u8D25",{error:n instanceof Error?n.message:String(n)}),process.exit(1)}})}c(Qe,"registerDesignCommand");import{runCheck as yn,runSetupCommand as vn,checkMigrateHint as kn,logger as bn,reportCliEvent as Z,setReportProject as Cn}from"aitable-workflow-core";import et from"path";function be(r){return r.skipConfig||r.skipConfigIfValid&&r.configValid===!0}c(be,"canSkipSetupConfig");function Ze(r){return be(r)?"setup":r.uiEnabled&&r.webAvailable?"web":"cli"}c(Ze,"resolveSetupConfigRoute");function tt(r,e){r.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").action(async t=>{Cn(t.config);let n=Date.now();Z("setup.start",{skipConfig:t.skipConfig===!0,clean:t.clean,kb:t.kb,kbFull:t.kbFull===!0,ui:t.ui!==!1});try{if(await kn(et.dirname(et.resolve(t.config)),e.version),!t.skipConfig){let o=t.ui!==!1,i=!1;if(t.skipConfigIfValid){console.log("\u{1F4CB} \u6B65\u9AA4 1/2\uFF1A\u6821\u9A8C\u9879\u76EE\u914D\u7F6E");let s=await yn({configPath:t.config});if(i=be({skipConfig:!1,skipConfigIfValid:!0,configValid:s.ok}),i){let a=[];s.summary.warnings>0&&a.push(`${s.summary.warnings} \u9879\u8B66\u544A`),s.summary.suggestions>0&&a.push(`${s.summary.suggestions} \u9879\u5EFA\u8BAE`);let l=a.length>0?`\uFF08${a.join("\uFF0C")}\uFF0C\u5747\u4E0D\u963B\u65AD\uFF09`:"";console.log(`\u2713 \u914D\u7F6E\u65E0\u963B\u65AD\u9879${l}\uFF0C\u8DF3\u8FC7\u914D\u7F6E\u754C\u9762\u5E76\u7EE7\u7EED\u642D\u5EFA\u3002`)}else console.log(`\u2139 \u68C0\u6D4B\u5230 ${s.summary.errors} \u9879\u963B\u65AD\uFF0C\u8FDB\u5165\u914D\u7F6E\u73AF\u8282\u3002`)}if(!i&&o){let{hasWebRoot:s,runConfigUI:a}=await import("./config-ui-server-B7QFGMVV.js");if(Ze({skipConfig:!1,skipConfigIfValid:t.skipConfigIfValid===!0,uiEnabled:o,webAvailable:s(),configValid:i})==="web"){console.log("\u{1F4CB} \u6B65\u9AA4 1/2\uFF1A\u53EF\u89C6\u5316\u914D\u7F6E\u754C\u9762");try{await a({configPath:t.config,setupOptions:{clean:t.clean,kb:t.kb,kbFull:t.kbFull}}),Z("setup.finish",{success:!0,route:"web",durationMs:Date.now()-n});return}catch(m){console.warn(`
|
|
3
|
+
\u26A0 \u53EF\u89C6\u5316\u754C\u9762\u5F02\u5E38\uFF0C\u56DE\u9000\u5230\u547D\u4EE4\u884C\u4EA4\u4E92: ${m instanceof Error?m.message:String(m)}
|
|
4
|
+
`)}}}if(!i){console.log("\u{1F4CB} \u6B65\u9AA4 1/2\uFF1A\u6821\u9A8C\u5E76\u8865\u9F50\u9879\u76EE\u914D\u7F6E");let{runConfigCommand:s}=await import("./config-command-HL4O3DHK.js");(await s({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
|
|
8
|
-
`));try{await
|
|
9
|
-
`):
|
|
10
|
-
`):
|
|
11
|
-
\u6B65\u9AA4\u94FE:`);for(let[i,s]of o.orderedStepIds.entries()){let
|
|
12
|
-
\u914D\u7F6E\u6458\u8981:`),console.log(` AI \u8868\u683C: base=${n.tracker.base_id} table=${n.tracker.table_id}`),console.log(` \u5F15\u64CE: ${n.agent.engine}`),console.log(` \u8F6E\u8BE2\u95F4\u9694: ${n.polling.interval_ms}ms`)}catch(n){console.error(`\u2717 \u9A8C\u8BC1\u5931\u8D25: ${n instanceof Error?n.message:String(n)}`),process.exit(1)}})}
|
|
7
|
+
`)}await vn(t),await Z("setup.finish",{success:!0,durationMs:Date.now()-n})}catch(o){bn.error("cli","setup \u5931\u8D25",{error:o instanceof Error?o.message:String(o)}),await Z("setup.finish",{success:!1,error:(o instanceof Error?o.message:String(o)).slice(0,500),durationMs:Date.now()-n}),process.exit(1)}})}c(tt,"registerSetupCommand");import nt from"path";import{createApp as ot,ensureTsxRegistered as Rn,checkMigrateHint as In,logger as R,runCheck as Sn}from"aitable-workflow-core";function An(){let t=[],n=c(()=>{let o=Date.now();for(t.push(o);t.length>0&&o-t[0]>6e4;)t.shift();t.length>=10&&(R.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=>{R.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}),n()}),process.on("unhandledRejection",o=>{R.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}),n()})}c(An,"installLongRunningCrashGuards");function rt(r,e){r.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("--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=>{try{await In(nt.dirname(nt.resolve(t.config)),e.version),An(),await Rn();let n=await Sn({configPath:t.config}),o=!n.ok||n.summary.errors>0,i,s="setup";if(!o)try{s="runtime",i=await ot(t.config,{})}catch(m){R.warn("cli","\u914D\u7F6E\u6821\u9A8C\u901A\u8FC7\u4F46\u88C5\u914D\u5931\u8D25\uFF0C\u56DE\u9000\u5230\u642D\u5EFA\u6A21\u5F0F",{error:m instanceof Error?m.message:String(m)}),s="setup",i=void 0}s==="runtime"&&i?t.skipConfigIfValid?(R.info("cli","\u914D\u7F6E\u5DF2\u5B8C\u6574\uFF0C\u76F4\u63A5\u542F\u52A8\u8FD0\u884C"),i.start().catch(m=>{R.error("cli","\u8FD0\u884C\u542F\u52A8\u5931\u8D25\uFF0C\u53EF\u5728\u63A7\u5236\u53F0\u91CD\u8BD5\u542F\u52A8",{error:m instanceof Error?m.message:String(m)})})):R.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"):R.info("cli","\u914D\u7F6E\u4E0D\u5B8C\u6574\uFF0C\u63A7\u5236\u53F0\u5C06\u5F15\u5BFC\u5B8C\u6210\u642D\u5EFA");let a=!1,l=c(async()=>{a&&(R.warn("cli","\u518D\u6B21\u6536\u5230\u9000\u51FA\u4FE1\u53F7\uFF0C\u5F3A\u5236\u9000\u51FA"),process.exit(1)),a=!0,R.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",l),process.on("SIGTERM",l),await He({configPath:t.config,mode:s,app:i,open:t.open,exitOnSetupError:!1,...s==="runtime"&&t.skipConfigIfValid?{initialRunStatus:{status:"running",since:new Date().toISOString(),lastError:null}}:{},...s==="setup"?{assembleApp:c(m=>ot(m,{}),"assembleApp"),onAppAssembled:c(m=>{i=m,R.info("cli","\u63A7\u5236\u53F0\u5DF2\u5B8C\u6210 setup\u2192runtime \u664B\u5347\uFF0C\u53EF\u5728\u63A7\u5236\u53F0\u542F\u52A8\u8FD0\u884C")},"onAppAssembled")}:{}})}catch(n){R.error("cli","start \u547D\u4EE4\u5931\u8D25",{error:n instanceof Error?n.message:String(n)}),process.exit(1)}})}c(rt,"registerStartCommand");import{createApp as xn,ensureTsxRegistered as En,checkMigrateHint as Tn,logger as D,reportCliEvent as ee,setReportProject as $n}from"aitable-workflow-core";import it from"path";function Pn(){let t=[],n=c(async()=>{let o=Date.now();for(t.push(o);t.length>0&&o-t[0]>6e4;)t.shift();t.length>=10&&(D.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 ee("run.exit",{reason:"crash-loop",crashes:t.length}),process.exit(1))},"recordCrashAndMaybeExit");process.on("uncaughtException",o=>{D.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}),n()}),process.on("unhandledRejection",o=>{D.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}),n()})}c(Pn,"installLongRunningCrashGuards");function st(r,e){r.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").action(async t=>{$n(t.config);try{await Tn(it.dirname(it.resolve(t.config)),e.version),Pn(),await En();let n=t.emitEvents==="ipc"&&typeof process.send=="function",o=await xn(t.config,n?{onRunEvent:c(a=>{process.send?.({type:"run-event",event:a})},"onRunEvent")}:{});ee("run.start",{emitEvents:t.emitEvents??null});let i=!1,s=c(async()=>{i&&(D.warn("cli","\u518D\u6B21\u6536\u5230\u9000\u51FA\u4FE1\u53F7\uFF0C\u5F3A\u5236\u9000\u51FA"),process.exit(1)),i=!0,D.info("cli","\u6536\u5230\u9000\u51FA\u4FE1\u53F7\uFF0C\u6B63\u5728\u7B49\u5F85\u8FDB\u884C\u4E2D\u7684\u4EFB\u52A1\u5B8C\u6210...");try{await o.stop()}finally{await ee("run.exit",{reason:"signal"}),process.exit(0)}},"shutdown");process.on("SIGINT",s),process.on("SIGTERM",s),await o.start()}catch(n){D.error("cli","\u542F\u52A8\u5931\u8D25",{error:n instanceof Error?n.message:String(n)}),await ee("run.exit",{reason:"start-failure",error:(n instanceof Error?n.message:String(n)).slice(0,500)}),process.exit(1)}})}c(st,"registerRunCommand");import{createApp as jn,ensureTsxRegistered as Dn,logger as Ce}from"aitable-workflow-core";function _n(r,e){let t=`\u5DE5\u4F5C\u6D41 ${r} / \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(_n,"formatTriggerOnceResult");function at(r){return new Promise(e=>{r.write("",()=>e())})}c(at,"flushStream");function ct(){return Promise.all([at(process.stdout),at(process.stderr)])}c(ct,"flushOutputs");function lt(r,e){r.command("trigger-once").description("\u5355\u6B21\u89E6\u53D1\u67D0\u4E2A\u5DE5\u4F5C\u6D41\u7684\u4E8B\u4EF6\u6E90 handler \u8DD1\u4E00\u904D\uFF08\u4E0D\u542F\u52A8\u5E38\u9A7B\u5F15\u64CE\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("--json","\u4EE5 JSON \u8F93\u51FA\u7ED3\u679C\uFF08\u4F9B\u811A\u672C\u6D88\u8D39\uFF09").action(async t=>{t.json&&Ce.setSink((n,o)=>process.stderr.write(`${o}
|
|
8
|
+
`));try{await Dn();let o=await(await jn(t.config)).triggerWorkflowOnce(t.workflow,{...t.source?{sourceName:t.source}:{}});t.json?process.stdout.write(`${JSON.stringify({ok:!0,workflowId:t.workflow,...o})}
|
|
9
|
+
`):Ce.info("cli",_n(t.workflow,o)),await ct(),process.exit(0)}catch(n){let o=n instanceof Error?n.message:String(n);t.json?process.stdout.write(`${JSON.stringify({ok:!1,error:o})}
|
|
10
|
+
`):Ce.error("cli","\u89E6\u53D1\u5931\u8D25",{error:o}),await ct(),process.exit(1)}})}c(lt,"registerTriggerCommand");import{loadSettings as On,loadWorkflowTemplate as Ln}from"aitable-workflow-core";function mt(r,e){r.command("validate").description("\u9A8C\u8BC1\u914D\u7F6E\u6587\u4EF6\u548C\u5DE5\u4F5C\u6D41\u6A21\u677F").option("-c, --config <path>","\u914D\u7F6E\u6587\u4EF6\u8DEF\u5F84",e.defaultConfig).action(async t=>{try{let n=await On(t.config);console.log("\u2713 \u914D\u7F6E\u6587\u4EF6\u9A8C\u8BC1\u901A\u8FC7");let o=await Ln(n.workflowTemplatePath,{envSource:n.envSource});console.log(`\u2713 \u5DE5\u4F5C\u6D41\u6A21\u677F\u9A8C\u8BC1\u901A\u8FC7: ${o.meta.name} (${o.orderedStepIds.length} \u6B65)`),console.log(`
|
|
11
|
+
\u6B65\u9AA4\u94FE:`);for(let[i,s]of o.orderedStepIds.entries()){let a=o.steps.find(m=>m.id===s),l=i<o.orderedStepIds.length-1?" \u2192":" \u2713";console.log(` ${i+1}. [${s}] ${a?.name??"?"}${l}`)}console.log(`
|
|
12
|
+
\u914D\u7F6E\u6458\u8981:`),console.log(` AI \u8868\u683C: base=${n.tracker.base_id} table=${n.tracker.table_id}`),console.log(` \u5F15\u64CE: ${n.agent.engine}`),console.log(` \u8F6E\u8BE2\u95F4\u9694: ${n.polling.interval_ms}ms`)}catch(n){console.error(`\u2717 \u9A8C\u8BC1\u5931\u8D25: ${n instanceof Error?n.message:String(n)}`),process.exit(1)}})}c(mt,"registerValidateCommand");import{logger as Mn}from"aitable-workflow-core";function Fn(r,e){if(r.getOptionValueSource("config")!=="default")return e;let t=r.parent?.getOptionValue("config");return typeof t=="string"?t:e}c(Fn,"effectiveConfigPath");function pt(r,e){r.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("--no-interactive","\u4EC5\u6821\u9A8C\uFF0C\u8DF3\u8FC7\u4EA4\u4E92\u5F0F\u4FEE\u6539").action(async n=>{try{let{runConfigCommand:o}=await import("./config-command-HL4O3DHK.js");await o({configPath:n.config,workflowId:n.workflow,json:n.json,interactive:n.interactive})}catch(o){o instanceof Error&&o.message.includes("cancelled")&&process.exit(0),Mn.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",(n,o)=>[...o,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,o)=>[...o,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,o)=>{try{let{runConfigSet:i,printConfigSetResult:s}=await import("./config-set-EGLLIMVJ.js"),a=await i({configPath:Fn(o,n.config),...n.workflow?{workflowId:n.workflow}:{},set:n.set,setStdin:n.setStdin,...n.dryRun?{dryRun:!0}:{},...n.json?{json:!0}:{}});s(a,n.json===!0)}catch(i){let s=i instanceof Error?i.message:String(i);n.json?process.stdout.write(JSON.stringify({ok:!1,error:s},null,2)+`
|
|
13
13
|
`):console.error(`
|
|
14
14
|
\u2717 ${s}
|
|
15
|
-
`),process.exit(1)}})}
|
|
15
|
+
`),process.exit(1)}})}c(pt,"registerConfigCommand");import{runSync as Bn,logger as Un}from"aitable-workflow-core";function dt(r,e){r.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 Bn({configPath:t.config,yes:t.yes})}catch(n){Un.error("cli","sync \u5931\u8D25",{error:n instanceof Error?n.message:String(n)}),process.exit(1)}})}c(dt,"registerSyncCommand");import{listCodingAgents as Wn,logger as Nn}from"aitable-workflow-core";function gt(r,e){r.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=Wn();if(t.json){process.stdout.write(JSON.stringify(n,null,2)+`
|
|
16
16
|
`);return}let o=n.filter(i=>i.installed).length;console.log(`
|
|
17
17
|
\u652F\u6301 ${n.length} \u4E2A Coding Agent\uFF0C\u672C\u673A\u5DF2\u63A2\u6D4B\u5230 ${o} \u4E2A\uFF1A
|
|
18
|
-
`);for(let i of n){let s=i.installed?"\u2713":"\u2717",c=[i.bin,...i.fallbackBins].join(" / "),l=i.installed?`\u5DF2\u5B89\u88C5 (${i.detectedCmd}${i.detectedVersion?` ${i.detectedVersion}`:""})`:"\u672A\u63A2\u6D4B\u5230";console.log(` ${s} ${i.name.padEnd(16)} [${i.id}] bin: ${c.padEnd(24)} ${l}`)}console.log("")}catch(n){Bn.error("cli","\u5217\u51FA agents \u5931\u8D25",{error:n instanceof Error?n.message:String(n)}),process.exit(1)}})}a(mt,"registerAgentsCommand");import{logger as Fn}from"aitable-workflow-core";import{startServer as Un,resolveServeConfig as Wn}from"aitable-workflow-server";import Z from"path";import{existsSync as pt}from"fs";function dt(r,e){r.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 i=Number.parseInt(t.port,10);Number.isFinite(i)&&i>0&&(n.port=i)}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 i=Z.join(e.cliDir,"web");if(pt(Z.join(i,"index.html")))n.webRoot=i;else{let s=Z.resolve(e.cliDir,"..","..","web","dist");pt(Z.join(s,"index.html"))&&(n.webRoot=s)}}let o=Wn(n);if(await Un(o),o.webRoot&&t.open!==!1){let i=o.host==="0.0.0.0"?"127.0.0.1":o.host;Ue(`http://${i}:${o.port}`)}}catch(n){Fn.error("cli","HTTP \u670D\u52A1\u542F\u52A8\u5931\u8D25",{error:n instanceof Error?n.message:String(n)}),process.exit(1)}})}a(dt,"registerServeCommand");import{Command as _e}from"commander";import{logger as A,listCredentials as Lt,getActiveCredential as j,maskSecret as tr}from"aitable-workflow-core";import B from"os";import M from"path";import{mkdir as $o,readFile as Po}from"fs/promises";import{mkdirSync as jo}from"fs";import{logger as w,detectInstalledAgents as _o,runCodingAgent as Oo,DwsClient as Do,getActiveCredential as Lo,assertPortableId as Et,resolveInsideRoot as xt,probeCommand as Mo}from"aitable-workflow-core";import be from"ws";import{logger as E,RELAY_REJECTED_CODE as Nn,isRelayMessage as Gn}from"aitable-workflow-core";var T="relay:conn",gt=1e3,Hn=3e4,qn=Number(process.env.AITABLE_RELAY_SERVER_STALE_MS??9e4),ee=class{static{a(this,"RelayConnection")}ws=null;delay=gt;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 be(t)),this.staleMs=e.staleMs??qn}connect(){this.permanentlyRejected||(this.should=!0,this.doConnect())}send(e){this.ws&&this.ws.readyState===be.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();E.info(T,"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",()=>{E.info(T,"connected"),this.onOpen?.(t)}),t.on("message",n=>{this.accepted||(this.accepted=!0,this.delay=gt,this.onAccepted?.(t)),this.lastServerFrameAt=Date.now(),this.armWatchdog();let o;try{o=JSON.parse(typeof n=="string"?n:String(n))}catch{return}Gn(o)&&(o.type==="ping"&&this.send({type:"pong"}),this.onMessage(o))}),t.on("close",(n,o)=>{this.watchdog&&(clearTimeout(this.watchdog),this.watchdog=null);let i=o==null?"":String(o);if(n===Nn){this.permanentlyRejected=!0,this.should=!1,E.error(T,"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:i}),this.onPermanentReject?.({code:n,reason:i});return}E.warn(T,"disconnected",{code:n}),this.scheduleReconnect()}),t.on("error",n=>{E.error(T,"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!==be.OPEN)){E.warn(T,"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||(E.info(T,"reconnecting",{ms:this.delay}),this.timer=setTimeout(()=>{this.timer=null,this.doConnect()},this.delay),this.timer.unref?.(),this.delay=Math.min(this.delay*2,Hn))}};import{createHash as Kn}from"crypto";import{readdir as Vn,readFile as Yn,stat as Jn}from"fs/promises";import ut from"path";import{isAllowedArtifactPath as zn,normalizeArtifactRelPath as Xn}from"aitable-workflow-core";var ft={async upload(r,e,t){let n=await fetch(r,{method:"PUT",body:e,headers:{...t}});if(!n.ok)throw new Error(`artifact PUT failed: ${n.status} ${n.statusText}`)}};async function ht(r){let e=[];return await wt(r,r,e),e.sort((t,n)=>t.relPath.localeCompare(n.relPath))}a(ht,"scanArtifacts");async function wt(r,e,t){let n;try{n=await Vn(e,{withFileTypes:!0})}catch{return}for(let o of n){if(o.name==="node_modules"||o.name.startsWith("."))continue;let i=ut.join(e,o.name);if(o.isDirectory())await wt(r,i,t);else if(o.isFile()){let s=ut.relative(r,i).replace(/\\/g,"/");if(!zn(s))continue;let c=await Jn(i),l=await Yn(i),m=Kn("sha256").update(l).digest("hex");t.push({relPath:Xn(s),absPath:i,size:c.size,sha256:m})}}}a(wt,"walk");import St from"path";import{logger as k}from"aitable-workflow-core";import{logger as O,spawnManagedProcess as Qn}from"aitable-workflow-core";var D="engine-supervisor",te=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??Qn,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&&(O.error(D,"\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}:{}}),o=n.child,i={managed:n,gen:e,startedAt:Date.now(),stopping:!1};this.child=i,O.info(D,"engine started",{projectId:this.options.projectId,pid:o.pid,generation:e}),o.on("message",s=>{Zn(s)&&this.options.onRunEvent?.(s.event)}),o.on("error",s=>{this.lastError=s.message,O.error(D,"engine spawn error",{projectId:this.options.projectId,error:s.message})}),o.on("exit",(s,c)=>this.handleExit(i,s,c))}handleExit(e,t,n){if(this.child?.gen===e.gen&&(this.child=null),this.lastExitCode=t,O.info(D,"engine exited",{projectId:this.options.projectId,generation:e.gen,code:t,signal:n}),e.stopping||this.stopped)return;this.consecutiveFailures+=1;let o=this.options.maxConsecutiveFailures??5;if(this.consecutiveFailures>=o){O.error(D,"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 i=this.options.restartBackoffMs??1e3,s=this.options.restartBackoffMaxMs??6e4,c=Math.min(s,i*2**(this.consecutiveFailures-1));O.warn(D,"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 Zn(r){return typeof r=="object"&&r!==null&&r.type==="run-event"&&"event"in r}a(Zn,"isRunEventMessage");import{appendFile as eo,mkdir as to,rename as no,stat as oo}from"fs/promises";import ro from"path";import{logger as ne}from"aitable-workflow-core";var oe="event-spool",re=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,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 i=this.pending.splice(0,this.pending.length-n);ne.warn(oe,"\u5F85\u53D1\u4E8B\u4EF6\u8D85\u4E0A\u9650\uFF0C\u4E22\u5F03\u6700\u65E7\u7684\u6279\u6B21",{projectId:this.options.projectId,dropped:i.length,untilSeq:i[i.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(n=>n.seq));this.pending=this.pending.filter(n=>!t.has(n.seq))}catch(t){ne.warn(oe,"\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)),n=this.buffer.filter(o=>o.seq>e&&!t.has(o.seq));return n.length===0?0:(this.pending=[...this.pending,...n].sort((o,i)=>o.seq-i.seq),ne.info(oe,"\u8865\u4F20\u7F3A\u53E3\u4E8B\u4EF6",{projectId:this.options.projectId,serverLastSeq:e,replay:n.length}),n.length)}async persist(e){let t=ro.join(this.options.spoolDir,"run-events.jsonl");try{await to(this.options.spoolDir,{recursive:!0}),await oo(t).then(o=>o.size).catch(()=>0)>(this.options.rotateBytes??10*1024*1024)&&await no(t,`${t}.1`).catch(()=>{}),await eo(t,`${JSON.stringify(e)}
|
|
19
|
-
`,"utf8")}catch(n){
|
|
20
|
-
`),n=t.indexOf(
|
|
21
|
-
`):i=r,i=i.replace(/^\n+/,"");let s=Object.entries(e).sort(([l],[m])=>l.localeCompare(m));return s.length===0?i:`${[
|
|
18
|
+
`);for(let i of n){let s=i.installed?"\u2713":"\u2717",a=[i.bin,...i.fallbackBins].join(" / "),l=i.installed?`\u5DF2\u5B89\u88C5 (${i.detectedCmd}${i.detectedVersion?` ${i.detectedVersion}`:""})`:"\u672A\u63A2\u6D4B\u5230";console.log(` ${s} ${i.name.padEnd(16)} [${i.id}] bin: ${a.padEnd(24)} ${l}`)}console.log("")}catch(n){Nn.error("cli","\u5217\u51FA agents \u5931\u8D25",{error:n instanceof Error?n.message:String(n)}),process.exit(1)}})}c(gt,"registerAgentsCommand");import{logger as Gn}from"aitable-workflow-core";import{startServer as Hn,resolveServeConfig as qn}from"aitable-workflow-server";import te from"path";import{existsSync as ut}from"fs";function ft(r,e){r.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 i=Number.parseInt(t.port,10);Number.isFinite(i)&&i>0&&(n.port=i)}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 i=te.join(e.cliDir,"web");if(ut(te.join(i,"index.html")))n.webRoot=i;else{let s=te.resolve(e.cliDir,"..","..","web","dist");ut(te.join(s,"index.html"))&&(n.webRoot=s)}}let o=qn(n);if(await Hn(o),o.webRoot&&t.open!==!1){let i=o.host==="0.0.0.0"?"127.0.0.1":o.host;Ge(`http://${i}:${o.port}`)}}catch(n){Gn.error("cli","HTTP \u670D\u52A1\u542F\u52A8\u5931\u8D25",{error:n instanceof Error?n.message:String(n)}),process.exit(1)}})}c(ft,"registerServeCommand");import{Command as Oe}from"commander";import{logger as S,listCredentials as Bt,getActiveCredential as j,maskSecret as ir}from"aitable-workflow-core";import F from"os";import M from"path";import{mkdir as _o,readFile as Oo}from"fs/promises";import{mkdirSync as Lo}from"fs";import{logger as w,detectInstalledAgents as Mo,runCodingAgent as Fo,DwsClient as Bo,getActiveCredential as Uo,assertPortableId as Pt,resolveInsideRoot as $t,probeCommand as Wo}from"aitable-workflow-core";import Re from"ws";import{logger as E,RELAY_REJECTED_CODE as Kn,isRelayMessage as Vn}from"aitable-workflow-core";var T="relay:conn",ht=1e3,Yn=3e4,Jn=Number(process.env.AITABLE_RELAY_SERVER_STALE_MS??9e4),ne=class{static{c(this,"RelayConnection")}ws=null;delay=ht;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 Re(t)),this.staleMs=e.staleMs??Jn}connect(){this.permanentlyRejected||(this.should=!0,this.doConnect())}send(e){this.ws&&this.ws.readyState===Re.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();E.info(T,"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",()=>{E.info(T,"connected"),this.onOpen?.(t)}),t.on("message",n=>{this.accepted||(this.accepted=!0,this.delay=ht,this.onAccepted?.(t)),this.lastServerFrameAt=Date.now(),this.armWatchdog();let o;try{o=JSON.parse(typeof n=="string"?n:String(n))}catch{return}Vn(o)&&(o.type==="ping"&&this.send({type:"pong"}),this.onMessage(o))}),t.on("close",(n,o)=>{this.watchdog&&(clearTimeout(this.watchdog),this.watchdog=null);let i=o==null?"":String(o);if(n===Kn){this.permanentlyRejected=!0,this.should=!1,E.error(T,"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:i}),this.onPermanentReject?.({code:n,reason:i});return}E.warn(T,"disconnected",{code:n}),this.scheduleReconnect()}),t.on("error",n=>{E.error(T,"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!==Re.OPEN)){E.warn(T,"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||(E.info(T,"reconnecting",{ms:this.delay}),this.timer=setTimeout(()=>{this.timer=null,this.doConnect()},this.delay),this.timer.unref?.(),this.delay=Math.min(this.delay*2,Yn))}};import{createHash as zn}from"crypto";import{readdir as Xn,readFile as Qn,stat as Zn}from"fs/promises";import wt from"path";import{isAllowedArtifactPath as eo,normalizeArtifactRelPath as to}from"aitable-workflow-core";var yt={async upload(r,e,t){let n=await fetch(r,{method:"PUT",body:e,headers:{...t}});if(!n.ok)throw new Error(`artifact PUT failed: ${n.status} ${n.statusText}`)}};async function vt(r){let e=[];return await kt(r,r,e),e.sort((t,n)=>t.relPath.localeCompare(n.relPath))}c(vt,"scanArtifacts");async function kt(r,e,t){let n;try{n=await Xn(e,{withFileTypes:!0})}catch{return}for(let o of n){if(o.name==="node_modules"||o.name.startsWith("."))continue;let i=wt.join(e,o.name);if(o.isDirectory())await kt(r,i,t);else if(o.isFile()){let s=wt.relative(r,i).replace(/\\/g,"/");if(!eo(s))continue;let a=await Zn(i),l=await Qn(i),m=zn("sha256").update(l).digest("hex");t.push({relPath:to(s),absPath:i,size:a.size,sha256:m})}}}c(kt,"walk");import Tt from"path";import{logger as k}from"aitable-workflow-core";import{logger as _,spawnManagedProcess as no}from"aitable-workflow-core";var O="engine-supervisor",oe=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??no,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&&(_.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}:{}}),o=n.child,i={managed:n,gen:e,startedAt:Date.now(),stopping:!1};this.child=i,_.info(O,"engine started",{projectId:this.options.projectId,pid:o.pid,generation:e}),o.on("message",s=>{oo(s)&&this.options.onRunEvent?.(s.event)}),o.on("error",s=>{this.lastError=s.message,_.error(O,"engine spawn error",{projectId:this.options.projectId,error:s.message})}),o.on("exit",(s,a)=>this.handleExit(i,s,a))}handleExit(e,t,n){if(this.child?.gen===e.gen&&(this.child=null),this.lastExitCode=t,_.info(O,"engine exited",{projectId:this.options.projectId,generation:e.gen,code:t,signal:n}),e.stopping||this.stopped)return;this.consecutiveFailures+=1;let o=this.options.maxConsecutiveFailures??5;if(this.consecutiveFailures>=o){_.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 i=this.options.restartBackoffMs??1e3,s=this.options.restartBackoffMaxMs??6e4,a=Math.min(s,i*2**(this.consecutiveFailures-1));_.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 oo(r){return typeof r=="object"&&r!==null&&r.type==="run-event"&&"event"in r}c(oo,"isRunEventMessage");import{appendFile as ro,mkdir as io,rename as so,stat as ao}from"fs/promises";import co from"path";import{logger as re}from"aitable-workflow-core";var ie="event-spool",se=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 i=this.pending.splice(0,this.pending.length-n);re.warn(ie,"\u5F85\u53D1\u4E8B\u4EF6\u8D85\u4E0A\u9650\uFF0C\u4E22\u5F03\u6700\u65E7\u7684\u6279\u6B21",{projectId:this.options.projectId,dropped:i.length,untilSeq:i[i.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(n=>n.seq));this.pending=this.pending.filter(n=>!t.has(n.seq))}catch(t){re.warn(ie,"\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)),n=this.buffer.filter(o=>o.seq>e&&!t.has(o.seq));return n.length===0?0:(this.pending=[...this.pending,...n].sort((o,i)=>o.seq-i.seq),re.info(ie,"\u8865\u4F20\u7F3A\u53E3\u4E8B\u4EF6",{projectId:this.options.projectId,serverLastSeq:e,replay:n.length}),n.length)}async persist(e){let t=co.join(this.options.spoolDir,"run-events.jsonl");try{await io(this.options.spoolDir,{recursive:!0}),await ao(t).then(o=>o.size).catch(()=>0)>(this.options.rotateBytes??10*1024*1024)&&await so(t,`${t}.1`).catch(()=>{}),await ro(t,`${JSON.stringify(e)}
|
|
19
|
+
`,"utf8")}catch(n){re.warn(ie,"spool \u843D\u76D8\u5931\u8D25",{projectId:this.options.projectId,error:n instanceof Error?n.message:String(n)})}}};import{readdir as Ee,rm as xe,stat as le}from"fs/promises";import L from"path";import{logger as N}from"aitable-workflow-core";import{createHash as ho}from"crypto";import{mkdir as Se,readFile as wo,rename as yo,rm as vo,writeFile as It}from"fs/promises";import ae from"path";import{decodeWorkspaceBundle as ko,logger as bo,resolveInsideRoot as Co}from"aitable-workflow-core";import{chmod as lo,readFile as mo,rename as po,writeFile as go}from"fs/promises";var bt="# \u2500\u2500\u2500 aitable-workflow managed credentials (auto-generated, do not edit) \u2500\u2500\u2500",Ct="# \u2500\u2500\u2500 end managed credentials \u2500\u2500\u2500";function uo(r,e){let t=r.split(`
|
|
20
|
+
`),n=t.indexOf(bt),o=t.indexOf(Ct),i;n!==-1&&o!==-1&&o>n?i=[...t.slice(0,n),...t.slice(o+1)].join(`
|
|
21
|
+
`):i=r,i=i.replace(/^\n+/,"");let s=Object.entries(e).sort(([l],[m])=>l.localeCompare(m));return s.length===0?i:`${[bt,...s.map(([l,m])=>`${l}=${fo(m)}`),Ct].join(`
|
|
22
22
|
`)}
|
|
23
23
|
${i?`
|
|
24
|
-
${i}`:""}`}
|
|
25
|
-
`,"utf8"),{projectId:e,revision:i.revision,action:l,written:s,deleted:c,envUpdated:u}}a(Rt,"syncWorkspace");var G="runner-gc";async function It(r){let e=0,t;try{t=await Se(r,{withFileTypes:!0})}catch{return 0}for(let n of t){let o=L.join(r,n.name);if(!n.isSymbolicLink()){if(n.isDirectory()){e+=await It(o);continue}e+=await ae(o).then(i=>i.size).catch(()=>0)}}return e}a(It,"dirSize");async function Co(r){let e=L.join(r,"projects"),t;try{t=await Se(e,{withFileTypes:!0})}catch{return[]}let n=[];for(let o of t){if(!o.isDirectory())continue;let i=L.join(e,o.name),s=await ae(L.join(i,se)).then(l=>l.mtimeMs).catch(()=>null),c=await ae(i).then(l=>l.mtimeMs).catch(()=>0);n.push({projectId:o.name,dir:i,lastTouchedMs:s??c,sizeBytes:await It(i)})}return n}a(Co,"scanProjects");async function Ct(r,e){let t=L.join(r,"traces"),n;try{n=await Se(t,{withFileTypes:!0})}catch{return 0}let o=[];for(let c of n){if(!c.isFile())continue;let l=L.join(t,c.name),m=await ae(l).catch(()=>null);m&&o.push({full:l,size:m.size,mtimeMs:m.mtimeMs})}let i=o.reduce((c,l)=>c+l.size,0);if(i<=e)return 0;o.sort((c,l)=>c.mtimeMs-l.mtimeMs);let s=0;for(let c of o){if(i<=e)break;await Ae(c.full,{force:!0}).catch(()=>{}),i-=c.size,s+=c.size}return s}a(Ct,"pruneTraces");async function At(r){let e=(r.now??Date.now)(),t=(r.ttlDays??14)*24*60*60*1e3,n=r.tracesMaxBytes??500*1024*1024,o=r.maxDiskBytes??20*1024*1024*1024,i=new Set(r.activeProjectIds),s=await Co(r.workspaceRoot),c=[],l=0;for(let u of s){if(i.has(u.projectId)){l+=await Ct(u.dir,n);continue}if(e-u.lastTouchedMs>=t){await Ae(u.dir,{recursive:!0,force:!0}).catch(p=>{N.warn(G,"\u9879\u76EE\u76EE\u5F55\u56DE\u6536\u5931\u8D25",{projectId:u.projectId,error:p instanceof Error?p.message:String(p)})}),c.push(u.projectId),N.info(G,"\u56DE\u6536\u8FC7\u671F\u9879\u76EE\u76EE\u5F55",{projectId:u.projectId,idleDays:Math.floor((e-u.lastTouchedMs)/864e5)});continue}l+=await Ct(u.dir,n)}let m=s.filter(u=>!c.includes(u.projectId)),d=m.reduce((u,p)=>u+p.sizeBytes,0)-l,g=!1;if(d>o){g=!0,N.warn(G,"\u5DE5\u4F5C\u533A\u8D85\u78C1\u76D8\u6C34\u4F4D\uFF0C\u5F00\u59CB\u56DE\u6536\u6700\u4E45\u672A\u8BA4\u9886\u9879\u76EE",{totalBytes:d,maxDiskBytes:o});let u=m.filter(p=>!i.has(p.projectId)).sort((p,v)=>p.lastTouchedMs-v.lastTouchedMs);for(let p of u){if(d<=o)break;await Ae(p.dir,{recursive:!0,force:!0}).catch(()=>{}),c.push(p.projectId),d-=p.sizeBytes,N.warn(G,"\u6C34\u4F4D\u56DE\u6536\u9879\u76EE\u76EE\u5F55",{projectId:p.projectId,freedBytes:p.sizeBytes})}d>o&&N.error(G,"\u56DE\u6536\u540E\u4ECD\u8D85\u78C1\u76D8\u6C34\u4F4D\uFF08\u6D3B\u8DC3\u9879\u76EE\u5360\u7528\uFF09\uFF0C\u9700\u4EBA\u5DE5\u4ECB\u5165",{totalBytes:d,maxDiskBytes:o})}return{removedProjects:c,tracesFreedBytes:l,diskPressure:g,totalBytes:Math.max(0,d)}}a(At,"runGc");var b="runner-loop",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,n)=>setTimeout(t,n)),this.clearTimer=e.clearTimeoutImpl??(t=>clearTimeout(t)),this.doSync=e.syncImpl??Rt}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,k.info(b,"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??At)({workspaceRoot:this.options.workspaceRoot,activeProjectIds:[...this.holdings.keys()],...this.options.gcOptions??{}});(e.removedProjects.length>0||e.tracesFreedBytes>0)&&k.info(b,"\u672C\u673A\u56DE\u6536\u5B8C\u6210",{removed:e.removedProjects.length,tracesFreedBytes:e.tracesFreedBytes,totalBytes:e.totalBytes})}catch(e){k.warn(b,"\u672C\u673A\u56DE\u6536\u5931\u8D25",{error:$(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 o of n.grants??[])await this.acceptGrant(o,n.heartbeatIntervalSeconds)}}catch(t){k.warn(b,"claim \u5931\u8D25\uFF08\u9000\u907F\u540E\u91CD\u8BD5\uFF09",{error:$(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=St.join(this.options.workspaceRoot,"projects",e.projectId);k.info(b,"\u8BA4\u9886\u9879\u76EE",{projectId:e.projectId,generation:e.generation,workspaceDir:n});let o;try{o=await this.doSync(this.clientConfig(),e.projectId,n)}catch(l){k.error(b,"\u5DE5\u4F5C\u533A\u540C\u6B65\u5931\u8D25\uFF0C\u4EA4\u8FD8\u79DF\u7EA6",{projectId:e.projectId,error:$(l)}),await this.postSafe(`/api/runner/workflows/${e.projectId}/release`,{generation:e.generation,reason:"workspace_sync_failed"});return}let i=(this.options.createSupervisor??Io)({projectId:e.projectId,workspaceDir:n,cliPath:this.options.cliPath,onRunEvent:a(l=>this.handleRunEvent(e.projectId,l),"onRunEvent"),onCrashLoop:a(()=>{this.releaseHolding(e.projectId,"engine_crash_loop")},"onCrashLoop")}),s=this.options.sendRunEvents?new re({projectId:e.projectId,spoolDir:n,send:a(l=>this.options.sendRunEvents(e.projectId,l),"send")}):null;s?.start();let c={projectId:e.projectId,generation:e.generation,revision:o.revision,engine:i,spool:s,heartbeatTimer:null,busy:!1};this.holdings.set(e.projectId,c),i.start(),this.scheduleHeartbeat(c,(t??15)*1e3)}handleRunEvent(e,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}:{}}),o=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"){k.info(b,"\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,o);return}e.engine.markHealthy(),this.scheduleHeartbeat(e,o)}catch(n){k.warn(b,"\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:$(n)}),this.scheduleHeartbeat(e,Math.min(t,5e3))}}async resyncHolding(e){if(e.busy)return!0;e.busy=!0;let t=St.join(this.options.workspaceRoot,"projects",e.projectId);try{k.info(b,"\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 k.error(b,"\u91CD\u540C\u6B65\u5931\u8D25\uFF0C\u4EA4\u8FD8\u79DF\u7EA6",{projectId:e.projectId,error:$(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(o=>{k.warn(b,"\u505C\u6B62\u5F15\u64CE\u5F02\u5E38",{projectId:e,error:$(o)})}),await n.spool?.stop().catch(()=>{}),await this.postSafe(`/api/runner/workflows/${e}/release`,{generation:n.generation,reason:t}),k.info(b,"\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 o=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(!o.ok){let i=await o.text().catch(()=>"");throw new Error(`runner API ${e} \u5931\u8D25: HTTP ${o.status} ${i.slice(0,200)}`)}return await o.json()}async postSafe(e,t){try{await this.post(e,t)}catch(n){k.warn(b,"\u6536\u5C3E\u8BF7\u6C42\u5931\u8D25\uFF08\u79DF\u7EA6\u5C06\u7531\u670D\u52A1\u7AEF\u8FC7\u671F\u56DE\u6536\uFF09",{pathname:e,error:$(n)})}}};function Io(r){return new te({projectId:r.projectId,workspaceDir:r.workspaceDir,cliPath:r.cliPath,...r.onRunEvent?{onRunEvent:r.onRunEvent}:{},...r.onCrashLoop?{onCrashLoop:a(()=>r.onCrashLoop(),"onCrashLoop")}:{}})}a(Io,"defaultSupervisorFactory");function $(r){return r instanceof Error?r.message:String(r)}a($,"describeError");import{spawn as So}from"child_process";import{existsSync as xo}from"fs";import q from"path";import{fileURLToPath as Eo}from"url";import{appendFileSync as As,statSync as Ss,renameSync as xs,mkdirSync as Es,existsSync as Ts}from"fs";import Ao from"path";var js=10*1024*1024;function H(r){return Ao.join(X(r),"daemon.log")}a(H,"logFilePath");var le=q.dirname(Eo(import.meta.url));function xe(){let r=[q.resolve(le,"..","..","bin","aitable-workflow.mjs"),q.resolve(le,"..","bin","aitable-workflow.mjs"),q.resolve(le,"..","..","dist","cli.js"),q.resolve(le,"cli.js")];return r.find(e=>xo(e))??r[0]}a(xe,"resolveDaemonEntry");var To=xe();async function K(r){await Ne(r.agentId);let e=["relay"];r.serverUrl&&e.push("--server-url",r.serverUrl),r.token&&e.push("--token",r.token),r.key&&e.push("--key",r.key),r.name&&e.push("--name",r.name),r.workspaceRoot&&e.push("--workspace-root",r.workspaceRoot),r.machineId&&e.push("--machine-id",r.machineId),r.maxTasks&&e.push("--max-tasks",String(r.maxTasks));let t=await import("fs").then(s=>{let c=H(r.agentId);return s.openSync(c,"a")}),n=So(process.execPath,[To,...e],{detached:!0,stdio:["ignore",t,t],env:{...process.env}});try{let{closeSync:s}=await import("fs");s(t)}catch{}n.unref();let{writeFile:o}=await import("fs/promises"),{pidFilePath:i}=await import("./pid-file-KT5KHCKU.js");return n.pid&&await o(i(r.agentId),String(n.pid),"utf8"),{pid:n.pid??0}}a(K,"startDaemon");async function me(r,e=5e3){let t=await we(r);if(t===null||!W(t))return await Q(r),!1;try{process.kill(t,"SIGTERM")}catch{return await Q(r),!1}let n=Date.now()+e;for(;Date.now()<n&&W(t);)await new Promise(o=>setTimeout(o,200));if(W(t))try{process.kill(t,"SIGKILL")}catch{}return await Q(r),!0}a(me,"stopDaemon");async function V(r){let e=await we(r),t=e!==null&&W(e),n=null;if(t&&e!==null)try{let{readFile:o}=await import("fs/promises"),i=await o(`/proc/${e}/stat`,"utf8"),s=parseInt(i.split(" ")[21]??"0",10),c=await o("/proc/uptime","utf8"),d=parseFloat(c.split(" ")[0]??"0")-s/100;n=Math.round(d*1e3)}catch{}return{agentId:r,running:t,pid:t?e:null,uptimeMs:n,logFile:H(r)}}a(V,"getDaemonStatus");function Bo(r){return r.replace(/\/+$/,"").replace(/^ws/,"http")}a(Bo,"toHttpBase");var y="relay:daemon",Tt=["aitable"],Fo="dws";function Uo(r,e=Tt){if(!Array.isArray(r)||r.length===0)return{ok:!1,reason:"dws args must be a non-empty array"};for(let n of r){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=r[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(Uo,"validateDwsArgs");function Wo(r){return Mo(r,["--version"],{timeoutMs:5e3}).ok}a(Wo,"detectDwsAvailable");var Ee=class{static{a(this,"RelayDaemon")}config;allowedDwsCommands;conn;runAgent;createDwsClient;detectAgents;detectDws;hostname;osString;onPermanentReject;artifactUploader;grantTimeoutMs;pendingGrants=new Map;maxTasks;inflight=0;taskQueue=[];runnerLoop;machineId;constructor(e,t={}){this.config={...e,dwsBin:e.dwsBin??Fo},this.machineId=e.machineId,this.allowedDwsCommands=e.allowedDwsCommands??Tt,this.runAgent=t.runAgent??Oo,this.createDwsClient=t.createDwsClient??((o,i)=>new Do({bin:o,timeoutMs:i})),this.detectAgents=t.detectAgents??(()=>_o()),this.detectDws=t.detectDws??(o=>Wo(o)),this.hostname=t.hostname??(()=>B.hostname()),this.osString=t.osString??(()=>`${B.platform()} ${B.arch()}`),this.onPermanentReject=t.onPermanentReject,this.artifactUploader=t.artifactUploader??ft,this.grantTimeoutMs=t.grantTimeoutMs??3e4,this.maxTasks=Math.max(1,Math.floor(e.maxTasks??1));let n=t.createConnection??(o=>new ee(o));this.conn=n({serverUrl:this.config.serverUrl,key:this.config.key,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 n=this.config.key??this.config.token;if(!n)return w.warn(y,"\u65E0 machine key/owner-token\uFF0C\u8DF3\u8FC7 RunnerLoop\uFF08run \u9636\u6BB5\u4E0D\u8BA4\u9886\u9879\u76EE\uFF09"),null;let o={gatewayUrl:Bo(this.config.serverUrl),machineKey:n,workspaceRoot:this.config.workspaceRoot,cliPath:xe(),maxWorkflows:t,sendRunEvents:a((i,s)=>this.sendRunEvents(i,s),"sendRunEvents")};return(e.createRunnerLoop??(i=>new ce(i)))(o)}sendRunEvents(e,t){t.length!==0&&this.conn.send({type:"run:events",projectId:e,entries:t})}start(){w.info(y,"starting",{serverUrl:this.config.serverUrl,workspaceRoot:this.config.workspaceRoot}),this.config.name||w.warn(y,"\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.conn.connect(),this.runnerLoop?.start()}stop(){return w.info(y,"stopping"),this.conn.close(),this.runnerLoop?this.runnerLoop.stop().catch(e=>{w.warn(y,"runner loop \u505C\u6B62\u5F02\u5E38",{error:e instanceof Error?e.message:String(e)})}):Promise.resolve()}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(y,"connected; sending ready",{runtimes:e.runtimes,hasDws:e.hasDws}),this.conn.send(e)}handlePermanentReject(e){w.error(y,"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(y,"machine id assigned",{machineId:e.machineId}));break;default:break}}enqueueTask(e){let t=a(()=>{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(y,"run:agent received",{requestId:t,projectId:e.projectId,agent:e.agent});try{let n=this.resolveWorkDir(e.projectId,e.workDir);await $o(n,{recursive:!0});let o=this.rewritePromptWorkDir(e.prompt,e.workDir,n),i={agent:e.agent,workDir:n,onEvent:a(l=>this.conn.send({type:"event",requestId:t,event:l}),"onEvent")};e.sessionId&&(i.sessionId=e.sessionId),e.permissionMode&&(i.adapterOptions={permissionMode:e.permissionMode}),e.timeoutMs!==void 0?i.timeoutMs=e.timeoutMs:this.config.agentTimeoutMs!=null&&(i.timeoutMs=this.config.agentTimeoutMs);let s=await this.runAgent(o,i),c;try{c=await this.collectAndUploadArtifacts(t,e.projectId,n)}catch(l){let m=l instanceof Error?l.message:String(l);w.error(y,"artifact upload failed",{requestId:t,error:m}),this.conn.send({type:"error",requestId:t,code:"artifact_upload_failed",message:m});return}this.conn.send({type:"result",requestId:t,ok:!0,response:s.response,sessionId:s.sessionId,...c?{artifacts:c}:{}}),w.info(y,"run:agent done",{requestId:t,sessionId:s.sessionId,artifacts:c?c.files.length:0})}catch(n){let o=n instanceof Error?n.message:String(n);w.error(y,"run:agent failed",{requestId:t,error:o}),this.conn.send({type:"error",requestId:t,code:"agent_failed",message:o})}}async collectAndUploadArtifacts(e,t,n){let o=await ht(n);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 i=await this.awaitGrant(e);if(!i)throw new Error("upload:grant \u7B49\u5F85\u8D85\u65F6");if(i.grants.length===0){w.warn(y,"upload:grant \u65E0\u6388\u6743\u9879\uFF08gateway \u672A\u914D\u7F6E store \u6216\u5168\u88AB\u62D2\uFF09",{requestId:e,rejected:(i.rejected??[]).length});return}let s=[];for(let c of i.grants){let l=o.find(d=>d.relPath===c.path);if(!l)continue;let m=await Po(l.absPath);await this.artifactUploader.upload(c.url,m,c.headers),s.push({path:c.path,key:c.key,sha256:l.sha256,size:l.size})}return{store:"oss",files:s}}awaitGrant(e){return new Promise(t=>{let n=setTimeout(()=>{this.pendingGrants.delete(e),t(void 0)},this.grantTimeoutMs);n.unref?.(),this.pendingGrants.set(e,o=>{clearTimeout(n),t(o)})})}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=Uo(e.args,this.allowedDwsCommands);if(!n.ok){w.warn(y,"run:dws rejected",{requestId:t,reason:n.reason}),this.conn.send({type:"error",requestId:t,code:"dws_rejected",message:n.reason});return}w.info(y,"run:dws received",{requestId:t,command:e.args[0]});try{let i=await this.createDwsClient(this.config.dwsBin,e.timeoutMs).runJson(e.args,e.timeoutMs!=null?{timeoutMs:e.timeoutMs}:void 0);this.conn.send({type:"result",requestId:t,ok:!0,response:JSON.stringify(i)}),w.info(y,"run:dws done",{requestId:t})}catch(o){let i=o instanceof Error?o.message:String(o);w.error(y,"run:dws failed",{requestId:t,error:i}),this.conn.send({type:"error",requestId:t,code:"dws_failed",message:i})}}resolveWorkDir(e,t){if(t&&t.trim()!=="")if(M.isAbsolute(t))w.warn(y,"\u5FFD\u7565\u670D\u52A1\u7AEF\u4E0B\u53D1\u7684\u7EDD\u5BF9\u8DEF\u5F84 workDir\uFF0C\u56DE\u9000\u5230 workspaceRoot/projectId",{workDir:t,projectId:e});else return xt(this.config.workspaceRoot,t,{allowRoot:!1});return xt(this.config.workspaceRoot,Et(e,{label:"projectId"}),{allowRoot:!1})}rewritePromptWorkDir(e,t,n){let o=t?.trim();return!o||!M.isAbsolute(o)||o===n?e:e.split(o).join(n)}};function Te(r,e){let t,n=r?.trim();if(n)t=M.isAbsolute(n)?M.resolve(n):M.resolve(B.homedir(),n);else{let o=e?.trim()?e.trim():"default";t=M.join(B.homedir(),".aitable-workflow","workspaces",Et(o,{label:"agentId"}))}return jo(t,{recursive:!0}),t}a(Te,"resolveWorkspaceRoot");function No(r,e=process.env){let t=r.serverUrl??e.AITABLE_RELAY_SERVER_URL,n=r.key??e.AITABLE_RELAY_BOOTSTRAP_KEY,o=r.token??e.AITABLE_RELAY_TOKEN,i=r.workspaceRoot??e.AITABLE_RELAY_WORKSPACE_ROOT,s=r.machineId??e.AITABLE_RELAY_MACHINE_ID,c=r.name??e.AITABLE_RELAY_NAME,l=r.desc??e.AITABLE_RELAY_DESC,m=r.maxTasks??e.AITABLE_RELAY_MAX_TASKS,d=r.maxWorkflows??e.AITABLE_RELAY_MAX_WORKFLOWS,g=[];if(t||g.push("--server-url (\u6216 AITABLE_RELAY_SERVER_URL)"),!n&&!o&&g.push("--key/--token (\u6216 AITABLE_RELAY_BOOTSTRAP_KEY/AITABLE_RELAY_TOKEN)"),g.length>0)throw new Error(`relay \u7F3A\u5C11\u5FC5\u8981\u53C2\u6570: ${g.join(", ")}
|
|
26
|
-
\u{1F4A1} \u63D0\u793A: \u4F7F\u7528 \`aitable-workflow connect\` \u6CE8\u518C\u540E\u53EF\u7701\u7565\u8FD9\u4E9B\u53C2\u6570`);let u=
|
|
27
|
-
\u{1F4A1} ${
|
|
28
|
-
\u{1F4A1} ${
|
|
29
|
-
\u{1F4A1} ${
|
|
24
|
+
${i}`:""}`}c(uo,"mergeEnvContent");function fo(r){return r===""||/[\s#'"`\\]/.test(r)?`"${r.replace(/\\/g,"\\\\").replace(/"/g,'\\"').replace(/\n/g,"\\n")}"`:r}c(fo,"quoteEnvValue");async function Rt(r,e){let t=await mo(r,"utf8").catch(()=>""),n=uo(t,e);if(n===t||n===""&&t==="")return!1;let o=`${r}.aitable-sync-tmp`;return await go(o,n,{encoding:"utf8",mode:384}),await lo(o,384).catch(()=>{}),await po(o,r),!0}c(Rt,"mergeEnvFile");var Ro="workspace-sync",ce=".workspace-meta.json";function Io(r){return ho("sha256").update(r).digest("hex")}c(Io,"sha256Hex");async function Ie(r,e){let n=await(r.fetchImpl??fetch)(`${r.gatewayUrl.replace(/\/+$/,"")}${e}`,{headers:{authorization:`Bearer ${r.machineKey}`}});if(!n.ok){let o=await n.text().catch(()=>"");throw new Error(`runner API ${e} \u5931\u8D25: HTTP ${n.status} ${o.slice(0,200)}`)}return n}c(Ie,"apiGet");async function So(r){try{let e=await wo(ae.join(r,ce),"utf8"),t=JSON.parse(e);return t&&typeof t.projectId=="string"?t:null}catch{return null}}c(So,"readWorkspaceMeta");function Ae(r,e){return Co(r,e,{allowRoot:!1})}c(Ae,"resolveTracked");async function Ao(r,e){let t=Ae(r,e.path);await Se(ae.dirname(t),{recursive:!0});let n=`${t}.aitable-sync-tmp`;await It(n,e.content,"utf8"),await yo(n,t)}c(Ao,"writeTracked");async function St(r,e,t){let n=await So(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 i=await(await Ie(r,`/api/runner/workspace/${e}`)).json(),s=0,a=0,l="up-to-date",m=n?.trackedManifest??{};if(!n||n.revision!==i.revision){l="synced";let v=await Ie(r,`/api/runner/workspace/${e}/bundle`),I=ko(Buffer.from(await v.arrayBuffer()));if(I.projectId!==e)throw new Error(`\u5FEB\u7167\u5305\u5F52\u5C5E\u4E0D\u7B26: \u5305\u5185 projectId=${I.projectId}\uFF0C\u671F\u671B ${e}`);I.revision!==i.revision&&(i.revision=I.revision),await Se(t,{recursive:!0});let x={};for(let C of I.files)x[C.path]=Io(C.content);for(let C of I.files)Ae(t,C.path);let z=n?.trackedManifest??{};for(let C of I.files)z[C.path]!==x[C.path]&&(await Ao(t,C),s+=1);for(let C of Object.keys(z))if(x[C]===void 0){let We;try{We=Ae(t,C)}catch(ye){bo.warn(Ro,"\u8DF3\u8FC7\u8D8A\u754C\u7684\u65E7 manifest \u6761\u76EE",{projectId:e,path:C,error:ye instanceof Error?ye.message:String(ye)});continue}await vo(We,{force:!0}).catch(()=>{}),a+=1}m=x}let g=await(await Ie(r,`/api/runner/workspace/${e}/credentials`)).json();await Se(t,{recursive:!0});let u=await Rt(ae.join(t,".env"),g.credentials??{}),p={projectId:e,revision:i.revision,syncedAt:new Date().toISOString(),trackedManifest:m};return await It(ae.join(t,ce),`${JSON.stringify(p,null,2)}
|
|
25
|
+
`,"utf8"),{projectId:e,revision:i.revision,action:l,written:s,deleted:a,envUpdated:u}}c(St,"syncWorkspace");var G="runner-gc";async function xt(r){let e=0,t;try{t=await Ee(r,{withFileTypes:!0})}catch{return 0}for(let n of t){let o=L.join(r,n.name);if(!n.isSymbolicLink()){if(n.isDirectory()){e+=await xt(o);continue}e+=await le(o).then(i=>i.size).catch(()=>0)}}return e}c(xt,"dirSize");async function xo(r){let e=L.join(r,"projects"),t;try{t=await Ee(e,{withFileTypes:!0})}catch{return[]}let n=[];for(let o of t){if(!o.isDirectory())continue;let i=L.join(e,o.name),s=await le(L.join(i,ce)).then(l=>l.mtimeMs).catch(()=>null),a=await le(i).then(l=>l.mtimeMs).catch(()=>0);n.push({projectId:o.name,dir:i,lastTouchedMs:s??a,sizeBytes:await xt(i)})}return n}c(xo,"scanProjects");async function At(r,e){let t=L.join(r,"traces"),n;try{n=await Ee(t,{withFileTypes:!0})}catch{return 0}let o=[];for(let a of n){if(!a.isFile())continue;let l=L.join(t,a.name),m=await le(l).catch(()=>null);m&&o.push({full:l,size:m.size,mtimeMs:m.mtimeMs})}let i=o.reduce((a,l)=>a+l.size,0);if(i<=e)return 0;o.sort((a,l)=>a.mtimeMs-l.mtimeMs);let s=0;for(let a of o){if(i<=e)break;await xe(a.full,{force:!0}).catch(()=>{}),i-=a.size,s+=a.size}return s}c(At,"pruneTraces");async function Et(r){let e=(r.now??Date.now)(),t=(r.ttlDays??14)*24*60*60*1e3,n=r.tracesMaxBytes??500*1024*1024,o=r.maxDiskBytes??20*1024*1024*1024,i=new Set(r.activeProjectIds),s=await xo(r.workspaceRoot),a=[],l=0;for(let u of s){if(i.has(u.projectId)){l+=await At(u.dir,n);continue}if(e-u.lastTouchedMs>=t){await xe(u.dir,{recursive:!0,force:!0}).catch(p=>{N.warn(G,"\u9879\u76EE\u76EE\u5F55\u56DE\u6536\u5931\u8D25",{projectId:u.projectId,error:p instanceof Error?p.message:String(p)})}),a.push(u.projectId),N.info(G,"\u56DE\u6536\u8FC7\u671F\u9879\u76EE\u76EE\u5F55",{projectId:u.projectId,idleDays:Math.floor((e-u.lastTouchedMs)/864e5)});continue}l+=await At(u.dir,n)}let m=s.filter(u=>!a.includes(u.projectId)),d=m.reduce((u,p)=>u+p.sizeBytes,0)-l,g=!1;if(d>o){g=!0,N.warn(G,"\u5DE5\u4F5C\u533A\u8D85\u78C1\u76D8\u6C34\u4F4D\uFF0C\u5F00\u59CB\u56DE\u6536\u6700\u4E45\u672A\u8BA4\u9886\u9879\u76EE",{totalBytes:d,maxDiskBytes:o});let u=m.filter(p=>!i.has(p.projectId)).sort((p,v)=>p.lastTouchedMs-v.lastTouchedMs);for(let p of u){if(d<=o)break;await xe(p.dir,{recursive:!0,force:!0}).catch(()=>{}),a.push(p.projectId),d-=p.sizeBytes,N.warn(G,"\u6C34\u4F4D\u56DE\u6536\u9879\u76EE\u76EE\u5F55",{projectId:p.projectId,freedBytes:p.sizeBytes})}d>o&&N.error(G,"\u56DE\u6536\u540E\u4ECD\u8D85\u78C1\u76D8\u6C34\u4F4D\uFF08\u6D3B\u8DC3\u9879\u76EE\u5360\u7528\uFF09\uFF0C\u9700\u4EBA\u5DE5\u4ECB\u5165",{totalBytes:d,maxDiskBytes:o})}return{removedProjects:a,tracesFreedBytes:l,diskPressure:g,totalBytes:Math.max(0,d)}}c(Et,"runGc");var b="runner-loop",me=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??St}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,k.info(b,"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??Et)({workspaceRoot:this.options.workspaceRoot,activeProjectIds:[...this.holdings.keys()],...this.options.gcOptions??{}});(e.removedProjects.length>0||e.tracesFreedBytes>0)&&k.info(b,"\u672C\u673A\u56DE\u6536\u5B8C\u6210",{removed:e.removedProjects.length,tracesFreedBytes:e.tracesFreedBytes,totalBytes:e.totalBytes})}catch(e){k.warn(b,"\u672C\u673A\u56DE\u6536\u5931\u8D25",{error:$(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 o of n.grants??[])await this.acceptGrant(o,n.heartbeatIntervalSeconds)}}catch(t){k.warn(b,"claim \u5931\u8D25\uFF08\u9000\u907F\u540E\u91CD\u8BD5\uFF09",{error:$(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=Tt.join(this.options.workspaceRoot,"projects",e.projectId);k.info(b,"\u8BA4\u9886\u9879\u76EE",{projectId:e.projectId,generation:e.generation,workspaceDir:n});let o;try{o=await this.doSync(this.clientConfig(),e.projectId,n)}catch(l){k.error(b,"\u5DE5\u4F5C\u533A\u540C\u6B65\u5931\u8D25\uFF0C\u4EA4\u8FD8\u79DF\u7EA6",{projectId:e.projectId,error:$(l)}),await this.postSafe(`/api/runner/workflows/${e.projectId}/release`,{generation:e.generation,reason:"workspace_sync_failed"});return}let i=(this.options.createSupervisor??Eo)({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")}),s=this.options.sendRunEvents?new se({projectId:e.projectId,spoolDir:n,send:c(l=>this.options.sendRunEvents(e.projectId,l),"send")}):null;s?.start();let a={projectId:e.projectId,generation:e.generation,revision:o.revision,engine:i,spool:s,heartbeatTimer:null,busy:!1};this.holdings.set(e.projectId,a),i.start(),this.scheduleHeartbeat(a,(t??15)*1e3)}handleRunEvent(e,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}:{}}),o=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"){k.info(b,"\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,o);return}e.engine.markHealthy(),this.scheduleHeartbeat(e,o)}catch(n){k.warn(b,"\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:$(n)}),this.scheduleHeartbeat(e,Math.min(t,5e3))}}async resyncHolding(e){if(e.busy)return!0;e.busy=!0;let t=Tt.join(this.options.workspaceRoot,"projects",e.projectId);try{k.info(b,"\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 k.error(b,"\u91CD\u540C\u6B65\u5931\u8D25\uFF0C\u4EA4\u8FD8\u79DF\u7EA6",{projectId:e.projectId,error:$(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(o=>{k.warn(b,"\u505C\u6B62\u5F15\u64CE\u5F02\u5E38",{projectId:e,error:$(o)})}),await n.spool?.stop().catch(()=>{}),await this.postSafe(`/api/runner/workflows/${e}/release`,{generation:n.generation,reason:t}),k.info(b,"\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 o=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(!o.ok){let i=await o.text().catch(()=>"");throw new Error(`runner API ${e} \u5931\u8D25: HTTP ${o.status} ${i.slice(0,200)}`)}return await o.json()}async postSafe(e,t){try{await this.post(e,t)}catch(n){k.warn(b,"\u6536\u5C3E\u8BF7\u6C42\u5931\u8D25\uFF08\u79DF\u7EA6\u5C06\u7531\u670D\u52A1\u7AEF\u8FC7\u671F\u56DE\u6536\uFF09",{pathname:e,error:$(n)})}}};function Eo(r){return new oe({projectId:r.projectId,workspaceDir:r.workspaceDir,cliPath:r.cliPath,...r.onRunEvent?{onRunEvent:r.onRunEvent}:{},...r.onCrashLoop?{onCrashLoop:c(()=>r.onCrashLoop(),"onCrashLoop")}:{}})}c(Eo,"defaultSupervisorFactory");function $(r){return r instanceof Error?r.message:String(r)}c($,"describeError");import{spawn as $o}from"child_process";import{existsSync as Po}from"fs";import q from"path";import{fileURLToPath as jo}from"url";import{appendFileSync as $s,statSync as Ps,renameSync as js,mkdirSync as Ds,existsSync as _s}from"fs";import To from"path";var Ms=10*1024*1024;function H(r){return To.join(X(r),"daemon.log")}c(H,"logFilePath");var pe=q.dirname(jo(import.meta.url));function Te(){let r=[q.resolve(pe,"..","..","bin","aitable-workflow.mjs"),q.resolve(pe,"..","bin","aitable-workflow.mjs"),q.resolve(pe,"..","..","dist","cli.js"),q.resolve(pe,"cli.js")];return r.find(e=>Po(e))??r[0]}c(Te,"resolveDaemonEntry");var Do=Te();async function K(r){await qe(r.agentId);let e=["relay"];r.serverUrl&&e.push("--server-url",r.serverUrl),r.token&&e.push("--token",r.token),r.key&&e.push("--key",r.key),r.name&&e.push("--name",r.name),r.workspaceRoot&&e.push("--workspace-root",r.workspaceRoot),r.machineId&&e.push("--machine-id",r.machineId),r.maxTasks&&e.push("--max-tasks",String(r.maxTasks));let t=await import("fs").then(s=>{let a=H(r.agentId);return s.openSync(a,"a")}),n=$o(process.execPath,[Do,...e],{detached:!0,stdio:["ignore",t,t],env:{...process.env}});try{let{closeSync:s}=await import("fs");s(t)}catch{}n.unref();let{writeFile:o}=await import("fs/promises"),{pidFilePath:i}=await import("./pid-file-KT5KHCKU.js");return n.pid&&await o(i(r.agentId),String(n.pid),"utf8"),{pid:n.pid??0}}c(K,"startDaemon");async function de(r,e=5e3){let t=await ve(r);if(t===null||!W(t))return await Q(r),!1;try{process.kill(t,"SIGTERM")}catch{return await Q(r),!1}let n=Date.now()+e;for(;Date.now()<n&&W(t);)await new Promise(o=>setTimeout(o,200));if(W(t))try{process.kill(t,"SIGKILL")}catch{}return await Q(r),!0}c(de,"stopDaemon");async function V(r){let e=await ve(r),t=e!==null&&W(e),n=null;if(t&&e!==null)try{let{readFile:o}=await import("fs/promises"),i=await o(`/proc/${e}/stat`,"utf8"),s=parseInt(i.split(" ")[21]??"0",10),a=await o("/proc/uptime","utf8"),d=parseFloat(a.split(" ")[0]??"0")-s/100;n=Math.round(d*1e3)}catch{}return{agentId:r,running:t,pid:t?e:null,uptimeMs:n,logFile:H(r)}}c(V,"getDaemonStatus");function No(r){return r.replace(/\/+$/,"").replace(/^ws/,"http")}c(No,"toHttpBase");var y="relay:daemon",jt=["aitable"],Go="dws";function Ho(r,e=jt){if(!Array.isArray(r)||r.length===0)return{ok:!1,reason:"dws args must be a non-empty array"};for(let n of r){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=r[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(Ho,"validateDwsArgs");function qo(r){return Wo(r,["--version"],{timeoutMs:5e3}).ok}c(qo,"detectDwsAvailable");var $e=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;machineId;constructor(e,t={}){this.config={...e,dwsBin:e.dwsBin??Go},this.machineId=e.machineId,this.allowedDwsCommands=e.allowedDwsCommands??jt,this.runAgent=t.runAgent??Fo,this.createDwsClient=t.createDwsClient??((o,i)=>new Bo({bin:o,timeoutMs:i})),this.detectAgents=t.detectAgents??(()=>Mo()),this.detectDws=t.detectDws??(o=>qo(o)),this.hostname=t.hostname??(()=>F.hostname()),this.osString=t.osString??(()=>`${F.platform()} ${F.arch()}`),this.onPermanentReject=t.onPermanentReject,this.artifactUploader=t.artifactUploader??yt,this.grantTimeoutMs=t.grantTimeoutMs??3e4,this.maxTasks=Math.max(1,Math.floor(e.maxTasks??1));let n=t.createConnection??(o=>new ne(o));this.conn=n({serverUrl:this.config.serverUrl,key:this.config.key,token:this.config.token,onMessage:c(o=>this.handleMessage(o),"onMessage"),onOpen:c(()=>this.handleOpen(),"onOpen"),onPermanentReject:c(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 n=this.config.key??this.config.token;if(!n)return w.warn(y,"\u65E0 machine key/owner-token\uFF0C\u8DF3\u8FC7 RunnerLoop\uFF08run \u9636\u6BB5\u4E0D\u8BA4\u9886\u9879\u76EE\uFF09"),null;let o={gatewayUrl:No(this.config.serverUrl),machineKey:n,workspaceRoot:this.config.workspaceRoot,cliPath:Te(),maxWorkflows:t,sendRunEvents:c((i,s)=>this.sendRunEvents(i,s),"sendRunEvents")};return(e.createRunnerLoop??(i=>new me(i)))(o)}sendRunEvents(e,t){t.length!==0&&this.conn.send({type:"run:events",projectId:e,entries:t})}start(){w.info(y,"starting",{serverUrl:this.config.serverUrl,workspaceRoot:this.config.workspaceRoot}),this.config.name||w.warn(y,"\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.conn.connect(),this.runnerLoop?.start()}stop(){return w.info(y,"stopping"),this.conn.close(),this.runnerLoop?this.runnerLoop.stop().catch(e=>{w.warn(y,"runner loop \u505C\u6B62\u5F02\u5E38",{error:e instanceof Error?e.message:String(e)})}):Promise.resolve()}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(y,"connected; sending ready",{runtimes:e.runtimes,hasDws:e.hasDws}),this.conn.send(e)}handlePermanentReject(e){w.error(y,"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(y,"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(y,"run:agent received",{requestId:t,projectId:e.projectId,agent:e.agent});try{let n=this.resolveWorkDir(e.projectId,e.workDir);await _o(n,{recursive:!0});let o=this.rewritePromptWorkDir(e.prompt,e.workDir,n),i={agent:e.agent,workDir:n,onEvent:c(l=>this.conn.send({type:"event",requestId:t,event:l}),"onEvent")};e.sessionId&&(i.sessionId=e.sessionId),e.permissionMode&&(i.adapterOptions={permissionMode:e.permissionMode}),e.timeoutMs!==void 0?i.timeoutMs=e.timeoutMs:this.config.agentTimeoutMs!=null&&(i.timeoutMs=this.config.agentTimeoutMs);let s=await this.runAgent(o,i),a;try{a=await this.collectAndUploadArtifacts(t,e.projectId,n)}catch(l){let m=l instanceof Error?l.message:String(l);w.error(y,"artifact upload failed",{requestId:t,error:m}),this.conn.send({type:"error",requestId:t,code:"artifact_upload_failed",message:m});return}this.conn.send({type:"result",requestId:t,ok:!0,response:s.response,sessionId:s.sessionId,...a?{artifacts:a}:{}}),w.info(y,"run:agent done",{requestId:t,sessionId:s.sessionId,artifacts:a?a.files.length:0})}catch(n){let o=n instanceof Error?n.message:String(n);w.error(y,"run:agent failed",{requestId:t,error:o}),this.conn.send({type:"error",requestId:t,code:"agent_failed",message:o})}}async collectAndUploadArtifacts(e,t,n){let o=await vt(n);if(o.length===0)return;this.conn.send({type:"upload:request",requestId:e,projectId:t,files:o.map(a=>({path:a.relPath,size:a.size,sha256:a.sha256}))});let i=await this.awaitGrant(e);if(!i)throw new Error("upload:grant \u7B49\u5F85\u8D85\u65F6");if(i.grants.length===0){w.warn(y,"upload:grant \u65E0\u6388\u6743\u9879\uFF08gateway \u672A\u914D\u7F6E store \u6216\u5168\u88AB\u62D2\uFF09",{requestId:e,rejected:(i.rejected??[]).length});return}let s=[];for(let a of i.grants){let l=o.find(d=>d.relPath===a.path);if(!l)continue;let m=await Oo(l.absPath);await this.artifactUploader.upload(a.url,m,a.headers),s.push({path:a.path,key:a.key,sha256:l.sha256,size:l.size})}return{store:"oss",files:s}}awaitGrant(e){return new Promise(t=>{let n=setTimeout(()=>{this.pendingGrants.delete(e),t(void 0)},this.grantTimeoutMs);n.unref?.(),this.pendingGrants.set(e,o=>{clearTimeout(n),t(o)})})}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=Ho(e.args,this.allowedDwsCommands);if(!n.ok){w.warn(y,"run:dws rejected",{requestId:t,reason:n.reason}),this.conn.send({type:"error",requestId:t,code:"dws_rejected",message:n.reason});return}w.info(y,"run:dws received",{requestId:t,command:e.args[0]});try{let i=await this.createDwsClient(this.config.dwsBin,e.timeoutMs).runJson(e.args,e.timeoutMs!=null?{timeoutMs:e.timeoutMs}:void 0);this.conn.send({type:"result",requestId:t,ok:!0,response:JSON.stringify(i)}),w.info(y,"run:dws done",{requestId:t})}catch(o){let i=o instanceof Error?o.message:String(o);w.error(y,"run:dws failed",{requestId:t,error:i}),this.conn.send({type:"error",requestId:t,code:"dws_failed",message:i})}}resolveWorkDir(e,t){if(t&&t.trim()!=="")if(M.isAbsolute(t))w.warn(y,"\u5FFD\u7565\u670D\u52A1\u7AEF\u4E0B\u53D1\u7684\u7EDD\u5BF9\u8DEF\u5F84 workDir\uFF0C\u56DE\u9000\u5230 workspaceRoot/projectId",{workDir:t,projectId:e});else return $t(this.config.workspaceRoot,t,{allowRoot:!1});return $t(this.config.workspaceRoot,Pt(e,{label:"projectId"}),{allowRoot:!1})}rewritePromptWorkDir(e,t,n){let o=t?.trim();return!o||!M.isAbsolute(o)||o===n?e:e.split(o).join(n)}};function Pe(r,e){let t,n=r?.trim();if(n)t=M.isAbsolute(n)?M.resolve(n):M.resolve(F.homedir(),n);else{let o=e?.trim()?e.trim():"default";t=M.join(F.homedir(),".aitable-workflow","workspaces",Pt(o,{label:"agentId"}))}return Lo(t,{recursive:!0}),t}c(Pe,"resolveWorkspaceRoot");function Ko(r,e=process.env){let t=r.serverUrl??e.AITABLE_RELAY_SERVER_URL,n=r.key??e.AITABLE_RELAY_BOOTSTRAP_KEY,o=r.token??e.AITABLE_RELAY_TOKEN,i=r.workspaceRoot??e.AITABLE_RELAY_WORKSPACE_ROOT,s=r.machineId??e.AITABLE_RELAY_MACHINE_ID,a=r.name??e.AITABLE_RELAY_NAME,l=r.desc??e.AITABLE_RELAY_DESC,m=r.maxTasks??e.AITABLE_RELAY_MAX_TASKS,d=r.maxWorkflows??e.AITABLE_RELAY_MAX_WORKFLOWS,g=[];if(t||g.push("--server-url (\u6216 AITABLE_RELAY_SERVER_URL)"),!n&&!o&&g.push("--key/--token (\u6216 AITABLE_RELAY_BOOTSTRAP_KEY/AITABLE_RELAY_TOKEN)"),g.length>0)throw new Error(`relay \u7F3A\u5C11\u5FC5\u8981\u53C2\u6570: ${g.join(", ")}
|
|
26
|
+
\u{1F4A1} \u63D0\u793A: \u4F7F\u7528 \`aitable-workflow connect\` \u6CE8\u518C\u540E\u53EF\u7701\u7565\u8FD9\u4E9B\u53C2\u6570`);let u=a??F.hostname()??"default",p={serverUrl:t,workspaceRoot:Pe(i,u)};if(o?p.token=o:n&&(p.key=n),s&&(p.machineId=s),a&&(p.name=a,p.displayName=a),l&&(p.description=l),m!=null&&m!==""){let v=Math.floor(Number(m));Number.isFinite(v)&&v>=1&&(p.maxTasks=v)}if(d!=null&&d!==""){let v=Math.floor(Number(d));Number.isFinite(v)&&v>=0&&(p.maxWorkflows=v)}return p}c(Ko,"resolveRelayCliConfig");async function B(r,e=process.env){let t=null;try{t=await Uo()}catch{t=null}let n={serverUrl:r.serverUrl??e.AITABLE_RELAY_SERVER_URL??t?.serverUrl,key:r.key??e.AITABLE_RELAY_BOOTSTRAP_KEY??t?.key,token:r.token??e.AITABLE_RELAY_TOKEN??t?.token,name:r.name??e.AITABLE_RELAY_NAME??t?.name,desc:r.desc??e.AITABLE_RELAY_DESC,workspaceRoot:r.workspaceRoot??e.AITABLE_RELAY_WORKSPACE_ROOT??t?.workspaceRoot,machineId:r.machineId??e.AITABLE_RELAY_MACHINE_ID??t?.machineId,maxTasks:r.maxTasks??e.AITABLE_RELAY_MAX_TASKS,maxWorkflows:r.maxWorkflows??e.AITABLE_RELAY_MAX_WORKFLOWS};return Ko(n,e)}c(B,"resolveDaemonConfig");async function ge(r){let e=await B(r),t=new $e(e,{onPermanentReject:c(()=>{process.exit(1)},"onPermanentReject")}),n=!1,o=c(()=>{n&&(w.warn(y,"\u518D\u6B21\u6536\u5230\u9000\u51FA\u4FE1\u53F7\uFF0C\u5F3A\u5236\u9000\u51FA"),process.exit(1)),n=!0,t.stop().catch(()=>{}).finally(()=>process.exit(0))},"shutdown");return process.on("SIGINT",o),process.on("SIGTERM",o),t.start(),t}c(ge,"runRelayDaemon");import{readFile as Vo,writeFile as aa,mkdir as ca}from"fs/promises";import Yo from"path";var Dt={connectionState:"disconnected",lastHeartbeatAt:null,machineId:null,serverUrl:"",runningTasks:0,queuedTasks:0,lastDisconnectReason:null,updatedAt:new Date().toISOString()};function Jo(r){return Yo.join(X(r),"state.json")}c(Jo,"stateFilePath");async function ue(r){try{let e=await Vo(Jo(r),"utf8");return{...Dt,...JSON.parse(e)}}catch{return{...Dt}}}c(ue,"readState");import{execSync as Y}from"child_process";import{writeFile as zo,rm as Xo,mkdir as Qo,access as Zo}from"fs/promises";import A from"path";import _t from"os";import{assertPortableId as er,readCredentials as tr}from"aitable-workflow-core";var nr="com.alibaba.aitable-workflow.daemon",je="\u8BF7\u5148\u5168\u5C40\u5B89\u88C5\uFF1Anpm i -g @ali/aitable-workflow";function J(r){return`${nr}.${er(r,{label:"agentId"})}`}c(J,"plistLabel");function De(r){return A.join(_t.homedir(),"Library","LaunchAgents",`${J(r)}.plist`)}c(De,"plistPath");function P(){return process.platform==="darwin"}c(P,"isMacOS");function Ot(){try{return Y("which aitable-workflow",{encoding:"utf8"}).trim()||null}catch{return null}}c(Ot,"resolveGlobalCliEntry");function Lt(r){if(!r||!r.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
|
|
27
|
+
\u{1F4A1} ${je}`);if(r.includes("/_npx/")||r.includes(`${A.sep}_npx${A.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${r}
|
|
28
|
+
\u{1F4A1} ${je}`);if(!A.isAbsolute(r))throw new Error(`CLI \u5165\u53E3\u4E0D\u662F\u7A33\u5B9A\u7684\u5168\u5C40\u7EDD\u5BF9\u8DEF\u5F84\uFF1A${r}
|
|
29
|
+
\u{1F4A1} ${je}`)}c(Lt,"assertStableCliEntry");async function or(r){let e={};e.AITABLE_RELAY_NAME=r;let t;try{let n=await tr();t=n.agents.find(o=>o.name===r)??n.agents.find(o=>o.name===n.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}c(or,"buildRelayEnv");function rr(r,e){let t=J(r),n=e?.cliEntry??Ot();Lt(n);let o=["relay"];e?.maxTasks&&o.push("--max-tasks",String(e.maxTasks));let i=A.join(_t.homedir(),".aitable-workflow","daemons",r),s=A.join(i,"launchd.log"),a=A.join(i,"launchd.err.log"),l=[n,...o].map(g=>` <string>${U(g)}</string>`).join(`
|
|
30
30
|
`),m={PATH:process.env.PATH??"/usr/local/bin:/usr/bin:/bin",...e?.relayEnv??{}},d=Object.entries(m).map(([g,u])=>` <key>${U(g)}</key>
|
|
31
31
|
<string>${U(u)}</string>`).join(`
|
|
32
32
|
`);return`<?xml version="1.0" encoding="UTF-8"?>
|
|
@@ -50,44 +50,44 @@ ${d}
|
|
|
50
50
|
<key>StandardOutPath</key>
|
|
51
51
|
<string>${U(s)}</string>
|
|
52
52
|
<key>StandardErrorPath</key>
|
|
53
|
-
<string>${U(
|
|
53
|
+
<string>${U(a)}</string>
|
|
54
54
|
</dict>
|
|
55
55
|
</plist>
|
|
56
|
-
`}
|
|
57
|
-
Agent: ${i.agentId}`),console.log(`Running: ${i.running?"\u2705 yes":"\u274C no"}`),i.pid&&console.log(`PID: ${i.pid}`),i.uptimeMs!==null){let
|
|
58
|
-
--- Configuration ---`),console.log(`Server: ${s.serverUrl}`),console.log(`Token: ${
|
|
56
|
+
`}c(rr,"generatePlist");function U(r){return r.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""")}c(U,"escapeXml");function fe(){let r=process.getuid?.();if(r===void 0)throw new Error("\u65E0\u6CD5\u83B7\u53D6\u7528\u6237 UID\uFF08\u4EC5\u652F\u6301 macOS/Linux\uFF09");return r}c(fe,"getUid");async function Mt(r,e){if(!P())throw new Error("\u5F00\u673A\u81EA\u542F\u5F53\u524D\u4EC5\u652F\u6301 macOS");let t=Ot();Lt(t);let n=await or(r),o=De(r),i=J(r);try{Y(`launchctl bootout gui/${fe()}/${i} 2>/dev/null`,{encoding:"utf8"})}catch{}await Qo(A.dirname(o),{recursive:!0});let s=rr(r,{maxTasks:e?.maxTasks,relayEnv:n,cliEntry:t});await zo(o,s,"utf8"),Y(`launchctl bootstrap gui/${fe()} ${o}`,{encoding:"utf8"})}c(Mt,"enableAutostart");async function Ft(r){if(!P())throw new Error("\u5F00\u673A\u81EA\u542F\u5F53\u524D\u4EC5\u652F\u6301 macOS");let e=J(r),t=De(r);try{Y(`launchctl bootout gui/${fe()}/${e} 2>/dev/null`,{encoding:"utf8"})}catch{}await Xo(t,{force:!0})}c(Ft,"disableAutostart");async function _e(r){if(!P())throw new Error("\u5F00\u673A\u81EA\u542F\u5F53\u524D\u4EC5\u652F\u6301 macOS");let e=J(r),t=De(r),n=!1;try{await Zo(t),n=!0}catch{n=!1}let o=!1,i=!1,s=null;try{let a=Y(`launchctl print gui/${fe()}/${e} 2>/dev/null`,{encoding:"utf8"});o=!0;let l=a.match(/pid\s*=\s*(\d+)/);l&&(s=parseInt(l[1],10),i=!0)}catch{o=!1}return{installed:n,loaded:o,running:i,pid:s}}c(_e,"getAutostartStatus");import{watchFile as sr,statSync as ar,openSync as cr,readSync as lr,closeSync as mr}from"fs";import{readFile as Ut}from"fs/promises";function Wt(r,e){let t=r.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 <ownerToken>","owner-token").option("--key <machineKey>","per-machine key\uFF08sk_machine_*\uFF09").option("--workspace-root <dir>","\u5DE5\u4F5C\u533A\u6839\u76EE\u5F55").option("--max-tasks <n>","\u5E76\u53D1\u4E0A\u9650","1").action(async n=>{try{let o=n.agent;if(!o){let a=await j();if(!a)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=a.name}let i=await B({serverUrl:n.serverUrl,token:n.token,key:n.key,workspaceRoot:n.workspaceRoot,name:o,maxTasks:n.maxTasks}),s=await K({agentId:o,serverUrl:i.serverUrl,token:i.token,key:i.key,name:i.name??o,workspaceRoot:i.workspaceRoot,machineId:i.machineId,maxTasks:i.maxTasks});console.log("\u2705 Daemon \u5DF2\u542F\u52A8"),console.log(` Agent: ${o}`),console.log(` PID: ${s.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 n=>{try{if(n.all){let o=await Bt(),i=0;for(let s of o)await de(s.name)&&i++;console.log(`\u2705 \u5DF2\u505C\u6B62 ${i} \u4E2A daemon`)}else{let o=n.agent;if(!o){let s=await j();if(!s)throw new Error("\u672A\u6307\u5B9A --agent \u4E14\u65E0\u6D3B\u8DC3 Agent");o=s.name}let i=await de(o);console.log(i?`\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 n=>{try{let o=n.agent;if(!o){let a=await j();if(!a)throw new Error("\u672A\u6307\u5B9A --agent \u4E14\u65E0\u6D3B\u8DC3 Agent");o=a.name}console.log(`\u{1F504} \u6B63\u5728\u91CD\u542F "${o}"...`),await de(o);let i=await B({name:o,maxTasks:n.maxTasks}),s=await K({agentId:o,serverUrl:i.serverUrl,token:i.token,key:i.key,name:i.name??o,workspaceRoot:i.workspaceRoot,machineId:i.machineId,maxTasks:i.maxTasks});console.log(`\u2705 Daemon \u5DF2\u91CD\u542F (PID: ${s.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 n=>{try{let o=n.agent;if(!o){let a=await j();if(!a){console.log("\u65E0\u6D3B\u8DC3 Agent");return}o=a.name}let i=await V(o),s=await j();if(console.log(`
|
|
57
|
+
Agent: ${i.agentId}`),console.log(`Running: ${i.running?"\u2705 yes":"\u274C no"}`),i.pid&&console.log(`PID: ${i.pid}`),i.uptimeMs!==null){let a=Math.floor(i.uptimeMs/1e3),l=Math.floor(a/60),m=Math.floor(l/60);console.log(`Uptime: ${m}h ${l%60}m ${a%60}s`)}console.log(`Log file: ${i.logFile}`),n.verbose&&s&&(console.log(`
|
|
58
|
+
--- Configuration ---`),console.log(`Server: ${s.serverUrl}`),console.log(`Token: ${ir(s.token)}`),s.machineId&&console.log(`MachineID: ${s.machineId}`),s.workspaceRoot&&console.log(`Workspace: ${s.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 n=>{try{let o=n.agent;if(!o){let a=await j();if(!a)throw new Error("\u672A\u6307\u5B9A --agent \u4E14\u65E0\u6D3B\u8DC3 Agent");o=a.name}let i=H(o),s=parseInt(n.n,10)||50;if(n.follow){let a=await Ut(i,"utf8").catch(()=>"");if(a){let m=a.trimEnd().split(`
|
|
59
59
|
`);console.log(m.slice(-s).join(`
|
|
60
|
-
`))}let l=
|
|
60
|
+
`))}let l=a.length;sr(i,{interval:500},()=>{try{let m=ar(i);if(m.size>l){let d=cr(i,"r"),g=Buffer.alloc(m.size-l);lr(d,g,0,g.length,l),mr(d),process.stdout.write(g.toString("utf8")),l=m.size}}catch{}})}else{let a=await Ut(i,"utf8").catch(()=>"");if(!a){console.log(`\u6682\u65E0\u65E5\u5FD7 (${i})`);return}let l=a.trimEnd().split(`
|
|
61
61
|
`);console.log(l.slice(-s).join(`
|
|
62
|
-
`))}}catch(o){
|
|
63
|
-
Agent: ${n.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
|
|
62
|
+
`))}}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 Oe("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 n=>{try{P()||(console.error("\u274C \u5F00\u673A\u81EA\u542F\u5F53\u524D\u4EC5\u652F\u6301 macOS"),process.exit(1)),await Mt(n.agentId,{maxTasks:n.maxTasks?parseInt(n.maxTasks,10):void 0}),console.log("\u2705 \u81EA\u542F\u52A8\u5DF2\u542F\u7528"),console.log(` Agent: ${n.agentId}`),console.log(` Plist: ~/Library/LaunchAgents/com.alibaba.aitable-workflow.daemon.${n.agentId}.plist`)}catch(o){S.error("cli","autostart enable \u5931\u8D25",{error:o instanceof Error?o.message:String(o)}),process.exit(1)}})).addCommand(new Oe("disable").description("\u5173\u95ED macOS \u767B\u5F55\u81EA\u542F\u52A8").requiredOption("--agent-id <id>","Agent ID / \u540D\u79F0").action(async n=>{try{P()||(console.error("\u274C \u5F00\u673A\u81EA\u542F\u5F53\u524D\u4EC5\u652F\u6301 macOS"),process.exit(1)),await Ft(n.agentId),console.log(`\u2705 \u81EA\u542F\u52A8\u5DF2\u5173\u95ED (${n.agentId})`)}catch(o){S.error("cli","autostart disable \u5931\u8D25",{error:o instanceof Error?o.message:String(o)}),process.exit(1)}})).addCommand(new Oe("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 n=>{try{if(P()||(console.error("\u274C \u5F00\u673A\u81EA\u542F\u5F53\u524D\u4EC5\u652F\u6301 macOS"),process.exit(1)),n.agentId){let o=await _e(n.agentId);console.log(`
|
|
63
|
+
Agent: ${n.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 Bt();if(o.length===0){console.log("\u65E0\u5DF2\u6CE8\u518C\u7684 Agent");return}for(let i of o){let s=await _e(i.name),a=s.running?`running (PID: ${s.pid})`:s.loaded?"loaded":s.installed?"installed":"not installed";console.log(` ${i.name}: ${a}`)}}}catch(o){S.error("cli","autostart status \u5931\u8D25",{error:o instanceof Error?o.message:String(o)}),process.exit(1)}}))}c(Wt,"registerDaemonCommands");function Nt(r,e){r.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 j();if(!t)throw new Error("\u65E0\u6D3B\u8DC3 Agent");if(!(await V(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 ue(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)}})}c(Nt,"registerHeartbeatCommand");import{logger as pr,saveCredential as dr,findConflictingCredential as gr,maskSecret as ur}from"aitable-workflow-core";function Gt(r,e){r.command("connect").description("\u4E00\u952E\u6CE8\u518C + \u4FDD\u5B58\u51ED\u8BC1 + \u540E\u53F0\u542F\u52A8 daemon\uFF08\u5BF9\u6807 Harness connect\uFF09").requiredOption("--server-url <url>","Gateway / \u5E73\u53F0\u5730\u5740").option("--token <ownerToken>","owner-token\uFF08\u81EA\u6CE8\u518C\uFF0C\u4E0E --key \u4E8C\u9009\u4E00\uFF09").option("--key <machineKey>","per-machine key\uFF08sk_machine_*\uFF0C\u4E0E --token \u4E8C\u9009\u4E00\uFF09").requiredOption("--name <name>","Agent \u540D\u79F0").option("--workspace-root <dir>","\u5DE5\u4F5C\u533A\u6839\u76EE\u5F55\uFF08\u53EF\u9009\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.token&&!t.key)throw new Error("\u5FC5\u987B\u63D0\u4F9B --token\uFF08owner-token\uFF09\u6216 --key\uFF08per-machine key\uFF0Csk_machine_*\uFF09\u5176\u4E2D\u4E4B\u4E00\u3002");if(!t.force){let l=await gr(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 n=t.workspaceRoot?Pe(t.workspaceRoot,t.name):void 0,o={name:t.name,serverUrl:t.serverUrl,token:t.token??"",key:t.key,workspaceRoot:n,createdAt:new Date().toISOString()};if(await dr(o),console.log(`\u2705 Agent "${t.name}" \u5DF2\u6CE8\u518C\u5E76\u4FDD\u5B58\u51ED\u8BC1`),console.log(` Server: ${t.serverUrl}`),console.log(` ${t.token?"Token":"Key"}: ${ur(t.token??t.key??"")}`),n&&console.log(` Workspace: ${n}`),console.log(" \u51ED\u8BC1\u6587\u4EF6: ~/.aitable-workflow/credentials.json"),!t.start){t.foreground&&console.log(`
|
|
64
64
|
\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(`
|
|
65
65
|
\u{1F4A1} \u542F\u52A8 daemon: aitable-workflow daemon start \u6216 aitable-workflow relay`);return}if(t.foreground){console.log(`
|
|
66
|
-
\u{1F680} \u524D\u53F0\u542F\u52A8 relay\uFF08Ctrl-C \u9000\u51FA\uFF09...`),await
|
|
67
|
-
\u{1F680} Daemon \u5DF2\u540E\u53F0\u542F\u52A8`),console.log(` Agent: ${i}`),console.log(` PID: ${
|
|
68
|
-
\u{1F4CB} \u5E38\u7528\u547D\u4EE4\uFF1A`),console.log(` \u67E5\u770B\u72B6\u6001: aitable-workflow daemon status --agent ${i}`),console.log(` \u8DDF\u8E2A\u65E5\u5FD7: aitable-workflow daemon logs -f --agent ${i}`),console.log(` \u505C\u6B62: aitable-workflow daemon stop --agent ${i}`),console.log(` \u91CD\u542F: aitable-workflow daemon restart --agent ${i}`),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 ${i}`)}catch(n){
|
|
66
|
+
\u{1F680} \u524D\u53F0\u542F\u52A8 relay\uFF08Ctrl-C \u9000\u51FA\uFF09...`),await ge({serverUrl:t.serverUrl,token:t.token,key:t.key,name:t.name,workspaceRoot:n});return}let i=t.name,s=await B({serverUrl:t.serverUrl,token:t.token,key:t.key,workspaceRoot:t.workspaceRoot,name:i}),a=await K({agentId:i,serverUrl:s.serverUrl,token:s.token,key:s.key,name:s.name??i,workspaceRoot:s.workspaceRoot,machineId:s.machineId,maxTasks:s.maxTasks});console.log(`
|
|
67
|
+
\u{1F680} Daemon \u5DF2\u540E\u53F0\u542F\u52A8`),console.log(` Agent: ${i}`),console.log(` PID: ${a.pid}`),console.log(` Log: ~/.aitable-workflow/daemons/${i}/daemon.log`),console.log(`
|
|
68
|
+
\u{1F4CB} \u5E38\u7528\u547D\u4EE4\uFF1A`),console.log(` \u67E5\u770B\u72B6\u6001: aitable-workflow daemon status --agent ${i}`),console.log(` \u8DDF\u8E2A\u65E5\u5FD7: aitable-workflow daemon logs -f --agent ${i}`),console.log(` \u505C\u6B62: aitable-workflow daemon stop --agent ${i}`),console.log(` \u91CD\u542F: aitable-workflow daemon restart --agent ${i}`),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 ${i}`)}catch(n){pr.error("cli","connect \u5931\u8D25",{error:n instanceof Error?n.message:String(n)}),process.exit(1)}})}c(Gt,"registerConnectCommand");import{logger as he,listCredentials as fr,setActiveAgent as hr,getActiveCredential as Ht,readCredentials as wr,maskSecret as qt}from"aitable-workflow-core";function Kt(r,e){let t=r.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 n=await fr();if(n.length===0){console.log("\u6682\u65E0\u5DF2\u4FDD\u5B58\u7684 Agent\u3002\u4F7F\u7528 `aitable-workflow connect` \u6CE8\u518C\u3002");return}let o=await wr();console.log(`
|
|
69
69
|
\u5DF2\u4FDD\u5B58 ${n.length} \u4E2A Agent\uFF08\u6D3B\u8DC3: ${o.activeAgent??"\u65E0"}\uFF09:
|
|
70
|
-
`);for(let i of n){let s=i.name===o.activeAgent?" \u2190 active":"";console.log(` \u2022 ${i.name}${s}`),console.log(` Server: ${i.serverUrl}`),console.log(` Token: ${
|
|
71
|
-
`);return}let l=
|
|
72
|
-
${l} Agent: ${
|
|
70
|
+
`);for(let i of n){let s=i.name===o.activeAgent?" \u2190 active":"";console.log(` \u2022 ${i.name}${s}`),console.log(` Server: ${i.serverUrl}`),console.log(` Token: ${qt(i.token)}`),i.machineId&&console.log(` MachineID: ${i.machineId}`),i.workspaceRoot&&console.log(` Workspace: ${i.workspaceRoot}`),console.log(` Created: ${i.createdAt}`)}console.log("")}catch(n){he.error("cli","agent list \u5931\u8D25",{error:n instanceof Error?n.message:String(n)}),process.exit(1)}}),t.command("use <name>").description("\u5207\u6362\u6D3B\u8DC3 Agent").action(async n=>{try{let o=await hr(n);console.log(`\u2705 \u5DF2\u5207\u6362\u5230 Agent "${o.activeAgent}"`)}catch(o){he.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 n=await Ht();if(!n){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: ${n.name}`),console.log(`Server: ${n.serverUrl}`),console.log(`Token: ${qt(n.token)}`),n.machineId&&console.log(`MachineID: ${n.machineId}`),n.workspaceRoot&&console.log(`Workspace: ${n.workspaceRoot}`)}catch(n){he.error("cli","agent whoami \u5931\u8D25",{error:n instanceof Error?n.message:String(n)}),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 n=>{try{let o=await Ht();if(!o){console.log("\u65E0\u6D3B\u8DC3 Agent\u3002\u4F7F\u7528 `aitable-workflow connect` \u6CE8\u518C\u3002");return}let i=await V(o.name),s=await ue(o.name),a={agent:o.name,serverUrl:o.serverUrl,connectionState:i.running?s.connectionState:"stopped",machineId:s.machineId??o.machineId??null,lastHeartbeatAt:s.lastHeartbeatAt,runningTasks:s.runningTasks,queuedTasks:s.queuedTasks,lastDisconnectReason:s.lastDisconnectReason,pid:i.pid};if(n.json){process.stdout.write(JSON.stringify(a,null,2)+`
|
|
71
|
+
`);return}let l=a.connectionState==="connected"?"\u{1F7E2}":a.connectionState==="reconnecting"?"\u{1F7E1}":"\u{1F534}";console.log(`
|
|
72
|
+
${l} Agent: ${a.agent}`),console.log(` Server: ${a.serverUrl}`),console.log(` Connection: ${a.connectionState}`),a.machineId&&console.log(` MachineID: ${a.machineId}`),a.lastHeartbeatAt&&console.log(` Last HB: ${a.lastHeartbeatAt}`),i.running&&(console.log(` PID: ${a.pid}`),console.log(` Tasks: ${a.runningTasks} running, ${a.queuedTasks} queued`)),a.lastDisconnectReason&&console.log(` Last Error: ${a.lastDisconnectReason}`),console.log("")}catch(o){he.error("cli","agent status \u5931\u8D25",{error:o instanceof Error?o.message:String(o)}),process.exit(1)}})}c(Kt,"registerAgentCommands");import{logger as yr}from"aitable-workflow-core";function Vt(r,e){r.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("--key <machineKey>","per-machine key\uFF08sk_machine_*\uFF09").option("--token <ownerToken>","owner-token \u81EA\u6CE8\u518C\uFF08\u4E5F\u53EF\u7528 AITABLE_RELAY_TOKEN\uFF1B\u4F18\u5148\u4E8E --key\uFF09").option("--name <name>","\u81EA\u6CE8\u518C\u673A\u5668\u540D\uFF08\u53EF\u9009\uFF0C\u7F3A\u7701\u81EA\u52A8\u4F7F\u7528\u4E3B\u673A\u540D\uFF1Bowner+name \u5E42\u7B49\u952E\uFF0C\u591A\u673A\u573A\u666F\u5EFA\u8BAE\u663E\u5F0F\u6307\u5B9A\u4EE5\u907F\u514D hostname \u51B2\u7A81\u4E92\u76F8\u9876\u8FDE\u63A5\uFF1B\u4E5F\u53EF\u7528 AITABLE_RELAY_NAME\uFF09").option("--desc <description>","\u81EA\u6CE8\u518C\u673A\u5668\u63CF\u8FF0\uFF08\u4E5F\u53EF\u7528 AITABLE_RELAY_DESC\uFF09").option("--workspace-root <dir>","\u5DE5\u4F5C\u533A\u6839\u76EE\u5F55\uFF08\u4E5F\u53EF\u7528 AITABLE_RELAY_WORKSPACE_ROOT\uFF09").option("--machine-id <id>","\u7A33\u5B9A\u673A\u5668\u8EAB\u4EFD\uFF08\u4E5F\u53EF\u7528 AITABLE_RELAY_MACHINE_ID\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").action(t=>{try{ge(t)}catch(n){yr.error("cli","relay \u542F\u52A8\u5931\u8D25",{error:n instanceof Error?n.message:String(n)}),process.exit(1)}})}c(Vt,"registerRelayCommand");import{loadSettings as Yt,loadWorkflowTemplate as vr,checkWorkflowRecipes as kr,Tracer as br}from"aitable-workflow-core";import Cr from"path";function Jt(r,e){r.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,n)=>{try{if(n.recipes||n.validate){await Rr(n);return}let o=await Yt(n.config),i=Cr.resolve(o.configDir,o.agent.trace_dir),s=new br(i),a=parseInt(n.limit,10)||10,l;if(n.latest||!t){if(l=await s.getLatestTraces(a),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(`
|
|
73
73
|
\u{1F4C4} \u6700\u8FD1 ${l.length} \u6761\u6267\u884C\u8BB0\u5F55:
|
|
74
74
|
`)}else{if(l=await s.getTraces(t),l.length===0){console.log(`\u26A0\uFE0F \u672A\u627E\u5230\u5DE5\u5355 ${t} \u7684 trace \u8BB0\u5F55\u3002`);return}n.step&&(l=l.filter(m=>m.step_id===n.step)),console.log(`
|
|
75
75
|
\u{1F4C4} \u5DE5\u5355 ${t} \u7684\u6267\u884C\u5386\u53F2 (${l.length} \u6B65):
|
|
76
|
-
`)}for(let m of l){let d=m.status==="success"?"\u2705":m.status==="failed"?"\u274C":"\u23F8\uFE0F",g=(m.duration_ms/1e3).toFixed(1);console.log(`${d} [${m.step_id}] ${m.step_name} \u2014 ${g}s \u2014 ${m.status.toUpperCase()}`);for(let[u,p]of m.llm_calls.entries()){let v=u===m.llm_calls.length-1,I=v?" \u2514\u2500":" \u251C\u2500",x=v?" ":" \u2502 ",z=(p.duration_ms/1e3).toFixed(1);console.log(`${I} LLM: ${p.model} (${z}s)`),console.log(`${x}Input: ${p.prompt_summary.slice(0,80)}${p.prompt_summary.length>80?"...":""}`),console.log(`${x}Output: ${p.response_summary.slice(0,100)}${p.response_summary.length>100?"...":""}`)}if(Object.keys(m.outputs).length>0){let u=Object.entries(m.outputs).map(([p,v])=>`${p}=${typeof v=="string"?v.slice(0,50):JSON.stringify(v)}`).join(", ");console.log(` \u2514\u2500 Outputs: ${u}`)}m.error&&console.log(` \u2514\u2500 Error: ${m.error}`),console.log()}}catch(o){console.error(`\u2717 inspect \u5931\u8D25: ${o instanceof Error?o.message:String(o)}`),process.exit(1)}})}
|
|
76
|
+
`)}for(let m of l){let d=m.status==="success"?"\u2705":m.status==="failed"?"\u274C":"\u23F8\uFE0F",g=(m.duration_ms/1e3).toFixed(1);console.log(`${d} [${m.step_id}] ${m.step_name} \u2014 ${g}s \u2014 ${m.status.toUpperCase()}`);for(let[u,p]of m.llm_calls.entries()){let v=u===m.llm_calls.length-1,I=v?" \u2514\u2500":" \u251C\u2500",x=v?" ":" \u2502 ",z=(p.duration_ms/1e3).toFixed(1);console.log(`${I} LLM: ${p.model} (${z}s)`),console.log(`${x}Input: ${p.prompt_summary.slice(0,80)}${p.prompt_summary.length>80?"...":""}`),console.log(`${x}Output: ${p.response_summary.slice(0,100)}${p.response_summary.length>100?"...":""}`)}if(Object.keys(m.outputs).length>0){let u=Object.entries(m.outputs).map(([p,v])=>`${p}=${typeof v=="string"?v.slice(0,50):JSON.stringify(v)}`).join(", ");console.log(` \u2514\u2500 Outputs: ${u}`)}m.error&&console.log(` \u2514\u2500 Error: ${m.error}`),console.log()}}catch(o){console.error(`\u2717 inspect \u5931\u8D25: ${o instanceof Error?o.message:String(o)}`),process.exit(1)}})}c(Jt,"registerInspectCommand");async function Rr(r){let e=await Yt(r.config),t=r.workflow?e.workflowEntries.find(s=>s.id===r.workflow):e.workflowEntries[0];t||(console.error(`\u2717 \u672A\u627E\u5230\u5DE5\u4F5C\u6D41\u300C${r.workflow}\u300D\u3002\u53EF\u7528\uFF1A${e.workflowEntries.map(s=>s.id).join(", ")}`),process.exit(1));let n=await vr(t.templatePath,{envSource:e.envSource}),{issues:o,rows:i}=await kr(t.recipeDir,n);if(r.recipes){console.log(`
|
|
77
77
|
\u{1F4CB} \u5DE5\u4F5C\u6D41\u300C${n.meta.name}\u300D(${t.id}) \u7684 recipe schema:
|
|
78
|
-
`);for(let s of i){let
|
|
78
|
+
`);for(let s of i){let a=s.configSummary.length>0?s.configSummary.join(", "):"(none)",l=s.loaded?"":" \u26A0 \u52A0\u8F7D\u5931\u8D25";console.log(` [${s.stepId} \u2192 ${s.recipeId}]${l}`),console.log(` config: ${a}`),console.log()}}if(r.validate)if(o.length===0)console.log(`
|
|
79
79
|
\u2705 \u5DE5\u4F5C\u6D41\u300C${n.meta.name}\u300D(${t.id}) \u5168\u90E8\u6B65\u9AA4\u6821\u9A8C\u901A\u8FC7
|
|
80
|
-
`);else{let s=o.filter(l=>l.level==="error"),
|
|
81
|
-
\u6821\u9A8C\u7ED3\u679C\uFF1A${s.length} \u4E2A\u9519\u8BEF\uFF0C${
|
|
82
|
-
`);for(let l of o){let m=l.level==="error"?"\u274C":"\u26A0\uFE0F ";console.log(` ${m} [${l.stepId} \u2192 ${l.recipeId}] ${l.message}`)}console.log(),s.length>0&&process.exit(1)}}
|
|
80
|
+
`);else{let s=o.filter(l=>l.level==="error"),a=o.filter(l=>l.level==="warn");console.log(`
|
|
81
|
+
\u6821\u9A8C\u7ED3\u679C\uFF1A${s.length} \u4E2A\u9519\u8BEF\uFF0C${a.length} \u4E2A\u8B66\u544A
|
|
82
|
+
`);for(let l of o){let m=l.level==="error"?"\u274C":"\u26A0\uFE0F ";console.log(` ${m} [${l.stepId} \u2192 ${l.recipeId}] ${l.message}`)}console.log(),s.length>0&&process.exit(1)}}c(Rr,"runRecipeInspect");import{runKbCompileCommand as Ir,runKbUpdateCommand as Sr,runKbStatusCommand as Ar,runKbIngestCommand as xr,runKbCleanupCommand as Er}from"aitable-workflow-core";function zt(r,e){let t=r.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(n,o)=>{try{await Ir(n,o)}catch(i){console.error(`\u2717 kb compile \u5931\u8D25: ${i instanceof Error?i.message:String(i)}`),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(n,o)=>{try{await Sr(n,o)}catch(i){console.error(`\u2717 kb update \u5931\u8D25: ${i instanceof Error?i.message:String(i)}`),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(n,o)=>{try{await Ar(n,o)}catch(i){console.error(`\u2717 kb status \u5931\u8D25: ${i instanceof Error?i.message:String(i)}`),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(n,o)=>{try{await xr(n,o)}catch(i){console.error(`\u2717 kb ingest \u5931\u8D25: ${i instanceof Error?i.message:String(i)}`),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(n,o)=>{try{await Er(n,o)}catch(i){console.error(`\u2717 kb cleanup \u5931\u8D25: ${i instanceof Error?i.message:String(i)}`),process.exit(1)}})}c(zt,"registerKbCommands");import we from"path";import{BotProvisioner as Tr,BotProvisionError as Zt,DwsDevRunner as Me,buildBotApprovalReportLines as $r,defaultProvisionStatePath as Fe,loadProvisionState as en,resolveConfigPath as Be,validateProvisionName as Pr}from"aitable-workflow-core";import{logger as Xt}from"aitable-workflow-core";function tn(r,e,t={}){let n=t.exit??(i=>process.exit(i)),o=r.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("--bind <target>","\u51ED\u636E\u7ED1\u5B9A\u76EE\u6807\uFF1Aenv\uFF08\u5199 .env DINGTALK_ROBOTS\uFF09| none","env").option("--group <group>","\u62C9\u7FA4\u76EE\u6807\uFF1AopenConversationId \u6216\u7FA4\u540D\uFF08\u9700\u5DF2\u5B8C\u6210 publish \u76F8\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("--env-file <path>",".env \u6587\u4EF6\u8DEF\u5F84\uFF08\u7F3A\u7701 <configDir>/.env\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 i=>{try{let s=await jr(i,e,t);s!==0&&n(s)}catch(s){Le(s),n(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 i=>{try{let s=await _r(i,e,t);s!==0&&n(s)}catch(s){Le(s),n(1)}});for(let[i,s]of[["disable","\u505C\u7528"],["enable","\u542F\u7528"]])o.command(i).description(`${s}\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 a=>{try{let l=await Or(i,a,e,t);l!==0&&n(l)}catch(l){Le(l),n(1)}})}c(tn,"registerBotCommands");async function jr(r,e,t){let n=Pr(r.name);if(n)return console.error(`\u274C ${n}`),1;if(r.bind&&r.bind!=="env"&&r.bind!=="none")return console.error(`\u274C --bind \u53EA\u652F\u6301 env | none\uFF0C\u6536\u5230: ${r.bind}`),1;let o=we.dirname(await Be(r.config??e.defaultConfig)),i=r.stateFile??Fe(o),s=r.envFile??we.join(o,".env");r.publish&&!r.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 a=t.createProvisioner?.()??new Tr({runner:new Me}),l={name:r.name,robotName:r.robotName,desc:r.desc,bind:r.bind??"env",envFile:s,stateFile:i,publish:r.publish,approverUserId:r.approverUserId,group:r.group};console.log(`\u{1F916} \u5F00\u59CB provision\u300C${r.name}\u300D\uFF08\u72B6\u6001\u6587\u4EF6: ${i}\uFF09`);let m=await a.provision(l);return Dr(m,{stateFile:i,envFile:s,bind:l.bind??"env"})}c(jr,"runProvision");function Dr(r,e){switch(r.status){case"bound":{console.log(`
|
|
83
83
|
\u2705 \u51ED\u636E\u5DF2\u7ED1\u5B9A\uFF08bound \u76F8\uFF09\u2014\u2014\u5F15\u64CE\u5EFA\u8054\u53EF\u5148\u884C\u3002`),e.bind==="env"?(console.log(` \u51ED\u636E\u5199\u5165: ${e.envFile}\uFF08DINGTALK_ROBOTS\uFF0CcredRef=${r.state.clientId??"?"}\uFF09`),console.log(" \u8FD0\u884C\u4E2D\u7684 dingtalk_stream \u6E90\u4F1A\u7ECF ConfigHotReload \u70ED\u66F4\uFF0C\u65E0\u9700\u91CD\u542F\u3002")):console.log(" --bind none\uFF1A\u672A\u5199 .env\uFF1B\u9700\u8981\u65F6\u7528 `dws dev app credentials get` \u590D\u53D6\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(`
|
|
84
84
|
\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(`
|
|
85
85
|
\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>`");break}case"grouped":{console.log(`
|
|
86
86
|
\u2705 \u5DF2\u62C9\u7FA4\uFF08grouped \u76F8\uFF09\u2014\u2014\u5168\u94FE\u8DEF\u5B8C\u6210\u3002`);break}case"approver_required":{console.error(`
|
|
87
87
|
\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 r.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 console.error(`
|
|
88
|
-
\u274C provision \u5931\u8D25: ${r.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}
|
|
88
|
+
\u274C provision \u5931\u8D25: ${r.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}c(Dr,"printProvisionResult");async function _r(r,e,t){let n=we.dirname(await Be(r.config??e.defaultConfig)),o=r.stateFile??Fe(n),i=await en(o),s,a=null,l=null;if(r.refresh&&i?.unifiedAppId&&i.versionId){let d=t.createRunner?.()??new Me;try{s=(await d.versionStatus(i.unifiedAppId,i.versionId)).versionStatus}catch(g){l=Qt(g)}if(!l)try{a=await d.checkApproval(i.unifiedAppId,i.versionId)}catch(g){l=Qt(g)}}let m=$r({state:i,versionStatus:s,approval:a,error:l});return console.log(m.map(d=>` ${d}`).join(`
|
|
89
89
|
`)),console.log(`
|
|
90
|
-
\u72B6\u6001\u6587\u4EF6: ${o}`),i&&!r.refresh&&(i.phase==="publish_pending"||i.phase==="version_created")&&console.log(" \u63D0\u793A: \u52A0 --refresh \u5B9E\u65F6\u67E5\u8BE2\u5BA1\u6279\u72B6\u6001\u4E0E\u5019\u9009\u3002"),i?0:1}
|
|
91
|
-
\u2705 \u5DF2${s}${l}\u3002`),r==="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}
|
|
92
|
-
\u274C ${r.message}`),console.error(` \u21B3 ${r.guidance}`);else{let e=r instanceof Error?r.message:String(r);
|
|
93
|
-
\u274C ${e}`)}}
|
|
90
|
+
\u72B6\u6001\u6587\u4EF6: ${o}`),i&&!r.refresh&&(i.phase==="publish_pending"||i.phase==="version_created")&&console.log(" \u63D0\u793A: \u52A0 --refresh \u5B9E\u65F6\u67E5\u8BE2\u5BA1\u6279\u72B6\u6001\u4E0E\u5019\u9009\u3002"),i?0:1}c(_r,"runStatus");function Qt(r){return r instanceof Zt?`${r.message}\uFF08${r.guidance}\uFF09`:r instanceof Error?r.message:String(r)}c(Qt,"describeError");async function Or(r,e,t,n){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 i=e.unifiedAppId?.trim();if(!i){let d=we.dirname(await Be(e.config??t.defaultConfig)),g=e.stateFile??Fe(d);if(i=(await en(g))?.unifiedAppId??void 0,!i)return console.error(`\u274C \u65E0\u6CD5\u786E\u5B9A\u76EE\u6807\u5E94\u7528\uFF1A\u72B6\u6001\u6587\u4EF6\u65E0 unifiedAppId\uFF08${g}\uFF09\uFF0C\u8BF7\u7528 --unified-app-id \u663E\u5F0F\u6307\u5B9A\u3002`),1}let s=r==="disable"?"\u505C\u7528":"\u542F\u7528",a=n.createRunner?.()??new Me,l=o==="app"?"\u6574\u4E2A\u5E94\u7528":"\u673A\u5668\u4EBA\u80FD\u529B";return console.log(`\u{1F916} ${s}${l}\uFF08unifiedAppId=${i}\uFF09`),o==="app"&&r==="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:a.disableRobot.bind(a),app:a.disableApp.bind(a)},enable:{robot:a.enableRobot.bind(a),app:a.enableApp.bind(a)}}[r][o](i),console.log(`
|
|
91
|
+
\u2705 \u5DF2${s}${l}\u3002`),r==="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}c(Or,"runToggle");function Le(r){if(r instanceof Zt)Xt.error("cli","bot \u547D\u4EE4\u5931\u8D25",{kind:r.kind}),console.error(`
|
|
92
|
+
\u274C ${r.message}`),console.error(` \u21B3 ${r.guidance}`);else{let e=r instanceof Error?r.message:String(r);Xt.error("cli","bot \u547D\u4EE4\u5931\u8D25",{error:e}),console.error(`
|
|
93
|
+
\u274C ${e}`)}}c(Le,"failWithDiagnostics");var sn=rn.dirname(Br(import.meta.url));on({override:!1,quiet:!0});on({path:rn.resolve(sn,"..",".env"),override:!1,quiet:!0});var an=Ve(),Ue=ke(an),Ur=Ye(an);Fr({version:Ue});var f=new Lr().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(Ue).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",async(r,e)=>{e.name()!=="init"&&await Mr()}).hook("preAction",(r,e)=>{r.opts().debug?nn.setLevel("debug"):(e.name()==="config"||e.parent?.name()==="config")&&nn.setLevel("warn")}),h={cliDir:sn,version:Ue,packageVersions:Ur,defaultConfig:Je};ze(f,h);Xe(f,h);Qe(f,h);tt(f,h);rt(f,h);st(f,h);lt(f,h);mt(f,h);Ne(f,h);pt(f,h);dt(f,h);gt(f,h);ft(f,h);Wt(f,h);Gt(f,h);Kt(f,h);Nt(f,h);Vt(f,h);Jt(f,h);zt(f,h);tn(f,h);await f.parseAsync();
|