aitable-workflow-cli 0.1.28-beta.1789632898670 → 0.1.28

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/cli.js CHANGED
@@ -1,99 +1,587 @@
1
1
  #!/usr/bin/env node
2
- import{a as He,b as Je,m as Ve}from"./chunk-YDJTCQW4.js";import"./chunk-4B6V7VHM.js";import{b as X,d as W,e as ke,f as qe,g as Q}from"./chunk-N2ATMPTO.js";import{a as c}from"./chunk-EI7MMDWY.js";import{config as dn}from"dotenv";import{Command as di}from"commander";import{logger as mn,activateGlobalDwsOnPath as ui,initSlsReport as gi}from"aitable-workflow-core";import{createRequire as hn}from"module";var Ke="aitable-workflow-",wn=/^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?$/;function Ye(){try{return hn(import.meta.url)("../package.json")}catch{return{}}}c(Ye,"loadCliPackageManifest");function be(r){return r.version??"0.0.0"}c(be,"resolveCliVersion");function ze(r){let t=be(r),e={};r.name?.startsWith(Ke)&&(e[r.name]=t);for(let[n,o]of Object.entries(r.dependencies??{}))n.startsWith(Ke)&&(e[n]=wn.test(o)?o:t);return e}c(ze,"resolveMonorepoPackageVersions");import un from"path";import{fileURLToPath as fi}from"url";var Xe="./aitable-workflow.config.yml";import{runInit as yn,logger as vn}from"aitable-workflow-core";import kn from"path";function Qe(r,t){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\u53EF\u7528\u6A21\u677F\u811A\u624B\u67B6").option("-c, --config <path>","\u76EE\u6807\u76EE\u5F55\u6216\u914D\u7F6E\u6587\u4EF6\u8DEF\u5F84\uFF08\u9ED8\u8BA4\u5F53\u524D\u76EE\u5F55\uFF09").option("-f, --force","\u8986\u76D6\u5DF2\u6709\u914D\u7F6E\u6587\u4EF6").option("-y, --yes","\u4F7F\u7528\u9ED8\u8BA4\u503C\u8DF3\u8FC7\u4EA4\u4E92\u5F0F\u5411\u5BFC").option("-t, --template <name>","\u4ECE\u5F53\u524D\u53D1\u884C\u5305\u63D0\u4F9B\u7684\u6A21\u677F\u811A\u624B\u67B6\uFF0C\u62F7\u8D1D\u5B8C\u6574\u53EF\u8FD0\u884C\u9879\u76EE\u5230\u76EE\u6807\u76EE\u5F55").option("--profile <name>","\u9009\u5B9A\u6A21\u677F\u4E0B\u7684 profile \u4E1A\u52A1\u5305\uFF0C\u8986\u76D6\u5F0F\u53E0\u52A0\u5230\u5B9E\u4F8B").action(async e=>{try{await yn({config:e.config,force:!!e.force,yes:!!e.yes,template:e.template,profile:e.profile,templatesDir:kn.resolve(t.cliDir,"..","templates"),templatePackageVersions:t.packageVersions,cliVersion:t.version})}catch(n){n instanceof Error&&n.message.includes("cancelled")&&process.exit(0),vn.error("cli","\u521D\u59CB\u5316\u5931\u8D25",{error:n instanceof Error?n.message:String(n)}),process.exit(1)}})}c(Qe,"registerInitCommand");import{runMigrate as bn,logger as Rn}from"aitable-workflow-core";import Cn from"path";function Ze(r,t){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",t.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 e=>{try{await bn({config:e.config,from:e.from,to:e.to,dryRun:e.dryRun,noBackup:e.backup===!1,force:e.force,template:e.template,profile:e.profile,rollback:e.rollback,list:e.list,templatesDir:Cn.resolve(t.cliDir,"..","templates"),templatePackageVersions:t.packageVersions,cliVersion:t.version})}catch(n){n instanceof Error&&n.message.includes("cancelled")&&process.exit(0),Rn.error("cli","migrate \u5931\u8D25",{error:n instanceof Error?n.message:String(n)}),process.exit(1)}})}c(Ze,"registerMigrateCommand");import{runDesignCommand as In,logger as Sn}from"aitable-workflow-core";function et(r,t){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",t.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 e=>{try{await In(e)}catch(n){n instanceof Error&&n.message.includes("cancelled")&&process.exit(0),Sn.error("cli","design \u5931\u8D25",{error:n instanceof Error?n.message:String(n)}),process.exit(1)}})}c(et,"registerDesignCommand");import{runCheck as An,runSetupCommand as En,checkMigrateHint as xn,logger as Tn,reportCliEvent as Z,setReportProject as $n}from"aitable-workflow-core";import nt from"path";function Re(r){return r.skipConfig||r.skipConfigIfValid&&r.configValid===!0}c(Re,"canSkipSetupConfig");function tt(r){return Re(r)?"setup":r.uiEnabled&&r.webAvailable?"web":"cli"}c(tt,"resolveSetupConfigRoute");function ot(r,t){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",t.defaultConfig).option("--no-clean","\u4E0D\u6E05\u7406\u7A7A\u767D\u884C").option("--no-kb","\u8DF3\u8FC7\u77E5\u8BC6\u5E93\u51C6\u5907/\u7F16\u8BD1").option("--kb-full","\u5F3A\u5236\u5168\u91CF\u91CD\u7F16\u8BD1\u77E5\u8BC6\u5E93").option("--skip-config","\u8DF3\u8FC7\u524D\u7F6E\u7684\u4EA4\u4E92\u5F0F\u914D\u7F6E\u6821\u9A8C\uFF08CI/\u5DF2\u786E\u8BA4\u914D\u7F6E\u65F6\u4F7F\u7528\uFF09").option("--skip-config-if-valid","\u5148\u6821\u9A8C\u914D\u7F6E\uFF1B\u65E0\u963B\u65AD\u9879\u65F6\u8DF3\u8FC7\u914D\u7F6E\u754C\u9762\u5E76\u76F4\u63A5\u5F00\u59CB\u642D\u5EFA").option("--no-ui","\u5F3A\u5236\u4F7F\u7528\u547D\u4EE4\u884C\u4EA4\u4E92\uFF08\u8DF3\u8FC7\u53EF\u89C6\u5316\u914D\u7F6E\u754C\u9762\uFF09").option("--only <round>","\u53EA\u6267\u884C\u6307\u5B9A\u73AF\u8282\uFF1B\u5F53\u524D\u4EC5\u652F\u6301 automations\uFF08\u6309 profile \u5F00\u5173\u5BF9\u9F50\u81EA\u52A8\u5316\uFF0C\u4E0D\u5EFA\u8868\u3001\u4E0D\u7F16\u77E5\u8BC6\u5E93\uFF09").action(async e=>{e.only!==void 0&&e.only!=="automations"&&(console.error(`\u2717 --only \u4E0D\u652F\u6301\u300C${e.only}\u300D\uFF0C\u5F53\u524D\u552F\u4E00\u5408\u6CD5\u503C\uFF1Aautomations`),process.exit(1));let n=e.only==="automations";$n(e.config);let o=Date.now();Z("setup.start",{skipConfig:e.skipConfig===!0,clean:e.clean,kb:e.kb,kbFull:e.kbFull===!0,ui:e.ui!==!1,...n?{only:"automations"}:{}});try{if(await xn(nt.dirname(nt.resolve(e.config)),t.version),!e.skipConfig&&!n){let i=e.ui!==!1,s=!1;if(e.skipConfigIfValid){console.log("\u{1F4CB} \u6B65\u9AA4 1/2\uFF1A\u6821\u9A8C\u9879\u76EE\u914D\u7F6E");let a=await An({configPath:e.config});if(s=Re({skipConfig:!1,skipConfigIfValid:!0,configValid:a.ok}),s){let l=[];a.summary.warnings>0&&l.push(`${a.summary.warnings} \u9879\u8B66\u544A`),a.summary.suggestions>0&&l.push(`${a.summary.suggestions} \u9879\u5EFA\u8BAE`);let p=l.length>0?`\uFF08${l.join("\uFF0C")}\uFF0C\u5747\u4E0D\u963B\u65AD\uFF09`:"";console.log(`\u2713 \u914D\u7F6E\u65E0\u963B\u65AD\u9879${p}\uFF0C\u8DF3\u8FC7\u914D\u7F6E\u754C\u9762\u5E76\u7EE7\u7EED\u642D\u5EFA\u3002`)}else console.log(`\u2139 \u68C0\u6D4B\u5230 ${a.summary.errors} \u9879\u963B\u65AD\uFF0C\u8FDB\u5165\u914D\u7F6E\u73AF\u8282\u3002`)}if(!s&&i){let{hasWebRoot:a,runConfigUI:l}=await import("./config-ui-server-4SVD42Z3.js");if(tt({skipConfig:!1,skipConfigIfValid:e.skipConfigIfValid===!0,uiEnabled:i,webAvailable:a(),configValid:s})==="web"){console.log("\u{1F4CB} \u6B65\u9AA4 1/2\uFF1A\u53EF\u89C6\u5316\u914D\u7F6E\u754C\u9762");try{await l({configPath:e.config,setupOptions:{clean:e.clean,kb:e.kb,kbFull:e.kbFull}}),Z("setup.finish",{success:!0,route:"web",durationMs:Date.now()-o});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(!s){console.log("\u{1F4CB} \u6B65\u9AA4 1/2\uFF1A\u6821\u9A8C\u5E76\u8865\u9F50\u9879\u76EE\u914D\u7F6E");let{runConfigCommand:a}=await import("./config-command-7ECUJOEU.js");(await a({configPath:e.config,interactive:!0,offerSkipToBuild:!0})).ok||(console.error(`
2
+ import{a as st,b as it,m as at}from"./chunk-YDJTCQW4.js";import"./chunk-4B6V7VHM.js";import{b as Q,d as G,e as Se,f as ct,g as ee}from"./chunk-N2ATMPTO.js";import{a as c}from"./chunk-EI7MMDWY.js";import{config as jn}from"dotenv";import{Command as si}from"commander";import{logger as On,activateGlobalDwsOnPath as ii,initSlsReport as ai}from"aitable-workflow-core";import{createRequire as Hn}from"module";var lt="aitable-workflow-",Fn=/^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?$/;function dt(){try{return Hn(import.meta.url)("../package.json")}catch{return{}}}c(dt,"loadCliPackageManifest");function Ie(o){return o.version??"0.0.0"}c(Ie,"resolveCliVersion");function pt(o){let e=Ie(o),t={};o.name?.startsWith(lt)&&(t[o.name]=e);for(let[n,r]of Object.entries(o.dependencies??{}))n.startsWith(lt)&&(t[n]=Fn.test(r)?r:e);return t}c(pt,"resolveMonorepoPackageVersions");import Mn from"path";import{fileURLToPath as ci}from"url";var ut="./aitable-workflow.config.yml";import{runInit as Nn,logger as Un}from"aitable-workflow-core";import Wn from"path";function mt(o,e){o.command("init").description("\u4EA4\u4E92\u5F0F\u521D\u59CB\u5316 \u2014 \u9009\u62E9 Coding Agent\u3001\u914D\u7F6E\u5DE5\u4F5C\u76EE\u5F55\u3001\u63CF\u8FF0\u4E1A\u52A1\u573A\u666F\uFF1B\u6216\u7528 --template \u4ECE\u53EF\u7528\u6A21\u677F\u811A\u624B\u67B6").option("-c, --config <path>","\u76EE\u6807\u76EE\u5F55\u6216\u914D\u7F6E\u6587\u4EF6\u8DEF\u5F84\uFF08\u9ED8\u8BA4\u5F53\u524D\u76EE\u5F55\uFF09").option("-f, --force","\u8986\u76D6\u5DF2\u6709\u914D\u7F6E\u6587\u4EF6").option("-y, --yes","\u4F7F\u7528\u9ED8\u8BA4\u503C\u8DF3\u8FC7\u4EA4\u4E92\u5F0F\u5411\u5BFC").option("-t, --template <name>","\u4ECE\u5F53\u524D\u53D1\u884C\u5305\u63D0\u4F9B\u7684\u6A21\u677F\u811A\u624B\u67B6\uFF0C\u62F7\u8D1D\u5B8C\u6574\u53EF\u8FD0\u884C\u9879\u76EE\u5230\u76EE\u6807\u76EE\u5F55").option("--profile <name>","\u9009\u5B9A\u6A21\u677F\u4E0B\u7684 profile \u4E1A\u52A1\u5305\uFF0C\u8986\u76D6\u5F0F\u53E0\u52A0\u5230\u5B9E\u4F8B").action(async t=>{try{await Nn({config:t.config,force:!!t.force,yes:!!t.yes,template:t.template,profile:t.profile,templatesDir:Wn.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","\u521D\u59CB\u5316\u5931\u8D25",{error:n instanceof Error?n.message:String(n)}),process.exit(1)}})}c(mt,"registerInitCommand");import{runMigrate as Gn,logger as qn}from"aitable-workflow-core";import zn from"path";function ft(o,e){o.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:zn.resolve(e.cliDir,"..","templates"),templatePackageVersions:e.packageVersions,cliVersion:e.version})}catch(n){n instanceof Error&&n.message.includes("cancelled")&&process.exit(0),qn.error("cli","migrate \u5931\u8D25",{error:n instanceof Error?n.message:String(n)}),process.exit(1)}})}c(ft,"registerMigrateCommand");import{runDesignCommand as Jn,logger as Yn}from"aitable-workflow-core";function gt(o,e){o.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 Jn(t)}catch(n){n instanceof Error&&n.message.includes("cancelled")&&process.exit(0),Yn.error("cli","design \u5931\u8D25",{error:n instanceof Error?n.message:String(n)}),process.exit(1)}})}c(gt,"registerDesignCommand");import{runCheck as Vn,runSetupCommand as Kn,checkMigrateHint as Xn,logger as Zn,reportCliEvent as te,setReportProject as Qn}from"aitable-workflow-core";import vt from"path";function Te(o){return o.skipConfig||o.skipConfigIfValid&&o.configValid===!0}c(Te,"canSkipSetupConfig");function ht(o){return Te(o)?"setup":o.uiEnabled&&o.webAvailable?"web":"cli"}c(ht,"resolveSetupConfigRoute");function wt(o,e){o.command("setup").description("\u6821\u9A8C\u5E76\u8865\u9F50\u9879\u76EE\u914D\u7F6E\uFF0C\u518D\u521D\u59CB\u5316 AI \u8868\u683C\u7ED3\u6784 + \u51C6\u5907\u77E5\u8BC6\u5E93 \u2014 \u4E00\u6B21\u5B8C\u6210 config + \u5EFA\u8868").option("-c, --config <path>","\u914D\u7F6E\u6587\u4EF6\u8DEF\u5F84",e.defaultConfig).option("--no-clean","\u4E0D\u6E05\u7406\u7A7A\u767D\u884C").option("--no-kb","\u8DF3\u8FC7\u77E5\u8BC6\u5E93\u51C6\u5907/\u7F16\u8BD1").option("--kb-full","\u5F3A\u5236\u5168\u91CF\u91CD\u7F16\u8BD1\u77E5\u8BC6\u5E93").option("--skip-config","\u8DF3\u8FC7\u524D\u7F6E\u7684\u4EA4\u4E92\u5F0F\u914D\u7F6E\u6821\u9A8C\uFF08CI/\u5DF2\u786E\u8BA4\u914D\u7F6E\u65F6\u4F7F\u7528\uFF09").option("--skip-config-if-valid","\u5148\u6821\u9A8C\u914D\u7F6E\uFF1B\u65E0\u963B\u65AD\u9879\u65F6\u8DF3\u8FC7\u914D\u7F6E\u754C\u9762\u5E76\u76F4\u63A5\u5F00\u59CB\u642D\u5EFA").option("--no-ui","\u5F3A\u5236\u4F7F\u7528\u547D\u4EE4\u884C\u4EA4\u4E92\uFF08\u8DF3\u8FC7\u53EF\u89C6\u5316\u914D\u7F6E\u754C\u9762\uFF09").option("--only <round>","\u53EA\u6267\u884C\u6307\u5B9A\u73AF\u8282\uFF1B\u5F53\u524D\u4EC5\u652F\u6301 automations\uFF08\u6309 profile \u5F00\u5173\u5BF9\u9F50\u81EA\u52A8\u5316\uFF0C\u4E0D\u5EFA\u8868\u3001\u4E0D\u7F16\u77E5\u8BC6\u5E93\uFF09").action(async t=>{t.only!==void 0&&t.only!=="automations"&&(console.error(`\u2717 --only \u4E0D\u652F\u6301\u300C${t.only}\u300D\uFF0C\u5F53\u524D\u552F\u4E00\u5408\u6CD5\u503C\uFF1Aautomations`),process.exit(1));let n=t.only==="automations";Qn(t.config);let r=Date.now();te("setup.start",{skipConfig:t.skipConfig===!0,clean:t.clean,kb:t.kb,kbFull:t.kbFull===!0,ui:t.ui!==!1,...n?{only:"automations"}:{}});try{if(await Xn(vt.dirname(vt.resolve(t.config)),e.version),!t.skipConfig&&!n){let s=t.ui!==!1,i=!1;if(t.skipConfigIfValid){console.log("\u{1F4CB} \u6B65\u9AA4 1/2\uFF1A\u6821\u9A8C\u9879\u76EE\u914D\u7F6E");let a=await Vn({configPath:t.config});if(i=Te({skipConfig:!1,skipConfigIfValid:!0,configValid:a.ok}),i){let l=[];a.summary.warnings>0&&l.push(`${a.summary.warnings} \u9879\u8B66\u544A`),a.summary.suggestions>0&&l.push(`${a.summary.suggestions} \u9879\u5EFA\u8BAE`);let d=l.length>0?`\uFF08${l.join("\uFF0C")}\uFF0C\u5747\u4E0D\u963B\u65AD\uFF09`:"";console.log(`\u2713 \u914D\u7F6E\u65E0\u963B\u65AD\u9879${d}\uFF0C\u8DF3\u8FC7\u914D\u7F6E\u754C\u9762\u5E76\u7EE7\u7EED\u642D\u5EFA\u3002`)}else console.log(`\u2139 \u68C0\u6D4B\u5230 ${a.summary.errors} \u9879\u963B\u65AD\uFF0C\u8FDB\u5165\u914D\u7F6E\u73AF\u8282\u3002`)}if(!i&&s){let{hasWebRoot:a,runConfigUI:l}=await import("./config-ui-server-4SVD42Z3.js");if(ht({skipConfig:!1,skipConfigIfValid:t.skipConfigIfValid===!0,uiEnabled:s,webAvailable:a(),configValid:i})==="web"){console.log("\u{1F4CB} \u6B65\u9AA4 1/2\uFF1A\u53EF\u89C6\u5316\u914D\u7F6E\u754C\u9762");try{await l({configPath:t.config,setupOptions:{clean:t.clean,kb:t.kb,kbFull:t.kbFull}}),te("setup.finish",{success:!0,route:"web",durationMs:Date.now()-r});return}catch(p){console.warn(`
3
+ \u26A0 \u53EF\u89C6\u5316\u754C\u9762\u5F02\u5E38\uFF0C\u56DE\u9000\u5230\u547D\u4EE4\u884C\u4EA4\u4E92: ${p instanceof Error?p.message:String(p)}
4
+ `)}}}if(!i){console.log("\u{1F4CB} \u6B65\u9AA4 1/2\uFF1A\u6821\u9A8C\u5E76\u8865\u9F50\u9879\u76EE\u914D\u7F6E");let{runConfigCommand:a}=await import("./config-command-7ECUJOEU.js");(await a({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 En({config:e.config,clean:e.clean,kb:e.kb,...e.kbFull?{kbFull:!0}:{},...n?{only:"automations"}:{}}),await Z("setup.finish",{success:!0,durationMs:Date.now()-o})}catch(i){Tn.error("cli","setup \u5931\u8D25",{error:i instanceof Error?i.message:String(i)}),await Z("setup.finish",{success:!1,error:(i instanceof Error?i.message:String(i)).slice(0,500),durationMs:Date.now()-o}),process.exit(1)}})}c(ot,"registerSetupCommand");import rt from"path";import{createApp as it,ensureTsxRegistered as Pn,checkMigrateHint as jn,logger as k,runCheck as On}from"aitable-workflow-core";function _n(){let e=[],n=c(()=>{let o=Date.now();for(e.push(o);e.length>0&&o-e[0]>6e4;)e.shift();e.length>=10&&(k.error("cli",`60000ms \u5185\u53D1\u751F ${e.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=>{k.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=>{k.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(_n,"installLongRunningCrashGuards");function st(r,t){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",t.defaultConfig).option("-p, --port <number>","\u63A7\u5236\u53F0\u7AEF\u53E3\u9996\u9009\u503C\uFF08\u7F3A\u7701 8788\uFF0C\u4E0D\u53EF\u7528\u65F6\u5411\u4E0A\u907F\u8BA9 13 \u4E2A\u7AEF\u53E3\uFF1B\u591A\u9879\u76EE\u5E76\u884C\u65F6\u5EFA\u8BAE\u663E\u5F0F\u6307\u5B9A\uFF09").option("--no-open","\u542F\u52A8\u540E\u4E0D\u8981\u81EA\u52A8\u6253\u5F00\u6D4F\u89C8\u5668").option("--skip-config-if-valid","\u914D\u7F6E\u5DF2\u5B8C\u6574\u65F6\u76F4\u63A5\u542F\u52A8\u8FD0\u884C").action(async e=>{let n;if(e.port!==void 0){let o=Number.parseInt(e.port,10);(!Number.isFinite(o)||o<=0||o>65535)&&(k.error("cli",`--port \u53D6\u503C\u975E\u6CD5: "${e.port}"\uFF08\u9700\u4E3A 1-65535 \u6574\u6570\uFF09`),process.exit(1)),n=o}try{await jn(rt.dirname(rt.resolve(e.config)),t.version),_n(),await Pn();let o=await On({configPath:e.config}),i=!o.ok||o.summary.errors>0,s,a="setup";if(!i)try{a="runtime",s=await it(e.config,{})}catch(m){k.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)}),a="setup",s=void 0}a==="runtime"&&s?e.skipConfigIfValid?(k.info("cli","\u914D\u7F6E\u5DF2\u5B8C\u6574\uFF0C\u76F4\u63A5\u542F\u52A8\u8FD0\u884C"),s.start().catch(m=>{k.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)})})):k.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"):k.info("cli","\u914D\u7F6E\u4E0D\u5B8C\u6574\uFF0C\u63A7\u5236\u53F0\u5C06\u5F15\u5BFC\u5B8C\u6210\u642D\u5EFA");let l=!1,p=c(async()=>{l&&(k.warn("cli","\u518D\u6B21\u6536\u5230\u9000\u51FA\u4FE1\u53F7\uFF0C\u5F3A\u5236\u9000\u51FA"),process.exit(1)),l=!0,k.info("cli","\u6536\u5230\u9000\u51FA\u4FE1\u53F7\uFF0C\u6B63\u5728\u505C\u6B62\u8FD0\u884C...");try{await s?.stop()}finally{process.exit(0)}},"shutdown");process.on("SIGINT",p),process.on("SIGTERM",p),await Ve({configPath:e.config,mode:a,app:s,port:n,open:e.open,exitOnSetupError:!1,...a==="runtime"&&e.skipConfigIfValid?{initialRunStatus:{status:"running",since:new Date().toISOString(),lastError:null}}:{},...a==="setup"?{assembleApp:c(m=>it(m,{}),"assembleApp"),onAppAssembled:c(m=>{s=m,k.info("cli","\u63A7\u5236\u53F0\u5DF2\u5B8C\u6210 setup\u2192runtime \u664B\u5347\uFF0C\u53EF\u5728\u63A7\u5236\u53F0\u542F\u52A8\u8FD0\u884C")},"onAppAssembled")}:{}})}catch(o){k.error("cli","start \u547D\u4EE4\u5931\u8D25",{error:o instanceof Error?o.message:String(o)}),process.exit(1)}})}c(st,"registerStartCommand");import{createApp as Dn,ensureTsxRegistered as Ln,checkMigrateHint as Mn,logger as O,reportCliEvent as ee,setReportProject as Bn}from"aitable-workflow-core";import at from"path";function Fn(){let e=[],n=c(async()=>{let o=Date.now();for(e.push(o);e.length>0&&o-e[0]>6e4;)e.shift();e.length>=10&&(O.error("cli",`60000ms \u5185\u53D1\u751F ${e.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:e.length}),process.exit(1))},"recordCrashAndMaybeExit");process.on("uncaughtException",o=>{O.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=>{O.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(Fn,"installLongRunningCrashGuards");function ct(r,t){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",t.defaultConfig).option("--emit-events <channel>","\u8FD0\u884C\u4E8B\u4EF6\u4E0A\u629B\u901A\u9053\uFF1Aipc = \u7ECF process.send \u53D1\u7ED9\u7236\u8FDB\u7A0B\uFF08daemon runner \u7528\uFF09\uFF0C\u7F3A\u7701\u4E0D\u4E0A\u629B").option("-p, --port <number>","\uFF08\u4EC5\u517C\u5BB9 launcher \u900F\u4F20\uFF0Crun \u547D\u4EE4\u4E0D\u4F7F\u7528\u6B64\u53C2\u6570\uFF09").action(async e=>{Bn(e.config);try{await Mn(at.dirname(at.resolve(e.config)),t.version),Fn(),await Ln();let n=e.emitEvents==="ipc"&&typeof process.send=="function",o=await Dn(e.config,n?{onRunEvent:c(a=>{process.send?.({type:"run-event",event:a})},"onRunEvent")}:{});ee("run.start",{emitEvents:e.emitEvents??null});let i=!1,s=c(async()=>{i&&(O.warn("cli","\u518D\u6B21\u6536\u5230\u9000\u51FA\u4FE1\u53F7\uFF0C\u5F3A\u5236\u9000\u51FA"),process.exit(1)),i=!0,O.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){O.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(ct,"registerRunCommand");import{readFile as Un}from"fs/promises";import dt from"path";import{createApp as Wn,ensureTsxRegistered as Nn,logger as Ce,resolveConfigPath as Gn}from"aitable-workflow-core";function Hn(r,t){let e=`\u5DE5\u4F5C\u6D41 ${r} / \u4E8B\u4EF6\u6E90 ${t.sourceName}\uFF08handler: ${t.handlerRecipe}\uFF09`;return t.actions===0?`${e}\uFF1A\u5DF2\u89E6\u53D1\u4F46\u6CA1\u6709\u4EA7\u51FA\u52A8\u4F5C\uFF08\u8017\u65F6 ${t.durationMs}ms\uFF09\u3002\u8BF7\u68C0\u67E5\u6570\u636E\u6E90\u662F\u5426\u6709\u53EF\u7528\u884C\u3002`:`${e}\uFF1A\u4EA7\u51FA ${t.actions} \u4E2A\u52A8\u4F5C\uFF08\u843D\u5E93 ${t.applied}\uFF0C\u77AC\u6001 ${t.transient}\uFF09\uFF0C\u8017\u65F6 ${t.durationMs}ms\u3002`}c(Hn,"formatTriggerOnceResult");function lt(r){return new Promise(t=>{r.write("",()=>t())})}c(lt,"flushStream");function pt(){return Promise.all([lt(process.stdout),lt(process.stderr)])}c(pt,"flushOutputs");function mt(r){let t;try{t=JSON.parse(r)}catch(n){throw new Error(`\u81EA\u5B9A\u4E49\u4E8B\u4EF6 JSON \u89E3\u6790\u5931\u8D25: ${n instanceof Error?n.message:String(n)}`)}if(!t||typeof t!="object"||Array.isArray(t))throw new Error("\u81EA\u5B9A\u4E49\u4E8B\u4EF6\u5FC5\u987B\u662F JSON \u5BF9\u8C61");let e=t;if(typeof e.type!="string"||e.type.trim().length===0)throw new Error("\u81EA\u5B9A\u4E49\u4E8B\u4EF6 type \u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32");if(!e.payload||typeof e.payload!="object"||Array.isArray(e.payload))throw new Error("\u81EA\u5B9A\u4E49\u4E8B\u4EF6 payload \u5FC5\u987B\u662F\u5BF9\u8C61");if(e.timestamp!==void 0&&(typeof e.timestamp!="string"||e.timestamp.trim().length===0))throw new Error("\u81EA\u5B9A\u4E49\u4E8B\u4EF6 timestamp \u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32");if(e.itemId!==void 0&&e.itemId!==null&&typeof e.itemId!="string")throw new Error("\u81EA\u5B9A\u4E49\u4E8B\u4EF6 itemId \u5FC5\u987B\u662F\u5B57\u7B26\u4E32\u6216 null");return{type:e.type,payload:e.payload,...typeof e.timestamp=="string"?{timestamp:e.timestamp}:{},...e.itemId!==void 0?{itemId:e.itemId}:{}}}c(mt,"parseTriggerEventJson");async function Jn(){let r=[];for await(let t of process.stdin)r.push(Buffer.isBuffer(t)?t:Buffer.from(String(t)));return Buffer.concat(r).toString("utf8")}c(Jn,"readStdin");async function Vn(r,t=process.cwd()){if(r.eventJson&&r.eventStdin)throw new Error("--event-json \u4E0E --event-stdin \u53EA\u80FD\u4E8C\u9009\u4E00");if(r.eventJson){let e=dt.resolve(t,r.eventJson);return mt(await Un(e,"utf8"))}if(r.eventStdin)return mt(await Jn())}c(Vn,"loadTriggerEvent");function ut(r,t){r.command("trigger-once").description("\u5355\u6B21\u89E6\u53D1\u67D0\u4E2A\u5DE5\u4F5C\u6D41\u7684\u4E8B\u4EF6\u6E90 handler \u8DD1\u4E00\u904D\uFF08\u53EA\u8DD1\u4E8B\u4EF6\u6E90 handler\uFF0C\u4E0D\u542F\u52A8\u5E38\u9A7B\u5F15\u64CE\uFF1B\u6B65\u9AA4\u94FE\u7531\u8FD0\u884C\u4E2D\u7684\u5F15\u64CE\u63A8\u8FDB\uFF09").requiredOption("-w, --workflow <id>","\u5DE5\u4F5C\u6D41 ID\uFF08\u591A\u5DE5\u4F5C\u6D41\u9879\u76EE\u91CC\u7684\u76EE\u5F55\u540D\uFF09").option("-c, --config <path>","\u914D\u7F6E\u6587\u4EF6\u8DEF\u5F84",t.defaultConfig).option("-s, --source <name>","\u53EA\u89E6\u53D1\u6307\u5B9A\u4E8B\u4EF6\u6E90\uFF1B\u7F3A\u7701\u7528\u8BE5\u5DE5\u4F5C\u6D41\u7684\u7B2C\u4E00\u4E2A\u4E8B\u4EF6\u6E90").option("--event-json <path>","\u4ECE JSON \u6587\u4EF6\u8BFB\u53D6\u81EA\u5B9A\u4E49 ExternalEvent\uFF08\u53EA\u89E6\u53D1 handler\uFF0C\u4E0D\u6A21\u62DF\u5B8C\u6574\u6B65\u9AA4\u94FE\uFF09").option("--event-stdin","\u4ECE stdin \u8BFB\u53D6\u81EA\u5B9A\u4E49 ExternalEvent JSON").option("--json","\u4EE5 JSON \u8F93\u51FA\u7ED3\u679C\uFF08\u4F9B\u811A\u672C\u6D88\u8D39\uFF09").action(async e=>{e.json&&Ce.setSink((n,o)=>process.stderr.write(`${o}
8
- `));try{await Nn();let n=await Gn(e.config),o=await Vn(e,dt.dirname(n)),i=await Wn(e.config),s={...e.source?{sourceName:e.source}:{},...o?{event:o}:{}},a=await i.triggerWorkflowOnce(e.workflow,s);e.json?process.stdout.write(`${JSON.stringify({ok:!0,workflowId:e.workflow,...a})}
9
- `):Ce.info("cli",Hn(e.workflow,a)),await pt(),process.exit(0)}catch(n){let o=n instanceof Error?n.message:String(n);e.json?process.stdout.write(`${JSON.stringify({ok:!1,error:o})}
10
- `):Ce.error("cli","\u89E6\u53D1\u5931\u8D25",{error:o}),await pt(),process.exit(1)}})}c(ut,"registerTriggerCommand");import{readFile as gt}from"fs/promises";import ne from"path";import ft from"yaml";import{logger as qn,loadSettings as ht,loadWorkflowTemplate as Kn,resolveConfigPath as Yn,scanWorkflowDirs as zn,buildEnvSource as Xn,loadProfileConfig as Qn,resetProfileCache as Zn,runWorkflowGates as eo}from"aitable-workflow-core";function wt(r,t){r.command("validate").description("\u9A8C\u8BC1\u914D\u7F6E\u6587\u4EF6\u548C\u5DE5\u4F5C\u6D41\u95E8\u7981\uFF08\u7ED3\u6784 / recipe \u7ED1\u5B9A / \u7C7B\u578B / \u914D\u7F6E\u5951\u7EA6 / \u53C2\u6570\u6D41\u8F6C\uFF09").option("-c, --config <path>","\u914D\u7F6E\u6587\u4EF6\u8DEF\u5F84",t.defaultConfig).option("--workflow <id>","\u53EA\u6821\u9A8C\u6307\u5B9A\u5DE5\u4F5C\u6D41\uFF08\u591A\u5DE5\u4F5C\u6D41\u6A21\u5F0F\uFF09").option("--strict","warning \u7EA7\u95EE\u9898\u5347\u7EA7\u4E3A error").option("--no-typecheck","\u8DF3\u8FC7 recipe TS \u7C7B\u578B\u68C0\u67E5\uFF08\u6279\u91CF\u573A\u666F\u63D0\u901F\uFF09").option("--json","\u8F93\u51FA\u673A\u5668\u53EF\u8BFB GateReport JSON").action(async e=>{try{await to(e.config,e)}catch(n){console.error(`\u2717 \u9A8C\u8BC1\u5931\u8D25: ${n instanceof Error?n.message:String(n)}`),process.exit(1)}})}c(wt,"registerValidateCommand");async function to(r,t){t.json&&qn.setSink((a,l)=>process.stderr.write(`${l}
11
- `));let e=await Yn(r),n=ne.dirname(e),o=await oo(e,t.workflow);o.length===0&&(console.error("\u2717 \u672A\u627E\u5230\u4EFB\u4F55\u5DE5\u4F5C\u6D41"),process.exit(1));let i=await io(n),s=await eo(o,{strict:t.strict===!0,includeTypecheck:t.typecheck!==!1,profile:i});s.configPath=e,t.json?console.log(JSON.stringify(s,null,2)):(await no(e),ao(s)),process.exit(s.ok?0:1)}c(to,"runValidateWorkflow");async function no(r){let t=await ht(r,{lenientEnv:!0});console.log("\u2713 \u914D\u7F6E\u6587\u4EF6\u9A8C\u8BC1\u901A\u8FC7");let e=await Kn(t.workflowTemplatePath,{envSource:t.envSource});console.log(`\u2713 \u5DE5\u4F5C\u6D41\u6A21\u677F\u9A8C\u8BC1\u901A\u8FC7: ${e.meta.name} (${e.orderedStepIds.length} \u6B65)`),console.log(`
12
- \u6B65\u9AA4\u94FE:`);for(let[l,p]of e.orderedStepIds.entries()){let m=e.steps.find(g=>g.id===p),u=l<e.orderedStepIds.length-1?" \u2192":" \u2713";console.log(` ${l+1}. [${p}] ${m?.name??"?"}${u}`)}let n=await gt(r,"utf8"),o=ft.parse(n),i=te(o.agent)?o.agent:{},a=typeof i.engine=="string"&&i.engine!==""?t.agent.engine:`\u672A\u914D\u7F6E\uFF08\u9ED8\u8BA4 ${t.agent.engine}\uFF09`;console.log(`
13
- \u914D\u7F6E\u6458\u8981:`),console.log(` AI \u8868\u683C: base=${t.tracker.base_id} table=${t.tracker.table_id}`),console.log(` \u5F15\u64CE: ${a}`),console.log(` \u8F6E\u8BE2\u95F4\u9694: ${t.polling.interval_ms}ms`),console.log()}c(no,"printConfigSummary");async function oo(r,t){let e=ne.dirname(r),n;try{n=(await ht(r,{lenientEnv:!0})).workflowEntries}catch{n=await ro(r,e)}if(t&&(n=n.filter(o=>o.id===t),n.length===0))throw new Error(`\u672A\u627E\u5230\u5DE5\u4F5C\u6D41\u300C${t}\u300D`);return n}c(oo,"resolveWorkflowEntries");function te(r){return typeof r=="object"&&r!==null&&!Array.isArray(r)}c(te,"isRecord");async function ro(r,t){let e=await gt(r,"utf8"),n=ft.parse(e);if(!te(n))throw new Error("\u914D\u7F6E\u6587\u4EF6\u5FC5\u987B\u662F\u4E00\u4E2A\u5BF9\u8C61");if(te(n.workflow)){let o=n.workflow.template,i=n.workflow.recipe_dir??"./recipes";if(typeof o=="string")return[{id:"default",templatePath:ne.resolve(t,o),recipeDir:ne.resolve(t,String(i))}]}if(te(n.workflows)&&typeof n.workflows.dir=="string")return await zn(t,n.workflows.dir);throw new Error("\u914D\u7F6E\u4E2D\u672A\u627E\u5230 workflow / workflows \u6BB5")}c(ro,"inferEntriesFromRawYaml");async function io(r){try{Zn();let t=await Xn(r);return Qn(r,t,{lenientEnv:!0})}catch{return null}}c(io,"tryLoadProfile");var so={structure:"\u7ED3\u6784\u5B8C\u6574\u6027",recipe_bind:"Recipe \u7ED1\u5B9A",recipe_typecheck:"\u7C7B\u578B\u68C0\u67E5",config_contract:"\u914D\u7F6E\u5951\u7EA6",dataflow:"\u53C2\u6570\u6D41\u8F6C"};function ao(r){console.log(`\u5DE5\u4F5C\u6D41\u95E8\u7981\u6821\u9A8C${r.strict?"\uFF08--strict\uFF09":""}`),console.log("\u2550".repeat(56));for(let e of r.workflows){console.log(`
14
- \u5DE5\u4F5C\u6D41: ${e.id} ${e.ok?"\u2713 \u901A\u8FC7":"\u2717 \u672A\u901A\u8FC7"}`);for(let n of e.gates)co(n)}console.log(`
15
- `+"\u2500".repeat(56));let t=po(r);console.log(`${r.workflows.length} \u4E2A\u5DE5\u4F5C\u6D41\uFF1A${r.ok?"\u5168\u90E8\u901A\u8FC7 \u2713":"\u5B58\u5728\u9519\u8BEF \u2717"}\uFF5Cerror ${t.errors}\uFF5Cwarning ${t.warnings}\uFF5Csuggestion ${t.suggestions}`),r.ok||console.log("\u4FEE\u590D\u4E0A\u8FF0 error \u540E\u91CD\u65B0\u8FD0\u884C\uFF1Berror \u8BA1\u5165\u9000\u51FA\u7801\uFF08CI \u53EF\u4F5C\u95E8\u7981\uFF09\u3002")}c(ao,"printReport");function co(r){let t=so[r.gate]??r.gate;if(r.status==="skipped"){console.log(` \u25CB ${t}: \u8DF3\u8FC7\uFF08${r.skipReason??""}\uFF09`);return}let e=r.status==="passed"?"\u2713":"\u2717",n=r.issues.filter(i=>i.severity==="error").length,o=r.status==="passed"?r.issues.length>0?`\uFF08${r.issues.length} \u6761\u63D0\u793A\uFF09`:"":`\uFF08${n} \u4E2A\u9519\u8BEF\uFF09`;console.log(` ${e} ${t}${o} [${r.durationMs}ms]`);for(let i of r.issues)lo(i)}c(co,"printGate");function lo(r){let t=r.severity==="error"?"\u2717":r.severity==="warning"?"\u25B3":"\xB7",e=r.location?[r.location.file,r.location.stepId,r.location.key].filter(Boolean).join(" \u203A "):"";console.log(` ${t} [${r.code}]${e?` ${e}`:""}`),console.log(` ${r.message}`)}c(lo,"printIssue");function po(r){let t=0,e=0,n=0;for(let o of r.workflows)for(let i of o.gates)for(let s of i.issues)s.severity==="error"?t++:s.severity==="warning"?e++:n++;return{errors:t,warnings:e,suggestions:n}}c(po,"summarize");import{logger as mo}from"aitable-workflow-core";function uo(r,t){if(r.getOptionValueSource("config")!=="default")return t;let e=r.parent?.getOptionValue("config");return typeof e=="string"?e:t}c(uo,"effectiveConfigPath");function yt(r,t){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",t.defaultConfig).option("-w, --workflow <id>","\u591A\u5DE5\u4F5C\u6D41\u6A21\u5F0F\uFF1A\u6307\u5B9A\u6821\u9A8C\u7684\u5DE5\u4F5C\u6D41 ID\uFF08\u7F3A\u7701\u6821\u9A8C\u5168\u90E8\uFF09").option("--json","JSON \u683C\u5F0F\u8F93\u51FA\u6821\u9A8C\u7ED3\u679C").option("--summary","\u4E0E --json \u5408\u7528\uFF1A\u53EA\u8F93\u51FA ok \u4E0E summary").option("--errors-only","\u4E0E --json \u5408\u7528\uFF1A\u53EA\u8F93\u51FA status \u4E3A error \u7684\u9879").option("--no-interactive","\u4EC5\u6821\u9A8C\uFF0C\u8DF3\u8FC7\u4EA4\u4E92\u5F0F\u4FEE\u6539").action(async n=>{try{let{runConfigCommand:o}=await import("./config-command-7ECUJOEU.js");await o({configPath:n.config,workflowId:n.workflow,json:n.json,interactive:n.interactive,summary:n.summary,errorsOnly:n.errorsOnly})}catch(o){o instanceof Error&&o.message.includes("cancelled")&&process.exit(0),mo.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",t.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-FBOQBRSJ.js"),a=await i({configPath:uo(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)+`
7
+ `)}await Kn({config:t.config,clean:t.clean,kb:t.kb,...t.kbFull?{kbFull:!0}:{},...n?{only:"automations"}:{}}),await te("setup.finish",{success:!0,durationMs:Date.now()-r})}catch(s){Zn.error("cli","setup \u5931\u8D25",{error:s instanceof Error?s.message:String(s)}),await te("setup.finish",{success:!1,error:(s instanceof Error?s.message:String(s)).slice(0,500),durationMs:Date.now()-r}),process.exit(1)}})}c(wt,"registerSetupCommand");import yt from"path";import{createApp as kt,ensureTsxRegistered as er,checkMigrateHint as tr,logger as C,runCheck as nr}from"aitable-workflow-core";function rr(){let t=[],n=c(()=>{let r=Date.now();for(t.push(r);t.length>0&&r-t[0]>6e4;)t.shift();t.length>=10&&(C.error("cli",`60000ms \u5185\u53D1\u751F ${t.length} \u6B21\u672A\u6355\u83B7\u5F02\u5E38\uFF0C\u7591\u4F3C\u975E\u5076\u53D1\u9519\u8BEF\uFF0C\u4E3B\u52A8\u9000\u51FA`),process.exit(1))},"recordCrashAndMaybeExit");process.on("uncaughtException",r=>{C.error("cli","\u6355\u83B7\u5230\u672A\u5904\u7406\u5F02\u5E38\uFF08\u5DF2\u5B58\u6D3B\uFF0C\u4EA4\u7531\u91CD\u8FDE/\u91CD\u8BD5\u903B\u8F91\u81EA\u6108\uFF09",{error:r instanceof Error?r.message:String(r),stack:r instanceof Error?r.stack:void 0}),n()}),process.on("unhandledRejection",r=>{C.error("cli","\u6355\u83B7\u5230\u672A\u5904\u7406 Promise \u62D2\u7EDD\uFF08\u5DF2\u5B58\u6D3B\uFF09",{error:r instanceof Error?r.message:String(r),stack:r instanceof Error?r.stack:void 0}),n()})}c(rr,"installLongRunningCrashGuards");function bt(o,e){o.command("start").description("\u542F\u52A8\u7EDF\u4E00\u63A7\u5236\u53F0\uFF1A\u914D\u7F6E\u68C0\u6D4B + \u642D\u5EFA + \u8FD0\u884C\u4E00\u4F53\u5316").option("-c, --config <path>","\u914D\u7F6E\u6587\u4EF6\u8DEF\u5F84",e.defaultConfig).option("-p, --port <number>","\u63A7\u5236\u53F0\u7AEF\u53E3\u9996\u9009\u503C\uFF08\u7F3A\u7701 8788\uFF0C\u4E0D\u53EF\u7528\u65F6\u5411\u4E0A\u907F\u8BA9 13 \u4E2A\u7AEF\u53E3\uFF1B\u591A\u9879\u76EE\u5E76\u884C\u65F6\u5EFA\u8BAE\u663E\u5F0F\u6307\u5B9A\uFF09").option("--no-open","\u542F\u52A8\u540E\u4E0D\u8981\u81EA\u52A8\u6253\u5F00\u6D4F\u89C8\u5668").option("--skip-config-if-valid","\u914D\u7F6E\u5DF2\u5B8C\u6574\u65F6\u76F4\u63A5\u542F\u52A8\u8FD0\u884C").action(async t=>{let n;if(t.port!==void 0){let r=Number.parseInt(t.port,10);(!Number.isFinite(r)||r<=0||r>65535)&&(C.error("cli",`--port \u53D6\u503C\u975E\u6CD5: "${t.port}"\uFF08\u9700\u4E3A 1-65535 \u6574\u6570\uFF09`),process.exit(1)),n=r}try{await tr(yt.dirname(yt.resolve(t.config)),e.version),rr(),await er();let r=await nr({configPath:t.config}),s=!r.ok||r.summary.errors>0,i,a="setup";if(!s)try{a="runtime",i=await kt(t.config,{})}catch(p){C.warn("cli","\u914D\u7F6E\u6821\u9A8C\u901A\u8FC7\u4F46\u88C5\u914D\u5931\u8D25\uFF0C\u56DE\u9000\u5230\u642D\u5EFA\u6A21\u5F0F",{error:p instanceof Error?p.message:String(p)}),a="setup",i=void 0}a==="runtime"&&i?t.skipConfigIfValid?(C.info("cli","\u914D\u7F6E\u5DF2\u5B8C\u6574\uFF0C\u76F4\u63A5\u542F\u52A8\u8FD0\u884C"),i.start().catch(p=>{C.error("cli","\u8FD0\u884C\u542F\u52A8\u5931\u8D25\uFF0C\u53EF\u5728\u63A7\u5236\u53F0\u91CD\u8BD5\u542F\u52A8",{error:p instanceof Error?p.message:String(p)})})):C.info("cli","\u914D\u7F6E\u5DF2\u5B8C\u6574\uFF0C\u8BF7\u5728\u63A7\u5236\u53F0\u70B9\u51FB\u300C\u5F00\u59CB\u8FD0\u884C\u300D\u542F\u52A8\u670D\u52A1"):C.info("cli","\u914D\u7F6E\u4E0D\u5B8C\u6574\uFF0C\u63A7\u5236\u53F0\u5C06\u5F15\u5BFC\u5B8C\u6210\u642D\u5EFA");let l=!1,d=c(async()=>{l&&(C.warn("cli","\u518D\u6B21\u6536\u5230\u9000\u51FA\u4FE1\u53F7\uFF0C\u5F3A\u5236\u9000\u51FA"),process.exit(1)),l=!0,C.info("cli","\u6536\u5230\u9000\u51FA\u4FE1\u53F7\uFF0C\u6B63\u5728\u505C\u6B62\u8FD0\u884C...");try{await i?.stop()}finally{process.exit(0)}},"shutdown");process.on("SIGINT",d),process.on("SIGTERM",d),await at({configPath:t.config,mode:a,app:i,port:n,open:t.open,exitOnSetupError:!1,...a==="runtime"&&t.skipConfigIfValid?{initialRunStatus:{status:"running",since:new Date().toISOString(),lastError:null}}:{},...a==="setup"?{assembleApp:c(p=>kt(p,{}),"assembleApp"),onAppAssembled:c(p=>{i=p,C.info("cli","\u63A7\u5236\u53F0\u5DF2\u5B8C\u6210 setup\u2192runtime \u664B\u5347\uFF0C\u53EF\u5728\u63A7\u5236\u53F0\u542F\u52A8\u8FD0\u884C")},"onAppAssembled")}:{}})}catch(r){C.error("cli","start \u547D\u4EE4\u5931\u8D25",{error:r instanceof Error?r.message:String(r)}),process.exit(1)}})}c(bt,"registerStartCommand");import{createApp as or,ensureTsxRegistered as sr,checkMigrateHint as ir,logger as F,reportCliEvent as ne,setReportProject as ar}from"aitable-workflow-core";import Rt from"path";function cr(){let t=[],n=c(async()=>{let r=Date.now();for(t.push(r);t.length>0&&r-t[0]>6e4;)t.shift();t.length>=10&&(F.error("cli",`60000ms \u5185\u53D1\u751F ${t.length} \u6B21\u672A\u6355\u83B7\u5F02\u5E38\uFF0C\u7591\u4F3C\u975E\u5076\u53D1\u9519\u8BEF\uFF0C\u4E3B\u52A8\u9000\u51FA`),await ne("run.exit",{reason:"crash-loop",crashes:t.length}),process.exit(1))},"recordCrashAndMaybeExit");process.on("uncaughtException",r=>{F.error("cli","\u6355\u83B7\u5230\u672A\u5904\u7406\u5F02\u5E38\uFF08\u5DF2\u5B58\u6D3B\uFF0C\u4EA4\u7531\u91CD\u8FDE/\u91CD\u8BD5\u903B\u8F91\u81EA\u6108\uFF09",{error:r instanceof Error?r.message:String(r),stack:r instanceof Error?r.stack:void 0}),n()}),process.on("unhandledRejection",r=>{F.error("cli","\u6355\u83B7\u5230\u672A\u5904\u7406 Promise \u62D2\u7EDD\uFF08\u5DF2\u5B58\u6D3B\uFF09",{error:r instanceof Error?r.message:String(r),stack:r instanceof Error?r.stack:void 0}),n()})}c(cr,"installLongRunningCrashGuards");function Ct(o,e){o.command("run").description("\u542F\u52A8\u7F16\u6392\u5F15\u64CE\uFF0C\u5F00\u59CB\u8F6E\u8BE2\u5904\u7406\u5DE5\u5355").option("-c, --config <path>","\u914D\u7F6E\u6587\u4EF6\u8DEF\u5F84",e.defaultConfig).option("--emit-events <channel>","\u8FD0\u884C\u4E8B\u4EF6\u4E0A\u629B\u901A\u9053\uFF1Aipc = \u7ECF process.send \u53D1\u7ED9\u7236\u8FDB\u7A0B\uFF08daemon runner \u7528\uFF09\uFF0C\u7F3A\u7701\u4E0D\u4E0A\u629B").option("-p, --port <number>","\uFF08\u4EC5\u517C\u5BB9 launcher \u900F\u4F20\uFF0Crun \u547D\u4EE4\u4E0D\u4F7F\u7528\u6B64\u53C2\u6570\uFF09").action(async t=>{ar(t.config);try{await ir(Rt.dirname(Rt.resolve(t.config)),e.version),cr(),await sr();let n=t.emitEvents==="ipc"&&typeof process.send=="function",r=await or(t.config,n?{onRunEvent:c(a=>{process.send?.({type:"run-event",event:a})},"onRunEvent")}:{});ne("run.start",{emitEvents:t.emitEvents??null});let s=!1,i=c(async()=>{s&&(F.warn("cli","\u518D\u6B21\u6536\u5230\u9000\u51FA\u4FE1\u53F7\uFF0C\u5F3A\u5236\u9000\u51FA"),process.exit(1)),s=!0,F.info("cli","\u6536\u5230\u9000\u51FA\u4FE1\u53F7\uFF0C\u6B63\u5728\u7B49\u5F85\u8FDB\u884C\u4E2D\u7684\u4EFB\u52A1\u5B8C\u6210...");try{await r.stop()}finally{await ne("run.exit",{reason:"signal"}),process.exit(0)}},"shutdown");process.on("SIGINT",i),process.on("SIGTERM",i),await r.start()}catch(n){F.error("cli","\u542F\u52A8\u5931\u8D25",{error:n instanceof Error?n.message:String(n)}),await ne("run.exit",{reason:"start-failure",error:(n instanceof Error?n.message:String(n)).slice(0,500)}),process.exit(1)}})}c(Ct,"registerRunCommand");import{readFile as lr}from"fs/promises";import St from"path";import{createApp as dr,ensureTsxRegistered as pr,logger as _e,resolveConfigPath as ur}from"aitable-workflow-core";function mr(o,e){let t=`\u5DE5\u4F5C\u6D41 ${o} / \u4E8B\u4EF6\u6E90 ${e.sourceName}\uFF08handler: ${e.handlerRecipe}\uFF09`;return e.actions===0?`${t}\uFF1A\u5DF2\u89E6\u53D1\u4F46\u6CA1\u6709\u4EA7\u51FA\u52A8\u4F5C\uFF08\u8017\u65F6 ${e.durationMs}ms\uFF09\u3002\u8BF7\u68C0\u67E5\u6570\u636E\u6E90\u662F\u5426\u6709\u53EF\u7528\u884C\u3002`:`${t}\uFF1A\u4EA7\u51FA ${e.actions} \u4E2A\u52A8\u4F5C\uFF08\u843D\u5E93 ${e.applied}\uFF0C\u77AC\u6001 ${e.transient}\uFF09\uFF0C\u8017\u65F6 ${e.durationMs}ms\u3002`}c(mr,"formatTriggerOnceResult");function xt(o){return new Promise(e=>{o.write("",()=>e())})}c(xt,"flushStream");function At(){return Promise.all([xt(process.stdout),xt(process.stderr)])}c(At,"flushOutputs");function Et(o){let e;try{e=JSON.parse(o)}catch(n){throw new Error(`\u81EA\u5B9A\u4E49\u4E8B\u4EF6 JSON \u89E3\u6790\u5931\u8D25: ${n instanceof Error?n.message:String(n)}`)}if(!e||typeof e!="object"||Array.isArray(e))throw new Error("\u81EA\u5B9A\u4E49\u4E8B\u4EF6\u5FC5\u987B\u662F JSON \u5BF9\u8C61");let t=e;if(typeof t.type!="string"||t.type.trim().length===0)throw new Error("\u81EA\u5B9A\u4E49\u4E8B\u4EF6 type \u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32");if(!t.payload||typeof t.payload!="object"||Array.isArray(t.payload))throw new Error("\u81EA\u5B9A\u4E49\u4E8B\u4EF6 payload \u5FC5\u987B\u662F\u5BF9\u8C61");if(t.timestamp!==void 0&&(typeof t.timestamp!="string"||t.timestamp.trim().length===0))throw new Error("\u81EA\u5B9A\u4E49\u4E8B\u4EF6 timestamp \u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32");if(t.itemId!==void 0&&t.itemId!==null&&typeof t.itemId!="string")throw new Error("\u81EA\u5B9A\u4E49\u4E8B\u4EF6 itemId \u5FC5\u987B\u662F\u5B57\u7B26\u4E32\u6216 null");return{type:t.type,payload:t.payload,...typeof t.timestamp=="string"?{timestamp:t.timestamp}:{},...t.itemId!==void 0?{itemId:t.itemId}:{}}}c(Et,"parseTriggerEventJson");async function fr(){let o=[];for await(let e of process.stdin)o.push(Buffer.isBuffer(e)?e:Buffer.from(String(e)));return Buffer.concat(o).toString("utf8")}c(fr,"readStdin");async function gr(o,e=process.cwd()){if(o.eventJson&&o.eventStdin)throw new Error("--event-json \u4E0E --event-stdin \u53EA\u80FD\u4E8C\u9009\u4E00");if(o.eventJson){let t=St.resolve(e,o.eventJson);return Et(await lr(t,"utf8"))}if(o.eventStdin)return Et(await fr())}c(gr,"loadTriggerEvent");function It(o,e){o.command("trigger-once").description("\u5355\u6B21\u89E6\u53D1\u67D0\u4E2A\u5DE5\u4F5C\u6D41\u7684\u4E8B\u4EF6\u6E90 handler \u8DD1\u4E00\u904D\uFF08\u53EA\u8DD1\u4E8B\u4EF6\u6E90 handler\uFF0C\u4E0D\u542F\u52A8\u5E38\u9A7B\u5F15\u64CE\uFF1B\u6B65\u9AA4\u94FE\u7531\u8FD0\u884C\u4E2D\u7684\u5F15\u64CE\u63A8\u8FDB\uFF09").requiredOption("-w, --workflow <id>","\u5DE5\u4F5C\u6D41 ID\uFF08\u591A\u5DE5\u4F5C\u6D41\u9879\u76EE\u91CC\u7684\u76EE\u5F55\u540D\uFF09").option("-c, --config <path>","\u914D\u7F6E\u6587\u4EF6\u8DEF\u5F84",e.defaultConfig).option("-s, --source <name>","\u53EA\u89E6\u53D1\u6307\u5B9A\u4E8B\u4EF6\u6E90\uFF1B\u7F3A\u7701\u7528\u8BE5\u5DE5\u4F5C\u6D41\u7684\u7B2C\u4E00\u4E2A\u4E8B\u4EF6\u6E90").option("--event-json <path>","\u4ECE JSON \u6587\u4EF6\u8BFB\u53D6\u81EA\u5B9A\u4E49 ExternalEvent\uFF08\u53EA\u89E6\u53D1 handler\uFF0C\u4E0D\u6A21\u62DF\u5B8C\u6574\u6B65\u9AA4\u94FE\uFF09").option("--event-stdin","\u4ECE stdin \u8BFB\u53D6\u81EA\u5B9A\u4E49 ExternalEvent JSON").option("--json","\u4EE5 JSON \u8F93\u51FA\u7ED3\u679C\uFF08\u4F9B\u811A\u672C\u6D88\u8D39\uFF09").action(async t=>{t.json&&_e.setSink((n,r)=>process.stderr.write(`${r}
8
+ `));try{await pr();let n=await ur(t.config),r=await gr(t,St.dirname(n)),s=await dr(t.config),i={...t.source?{sourceName:t.source}:{},...r?{event:r}:{}},a=await s.triggerWorkflowOnce(t.workflow,i);t.json?process.stdout.write(`${JSON.stringify({ok:!0,workflowId:t.workflow,...a})}
9
+ `):_e.info("cli",mr(t.workflow,a)),await At(),process.exit(0)}catch(n){let r=n instanceof Error?n.message:String(n);t.json?process.stdout.write(`${JSON.stringify({ok:!1,error:r})}
10
+ `):_e.error("cli","\u89E6\u53D1\u5931\u8D25",{error:r}),await At(),process.exit(1)}})}c(It,"registerTriggerCommand");import{readFile as Tt}from"fs/promises";import oe from"path";import _t from"yaml";import{logger as hr,loadSettings as Pt,loadWorkflowTemplate as vr,resolveConfigPath as wr,scanWorkflowDirs as yr,buildEnvSource as kr,loadProfileConfig as br,resetProfileCache as Rr,runWorkflowGates as Cr}from"aitable-workflow-core";function $t(o,e){o.command("validate").description("\u9A8C\u8BC1\u914D\u7F6E\u6587\u4EF6\u548C\u5DE5\u4F5C\u6D41\u95E8\u7981\uFF08\u7ED3\u6784 / recipe \u7ED1\u5B9A / \u7C7B\u578B / \u914D\u7F6E\u5951\u7EA6 / \u53C2\u6570\u6D41\u8F6C\uFF09").option("-c, --config <path>","\u914D\u7F6E\u6587\u4EF6\u8DEF\u5F84",e.defaultConfig).option("--workflow <id>","\u53EA\u6821\u9A8C\u6307\u5B9A\u5DE5\u4F5C\u6D41\uFF08\u591A\u5DE5\u4F5C\u6D41\u6A21\u5F0F\uFF09").option("--strict","warning \u7EA7\u95EE\u9898\u5347\u7EA7\u4E3A error").option("--no-typecheck","\u8DF3\u8FC7 recipe TS \u7C7B\u578B\u68C0\u67E5\uFF08\u6279\u91CF\u573A\u666F\u63D0\u901F\uFF09").option("--json","\u8F93\u51FA\u673A\u5668\u53EF\u8BFB GateReport JSON").action(async t=>{try{await xr(t.config,t)}catch(n){console.error(`\u2717 \u9A8C\u8BC1\u5931\u8D25: ${n instanceof Error?n.message:String(n)}`),process.exit(1)}})}c($t,"registerValidateCommand");async function xr(o,e){e.json&&hr.setSink((a,l)=>process.stderr.write(`${l}
11
+ `));let t=await wr(o),n=oe.dirname(t),r=await Er(t,e.workflow);r.length===0&&(console.error("\u2717 \u672A\u627E\u5230\u4EFB\u4F55\u5DE5\u4F5C\u6D41"),process.exit(1));let s=await Ir(n),i=await Cr(r,{strict:e.strict===!0,includeTypecheck:e.typecheck!==!1,profile:s});i.configPath=t,e.json?console.log(JSON.stringify(i,null,2)):(await Ar(t),_r(i)),process.exit(i.ok?0:1)}c(xr,"runValidateWorkflow");async function Ar(o){let e=await Pt(o,{lenientEnv:!0});console.log("\u2713 \u914D\u7F6E\u6587\u4EF6\u9A8C\u8BC1\u901A\u8FC7");let t=await vr(e.workflowTemplatePath,{envSource:e.envSource});console.log(`\u2713 \u5DE5\u4F5C\u6D41\u6A21\u677F\u9A8C\u8BC1\u901A\u8FC7: ${t.meta.name} (${t.orderedStepIds.length} \u6B65)`),console.log(`
12
+ \u6B65\u9AA4\u94FE:`);for(let[l,d]of t.orderedStepIds.entries()){let p=t.steps.find(m=>m.id===d),u=l<t.orderedStepIds.length-1?" \u2192":" \u2713";console.log(` ${l+1}. [${d}] ${p?.name??"?"}${u}`)}let n=await Tt(o,"utf8"),r=_t.parse(n),s=re(r.agent)?r.agent:{},a=typeof s.engine=="string"&&s.engine!==""?e.agent.engine:`\u672A\u914D\u7F6E\uFF08\u9ED8\u8BA4 ${e.agent.engine}\uFF09`;console.log(`
13
+ \u914D\u7F6E\u6458\u8981:`),console.log(` AI \u8868\u683C: base=${e.tracker.base_id} table=${e.tracker.table_id}`),console.log(` \u5F15\u64CE: ${a}`),console.log(` \u8F6E\u8BE2\u95F4\u9694: ${e.polling.interval_ms}ms`),console.log()}c(Ar,"printConfigSummary");async function Er(o,e){let t=oe.dirname(o),n;try{n=(await Pt(o,{lenientEnv:!0})).workflowEntries}catch{n=await Sr(o,t)}if(e&&(n=n.filter(r=>r.id===e),n.length===0))throw new Error(`\u672A\u627E\u5230\u5DE5\u4F5C\u6D41\u300C${e}\u300D`);return n}c(Er,"resolveWorkflowEntries");function re(o){return typeof o=="object"&&o!==null&&!Array.isArray(o)}c(re,"isRecord");async function Sr(o,e){let t=await Tt(o,"utf8"),n=_t.parse(t);if(!re(n))throw new Error("\u914D\u7F6E\u6587\u4EF6\u5FC5\u987B\u662F\u4E00\u4E2A\u5BF9\u8C61");if(re(n.workflow)){let r=n.workflow.template,s=n.workflow.recipe_dir??"./recipes";if(typeof r=="string")return[{id:"default",templatePath:oe.resolve(e,r),recipeDir:oe.resolve(e,String(s))}]}if(re(n.workflows)&&typeof n.workflows.dir=="string")return await yr(e,n.workflows.dir);throw new Error("\u914D\u7F6E\u4E2D\u672A\u627E\u5230 workflow / workflows \u6BB5")}c(Sr,"inferEntriesFromRawYaml");async function Ir(o){try{Rr();let e=await kr(o);return br(o,e,{lenientEnv:!0})}catch{return null}}c(Ir,"tryLoadProfile");var Tr={structure:"\u7ED3\u6784\u5B8C\u6574\u6027",recipe_bind:"Recipe \u7ED1\u5B9A",recipe_typecheck:"\u7C7B\u578B\u68C0\u67E5",config_contract:"\u914D\u7F6E\u5951\u7EA6",dataflow:"\u53C2\u6570\u6D41\u8F6C"};function _r(o){console.log(`\u5DE5\u4F5C\u6D41\u95E8\u7981\u6821\u9A8C${o.strict?"\uFF08--strict\uFF09":""}`),console.log("\u2550".repeat(56));for(let t of o.workflows){console.log(`
14
+ \u5DE5\u4F5C\u6D41: ${t.id} ${t.ok?"\u2713 \u901A\u8FC7":"\u2717 \u672A\u901A\u8FC7"}`);for(let n of t.gates)Pr(n)}console.log(`
15
+ `+"\u2500".repeat(56));let e=Lr(o);console.log(`${o.workflows.length} \u4E2A\u5DE5\u4F5C\u6D41\uFF1A${o.ok?"\u5168\u90E8\u901A\u8FC7 \u2713":"\u5B58\u5728\u9519\u8BEF \u2717"}\uFF5Cerror ${e.errors}\uFF5Cwarning ${e.warnings}\uFF5Csuggestion ${e.suggestions}`),o.ok||console.log("\u4FEE\u590D\u4E0A\u8FF0 error \u540E\u91CD\u65B0\u8FD0\u884C\uFF1Berror \u8BA1\u5165\u9000\u51FA\u7801\uFF08CI \u53EF\u4F5C\u95E8\u7981\uFF09\u3002")}c(_r,"printReport");function Pr(o){let e=Tr[o.gate]??o.gate;if(o.status==="skipped"){console.log(` \u25CB ${e}: \u8DF3\u8FC7\uFF08${o.skipReason??""}\uFF09`);return}let t=o.status==="passed"?"\u2713":"\u2717",n=o.issues.filter(s=>s.severity==="error").length,r=o.status==="passed"?o.issues.length>0?`\uFF08${o.issues.length} \u6761\u63D0\u793A\uFF09`:"":`\uFF08${n} \u4E2A\u9519\u8BEF\uFF09`;console.log(` ${t} ${e}${r} [${o.durationMs}ms]`);for(let s of o.issues)$r(s)}c(Pr,"printGate");function $r(o){let e=o.severity==="error"?"\u2717":o.severity==="warning"?"\u25B3":"\xB7",t=o.location?[o.location.file,o.location.stepId,o.location.key].filter(Boolean).join(" \u203A "):"";console.log(` ${e} [${o.code}]${t?` ${t}`:""}`),console.log(` ${o.message}`)}c($r,"printIssue");function Lr(o){let e=0,t=0,n=0;for(let r of o.workflows)for(let s of r.gates)for(let i of s.issues)i.severity==="error"?e++:i.severity==="warning"?t++:n++;return{errors:e,warnings:t,suggestions:n}}c(Lr,"summarize");import{logger as Or}from"aitable-workflow-core";function jr(o,e){if(o.getOptionValueSource("config")!=="default")return e;let t=o.parent?.getOptionValue("config");return typeof t=="string"?t:e}c(jr,"effectiveConfigPath");function Lt(o,e){o.command("config").description("\u6821\u9A8C\u9879\u76EE\u914D\u7F6E\u5B8C\u6574\u6027\uFF0C\u5E76\u53EF\u4EA4\u4E92\u5F0F\u4FEE\u6539\u53C2\u6570").option("-c, --config <path>","\u9879\u76EE\u76EE\u5F55\u6216\u914D\u7F6E\u6587\u4EF6\u8DEF\u5F84",e.defaultConfig).option("-w, --workflow <id>","\u591A\u5DE5\u4F5C\u6D41\u6A21\u5F0F\uFF1A\u6307\u5B9A\u6821\u9A8C\u7684\u5DE5\u4F5C\u6D41 ID\uFF08\u7F3A\u7701\u6821\u9A8C\u5168\u90E8\uFF09").option("--json","JSON \u683C\u5F0F\u8F93\u51FA\u6821\u9A8C\u7ED3\u679C").option("--summary","\u4E0E --json \u5408\u7528\uFF1A\u53EA\u8F93\u51FA ok \u4E0E summary").option("--errors-only","\u4E0E --json \u5408\u7528\uFF1A\u53EA\u8F93\u51FA status \u4E3A error \u7684\u9879").option("--no-interactive","\u4EC5\u6821\u9A8C\uFF0C\u8DF3\u8FC7\u4EA4\u4E92\u5F0F\u4FEE\u6539").action(async n=>{try{let{runConfigCommand:r}=await import("./config-command-7ECUJOEU.js");await r({configPath:n.config,workflowId:n.workflow,json:n.json,interactive:n.interactive,summary:n.summary,errorsOnly:n.errorsOnly})}catch(r){r instanceof Error&&r.message.includes("cancelled")&&process.exit(0),Or.error("cli","config \u547D\u4EE4\u5931\u8D25",{error:r instanceof Error?r.message:String(r)}),process.exit(1)}}).command("set").description("\u975E\u4EA4\u4E92\u5199\u914D\u7F6E\u9879\uFF08key \u53D6\u81EA config --json \u7684 item.key\uFF09").option("-c, --config <path>","\u9879\u76EE\u76EE\u5F55\u6216\u914D\u7F6E\u6587\u4EF6\u8DEF\u5F84",e.defaultConfig).option("-w, --workflow <id>","\u591A\u5DE5\u4F5C\u6D41\u9879\u76EE\u91CC\u7ED9 key \u6D88\u6B67\uFF08\u540C\u540D key \u547D\u4E2D\u591A\u4E2A\u5DE5\u4F5C\u6D41\u65F6\u5FC5\u586B\uFF09").option("--set <key=value>","\u5199\u4E00\u9879\uFF1B\u53EF\u91CD\u590D\u3002\u654F\u611F\u9879\u62D2\u6536\uFF08\u503C\u4F1A\u8FDB argv\uFF09\uFF0C\u6539\u7528 --set-stdin",(n,r)=>[...r,n],[]).option("--set-stdin <key>","\u5199\u4E00\u9879\uFF0C\u503C\u4ECE stdin \u9010\u884C\u6309\u987A\u5E8F\u8BFB\uFF1B\u53EF\u91CD\u590D\u3002\u654F\u611F\u9879\u8D70\u8FD9\u6761",(n,r)=>[...r,n],[]).option("--dry-run","\u53EA\u6253\u5370\u5C06\u5199\u54EA\u4E2A\u6587\u4EF6\u7684\u54EA\u4E2A\u8DEF\u5F84\uFF0C\u4E0D\u5199\u76D8\uFF08\u654F\u611F\u503C\u53EA\u6253\u952E\u540D\uFF09").option("--json","JSON \u683C\u5F0F\u8F93\u51FA\u7ED3\u679C").action(async(n,r)=>{try{let{runConfigSet:s,printConfigSetResult:i}=await import("./config-set-FBOQBRSJ.js"),a=await s({configPath:jr(r,n.config),...n.workflow?{workflowId:n.workflow}:{},set:n.set,setStdin:n.setStdin,...n.dryRun?{dryRun:!0}:{},...n.json?{json:!0}:{}});i(a,n.json===!0)}catch(s){let i=s instanceof Error?s.message:String(s);n.json?process.stdout.write(JSON.stringify({ok:!1,error:i},null,2)+`
16
16
  `):console.error(`
17
- \u2717 ${s}
18
- `),process.exit(1)}})}c(yt,"registerConfigCommand");import{runSync as go,logger as fo}from"aitable-workflow-core";function vt(r,t){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",t.defaultConfig).option("-y, --yes","\u975E\u4EA4\u4E92\u6A21\u5F0F").action(async e=>{try{await go({configPath:e.config,yes:e.yes})}catch(n){fo.error("cli","sync \u5931\u8D25",{error:n instanceof Error?n.message:String(n)}),process.exit(1)}})}c(vt,"registerSyncCommand");import{listCodingAgents as ho,logger as wo}from"aitable-workflow-core";function kt(r,t){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(e=>{try{let n=ho();if(e.json){process.stdout.write(JSON.stringify(n,null,2)+`
19
- `);return}let o=n.filter(i=>i.installed).length;console.log(`
20
- \u652F\u6301 ${n.length} \u4E2A Coding Agent\uFF0C\u672C\u673A\u5DF2\u63A2\u6D4B\u5230 ${o} \u4E2A\uFF1A
21
- `);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){wo.error("cli","\u5217\u51FA agents \u5931\u8D25",{error:n instanceof Error?n.message:String(n)}),process.exit(1)}})}c(kt,"registerAgentsCommand");import{logger as yo}from"aitable-workflow-core";import{startServer as vo,resolveServeConfig as ko}from"aitable-workflow-server";import oe from"path";import{existsSync as bt}from"fs";function Rt(r,t){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 e=>{try{let n={};if(e.port!==void 0){let i=Number.parseInt(e.port,10);Number.isFinite(i)&&i>0&&(n.port=i)}if(e.host!==void 0&&(n.host=e.host),e.dataRoot!==void 0&&(n.dataRoot=e.dataRoot),e.webRoot!==void 0)n.webRoot=e.webRoot;else{let i=oe.join(t.cliDir,"web");if(bt(oe.join(i,"index.html")))n.webRoot=i;else{let s=oe.resolve(t.cliDir,"..","..","web","dist");bt(oe.join(s,"index.html"))&&(n.webRoot=s)}}let o=ko(n);if(await vo(o),o.webRoot&&e.open!==!1){let i=o.host==="0.0.0.0"?"127.0.0.1":o.host;Je(`http://${i}:${o.port}`)}}catch(n){yo.error("cli","HTTP \u670D\u52A1\u542F\u52A8\u5931\u8D25",{error:n instanceof Error?n.message:String(n)}),process.exit(1)}})}c(Rt,"registerServeCommand");import{Command as Le}from"commander";import{logger as S,listCredentials as Vt,getActiveCredential as j,maskSecret as _r}from"aitable-workflow-core";import B from"os";import M from"path";import{mkdir as cr,readFile as lr}from"fs/promises";import{mkdirSync as pr}from"fs";import{logger as w,detectInstalledAgents as mr,runCodingAgent as dr,DwsClient as ur,getActiveCredential as gr,assertPortableId as Bt,resolveInsideRoot as Mt,probeCommand as fr,dwsCommandOptions as hr}from"aitable-workflow-core";import Ie from"ws";import{logger as x,RELAY_REJECTED_CODE as bo,isRelayMessage as Ro}from"aitable-workflow-core";var T="relay:conn",Ct=1e3,Co=3e4,Io=Number(process.env.AITABLE_RELAY_SERVER_STALE_MS??9e4),re=class{static{c(this,"RelayConnection")}ws=null;delay=Ct;timer=null;watchdog=null;should=!0;permanentlyRejected=!1;accepted=!1;lastServerFrameAt=0;serverUrl;key;token;onMessage;onOpen;onAccepted;onPermanentReject;mkWs;staleMs;constructor(t){this.serverUrl=t.serverUrl,this.key=t.key??"",this.token=t.token??"",this.onMessage=t.onMessage,this.onOpen=t.onOpen,this.onAccepted=t.onAccepted,this.onPermanentReject=t.onPermanentReject,this.mkWs=t.mkWs??(e=>new Ie(e)),this.staleMs=t.staleMs??Io}connect(){this.permanentlyRejected||(this.should=!0,this.doConnect())}send(t){this.ws&&this.ws.readyState===Ie.OPEN&&this.ws.send(JSON.stringify(t))}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 t=this.serverUrl.replace(/\/+$/,"").replace(/^http/,"ws"),e=this.token?`token=${encodeURIComponent(this.token)}`:`key=${encodeURIComponent(this.key)}`;return`${t}/api/relay/connect?${e}`}doConnect(){if(!this.should||this.permanentlyRejected)return;let t=this.buildUrl();x.info(T,"connecting",{serverUrl:this.serverUrl}),this.watchdog&&(clearTimeout(this.watchdog),this.watchdog=null),this.accepted=!1,this.lastServerFrameAt=0;let e=this.mkWs(t);this.ws=e,e.on("open",()=>{x.info(T,"connected"),this.onOpen?.(e)}),e.on("message",n=>{this.accepted||(this.accepted=!0,this.delay=Ct,this.onAccepted?.(e)),this.lastServerFrameAt=Date.now(),this.armWatchdog();let o;try{o=JSON.parse(typeof n=="string"?n:String(n))}catch{return}Ro(o)&&(o.type==="ping"&&this.send({type:"pong"}),this.onMessage(o))}),e.on("close",(n,o)=>{this.watchdog&&(clearTimeout(this.watchdog),this.watchdog=null);let i=o==null?"":String(o);if(n===bo){this.permanentlyRejected=!0,this.should=!1,x.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}x.warn(T,"disconnected",{code:n}),this.scheduleReconnect()}),e.on("error",n=>{x.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!==Ie.OPEN)){x.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||(x.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,Co))}};import{createHash as So}from"crypto";import{readdir as Ao,readFile as Eo,stat as xo}from"fs/promises";import It from"path";import{isAllowedArtifactPath as To,normalizeArtifactRelPath as $o}from"aitable-workflow-core";var St={async upload(r,t,e){let n=await fetch(r,{method:"PUT",body:t,headers:{...e}});if(!n.ok)throw new Error(`artifact PUT failed: ${n.status} ${n.statusText}`)}};async function At(r){let t=[];return await Et(r,r,t),t.sort((e,n)=>e.relPath.localeCompare(n.relPath))}c(At,"scanArtifacts");async function Et(r,t,e){let n;try{n=await Ao(t,{withFileTypes:!0})}catch{return}for(let o of n){if(o.name==="node_modules"||o.name.startsWith("."))continue;let i=It.join(t,o.name);if(o.isDirectory())await Et(r,i,e);else if(o.isFile()){let s=It.relative(r,i).replace(/\\/g,"/");if(!To(s))continue;let a=await xo(i),l=await Eo(i),p=So("sha256").update(l).digest("hex");e.push({relPath:$o(s),absPath:i,size:a.size,sha256:p})}}}c(Et,"walk");import Lt from"path";import{logger as b}from"aitable-workflow-core";import{logger as _,spawnManagedProcess as Po}from"aitable-workflow-core";var D="engine-supervisor",ie=class{static{c(this,"EngineSupervisor")}options;doSpawn;setTimer;clearTimer;child=null;childGen=0;consecutiveFailures=0;lastExitCode=null;lastError=null;restartTimer=null;stopped=!0;constructor(t){this.options=t,this.doSpawn=t.spawnImpl??Po,this.setTimer=t.setTimeoutImpl??((e,n)=>setTimeout(e,n)),this.clearTimer=t.clearTimeoutImpl??(e=>clearTimeout(e))}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 t=this.child;if(!t)return;t.stopping=!0;let e=t.managed.child.pid;if(e==null){this.child=null;return}let n=t.gen;await t.managed.terminateTree({gracePeriodMs:this.options.drainTimeoutMs??2e4}),t.managed.child.exitCode==null&&t.managed.child.signalCode==null&&(_.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:e,generation:n}),this.child?.gen===n&&(this.child=null))}spawnChild(){this.childGen+=1;let t=this.childGen,e=["run","--config",this.options.workspaceDir,"--emit-events","ipc"],n=this.doSpawn({command:process.execPath,args:[this.options.cliPath,...e],cwd:this.options.workspaceDir,stdio:["ignore","pipe","pipe","ipc"],...this.options.env?{env:this.options.env}:{}}),o=n.child,i={managed:n,gen:t,startedAt:Date.now(),stopping:!1};this.child=i,_.info(D,"engine started",{projectId:this.options.projectId,pid:o.pid,generation:t}),o.on("message",s=>{jo(s)&&this.options.onRunEvent?.(s.event)}),o.on("error",s=>{this.lastError=s.message,_.error(D,"engine spawn error",{projectId:this.options.projectId,error:s.message})}),o.on("exit",(s,a)=>this.handleExit(i,s,a))}handleExit(t,e,n){if(this.child?.gen===t.gen&&(this.child=null),this.lastExitCode=e,_.info(D,"engine exited",{projectId:this.options.projectId,generation:t.gen,code:e,signal:n}),t.stopping||this.stopped)return;this.consecutiveFailures+=1;let o=this.options.maxConsecutiveFailures??5;if(this.consecutiveFailures>=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:e});return}let i=this.options.restartBackoffMs??1e3,s=this.options.restartBackoffMaxMs??6e4,a=Math.min(s,i*2**(this.consecutiveFailures-1));_.warn(D,"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 jo(r){return typeof r=="object"&&r!==null&&r.type==="run-event"&&"event"in r}c(jo,"isRunEventMessage");import{appendFile as Oo,mkdir as _o,rename as Do,stat as Lo}from"fs/promises";import Mo from"path";import{logger as se}from"aitable-workflow-core";var ae="event-spool",ce=class{static{c(this,"EventSpool")}options;setInterval;clearInterval;now;buffer=[];pending=[];seq=0;timer=null;flushing=!1;constructor(t){this.options=t,this.setInterval=t.setIntervalImpl??((e,n)=>setInterval(e,n)),this.clearInterval=t.clearIntervalImpl??(e=>clearInterval(e)),this.now=t.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(t){this.seq+=1;let e={seq:this.seq,ts:new Date(this.now()).toISOString(),event:t};this.pending.push(e),this.buffer.push(e);let n=this.options.maxPending??5e3;if(this.pending.length>n){let i=this.pending.splice(0,this.pending.length-n);se.warn(ae,"\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(e)}async flush(){if(this.flushing||this.pending.length===0)return;this.flushing=!0;let t=this.pending.slice(0,this.options.maxBatch??200);try{await this.options.send(t);let e=new Set(t.map(n=>n.seq));this.pending=this.pending.filter(n=>!e.has(n.seq))}catch(e){se.warn(ae,"\u4E8B\u4EF6\u6279\u4E0A\u884C\u5931\u8D25\uFF08\u4FDD\u7559\u5F85\u4E0B\u8F6E\u91CD\u8BD5\uFF09",{projectId:this.options.projectId,count:t.length,error:e instanceof Error?e.message:String(e)})}finally{this.flushing=!1}}replayFrom(t){let e=new Set(this.pending.map(o=>o.seq)),n=this.buffer.filter(o=>o.seq>t&&!e.has(o.seq));return n.length===0?0:(this.pending=[...this.pending,...n].sort((o,i)=>o.seq-i.seq),se.info(ae,"\u8865\u4F20\u7F3A\u53E3\u4E8B\u4EF6",{projectId:this.options.projectId,serverLastSeq:t,replay:n.length}),n.length)}async persist(t){let e=Mo.join(this.options.spoolDir,"run-events.jsonl");try{await _o(this.options.spoolDir,{recursive:!0}),await Lo(e).then(o=>o.size).catch(()=>0)>(this.options.rotateBytes??10*1024*1024)&&await Do(e,`${e}.1`).catch(()=>{}),await Oo(e,`${JSON.stringify(t)}
22
- `,"utf8")}catch(n){se.warn(ae,"spool \u843D\u76D8\u5931\u8D25",{projectId:this.options.projectId,error:n instanceof Error?n.message:String(n)})}}};import{readdir as Te,rm as xe,stat as me}from"fs/promises";import L from"path";import{logger as N}from"aitable-workflow-core";import{createHash as Ho}from"crypto";import{mkdir as Ae,readFile as Jo,rename as Vo,rm as qo,writeFile as Pt}from"fs/promises";import le from"path";import{decodeWorkspaceBundle as Ko,logger as Yo,resolveInsideRoot as zo}from"aitable-workflow-core";import{chmod as Bo,readFile as Fo,rename as Uo,writeFile as Wo}from"fs/promises";var xt="# \u2500\u2500\u2500 aitable-workflow managed credentials (auto-generated, do not edit) \u2500\u2500\u2500",Tt="# \u2500\u2500\u2500 end managed credentials \u2500\u2500\u2500";function No(r,t){let e=r.split(`
23
- `),n=e.indexOf(xt),o=e.indexOf(Tt),i;n!==-1&&o!==-1&&o>n?i=[...e.slice(0,n),...e.slice(o+1)].join(`
24
- `):i=r,i=i.replace(/^\n+/,"");let s=Object.entries(t).sort(([l],[p])=>l.localeCompare(p));return s.length===0?i:`${[xt,...s.map(([l,p])=>`${l}=${Go(p)}`),Tt].join(`
17
+ \u2717 ${i}
18
+ `),process.exit(1)}})}c(Lt,"registerConfigCommand");import{runSync as Mr,logger as Dr}from"aitable-workflow-core";function Ot(o,e){o.command("sync").description("\u68C0\u6D4B\u914D\u7F6E\u4E0E\u8868\u7684\u504F\u5DEE\uFF08\u5B57\u6BB5\u7C7B\u578B/\u9009\u9879 drift\uFF09\uFF0C\u8F93\u51FA\u8BCA\u65AD\u62A5\u544A\u548C\u4FEE\u590D\u5EFA\u8BAE").option("-c, --config <path>","\u914D\u7F6E\u6587\u4EF6\u8DEF\u5F84",e.defaultConfig).option("-y, --yes","\u975E\u4EA4\u4E92\u6A21\u5F0F").action(async t=>{try{await Mr({configPath:t.config,yes:t.yes})}catch(n){Dr.error("cli","sync \u5931\u8D25",{error:n instanceof Error?n.message:String(n)}),process.exit(1)}})}c(Ot,"registerSyncCommand");import{listCodingAgents as Br,logger as Hr}from"aitable-workflow-core";function jt(o,e){o.command("agents").description("\u5217\u51FA\u5168\u90E8\u652F\u6301\u7684 Coding Agent \u9002\u914D\u5668\uFF0C\u5E76\u6807\u6CE8\u672C\u673A\u5DF2\u63A2\u6D4B\u5230\u5B89\u88C5\u7684").option("--json","\u4EE5 JSON \u683C\u5F0F\u8F93\u51FA").action(t=>{try{let n=Br();if(t.json){process.stdout.write(JSON.stringify(n,null,2)+`
19
+ `);return}let r=n.filter(s=>s.installed).length;console.log(`
20
+ \u652F\u6301 ${n.length} \u4E2A Coding Agent\uFF0C\u672C\u673A\u5DF2\u63A2\u6D4B\u5230 ${r} \u4E2A\uFF1A
21
+ `);for(let s of n){let i=s.installed?"\u2713":"\u2717",a=[s.bin,...s.fallbackBins].join(" / "),l=s.installed?`\u5DF2\u5B89\u88C5 (${s.detectedCmd}${s.detectedVersion?` ${s.detectedVersion}`:""})`:"\u672A\u63A2\u6D4B\u5230";console.log(` ${i} ${s.name.padEnd(16)} [${s.id}] bin: ${a.padEnd(24)} ${l}`)}console.log("")}catch(n){Hr.error("cli","\u5217\u51FA agents \u5931\u8D25",{error:n instanceof Error?n.message:String(n)}),process.exit(1)}})}c(jt,"registerAgentsCommand");import{logger as Fr}from"aitable-workflow-core";import{startServer as Nr,resolveServeConfig as Ur}from"aitable-workflow-server";import se from"path";import{existsSync as Mt}from"fs";function Dt(o,e){o.command("serve").description("\u542F\u52A8\u672C\u5730 HTTP API \u670D\u52A1\u5E76\u6258\u7BA1 Web \u524D\u7AEF\u9875\u9762\uFF08local \u6A21\u5F0F\u81EA\u52A8\u6253\u5F00\u6D4F\u89C8\u5668\uFF09").option("-p, --port <number>","\u76D1\u542C\u7AEF\u53E3\uFF08\u9ED8\u8BA4 8787\uFF0C\u53EF\u7528 AITABLE_WORKFLOW_PORT \u8986\u76D6\uFF09").option("--host <host>","\u76D1\u542C\u5730\u5740\uFF08\u9ED8\u8BA4 127.0.0.1\uFF0C\u53EF\u7528 AITABLE_WORKFLOW_HOST \u8986\u76D6\uFF09").option("--data-root <path>","\u9879\u76EE\u5DE5\u4F5C\u533A\u6570\u636E\u76EE\u5F55\uFF08\u9ED8\u8BA4 .sandbox/aitable-workflow-server\uFF0C\u53EF\u7528 AITABLE_WORKFLOW_DATA_DIR \u8986\u76D6\uFF09").option("--web-root <path>","Web \u524D\u7AEF\u9759\u6001\u8D44\u6E90\u76EE\u5F55\uFF08\u9ED8\u8BA4\u4F7F\u7528\u968F CLI \u6253\u5305\u7684 dist/web\uFF09").option("--no-open","\u542F\u52A8\u540E\u4E0D\u81EA\u52A8\u6253\u5F00\u6D4F\u89C8\u5668\uFF08\u9ED8\u8BA4\u81EA\u52A8\u6253\u5F00\uFF09").action(async t=>{try{let n={};if(t.port!==void 0){let s=Number.parseInt(t.port,10);Number.isFinite(s)&&s>0&&(n.port=s)}if(t.host!==void 0&&(n.host=t.host),t.dataRoot!==void 0&&(n.dataRoot=t.dataRoot),t.webRoot!==void 0)n.webRoot=t.webRoot;else{let s=se.join(e.cliDir,"web");if(Mt(se.join(s,"index.html")))n.webRoot=s;else{let i=se.resolve(e.cliDir,"..","..","web","dist");Mt(se.join(i,"index.html"))&&(n.webRoot=i)}}let r=Ur(n);if(await Nr(r),r.webRoot&&t.open!==!1){let s=r.host==="0.0.0.0"?"127.0.0.1":r.host;it(`http://${s}:${r.port}`)}}catch(n){Fr.error("cli","HTTP \u670D\u52A1\u542F\u52A8\u5931\u8D25",{error:n instanceof Error?n.message:String(n)}),process.exit(1)}})}c(Dt,"registerServeCommand");import{Command as Ze}from"commander";import{logger as T,listCredentials as hn,getActiveCredential as B,maskSecret as Ss}from"aitable-workflow-core";import M from"os";import I from"path";import{fileURLToPath as Bo}from"url";import{createServer as Ho}from"http";import{mkdir as Fo,readFile as sn,mkdtemp as No,writeFile as Uo,rm as Wo}from"fs/promises";import{mkdirSync as Go,existsSync as qo}from"fs";import{logger as w,detectInstalledAgents as zo,projectAgentEvents as rn,runCodingAgent as Jo,DwsClient as Yo,getActiveCredential as Vo,assertPortableId as Ko,probeCommand as Xo,dwsCommandOptions as Zo,substituteArgPath as Qo}from"aitable-workflow-core";var Bt=`<!doctype html>
22
+ <html lang="zh-CN">
23
+ <head>
24
+ <meta charset="utf-8" />
25
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
26
+ <title>Local Agent Workbench</title>
27
+ <link rel="stylesheet" href="/assets/workbench.css" />
28
+ </head>
29
+ <body>
30
+ <header class="topbar">
31
+ <div class="brand">
32
+ <span class="dot" id="health-dot" title="daemon \u72B6\u6001"></span>
33
+ <strong>aitable-workflow</strong>
34
+ <span class="muted">local agent workbench</span>
35
+ </div>
36
+ <div class="topbar-right muted" id="meta">
37
+ <a id="assistant-link" class="assistant-link" href="/" title="assistant-ui \u8FD0\u884C/\u5BF9\u8BDD\u89C6\u56FE">Assistant \u89C6\u56FE \u2192</a>
38
+ <span id="meta-text">\u2014</span>
39
+ </div>
40
+ </header>
41
+ <main class="layout">
42
+ <aside class="runs">
43
+ <div class="pane-head">
44
+ <span>Runs</span>
45
+ <button id="refresh" class="ghost" title="\u7ACB\u5373\u5237\u65B0">\u21BB</button>
46
+ </div>
47
+ <ul id="run-list" class="run-list"></ul>
48
+ </aside>
49
+ <section class="timeline">
50
+ <div class="pane-head" id="timeline-head">\u9009\u62E9\u5DE6\u4FA7\u4E00\u4E2A run \u67E5\u770B\u6267\u884C\u6D41</div>
51
+ <div id="timeline" class="timeline-body"></div>
52
+ <div id="chat-bar" class="chat-bar hidden">
53
+ <div class="chat-row">
54
+ <select id="chat-agent" class="chat-agent" title="\u9009\u62E9\u6267\u884C\u672C\u8F6E\u5BF9\u8BDD\u7684 Agent"></select>
55
+ <span id="chat-session" class="chat-session muted" title="\u672C\u8F6E\u5C06\u590D\u7528\u4E0A\u4E00\u6B21\u5BF9\u8BDD\u7684 sessionId \u7EED\u804A\uFF1B\u6E05\u7A7A\u5219\u5F00\u542F\u65B0\u4F1A\u8BDD"></span>
56
+ <button id="chat-clear-session" class="ghost hidden" title="\u6E05\u7A7A sessionId\uFF0C\u5F00\u542F\u65B0\u4F1A\u8BDD">\u65B0\u4F1A\u8BDD</button>
57
+ </div>
58
+ <div class="chat-row">
59
+ <textarea id="chat-input" class="chat-input" rows="2" placeholder="\u5411\u672C\u673A Agent \u53D1\u4E00\u53E5\uFF08Ctrl/\u2318 + Enter \u53D1\u9001\uFF09"></textarea>
60
+ </div>
61
+ <div class="chat-row chat-actions">
62
+ <span id="chat-hint" class="muted"></span>
63
+ <span class="spacer"></span>
64
+ <button id="chat-send" class="primary" title="\u53D1\u8D77\u4E00\u8F6E\u5BF9\u8BDD">\u53D1\u9001</button>
65
+ <button id="chat-stop" class="ghost hidden" title="\u6253\u65AD\u5F53\u524D\u6D3B\u8DC3\u8F6E\u6B21">\u505C\u6B62</button>
66
+ </div>
67
+ </div>
68
+ </section>
69
+ </main>
70
+ <script src="/assets/workbench.js"></script>
71
+ </body>
72
+ </html>`,Ht=`:root {
73
+ --bg: #0e1116;
74
+ --panel: #161b22;
75
+ --panel-2: #1c2230;
76
+ --border: #262d3a;
77
+ --text: #e6edf3;
78
+ --muted: #8b949e;
79
+ --accent: #4c8dff;
80
+ --ok: #3fb950;
81
+ --warn: #d29922;
82
+ --err: #f85149;
83
+ --tool: #a371f7;
84
+ --mono: ui-monospace, SFMonoRLG, "SF Mono", Menlo, Consolas, monospace;
85
+ }
86
+ * { box-sizing: border-box; }
87
+ html, body { height: 100%; margin: 0; }
88
+ body {
89
+ background: var(--bg);
90
+ color: var(--text);
91
+ font: 14px/1.5 -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC", "Microsoft YaHei", sans-serif;
92
+ display: flex;
93
+ flex-direction: column;
94
+ }
95
+ .topbar {
96
+ display: flex; align-items: center; justify-content: space-between;
97
+ padding: 10px 16px; border-bottom: 1px solid var(--border); background: var(--panel);
98
+ }
99
+ .brand { display: flex; align-items: center; gap: 8px; }
100
+ .brand strong { letter-spacing: .2px; }
101
+ .dot { width: 9px; height: 9px; border-radius: 50%; background: var(--muted); display: inline-block; }
102
+ .dot.ok { background: var(--ok); }
103
+ .dot.err { background: var(--err); }
104
+ .muted { color: var(--muted); font-size: 12px; }
105
+ .layout { flex: 1; display: grid; grid-template-columns: 320px 1fr; min-height: 0; }
106
+ .runs { border-right: 1px solid var(--border); background: var(--panel); display: flex; flex-direction: column; min-height: 0; }
107
+ .timeline { display: flex; flex-direction: column; min-height: 0; }
108
+ .pane-head {
109
+ display: flex; align-items: center; justify-content: space-between;
110
+ padding: 10px 14px; border-bottom: 1px solid var(--border);
111
+ font-weight: 600; font-size: 13px; color: var(--text); background: var(--panel);
112
+ position: sticky; top: 0;
113
+ }
114
+ .ghost {
115
+ background: transparent; color: var(--muted); border: 1px solid var(--border);
116
+ border-radius: 6px; cursor: pointer; font-size: 13px; line-height: 1; padding: 3px 8px;
117
+ }
118
+ .ghost:hover { color: var(--text); border-color: var(--accent); }
119
+ .topbar-right { display: flex; align-items: center; gap: 10px; }
120
+ .assistant-link {
121
+ color: var(--muted); text-decoration: none; border: 1px solid var(--border);
122
+ border-radius: 6px; padding: 3px 8px; font-size: 12px; line-height: 1;
123
+ }
124
+ .assistant-link:hover { color: var(--text); border-color: var(--accent); }
125
+ .run-list { list-style: none; margin: 0; padding: 6px; overflow: auto; flex: 1; }
126
+ .run-item {
127
+ padding: 10px; border-radius: 8px; cursor: pointer; border: 1px solid transparent; margin-bottom: 4px;
128
+ }
129
+ .run-item:hover { background: var(--panel-2); }
130
+ .run-item.active { background: var(--panel-2); border-color: var(--accent); }
131
+ .run-item .row1 { display: flex; align-items: center; gap: 8px; }
132
+ .run-item .rid { font-family: var(--mono); font-size: 12px; color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
133
+ .run-item .row2 { margin-top: 4px; font-size: 12px; color: var(--muted); display: flex; gap: 8px; flex-wrap: wrap; }
134
+ .badge { font-size: 11px; padding: 1px 7px; border-radius: 999px; border: 1px solid var(--border); color: var(--muted); }
135
+ .badge.running { color: var(--accent); border-color: var(--accent); }
136
+ .badge.succeeded { color: var(--ok); border-color: var(--ok); }
137
+ .badge.failed { color: var(--err); border-color: var(--err); }
138
+ .badge.aborted { color: var(--warn); border-color: var(--warn); }
139
+ .badge.agent { color: var(--tool); border-color: var(--tool); }
140
+ .badge.source { color: var(--muted); border-color: var(--border); }
141
+ .badge.source-chat { color: var(--accent); border-color: var(--accent); }
142
+ .timeline-body { overflow: auto; padding: 18px 22px 60px; flex: 1; }
143
+ .group { margin-bottom: 16px; display: flex; flex-direction: column; gap: 8px; }
144
+ .item { max-width: 860px; }
145
+ .item.text { background: var(--panel-2); border: 1px solid var(--border); border-radius: 10px; padding: 10px 13px; white-space: pre-wrap; word-break: break-word; }
146
+ details { background: var(--panel); border: 1px solid var(--border); border-radius: 10px; max-width: 860px; }
147
+ details > summary { cursor: pointer; padding: 8px 13px; list-style: none; display: flex; align-items: center; gap: 8px; }
148
+ details > summary::-webkit-details-marker { display: none; }
149
+ details[open] > summary { border-bottom: 1px solid var(--border); }
150
+ .tag { font-size: 11px; text-transform: uppercase; letter-spacing: .4px; padding: 1px 7px; border-radius: 6px; border: 1px solid var(--border); color: var(--muted); flex: none; }
151
+ .tag.thinking { color: var(--warn); border-color: var(--warn); }
152
+ .tag.tool { color: var(--tool); border-color: var(--tool); }
153
+ .tag.tool_result { color: var(--accent); border-color: var(--accent); }
154
+ .tag.permission { color: var(--err); border-color: var(--err); }
155
+ .item .body { padding: 10px 13px; white-space: pre-wrap; word-break: break-word; font-family: var(--mono); font-size: 12.5px; color: var(--text); }
156
+ .item.status { display: flex; align-items: center; gap: 8px; color: var(--muted); font-size: 13px; }
157
+ .item.status .line { flex: 1; height: 1px; background: var(--border); }
158
+ .item.status.result { color: var(--ok); }
159
+ .item.status.error { color: var(--err); }
160
+ .tag.ask { color: var(--warn); border-color: var(--warn); }
161
+ .item.ask { max-width: 860px; border: 1px solid var(--warn); background: rgba(210,153,34,.10); border-radius: 10px; padding: 10px 13px; display: flex; flex-direction: column; gap: 6px; }
162
+ .item.ask .ask-head { display: flex; align-items: center; gap: 8px; font-weight: 600; color: var(--warn); }
163
+ .item.ask .ask-q { white-space: pre-wrap; word-break: break-word; }
164
+ .item.ask .ask-body { font-family: var(--mono); font-size: 12.5px; color: var(--muted); white-space: pre-wrap; word-break: break-word; }
165
+ .empty { color: var(--muted); padding: 40px; text-align: center; }
166
+ .mono { font-family: var(--mono); }
167
+ .hidden { display: none !important; }
168
+ .chat-bar {
169
+ border-top: 1px solid var(--border); background: var(--panel);
170
+ padding: 10px 14px; display: flex; flex-direction: column; gap: 8px;
171
+ }
172
+ .chat-row { display: flex; align-items: center; gap: 8px; }
173
+ .chat-actions { justify-content: flex-end; }
174
+ .chat-row .spacer { flex: 1; }
175
+ .chat-agent {
176
+ background: var(--panel-2); color: var(--text); border: 1px solid var(--border);
177
+ border-radius: 6px; padding: 4px 8px; font: inherit; font-size: 13px;
178
+ }
179
+ .chat-input {
180
+ flex: 1; resize: vertical; min-height: 36px; background: var(--panel-2); color: var(--text);
181
+ border: 1px solid var(--border); border-radius: 8px; padding: 8px 10px; font: inherit; font-size: 13px;
182
+ }
183
+ .chat-input:focus { outline: none; border-color: var(--accent); }
184
+ .chat-session { font-family: var(--mono); font-size: 11px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 260px; }
185
+ button.primary {
186
+ background: var(--accent); color: #fff; border: 1px solid var(--accent);
187
+ border-radius: 6px; cursor: pointer; font-size: 13px; padding: 4px 14px;
188
+ }
189
+ button.primary:hover { filter: brightness(1.08); }
190
+ button.primary:disabled { opacity: .5; cursor: not-allowed; }
191
+ `,Ft=`(function () {
192
+ "use strict";
193
+ var REFRESH_MS = 1500;
194
+ var state = {
195
+ runs: [], activeId: null, timer: null, es: null,
196
+ // chat \u76F8\u5173\uFF08Task D\uFF09\uFF1AchatEnabled \u7531 /health \u63A2\u6D4B\uFF0C\u672A\u5F00\u542F\u65F6\u4E0B\u9762\u5176\u4F59\u5B57\u6BB5\u5168\u90E8\u65E0\u610F\u4E49\u3002
197
+ chatEnabled: false, chatAgents: [], chatAgentsLoaded: false,
198
+ chatSessionId: null, activeChatId: null,
199
+ };
200
+ var el = function (id) { return document.getElementById(id); };
201
+
202
+ function esc(s) {
203
+ return String(s == null ? "" : s).replace(/[&<>"]/g, function (c) {
204
+ return { "&": "&amp;", "<": "&lt;", ">": "&gt;", '"': "&quot;" }[c];
205
+ });
206
+ }
207
+
208
+ async function getJSON(path) {
209
+ var res = await fetch(path, { headers: { accept: "application/json" } });
210
+ if (!res.ok) throw new Error(path + " -> " + res.status);
211
+ return res.json();
212
+ }
213
+
214
+ async function pingHealth() {
215
+ var dot = el("health-dot");
216
+ try {
217
+ var h = await getJSON("/health");
218
+ dot.className = "dot " + (h && h.ok ? "ok" : "err");
219
+ applyChatCapability(h && h.chat === true);
220
+ } catch (e) {
221
+ dot.className = "dot err";
222
+ }
223
+ }
224
+
225
+ /**
226
+ * /health \u7684 chat \u5B57\u6BB5\u51B3\u5B9A Local Chat \u9762\u677F\u662F\u5426\u53EF\u7528\uFF08daemon \u4EE5 --trace-chat \u542F\u52A8\u624D\u662F true\uFF09\u3002
227
+ * \u9996\u6B21\u63A2\u6D4B\u5230 true \u65F6\u61D2\u52A0\u8F7D\u4E00\u6B21\u53EF\u7528 Agent \u5217\u8868\uFF0C\u4E4B\u540E\u4E0D\u91CD\u590D\u62C9\u53D6\u3002
228
+ */
229
+ function applyChatCapability(enabled) {
230
+ state.chatEnabled = enabled;
231
+ el("chat-bar").classList.toggle("hidden", !enabled);
232
+ // assistant-link \u5E38\u9A7B\u53EF\u89C1\uFF1A/ \u9ED8\u8BA4\u5DF2\u662F assistant-ui \u8FD0\u884C\u89C6\u56FE\uFF0C\u4E0D\u4F9D\u8D56 chat \u5F00\u5173\u3002
233
+ if (enabled && !state.chatAgentsLoaded) loadChatAgents();
234
+ }
235
+
236
+ async function loadChatAgents() {
237
+ try {
238
+ var data = await getJSON("/api/chat/agents");
239
+ state.chatAgents = data.agents || [];
240
+ state.chatAgentsLoaded = true;
241
+ var sel = el("chat-agent");
242
+ sel.innerHTML = state.chatAgents.map(function (a) {
243
+ return '<option value="' + esc(a) + '">' + esc(a) + "</option>";
244
+ }).join("");
245
+ if (!state.chatAgents.length) setChatHint("\u672C\u673A\u672A\u68C0\u6D4B\u5230\u53EF\u7528\u7684\u7F16\u7A0B Agent");
246
+ } catch (e) {
247
+ setChatHint("\u65E0\u6CD5\u52A0\u8F7D Agent \u5217\u8868\uFF1A" + e.message);
248
+ }
249
+ }
250
+
251
+ function setChatHint(text) {
252
+ el("chat-hint").textContent = text || "";
253
+ }
254
+
255
+ function updateSessionIndicator() {
256
+ var el2 = el("chat-session");
257
+ var btn = el("chat-clear-session");
258
+ if (state.chatSessionId) {
259
+ el2.textContent = "\u7EED\u804A\u4F1A\u8BDD " + state.chatSessionId.slice(0, 8) + "\u2026";
260
+ btn.classList.remove("hidden");
261
+ } else {
262
+ el2.textContent = "";
263
+ btn.classList.add("hidden");
264
+ }
265
+ }
266
+
267
+ /** \u4E00\u8F6E chat \u7ED3\u675F\uFF08\u65E0\u8BBA\u6210\u529F/\u6253\u65AD/\u5931\u8D25\uFF09\u540E\u8C03\u7528\uFF1A\u505C\u6B62\u6309\u94AE\u9690\u85CF\uFF0C\u5141\u8BB8\u518D\u6B21\u53D1\u9001\u3002 */
268
+ function endChatTurn() {
269
+ state.activeChatId = null;
270
+ el("chat-stop").classList.add("hidden");
271
+ el("chat-send").disabled = false;
272
+ }
273
+
274
+ async function sendChatTurn() {
275
+ if (!state.chatEnabled || state.activeChatId) return;
276
+ var prompt = el("chat-input").value.trim();
277
+ if (!prompt) { setChatHint("\u8BF7\u5148\u8F93\u5165\u5185\u5BB9"); return; }
278
+ var requestId = "chat-" + Date.now() + "-" + Math.random().toString(36).slice(2, 8);
279
+ var body = { requestId: requestId, prompt: prompt };
280
+ var agent = el("chat-agent").value;
281
+ if (agent) body.agent = agent;
282
+ if (state.chatSessionId) body.sessionId = state.chatSessionId;
283
+
284
+ state.activeChatId = requestId;
285
+ el("chat-send").disabled = true;
286
+ el("chat-stop").classList.remove("hidden");
287
+ setChatHint("");
288
+
289
+ var res;
290
+ try {
291
+ res = await fetch("/api/chat", {
292
+ method: "POST",
293
+ headers: { "content-type": "application/json" },
294
+ body: JSON.stringify(body),
295
+ });
296
+ } catch (e) {
297
+ setChatHint("\u53D1\u9001\u5931\u8D25\uFF1A" + e.message);
298
+ endChatTurn();
299
+ return;
300
+ }
301
+ if (!res.ok) {
302
+ var errBody = await res.json().catch(function () { return {}; });
303
+ setChatHint("\u53D1\u9001\u5931\u8D25\uFF08" + res.status + "\uFF09\uFF1A" + (errBody.error || ""));
304
+ endChatTurn();
305
+ return;
306
+ }
307
+ // 202 \u53D7\u7406\uFF1A\u7ACB\u5373\u5207\u5230\u8BE5 run \u7684 SSE \u6D41\u89C2\u770B\uFF0C\u4E0E\u300C\u770B\u670D\u52A1\u7AEF run\u300D\u590D\u7528\u540C\u4E00\u6761\u6D88\u8D39\u8DEF\u5F84\u3002
308
+ el("chat-input").value = "";
309
+ selectRun(requestId);
310
+ refreshRuns();
311
+ }
312
+
313
+ async function stopChatTurn() {
314
+ if (!state.activeChatId) return;
315
+ try {
316
+ var res = await fetch("/api/chat/" + encodeURIComponent(state.activeChatId) + "/stop", { method: "POST" });
317
+ if (!res.ok) setChatHint("\u6253\u65AD\u5931\u8D25\uFF08" + res.status + "\uFF09");
318
+ // \u6210\u529F\u4E0E\u5426\u90FD\u4E0D\u672C\u5730\u6E05\u7406 activeChatId\uFF1A\u7EC8\u6001\u4EE5 SSE finish \u5E27\u4E3A\u51C6\uFF0C\u907F\u514D\u4E0E\u6253\u65AD\u7ADE\u6001\u3002
319
+ } catch (e) {
320
+ setChatHint("\u6253\u65AD\u5931\u8D25\uFF1A" + e.message);
321
+ }
322
+ }
323
+
324
+ function timeAgo(iso) {
325
+ if (!iso) return "";
326
+ var t = new Date(iso).getTime();
327
+ if (isNaN(t)) return "";
328
+ var s = Math.round((Date.now() - t) / 1000);
329
+ if (s < 60) return s + "s \u524D";
330
+ if (s < 3600) return Math.round(s / 60) + "m \u524D";
331
+ if (s < 86400) return Math.round(s / 3600) + "h \u524D";
332
+ return Math.round(s / 86400) + "d \u524D";
333
+ }
334
+
335
+ function renderRuns() {
336
+ var ul = el("run-list");
337
+ if (!state.runs.length) {
338
+ ul.innerHTML = '<li class="empty">\u6682\u65E0 run\u3002\u670D\u52A1\u7AEF\u89E6\u53D1\u4E00\u6B21 workflow agent step \u540E\u4F1A\u51FA\u73B0\u5728\u8FD9\u91CC\u3002</li>';
339
+ return;
340
+ }
341
+ ul.innerHTML = state.runs.map(function (r) {
342
+ var active = r.id === state.activeId ? " active" : "";
343
+ var dur = r.endedAt
344
+ ? Math.max(0, Math.round((new Date(r.endedAt) - new Date(r.startedAt)) / 1000)) + "s"
345
+ : "\u2026";
346
+ var sourceBadge = r.source === "chat"
347
+ ? '<span class="badge source source-chat">chat</span>'
348
+ : "";
349
+ return '<li class="run-item' + active + '" data-id="' + esc(r.id) + '">' +
350
+ '<div class="row1"><span class="badge ' + esc(r.status) + '">' + esc(r.status) + '</span>' +
351
+ '<span class="badge agent">' + esc(r.agent) + '</span>' + sourceBadge +
352
+ '<span class="rid">' + esc(r.requestId) + '</span></div>' +
353
+ '<div class="row2"><span>' + esc(r.projectId || "-") + '</span>' +
354
+ '<span>' + r.eventCount + ' events' + (r.droppedEvents ? ' (drop ' + r.droppedEvents + ')' : '') + '</span>' +
355
+ '<span>' + esc(timeAgo(r.startedAt)) + (r.status === "running" ? '' : ' \xB7 ' + dur) + '</span></div>' +
356
+ '</li>';
357
+ }).join("");
358
+ Array.prototype.forEach.call(ul.querySelectorAll(".run-item"), function (li) {
359
+ li.addEventListener("click", function () {
360
+ selectRun(li.getAttribute("data-id"));
361
+ });
362
+ });
363
+ }
364
+
365
+ function renderGroup(g) {
366
+ return '<div class="group">' + g.items.map(renderItem).join("") + "</div>";
367
+ }
368
+
369
+ function renderItem(it) {
370
+ if (it.kind === "text") {
371
+ return '<div class="item text">' + esc(it.text) + "</div>";
372
+ }
373
+ if (it.kind === "status") {
374
+ var cls = /\u9519\u8BEF|\u5931\u8D25|error/i.test(it.text) ? " error" : (/\u2713|\u5B8C\u6210|\u6210\u529F/.test(it.text) ? " result" : "");
375
+ return '<div class="item status' + cls + '"><span>' + esc(it.text) + '</span><span class="line"></span></div>';
376
+ }
377
+ if (it.kind === "ask") {
378
+ var html = '<div class="item ask"><div class="ask-head"><span class="tag ask">ask</span>' +
379
+ "<span>\u23F8 \u7B49\u5F85\u4EBA\u5DE5\u56DE\u7B54</span></div>" +
380
+ '<div class="ask-q">' + esc(it.text) + "</div>";
381
+ if (it.fullText) html += '<div class="ask-body">' + esc(it.fullText) + "</div>";
382
+ html += "</div>";
383
+ return html;
384
+ }
385
+ // thinking / tool / tool_result / permission -> collapsible
386
+ var body = it.fullText ? esc(it.fullText) : esc(it.text);
387
+ var title = it.kind === "tool" ? esc(it.text) : esc((it.toolName ? it.toolName + " " : "") + labelOf(it.kind));
388
+ return '<details class="item"><summary><span class="tag ' + esc(it.kind) + '">' + esc(it.kind) + "</span>" +
389
+ "<span>" + title + "</span></summary>" +
390
+ '<div class="body">' + body + "</div></details>";
391
+ }
392
+
393
+ function labelOf(kind) {
394
+ return { thinking: "\u601D\u8003\u8FC7\u7A0B", tool: "\u5DE5\u5177\u8C03\u7528", tool_result: "\u8FD4\u56DE\u7ED3\u679C", permission: "\u5F85\u6388\u6743", ask: "\u5411\u4EBA\u63D0\u95EE" }[kind] || kind;
395
+ }
396
+
397
+ function stopStream() {
398
+ if (state.es) {
399
+ try { state.es.close(); } catch (e) { /* noop */ }
400
+ state.es = null;
401
+ }
402
+ }
403
+
404
+ function setHead(run) {
405
+ if (!run) { el("timeline-head").textContent = "\u9009\u62E9\u5DE6\u4FA7\u4E00\u4E2A run \u67E5\u770B\u6267\u884C\u6D41"; return; }
406
+ el("timeline-head").textContent =
407
+ "run " + run.requestId + " \xB7 " + run.agent + " \xB7 " + run.status +
408
+ " \xB7 " + (run.eventCount || 0) + " events";
409
+ }
410
+
411
+ function renderDetail(data) {
412
+ var body = el("timeline");
413
+ var groups = (data.groups || []).filter(function (g) { return g.items && g.items.length; });
414
+ if (data.run) setHead(data.run);
415
+ if (!groups.length) {
416
+ body.innerHTML = '<div class="empty">\u8BE5 run \u6682\u65E0\u53EF\u5C55\u793A\u7684 agent \u4E8B\u4EF6\u3002</div>';
417
+ return;
418
+ }
419
+ var atBottom = body.scrollHeight - body.scrollTop - body.clientHeight < 80;
420
+ body.innerHTML = groups.map(renderGroup).join("");
421
+ if (atBottom) body.scrollTop = body.scrollHeight;
422
+ }
423
+
424
+ function selectRun(id) {
425
+ if (state.activeId === id && state.es) return; // \u5DF2\u5728\u6D41\u5F0F\u89C2\u770B\u8BE5 run\uFF0C\u52FF\u91CD\u5EFA\u8FDE\u63A5
426
+ state.activeId = id;
427
+ renderRuns();
428
+ stopStream();
429
+ el("timeline").innerHTML = '<div class="empty">\u8FDE\u63A5\u4E2D\u2026</div>';
430
+ var es = new EventSource("/api/runs/" + encodeURIComponent(id) + "/stream");
431
+ state.es = es;
432
+ es.addEventListener("snapshot", function (e) { renderDetail(JSON.parse(e.data)); });
433
+ es.addEventListener("update", function (e) { renderDetail(JSON.parse(e.data)); });
434
+ es.addEventListener("finish", function (e) {
435
+ var data = JSON.parse(e.data);
436
+ renderDetail(data);
437
+ stopStream(); // \u7EC8\u6001\uFF1A\u5173\u95ED\u6D41\uFF0Crun \u72B6\u6001\u540E\u7EED\u7531\u5217\u8868\u8F6E\u8BE2\u7EF4\u62A4
438
+ onRunFinished(data.run);
439
+ });
440
+ es.onerror = function () { /* EventSource \u81EA\u52A8\u91CD\u8FDE\uFF1B\u65E0\u9700\u5904\u7406 */ };
441
+ }
442
+
443
+ /**
444
+ * run \u7EC8\u6001\u7EDF\u4E00\u6536\u53E3\uFF1A\u82E5\u662F\u521A\u53D1\u8D77\u7684 chat \u8F6E\u7ED3\u675F\uFF0C\u6062\u590D\u53D1\u9001\u6309\u94AE\u5E76\u6355\u83B7 sessionId\uFF08\u4F9B\u4E0B\u4E00\u8F6E\u7EED\u804A\uFF09\u3002
445
+ * \u975E chat \u6765\u6E90\u6216\u670D\u52A1\u7AEF workflow run \u4E0D\u5F71\u54CD chat \u9762\u677F\u72B6\u6001\u3002
446
+ */
447
+ function onRunFinished(run) {
448
+ if (!run || run.source !== "chat") return;
449
+ if (run.requestId === state.activeChatId) endChatTurn();
450
+ if (run.sessionId) {
451
+ state.chatSessionId = run.sessionId;
452
+ updateSessionIndicator();
453
+ }
454
+ setChatHint("\u4E0A\u4E00\u8F6E\uFF1A" + run.status + (run.error ? "\uFF08" + run.error + "\uFF09" : ""));
455
+ }
456
+
457
+ async function refreshRuns() {
458
+ try {
459
+ var data = await getJSON("/api/runs");
460
+ state.runs = data.runs || [];
461
+ el("meta-text").textContent = state.runs.length + " runs";
462
+ renderRuns();
463
+ if (!state.activeId && state.runs.length) {
464
+ selectRun(state.runs[0].id);
465
+ } else if (state.activeId && !state.runs.some(function (r) { return r.id === state.activeId; })) {
466
+ // \u5F53\u524D\u67E5\u770B\u7684 run \u5DF2\u88AB ring buffer \u6DD8\u6C70\uFF1A\u505C\u6D41\u6E05\u7A7A
467
+ stopStream();
468
+ state.activeId = null;
469
+ el("timeline").innerHTML = '<div class="empty">\u8BE5 run \u5DF2\u4E0D\u5728\u6700\u8FD1\u8BB0\u5F55\u4E2D\u3002</div>';
470
+ setHead(null);
471
+ }
472
+ } catch (e) {
473
+ el("meta-text").textContent = "\u65E0\u6CD5\u8FDE\u63A5 daemon";
474
+ }
475
+ }
476
+
477
+ function start() {
478
+ pingHealth();
479
+ refreshRuns();
480
+ state.timer = setInterval(function () {
481
+ refreshRuns();
482
+ pingHealth();
483
+ }, REFRESH_MS);
484
+ el("refresh").addEventListener("click", refreshRuns);
485
+ el("chat-send").addEventListener("click", sendChatTurn);
486
+ el("chat-stop").addEventListener("click", stopChatTurn);
487
+ el("chat-clear-session").addEventListener("click", function () {
488
+ state.chatSessionId = null;
489
+ updateSessionIndicator();
490
+ setChatHint("\u5DF2\u6E05\u7A7A\u7EED\u804A\u4F1A\u8BDD\uFF0C\u4E0B\u4E00\u8F6E\u5F00\u542F\u65B0\u4F1A\u8BDD");
491
+ });
492
+ el("chat-input").addEventListener("keydown", function (ev) {
493
+ if ((ev.metaKey || ev.ctrlKey) && ev.key === "Enter") {
494
+ ev.preventDefault();
495
+ sendChatTurn();
496
+ }
497
+ });
498
+ }
499
+
500
+ document.addEventListener("DOMContentLoaded", start);
501
+ })();
502
+ `;import{mkdir as Jr}from"fs/promises";import{logger as Pe}from"aitable-workflow-core";import Wr from"path";import{logger as Gr,resolveInsideRoot as Nt,assertPortableId as qr}from"aitable-workflow-core";var zr="relay:daemon";function ie(o,e,t){if(t&&t.trim()!=="")if(Wr.isAbsolute(t))Gr.warn(zr,"\u5FFD\u7565\u7EDD\u5BF9\u8DEF\u5F84 workDir\uFF0C\u56DE\u9000\u5230 workspaceRoot/projectId",{workDir:t,projectId:e});else return Nt(o,t,{allowRoot:!1});return Nt(o,qr(e,{label:"projectId"}),{allowRoot:!1})}c(ie,"resolveRelayWorkDir");var $e="relay:chat",Le="local-chat",Yr=128,Ut=32e3,ae=class{constructor(e){this.deps=e}deps;static{c(this,"ChatTurnManager")}active=new Map;listAgents(){return this.deps.detectAgents().map(e=>e.type)}start(e){if(typeof e.requestId!="string"||e.requestId.trim()===""||e.requestId.length>Yr)return{ok:!1,status:400,error:"requestId \u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32\u4E14\u4E0D\u8D85\u8FC7 128 \u5B57\u7B26"};if(this.active.has(e.requestId))return{ok:!1,status:409,error:"\u8BE5 requestId \u4ECD\u6709\u6D3B\u8DC3\u8F6E\u6B21\u672A\u7ED3\u675F"};if(typeof e.prompt!="string"||e.prompt.trim()==="")return{ok:!1,status:400,error:"prompt \u4E0D\u80FD\u4E3A\u7A7A"};if(e.prompt.length>Ut)return{ok:!1,status:400,error:`prompt \u8D85\u8FC7\u957F\u5EA6\u4E0A\u9650 ${Ut}`};let t=new AbortController;return this.active.set(e.requestId,t),this.deps.enqueue(()=>this.runTurn(e,t)),{ok:!0}}stop(e){let t=this.active.get(e);return t?(t.abort(),!0):!1}activeCount(){return this.active.size}async runTurn(e,t){let{requestId:n}=e;try{let r=e.agent??this.listAgents()[0];if(!r){this.fail(n,"\u672C\u673A\u672A\u68C0\u6D4B\u5230\u53EF\u7528\u7684\u7F16\u7A0B Agent");return}let s;try{s=ie(this.deps.workspaceRoot,Le,e.workDir)}catch(d){let p=d instanceof Error?d.message:String(d);this.fail(n,`workDir \u8D8A\u754C\u6216\u975E\u6CD5\uFF1A${p}`);return}await Jr(s,{recursive:!0}),this.deps.store.startRun({requestId:n,projectId:Le,agent:r,workDir:s,source:"chat"});let i={agent:r,workDir:s,signal:t.signal,onEvent:c(d=>this.deps.store.appendEvent(n,d),"onEvent")};e.sessionId&&(i.sessionId=e.sessionId);let a=e.timeoutMs??this.deps.defaultTimeoutMs;a!=null&&(i.timeoutMs=a);let l;try{l=await this.deps.runAgent(e.prompt,i)}catch(d){let p=d instanceof Error?d.message:String(d),u=t.signal.aborted?"aborted":"failed";this.deps.store.finishRun(n,{status:u,error:p}),Pe.warn($e,"chat turn ended with error",{requestId:n,status:u,error:p});return}this.deps.store.finishRun(n,{status:"succeeded",response:l.response,sessionId:l.sessionId}),Pe.info($e,"chat turn succeeded",{requestId:n,sessionId:l.sessionId})}finally{this.active.delete(n)}}fail(e,t){this.deps.store.startRun({requestId:e,projectId:Le,agent:"qoder",workDir:"",source:"chat"}),this.deps.store.finishRun(e,{status:"failed",error:t}),Pe.warn($e,"chat turn rejected before agent run",{requestId:e,error:t})}};import Oe from"ws";import{logger as P,RELAY_REJECTED_CODE as Vr,isRelayMessage as Kr}from"aitable-workflow-core";var $="relay:conn",Wt=1e3,Xr=3e4,Zr=Number(process.env.AITABLE_RELAY_SERVER_STALE_MS??9e4),ce=class{static{c(this,"RelayConnection")}ws=null;delay=Wt;timer=null;watchdog=null;should=!0;permanentlyRejected=!1;accepted=!1;lastServerFrameAt=0;serverUrl;key;token;onMessage;onOpen;onAccepted;onPermanentReject;mkWs;staleMs;constructor(e){this.serverUrl=e.serverUrl,this.key=e.key??"",this.token=e.token??"",this.onMessage=e.onMessage,this.onOpen=e.onOpen,this.onAccepted=e.onAccepted,this.onPermanentReject=e.onPermanentReject,this.mkWs=e.mkWs??(t=>new Oe(t)),this.staleMs=e.staleMs??Zr}connect(){this.permanentlyRejected||(this.should=!0,this.doConnect())}send(e){this.ws&&this.ws.readyState===Oe.OPEN&&this.ws.send(JSON.stringify(e))}close(){this.should=!1,this.timer&&(clearTimeout(this.timer),this.timer=null),this.watchdog&&(clearTimeout(this.watchdog),this.watchdog=null),this.ws?.close()}isPermanentlyRejected(){return this.permanentlyRejected}currentSocket(){return this.ws}buildUrl(){let e=this.serverUrl.replace(/\/+$/,"").replace(/^http/,"ws"),t=this.token?`token=${encodeURIComponent(this.token)}`:`key=${encodeURIComponent(this.key)}`;return`${e}/api/relay/connect?${t}`}doConnect(){if(!this.should||this.permanentlyRejected)return;let e=this.buildUrl();P.info($,"connecting",{serverUrl:this.serverUrl}),this.watchdog&&(clearTimeout(this.watchdog),this.watchdog=null),this.accepted=!1,this.lastServerFrameAt=0;let t=this.mkWs(e);this.ws=t,t.on("open",()=>{P.info($,"connected"),this.onOpen?.(t)}),t.on("message",n=>{this.accepted||(this.accepted=!0,this.delay=Wt,this.onAccepted?.(t)),this.lastServerFrameAt=Date.now(),this.armWatchdog();let r;try{r=JSON.parse(typeof n=="string"?n:String(n))}catch{return}Kr(r)&&(r.type==="ping"&&this.send({type:"pong"}),this.onMessage(r))}),t.on("close",(n,r)=>{this.watchdog&&(clearTimeout(this.watchdog),this.watchdog=null);let s=r==null?"":String(r);if(n===Vr){this.permanentlyRejected=!0,this.should=!1,P.error($,"server permanently rejected this machine: its connection key is unknown or was removed; re-issue the relay connect command and restart with the new key",{code:n,reason:s}),this.onPermanentReject?.({code:n,reason:s});return}P.warn($,"disconnected",{code:n}),this.scheduleReconnect()}),t.on("error",n=>{P.error($,"ws error",{detail:n instanceof Error?n.message:String(n)})})}armWatchdog(){this.watchdog&&clearTimeout(this.watchdog),this.watchdog=setTimeout(()=>{if(!(!this.accepted||!this.lastServerFrameAt||this.ws?.readyState!==Oe.OPEN)){P.warn($,"server heartbeat stale; closing socket to reconnect",{staleMs:Date.now()-this.lastServerFrameAt});try{this.ws.close()}catch{}}},this.staleMs+1),this.watchdog.unref?.()}scheduleReconnect(){!this.should||this.permanentlyRejected||this.timer||(P.info($,"reconnecting",{ms:this.delay}),this.timer=setTimeout(()=>{this.timer=null,this.doConnect()},this.delay),this.timer.unref?.(),this.delay=Math.min(this.delay*2,Xr))}};import{createHash as Qr}from"crypto";import{readdir as eo,readFile as to,stat as no}from"fs/promises";import Gt from"path";import{isAllowedArtifactPath as ro,normalizeArtifactRelPath as oo}from"aitable-workflow-core";var qt={async upload(o,e,t){let n=await fetch(o,{method:"PUT",body:e,headers:{...t}});if(!n.ok)throw new Error(`artifact PUT failed: ${n.status} ${n.statusText}`)}};async function zt(o){let e=[];return await Jt(o,o,e),e.sort((t,n)=>t.relPath.localeCompare(n.relPath))}c(zt,"scanArtifacts");async function Jt(o,e,t){let n;try{n=await eo(e,{withFileTypes:!0})}catch{return}for(let r of n){if(r.name==="node_modules"||r.name.startsWith("."))continue;let s=Gt.join(e,r.name);if(r.isDirectory())await Jt(o,s,t);else if(r.isFile()){let i=Gt.relative(o,s).replace(/\\/g,"/");if(!ro(i))continue;let a=await no(s),l=await to(s),d=Qr("sha256").update(l).digest("hex");t.push({relPath:oo(i),absPath:s,size:a.size,sha256:d})}}}c(Jt,"walk");import nn from"path";import{logger as x}from"aitable-workflow-core";import{logger as L,spawnManagedProcess as so}from"aitable-workflow-core";var O="engine-supervisor",je=2e3,le=class{static{c(this,"EngineSupervisor")}options;doSpawn;setTimer;clearTimer;child=null;childGen=0;consecutiveFailures=0;lastExitCode=null;lastError=null;restartTimer=null;stopped=!0;constructor(e){this.options=e,this.doSpawn=e.spawnImpl??so,this.setTimer=e.setTimeoutImpl??((t,n)=>setTimeout(t,n)),this.clearTimer=e.clearTimeoutImpl??(t=>clearTimeout(t))}get status(){return{running:this.child!=null,pid:this.child?.managed.child.pid??null,generation:this.childGen,startedAt:this.child?new Date(this.child.startedAt).toISOString():null,consecutiveFailures:this.consecutiveFailures,lastExitCode:this.lastExitCode,lastError:this.lastError}}start(){this.stopped=!1,!this.child&&this.spawnChild()}async stop(){this.stopped=!0,this.restartTimer&&(this.clearTimer(this.restartTimer),this.restartTimer=null);let e=this.child;if(!e)return;e.stopping=!0;let t=e.managed.child.pid;if(t==null){this.child=null;return}let n=e.gen;await e.managed.terminateTree({gracePeriodMs:this.options.drainTimeoutMs??2e4}),e.managed.child.exitCode==null&&e.managed.child.signalCode==null&&(L.error(O,"\u5F15\u64CE\u8FDB\u7A0B\u672A\u54CD\u5E94\u5F3A\u5236\u7EC8\u6B62\uFF0C\u653E\u5F03\u7B49\u5F85\uFF08\u53EF\u80FD\u6B8B\u7559\u5B64\u513F\u8FDB\u7A0B\uFF09",{projectId:this.options.projectId,pid:t,generation:n}),this.child?.gen===n&&(this.child=null))}spawnChild(){this.childGen+=1;let e=this.childGen,t=["run","--config",this.options.workspaceDir,"--emit-events","ipc"],n=this.doSpawn({command:process.execPath,args:[this.options.cliPath,...t],cwd:this.options.workspaceDir,stdio:["ignore","pipe","pipe","ipc"],...this.options.env?{env:this.options.env}:{}}),r=n.child,s={managed:n,gen:e,startedAt:Date.now(),stopping:!1};this.child=s,L.info(O,"engine started",{projectId:this.options.projectId,pid:r.pid,generation:e}),r.on("message",i=>{io(i)&&this.options.onRunEvent?.(i.event)}),r.on("error",i=>{this.lastError=i.message,L.error(O,"engine spawn error",{projectId:this.options.projectId,error:i.message})}),r.on("exit",(i,a)=>this.handleExit(s,i,a)),this.forwardChildOutput(r.stdout,s,"stdout"),this.forwardChildOutput(r.stderr,s,"stderr")}forwardChildOutput(e,t,n){if(!e)return;e.setEncoding("utf8");let r="",s=c(i=>{let a=i.trim();if(!a)return;let l=a.length>je?`${a.slice(0,je)}\u2026[+${a.length-je}]`:a;L.info(O,l,{projectId:this.options.projectId,generation:t.gen,stream:n})},"emit");e.on("data",i=>{if(this.child?.gen!==t.gen)return;let l=(r+i).split(/\r?\n/);r=l.pop()??"";for(let d of l)s(d)}),e.on("end",()=>{r.trim()&&this.child?.gen===t.gen&&s(r),r=""})}handleExit(e,t,n){if(this.child?.gen===e.gen&&(this.child=null),this.lastExitCode=t,L.info(O,"engine exited",{projectId:this.options.projectId,generation:e.gen,code:t,signal:n}),e.stopping||this.stopped)return;this.consecutiveFailures+=1;let r=this.options.maxConsecutiveFailures??5;if(this.consecutiveFailures>=r){L.error(O,"engine crash loop\uFF0C\u505C\u6B62\u91CD\u542F\u5E76\u4E0A\u62A5",{projectId:this.options.projectId,failures:this.consecutiveFailures}),this.stopped=!0,this.options.onCrashLoop?.({projectId:this.options.projectId,failures:this.consecutiveFailures,lastExitCode:t});return}let s=this.options.restartBackoffMs??1e3,i=this.options.restartBackoffMaxMs??6e4,a=Math.min(i,s*2**(this.consecutiveFailures-1));L.warn(O,"engine \u5F02\u5E38\u9000\u51FA\uFF0C\u9000\u907F\u91CD\u542F",{projectId:this.options.projectId,failures:this.consecutiveFailures,delayMs:a}),this.restartTimer=this.setTimer(()=>{this.restartTimer=null,!this.stopped&&!this.child&&this.spawnChild()},a)}markHealthy(){this.consecutiveFailures=0}};function io(o){return typeof o=="object"&&o!==null&&o.type==="run-event"&&"event"in o}c(io,"isRunEventMessage");import{appendFile as ao,mkdir as co,rename as lo,stat as po}from"fs/promises";import uo from"path";import{logger as de}from"aitable-workflow-core";var pe="event-spool",ue=class{static{c(this,"EventSpool")}options;setInterval;clearInterval;now;buffer=[];pending=[];seq=0;timer=null;flushing=!1;constructor(e){this.options=e,this.setInterval=e.setIntervalImpl??((t,n)=>setInterval(t,n)),this.clearInterval=e.clearIntervalImpl??(t=>clearInterval(t)),this.now=e.now??Date.now}get lastSeq(){return this.seq}get pendingCount(){return this.pending.length}start(){this.timer||(this.timer=this.setInterval(()=>{this.flush()},this.options.flushIntervalMs??500))}async stop(){this.timer&&(this.clearInterval(this.timer),this.timer=null),await this.flush()}append(e){this.seq+=1;let t={seq:this.seq,ts:new Date(this.now()).toISOString(),event:e};this.pending.push(t),this.buffer.push(t);let n=this.options.maxPending??5e3;if(this.pending.length>n){let s=this.pending.splice(0,this.pending.length-n);de.warn(pe,"\u5F85\u53D1\u4E8B\u4EF6\u8D85\u4E0A\u9650\uFF0C\u4E22\u5F03\u6700\u65E7\u7684\u6279\u6B21",{projectId:this.options.projectId,dropped:s.length,untilSeq:s[s.length-1]?.seq})}let r=this.options.retain??2e3;this.buffer.length>r&&this.buffer.splice(0,this.buffer.length-r),this.options.persist!==!1&&this.persist(t)}async flush(){if(this.flushing||this.pending.length===0)return;this.flushing=!0;let e=this.pending.slice(0,this.options.maxBatch??200);try{await this.options.send(e);let t=new Set(e.map(n=>n.seq));this.pending=this.pending.filter(n=>!t.has(n.seq))}catch(t){de.warn(pe,"\u4E8B\u4EF6\u6279\u4E0A\u884C\u5931\u8D25\uFF08\u4FDD\u7559\u5F85\u4E0B\u8F6E\u91CD\u8BD5\uFF09",{projectId:this.options.projectId,count:e.length,error:t instanceof Error?t.message:String(t)})}finally{this.flushing=!1}}replayFrom(e){let t=new Set(this.pending.map(r=>r.seq)),n=this.buffer.filter(r=>r.seq>e&&!t.has(r.seq));return n.length===0?0:(this.pending=[...this.pending,...n].sort((r,s)=>r.seq-s.seq),de.info(pe,"\u8865\u4F20\u7F3A\u53E3\u4E8B\u4EF6",{projectId:this.options.projectId,serverLastSeq:e,replay:n.length}),n.length)}async persist(e){let t=uo.join(this.options.spoolDir,"run-events.jsonl");try{await co(this.options.spoolDir,{recursive:!0}),await po(t).then(r=>r.size).catch(()=>0)>(this.options.rotateBytes??10*1024*1024)&&await lo(t,`${t}.1`).catch(()=>{}),await ao(t,`${JSON.stringify(e)}
503
+ `,"utf8")}catch(n){de.warn(pe,"spool \u843D\u76D8\u5931\u8D25",{projectId:this.options.projectId,error:n instanceof Error?n.message:String(n)})}}};import{readdir as Fe,rm as He,stat as ge}from"fs/promises";import N from"path";import{logger as q}from"aitable-workflow-core";import{createHash as yo}from"crypto";import{mkdir as De,readFile as ko,rename as bo,rm as Ro,writeFile as Xt}from"fs/promises";import me from"path";import{decodeWorkspaceBundle as Co,logger as xo,resolveInsideRoot as Ao}from"aitable-workflow-core";import{chmod as mo,readFile as fo,rename as go,writeFile as ho}from"fs/promises";var Yt="# \u2500\u2500\u2500 aitable-workflow managed credentials (auto-generated, do not edit) \u2500\u2500\u2500",Vt="# \u2500\u2500\u2500 end managed credentials \u2500\u2500\u2500";function vo(o,e){let t=o.split(`
504
+ `),n=t.indexOf(Yt),r=t.indexOf(Vt),s;n!==-1&&r!==-1&&r>n?s=[...t.slice(0,n),...t.slice(r+1)].join(`
505
+ `):s=o,s=s.replace(/^\n+/,"");let i=Object.entries(e).sort(([l],[d])=>l.localeCompare(d));return i.length===0?s:`${[Yt,...i.map(([l,d])=>`${l}=${wo(d)}`),Vt].join(`
25
506
  `)}
26
- ${i?`
27
- ${i}`:""}`}c(No,"mergeEnvContent");function Go(r){return r===""||/[\s#'"`\\]/.test(r)?`"${r.replace(/\\/g,"\\\\").replace(/"/g,'\\"').replace(/\n/g,"\\n")}"`:r}c(Go,"quoteEnvValue");async function $t(r,t){let e=await Fo(r,"utf8").catch(()=>""),n=No(e,t);if(n===e||n===""&&e==="")return!1;let o=`${r}.aitable-sync-tmp`;return await Wo(o,n,{encoding:"utf8",mode:384}),await Bo(o,384).catch(()=>{}),await Uo(o,r),!0}c($t,"mergeEnvFile");var Xo="workspace-sync",pe=".workspace-meta.json";function Qo(r){return Ho("sha256").update(r).digest("hex")}c(Qo,"sha256Hex");async function Se(r,t){let n=await(r.fetchImpl??fetch)(`${r.gatewayUrl.replace(/\/+$/,"")}${t}`,{headers:{authorization:`Bearer ${r.machineKey}`}});if(!n.ok){let o=await n.text().catch(()=>"");throw new Error(`runner API ${t} \u5931\u8D25: HTTP ${n.status} ${o.slice(0,200)}`)}return n}c(Se,"apiGet");async function Zo(r){try{let t=await Jo(le.join(r,pe),"utf8"),e=JSON.parse(t);return e&&typeof e.projectId=="string"?e:null}catch{return null}}c(Zo,"readWorkspaceMeta");function Ee(r,t){return zo(r,t,{allowRoot:!1})}c(Ee,"resolveTracked");async function er(r,t){let e=Ee(r,t.path);await Ae(le.dirname(e),{recursive:!0});let n=`${e}.aitable-sync-tmp`;await Pt(n,t.content,"utf8"),await Vo(n,e)}c(er,"writeTracked");async function jt(r,t,e){let n=await Zo(e);if(n&&n.projectId!==t)throw new Error(`\u5DE5\u4F5C\u533A\u76EE\u5F55\u5F52\u5C5E\u4E0D\u7B26: \u76EE\u5F55\u8BB0\u5F55 projectId=${n.projectId}\uFF0C\u8BF7\u6C42\u540C\u6B65 ${t}\uFF08${e}\uFF09`);let i=await(await Se(r,`/api/runner/workspace/${t}`)).json(),s=0,a=0,l="up-to-date",p=n?.trackedManifest??{};if(!n||n.revision!==i.revision){l="synced";let v=await Se(r,`/api/runner/workspace/${t}/bundle`),I=Ko(Buffer.from(await v.arrayBuffer()));if(I.projectId!==t)throw new Error(`\u5FEB\u7167\u5305\u5F52\u5C5E\u4E0D\u7B26: \u5305\u5185 projectId=${I.projectId}\uFF0C\u671F\u671B ${t}`);I.revision!==i.revision&&(i.revision=I.revision),await Ae(e,{recursive:!0});let E={};for(let C of I.files)E[C.path]=Qo(C.content);for(let C of I.files)Ee(e,C.path);let z=n?.trackedManifest??{};for(let C of I.files)z[C.path]!==E[C.path]&&(await er(e,C),s+=1);for(let C of Object.keys(z))if(E[C]===void 0){let Ge;try{Ge=Ee(e,C)}catch(ve){Yo.warn(Xo,"\u8DF3\u8FC7\u8D8A\u754C\u7684\u65E7 manifest \u6761\u76EE",{projectId:t,path:C,error:ve instanceof Error?ve.message:String(ve)});continue}await qo(Ge,{force:!0}).catch(()=>{}),a+=1}p=E}let u=await(await Se(r,`/api/runner/workspace/${t}/credentials`)).json();await Ae(e,{recursive:!0});let g=await $t(le.join(e,".env"),u.credentials??{}),d={projectId:t,revision:i.revision,syncedAt:new Date().toISOString(),trackedManifest:p};return await Pt(le.join(e,pe),`${JSON.stringify(d,null,2)}
28
- `,"utf8"),{projectId:t,revision:i.revision,action:l,written:s,deleted:a,envUpdated:g}}c(jt,"syncWorkspace");var G="runner-gc";async function _t(r){let t=0,e;try{e=await Te(r,{withFileTypes:!0})}catch{return 0}for(let n of e){let o=L.join(r,n.name);if(!n.isSymbolicLink()){if(n.isDirectory()){t+=await _t(o);continue}t+=await me(o).then(i=>i.size).catch(()=>0)}}return t}c(_t,"dirSize");async function tr(r){let t=L.join(r,"projects"),e;try{e=await Te(t,{withFileTypes:!0})}catch{return[]}let n=[];for(let o of e){if(!o.isDirectory())continue;let i=L.join(t,o.name),s=await me(L.join(i,pe)).then(l=>l.mtimeMs).catch(()=>null),a=await me(i).then(l=>l.mtimeMs).catch(()=>0);n.push({projectId:o.name,dir:i,lastTouchedMs:s??a,sizeBytes:await _t(i)})}return n}c(tr,"scanProjects");async function Ot(r,t){let e=L.join(r,"traces"),n;try{n=await Te(e,{withFileTypes:!0})}catch{return 0}let o=[];for(let a of n){if(!a.isFile())continue;let l=L.join(e,a.name),p=await me(l).catch(()=>null);p&&o.push({full:l,size:p.size,mtimeMs:p.mtimeMs})}let i=o.reduce((a,l)=>a+l.size,0);if(i<=t)return 0;o.sort((a,l)=>a.mtimeMs-l.mtimeMs);let s=0;for(let a of o){if(i<=t)break;await xe(a.full,{force:!0}).catch(()=>{}),i-=a.size,s+=a.size}return s}c(Ot,"pruneTraces");async function Dt(r){let t=(r.now??Date.now)(),e=(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 tr(r.workspaceRoot),a=[],l=0;for(let g of s){if(i.has(g.projectId)){l+=await Ot(g.dir,n);continue}if(t-g.lastTouchedMs>=e){await xe(g.dir,{recursive:!0,force:!0}).catch(d=>{N.warn(G,"\u9879\u76EE\u76EE\u5F55\u56DE\u6536\u5931\u8D25",{projectId:g.projectId,error:d instanceof Error?d.message:String(d)})}),a.push(g.projectId),N.info(G,"\u56DE\u6536\u8FC7\u671F\u9879\u76EE\u76EE\u5F55",{projectId:g.projectId,idleDays:Math.floor((t-g.lastTouchedMs)/864e5)});continue}l+=await Ot(g.dir,n)}let p=s.filter(g=>!a.includes(g.projectId)),m=p.reduce((g,d)=>g+d.sizeBytes,0)-l,u=!1;if(m>o){u=!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:m,maxDiskBytes:o});let g=p.filter(d=>!i.has(d.projectId)).sort((d,v)=>d.lastTouchedMs-v.lastTouchedMs);for(let d of g){if(m<=o)break;await xe(d.dir,{recursive:!0,force:!0}).catch(()=>{}),a.push(d.projectId),m-=d.sizeBytes,N.warn(G,"\u6C34\u4F4D\u56DE\u6536\u9879\u76EE\u76EE\u5F55",{projectId:d.projectId,freedBytes:d.sizeBytes})}m>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:m,maxDiskBytes:o})}return{removedProjects:a,tracesFreedBytes:l,diskPressure:u,totalBytes:Math.max(0,m)}}c(Dt,"runGc");var R="runner-loop",de=class{static{c(this,"RunnerLoop")}options;maxWorkflows;setTimer;clearTimer;doSync;holdings=new Map;pollTimer=null;gcTimer=null;running=!1;claiming=!1;constructor(t){this.options=t,this.maxWorkflows=Math.max(1,Math.floor(t.maxWorkflows??3)),this.setTimer=t.setTimeoutImpl??((e,n)=>setTimeout(e,n)),this.clearTimer=t.clearTimeoutImpl??(e=>clearTimeout(e)),this.doSync=t.syncImpl??jt}get held(){return[...this.holdings.values()].map(t=>({projectId:t.projectId,generation:t.generation,revision:t.revision,engine:t.engine.status}))}get freeSlots(){return Math.max(0,this.maxWorkflows-this.holdings.size)}start(){this.running||(this.running=!0,b.info(R,"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(t=>this.releaseHolding(t,"daemon_shutdown")))}scheduleGc(t){let e=this.options.gcIntervalMs??864e5;!this.running||e<=0||(this.gcTimer&&this.clearTimer(this.gcTimer),this.gcTimer=this.setTimer(()=>{this.gcTimer=null,this.gcOnce().finally(()=>this.scheduleGc(e))},t))}async gcOnce(){try{let t=await(this.options.gcImpl??Dt)({workspaceRoot:this.options.workspaceRoot,activeProjectIds:[...this.holdings.keys()],...this.options.gcOptions??{}});(t.removedProjects.length>0||t.tracesFreedBytes>0)&&b.info(R,"\u672C\u673A\u56DE\u6536\u5B8C\u6210",{removed:t.removedProjects.length,tracesFreedBytes:t.tracesFreedBytes,totalBytes:t.totalBytes})}catch(t){b.warn(R,"\u672C\u673A\u56DE\u6536\u5931\u8D25",{error:$(t)})}}onWakeup(){this.running&&this.claimOnce()}async claimOnce(){if(!this.running||this.claiming)return;this.claiming=!0;let t=this.options.defaultPollMs??1e4;try{let e=this.freeSlots;if(e>0){let n=await this.post("/api/runner/workflows/claim",{capacity:e});typeof n.nextPollAfterMs=="number"&&n.nextPollAfterMs>0&&(t=n.nextPollAfterMs);for(let o of n.grants??[])await this.acceptGrant(o,n.heartbeatIntervalSeconds)}}catch(e){b.warn(R,"claim \u5931\u8D25\uFF08\u9000\u907F\u540E\u91CD\u8BD5\uFF09",{error:$(e)}),t=Math.max(t,5e3)}finally{this.claiming=!1,this.scheduleNextPoll(t)}}scheduleNextPoll(t){this.running&&(this.pollTimer&&this.clearTimer(this.pollTimer),this.pollTimer=this.setTimer(()=>{this.pollTimer=null,this.claimOnce()},t))}async acceptGrant(t,e){if(this.holdings.has(t.projectId))return;let n=Lt.join(this.options.workspaceRoot,"projects",t.projectId);b.info(R,"\u8BA4\u9886\u9879\u76EE",{projectId:t.projectId,generation:t.generation,workspaceDir:n});let o;try{o=await this.doSync(this.clientConfig(),t.projectId,n)}catch(l){b.error(R,"\u5DE5\u4F5C\u533A\u540C\u6B65\u5931\u8D25\uFF0C\u4EA4\u8FD8\u79DF\u7EA6",{projectId:t.projectId,error:$(l)}),await this.postSafe(`/api/runner/workflows/${t.projectId}/release`,{generation:t.generation,reason:"workspace_sync_failed"});return}let i=(this.options.createSupervisor??nr)({projectId:t.projectId,workspaceDir:n,cliPath:this.options.cliPath,onRunEvent:c(l=>this.handleRunEvent(t.projectId,l),"onRunEvent"),onCrashLoop:c(()=>{this.releaseHolding(t.projectId,"engine_crash_loop")},"onCrashLoop")}),s=this.options.sendRunEvents?new ce({projectId:t.projectId,spoolDir:n,send:c(l=>this.options.sendRunEvents(t.projectId,l),"send")}):null;s?.start();let a={projectId:t.projectId,generation:t.generation,revision:o.revision,engine:i,spool:s,heartbeatTimer:null,busy:!1};this.holdings.set(t.projectId,a),i.start(),this.scheduleHeartbeat(a,(e??15)*1e3)}handleRunEvent(t,e){this.holdings.get(t)?.spool?.append(e),this.options.onRunEvent?.(t,e)}scheduleHeartbeat(t,e){this.running&&(t.heartbeatTimer&&this.clearTimer(t.heartbeatTimer),t.heartbeatTimer=this.setTimer(()=>{t.heartbeatTimer=null,this.heartbeatOnce(t)},e))}async heartbeatOnce(t){if(!this.running||t.busy||!this.holdings.has(t.projectId))return;let e=this.options.defaultHeartbeatMs??15e3;try{let n=await this.post(`/api/runner/workflows/${t.projectId}/heartbeat`,{generation:t.generation,workspaceRevision:t.revision,engineStatus:t.engine.status,...t.spool?{lastEventSeq:t.spool.lastSeq}:{}}),o=typeof n.nextIntervalSeconds=="number"&&n.nextIntervalSeconds>0?n.nextIntervalSeconds*1e3:e;if(t.spool&&typeof n.lastEventSeq=="number"&&t.spool.replayFrom(n.lastEventSeq),n.action==="stop"){b.info(R,"\u5FC3\u8DF3\u4E0B\u53D1 stop\uFF0C\u505C\u6B62\u5F15\u64CE",{projectId:t.projectId}),await this.releaseHolding(t.projectId,"heartbeat_stop");return}if(n.action==="resync"){await this.resyncHolding(t)&&this.scheduleHeartbeat(t,o);return}t.engine.markHealthy(),this.scheduleHeartbeat(t,o)}catch(n){b.warn(R,"\u5FC3\u8DF3\u5931\u8D25\uFF08\u4FDD\u6301\u5F15\u64CE\u8FD0\u884C\uFF0C\u7B49\u5F85\u6062\u590D\u6216\u79DF\u7EA6\u8FC7\u671F\uFF09",{projectId:t.projectId,error:$(n)}),this.scheduleHeartbeat(t,Math.min(e,5e3))}}async resyncHolding(t){if(t.busy)return!0;t.busy=!0;let e=Lt.join(this.options.workspaceRoot,"projects",t.projectId);try{b.info(R,"\u5DE5\u4F5C\u533A\u9700\u91CD\u540C\u6B65\uFF0C\u91CD\u542F\u5F15\u64CE",{projectId:t.projectId}),await t.engine.stop();let n=await this.doSync(this.clientConfig(),t.projectId,e);t.revision=n.revision,t.engine.start()}catch(n){return b.error(R,"\u91CD\u540C\u6B65\u5931\u8D25\uFF0C\u4EA4\u8FD8\u79DF\u7EA6",{projectId:t.projectId,error:$(n)}),t.busy=!1,await this.releaseHolding(t.projectId,"resync_failed"),!1}return t.busy=!1,!0}async releaseHolding(t,e){let n=this.holdings.get(t);n&&(this.holdings.delete(t),n.heartbeatTimer&&(this.clearTimer(n.heartbeatTimer),n.heartbeatTimer=null),await n.engine.stop().catch(o=>{b.warn(R,"\u505C\u6B62\u5F15\u64CE\u5F02\u5E38",{projectId:t,error:$(o)})}),await n.spool?.stop().catch(()=>{}),await this.postSafe(`/api/runner/workflows/${t}/release`,{generation:n.generation,reason:e}),b.info(R,"\u5DF2\u8BA9\u51FA\u79DF\u7EA6",{projectId:t,reason:e}),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(t,e){let o=await(this.options.fetchImpl??fetch)(`${this.options.gatewayUrl.replace(/\/+$/,"")}${t}`,{method:"POST",headers:{authorization:`Bearer ${this.options.machineKey}`,"content-type":"application/json"},body:JSON.stringify(e??{})});if(!o.ok){let i=await o.text().catch(()=>"");throw new Error(`runner API ${t} \u5931\u8D25: HTTP ${o.status} ${i.slice(0,200)}`)}return await o.json()}async postSafe(t,e){try{await this.post(t,e)}catch(n){b.warn(R,"\u6536\u5C3E\u8BF7\u6C42\u5931\u8D25\uFF08\u79DF\u7EA6\u5C06\u7531\u670D\u52A1\u7AEF\u8FC7\u671F\u56DE\u6536\uFF09",{pathname:t,error:$(n)})}}};function nr(r){return new ie({projectId:r.projectId,workspaceDir:r.workspaceDir,cliPath:r.cliPath,...r.onRunEvent?{onRunEvent:r.onRunEvent}:{},...r.onCrashLoop?{onCrashLoop:c(()=>r.onCrashLoop(),"onCrashLoop")}:{}})}c(nr,"defaultSupervisorFactory");function $(r){return r instanceof Error?r.message:String(r)}c($,"describeError");import{spawn as rr}from"child_process";import{existsSync as ir}from"fs";import J from"path";import{fileURLToPath as sr}from"url";import{appendFileSync as ma,statSync as da,renameSync as ua,mkdirSync as ga,existsSync as fa}from"fs";import or from"path";var ya=10*1024*1024;function H(r){return or.join(X(r),"daemon.log")}c(H,"logFilePath");var ue=J.dirname(sr(import.meta.url));function $e(){let r=[J.resolve(ue,"..","..","bin","aitable-workflow.mjs"),J.resolve(ue,"..","bin","aitable-workflow.mjs"),J.resolve(ue,"..","..","dist","cli.js"),J.resolve(ue,"cli.js")];return r.find(t=>ir(t))??r[0]}c($e,"resolveDaemonEntry");var ar=$e();async function V(r){await qe(r.agentId);let t=["relay"];r.serverUrl&&t.push("--server-url",r.serverUrl),r.token&&t.push("--token",r.token),r.key&&t.push("--key",r.key),r.name&&t.push("--name",r.name),r.workspaceRoot&&t.push("--workspace-root",r.workspaceRoot),r.machineId&&t.push("--machine-id",r.machineId),r.maxTasks&&t.push("--max-tasks",String(r.maxTasks));let e=await import("fs").then(s=>{let a=H(r.agentId);return s.openSync(a,"a")}),n=rr(process.execPath,[ar,...t],{detached:!0,stdio:["ignore",e,e],env:{...process.env}});try{let{closeSync:s}=await import("fs");s(e)}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(V,"startDaemon");async function ge(r,t=5e3){let e=await ke(r);if(e===null||!W(e))return await Q(r),!1;try{process.kill(e,"SIGTERM")}catch{return await Q(r),!1}let n=Date.now()+t;for(;Date.now()<n&&W(e);)await new Promise(o=>setTimeout(o,200));if(W(e))try{process.kill(e,"SIGKILL")}catch{}return await Q(r),!0}c(ge,"stopDaemon");async function q(r){let t=await ke(r),e=t!==null&&W(t),n=null;if(e&&t!==null)try{let{readFile:o}=await import("fs/promises"),i=await o(`/proc/${t}/stat`,"utf8"),s=parseInt(i.split(" ")[21]??"0",10),a=await o("/proc/uptime","utf8"),m=parseFloat(a.split(" ")[0]??"0")-s/100;n=Math.round(m*1e3)}catch{}return{agentId:r,running:e,pid:e?t:null,uptimeMs:n,logFile:H(r)}}c(q,"getDaemonStatus");function wr(r){return r.replace(/\/+$/,"").replace(/^ws/,"http")}c(wr,"toHttpBase");var y="relay:daemon",Ft=["aitable"],yr="dws";function vr(r,t=Ft){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 e=r[0];return e.startsWith("-")?{ok:!1,reason:"first dws arg must be a subcommand, not a flag"}:t.length>0&&!t.includes(e)?{ok:!1,reason:`dws command "${e}" is not allowed`}:{ok:!0}}c(vr,"validateDwsArgs");function kr(r){return fr(r,["--version"],hr({timeoutMs:5e3})).ok}c(kr,"detectDwsAvailable");var Pe=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(t,e={}){this.config={...t,dwsBin:t.dwsBin??yr},this.machineId=t.machineId,this.allowedDwsCommands=t.allowedDwsCommands??Ft,this.runAgent=e.runAgent??dr,this.createDwsClient=e.createDwsClient??((o,i)=>new ur({bin:o,timeoutMs:i})),this.detectAgents=e.detectAgents??(()=>mr()),this.detectDws=e.detectDws??(o=>kr(o)),this.hostname=e.hostname??(()=>B.hostname()),this.osString=e.osString??(()=>`${B.platform()} ${B.arch()}`),this.onPermanentReject=e.onPermanentReject,this.artifactUploader=e.artifactUploader??St,this.grantTimeoutMs=e.grantTimeoutMs??3e4,this.maxTasks=Math.max(1,Math.floor(t.maxTasks??1));let n=e.createConnection??(o=>new re(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(e)}buildRunnerLoop(t){let e=Math.max(0,Math.floor(this.config.maxWorkflows??3));if(e===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:wr(this.config.serverUrl),machineKey:n,workspaceRoot:this.config.workspaceRoot,cliPath:$e(),maxWorkflows:e,sendRunEvents:c((i,s)=>this.sendRunEvents(i,s),"sendRunEvents")};return(t.createRunnerLoop??(i=>new de(i)))(o)}sendRunEvents(t,e){e.length!==0&&this.conn.send({type:"run:events",projectId:t,entries:e})}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(t=>{w.warn(y,"runner loop \u505C\u6B62\u5F02\u5E38",{error:t instanceof Error?t.message:String(t)})}):Promise.resolve()}buildReady(){let e={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&&(e.machineId=this.machineId),this.config.name&&(e.name=this.config.name),this.config.displayName&&(e.displayName=this.config.displayName),this.config.description&&(e.description=this.config.description),this.maxTasks>1&&(e.maxTasks=this.maxTasks),e}handleOpen(){let t=this.buildReady();w.info(y,"connected; sending ready",{runtimes:t.runtimes,hasDws:t.hasDws}),this.conn.send(t)}handlePermanentReject(t){w.error(y,"permanently rejected by gateway",{...t}),this.onPermanentReject?.(t)}handleMessage(t){switch(t.type){case"run:agent":this.enqueueTask(()=>this.handleRunAgent(t));break;case"run:dws":this.enqueueTask(()=>this.handleRunDws(t));break;case"upload:grant":this.resolveGrant(t);break;case"wf:available":this.runnerLoop?.onWakeup();break;case"ready:ack":t.machineId&&(this.machineId=t.machineId,w.info(y,"machine id assigned",{machineId:t.machineId}));break;default:break}}enqueueTask(t){let e=c(()=>{this.inflight+=1,t().finally(()=>{this.inflight-=1;let n=this.taskQueue.shift();n&&n()})},"exec");this.inflight<this.maxTasks?e():this.taskQueue.push(e)}async handleRunAgent(t){let{requestId:e}=t;w.info(y,"run:agent received",{requestId:e,projectId:t.projectId,agent:t.agent});try{let n=this.resolveWorkDir(t.projectId,t.workDir);await cr(n,{recursive:!0});let o=this.rewritePromptWorkDir(t.prompt,t.workDir,n),i={agent:t.agent,workDir:n,onEvent:c(l=>this.conn.send({type:"event",requestId:e,event:l}),"onEvent")};t.sessionId&&(i.sessionId=t.sessionId),t.permissionMode&&(i.adapterOptions={permissionMode:t.permissionMode}),t.timeoutMs!==void 0?i.timeoutMs=t.timeoutMs:this.config.agentTimeoutMs!=null&&(i.timeoutMs=this.config.agentTimeoutMs);let s=await this.runAgent(o,i),a;try{a=await this.collectAndUploadArtifacts(e,t.projectId,n)}catch(l){let p=l instanceof Error?l.message:String(l);w.error(y,"artifact upload failed",{requestId:e,error:p}),this.conn.send({type:"error",requestId:e,code:"artifact_upload_failed",message:p});return}this.conn.send({type:"result",requestId:e,ok:!0,response:s.response,sessionId:s.sessionId,...a?{artifacts:a}:{}}),w.info(y,"run:agent done",{requestId:e,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:e,error:o}),this.conn.send({type:"error",requestId:e,code:"agent_failed",message:o})}}async collectAndUploadArtifacts(t,e,n){let o=await At(n);if(o.length===0)return;this.conn.send({type:"upload:request",requestId:t,projectId:e,files:o.map(a=>({path:a.relPath,size:a.size,sha256:a.sha256}))});let i=await this.awaitGrant(t);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:t,rejected:(i.rejected??[]).length});return}let s=[];for(let a of i.grants){let l=o.find(m=>m.relPath===a.path);if(!l)continue;let p=await lr(l.absPath);await this.artifactUploader.upload(a.url,p,a.headers),s.push({path:a.path,key:a.key,sha256:l.sha256,size:l.size})}return{store:"oss",files:s}}awaitGrant(t){return new Promise(e=>{let n=setTimeout(()=>{this.pendingGrants.delete(t),e(void 0)},this.grantTimeoutMs);n.unref?.(),this.pendingGrants.set(t,o=>{clearTimeout(n),e(o)})})}resolveGrant(t){let e=this.pendingGrants.get(t.requestId);e&&(this.pendingGrants.delete(t.requestId),e(t))}async handleRunDws(t){let{requestId:e}=t,n=vr(t.args,this.allowedDwsCommands);if(!n.ok){w.warn(y,"run:dws rejected",{requestId:e,reason:n.reason}),this.conn.send({type:"error",requestId:e,code:"dws_rejected",message:n.reason});return}w.info(y,"run:dws received",{requestId:e,command:t.args[0]});try{let i=await this.createDwsClient(this.config.dwsBin,t.timeoutMs).runJson(t.args,t.timeoutMs!=null?{timeoutMs:t.timeoutMs}:void 0);this.conn.send({type:"result",requestId:e,ok:!0,response:JSON.stringify(i)}),w.info(y,"run:dws done",{requestId:e})}catch(o){let i=o instanceof Error?o.message:String(o);w.error(y,"run:dws failed",{requestId:e,error:i}),this.conn.send({type:"error",requestId:e,code:"dws_failed",message:i})}}resolveWorkDir(t,e){if(e&&e.trim()!=="")if(M.isAbsolute(e))w.warn(y,"\u5FFD\u7565\u670D\u52A1\u7AEF\u4E0B\u53D1\u7684\u7EDD\u5BF9\u8DEF\u5F84 workDir\uFF0C\u56DE\u9000\u5230 workspaceRoot/projectId",{workDir:e,projectId:t});else return Mt(this.config.workspaceRoot,e,{allowRoot:!1});return Mt(this.config.workspaceRoot,Bt(t,{label:"projectId"}),{allowRoot:!1})}rewritePromptWorkDir(t,e,n){let o=e?.trim();return!o||!M.isAbsolute(o)||o===n?t:t.split(o).join(n)}};function je(r,t){let e,n=r?.trim();if(n)e=M.isAbsolute(n)?M.resolve(n):M.resolve(B.homedir(),n);else{let o=t?.trim()?t.trim():"default";e=M.join(B.homedir(),".aitable-workflow","workspaces",Bt(o,{label:"agentId"}))}return pr(e,{recursive:!0}),e}c(je,"resolveWorkspaceRoot");function br(r,t=process.env){let e=r.serverUrl??t.AITABLE_RELAY_SERVER_URL,n=r.key??t.AITABLE_RELAY_BOOTSTRAP_KEY,o=r.token??t.AITABLE_RELAY_TOKEN,i=r.workspaceRoot??t.AITABLE_RELAY_WORKSPACE_ROOT,s=r.machineId??t.AITABLE_RELAY_MACHINE_ID,a=r.name??t.AITABLE_RELAY_NAME,l=r.desc??t.AITABLE_RELAY_DESC,p=r.maxTasks??t.AITABLE_RELAY_MAX_TASKS,m=r.maxWorkflows??t.AITABLE_RELAY_MAX_WORKFLOWS,u=[];if(e||u.push("--server-url (\u6216 AITABLE_RELAY_SERVER_URL)"),!n&&!o&&u.push("--key/--token (\u6216 AITABLE_RELAY_BOOTSTRAP_KEY/AITABLE_RELAY_TOKEN)"),u.length>0)throw new Error(`relay \u7F3A\u5C11\u5FC5\u8981\u53C2\u6570: ${u.join(", ")}
29
- \u{1F4A1} \u63D0\u793A: \u4F7F\u7528 \`aitable-workflow connect\` \u6CE8\u518C\u540E\u53EF\u7701\u7565\u8FD9\u4E9B\u53C2\u6570`);let g=a??B.hostname()??"default",d={serverUrl:e,workspaceRoot:je(i,g)};if(o?d.token=o:n&&(d.key=n),s&&(d.machineId=s),a&&(d.name=a,d.displayName=a),l&&(d.description=l),p!=null&&p!==""){let v=Math.floor(Number(p));Number.isFinite(v)&&v>=1&&(d.maxTasks=v)}if(m!=null&&m!==""){let v=Math.floor(Number(m));Number.isFinite(v)&&v>=0&&(d.maxWorkflows=v)}return d}c(br,"resolveRelayCliConfig");async function F(r,t=process.env){let e=null;try{e=await gr()}catch{e=null}let n={serverUrl:r.serverUrl??t.AITABLE_RELAY_SERVER_URL??e?.serverUrl,key:r.key??t.AITABLE_RELAY_BOOTSTRAP_KEY??e?.key,token:r.token??t.AITABLE_RELAY_TOKEN??e?.token,name:r.name??t.AITABLE_RELAY_NAME??e?.name,desc:r.desc??t.AITABLE_RELAY_DESC,workspaceRoot:r.workspaceRoot??t.AITABLE_RELAY_WORKSPACE_ROOT??e?.workspaceRoot,machineId:r.machineId??t.AITABLE_RELAY_MACHINE_ID??e?.machineId,maxTasks:r.maxTasks??t.AITABLE_RELAY_MAX_TASKS,maxWorkflows:r.maxWorkflows??t.AITABLE_RELAY_MAX_WORKFLOWS};return br(n,t)}c(F,"resolveDaemonConfig");async function fe(r){let t=await F(r),e=new Pe(t,{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,e.stop().catch(()=>{}).finally(()=>process.exit(0))},"shutdown");return process.on("SIGINT",o),process.on("SIGTERM",o),e.start(),e}c(fe,"runRelayDaemon");import{readFile as Rr,writeFile as Na,mkdir as Ga}from"fs/promises";import Cr from"path";var Ut={connectionState:"disconnected",lastHeartbeatAt:null,machineId:null,serverUrl:"",runningTasks:0,queuedTasks:0,lastDisconnectReason:null,updatedAt:new Date().toISOString()};function Ir(r){return Cr.join(X(r),"state.json")}c(Ir,"stateFilePath");async function he(r){try{let t=await Rr(Ir(r),"utf8");return{...Ut,...JSON.parse(t)}}catch{return{...Ut}}}c(he,"readState");import{execSync as K}from"child_process";import{writeFile as Sr,rm as Ar,mkdir as Er,access as xr}from"fs/promises";import A from"path";import Wt from"os";import{assertPortableId as Tr,readCredentials as $r}from"aitable-workflow-core";var Pr="com.alibaba.aitable-workflow.daemon",Oe="\u8BF7\u5148\u5168\u5C40\u5B89\u88C5\uFF1Anpm i -g @ali/aitable-workflow";function Y(r){return`${Pr}.${Tr(r,{label:"agentId"})}`}c(Y,"plistLabel");function _e(r){return A.join(Wt.homedir(),"Library","LaunchAgents",`${Y(r)}.plist`)}c(_e,"plistPath");function P(){return process.platform==="darwin"}c(P,"isMacOS");function Nt(){try{return K("which aitable-workflow",{encoding:"utf8"}).trim()||null}catch{return null}}c(Nt,"resolveGlobalCliEntry");function Gt(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
30
- \u{1F4A1} ${Oe}`);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}
31
- \u{1F4A1} ${Oe}`);if(!A.isAbsolute(r))throw new Error(`CLI \u5165\u53E3\u4E0D\u662F\u7A33\u5B9A\u7684\u5168\u5C40\u7EDD\u5BF9\u8DEF\u5F84\uFF1A${r}
32
- \u{1F4A1} ${Oe}`)}c(Gt,"assertStableCliEntry");async function jr(r){let t={};t.AITABLE_RELAY_NAME=r;let e;try{let n=await $r();e=n.agents.find(o=>o.name===r)??n.agents.find(o=>o.name===n.activeAgent)??void 0}catch{e=void 0}return e&&(e.serverUrl&&(t.AITABLE_RELAY_SERVER_URL=e.serverUrl),e.token&&(t.AITABLE_RELAY_TOKEN=e.token),e.workspaceRoot&&(t.AITABLE_RELAY_WORKSPACE_ROOT=e.workspaceRoot)),t}c(jr,"buildRelayEnv");function Or(r,t){let e=Y(r),n=t?.cliEntry??Nt();Gt(n);let o=["relay"];t?.maxTasks&&o.push("--max-tasks",String(t.maxTasks));let i=A.join(Wt.homedir(),".aitable-workflow","daemons",r),s=A.join(i,"launchd.log"),a=A.join(i,"launchd.err.log"),l=[n,...o].map(u=>` <string>${U(u)}</string>`).join(`
33
- `),p={PATH:process.env.PATH??"/usr/local/bin:/usr/bin:/bin",...t?.relayEnv??{}},m=Object.entries(p).map(([u,g])=>` <key>${U(u)}</key>
34
- <string>${U(g)}</string>`).join(`
507
+ ${s?`
508
+ ${s}`:""}`}c(vo,"mergeEnvContent");function wo(o){return o===""||/[\s#'"`\\]/.test(o)?`"${o.replace(/\\/g,"\\\\").replace(/"/g,'\\"').replace(/\n/g,"\\n")}"`:o}c(wo,"quoteEnvValue");async function Kt(o,e){let t=await fo(o,"utf8").catch(()=>""),n=vo(t,e);if(n===t||n===""&&t==="")return!1;let r=`${o}.aitable-sync-tmp`;return await ho(r,n,{encoding:"utf8",mode:384}),await mo(r,384).catch(()=>{}),await go(r,o),!0}c(Kt,"mergeEnvFile");var Eo="workspace-sync",fe=".workspace-meta.json";function So(o){return yo("sha256").update(o).digest("hex")}c(So,"sha256Hex");async function Me(o,e){let n=await(o.fetchImpl??fetch)(`${o.gatewayUrl.replace(/\/+$/,"")}${e}`,{headers:{authorization:`Bearer ${o.machineKey}`}});if(!n.ok){let r=await n.text().catch(()=>"");throw new Error(`runner API ${e} \u5931\u8D25: HTTP ${n.status} ${r.slice(0,200)}`)}return n}c(Me,"apiGet");async function Io(o){try{let e=await ko(me.join(o,fe),"utf8"),t=JSON.parse(e);return t&&typeof t.projectId=="string"?t:null}catch{return null}}c(Io,"readWorkspaceMeta");function Be(o,e){return Ao(o,e,{allowRoot:!1})}c(Be,"resolveTracked");async function To(o,e){let t=Be(o,e.path);await De(me.dirname(t),{recursive:!0});let n=`${t}.aitable-sync-tmp`;await Xt(n,e.content,"utf8"),await bo(n,t)}c(To,"writeTracked");async function Zt(o,e,t){let n=await Io(t);if(n&&n.projectId!==e)throw new Error(`\u5DE5\u4F5C\u533A\u76EE\u5F55\u5F52\u5C5E\u4E0D\u7B26: \u76EE\u5F55\u8BB0\u5F55 projectId=${n.projectId}\uFF0C\u8BF7\u6C42\u540C\u6B65 ${e}\uFF08${t}\uFF09`);let s=await(await Me(o,`/api/runner/workspace/${e}`)).json(),i=0,a=0,l="up-to-date",d=n?.trackedManifest??{};if(!n||n.revision!==s.revision){l="synced";let R=await Me(o,`/api/runner/workspace/${e}/bundle`),S=Co(Buffer.from(await R.arrayBuffer()));if(S.projectId!==e)throw new Error(`\u5FEB\u7167\u5305\u5F52\u5C5E\u4E0D\u7B26: \u5305\u5185 projectId=${S.projectId}\uFF0C\u671F\u671B ${e}`);S.revision!==s.revision&&(s.revision=S.revision),await De(t,{recursive:!0});let E={};for(let g of S.files)E[g.path]=So(g.content);for(let g of S.files)Be(t,g.path);let H=n?.trackedManifest??{};for(let g of S.files)H[g.path]!==E[g.path]&&(await To(t,g),i+=1);for(let g of Object.keys(H))if(E[g]===void 0){let h;try{h=Be(t,g)}catch(Ee){xo.warn(Eo,"\u8DF3\u8FC7\u8D8A\u754C\u7684\u65E7 manifest \u6761\u76EE",{projectId:e,path:g,error:Ee instanceof Error?Ee.message:String(Ee)});continue}await Ro(h,{force:!0}).catch(()=>{}),a+=1}d=E}let u=await(await Me(o,`/api/runner/workspace/${e}/credentials`)).json();await De(t,{recursive:!0});let m=await Kt(me.join(t,".env"),u.credentials??{}),f={projectId:e,revision:s.revision,syncedAt:new Date().toISOString(),trackedManifest:d};return await Xt(me.join(t,fe),`${JSON.stringify(f,null,2)}
509
+ `,"utf8"),{projectId:e,revision:s.revision,action:l,written:i,deleted:a,envUpdated:m}}c(Zt,"syncWorkspace");var z="runner-gc";async function en(o){let e=0,t;try{t=await Fe(o,{withFileTypes:!0})}catch{return 0}for(let n of t){let r=N.join(o,n.name);if(!n.isSymbolicLink()){if(n.isDirectory()){e+=await en(r);continue}e+=await ge(r).then(s=>s.size).catch(()=>0)}}return e}c(en,"dirSize");async function _o(o){let e=N.join(o,"projects"),t;try{t=await Fe(e,{withFileTypes:!0})}catch{return[]}let n=[];for(let r of t){if(!r.isDirectory())continue;let s=N.join(e,r.name),i=await ge(N.join(s,fe)).then(l=>l.mtimeMs).catch(()=>null),a=await ge(s).then(l=>l.mtimeMs).catch(()=>0);n.push({projectId:r.name,dir:s,lastTouchedMs:i??a,sizeBytes:await en(s)})}return n}c(_o,"scanProjects");async function Qt(o,e){let t=N.join(o,"traces"),n;try{n=await Fe(t,{withFileTypes:!0})}catch{return 0}let r=[];for(let a of n){if(!a.isFile())continue;let l=N.join(t,a.name),d=await ge(l).catch(()=>null);d&&r.push({full:l,size:d.size,mtimeMs:d.mtimeMs})}let s=r.reduce((a,l)=>a+l.size,0);if(s<=e)return 0;r.sort((a,l)=>a.mtimeMs-l.mtimeMs);let i=0;for(let a of r){if(s<=e)break;await He(a.full,{force:!0}).catch(()=>{}),s-=a.size,i+=a.size}return i}c(Qt,"pruneTraces");async function tn(o){let e=(o.now??Date.now)(),t=(o.ttlDays??14)*24*60*60*1e3,n=o.tracesMaxBytes??500*1024*1024,r=o.maxDiskBytes??20*1024*1024*1024,s=new Set(o.activeProjectIds),i=await _o(o.workspaceRoot),a=[],l=0;for(let m of i){if(s.has(m.projectId)){l+=await Qt(m.dir,n);continue}if(e-m.lastTouchedMs>=t){await He(m.dir,{recursive:!0,force:!0}).catch(f=>{q.warn(z,"\u9879\u76EE\u76EE\u5F55\u56DE\u6536\u5931\u8D25",{projectId:m.projectId,error:f instanceof Error?f.message:String(f)})}),a.push(m.projectId),q.info(z,"\u56DE\u6536\u8FC7\u671F\u9879\u76EE\u76EE\u5F55",{projectId:m.projectId,idleDays:Math.floor((e-m.lastTouchedMs)/864e5)});continue}l+=await Qt(m.dir,n)}let d=i.filter(m=>!a.includes(m.projectId)),p=d.reduce((m,f)=>m+f.sizeBytes,0)-l,u=!1;if(p>r){u=!0,q.warn(z,"\u5DE5\u4F5C\u533A\u8D85\u78C1\u76D8\u6C34\u4F4D\uFF0C\u5F00\u59CB\u56DE\u6536\u6700\u4E45\u672A\u8BA4\u9886\u9879\u76EE",{totalBytes:p,maxDiskBytes:r});let m=d.filter(f=>!s.has(f.projectId)).sort((f,R)=>f.lastTouchedMs-R.lastTouchedMs);for(let f of m){if(p<=r)break;await He(f.dir,{recursive:!0,force:!0}).catch(()=>{}),a.push(f.projectId),p-=f.sizeBytes,q.warn(z,"\u6C34\u4F4D\u56DE\u6536\u9879\u76EE\u76EE\u5F55",{projectId:f.projectId,freedBytes:f.sizeBytes})}p>r&&q.error(z,"\u56DE\u6536\u540E\u4ECD\u8D85\u78C1\u76D8\u6C34\u4F4D\uFF08\u6D3B\u8DC3\u9879\u76EE\u5360\u7528\uFF09\uFF0C\u9700\u4EBA\u5DE5\u4ECB\u5165",{totalBytes:p,maxDiskBytes:r})}return{removedProjects:a,tracesFreedBytes:l,diskPressure:u,totalBytes:Math.max(0,p)}}c(tn,"runGc");var A="runner-loop";function Po(o){return!(typeof o=="object"&&o!==null&&o.type==="run.agent_event")}c(Po,"shouldUplinkRunEvent");var he=class{static{c(this,"RunnerLoop")}options;maxWorkflows;setTimer;clearTimer;doSync;holdings=new Map;pollTimer=null;gcTimer=null;running=!1;claiming=!1;constructor(e){this.options=e,this.maxWorkflows=Math.max(1,Math.floor(e.maxWorkflows??3)),this.setTimer=e.setTimeoutImpl??((t,n)=>setTimeout(t,n)),this.clearTimer=e.clearTimeoutImpl??(t=>clearTimeout(t)),this.doSync=e.syncImpl??Zt}get held(){return[...this.holdings.values()].map(e=>({projectId:e.projectId,generation:e.generation,revision:e.revision,engine:e.engine.status}))}get freeSlots(){return Math.max(0,this.maxWorkflows-this.holdings.size)}start(){this.running||(this.running=!0,x.info(A,"runner loop \u542F\u52A8",{maxWorkflows:this.maxWorkflows,workspaceRoot:this.options.workspaceRoot}),this.claimOnce(),this.scheduleGc(0))}async stop(){this.running=!1,this.pollTimer&&(this.clearTimer(this.pollTimer),this.pollTimer=null),this.gcTimer&&(this.clearTimer(this.gcTimer),this.gcTimer=null),await Promise.all([...this.holdings.keys()].map(e=>this.releaseHolding(e,"daemon_shutdown")))}scheduleGc(e){let t=this.options.gcIntervalMs??864e5;!this.running||t<=0||(this.gcTimer&&this.clearTimer(this.gcTimer),this.gcTimer=this.setTimer(()=>{this.gcTimer=null,this.gcOnce().finally(()=>this.scheduleGc(t))},e))}async gcOnce(){try{let e=await(this.options.gcImpl??tn)({workspaceRoot:this.options.workspaceRoot,activeProjectIds:[...this.holdings.keys()],...this.options.gcOptions??{}});(e.removedProjects.length>0||e.tracesFreedBytes>0)&&x.info(A,"\u672C\u673A\u56DE\u6536\u5B8C\u6210",{removed:e.removedProjects.length,tracesFreedBytes:e.tracesFreedBytes,totalBytes:e.totalBytes})}catch(e){x.warn(A,"\u672C\u673A\u56DE\u6536\u5931\u8D25",{error:j(e)})}}onWakeup(){this.running&&this.claimOnce()}async claimOnce(){if(!this.running||this.claiming)return;this.claiming=!0;let e=this.options.defaultPollMs??1e4;try{let t=this.freeSlots;if(t>0){let n=await this.post("/api/runner/workflows/claim",{capacity:t});typeof n.nextPollAfterMs=="number"&&n.nextPollAfterMs>0&&(e=n.nextPollAfterMs);for(let r of n.grants??[])await this.acceptGrant(r,n.heartbeatIntervalSeconds)}}catch(t){x.warn(A,"claim \u5931\u8D25\uFF08\u9000\u907F\u540E\u91CD\u8BD5\uFF09",{error:j(t)}),e=Math.max(e,5e3)}finally{this.claiming=!1,this.scheduleNextPoll(e)}}scheduleNextPoll(e){this.running&&(this.pollTimer&&this.clearTimer(this.pollTimer),this.pollTimer=this.setTimer(()=>{this.pollTimer=null,this.claimOnce()},e))}async acceptGrant(e,t){if(this.holdings.has(e.projectId))return;let n=nn.join(this.options.workspaceRoot,"projects",e.projectId);x.info(A,"\u8BA4\u9886\u9879\u76EE",{projectId:e.projectId,generation:e.generation,workspaceDir:n});let r;try{r=await this.doSync(this.clientConfig(),e.projectId,n)}catch(l){x.error(A,"\u5DE5\u4F5C\u533A\u540C\u6B65\u5931\u8D25\uFF0C\u4EA4\u8FD8\u79DF\u7EA6",{projectId:e.projectId,error:j(l)}),await this.postSafe(`/api/runner/workflows/${e.projectId}/release`,{generation:e.generation,reason:"workspace_sync_failed"});return}let s=(this.options.createSupervisor??$o)({projectId:e.projectId,workspaceDir:n,cliPath:this.options.cliPath,onRunEvent:c(l=>this.handleRunEvent(e.projectId,l),"onRunEvent"),onCrashLoop:c(()=>{this.releaseHolding(e.projectId,"engine_crash_loop")},"onCrashLoop")}),i=this.options.sendRunEvents?new ue({projectId:e.projectId,spoolDir:n,send:c(l=>this.options.sendRunEvents(e.projectId,l),"send")}):null;i?.start();let a={projectId:e.projectId,generation:e.generation,revision:r.revision,engine:s,spool:i,heartbeatTimer:null,busy:!1};this.holdings.set(e.projectId,a),s.start(),this.scheduleHeartbeat(a,(t??15)*1e3)}handleRunEvent(e,t){Po(t)&&this.holdings.get(e)?.spool?.append(t),this.options.onRunEvent?.(e,t)}scheduleHeartbeat(e,t){this.running&&(e.heartbeatTimer&&this.clearTimer(e.heartbeatTimer),e.heartbeatTimer=this.setTimer(()=>{e.heartbeatTimer=null,this.heartbeatOnce(e)},t))}async heartbeatOnce(e){if(!this.running||e.busy||!this.holdings.has(e.projectId))return;let t=this.options.defaultHeartbeatMs??15e3;try{let n=await this.post(`/api/runner/workflows/${e.projectId}/heartbeat`,{generation:e.generation,workspaceRevision:e.revision,engineStatus:e.engine.status,...e.spool?{lastEventSeq:e.spool.lastSeq}:{}}),r=typeof n.nextIntervalSeconds=="number"&&n.nextIntervalSeconds>0?n.nextIntervalSeconds*1e3:t;if(e.spool&&typeof n.lastEventSeq=="number"&&e.spool.replayFrom(n.lastEventSeq),n.action==="stop"){x.info(A,"\u5FC3\u8DF3\u4E0B\u53D1 stop\uFF0C\u505C\u6B62\u5F15\u64CE",{projectId:e.projectId}),await this.releaseHolding(e.projectId,"heartbeat_stop");return}if(n.action==="resync"){await this.resyncHolding(e)&&this.scheduleHeartbeat(e,r);return}e.engine.markHealthy(),this.scheduleHeartbeat(e,r)}catch(n){x.warn(A,"\u5FC3\u8DF3\u5931\u8D25\uFF08\u4FDD\u6301\u5F15\u64CE\u8FD0\u884C\uFF0C\u7B49\u5F85\u6062\u590D\u6216\u79DF\u7EA6\u8FC7\u671F\uFF09",{projectId:e.projectId,error:j(n)}),this.scheduleHeartbeat(e,Math.min(t,5e3))}}async resyncHolding(e){if(e.busy)return!0;e.busy=!0;let t=nn.join(this.options.workspaceRoot,"projects",e.projectId);try{x.info(A,"\u5DE5\u4F5C\u533A\u9700\u91CD\u540C\u6B65\uFF0C\u91CD\u542F\u5F15\u64CE",{projectId:e.projectId}),await e.engine.stop();let n=await this.doSync(this.clientConfig(),e.projectId,t);e.revision=n.revision,e.engine.start()}catch(n){return x.error(A,"\u91CD\u540C\u6B65\u5931\u8D25\uFF0C\u4EA4\u8FD8\u79DF\u7EA6",{projectId:e.projectId,error:j(n)}),e.busy=!1,await this.releaseHolding(e.projectId,"resync_failed"),!1}return e.busy=!1,!0}async releaseHolding(e,t){let n=this.holdings.get(e);n&&(this.holdings.delete(e),n.heartbeatTimer&&(this.clearTimer(n.heartbeatTimer),n.heartbeatTimer=null),await n.engine.stop().catch(r=>{x.warn(A,"\u505C\u6B62\u5F15\u64CE\u5F02\u5E38",{projectId:e,error:j(r)})}),await n.spool?.stop().catch(()=>{}),await this.postSafe(`/api/runner/workflows/${e}/release`,{generation:n.generation,reason:t}),x.info(A,"\u5DF2\u8BA9\u51FA\u79DF\u7EA6",{projectId:e,reason:t}),this.running&&this.scheduleNextPoll(this.options.defaultPollMs??1e4))}clientConfig(){return{gatewayUrl:this.options.gatewayUrl,machineKey:this.options.machineKey,...this.options.fetchImpl?{fetchImpl:this.options.fetchImpl}:{}}}async post(e,t){let r=await(this.options.fetchImpl??fetch)(`${this.options.gatewayUrl.replace(/\/+$/,"")}${e}`,{method:"POST",headers:{authorization:`Bearer ${this.options.machineKey}`,"content-type":"application/json"},body:JSON.stringify(t??{})});if(!r.ok){let s=await r.text().catch(()=>"");throw new Error(`runner API ${e} \u5931\u8D25: HTTP ${r.status} ${s.slice(0,200)}`)}return await r.json()}async postSafe(e,t){try{await this.post(e,t)}catch(n){x.warn(A,"\u6536\u5C3E\u8BF7\u6C42\u5931\u8D25\uFF08\u79DF\u7EA6\u5C06\u7531\u670D\u52A1\u7AEF\u8FC7\u671F\u56DE\u6536\uFF09",{pathname:e,error:j(n)})}}};function $o(o){return new le({projectId:o.projectId,workspaceDir:o.workspaceDir,cliPath:o.cliPath,...o.onRunEvent?{onRunEvent:o.onRunEvent}:{},...o.onCrashLoop?{onCrashLoop:c(()=>o.onCrashLoop(),"onCrashLoop")}:{}})}c($o,"defaultSupervisorFactory");function j(o){return o instanceof Error?o.message:String(o)}c(j,"describeError");import{spawn as Oo}from"child_process";import{existsSync as jo}from"fs";import Y from"path";import{fileURLToPath as Mo}from"url";import{appendFileSync as fc,statSync as gc,renameSync as hc,mkdirSync as vc,existsSync as wc}from"fs";import Lo from"path";var bc=10*1024*1024;function J(o){return Lo.join(Q(o),"daemon.log")}c(J,"logFilePath");var ve=Y.dirname(Mo(import.meta.url));function Ne(){let o=[Y.resolve(ve,"..","..","bin","aitable-workflow.mjs"),Y.resolve(ve,"..","bin","aitable-workflow.mjs"),Y.resolve(ve,"..","..","dist","cli.js"),Y.resolve(ve,"cli.js")];return o.find(e=>jo(e))??o[0]}c(Ne,"resolveDaemonEntry");var Do=Ne();async function V(o){await ct(o.agentId);let e=["relay"];o.serverUrl&&e.push("--server-url",o.serverUrl),o.token&&e.push("--token",o.token),o.key&&e.push("--key",o.key),o.name&&e.push("--name",o.name),o.workspaceRoot&&e.push("--workspace-root",o.workspaceRoot),o.machineId&&e.push("--machine-id",o.machineId),o.maxTasks&&e.push("--max-tasks",String(o.maxTasks));let t=await import("fs").then(i=>{let a=J(o.agentId);return i.openSync(a,"a")}),n=Oo(process.execPath,[Do,...e],{detached:!0,stdio:["ignore",t,t],env:{...process.env}});try{let{closeSync:i}=await import("fs");i(t)}catch{}n.unref();let{writeFile:r}=await import("fs/promises"),{pidFilePath:s}=await import("./pid-file-KT5KHCKU.js");return n.pid&&await r(s(o.agentId),String(n.pid),"utf8"),{pid:n.pid??0}}c(V,"startDaemon");async function we(o,e=5e3){let t=await Se(o);if(t===null||!G(t))return await ee(o),!1;try{process.kill(t,"SIGTERM")}catch{return await ee(o),!1}let n=Date.now()+e;for(;Date.now()<n&&G(t);)await new Promise(r=>setTimeout(r,200));if(G(t))try{process.kill(t,"SIGKILL")}catch{}return await ee(o),!0}c(we,"stopDaemon");async function K(o){let e=await Se(o),t=e!==null&&G(e),n=null;if(t&&e!==null)try{let{readFile:r}=await import("fs/promises"),s=await r(`/proc/${e}/stat`,"utf8"),i=parseInt(s.split(" ")[21]??"0",10),a=await r("/proc/uptime","utf8"),p=parseFloat(a.split(" ")[0]??"0")-i/100;n=Math.round(p*1e3)}catch{}return{agentId:o,running:t,pid:t?e:null,uptimeMs:n,logFile:J(o)}}c(K,"getDaemonStatus");function es(o){return o.replace(/\/+$/,"").replace(/^ws/,"http")}c(es,"toHttpBase");var b="relay:daemon",be="relay:trace",an=["aitable"],ts="dws",ns=20,rs=500,os=2e4,on=8e3,Ue="127.0.0.1",ss=200,is=15e3,We=class{static{c(this,"AgentTraceRingBuffer")}maxRuns;maxEventsPerRun;now;runs=new Map;order=[];listeners=new Map;constructor(e={}){this.maxRuns=Math.max(1,Math.floor(e.maxRuns??ns)),this.maxEventsPerRun=Math.max(1,Math.floor(e.maxEventsPerRun??rs)),this.now=e.now??(()=>new Date().toISOString())}subscribeRun(e,t){let n=this.listeners.get(e);return n||(n=new Set,this.listeners.set(e,n)),n.add(t),()=>{let r=this.listeners.get(e);r&&(r.delete(t),r.size===0&&this.listeners.delete(e))}}notify(e){let t=this.listeners.get(e);if(!(!t||t.size===0))for(let n of[...t])try{n()}catch{}}startRun(e){this.runs.delete(e.requestId);let t=this.order.indexOf(e.requestId);if(t>=0&&this.order.splice(t,1),this.order.length>=this.maxRuns){let n=this.order.shift();n&&(this.runs.delete(n),this.notify(n))}this.order.push(e.requestId),this.runs.set(e.requestId,{...e,startedAt:this.now(),status:"running",events:[],eventCount:0,droppedEvents:0})}appendEvent(e,t){let n=this.runs.get(e);if(n){for(n.eventCount+=1,n.events.push(ln(t));n.events.length>this.maxEventsPerRun;)n.events.shift(),n.droppedEvents+=1;this.notify(e)}}finishRun(e,t){let n=this.runs.get(e);n&&(n.status=t.status,n.endedAt=this.now(),t.error&&(n.error=ze(t.error,on)),t.response&&(n.responsePreview=ze(t.response,on)),t.sessionId&&(n.sessionId=t.sessionId),this.notify(e))}listRuns(){return[...this.order].reverse().map(e=>this.runs.get(e)).filter(e=>!!e).map(e=>({...cn(e),eventBufferSize:e.events.length}))}getRun(e){let t=this.runs.get(e);return t?ls(t):void 0}},Ge=class{constructor(e,t){this.store=e;this.options=t;this.server=Ho((n,r)=>{this.handle(n,r).catch(s=>{let i=s instanceof Error?s.message:String(s);w.error(be,"trace http handler error",{error:i}),r.headersSent?r.end():v(r,500,{error:"internal_error"})})})}store;options;static{c(this,"AgentTraceHttpServer")}server;started=!1;start(){if(this.started)return Promise.resolve();let e=this.options.host??Ue;return new Promise((t,n)=>{let r=c(i=>{this.server.off("listening",s),n(i)},"onError"),s=c(()=>{this.server.off("error",r),this.started=!0,t()},"onListening");this.server.once("error",r),this.server.once("listening",s),this.server.listen(this.options.port,e)})}stop(){return this.started?new Promise((e,t)=>{this.server.close(n=>{if(n){t(n);return}this.started=!1,e()})}):Promise.resolve()}address(){let e=this.server.address();return!e||typeof e=="string"?null:{host:this.options.host??Ue,port:e.port}}async handle(e,t){let n=new URL(e.url??"/","http://127.0.0.1"),r=e.method??"GET";if(r==="GET"){await this.handleGet(n,t);return}if(r==="POST"){await this.handlePost(e,n,t);return}v(t,405,{error:"method_not_allowed"})}async handleGet(e,t){if(e.pathname==="/"||e.pathname==="/index.html"||e.pathname==="/assistant"||e.pathname==="/assistant/"){await this.serveAssistantFile(t,"index.html","text/html; charset=utf-8");return}if(e.pathname==="/classic"||e.pathname==="/classic/"){ye(t,200,"text/html; charset=utf-8",Bt);return}if(e.pathname==="/assets/workbench.css"){ye(t,200,"text/css; charset=utf-8",Ht);return}if(e.pathname==="/assets/workbench.js"){ye(t,200,"application/javascript; charset=utf-8",Ft);return}let n=/^\/assistant\/assets\/([A-Za-z0-9._-]+)$/.exec(e.pathname);if(n){let l=n[1]??"",d=l.endsWith(".css")?"text/css; charset=utf-8":l.endsWith(".js")?"application/javascript; charset=utf-8":"application/octet-stream";await this.serveAssistantFile(t,`assets/${l}`,d);return}if(e.pathname==="/health"){v(t,200,{ok:!0,chat:!!this.options.chat});return}if(e.pathname==="/api/chat/agents"){if(!this.options.chat){v(t,404,{error:"not_found"});return}v(t,200,{agents:this.options.chat.listAgents()});return}if(e.pathname==="/runs"){v(t,200,{runs:this.store.listRuns()});return}let r=/^\/runs\/([^/]+)\/events$/.exec(e.pathname);if(r){let l=decodeURIComponent(r[1]??""),d=this.store.getRun(l);if(!d){v(t,404,{error:"run_not_found"});return}v(t,200,{run:d,events:d.events});return}if(e.pathname==="/api/runs"){v(t,200,{runs:this.store.listRuns().map(ke)});return}let s=/^\/api\/runs\/([^/]+)$/.exec(e.pathname);if(s){let l=this.store.getRun(decodeURIComponent(s[1]??""));if(!l){v(t,404,{error:"run_not_found"});return}v(t,200,{run:ke(l)});return}let i=/^\/api\/runs\/([^/]+)\/events$/.exec(e.pathname);if(i){let l=this.store.getRun(decodeURIComponent(i[1]??""));if(!l){v(t,404,{error:"run_not_found"});return}let d=rn(l.events);v(t,200,{run:ke(l),groups:d,eventCount:l.eventCount,droppedEvents:l.droppedEvents});return}let a=/^\/api\/runs\/([^/]+)\/stream$/.exec(e.pathname);if(a){this.handleSse(t,decodeURIComponent(a[1]??""));return}v(t,404,{error:"not_found"})}async handlePost(e,t,n){let r=this.options.chat;if(!r){v(n,404,{error:"not_found"});return}let s=/^\/api\/chat\/([^/]+)\/stop$/.exec(t.pathname);if(s){let i=decodeURIComponent(s[1]??"");if(!r.stop(i)){v(n,404,{error:"no_active_chat"});return}v(n,200,{ok:!0,requestId:i});return}if(t.pathname==="/api/chat"){let i=await cs(e);if(!i.ok){v(n,i.status,{error:i.error});return}let a=i.value,l=r.start({requestId:typeof a.requestId=="string"?a.requestId:"",prompt:typeof a.prompt=="string"?a.prompt:"",...typeof a.agent=="string"?{agent:a.agent}:{},...typeof a.workDir=="string"?{workDir:a.workDir}:{},...typeof a.sessionId=="string"?{sessionId:a.sessionId}:{},...typeof a.timeoutMs=="number"?{timeoutMs:a.timeoutMs}:{}});if(!l.ok){v(n,l.status,{error:l.error});return}v(n,202,{accepted:!0,stream:`/api/runs/${encodeURIComponent(a.requestId??"")}/stream`});return}v(n,404,{error:"not_found"})}buildSnapshot(e){let t=this.store.getRun(e);return t?{run:ke(t),groups:rn(t.events)}:{run:null,groups:[]}}async serveAssistantFile(e,t,n){let r=this.resolveAssistantDir();if(r)try{let s=await sn(I.join(r,t));e.statusCode=200,e.setHeader("content-type",n),e.setHeader("cache-control","no-store"),e.end(s);return}catch{}ye(e,404,"text/plain; charset=utf-8","assistant UI \u672A\u6784\u5EFA\uFF1A\u5728 packages/cli \u4E0B\u6267\u884C pnpm run build\uFF08\u6216\u5355\u72EC\u6784\u5EFA assistant-ui \u5B50\u5305\uFF09\u540E\u91CD\u8BD5\u3002")}resolveAssistantDir(){if(this.options.assistantDir)return this.options.assistantDir;let e=[new URL("./assistant/",import.meta.url),new URL("../../dist/assistant/",import.meta.url)];for(let t of e){let n=Bo(t);try{if(qo(I.join(n,"index.html")))return n}catch{}}return null}handleSse(e,t){if(!this.store.getRun(t)){v(e,404,{error:"run_not_found"});return}e.statusCode=200,e.setHeader("content-type","text/event-stream; charset=utf-8"),e.setHeader("cache-control","no-cache, no-transform"),e.setHeader("connection","keep-alive"),e.setHeader("x-accel-buffering","no"),e.write(`retry: 3000
510
+
511
+ `);let n=!1,r=null,s=c((m,f)=>{e.write(`event: ${m}
512
+ data: ${JSON.stringify(f)}
513
+
514
+ `)},"writeFrame"),i=c(()=>{n||(n=!0,r&&clearTimeout(r),clearInterval(p),d(),e.end())},"cleanup"),a=c(()=>{if(r=null,n)return;let m=this.buildSnapshot(t);if(!m.run){s("finish",{run:null,groups:[]}),i();return}s("update",m),m.run.status!=="running"&&(s("finish",m),i())},"flush"),l=c(()=>{n||r||(r=setTimeout(a,ss))},"schedule"),d=this.store.subscribeRun(t,l),p=setInterval(()=>{n||e.write(`: ping
515
+
516
+ `)},is);p.unref?.(),e.on("close",i);let u=this.buildSnapshot(t);s("snapshot",u),(!u.run||u.run.status!=="running")&&(s("finish",u),i())}};function ye(o,e,t,n){o.statusCode=e,o.setHeader("content-type",t),o.setHeader("cache-control","no-store"),o.end(n)}c(ye,"sendTraceText");function ke(o){let{events:e,eventBufferSize:t,...n}=o;return{...n,id:o.requestId,source:o.source??"server_workflow"}}c(ke,"toWorkbenchRunSummary");function v(o,e,t){o.statusCode=e,o.setHeader("content-type","application/json; charset=utf-8"),o.end(JSON.stringify(t))}c(v,"sendTraceJson");var as=64e3;async function cs(o){let e=[],t=0;for await(let s of o){let i=Buffer.isBuffer(s)?s:Buffer.from(s);if(t+=i.length,t>as)return{ok:!1,status:413,error:"request_body_too_large"};e.push(i)}let n=Buffer.concat(e).toString("utf8").trim();if(n==="")return{ok:!1,status:400,error:"request_body_required"};let r;try{r=JSON.parse(n)}catch{return{ok:!1,status:400,error:"invalid_json"}}return typeof r!="object"||r===null||Array.isArray(r)?{ok:!1,status:400,error:"request_body_must_be_object"}:{ok:!0,value:r}}c(cs,"readJsonBody");function ls(o){return{...cn(o),events:o.events.map(e=>ln(e))}}c(ls,"cloneTraceRun");function cn(o){let{events:e,...t}=o;return{...t}}c(cn,"cloneRunWithoutEvents");function ln(o){return qe(o)}c(ln,"cloneTraceEvent");function qe(o){if(typeof o=="string")return ze(o,os);if(Array.isArray(o))return o.map(e=>qe(e));if(o&&typeof o=="object"){let e={};for(let[t,n]of Object.entries(o))e[t]=qe(n);return e}return o}c(qe,"clipTraceValue");function ze(o,e){return o.length<=e?o:`${o.slice(0,e)}... [truncated ${o.length-e} chars]`}c(ze,"clipTraceText");function ds(o){if(typeof o!="object"||o===null)return null;let e=o,t=typeof e.itemId=="string"?e.itemId:null,n=typeof e.stepId=="string"?e.stepId:null;if(!t||!n)return null;switch(e.type){case"step.started":return{op:"start",itemId:t,stepId:n};case"run.agent_event":{let r=typeof e.text=="string"?e.text:void 0,s=typeof e.tool=="string"?e.tool:void 0,i=typeof e.args=="string"?e.args:void 0,a=null;return e.kind==="text"?a={type:"text",content:r}:e.kind==="thinking"?a={type:"thinking",content:r}:e.kind==="tool_use"?a={type:"tool_use",toolName:s,toolInput:i}:e.kind==="tool_result"?a={type:"tool_result",content:r}:e.kind==="result"&&(a={type:"result",content:r}),a?{op:"event",itemId:t,stepId:n,event:a}:null}case"step.succeeded":return{op:"finish",itemId:t,stepId:n,status:"succeeded"};case"step.failed":return{op:"finish",itemId:t,stepId:n,status:"failed",error:typeof e.error=="string"?e.error:void 0};case"record.blocked":return{op:"finish",itemId:t,stepId:n,status:"failed",error:typeof e.reason=="string"?e.reason:void 0};default:return null}}c(ds,"toRunnerTraceProjection");function ps(o,e=an){if(!Array.isArray(o)||o.length===0)return{ok:!1,reason:"dws args must be a non-empty array"};for(let n of o){if(typeof n!="string")return{ok:!1,reason:"dws args must all be strings"};if(n.length===0)return{ok:!1,reason:"dws args must not contain empty tokens"};if(/[\u0000-\u001f]/.test(n))return{ok:!1,reason:"dws args must not contain control characters"}}let t=o[0];return t.startsWith("-")?{ok:!1,reason:"first dws arg must be a subcommand, not a flag"}:e.length>0&&!e.includes(t)?{ok:!1,reason:`dws command "${t}" is not allowed`}:{ok:!0}}c(ps,"validateDwsArgs");function us(o){return Xo(o,["--version"],Zo({timeoutMs:5e3})).ok}c(us,"detectDwsAvailable");var Je=class{static{c(this,"RelayDaemon")}config;allowedDwsCommands;conn;runAgent;createDwsClient;detectAgents;detectDws;hostname;osString;onPermanentReject;artifactUploader;grantTimeoutMs;pendingGrants=new Map;maxTasks;inflight=0;taskQueue=[];runnerLoop;traceStore;traceHttpServer;chatManager;machineId;constructor(e,t={}){this.config={...e,dwsBin:e.dwsBin??ts},this.machineId=e.machineId,this.allowedDwsCommands=e.allowedDwsCommands??an,this.runAgent=t.runAgent??Jo,this.createDwsClient=t.createDwsClient??((r,s)=>new Yo({bin:r,timeoutMs:s})),this.detectAgents=t.detectAgents??(()=>zo()),this.detectDws=t.detectDws??(r=>us(r)),this.hostname=t.hostname??(()=>M.hostname()),this.osString=t.osString??(()=>`${M.platform()} ${M.arch()}`),this.onPermanentReject=t.onPermanentReject,this.artifactUploader=t.artifactUploader??qt,this.grantTimeoutMs=t.grantTimeoutMs??3e4,this.maxTasks=Math.max(1,Math.floor(e.maxTasks??1)),this.traceStore=t.traceStore??new We({maxRuns:e.traceRunBufferSize,maxEventsPerRun:e.traceEventBufferSize}),this.chatManager=e.traceChat&&e.traceHttpPort!=null?new ae({workspaceRoot:this.config.workspaceRoot,store:this.traceStore,runAgent:this.runAgent,detectAgents:this.detectAgents,enqueue:c(r=>this.enqueueTask(r),"enqueue"),defaultTimeoutMs:e.agentTimeoutMs}):null,this.traceHttpServer=e.traceHttpPort!=null?new Ge(this.traceStore,{host:e.traceHttpHost??Ue,port:e.traceHttpPort,...this.chatManager?{chat:this.chatManager}:{}}):null;let n=t.createConnection??(r=>new ce(r));this.conn=n({serverUrl:this.config.serverUrl,key:this.config.key,token:this.config.token,onMessage:c(r=>this.handleMessage(r),"onMessage"),onOpen:c(()=>this.handleOpen(),"onOpen"),onPermanentReject:c(r=>this.handlePermanentReject(r),"onPermanentReject")}),this.runnerLoop=this.buildRunnerLoop(t)}buildRunnerLoop(e){let t=Math.max(0,Math.floor(this.config.maxWorkflows??3));if(t===0)return null;let n=this.config.key??this.config.token;if(!n)return w.warn(b,"\u65E0 machine key/owner-token\uFF0C\u8DF3\u8FC7 RunnerLoop\uFF08run \u9636\u6BB5\u4E0D\u8BA4\u9886\u9879\u76EE\uFF09"),null;let r={gatewayUrl:es(this.config.serverUrl),machineKey:n,workspaceRoot:this.config.workspaceRoot,cliPath:Ne(),maxWorkflows:t,sendRunEvents:c((s,i)=>this.sendRunEvents(s,i),"sendRunEvents"),onRunEvent:c((s,i)=>this.recordRunnerTrace(s,i),"onRunEvent")};return(e.createRunnerLoop??(s=>new he(s)))(r)}recordRunnerTrace(e,t){let n=ds(t);if(!n)return;let r=`run:${e}:${n.itemId}:${n.stepId}`;if(n.op==="start"){this.traceStore.getRun(r)||this.traceStore.startRun({requestId:r,projectId:e,agent:"engine",workDir:this.config.workspaceRoot??e});return}if(n.op==="event"){this.traceStore.getRun(r)||this.traceStore.startRun({requestId:r,projectId:e,agent:"engine",workDir:this.config.workspaceRoot??e}),this.traceStore.appendEvent(r,n.event);return}this.traceStore.finishRun(r,{status:n.status,...n.error?{error:n.error}:{}})}sendRunEvents(e,t){t.length!==0&&this.conn.send({type:"run:events",projectId:e,entries:t})}start(){w.info(b,"starting",{serverUrl:this.config.serverUrl,workspaceRoot:this.config.workspaceRoot}),this.config.name||w.warn(b,"\u672A\u6307\u5B9A --name\uFF0C\u5C06\u4F7F\u7528\u4E3B\u673A\u540D\u4F5C\u4E3A\u673A\u5668\u6CE8\u518C\u540D\uFF1B\u591A\u673A\u573A\u666F\u4E0B hostname \u82E5\u91CD\u590D\u4F1A\u5BFC\u81F4\u8FDE\u63A5\u4E92\u76F8\u9876\u66FF\uFF0C\u5EFA\u8BAE\u663E\u5F0F\u6307\u5B9A --name",{hostname:this.hostname()}),this.startTraceHttpServer(),this.conn.connect(),this.runnerLoop?.start()}stop(){w.info(b,"stopping"),this.conn.close();let e=[];return this.runnerLoop&&e.push(this.runnerLoop.stop().catch(t=>{w.warn(b,"runner loop \u505C\u6B62\u5F02\u5E38",{error:t instanceof Error?t.message:String(t)})})),this.traceHttpServer&&e.push(this.traceHttpServer.stop().catch(t=>{w.warn(be,"trace http \u505C\u6B62\u5F02\u5E38",{error:t instanceof Error?t.message:String(t)})})),Promise.all(e).then(()=>{})}startTraceHttpServer(){this.traceHttpServer&&this.traceHttpServer.start().then(()=>{let e=this.traceHttpServer?.address();e&&w.info(be,"trace http listening",{url:`http://${e.host}:${e.port}`})}).catch(e=>{w.warn(be,"trace http \u542F\u52A8\u5931\u8D25\uFF0C\u672C\u5730\u4E8B\u4EF6\u4ECD\u4FDD\u7559\u5728\u5185\u5B58\u4F46\u65E0\u6CD5 HTTP \u67E5\u770B",{error:e instanceof Error?e.message:String(e)})})}buildReady(){let t={type:"ready",runtimes:Array.from(new Set(this.detectAgents().map(n=>n.type))),hasDws:this.detectDws(this.config.dwsBin),hostname:this.hostname(),os:this.osString()};return this.machineId&&(t.machineId=this.machineId),this.config.name&&(t.name=this.config.name),this.config.displayName&&(t.displayName=this.config.displayName),this.config.description&&(t.description=this.config.description),this.maxTasks>1&&(t.maxTasks=this.maxTasks),t}handleOpen(){let e=this.buildReady();w.info(b,"connected; sending ready",{runtimes:e.runtimes,hasDws:e.hasDws}),this.conn.send(e)}handlePermanentReject(e){w.error(b,"permanently rejected by gateway",{...e}),this.onPermanentReject?.(e)}handleMessage(e){switch(e.type){case"run:agent":this.enqueueTask(()=>this.handleRunAgent(e));break;case"run:dws":this.enqueueTask(()=>this.handleRunDws(e));break;case"upload:grant":this.resolveGrant(e);break;case"wf:available":this.runnerLoop?.onWakeup();break;case"ready:ack":e.machineId&&(this.machineId=e.machineId,w.info(b,"machine id assigned",{machineId:e.machineId}));break;default:break}}enqueueTask(e){let t=c(()=>{this.inflight+=1,e().finally(()=>{this.inflight-=1;let n=this.taskQueue.shift();n&&n()})},"exec");this.inflight<this.maxTasks?t():this.taskQueue.push(t)}async handleRunAgent(e){let{requestId:t}=e;w.info(b,"run:agent received",{requestId:t,projectId:e.projectId,agent:e.agent});try{let n=this.resolveWorkDir(e.projectId,e.workDir);this.traceStore.startRun({requestId:t,projectId:e.projectId,agent:e.agent,workDir:n}),await Fo(n,{recursive:!0});let r=this.rewritePromptWorkDir(e.prompt,e.workDir,n),s={agent:e.agent,workDir:n,onEvent:c(l=>{this.traceStore.appendEvent(t,l),this.conn.send({type:"event",requestId:t,event:l})},"onEvent")};e.sessionId&&(s.sessionId=e.sessionId),e.permissionMode&&(s.adapterOptions={permissionMode:e.permissionMode}),e.timeoutMs!==void 0?s.timeoutMs=e.timeoutMs:this.config.agentTimeoutMs!=null&&(s.timeoutMs=this.config.agentTimeoutMs);let i=await this.runAgent(r,s),a;try{a=await this.collectAndUploadArtifacts(t,e.projectId,n)}catch(l){let d=l instanceof Error?l.message:String(l);w.error(b,"artifact upload failed",{requestId:t,error:d}),this.traceStore.finishRun(t,{status:"failed",error:d,sessionId:i.sessionId}),this.conn.send({type:"error",requestId:t,code:"artifact_upload_failed",message:d});return}this.traceStore.finishRun(t,{status:"succeeded",response:i.response,sessionId:i.sessionId}),this.conn.send({type:"result",requestId:t,ok:!0,response:i.response,sessionId:i.sessionId,...a?{artifacts:a}:{}}),w.info(b,"run:agent done",{requestId:t,sessionId:i.sessionId,artifacts:a?a.files.length:0})}catch(n){let r=n instanceof Error?n.message:String(n);w.error(b,"run:agent failed",{requestId:t,error:r}),this.traceStore.finishRun(t,{status:"failed",error:r}),this.conn.send({type:"error",requestId:t,code:"agent_failed",message:r})}}async collectAndUploadArtifacts(e,t,n){let r=await zt(n);if(r.length===0)return;this.conn.send({type:"upload:request",requestId:e,projectId:t,files:r.map(a=>({path:a.relPath,size:a.size,sha256:a.sha256}))});let s=await this.awaitGrant(e);if(!s)throw new Error("upload:grant \u7B49\u5F85\u8D85\u65F6");if(s.grants.length===0){w.warn(b,"upload:grant \u65E0\u6388\u6743\u9879\uFF08gateway \u672A\u914D\u7F6E store \u6216\u5168\u88AB\u62D2\uFF09",{requestId:e,rejected:(s.rejected??[]).length});return}let i=[];for(let a of s.grants){let l=r.find(p=>p.relPath===a.path);if(!l)continue;let d=await sn(l.absPath);await this.artifactUploader.upload(a.url,d,a.headers),i.push({path:a.path,key:a.key,sha256:l.sha256,size:l.size})}return{store:"oss",files:i}}awaitGrant(e){return new Promise(t=>{let n=setTimeout(()=>{this.pendingGrants.delete(e),t(void 0)},this.grantTimeoutMs);n.unref?.(),this.pendingGrants.set(e,r=>{clearTimeout(n),t(r)})})}resolveGrant(e){let t=this.pendingGrants.get(e.requestId);t&&(this.pendingGrants.delete(e.requestId),t(e))}async handleRunDws(e){let{requestId:t}=e,n=ps(e.args,this.allowedDwsCommands);if(!n.ok){w.warn(b,"run:dws rejected",{requestId:t,reason:n.reason}),this.conn.send({type:"error",requestId:t,code:"dws_rejected",message:n.reason});return}w.info(b,"run:dws received",{requestId:t,command:e.args[0]});let r=e.args,s;try{let i=await this.materializeInlineFiles(e.args,e.inlineFiles);r=i.args,s=i.tmpDir;let l=await this.createDwsClient(this.config.dwsBin,e.timeoutMs).runJson(r,e.timeoutMs!=null?{timeoutMs:e.timeoutMs}:void 0);this.conn.send({type:"result",requestId:t,ok:!0,response:JSON.stringify(l)}),w.info(b,"run:dws done",{requestId:t})}catch(i){let a=i instanceof Error?i.message:String(i);w.error(b,"run:dws failed",{requestId:t,error:a}),this.conn.send({type:"error",requestId:t,code:"dws_failed",message:a})}finally{s&&await Wo(s,{recursive:!0,force:!0}).catch(()=>{})}}async materializeInlineFiles(e,t){let n=t?Object.entries(t):[];if(n.length===0)return{args:e};let r=await No(I.join(M.tmpdir(),"aitable-dws-records-")),s=e,i=0;for(let[a,l]of n){let d=I.join(r,`records-${i++}.json`);await Uo(d,l,"utf8"),s=Qo(s,a,d)}return{args:s,tmpDir:r}}resolveWorkDir(e,t){return ie(this.config.workspaceRoot,e,t)}rewritePromptWorkDir(e,t,n){let r=t?.trim();return!r||!I.isAbsolute(r)||r===n?e:e.split(r).join(n)}};function Ye(o,e){let t,n=o?.trim();if(n)t=I.isAbsolute(n)?I.resolve(n):I.resolve(M.homedir(),n);else{let r=e?.trim()?e.trim():"default";t=I.join(M.homedir(),".aitable-workflow","workspaces",Ko(r,{label:"agentId"}))}return Go(t,{recursive:!0}),t}c(Ye,"resolveWorkspaceRoot");function ms(o,e=process.env){let t=o.serverUrl??e.AITABLE_RELAY_SERVER_URL,n=o.key??e.AITABLE_RELAY_BOOTSTRAP_KEY,r=o.token??e.AITABLE_RELAY_TOKEN,s=o.workspaceRoot??e.AITABLE_RELAY_WORKSPACE_ROOT,i=o.machineId??e.AITABLE_RELAY_MACHINE_ID,a=o.name??e.AITABLE_RELAY_NAME,l=o.desc??e.AITABLE_RELAY_DESC,d=o.maxTasks??e.AITABLE_RELAY_MAX_TASKS,p=o.maxWorkflows??e.AITABLE_RELAY_MAX_WORKFLOWS,u=o.traceHttpPort??e.AITABLE_RELAY_TRACE_HTTP_PORT,m=o.traceHttpHost??e.AITABLE_RELAY_TRACE_HTTP_HOST,f=o.traceBufferSize??e.AITABLE_RELAY_TRACE_BUFFER_SIZE,R=o.traceEventsPerRun??e.AITABLE_RELAY_TRACE_EVENTS_PER_RUN,S=o.traceChat??e.AITABLE_RELAY_TRACE_CHAT,E=[];if(t||E.push("--server-url (\u6216 AITABLE_RELAY_SERVER_URL)"),!n&&!r&&E.push("--key/--token (\u6216 AITABLE_RELAY_BOOTSTRAP_KEY/AITABLE_RELAY_TOKEN)"),E.length>0)throw new Error(`relay \u7F3A\u5C11\u5FC5\u8981\u53C2\u6570: ${E.join(", ")}
517
+ \u{1F4A1} \u63D0\u793A: \u4F7F\u7528 \`aitable-workflow connect\` \u6CE8\u518C\u540E\u53EF\u7701\u7565\u8FD9\u4E9B\u53C2\u6570`);let H=a??M.hostname()??"default",g={serverUrl:t,workspaceRoot:Ye(s,H)};if(r?g.token=r:n&&(g.key=n),i&&(g.machineId=i),a&&(g.name=a,g.displayName=a),l&&(g.description=l),d!=null&&d!==""){let h=Math.floor(Number(d));Number.isFinite(h)&&h>=1&&(g.maxTasks=h)}if(p!=null&&p!==""){let h=Math.floor(Number(p));Number.isFinite(h)&&h>=0&&(g.maxWorkflows=h)}if(u!=null&&u!==""){let h=Math.floor(Number(u));Number.isFinite(h)&&h>=0&&(g.traceHttpPort=h)}if(m?.trim()&&(g.traceHttpHost=m.trim()),f!=null&&f!==""){let h=Math.floor(Number(f));Number.isFinite(h)&&h>=1&&(g.traceRunBufferSize=h)}if(R!=null&&R!==""){let h=Math.floor(Number(R));Number.isFinite(h)&&h>=1&&(g.traceEventBufferSize=h)}return fs(S)&&(g.traceChat=!0),g}c(ms,"resolveRelayCliConfig");function fs(o){return typeof o=="boolean"?o:typeof o!="string"?!1:["1","true","yes","on"].includes(o.trim().toLowerCase())}c(fs,"isTruthyFlag");async function U(o,e=process.env){let t=null;try{t=await Vo()}catch{t=null}let n={serverUrl:o.serverUrl??e.AITABLE_RELAY_SERVER_URL??t?.serverUrl,key:o.key??e.AITABLE_RELAY_BOOTSTRAP_KEY??t?.key,token:o.token??e.AITABLE_RELAY_TOKEN??t?.token,name:o.name??e.AITABLE_RELAY_NAME??t?.name,desc:o.desc??e.AITABLE_RELAY_DESC,workspaceRoot:o.workspaceRoot??e.AITABLE_RELAY_WORKSPACE_ROOT??t?.workspaceRoot,machineId:o.machineId??e.AITABLE_RELAY_MACHINE_ID??t?.machineId,maxTasks:o.maxTasks??e.AITABLE_RELAY_MAX_TASKS,maxWorkflows:o.maxWorkflows??e.AITABLE_RELAY_MAX_WORKFLOWS,traceHttpPort:o.traceHttpPort??e.AITABLE_RELAY_TRACE_HTTP_PORT,traceHttpHost:o.traceHttpHost??e.AITABLE_RELAY_TRACE_HTTP_HOST,traceBufferSize:o.traceBufferSize??e.AITABLE_RELAY_TRACE_BUFFER_SIZE,traceEventsPerRun:o.traceEventsPerRun??e.AITABLE_RELAY_TRACE_EVENTS_PER_RUN,traceChat:o.traceChat??e.AITABLE_RELAY_TRACE_CHAT};return ms(n,e)}c(U,"resolveDaemonConfig");async function Re(o){let e=await U(o),t=new Je(e,{onPermanentReject:c(()=>{process.exit(1)},"onPermanentReject")}),n=!1,r=c(()=>{n&&(w.warn(b,"\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",r),process.on("SIGTERM",r),t.start(),t}c(Re,"runRelayDaemon");import{readFile as gs,writeFile as Kc,mkdir as Xc}from"fs/promises";import hs from"path";var dn={connectionState:"disconnected",lastHeartbeatAt:null,machineId:null,serverUrl:"",runningTasks:0,queuedTasks:0,lastDisconnectReason:null,updatedAt:new Date().toISOString()};function vs(o){return hs.join(Q(o),"state.json")}c(vs,"stateFilePath");async function Ce(o){try{let e=await gs(vs(o),"utf8");return{...dn,...JSON.parse(e)}}catch{return{...dn}}}c(Ce,"readState");import{execSync as X}from"child_process";import{writeFile as ws,rm as ys,mkdir as ks,access as bs}from"fs/promises";import _ from"path";import pn from"os";import{assertPortableId as Rs,readCredentials as Cs}from"aitable-workflow-core";var xs="com.alibaba.aitable-workflow.daemon",Ve="\u8BF7\u5148\u5168\u5C40\u5B89\u88C5\uFF1Anpm i -g @ali/aitable-workflow";function Z(o){return`${xs}.${Rs(o,{label:"agentId"})}`}c(Z,"plistLabel");function Ke(o){return _.join(pn.homedir(),"Library","LaunchAgents",`${Z(o)}.plist`)}c(Ke,"plistPath");function D(){return process.platform==="darwin"}c(D,"isMacOS");function un(){try{return X("which aitable-workflow",{encoding:"utf8"}).trim()||null}catch{return null}}c(un,"resolveGlobalCliEntry");function mn(o){if(!o||!o.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
518
+ \u{1F4A1} ${Ve}`);if(o.includes("/_npx/")||o.includes(`${_.sep}_npx${_.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${o}
519
+ \u{1F4A1} ${Ve}`);if(!_.isAbsolute(o))throw new Error(`CLI \u5165\u53E3\u4E0D\u662F\u7A33\u5B9A\u7684\u5168\u5C40\u7EDD\u5BF9\u8DEF\u5F84\uFF1A${o}
520
+ \u{1F4A1} ${Ve}`)}c(mn,"assertStableCliEntry");async function As(o){let e={};e.AITABLE_RELAY_NAME=o;let t;try{let n=await Cs();t=n.agents.find(r=>r.name===o)??n.agents.find(r=>r.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(As,"buildRelayEnv");function Es(o,e){let t=Z(o),n=e?.cliEntry??un();mn(n);let r=["relay"];e?.maxTasks&&r.push("--max-tasks",String(e.maxTasks));let s=_.join(pn.homedir(),".aitable-workflow","daemons",o),i=_.join(s,"launchd.log"),a=_.join(s,"launchd.err.log"),l=[n,...r].map(u=>` <string>${W(u)}</string>`).join(`
521
+ `),d={PATH:process.env.PATH??"/usr/local/bin:/usr/bin:/bin",...e?.relayEnv??{}},p=Object.entries(d).map(([u,m])=>` <key>${W(u)}</key>
522
+ <string>${W(m)}</string>`).join(`
35
523
  `);return`<?xml version="1.0" encoding="UTF-8"?>
36
524
  <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
37
525
  <plist version="1.0">
38
526
  <dict>
39
527
  <key>Label</key>
40
- <string>${U(e)}</string>
528
+ <string>${W(t)}</string>
41
529
  <key>ProgramArguments</key>
42
530
  <array>
43
531
  ${l}
44
532
  </array>
45
533
  <key>EnvironmentVariables</key>
46
534
  <dict>
47
- ${m}
535
+ ${p}
48
536
  </dict>
49
537
  <key>KeepAlive</key>
50
538
  <true/>
51
539
  <key>RunAtLoad</key>
52
540
  <true/>
53
541
  <key>StandardOutPath</key>
54
- <string>${U(s)}</string>
542
+ <string>${W(i)}</string>
55
543
  <key>StandardErrorPath</key>
56
- <string>${U(a)}</string>
544
+ <string>${W(a)}</string>
57
545
  </dict>
58
546
  </plist>
59
- `}c(Or,"generatePlist");function U(r){return r.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;")}c(U,"escapeXml");function we(){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(we,"getUid");async function Ht(r,t){if(!P())throw new Error("\u5F00\u673A\u81EA\u542F\u5F53\u524D\u4EC5\u652F\u6301 macOS");let e=Nt();Gt(e);let n=await jr(r),o=_e(r),i=Y(r);try{K(`launchctl bootout gui/${we()}/${i} 2>/dev/null`,{encoding:"utf8"})}catch{}await Er(A.dirname(o),{recursive:!0});let s=Or(r,{maxTasks:t?.maxTasks,relayEnv:n,cliEntry:e});await Sr(o,s,"utf8"),K(`launchctl bootstrap gui/${we()} ${o}`,{encoding:"utf8"})}c(Ht,"enableAutostart");async function Jt(r){if(!P())throw new Error("\u5F00\u673A\u81EA\u542F\u5F53\u524D\u4EC5\u652F\u6301 macOS");let t=Y(r),e=_e(r);try{K(`launchctl bootout gui/${we()}/${t} 2>/dev/null`,{encoding:"utf8"})}catch{}await Ar(e,{force:!0})}c(Jt,"disableAutostart");async function De(r){if(!P())throw new Error("\u5F00\u673A\u81EA\u542F\u5F53\u524D\u4EC5\u652F\u6301 macOS");let t=Y(r),e=_e(r),n=!1;try{await xr(e),n=!0}catch{n=!1}let o=!1,i=!1,s=null;try{let a=K(`launchctl print gui/${we()}/${t} 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(De,"getAutostartStatus");import{watchFile as Dr,statSync as Lr,openSync as Mr,readSync as Br,closeSync as Fr}from"fs";import{readFile as qt}from"fs/promises";function Kt(r,t){let e=r.command("daemon").description("\u540E\u53F0 relay daemon \u751F\u547D\u5468\u671F\u7BA1\u7406");e.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 F({serverUrl:n.serverUrl,token:n.token,key:n.key,workspaceRoot:n.workspaceRoot,name:o,maxTasks:n.maxTasks}),s=await V({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)}}),e.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 Vt(),i=0;for(let s of o)await ge(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 ge(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)}}),e.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 ge(o);let i=await F({name:o,maxTasks:n.maxTasks}),s=await V({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)}}),e.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 q(o),s=await j();if(console.log(`
60
- 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),p=Math.floor(l/60);console.log(`Uptime: ${p}h ${l%60}m ${a%60}s`)}console.log(`Log file: ${i.logFile}`),n.verbose&&s&&(console.log(`
61
- --- Configuration ---`),console.log(`Server: ${s.serverUrl}`),console.log(`Token: ${_r(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)}}),e.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 qt(i,"utf8").catch(()=>"");if(a){let p=a.trimEnd().split(`
62
- `);console.log(p.slice(-s).join(`
63
- `))}let l=a.length;Dr(i,{interval:500},()=>{try{let p=Lr(i);if(p.size>l){let m=Mr(i,"r"),u=Buffer.alloc(p.size-l);Br(m,u,0,u.length,l),Fr(m),process.stdout.write(u.toString("utf8")),l=p.size}}catch{}})}else{let a=await qt(i,"utf8").catch(()=>"");if(!a){console.log(`\u6682\u65E0\u65E5\u5FD7 (${i})`);return}let l=a.trimEnd().split(`
64
- `);console.log(l.slice(-s).join(`
65
- `))}}catch(o){S.error("cli","logs \u5931\u8D25",{error:o instanceof Error?o.message:String(o)}),process.exit(1)}}),e.command("autostart").description("macOS \u5F00\u673A\u81EA\u542F\u7BA1\u7406").addCommand(new Le("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 Ht(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 Le("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 Jt(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 Le("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 De(n.agentId);console.log(`
66
- 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 Vt();if(o.length===0){console.log("\u65E0\u5DF2\u6CE8\u518C\u7684 Agent");return}for(let i of o){let s=await De(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(Kt,"registerDaemonCommands");function Yt(r,t){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 e=await j();if(!e)throw new Error("\u65E0\u6D3B\u8DC3 Agent");if(!(await q(e.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 he(e.name);console.log("\u2705 Heartbeat OK"),console.log(` Agent: ${e.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(e){S.error("cli","heartbeat \u5931\u8D25",{error:e instanceof Error?e.message:String(e)}),process.exit(1)}})}c(Yt,"registerHeartbeatCommand");import{logger as Ur,saveCredential as Wr,findConflictingCredential as Nr,maskSecret as Gr}from"aitable-workflow-core";function zt(r,t){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 e=>{try{if(!e.token&&!e.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(!e.force){let l=await Nr(e.name,e.serverUrl);l&&(console.error(`\u26A0\uFE0F \u62D2\u7EDD\u8986\u76D6\uFF1AAgent \u540D\u79F0 "${e.name}" \u5DF2\u7ED1\u5B9A\u5230\u53E6\u4E00\u4E2A\u7F51\u5173\u3002`),console.error(` \u65E7\u7F51\u5173: ${l.serverUrl}`),console.error(` \u65B0\u7F51\u5173: ${e.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=e.workspaceRoot?je(e.workspaceRoot,e.name):void 0,o={name:e.name,serverUrl:e.serverUrl,token:e.token??"",key:e.key,workspaceRoot:n,createdAt:new Date().toISOString()};if(await Wr(o),console.log(`\u2705 Agent "${e.name}" \u5DF2\u6CE8\u518C\u5E76\u4FDD\u5B58\u51ED\u8BC1`),console.log(` Server: ${e.serverUrl}`),console.log(` ${e.token?"Token":"Key"}: ${Gr(e.token??e.key??"")}`),n&&console.log(` Workspace: ${n}`),console.log(" \u51ED\u8BC1\u6587\u4EF6: ~/.aitable-workflow/credentials.json"),!e.start){e.foreground&&console.log(`
547
+ `}c(Es,"generatePlist");function W(o){return o.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;")}c(W,"escapeXml");function xe(){let o=process.getuid?.();if(o===void 0)throw new Error("\u65E0\u6CD5\u83B7\u53D6\u7528\u6237 UID\uFF08\u4EC5\u652F\u6301 macOS/Linux\uFF09");return o}c(xe,"getUid");async function fn(o,e){if(!D())throw new Error("\u5F00\u673A\u81EA\u542F\u5F53\u524D\u4EC5\u652F\u6301 macOS");let t=un();mn(t);let n=await As(o),r=Ke(o),s=Z(o);try{X(`launchctl bootout gui/${xe()}/${s} 2>/dev/null`,{encoding:"utf8"})}catch{}await ks(_.dirname(r),{recursive:!0});let i=Es(o,{maxTasks:e?.maxTasks,relayEnv:n,cliEntry:t});await ws(r,i,"utf8"),X(`launchctl bootstrap gui/${xe()} ${r}`,{encoding:"utf8"})}c(fn,"enableAutostart");async function gn(o){if(!D())throw new Error("\u5F00\u673A\u81EA\u542F\u5F53\u524D\u4EC5\u652F\u6301 macOS");let e=Z(o),t=Ke(o);try{X(`launchctl bootout gui/${xe()}/${e} 2>/dev/null`,{encoding:"utf8"})}catch{}await ys(t,{force:!0})}c(gn,"disableAutostart");async function Xe(o){if(!D())throw new Error("\u5F00\u673A\u81EA\u542F\u5F53\u524D\u4EC5\u652F\u6301 macOS");let e=Z(o),t=Ke(o),n=!1;try{await bs(t),n=!0}catch{n=!1}let r=!1,s=!1,i=null;try{let a=X(`launchctl print gui/${xe()}/${e} 2>/dev/null`,{encoding:"utf8"});r=!0;let l=a.match(/pid\s*=\s*(\d+)/);l&&(i=parseInt(l[1],10),s=!0)}catch{r=!1}return{installed:n,loaded:r,running:s,pid:i}}c(Xe,"getAutostartStatus");import{watchFile as Is,statSync as Ts,openSync as _s,readSync as Ps,closeSync as $s}from"fs";import{readFile as vn}from"fs/promises";function wn(o,e){let t=o.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 r=n.agent;if(!r){let a=await B();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");r=a.name}let s=await U({serverUrl:n.serverUrl,token:n.token,key:n.key,workspaceRoot:n.workspaceRoot,name:r,maxTasks:n.maxTasks}),i=await V({agentId:r,serverUrl:s.serverUrl,token:s.token,key:s.key,name:s.name??r,workspaceRoot:s.workspaceRoot,machineId:s.machineId,maxTasks:s.maxTasks});console.log("\u2705 Daemon \u5DF2\u542F\u52A8"),console.log(` Agent: ${r}`),console.log(` PID: ${i.pid}`),console.log(` Log: ~/.aitable-workflow/daemons/${r}/daemon.log`)}catch(r){T.error("cli","start \u5931\u8D25",{error:r instanceof Error?r.message:String(r)}),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 r=await hn(),s=0;for(let i of r)await we(i.name)&&s++;console.log(`\u2705 \u5DF2\u505C\u6B62 ${s} \u4E2A daemon`)}else{let r=n.agent;if(!r){let i=await B();if(!i)throw new Error("\u672A\u6307\u5B9A --agent \u4E14\u65E0\u6D3B\u8DC3 Agent");r=i.name}let s=await we(r);console.log(s?`\u2705 Daemon "${r}" \u5DF2\u505C\u6B62`:`\u26A0\uFE0F Daemon "${r}" \u672A\u5728\u8FD0\u884C`)}}catch(r){T.error("cli","stop \u5931\u8D25",{error:r instanceof Error?r.message:String(r)}),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 r=n.agent;if(!r){let a=await B();if(!a)throw new Error("\u672A\u6307\u5B9A --agent \u4E14\u65E0\u6D3B\u8DC3 Agent");r=a.name}console.log(`\u{1F504} \u6B63\u5728\u91CD\u542F "${r}"...`),await we(r);let s=await U({name:r,maxTasks:n.maxTasks}),i=await V({agentId:r,serverUrl:s.serverUrl,token:s.token,key:s.key,name:s.name??r,workspaceRoot:s.workspaceRoot,machineId:s.machineId,maxTasks:s.maxTasks});console.log(`\u2705 Daemon \u5DF2\u91CD\u542F (PID: ${i.pid})`)}catch(r){T.error("cli","restart \u5931\u8D25",{error:r instanceof Error?r.message:String(r)}),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 r=n.agent;if(!r){let a=await B();if(!a){console.log("\u65E0\u6D3B\u8DC3 Agent");return}r=a.name}let s=await K(r),i=await B();if(console.log(`
548
+ Agent: ${s.agentId}`),console.log(`Running: ${s.running?"\u2705 yes":"\u274C no"}`),s.pid&&console.log(`PID: ${s.pid}`),s.uptimeMs!==null){let a=Math.floor(s.uptimeMs/1e3),l=Math.floor(a/60),d=Math.floor(l/60);console.log(`Uptime: ${d}h ${l%60}m ${a%60}s`)}console.log(`Log file: ${s.logFile}`),n.verbose&&i&&(console.log(`
549
+ --- Configuration ---`),console.log(`Server: ${i.serverUrl}`),console.log(`Token: ${Ss(i.token)}`),i.machineId&&console.log(`MachineID: ${i.machineId}`),i.workspaceRoot&&console.log(`Workspace: ${i.workspaceRoot}`)),console.log("")}catch(r){T.error("cli","status \u5931\u8D25",{error:r instanceof Error?r.message:String(r)}),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 r=n.agent;if(!r){let a=await B();if(!a)throw new Error("\u672A\u6307\u5B9A --agent \u4E14\u65E0\u6D3B\u8DC3 Agent");r=a.name}let s=J(r),i=parseInt(n.n,10)||50;if(n.follow){let a=await vn(s,"utf8").catch(()=>"");if(a){let d=a.trimEnd().split(`
550
+ `);console.log(d.slice(-i).join(`
551
+ `))}let l=a.length;Is(s,{interval:500},()=>{try{let d=Ts(s);if(d.size>l){let p=_s(s,"r"),u=Buffer.alloc(d.size-l);Ps(p,u,0,u.length,l),$s(p),process.stdout.write(u.toString("utf8")),l=d.size}}catch{}})}else{let a=await vn(s,"utf8").catch(()=>"");if(!a){console.log(`\u6682\u65E0\u65E5\u5FD7 (${s})`);return}let l=a.trimEnd().split(`
552
+ `);console.log(l.slice(-i).join(`
553
+ `))}}catch(r){T.error("cli","logs \u5931\u8D25",{error:r instanceof Error?r.message:String(r)}),process.exit(1)}}),t.command("autostart").description("macOS \u5F00\u673A\u81EA\u542F\u7BA1\u7406").addCommand(new Ze("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{D()||(console.error("\u274C \u5F00\u673A\u81EA\u542F\u5F53\u524D\u4EC5\u652F\u6301 macOS"),process.exit(1)),await fn(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(r){T.error("cli","autostart enable \u5931\u8D25",{error:r instanceof Error?r.message:String(r)}),process.exit(1)}})).addCommand(new Ze("disable").description("\u5173\u95ED macOS \u767B\u5F55\u81EA\u542F\u52A8").requiredOption("--agent-id <id>","Agent ID / \u540D\u79F0").action(async n=>{try{D()||(console.error("\u274C \u5F00\u673A\u81EA\u542F\u5F53\u524D\u4EC5\u652F\u6301 macOS"),process.exit(1)),await gn(n.agentId),console.log(`\u2705 \u81EA\u542F\u52A8\u5DF2\u5173\u95ED (${n.agentId})`)}catch(r){T.error("cli","autostart disable \u5931\u8D25",{error:r instanceof Error?r.message:String(r)}),process.exit(1)}})).addCommand(new Ze("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(D()||(console.error("\u274C \u5F00\u673A\u81EA\u542F\u5F53\u524D\u4EC5\u652F\u6301 macOS"),process.exit(1)),n.agentId){let r=await Xe(n.agentId);console.log(`
554
+ Agent: ${n.agentId}`),console.log(`Installed: ${r.installed?"yes":"no"}`),console.log(`Loaded: ${r.loaded?"yes":"no"}`),console.log(`Running: ${r.running?`yes (PID: ${r.pid})`:"no"}`),console.log("")}else{let r=await hn();if(r.length===0){console.log("\u65E0\u5DF2\u6CE8\u518C\u7684 Agent");return}for(let s of r){let i=await Xe(s.name),a=i.running?`running (PID: ${i.pid})`:i.loaded?"loaded":i.installed?"installed":"not installed";console.log(` ${s.name}: ${a}`)}}}catch(r){T.error("cli","autostart status \u5931\u8D25",{error:r instanceof Error?r.message:String(r)}),process.exit(1)}}))}c(wn,"registerDaemonCommands");function yn(o,e){o.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 B();if(!t)throw new Error("\u65E0\u6D3B\u8DC3 Agent");if(!(await K(t.name)).running){console.log("\u26A0\uFE0F Daemon \u672A\u5728\u8FD0\u884C\u3002\u4F7F\u7528 `aitable-workflow daemon start` \u542F\u52A8\u3002");return}let r=await Ce(t.name);console.log("\u2705 Heartbeat OK"),console.log(` Agent: ${t.name}`),console.log(` Connection: ${r.connectionState}`),console.log(` Running: ${r.runningTasks} tasks`),console.log(` Queued: ${r.queuedTasks} tasks`),r.lastHeartbeatAt&&console.log(` Last HB: ${r.lastHeartbeatAt}`)}catch(t){T.error("cli","heartbeat \u5931\u8D25",{error:t instanceof Error?t.message:String(t)}),process.exit(1)}})}c(yn,"registerHeartbeatCommand");import{logger as Ls,saveCredential as Os,findConflictingCredential as js,maskSecret as Ms}from"aitable-workflow-core";function kn(o,e){o.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 js(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?Ye(t.workspaceRoot,t.name):void 0,r={name:t.name,serverUrl:t.serverUrl,token:t.token??"",key:t.key,workspaceRoot:n,createdAt:new Date().toISOString()};if(await Os(r),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"}: ${Ms(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(`
67
555
  \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(`
68
- \u{1F4A1} \u542F\u52A8 daemon: aitable-workflow daemon start \u6216 aitable-workflow relay`);return}if(e.foreground){console.log(`
69
- \u{1F680} \u524D\u53F0\u542F\u52A8 relay\uFF08Ctrl-C \u9000\u51FA\uFF09...`),await fe({serverUrl:e.serverUrl,token:e.token,key:e.key,name:e.name,workspaceRoot:n});return}let i=e.name,s=await F({serverUrl:e.serverUrl,token:e.token,key:e.key,workspaceRoot:e.workspaceRoot,name:i}),a=await V({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(`
70
- \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(`
71
- \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){Ur.error("cli","connect \u5931\u8D25",{error:n instanceof Error?n.message:String(n)}),process.exit(1)}})}c(zt,"registerConnectCommand");import{logger as ye,listCredentials as Hr,setActiveAgent as Jr,getActiveCredential as Xt,readCredentials as Vr,maskSecret as Qt}from"aitable-workflow-core";function Zt(r,t){let e=r.command("agent").description("Agent \u51ED\u8BC1\u7BA1\u7406");e.command("list").description("\u5217\u51FA\u6240\u6709\u5DF2\u4FDD\u5B58\u7684 Agent \u51ED\u8BC1").action(async()=>{try{let n=await Hr();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 Vr();console.log(`
72
- \u5DF2\u4FDD\u5B58 ${n.length} \u4E2A Agent\uFF08\u6D3B\u8DC3: ${o.activeAgent??"\u65E0"}\uFF09:
73
- `);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){ye.error("cli","agent list \u5931\u8D25",{error:n instanceof Error?n.message:String(n)}),process.exit(1)}}),e.command("use <name>").description("\u5207\u6362\u6D3B\u8DC3 Agent").action(async n=>{try{let o=await Jr(n);console.log(`\u2705 \u5DF2\u5207\u6362\u5230 Agent "${o.activeAgent}"`)}catch(o){ye.error("cli","agent use \u5931\u8D25",{error:o instanceof Error?o.message:String(o)}),process.exit(1)}}),e.command("whoami").description("\u663E\u793A\u5F53\u524D\u6D3B\u8DC3 Agent").action(async()=>{try{let n=await Xt();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){ye.error("cli","agent whoami \u5931\u8D25",{error:n instanceof Error?n.message:String(n)}),process.exit(1)}}),e.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 Xt();if(!o){console.log("\u65E0\u6D3B\u8DC3 Agent\u3002\u4F7F\u7528 `aitable-workflow connect` \u6CE8\u518C\u3002");return}let i=await q(o.name),s=await he(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)+`
556
+ \u{1F4A1} \u542F\u52A8 daemon: aitable-workflow daemon start \u6216 aitable-workflow relay`);return}if(t.foreground){console.log(`
557
+ \u{1F680} \u524D\u53F0\u542F\u52A8 relay\uFF08Ctrl-C \u9000\u51FA\uFF09...`),await Re({serverUrl:t.serverUrl,token:t.token,key:t.key,name:t.name,workspaceRoot:n});return}let s=t.name,i=await U({serverUrl:t.serverUrl,token:t.token,key:t.key,workspaceRoot:t.workspaceRoot,name:s}),a=await V({agentId:s,serverUrl:i.serverUrl,token:i.token,key:i.key,name:i.name??s,workspaceRoot:i.workspaceRoot,machineId:i.machineId,maxTasks:i.maxTasks});console.log(`
558
+ \u{1F680} Daemon \u5DF2\u540E\u53F0\u542F\u52A8`),console.log(` Agent: ${s}`),console.log(` PID: ${a.pid}`),console.log(` Log: ~/.aitable-workflow/daemons/${s}/daemon.log`),console.log(`
559
+ \u{1F4CB} \u5E38\u7528\u547D\u4EE4\uFF1A`),console.log(` \u67E5\u770B\u72B6\u6001: aitable-workflow daemon status --agent ${s}`),console.log(` \u8DDF\u8E2A\u65E5\u5FD7: aitable-workflow daemon logs -f --agent ${s}`),console.log(` \u505C\u6B62: aitable-workflow daemon stop --agent ${s}`),console.log(` \u91CD\u542F: aitable-workflow daemon restart --agent ${s}`),console.log(" \u5217\u51FA Agent: aitable-workflow agent list"),console.log(" \u5207\u6362 Agent: aitable-workflow agent use <name>"),console.log(` \u5F00\u673A\u81EA\u542F: aitable-workflow daemon autostart enable --agent-id ${s}`)}catch(n){Ls.error("cli","connect \u5931\u8D25",{error:n instanceof Error?n.message:String(n)}),process.exit(1)}})}c(kn,"registerConnectCommand");import{logger as Ae,listCredentials as Ds,setActiveAgent as Bs,getActiveCredential as bn,readCredentials as Hs,maskSecret as Rn}from"aitable-workflow-core";function Cn(o,e){let t=o.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 Ds();if(n.length===0){console.log("\u6682\u65E0\u5DF2\u4FDD\u5B58\u7684 Agent\u3002\u4F7F\u7528 `aitable-workflow connect` \u6CE8\u518C\u3002");return}let r=await Hs();console.log(`
560
+ \u5DF2\u4FDD\u5B58 ${n.length} \u4E2A Agent\uFF08\u6D3B\u8DC3: ${r.activeAgent??"\u65E0"}\uFF09:
561
+ `);for(let s of n){let i=s.name===r.activeAgent?" \u2190 active":"";console.log(` \u2022 ${s.name}${i}`),console.log(` Server: ${s.serverUrl}`),console.log(` Token: ${Rn(s.token)}`),s.machineId&&console.log(` MachineID: ${s.machineId}`),s.workspaceRoot&&console.log(` Workspace: ${s.workspaceRoot}`),console.log(` Created: ${s.createdAt}`)}console.log("")}catch(n){Ae.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 r=await Bs(n);console.log(`\u2705 \u5DF2\u5207\u6362\u5230 Agent "${r.activeAgent}"`)}catch(r){Ae.error("cli","agent use \u5931\u8D25",{error:r instanceof Error?r.message:String(r)}),process.exit(1)}}),t.command("whoami").description("\u663E\u793A\u5F53\u524D\u6D3B\u8DC3 Agent").action(async()=>{try{let n=await bn();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: ${Rn(n.token)}`),n.machineId&&console.log(`MachineID: ${n.machineId}`),n.workspaceRoot&&console.log(`Workspace: ${n.workspaceRoot}`)}catch(n){Ae.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 r=await bn();if(!r){console.log("\u65E0\u6D3B\u8DC3 Agent\u3002\u4F7F\u7528 `aitable-workflow connect` \u6CE8\u518C\u3002");return}let s=await K(r.name),i=await Ce(r.name),a={agent:r.name,serverUrl:r.serverUrl,connectionState:s.running?i.connectionState:"stopped",machineId:i.machineId??r.machineId??null,lastHeartbeatAt:i.lastHeartbeatAt,runningTasks:i.runningTasks,queuedTasks:i.queuedTasks,lastDisconnectReason:i.lastDisconnectReason,pid:s.pid};if(n.json){process.stdout.write(JSON.stringify(a,null,2)+`
74
562
  `);return}let l=a.connectionState==="connected"?"\u{1F7E2}":a.connectionState==="reconnecting"?"\u{1F7E1}":"\u{1F534}";console.log(`
75
- ${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){ye.error("cli","agent status \u5931\u8D25",{error:o instanceof Error?o.message:String(o)}),process.exit(1)}})}c(Zt,"registerAgentCommands");import{logger as qr}from"aitable-workflow-core";function en(r,t){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(e=>{try{fe(e)}catch(n){qr.error("cli","relay \u542F\u52A8\u5931\u8D25",{error:n instanceof Error?n.message:String(n)}),process.exit(1)}})}c(en,"registerRelayCommand");import{loadSettings as tn,loadWorkflowTemplate as Kr,checkWorkflowRecipes as Yr,Tracer as zr}from"aitable-workflow-core";import Xr from"path";function nn(r,t){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",t.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(e,n)=>{try{if(n.recipes||n.validate){await Qr(n);return}let o=await tn(n.config),i=Xr.resolve(o.configDir,o.agent.trace_dir),s=new zr(i),a=parseInt(n.limit,10)||10,l;if(n.latest||!e){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(`
563
+ ${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}`),s.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(r){Ae.error("cli","agent status \u5931\u8D25",{error:r instanceof Error?r.message:String(r)}),process.exit(1)}})}c(Cn,"registerAgentCommands");import{logger as Fs}from"aitable-workflow-core";function xn(o,e){o.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").option("--trace-http-port <port>","\u542F\u7528\u672C\u5730\u53EA\u8BFB trace HTTP \u670D\u52A1\u7AEF\u53E3\uFF08\u4E5F\u53EF\u7528 AITABLE_RELAY_TRACE_HTTP_PORT\uFF09").option("--trace-http-host <host>","\u672C\u5730 trace HTTP \u76D1\u542C\u5730\u5740\uFF0C\u9ED8\u8BA4 127.0.0.1\uFF08\u4E5F\u53EF\u7528 AITABLE_RELAY_TRACE_HTTP_HOST\uFF09").option("--trace-buffer-size <n>","\u672C\u5730 trace \u4FDD\u7559\u6700\u8FD1 run \u6570\uFF0C\u9ED8\u8BA4 20\uFF08\u4E5F\u53EF\u7528 AITABLE_RELAY_TRACE_BUFFER_SIZE\uFF09").option("--trace-events-per-run <n>","\u6BCF\u4E2A run \u4FDD\u7559\u6700\u8FD1 agent event \u6570\uFF0C\u9ED8\u8BA4 500\uFF08\u4E5F\u53EF\u7528 AITABLE_RELAY_TRACE_EVENTS_PER_RUN\uFF09").option("--trace-chat","\u5728\u672C\u673A trace HTTP \u670D\u52A1\u4E0A\u5F00\u542F Local Chat \u5199\u63A5\u53E3\uFF08Task D\uFF0C\u9ED8\u8BA4\u5173\uFF1B\u4E5F\u53EF\u7528 AITABLE_RELAY_TRACE_CHAT=1\uFF09").action(t=>{try{Re(t)}catch(n){Fs.error("cli","relay \u542F\u52A8\u5931\u8D25",{error:n instanceof Error?n.message:String(n)}),process.exit(1)}})}c(xn,"registerRelayCommand");import{loadSettings as An,loadWorkflowTemplate as Ns,checkWorkflowRecipes as Us,Tracer as Ws}from"aitable-workflow-core";import Gs from"path";function En(o,e){o.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 qs(n);return}let r=await An(n.config),s=Gs.resolve(r.configDir,r.agent.trace_dir),i=new Ws(s),a=parseInt(n.limit,10)||10,l;if(n.latest||!t){if(l=await i.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(`
76
564
  \u{1F4C4} \u6700\u8FD1 ${l.length} \u6761\u6267\u884C\u8BB0\u5F55:
77
- `)}else{if(l=await s.getTraces(e),l.length===0){console.log(`\u26A0\uFE0F \u672A\u627E\u5230\u5DE5\u5355 ${e} \u7684 trace \u8BB0\u5F55\u3002`);return}n.step&&(l=l.filter(p=>p.step_id===n.step)),console.log(`
78
- \u{1F4C4} \u5DE5\u5355 ${e} \u7684\u6267\u884C\u5386\u53F2 (${l.length} \u6B65):
79
- `)}for(let p of l){let m=p.status==="success"?"\u2705":p.status==="failed"?"\u274C":"\u23F8\uFE0F",u=(p.duration_ms/1e3).toFixed(1);console.log(`${m} [${p.step_id}] ${p.step_name} \u2014 ${u}s \u2014 ${p.status.toUpperCase()}`);for(let[g,d]of p.llm_calls.entries()){let v=g===p.llm_calls.length-1,I=v?" \u2514\u2500":" \u251C\u2500",E=v?" ":" \u2502 ",z=(d.duration_ms/1e3).toFixed(1);console.log(`${I} LLM: ${d.model} (${z}s)`),console.log(`${E}Input: ${d.prompt_summary.slice(0,80)}${d.prompt_summary.length>80?"...":""}`),console.log(`${E}Output: ${d.response_summary.slice(0,100)}${d.response_summary.length>100?"...":""}`)}if(Object.keys(p.outputs).length>0){let g=Object.entries(p.outputs).map(([d,v])=>`${d}=${typeof v=="string"?v.slice(0,50):JSON.stringify(v)}`).join(", ");console.log(` \u2514\u2500 Outputs: ${g}`)}p.error&&console.log(` \u2514\u2500 Error: ${p.error}`),console.log()}}catch(o){console.error(`\u2717 inspect \u5931\u8D25: ${o instanceof Error?o.message:String(o)}`),process.exit(1)}})}c(nn,"registerInspectCommand");async function Qr(r){let t=await tn(r.config),e=r.workflow?t.workflowEntries.find(s=>s.id===r.workflow):t.workflowEntries[0];e||(console.error(`\u2717 \u672A\u627E\u5230\u5DE5\u4F5C\u6D41\u300C${r.workflow}\u300D\u3002\u53EF\u7528\uFF1A${t.workflowEntries.map(s=>s.id).join(", ")}`),process.exit(1));let n=await Kr(e.templatePath,{envSource:t.envSource}),{issues:o,rows:i}=await Yr(e.recipeDir,n);if(r.recipes){console.log(`
80
- \u{1F4CB} \u5DE5\u4F5C\u6D41\u300C${n.meta.name}\u300D(${e.id}) \u7684 recipe schema:
81
- `);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(`
82
- \u2705 \u5DE5\u4F5C\u6D41\u300C${n.meta.name}\u300D(${e.id}) \u5168\u90E8\u6B65\u9AA4\u6821\u9A8C\u901A\u8FC7
83
- `);else{let s=o.filter(l=>l.level==="error"),a=o.filter(l=>l.level==="warn");console.log(`
84
- \u6821\u9A8C\u7ED3\u679C\uFF1A${s.length} \u4E2A\u9519\u8BEF\uFF0C${a.length} \u4E2A\u8B66\u544A
85
- `);for(let l of o){let p=l.level==="error"?"\u274C":"\u26A0\uFE0F ";console.log(` ${p} [${l.stepId} \u2192 ${l.recipeId}] ${l.message}`)}console.log(),s.length>0&&process.exit(1)}}c(Qr,"runRecipeInspect");import{runKbCompileCommand as Zr,runKbUpdateCommand as ei,runKbStatusCommand as ti,runKbIngestCommand as ni,runKbCleanupCommand as oi}from"aitable-workflow-core";function on(r,t){let e=r.command("kb").description("\u77E5\u8BC6\u5E93(LLM-Wiki)\u7F16\u8BD1\u4E0E\u72B6\u6001\u7BA1\u7406");e.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",t.defaultConfig).option("--full","\u5F3A\u5236\u5168\u91CF\u91CD\u7F16\u8BD1").action(async(n,o)=>{try{await Zr(n,o)}catch(i){console.error(`\u2717 kb compile \u5931\u8D25: ${i instanceof Error?i.message:String(i)}`),process.exit(1)}}),e.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",t.defaultConfig).action(async(n,o)=>{try{await ei(n,o)}catch(i){console.error(`\u2717 kb update \u5931\u8D25: ${i instanceof Error?i.message:String(i)}`),process.exit(1)}}),e.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",t.defaultConfig).action(async(n,o)=>{try{await ti(n,o)}catch(i){console.error(`\u2717 kb status \u5931\u8D25: ${i instanceof Error?i.message:String(i)}`),process.exit(1)}}),e.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",t.defaultConfig).option("--timeout <ms>","\u5355\u6587\u6863\u8BF7\u6C42\u8D85\u65F6\uFF08\u6BEB\u79D2\uFF09").action(async(n,o)=>{try{await ni(n,o)}catch(i){console.error(`\u2717 kb ingest \u5931\u8D25: ${i instanceof Error?i.message:String(i)}`),process.exit(1)}}),e.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",t.defaultConfig).action(async(n,o)=>{try{await oi(n,o)}catch(i){console.error(`\u2717 kb cleanup \u5931\u8D25: ${i instanceof Error?i.message:String(i)}`),process.exit(1)}})}c(on,"registerKbCommands");import Be from"path";import{BotProvisioner as ri,BotProvisionError as cn,DwsDevRunner as Fe,buildBotApprovalReportLines as ii,defaultProvisionStatePath as Ue,groupEntriesOf as si,loadProvisionState as ln,resolveConfigPath as We,validateProvisionName as ai}from"aitable-workflow-core";import{logger as rn}from"aitable-workflow-core";function sn(r){for(let t of r){let e=t.title?`\u300C${t.title}\u300D${t.openConversationId}`:t.openConversationId;t.outcome==="added"?console.log(`
86
- \u2705 \u7FA4 ${e}\uFF1A\u672C\u6B21\u5DF2\u771F\u5B9E\u8C03\u7528 add-bot \u5165\u7FA4${t.robotName?`\uFF08\u673A\u5668\u4EBA\u663E\u793A\u540D=${t.robotName}\uFF09`:""}\u3002`):t.source==="server"?console.log(`
87
- \u2139\uFE0F \u7FA4 ${e}\uFF1A\u670D\u52A1\u7AEF\u786E\u8BA4\u8BE5\u7FA4\u5DF2\u5B89\u88C5\u6B64\u673A\u5668\u4EBA\uFF08500043\uFF09\uFF0C\u89C6\u540C\u5165\u7FA4\u6210\u529F\u3002`):(console.log(`
88
- \u2139\uFE0F \u7FA4 ${e}\uFF1A\u5DF2\u5728\u7FA4\u53F0\u8D26\uFF08addedAt=${t.addedAt??"?"}\uFF09\uFF0C\u672C\u6B21\u672A\u53D1\u8D77\u4EFB\u4F55 API \u8C03\u7528\u3002`),console.log(" \u6CE8\u610F\uFF1A\u82E5\u673A\u5668\u4EBA\u66FE\u88AB\u624B\u52A8\u79FB\u51FA\u7FA4\uFF0C\u91CD\u8DD1\u672C\u547D\u4EE4\u4E0D\u4F1A\u91CD\u65B0\u6DFB\u52A0\uFF1B\u4EE5\u7FA4\u8BBE\u7F6E\u9875\u6216\u7FA4\u91CC @ \u5B9E\u6D4B\u4E3A\u51C6\u3002"))}}c(sn,"printGroupOutcomes");function pn(r,t,e={}){let n=e.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("--group <group>","\u62C9\u7FA4\u76EE\u6807\uFF1AopenConversationId \u6216\u7FA4\u540D\uFF0C\u9017\u53F7\u5206\u9694\u591A\u7FA4\uFF08\u9700\u5DF2\u5B8C\u6210 publish \u76F8\uFF1B\u5DF2\u5728\u7FA4\u53F0\u8D26\u7684\u7FA4\u96F6\u8C03\u7528\u8DF3\u8FC7\uFF09").option("--publish","\u8FDB\u5165\u53D1\u5E03\u76F8\uFF08\u771F\u5B9E\u6253\u6270\u7BA1\u7406\u5458\u5BA1\u6279\uFF0C\u9700\u914D\u5408 --approver-user-id \u786E\u8BA4\uFF09").option("--approver-user-id <userId>","\u5BA1\u6279\u4EBA userId\uFF08\u5019\u9009\u7531 check-approval \u5217\u51FA\uFF1B\u4EBA\u5BA1\u95E8\u4E0D\u5F97\u9759\u9ED8\u4EE3\u9009\uFF09").option("--state-file <path>","\u72B6\u6001\u6587\u4EF6\u8DEF\u5F84\uFF08\u7F3A\u7701 <configDir>/.aitable/provision-state.json\uFF09").option("-c, --config <path>","\u914D\u7F6E\u6587\u4EF6\u8DEF\u5F84\uFF08\u7528\u4E8E\u5B9A\u4F4D configDir\uFF09",t.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 ci(i,t,e);s!==0&&n(s)}catch(s){Me(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",t.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 pi(i,t,e);s!==0&&n(s)}catch(s){Me(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",t.defaultConfig).action(async a=>{try{let l=await mi(i,a,t,e);l!==0&&n(l)}catch(l){Me(l),n(1)}})}c(pn,"registerBotCommands");async function ci(r,t,e){let n=ai(r.name);if(n)return console.error(`\u274C ${n}`),1;let o=Be.dirname(await We(r.config??t.defaultConfig)),i=r.stateFile??Ue(o);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 s=e.createProvisioner?.()??new ri({runner:new Fe}),a={name:r.name,robotName:r.robotName,desc:r.desc,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 l=await s.provision(a);return li(l,{stateFile:i})}c(ci,"runProvision");function li(r,t){switch(r.status){case"bound":{console.log(`
89
- \u2705 \u51ED\u636E\u5DF2\u7ED1\u5B9A\uFF08bound \u76F8\uFF09\u3002`),console.log(` appKey=${r.state.clientId??"?"}`),console.log(` AppSecret \u4E0D\u56DE\u663E\uFF0C\u590D\u53D6: dws dev app credentials get --unified-app-id ${r.state.unifiedAppId??"<unifiedAppId>"}`),console.log(" \u51ED\u636E\u843D\u6CD5\u4E8C\u9009\u4E00\uFF08\u4E0D\u8981\u4E24\u5904\u90FD\u5199\uFF09\uFF1A"),console.log(" \xB7 \u5355\u4E00\u673A\u5668\u4EBA \u2192 \u5199\u5165 `.env`\uFF0C\u914D\u7F6E\u91CC\u7528 `${env.X}` \u5F15\u7528\uFF1B"),console.log(" \xB7 \u591A\u7FA4/\u591A\u673A\u5668\u4EBA/\u9700\u8FD0\u8425\u81EA\u7EF4\u62A4 \u2192 \u5199\u5165 AI \u8868\u683C\u7FA4\u914D\u7F6E\u8868\uFF0C\u7531 config-sync \u53D1\u5E03\u6210 `globalVar.robot_creds`\u3002"),console.log(" \u72B6\u6001\u6587\u4EF6:",t.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(`
565
+ `)}else{if(l=await i.getTraces(t),l.length===0){console.log(`\u26A0\uFE0F \u672A\u627E\u5230\u5DE5\u5355 ${t} \u7684 trace \u8BB0\u5F55\u3002`);return}n.step&&(l=l.filter(d=>d.step_id===n.step)),console.log(`
566
+ \u{1F4C4} \u5DE5\u5355 ${t} \u7684\u6267\u884C\u5386\u53F2 (${l.length} \u6B65):
567
+ `)}for(let d of l){let p=d.status==="success"?"\u2705":d.status==="failed"?"\u274C":"\u23F8\uFE0F",u=(d.duration_ms/1e3).toFixed(1);console.log(`${p} [${d.step_id}] ${d.step_name} \u2014 ${u}s \u2014 ${d.status.toUpperCase()}`);for(let[m,f]of d.llm_calls.entries()){let R=m===d.llm_calls.length-1,S=R?" \u2514\u2500":" \u251C\u2500",E=R?" ":" \u2502 ",H=(f.duration_ms/1e3).toFixed(1);console.log(`${S} LLM: ${f.model} (${H}s)`),console.log(`${E}Input: ${f.prompt_summary.slice(0,80)}${f.prompt_summary.length>80?"...":""}`),console.log(`${E}Output: ${f.response_summary.slice(0,100)}${f.response_summary.length>100?"...":""}`)}if(Object.keys(d.outputs).length>0){let m=Object.entries(d.outputs).map(([f,R])=>`${f}=${typeof R=="string"?R.slice(0,50):JSON.stringify(R)}`).join(", ");console.log(` \u2514\u2500 Outputs: ${m}`)}d.error&&console.log(` \u2514\u2500 Error: ${d.error}`),console.log()}}catch(r){console.error(`\u2717 inspect \u5931\u8D25: ${r instanceof Error?r.message:String(r)}`),process.exit(1)}})}c(En,"registerInspectCommand");async function qs(o){let e=await An(o.config),t=o.workflow?e.workflowEntries.find(i=>i.id===o.workflow):e.workflowEntries[0];t||(console.error(`\u2717 \u672A\u627E\u5230\u5DE5\u4F5C\u6D41\u300C${o.workflow}\u300D\u3002\u53EF\u7528\uFF1A${e.workflowEntries.map(i=>i.id).join(", ")}`),process.exit(1));let n=await Ns(t.templatePath,{envSource:e.envSource}),{issues:r,rows:s}=await Us(t.recipeDir,n);if(o.recipes){console.log(`
568
+ \u{1F4CB} \u5DE5\u4F5C\u6D41\u300C${n.meta.name}\u300D(${t.id}) \u7684 recipe schema:
569
+ `);for(let i of s){let a=i.configSummary.length>0?i.configSummary.join(", "):"(none)",l=i.loaded?"":" \u26A0 \u52A0\u8F7D\u5931\u8D25";console.log(` [${i.stepId} \u2192 ${i.recipeId}]${l}`),console.log(` config: ${a}`),console.log()}}if(o.validate)if(r.length===0)console.log(`
570
+ \u2705 \u5DE5\u4F5C\u6D41\u300C${n.meta.name}\u300D(${t.id}) \u5168\u90E8\u6B65\u9AA4\u6821\u9A8C\u901A\u8FC7
571
+ `);else{let i=r.filter(l=>l.level==="error"),a=r.filter(l=>l.level==="warn");console.log(`
572
+ \u6821\u9A8C\u7ED3\u679C\uFF1A${i.length} \u4E2A\u9519\u8BEF\uFF0C${a.length} \u4E2A\u8B66\u544A
573
+ `);for(let l of r){let d=l.level==="error"?"\u274C":"\u26A0\uFE0F ";console.log(` ${d} [${l.stepId} \u2192 ${l.recipeId}] ${l.message}`)}console.log(),i.length>0&&process.exit(1)}}c(qs,"runRecipeInspect");import{runKbCompileCommand as zs,runKbUpdateCommand as Js,runKbStatusCommand as Ys,runKbIngestCommand as Vs,runKbCleanupCommand as Ks}from"aitable-workflow-core";function Sn(o,e){let t=o.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,r)=>{try{await zs(n,r)}catch(s){console.error(`\u2717 kb compile \u5931\u8D25: ${s instanceof Error?s.message:String(s)}`),process.exit(1)}}),t.command("update [collections...]").description("\u6E90\u6587\u6863\u53D8\u66F4\u540E\u89E6\u53D1\u589E\u91CF\u7F16\u8BD1\uFF08\u672A\u53D8\u66F4\u5219\u8DF3\u8FC7\uFF09").option("-c, --config <path>","\u914D\u7F6E\u6587\u4EF6\u8DEF\u5F84",e.defaultConfig).action(async(n,r)=>{try{await Js(n,r)}catch(s){console.error(`\u2717 kb update \u5931\u8D25: ${s instanceof Error?s.message:String(s)}`),process.exit(1)}}),t.command("status [collections...]").description("\u67E5\u770B\u77E5\u8BC6\u5E93\u7F16\u8BD1\u72B6\u6001\uFF08\u7F16\u8BD1\u4E2D/\u5B8C\u6210/\u5931\u8D25 + \u6E90\u662F\u5426\u5DF2\u53D8\u66F4\uFF09").option("-c, --config <path>","\u914D\u7F6E\u6587\u4EF6\u8DEF\u5F84",e.defaultConfig).action(async(n,r)=>{try{await Ys(n,r)}catch(s){console.error(`\u2717 kb status \u5931\u8D25: ${s instanceof Error?s.message:String(s)}`),process.exit(1)}}),t.command("ingest <url-or-path>").description("\u5BFC\u5165\u6587\u6863\u5230 wiki \u76EE\u5F55\uFF08\u652F\u6301\u9489\u9489 URL \u6216\u672C\u5730\u8DEF\u5F84\uFF0Cdocx/pdf \u81EA\u52A8\u8F6C md\uFF09").option("-o, --output <dir>","\u8F93\u51FA\u76EE\u5F55\uFF08\u9ED8\u8BA4 ./wiki\uFF09").option("-t, --type <type>","\u6E90\u7C7B\u578B: dingtalk-doc\uFF08\u4E0D\u4F20\u5219\u81EA\u52A8\u8BC6\u522B\uFF09").option("--flat","\u4E0D\u4FDD\u7559\u8FDC\u7AEF\u76EE\u5F55\u7ED3\u6784\uFF08\u6240\u6709\u6587\u6863\u5E73\u94FA\u5230\u8F93\u51FA\u76EE\u5F55\uFF09").option("--force","\u5F3A\u5236\u91CD\u65B0\u62C9\u53D6\u6240\u6709\u6587\u6863\uFF08\u5FFD\u7565\u589E\u91CF\u5224\u65AD\uFF09").option("--compile","\u5BFC\u5165\u540E\u81EA\u52A8\u89E6\u53D1 kb compile").option("-c, --config <path>","\u914D\u7F6E\u6587\u4EF6\u8DEF\u5F84",e.defaultConfig).option("--timeout <ms>","\u5355\u6587\u6863\u8BF7\u6C42\u8D85\u65F6\uFF08\u6BEB\u79D2\uFF09").action(async(n,r)=>{try{await Vs(n,r)}catch(s){console.error(`\u2717 kb ingest \u5931\u8D25: ${s instanceof Error?s.message:String(s)}`),process.exit(1)}}),t.command("cleanup <collection>").description("\u6E05\u7406\u77E5\u8BC6\u5E93\u4E2D\u7684\u5B64\u513F\u6587\u7AE0\uFF08\u6E90\u884C\u5DF2\u5220\u4F46 articles/ \u8FD8\u5728\uFF09").option("-c, --config <path>","\u914D\u7F6E\u6587\u4EF6\u8DEF\u5F84",e.defaultConfig).action(async(n,r)=>{try{await Ks(n,r)}catch(s){console.error(`\u2717 kb cleanup \u5931\u8D25: ${s instanceof Error?s.message:String(s)}`),process.exit(1)}})}c(Sn,"registerKbCommands");import et from"path";import{BotProvisioner as Xs,BotProvisionError as Pn,DwsDevRunner as tt,buildBotApprovalReportLines as Zs,defaultProvisionStatePath as nt,groupEntriesOf as Qs,loadProvisionState as $n,resolveConfigPath as rt,validateProvisionName as ei}from"aitable-workflow-core";import{logger as In}from"aitable-workflow-core";function Tn(o){for(let e of o){let t=e.title?`\u300C${e.title}\u300D${e.openConversationId}`:e.openConversationId;e.outcome==="added"?console.log(`
574
+ \u2705 \u7FA4 ${t}\uFF1A\u672C\u6B21\u5DF2\u771F\u5B9E\u8C03\u7528 add-bot \u5165\u7FA4${e.robotName?`\uFF08\u673A\u5668\u4EBA\u663E\u793A\u540D=${e.robotName}\uFF09`:""}\u3002`):e.source==="server"?console.log(`
575
+ \u2139\uFE0F \u7FA4 ${t}\uFF1A\u670D\u52A1\u7AEF\u786E\u8BA4\u8BE5\u7FA4\u5DF2\u5B89\u88C5\u6B64\u673A\u5668\u4EBA\uFF08500043\uFF09\uFF0C\u89C6\u540C\u5165\u7FA4\u6210\u529F\u3002`):(console.log(`
576
+ \u2139\uFE0F \u7FA4 ${t}\uFF1A\u5DF2\u5728\u7FA4\u53F0\u8D26\uFF08addedAt=${e.addedAt??"?"}\uFF09\uFF0C\u672C\u6B21\u672A\u53D1\u8D77\u4EFB\u4F55 API \u8C03\u7528\u3002`),console.log(" \u6CE8\u610F\uFF1A\u82E5\u673A\u5668\u4EBA\u66FE\u88AB\u624B\u52A8\u79FB\u51FA\u7FA4\uFF0C\u91CD\u8DD1\u672C\u547D\u4EE4\u4E0D\u4F1A\u91CD\u65B0\u6DFB\u52A0\uFF1B\u4EE5\u7FA4\u8BBE\u7F6E\u9875\u6216\u7FA4\u91CC @ \u5B9E\u6D4B\u4E3A\u51C6\u3002"))}}c(Tn,"printGroupOutcomes");function Ln(o,e,t={}){let n=t.exit??(s=>process.exit(s)),r=o.command("bot").description("\u9489\u9489\u673A\u5668\u4EBA provisioning\uFF08\u5EFA\u53F7 / \u51ED\u636E\u7ED1\u5B9A / \u53D1\u5E03\u5BA1\u6279 / \u62C9\u7FA4\uFF09");r.command("provision").description("\u786E\u5B9A\u6027\u5EFA\u53F7\u5E76\u7ED1\u5B9A\u51ED\u636E\uFF08\u5E42\u7B49\u3001\u53EF\u65AD\u70B9\u7EED\u8DD1\uFF1B--publish/--group \u8D70\u4EBA\u5BA1\u4E0E\u62C9\u7FA4\u76F8\uFF09").requiredOption("--name <name>","\u5E94\u7528\u540D\uFF08\u4F01\u4E1A\u5185\u552F\u4E00\uFF0C2-20 \u5B57\uFF09").option("--robot-name <robotName>","\u673A\u5668\u4EBA\u663E\u793A\u540D\uFF08\u7F3A\u7701\u540C --name\uFF09").option("--desc <desc>","\u5E94\u7528\u63CF\u8FF0\uFF08\u2264200 \u5B57\uFF09").option("--group <group>","\u62C9\u7FA4\u76EE\u6807\uFF1AopenConversationId \u6216\u7FA4\u540D\uFF0C\u9017\u53F7\u5206\u9694\u591A\u7FA4\uFF08\u9700\u5DF2\u5B8C\u6210 publish \u76F8\uFF1B\u5DF2\u5728\u7FA4\u53F0\u8D26\u7684\u7FA4\u96F6\u8C03\u7528\u8DF3\u8FC7\uFF09").option("--publish","\u8FDB\u5165\u53D1\u5E03\u76F8\uFF08\u771F\u5B9E\u6253\u6270\u7BA1\u7406\u5458\u5BA1\u6279\uFF0C\u9700\u914D\u5408 --approver-user-id \u786E\u8BA4\uFF09").option("--approver-user-id <userId>","\u5BA1\u6279\u4EBA userId\uFF08\u5019\u9009\u7531 check-approval \u5217\u51FA\uFF1B\u4EBA\u5BA1\u95E8\u4E0D\u5F97\u9759\u9ED8\u4EE3\u9009\uFF09").option("--state-file <path>","\u72B6\u6001\u6587\u4EF6\u8DEF\u5F84\uFF08\u7F3A\u7701 <configDir>/.aitable/provision-state.json\uFF09").option("-c, --config <path>","\u914D\u7F6E\u6587\u4EF6\u8DEF\u5F84\uFF08\u7528\u4E8E\u5B9A\u4F4D configDir\uFF09",e.defaultConfig).option("--yes","\u4E0E dws \u8BED\u4E49\u5BF9\u9F50\uFF1A\u8DF3\u8FC7\u786E\u8BA4\uFF08provision \u5168\u7A0B\u975E\u4EA4\u4E92\uFF0C\u5199\u64CD\u4F5C\u5DF2\u5E26 --yes\uFF09").action(async s=>{try{let i=await ti(s,e,t);i!==0&&n(i)}catch(i){Qe(i),n(1)}}),r.command("status").description("\u67E5\u770B provision \u76F8\u4F4D / \u53D1\u5E03\u5BA1\u6279\u72B6\u6001 / \u5BA1\u6279\u4EBA\u5019\u9009\u4E0E\u50AC\u529E\u547D\u4EE4\u6A21\u677F").option("--state-file <path>","\u72B6\u6001\u6587\u4EF6\u8DEF\u5F84\uFF08\u7F3A\u7701 <configDir>/.aitable/provision-state.json\uFF09").option("-c, --config <path>","\u914D\u7F6E\u6587\u4EF6\u8DEF\u5F84\uFF08\u7528\u4E8E\u5B9A\u4F4D configDir\uFF09",e.defaultConfig).option("--refresh","\u5B9E\u65F6\u67E5\u8BE2 dws\uFF08version status + check-approval\uFF09\uFF0C\u800C\u975E\u53EA\u8BFB\u72B6\u6001\u6587\u4EF6").action(async s=>{try{let i=await ri(s,e,t);i!==0&&n(i)}catch(i){Qe(i),n(1)}});for(let[s,i]of[["disable","\u505C\u7528"],["enable","\u542F\u7528"]])r.command(s).description(`${i}\u673A\u5668\u4EBA\u80FD\u529B\u6216\u6574\u4E2A\u5E94\u7528\uFF08\u53EF\u9006\uFF1B--scope app \u4F5C\u7528\u4E8E\u6574\u4E2A\u5E94\u7528\uFF09`).option("--scope <scope>","\u4F5C\u7528\u8303\u56F4\uFF1Arobot\uFF08\u9ED8\u8BA4\uFF0C\u4EC5\u673A\u5668\u4EBA\u80FD\u529B\uFF09| app\uFF08\u6574\u4E2A\u5E94\u7528\uFF09","robot").option("--unified-app-id <id>","\u76EE\u6807\u5E94\u7528 unifiedAppId\uFF08\u7F3A\u7701\u4ECE\u72B6\u6001\u6587\u4EF6\u8BFB\uFF09").option("--state-file <path>","\u72B6\u6001\u6587\u4EF6\u8DEF\u5F84\uFF08\u7F3A\u7701 <configDir>/.aitable/provision-state.json\uFF09").option("-c, --config <path>","\u914D\u7F6E\u6587\u4EF6\u8DEF\u5F84\uFF08\u7528\u4E8E\u5B9A\u4F4D configDir\uFF09",e.defaultConfig).action(async a=>{try{let l=await oi(s,a,e,t);l!==0&&n(l)}catch(l){Qe(l),n(1)}})}c(Ln,"registerBotCommands");async function ti(o,e,t){let n=ei(o.name);if(n)return console.error(`\u274C ${n}`),1;let r=et.dirname(await rt(o.config??e.defaultConfig)),s=o.stateFile??nt(r);o.publish&&!o.approverUserId&&console.log("\u2139 --publish \u672A\u6307\u5B9A --approver-user-id\uFF1A\u82E5\u7EC4\u7EC7\u5BA1\u6279\u7B56\u7565\u9700\u9009\u4EBA\uFF0C\u5C06\u5217\u51FA\u5019\u9009\u540E\u505C\u4E0B\uFF0C\u7531\u4F60\u663E\u5F0F\u786E\u8BA4\u3002");let i=t.createProvisioner?.()??new Xs({runner:new tt}),a={name:o.name,robotName:o.robotName,desc:o.desc,stateFile:s,publish:o.publish,approverUserId:o.approverUserId,group:o.group};console.log(`\u{1F916} \u5F00\u59CB provision\u300C${o.name}\u300D\uFF08\u72B6\u6001\u6587\u4EF6: ${s}\uFF09`);let l=await i.provision(a);return ni(l,{stateFile:s})}c(ti,"runProvision");function ni(o,e){switch(o.status){case"bound":{console.log(`
577
+ \u2705 \u51ED\u636E\u5DF2\u7ED1\u5B9A\uFF08bound \u76F8\uFF09\u3002`),console.log(` appKey=${o.state.clientId??"?"}`),console.log(` AppSecret \u4E0D\u56DE\u663E\uFF0C\u590D\u53D6: dws dev app credentials get --unified-app-id ${o.state.unifiedAppId??"<unifiedAppId>"}`),console.log(" \u51ED\u636E\u843D\u6CD5\u4E8C\u9009\u4E00\uFF08\u4E0D\u8981\u4E24\u5904\u90FD\u5199\uFF09\uFF1A"),console.log(" \xB7 \u5355\u4E00\u673A\u5668\u4EBA \u2192 \u5199\u5165 `.env`\uFF0C\u914D\u7F6E\u91CC\u7528 `${env.X}` \u5F15\u7528\uFF1B"),console.log(" \xB7 \u591A\u7FA4/\u591A\u673A\u5668\u4EBA/\u9700\u8FD0\u8425\u81EA\u7EF4\u62A4 \u2192 \u5199\u5165 AI \u8868\u683C\u7FA4\u914D\u7F6E\u8868\uFF0C\u7531 config-sync \u53D1\u5E03\u6210 `globalVar.robot_creds`\u3002"),console.log(" \u72B6\u6001\u6587\u4EF6:",e.stateFile),console.log("\n\u26A0\uFE0F Stream \u5355\u6D3E\u53D1\u4E92\u65A5\uFF1A\u52FF\u5BF9\u540C\u4E00\u673A\u5668\u4EBA\u540C\u65F6\u8FD0\u884C `dws dev connect`\uFF0C\u5426\u5219\u6D88\u606F\u53EA\u6D3E\u53D1\u5176\u4E00\u3002"),console.log("\u{1F4A1} \u771F\u5B9E\u7528\u6237\u6D41\u91CF\uFF08\u7FA4\u91CC @bot / \u5355\u804A\u53D1\u73B0\uFF09\u9700\u516C\u5F00\u53D1\u5E03\uFF1A`aitable-workflow bot provision --name <\u540C\u540D> --publish`");break}case"publish_pending":{console.log(`
90
578
  \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(`
91
- \u2705 \u5DF2\u53D1\u5E03\uFF08published \u76F8\uFF09\u2014\u2014\u771F\u5B9E\u7528\u6237\u6D41\u91CF\u53EF\u7528\u3002`),console.log("\u{1F4A1} \u62C9\u7FA4: `aitable-workflow bot provision --name <\u540C\u540D> --group <openConversationId|\u7FA4\u540D>`\uFF08\u591A\u7FA4\u9017\u53F7\u5206\u9694\uFF09");break}case"grouped":{if(r.groups.length===0){let e=Object.keys(si(r.state)).length;console.log(`
92
- \u2705 grouped \u76F8\uFF1A\u7FA4\u53F0\u8D26\u5DF2\u6709 ${e} \u4E2A\u7FA4\u3002\u672C\u6B21\u672A\u4F20 --group\uFF0C\u672A\u53D1\u8D77\u4EFB\u4F55\u62C9\u7FA4\u8C03\u7528\u3002`);break}sn(r.groups),console.log("\u{1F4A1} add-bot \u7684 success \u53EA\u662F\u53D7\u7406\u4FE1\u53F7\uFF08dws \u65E0\u5728\u7FA4\u5217\u8868\u67E5\u8BE2\u63A5\u53E3\uFF09\uFF1A\u8BF7\u5230\u7FA4\u8BBE\u7F6E\u6838\u5BF9\u673A\u5668\u4EBA\u5728\u7FA4\u3002");break}case"approver_required":{console.error(`
93
- \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 e of r.candidates)console.error(` - ${e.name??"(\u672A\u77E5)"} userId=${e.userId}${e.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 r.groups&&r.groups.length>0&&sn(r.groups),console.error(`
94
- \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(li,"printProvisionResult");async function pi(r,t,e){let n=Be.dirname(await We(r.config??t.defaultConfig)),o=r.stateFile??Ue(n),i=await ln(o),s,a=null,l=null;if(r.refresh&&i?.unifiedAppId&&i.versionId){let m=e.createRunner?.()??new Fe;try{s=(await m.versionStatus(i.unifiedAppId,i.versionId)).versionStatus}catch(u){l=an(u)}if(!l)try{a=await m.checkApproval(i.unifiedAppId,i.versionId)}catch(u){l=an(u)}}let p=ii({state:i,versionStatus:s,approval:a,error:l});return console.log(p.map(m=>` ${m}`).join(`
579
+ \u2705 \u5DF2\u53D1\u5E03\uFF08published \u76F8\uFF09\u2014\u2014\u771F\u5B9E\u7528\u6237\u6D41\u91CF\u53EF\u7528\u3002`),console.log("\u{1F4A1} \u62C9\u7FA4: `aitable-workflow bot provision --name <\u540C\u540D> --group <openConversationId|\u7FA4\u540D>`\uFF08\u591A\u7FA4\u9017\u53F7\u5206\u9694\uFF09");break}case"grouped":{if(o.groups.length===0){let t=Object.keys(Qs(o.state)).length;console.log(`
580
+ \u2705 grouped \u76F8\uFF1A\u7FA4\u53F0\u8D26\u5DF2\u6709 ${t} \u4E2A\u7FA4\u3002\u672C\u6B21\u672A\u4F20 --group\uFF0C\u672A\u53D1\u8D77\u4EFB\u4F55\u62C9\u7FA4\u8C03\u7528\u3002`);break}Tn(o.groups),console.log("\u{1F4A1} add-bot \u7684 success \u53EA\u662F\u53D7\u7406\u4FE1\u53F7\uFF08dws \u65E0\u5728\u7FA4\u5217\u8868\u67E5\u8BE2\u63A5\u53E3\uFF09\uFF1A\u8BF7\u5230\u7FA4\u8BBE\u7F6E\u6838\u5BF9\u673A\u5668\u4EBA\u5728\u7FA4\u3002");break}case"approver_required":{console.error(`
581
+ \u26D4 \u516C\u5F00\u53D1\u5E03\u9700\u771F\u4EBA\u5BA1\u6279\uFF0C\u4E14\u672C\u7EC4\u7EC7\u7B56\u7565\u8981\u6C42\u663E\u5F0F\u9009\u5BA1\u6279\u4EBA\uFF08\u4EBA\u5BA1\u95E8\u4E0D\u5F97\u9759\u9ED8\u4EE3\u9009\uFF09\u3002`),console.error(" \u5BA1\u6279\u4EBA\u5019\u9009\uFF08\u6765\u81EA check-approval\uFF09:");for(let t of o.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 o.groups&&o.groups.length>0&&Tn(o.groups),console.error(`
582
+ \u274C provision \u5931\u8D25: ${o.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(ni,"printProvisionResult");async function ri(o,e,t){let n=et.dirname(await rt(o.config??e.defaultConfig)),r=o.stateFile??nt(n),s=await $n(r),i,a=null,l=null;if(o.refresh&&s?.unifiedAppId&&s.versionId){let p=t.createRunner?.()??new tt;try{i=(await p.versionStatus(s.unifiedAppId,s.versionId)).versionStatus}catch(u){l=_n(u)}if(!l)try{a=await p.checkApproval(s.unifiedAppId,s.versionId)}catch(u){l=_n(u)}}let d=Zs({state:s,versionStatus:i,approval:a,error:l});return console.log(d.map(p=>` ${p}`).join(`
95
583
  `)),console.log(`
96
- \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(pi,"runStatus");function an(r){return r instanceof cn?`${r.message}\uFF08${r.guidance}\uFF09`:r instanceof Error?r.message:String(r)}c(an,"describeError");async function mi(r,t,e,n){let o=t.scope??"robot";if(o!=="robot"&&o!=="app")return console.error(`\u274C --scope \u53EA\u652F\u6301 robot | app\uFF0C\u6536\u5230: ${o}`),1;let i=t.unifiedAppId?.trim();if(!i){let m=Be.dirname(await We(t.config??e.defaultConfig)),u=t.stateFile??Ue(m);if(i=(await ln(u))?.unifiedAppId??void 0,!i)return console.error(`\u274C \u65E0\u6CD5\u786E\u5B9A\u76EE\u6807\u5E94\u7528\uFF1A\u72B6\u6001\u6587\u4EF6\u65E0 unifiedAppId\uFF08${u}\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 Fe,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(`
97
- \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(mi,"runToggle");function Me(r){if(r instanceof cn)rn.error("cli","bot \u547D\u4EE4\u5931\u8D25",{kind:r.kind}),console.error(`
98
- \u274C ${r.message}`),console.error(` \u21B3 ${r.guidance}`);else{let t=r instanceof Error?r.message:String(r);rn.error("cli","bot \u547D\u4EE4\u5931\u8D25",{error:t}),console.error(`
99
- \u274C ${t}`)}}c(Me,"failWithDiagnostics");var gn=un.dirname(fi(import.meta.url));dn({override:!1,quiet:!0});dn({path:un.resolve(gn,"..",".env"),override:!1,quiet:!0});var fn=Ye(),Ne=be(fn),hi=ze(fn);gi({version:Ne});var f=new di().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(Ne).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",(r,t)=>{r.opts().debug?mn.setLevel("debug"):(t.name()==="config"||t.parent?.name()==="config")&&mn.setLevel("warn")}).hook("preAction",async(r,t)=>{t.name()!=="init"&&await ui()}),h={cliDir:gn,version:Ne,packageVersions:hi,defaultConfig:Xe};Qe(f,h);Ze(f,h);et(f,h);ot(f,h);st(f,h);ct(f,h);ut(f,h);wt(f,h);He(f,h);yt(f,h);vt(f,h);kt(f,h);Rt(f,h);Kt(f,h);zt(f,h);Zt(f,h);Yt(f,h);en(f,h);nn(f,h);on(f,h);pn(f,h);await f.parseAsync();
584
+ \u72B6\u6001\u6587\u4EF6: ${r}`),s&&!o.refresh&&(s.phase==="publish_pending"||s.phase==="version_created")&&console.log(" \u63D0\u793A: \u52A0 --refresh \u5B9E\u65F6\u67E5\u8BE2\u5BA1\u6279\u72B6\u6001\u4E0E\u5019\u9009\u3002"),s?0:1}c(ri,"runStatus");function _n(o){return o instanceof Pn?`${o.message}\uFF08${o.guidance}\uFF09`:o instanceof Error?o.message:String(o)}c(_n,"describeError");async function oi(o,e,t,n){let r=e.scope??"robot";if(r!=="robot"&&r!=="app")return console.error(`\u274C --scope \u53EA\u652F\u6301 robot | app\uFF0C\u6536\u5230: ${r}`),1;let s=e.unifiedAppId?.trim();if(!s){let p=et.dirname(await rt(e.config??t.defaultConfig)),u=e.stateFile??nt(p);if(s=(await $n(u))?.unifiedAppId??void 0,!s)return console.error(`\u274C \u65E0\u6CD5\u786E\u5B9A\u76EE\u6807\u5E94\u7528\uFF1A\u72B6\u6001\u6587\u4EF6\u65E0 unifiedAppId\uFF08${u}\uFF09\uFF0C\u8BF7\u7528 --unified-app-id \u663E\u5F0F\u6307\u5B9A\u3002`),1}let i=o==="disable"?"\u505C\u7528":"\u542F\u7528",a=n.createRunner?.()??new tt,l=r==="app"?"\u6574\u4E2A\u5E94\u7528":"\u673A\u5668\u4EBA\u80FD\u529B";return console.log(`\u{1F916} ${i}${l}\uFF08unifiedAppId=${s}\uFF09`),r==="app"&&o==="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)}}[o][r](s),console.log(`
585
+ \u2705 \u5DF2${i}${l}\u3002`),o==="disable"&&(console.log(` \u6062\u590D: ${r==="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(oi,"runToggle");function Qe(o){if(o instanceof Pn)In.error("cli","bot \u547D\u4EE4\u5931\u8D25",{kind:o.kind}),console.error(`
586
+ \u274C ${o.message}`),console.error(` \u21B3 ${o.guidance}`);else{let e=o instanceof Error?o.message:String(o);In.error("cli","bot \u547D\u4EE4\u5931\u8D25",{error:e}),console.error(`
587
+ \u274C ${e}`)}}c(Qe,"failWithDiagnostics");var Dn=Mn.dirname(ci(import.meta.url));jn({override:!1,quiet:!0});jn({path:Mn.resolve(Dn,"..",".env"),override:!1,quiet:!0});var Bn=dt(),ot=Ie(Bn),li=pt(Bn);ai({version:ot});var y=new si().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(ot).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",(o,e)=>{o.opts().debug?On.setLevel("debug"):(e.name()==="config"||e.parent?.name()==="config")&&On.setLevel("warn")}).hook("preAction",async(o,e)=>{e.name()!=="init"&&await ii()}),k={cliDir:Dn,version:ot,packageVersions:li,defaultConfig:ut};mt(y,k);ft(y,k);gt(y,k);wt(y,k);bt(y,k);Ct(y,k);It(y,k);$t(y,k);st(y,k);Lt(y,k);Ot(y,k);jt(y,k);Dt(y,k);wn(y,k);kn(y,k);Cn(y,k);yn(y,k);xn(y,k);En(y,k);Sn(y,k);Ln(y,k);await y.parseAsync();