aws-runtime-bridge 1.9.162 → 1.9.169

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.
Files changed (123) hide show
  1. package/CHANGELOG.md +324 -0
  2. package/dist/adapter/AcodeSdkAdapter.d.ts +31 -3
  3. package/dist/adapter/AcodeSdkAdapter.js +4 -9
  4. package/dist/adapter/ClaudeSdkAdapter.d.ts +2 -0
  5. package/dist/adapter/ClaudeSdkAdapter.js +3 -3
  6. package/dist/adapter/CodexSdkAdapter.d.ts +2 -0
  7. package/dist/adapter/CodexSdkAdapter.js +3 -3
  8. package/dist/adapter/OpencodeSdkAdapter.d.ts +2 -0
  9. package/dist/adapter/OpencodeSdkAdapter.js +3 -3
  10. package/dist/adapter/prompts.d.ts +1 -1
  11. package/dist/adapter/prompts.js +1 -1
  12. package/dist/adapter/types.d.ts +41 -4
  13. package/dist/adapter/types.js +1 -1
  14. package/dist/browser/frame-encode.d.ts +25 -0
  15. package/dist/browser/frame-encode.js +2 -0
  16. package/dist/browser/screencast-differ.d.ts +2 -3
  17. package/dist/browser/screencast-differ.js +1 -1
  18. package/dist/browser/screencast-manager.js +1 -1
  19. package/dist/browser/types.d.ts +5 -1
  20. package/dist/browser/types.js +1 -1
  21. package/dist/desktop/desktop-mcp-client.js +2 -2
  22. package/dist/routes/background-tasks.js +3 -3
  23. package/dist/routes/capabilities.js +1 -1
  24. package/dist/routes/dashboard.d.ts +2 -0
  25. package/dist/routes/dashboard.js +4 -4
  26. package/dist/routes/git.js +22 -22
  27. package/dist/routes/instance.js +1 -1
  28. package/dist/routes/launch.js +10 -10
  29. package/dist/routes/mcp-extra.js +2 -2
  30. package/dist/routes/mcp.d.ts +4 -0
  31. package/dist/routes/mcp.js +1 -1
  32. package/dist/routes/plugins.js +1 -1
  33. package/dist/routes/pty.d.ts +11 -3
  34. package/dist/routes/pty.js +3 -3
  35. package/dist/routes/runtime-binding.js +1 -1
  36. package/dist/routes/sessions.js +1 -1
  37. package/dist/routes/skills.js +1 -1
  38. package/dist/routes/sub-agents.js +8 -8
  39. package/dist/routes/terminal.d.ts +16 -2
  40. package/dist/routes/terminal.js +34 -36
  41. package/dist/services/agent-process-manager.js +1 -1
  42. package/dist/services/agent-pty-manager.js +4 -4
  43. package/dist/services/aws-client-agent-mcp.js +2 -2
  44. package/dist/services/capability-config.d.ts +8 -0
  45. package/dist/services/capability-config.js +2 -2
  46. package/dist/services/desktop-mcp-manager.d.ts +3 -1
  47. package/dist/services/desktop-mcp-manager.js +1 -1
  48. package/dist/services/instance-ai-config-service.js +1 -1
  49. package/dist/services/instance-features.d.ts +10 -0
  50. package/dist/services/instance-features.js +1 -1
  51. package/dist/services/instance-init-service.js +1 -1
  52. package/dist/services/launch-manager.d.ts +9 -1
  53. package/dist/services/launch-manager.js +6 -6
  54. package/dist/services/launch-metrics.d.ts +1 -1
  55. package/dist/services/launch-metrics.js +4 -3
  56. package/dist/services/mcp-deploy.d.ts +4 -0
  57. package/dist/services/mcp-env-injector.d.ts +12 -0
  58. package/dist/services/mcp-env-injector.js +2 -0
  59. package/dist/services/mcp-launch-binding-queue.d.ts +8 -0
  60. package/dist/services/mcp-launch-binding-queue.js +1 -1
  61. package/dist/services/orphan-monitor.js +1 -1
  62. package/dist/services/panel-env.d.ts +6 -2
  63. package/dist/services/panel-env.js +1 -1
  64. package/dist/services/plugin-manager.js +9 -9
  65. package/dist/services/process-detector.d.ts +23 -3
  66. package/dist/services/process-detector.js +13 -13
  67. package/dist/services/runtime-resources-snapshot.d.ts +3 -0
  68. package/dist/services/runtime-resources-snapshot.js +3 -0
  69. package/dist/services/session-output.d.ts +13 -0
  70. package/dist/services/session-output.js +4 -4
  71. package/dist/services/tunnel-client.js +1 -1
  72. package/dist/services/workspace-files.js +1 -1
  73. package/dist/types.d.ts +4 -0
  74. package/dist/utils/env-safety.d.ts +15 -0
  75. package/dist/utils/env-safety.js +2 -0
  76. package/dist/utils/lifecycle-log.d.ts +2 -0
  77. package/dist/utils/lifecycle-log.js +3 -0
  78. package/dist/utils/mcp-utils.js +1 -1
  79. package/package/acode/dist/background-command-manager.js +4 -4
  80. package/package/acode/dist/built-in-file-tools.d.ts +13 -0
  81. package/package/acode/dist/built-in-file-tools.js +2 -2
  82. package/package/acode/dist/builtins/shellCommandPreparation.d.ts +2 -0
  83. package/package/acode/dist/builtins/shellCommandPreparation.js +2 -2
  84. package/package/acode/dist/compaction.d.ts +10 -0
  85. package/package/acode/dist/compaction.js +6 -6
  86. package/package/acode/dist/context-overflow.js +1 -1
  87. package/package/acode/dist/index.d.ts +1 -0
  88. package/package/acode/dist/index.js +1 -1
  89. package/package/acode/dist/mcpToolNames.d.ts +4 -0
  90. package/package/acode/dist/mcpToolNames.js +1 -1
  91. package/package/acode/dist/runtime-environment.d.ts +2 -0
  92. package/package/acode/dist/runtime-environment.js +3 -2
  93. package/package/acode/dist/runtime.d.ts +68 -8
  94. package/package/acode/dist/runtime.js +28 -27
  95. package/package/acode/dist/sub-agent-manager.js +1 -1
  96. package/package/acode/dist/tool-allocation.js +1 -1
  97. package/package/acode/dist/tool-group-manager.d.ts +12 -0
  98. package/package/acode/dist/tool-group-manager.js +8 -4
  99. package/package/acode/dist/types.d.ts +8 -0
  100. package/package/acode/package.json +1 -1
  101. package/package/aws-client-agent-mcp/README.md +1 -0
  102. package/package/aws-client-agent-mcp/dist/agent-client.d.ts +22 -8
  103. package/package/aws-client-agent-mcp/dist/agent-client.js +1 -1
  104. package/package/aws-client-agent-mcp/dist/http-client.d.ts +10 -0
  105. package/package/aws-client-agent-mcp/dist/http-client.js +1 -1
  106. package/package/aws-client-agent-mcp/dist/logger.d.ts +2 -1
  107. package/package/aws-client-agent-mcp/dist/logger.js +2 -2
  108. package/package/aws-client-agent-mcp/dist/mcp-server.d.ts +19 -2
  109. package/package/aws-client-agent-mcp/dist/mcp-server.js +18 -18
  110. package/package/aws-client-agent-mcp/dist/mcp-tools.d.ts +15 -4
  111. package/package/aws-client-agent-mcp/dist/mcp-tools.js +79 -29
  112. package/package/aws-client-agent-mcp/dist/memory-store.d.ts +2 -0
  113. package/package/aws-client-agent-mcp/dist/memory-store.js +3 -3
  114. package/package/aws-client-agent-mcp/dist/message-buffer.js +1 -1
  115. package/package/aws-client-agent-mcp/dist/office/office-workspace.d.ts +15 -0
  116. package/package/aws-client-agent-mcp/dist/office/office-workspace.js +1 -1
  117. package/package/aws-client-agent-mcp/dist/status-reporter.js +1 -1
  118. package/package/aws-client-agent-mcp/dist/tool-groups.d.ts +4 -0
  119. package/package/aws-client-agent-mcp/dist/tool-groups.js +2 -2
  120. package/package/aws-client-agent-mcp/dist/types.d.ts +52 -1
  121. package/package/aws-client-agent-mcp/dist/websocket-client.js +1 -1
  122. package/package/aws-client-agent-mcp/package.json +1 -1
  123. package/package.json +1 -1
@@ -1,16 +1,16 @@
1
- import{spawn as _}from"node:child_process";import{cpSync as F,existsSync as w,lstatSync as ie,mkdirSync as T,readFileSync as k,readdirSync as x,renameSync as j,rmSync as E,symlinkSync as se,writeFileSync as H}from"node:fs";import{dirname as U,join as m,resolve as Z}from"node:path";import{fileURLToPath as oe,pathToFileURL as ae}from"node:url";import{parseAcodeCommandMarkdown as le,splitQualifiedToolName as ue}from"@agentswork/acode";import{getBridgeInstancePluginsDir as ce,getBridgeTemplatePluginsDir as de,getBridgeVersion as fe}from"../config.js";import{sanitizeAgentId as N,withFileLock as W,downloadPluginZip as ge,sanitizeArchiveFileName as pe}from"../utils/file-utils.js";import{createLogger as he}from"../utils/logger.js";import{setDeployedDefaultsProvider as me,reconcileDefaultsFromDeployed as ye}from"./capability-config.js";import{isCapabilityEnabled as Se,getAgentPluginSources as we}from"./instance-features.js";import{PluginEventBuffer as ve}from"./plugin-event-buffer.js";import{extractPluginZip as q}from"./plugin-package.js";const f=he("plugin-manager"),$="plugin-manager",X="\u7CFB\u7EDF\u5185\u7F6E\uFF1A\u7BA1\u7406\u63D2\u4EF6\u7684\u751F\u547D\u5468\u671F\uFF08\u5B89\u88C5/\u5378\u8F7D/\u542F\u505C/\u91CD\u8F7D\uFF09\uFF1B\u5F00\u53D1\u63D2\u4EF6\u7528\u5185\u7F6E /create-plugin \u547D\u4EE4",Q=`\u300C\u63D2\u4EF6\u7BA1\u7406\u63D2\u4EF6\u300D\u7684\u751F\u547D\u5468\u671F\u5DE5\u5177\uFF1A\u7BA1\u7406\u63D2\u4EF6\uFF08\u5B89\u88C5/\u5378\u8F7D/\u91CD\u8F7D/\u542F\u505C/\u5217\u8868\uFF09\u3002\u4EC5\u5F53\u7528\u6237\u660E\u786E\u8981\u6C42\u5B89\u88C5\u3001\u79FB\u9664\u6216\u4FEE\u590D\u63D2\u4EF6\u65F6\u4F7F\u7528\u3002
1
+ import{spawn as _}from"node:child_process";import{cpSync as F,existsSync as w,lstatSync as ie,mkdirSync as N,readFileSync as b,readdirSync as x,renameSync as j,rmSync as P,symlinkSync as se,writeFileSync as q}from"node:fs";import{dirname as J,join as m,resolve as Y}from"node:path";import{fileURLToPath as oe,pathToFileURL as ae}from"node:url";import{parseAcodeCommandMarkdown as le,splitQualifiedToolName as ue}from"@agentswork/acode";import{getBridgeInstancePluginsDir as ce,getBridgeTemplatePluginsDir as de,getBridgeVersion as fe}from"../config.js";import{sanitizeAgentId as I,withFileLock as W,downloadPluginZip as ge,sanitizeArchiveFileName as pe}from"../utils/file-utils.js";import{BLOCKED_ENV_KEYS as he}from"../utils/env-safety.js";import{createLogger as me}from"../utils/logger.js";import{setDeployedDefaultsProvider as ye,reconcileDefaultsFromDeployed as Se}from"./capability-config.js";import{isCapabilityEnabled as we,getAgentPluginSources as ve}from"./instance-features.js";import{PluginEventBuffer as $e}from"./plugin-event-buffer.js";import{extractPluginZip as U}from"./plugin-package.js";const f=me("plugin-manager"),k="plugin-manager",X="\u7CFB\u7EDF\u5185\u7F6E\uFF1A\u7BA1\u7406\u63D2\u4EF6\u7684\u751F\u547D\u5468\u671F\uFF08\u5B89\u88C5/\u5378\u8F7D/\u542F\u505C/\u91CD\u8F7D\uFF09\uFF1B\u5F00\u53D1\u63D2\u4EF6\u7528\u5185\u7F6E /create-plugin \u547D\u4EE4",Q=`\u300C\u63D2\u4EF6\u7BA1\u7406\u63D2\u4EF6\u300D\u7684\u751F\u547D\u5468\u671F\u5DE5\u5177\uFF1A\u7BA1\u7406\u63D2\u4EF6\uFF08\u5B89\u88C5/\u5378\u8F7D/\u91CD\u8F7D/\u542F\u505C/\u5217\u8868\uFF09\u3002\u4EC5\u5F53\u7528\u6237\u660E\u786E\u8981\u6C42\u5B89\u88C5\u3001\u79FB\u9664\u6216\u4FEE\u590D\u63D2\u4EF6\u65F6\u4F7F\u7528\u3002
2
2
  - action=list\uFF1A\u5217\u51FA\u5DF2\u5B89\u88C5\u63D2\u4EF6\uFF08\u72B6\u6001\u3001\u76D1\u542C\u5668\u5065\u5EB7\u3001\u5DE5\u5177\u6570\uFF09\u3002
3
3
  - action=install\uFF1Asource \u4E3A\u63D2\u4EF6\u6765\u6E90\uFF0C\u5F53\u524D\u652F\u6301 "local:<\u4EFB\u610F\u63D2\u4EF6\u76EE\u5F55\u7EDD\u5BF9\u8DEF\u5F84>"\uFF08\u4E0D\u505A\u76EE\u5F55\u4F4D\u7F6E\u9650\u5236\uFF09\uFF1Bconfig \u4F20\u63D2\u4EF6 manifest \u91CC userConfig \u58F0\u660E\u7684\u914D\u7F6E\u503C\u3002\u5B89\u88C5\u65F6\u4F1A\u5148\u628A\u8BE5\u76EE\u5F55\u79FB\u52A8\u5230\u672C agent \u52A0\u8F7D\u63D2\u4EF6\u7684\u4F4D\u7F6E\uFF0C\u518D\u52A0\u8F7D\u79FB\u52A8\u540E\u7684\u526F\u672C\uFF08\u79FB\u52A8\u540E\u6E90\u76EE\u5F55\u4E0D\u518D\u4FDD\u7559\uFF09\uFF0C\u5B89\u88C5\u540E\u7ACB\u5373\u751F\u6548\uFF1A\u4E0B\u4E00\u6B21 poll_message \u7684 pluginCatalog \u5373\u53EF\u89C1\u3002
4
4
  - action=reload\uFF1A\u91CD\u8F7D\u6307\u5B9A\u63D2\u4EF6\uFF08\u6539\u8FC7\u63D2\u4EF6\u6587\u4EF6\u540E\u4F7F\u7528\uFF09\uFF0C\u539F\u5B50\u6362\u88C5\uFF0C\u76D1\u542C\u5668\u91CD\u542F\u3002
5
5
  - action=enable / disable\uFF1A\u505C\u7528/\u542F\u7528\uFF08disable \u4FDD\u7559\u5B89\u88C5\u4E0E\u914D\u7F6E\uFF0C\u4EC5\u505C\u6B62\u76D1\u542C\u4E0E\u5DE5\u5177\u8C03\u7528\uFF09\u3002
6
- - action=uninstall\uFF1A\u5378\u8F7D\u5E76\u5220\u9664\u63D2\u4EF6\u76EE\u5F55\uFF08\u4E0D\u53EF\u9006\uFF0C\u9700\u7528\u6237\u660E\u786E\u8981\u6C42\uFF09\u3002`,Pe={type:"object",properties:{action:{type:"string",enum:["install","uninstall","reload","enable","disable","list"],description:"\u751F\u547D\u5468\u671F\u52A8\u4F5C"},name:{type:"string",description:"\u63D2\u4EF6\u540D\uFF08uninstall/reload/enable/disable \u5FC5\u586B\uFF09"},source:{type:"string",description:'install \u6765\u6E90\uFF0C\u5F53\u524D\u652F\u6301 "local:<\u4EFB\u610F\u63D2\u4EF6\u76EE\u5F55\u7EDD\u5BF9\u8DEF\u5F84>"\uFF08\u5B89\u88C5\u65F6\u81EA\u52A8\u79FB\u52A8\u5230\u672C agent \u63D2\u4EF6\u4F4D\u7F6E\u540E\u52A0\u8F7D\uFF09'},config:{type:"object",description:"install \u65F6\u63D2\u4EF6 userConfig \u58F0\u660E\u7684\u914D\u7F6E\u503C\uFF08\u952E\u503C\u5BF9\uFF09",additionalProperties:{type:"string"}}},required:["action"],additionalProperties:!1},$e=new Set(["install","uninstall","reload","enable","disable","list"]);function ee(){const l=fe();return l&&l!=="unknown"?l:void 0}function Ee(){return oe(new URL("./builtin-commands/",import.meta.url))}const ke=200,R=256*1024,Ae=4*1024,te=6e4,J=6e4,De=/^[a-zA-Z0-9_][a-zA-Z0-9_-]*$/,z=/^[a-z0-9][a-z0-9-]*$/,be=["system.","aws-","acode-"],Te=new Set(["NODE_OPTIONS","NODE_PATH","NODE_EXTRA_CA_CERTS","NODE_REPL_HISTORY","LD_PRELOAD","LD_LIBRARY_PATH","LD_AUDIT","DYLD_INSERT_LIBRARIES","DYLD_LIBRARY_PATH","DYLD_FRAMEWORK_PATH","PYTHONPATH","PYTHONSTARTUP","PYTHONHOME","PERL5LIB","PERL5OPT","RUBYOPT","RUBYLIB","BASH_ENV","ENV","SHELLOPTS","BASHOPTS","IFS","PS1","PS4","GIT_SSH","GIT_SSH_COMMAND","GIT_CONFIG","GIT_CONFIG_GLOBAL","PATH","HOME","USERPROFILE","SYSTEMROOT","COMSPEC","TEMP","TMP","LANG","TZ"]),Oe=/^[A-Za-z_][A-Za-z0-9_]*$/,Le=process.platform==="win32"?"junction":"dir",Ne=/[^\x20-\x7E]/,Ie=6e4,G=20,ne=80;function v(l){return typeof l=="object"&&l!==null&&!Array.isArray(l)}function I(l,e){let t=l;for(const n of e.split(".")){if(!v(t))return;t=t[n]}return t}function D(l,e){return l.length<=e?l:`${l.slice(0,e)}\u2026(\u622A\u65AD,\u5171 ${l.length} \u5B57\u7B26)`}async function C(l,e=8,t=200){for(let n=0;;n++)try{E(l,{recursive:!0,force:!0});return}catch(r){if(n>=e-1)throw r;await new Promise(i=>setTimeout(i,t))}}async function re(l,e){T(U(e),{recursive:!0});try{j(l,e);return}catch(t){const n=t?.code;if(!n||!["EXDEV","EPERM","EACCES","EBUSY","EINVAL"].includes(n))throw t}F(l,e,{recursive:!0,filter:t=>!/[\\/]\.git([\\/]|$)/.test(t)&&!/[\\/]node_modules([\\/]|$)/.test(t)}),await C(l)}function b(l,e){l.logs.push(`${new Date().toISOString()} ${e}`),l.logs.length>ke&&l.logs.shift()}function B(l,e,t="params"){if(!v(l))return[];const n=[],r=l.type;if(typeof r=="string"&&!Ce(r,e))return[`${t}: \u671F\u671B ${r}\uFF0C\u5B9E\u9645 ${Re(e)}`];if(Array.isArray(l.enum)&&l.enum.length>0&&(l.enum.some(s=>JSON.stringify(s)===JSON.stringify(e))||n.push(`${t}: \u503C ${JSON.stringify(e)} \u4E0D\u5728\u679A\u4E3E ${JSON.stringify(l.enum)} \u5185`)),r==="object"&&v(e)){const i=v(l.properties)?l.properties:{},s=Array.isArray(l.required)?l.required:[];for(const o of s)(!(o in e)||e[o]===void 0)&&n.push(`${t}.${o}: \u5FC5\u586B\u53C2\u6570\u7F3A\u5931`);for(const[o,a]of Object.entries(i))o in e&&e[o]!==void 0&&n.push(...B(a,e[o],`${t}.${o}`));if(l.additionalProperties===!1)for(const o of Object.keys(e))o in i||n.push(`${t}.${o}: \u4E0D\u5141\u8BB8\u7684\u672A\u77E5\u53C2\u6570\uFF08schema additionalProperties=false\uFF09`)}return r==="array"&&Array.isArray(e)&&v(l.items)&&e.forEach((i,s)=>{n.push(...B(l.items,i,`${t}[${s}]`))}),n}function Ce(l,e){switch(l){case"string":return typeof e=="string";case"number":return typeof e=="number"&&Number.isFinite(e);case"boolean":return typeof e=="boolean";case"object":return v(e);case"array":return Array.isArray(e);case"null":return e===null;default:return!0}}function Re(l){return l===null?"null":Array.isArray(l)?"array":typeof l}class Me{constructor(e={}){this.agents=new Map,this.moduleNonce=0,this.templatePullInFlight=new Set,this.backgroundTemplatePulls=new Set,this.rootDir=e.rootDir??de(),this.runtimeRootDir=e.runtimeRootDir}forAgent(e){return{listPlugins:()=>this.list(e),getCatalog:()=>this.getCatalog(e),getToolSchema:t=>this.getToolSchema(e,t),invokeTool:(t,n,r,i)=>this.invokeTool(e,t,n,r,i),manage:t=>this.manage(e,t),getCommandDirs:()=>this.getCommandDirs(e),exposePlugin:t=>this.exposePlugin(e,t)}}setOnPluginsChanged(e){this.onPluginsChanged=e}notifyPluginsChanged(e){try{this.onPluginsChanged?.(e)}catch(t){f.warn("[agent:%s] onPluginsChanged \u56DE\u8C03\u5931\u8D25: %s",e,t instanceof Error?t.message:String(t))}}async getCommandDirs(e){return[...(await this.hydrate(e)).plugins.values()].filter(n=>n.enabled&&n.commandDir).map(n=>n.commandDir)}async getPluginCommands(e){const t=await this.hydrate(e),n=[],r=Ee(),i=this.parseCommandDir($,r);i.length===0&&f.warn("[plugin-manager] \u5185\u7F6E\u547D\u4EE4\u76EE\u5F55\u4E0D\u53EF\u8BFB\u6216\u4E3A\u7A7A: %s\uFF08/create-plugin \u4E0D\u53EF\u7528\uFF0C\u8BF7\u68C0\u67E5\u5B89\u88C5\u5305\u662F\u5426\u5B8C\u6574\uFF09",r),n.push(...i);for(const s of t.plugins.values())!s.enabled||!s.commandDir||n.push(...this.parsePluginCommandDir(s));return n}parsePluginCommandDir(e){return this.parseCommandDir(e.name,e.commandDir)}parseCommandDir(e,t){const n=[];if(!t)return n;try{for(const r of x(t)){if(!r.endsWith(".md"))continue;const i=m(t,r);try{const s=le(i,k(i,"utf8"));s.plugin=e,n.push(s)}catch(s){f.warn("[plugin:%s] \u547D\u4EE4\u89E3\u6790\u5931\u8D25 %s: %s",e,r,s instanceof Error?s.message:String(s))}}}catch{}return n}async list(e){const t=await this.hydrate(e),n=new Map;for(const r of t.plugins.values()){const i=this.toSummary(r);n.set(i.name,i)}n.has($)||n.set($,{name:$,version:ee(),description:X,status:"enabled",enabled:!0,source:"builtin",installedAt:new Date().toISOString(),toolCount:1,tools:[{name:"plugin-manager.manage",description:"\u63D2\u4EF6\u751F\u547D\u5468\u671F\u7BA1\u7406\uFF08install/uninstall/reload/disable/enable/list\uFF09"}],listeners:[],builtin:!0});for(const r of this.readSharedManifest()){const i=r.pluginName;if(!this.deployedPluginHealthy(i))continue;const o=n.get(i);if(o){String(o.source||"").startsWith("shared:")&&(o.enabled=this.effectiveSharedEnabled(e,r));continue}n.set(i,{name:i,version:this.deployedPluginVersion(i),status:"enabled",enabled:this.effectiveSharedEnabled(e,r),source:`shared:${r.fileName??`${i}.zip`}`,installedAt:new Date().toISOString(),toolCount:0,listeners:[]})}return[...n.values()].sort((r,i)=>r.name.localeCompare(i.name))}deployedPluginVersion(e){try{const t=JSON.parse(k(m(this.deployedPluginDir(e),"plugin.json"),"utf8"));return typeof t.version=="string"?t.version:void 0}catch{return}}async getCatalog(e){const t=await this.hydrate(e),n=[];for(const r of t.plugins.values()){if(!r.enabled||r.status==="error")continue;const i=r.tools.slice(0,G).map(s=>({name:s.name,description:D(s.title||s.description,ne),requiredParams:this.requiredParamsOf(s)}));r.tools.length>G&&i.push({name:`(\u53E6\u6709 ${r.tools.length-G} \u4E2A\u5DE5\u5177\u672A\u5217\u51FA)`,description:'\u7528 function_call {action:"catalog"} \u67E5\u770B\u5168\u91CF',requiredParams:void 0}),n.push({plugin:r.name,version:r.version,description:r.description,status:r.status,tools:i})}return n.push({plugin:$,version:ee(),description:X,status:"enabled",tools:[{name:"manage",description:D(Q,ne),requiredParams:["action"]}]}),{revision:t.catalogRevision,plugins:n}}async getToolSchema(e,t){const n=ue(t);if(!n)return null;if(n.plugin===$&&n.tool==="manage")return{plugin:$,name:"manage",description:Q,inputSchema:Pe};const i=(await this.hydrate(e)).plugins.get(n.plugin);if(!i||!i.enabled)return null;const s=i.tools.find(o=>o.name===n.tool);return s?{plugin:i.name,name:s.name,title:s.title,description:s.description,inputSchema:s.inputSchema??{type:"object",properties:{}}}:null}async invokeTool(e,t,n,r,i){if(t===$&&n==="manage"){const u=this.buildManageRequest(r);if(!u)return{ok:!1,error:"plugin-manager.manage \u7F3A\u5C11 action"};const c=await this.manage(e,u);if(!c.ok)return{ok:!1,error:c.error??"\u63D2\u4EF6\u7BA1\u7406\u64CD\u4F5C\u5931\u8D25"};const d={ok:!0};return c.plugins&&(d.plugins=c.plugins),c.summary&&(d.summary=c.summary),{ok:!0,result:d}}const s=await this.hydrate(e),o=s.plugins.get(t);if(!o)return{ok:!1,error:`\u63D2\u4EF6 ${t} \u672A\u5B89\u88C5\uFF08\u53EF\u7528\u63D2\u4EF6: ${[...s.plugins.keys()].join(", ")||"\u65E0"}\uFF09`};if(!o.enabled)return{ok:!1,error:`\u63D2\u4EF6 ${t} \u5DF2\u505C\u7528\uFF0C\u53EF\u8BA9\u7528\u6237\u5728\u9762\u677F\u6216\u7528 plugin-manager.manage enable \u542F\u7528`};const a=o.tools.find(u=>u.name===n);if(!a)return{ok:!1,error:`\u63D2\u4EF6 ${t} \u65E0\u5DE5\u5177 ${n}\uFF08\u53EF\u7528: ${o.tools.map(u=>u.name).join(", ")||"\u65E0"}\uFF09`};if(a.inputSchema){const u=B(a.inputSchema,r);if(u.length>0)return{ok:!1,error:`\u53C2\u6570\u6821\u9A8C\u5931\u8D25: ${u.join("; ")}`,inputSchema:a.inputSchema}}return this.executeHandler(e,o,a,r,i)}buildManageRequest(e){const t=e.action;if(typeof t!="string"||!$e.has(t))return null;const n={action:t};if(typeof e.name=="string"&&e.name.trim()&&(n.name=e.name.trim()),typeof e.source=="string"&&e.source.trim()&&(n.source=e.source.trim()),e.config&&typeof e.config=="object"&&!Array.isArray(e.config)){const r={};for(const[i,s]of Object.entries(e.config))typeof s=="string"&&(r[i]=s);n.config=r}return n}async executeHandler(e,t,n,r,i){const s=Date.now(),o=n.handler??{type:"process"};try{return o.type==="mcp"?{ok:!1,error:"handler.type=mcp \u5C06\u5728\u540E\u7EED\u7248\u672C\u652F\u6301\uFF0C\u8BF7\u6539\u7528 process/module handler"}:o.type==="module"?{ok:!0,result:await this.invokeModuleHandler(t,o,r,e,i),durationMs:Date.now()-s}:!o.command||!o.command.trim()?{ok:!1,error:`\u5DE5\u5177 ${n.name} \u7684 process handler \u7F3A\u5C11 command`}:{ok:!0,result:await this.invokeProcessHandler(t,o,r,e,i),durationMs:Date.now()-s}}catch(a){return{ok:!1,error:a instanceof Error?a.message:String(a),durationMs:Date.now()-s}}}async invokeProcessHandler(e,t,n,r,i){const s=Y(t.command??"",{params:n});if(s.length===0)throw new Error("process handler command \u4E3A\u7A7A");const o=typeof t.timeoutMs=="number"&&t.timeoutMs>0?t.timeoutMs:te,a=new AbortController,u=()=>a.abort();i?.signal?.addEventListener("abort",u,{once:!0});const c=setTimeout(()=>a.abort(),o);try{return await new Promise((d,y)=>{f.info("[plugin:%s] spawn: %s",e.name,s.join(" "));const p=_(s[0],s.slice(1),{cwd:e.dir,env:this.buildPluginEnv(e,r),shell:t.shell===!0,windowsHide:!0,signal:a.signal});let g="",h="";p.stdin?.on("error",()=>{}),p.stdout?.on("data",P=>{g.length<R&&(g+=P.toString("utf8"))}),p.stderr?.on("data",P=>{h.length<R&&(h+=P.toString("utf8"))}),p.on("error",P=>{y(new Error(`\u63D2\u4EF6\u8FDB\u7A0B\u542F\u52A8\u5931\u8D25: ${P.message}`))}),p.on("close",P=>{const A=g.trim();if(P!==0){const O=D(h.trim()||A||"(\u65E0\u8F93\u51FA)",600);y(new Error(a.signal.aborted?`\u63D2\u4EF6\u8FDB\u7A0B\u8D85\u65F6(${o}ms)\u6216\u88AB\u4E2D\u6B62`:`\u63D2\u4EF6\u8FDB\u7A0B\u9000\u51FA\u7801 ${P}: ${O}`));return}if(!A){d({ok:!0});return}try{d(JSON.parse(A))}catch{d(A)}});try{t.stdin==="params"?p.stdin?.end(`${JSON.stringify(n)}
7
- `):p.stdin?.end()}catch{}})}finally{clearTimeout(c),i?.signal?.removeEventListener("abort",u)}}async invokeModuleHandler(e,t,n,r,i){if(!t.module)throw new Error("module handler \u7F3A\u5C11 module \u8DEF\u5F84");const s=m(e.dir,t.module);let o=e.moduleCache.get(s);o||(o=await import(`${ae(s).href}?acode_nonce=${e.importNonce}`),e.moduleCache.set(s,o));const a=t.export||"default",c=o[a];if(typeof c!="function")throw new Error(`\u6A21\u5757 ${t.module} \u672A\u5BFC\u51FA\u51FD\u6570 ${a}`);const d=typeof t.timeoutMs=="number"&&t.timeoutMs>0?t.timeoutMs:te;let y;const p=Promise.resolve().then(()=>c(n,{agentId:r,signal:i?.signal,pluginRoot:e.dir}));try{return await Promise.race([p,new Promise((g,h)=>{y=setTimeout(()=>h(new Error(`\u63D2\u4EF6\u6A21\u5757\u6267\u884C\u8D85\u65F6(${d}ms)`)),d)})])}finally{clearTimeout(y)}}buildPluginEnv(e,t){const n={};for(const i of["PATH","HOME","USERPROFILE","SystemRoot","COMSPEC","TEMP","TMP","LANG","TZ"]){const s=process.env[i];s!==void 0&&(n[i]=s)}n.ACODE_PLUGIN_ROOT=e.dir,n.ACODE_AGENT_ID=t,n.ACODE_PLUGIN_NAME=e.name;const r=new Set((e.userConfig??[]).map(i=>i.key));for(const[i,s]of Object.entries(e.configValues))r.has(i)&&(!Oe.test(i)||Te.has(i.toUpperCase())||(n[i]=s));return n}async manage(e,t){const n=this.agentState(e),r=n.queue.then(async()=>{const i=await this.hydrate(e);return this.doManage(i,t)});return n.queue=r.catch(()=>{}),r}async doManage(e,t){if(t.name===$&&(t.action==="uninstall"||t.action==="disable"||t.action==="enable"||t.action==="reload"))return{ok:!1,error:`\u5185\u7F6E\u7CFB\u7EDF\u63D2\u4EF6 ${$} \u4E0D\u53EF${t.action==="uninstall"?"\u5378\u8F7D":t.action==="reload"?"\u91CD\u8F7D":"\u505C\u7528/\u542F\u7528"}`};switch(t.action){case"list":return{ok:!0,plugins:await this.list(e.agentId)};case"install":return this.installPlugin(e,t);case"uninstall":return this.uninstallPlugin(e,t);case"reload":return this.reloadPlugin(e,t);case"enable":case"disable":return this.setEnabled(e,t,t.action==="enable");default:return{ok:!1,error:`\u672A\u77E5 action: ${String(t.action)}`}}}async installPlugin(e,t){const n=(t.source??"").trim();if(!n)return{ok:!1,error:"install \u9700\u8981 source\uFF08\u5F53\u524D\u652F\u6301 local:<\u63D2\u4EF6\u76EE\u5F55\u7EDD\u5BF9\u8DEF\u5F84>\uFF09"};const r=n.split(":",1)[0];if(r!=="local")return{ok:!1,error:`\u6682\u4E0D\u652F\u6301\u63D2\u4EF6\u6765\u6E90 "${r}:"\uFF08npm:/git: \u5728\u8DEF\u7EBF\u56FE\u4E2D\uFF1Bzip \u5305\u8BF7\u7528\u9762\u677F\u5BFC\u5165\u6216 POST /runtime/plugins/:agentId/upload\uFF09`};const i=n.slice(6).trim();return!i||!w(m(i,"plugin.json"))?{ok:!1,error:`\u63D2\u4EF6\u76EE\u5F55\u4E0D\u5B58\u5728\u6216\u7F3A\u5C11 plugin.json: ${i}`}:this.installFromDirectory(e,i,n,t.config)}async installFromZip(e,t,n,r){if(!t||t.length===0)return{ok:!1,error:"zip \u5305\u5185\u5BB9\u4E3A\u7A7A"};const i=this.agentState(e),s=i.queue.then(async()=>{await this.hydrate(e);const o=m(this.rootDir,"tmp",`upload-${Date.now()}-${Math.random().toString(36).slice(2,8)}`);try{const a=await q(t,o);return w(m(a.pluginDir,"plugin.json"))?(f.info("[agent:%s] zip \u5BFC\u5165: %s\uFF08%d \u4E2A\u6587\u4EF6\uFF09",e,n,a.fileCount),await this.installFromDirectory(i,a.pluginDir,`upload:${n}`,r)):{ok:!1,error:"zip \u5185\u672A\u627E\u5230 plugin.json\uFF08\u8BF7\u6253\u5305\u63D2\u4EF6\u76EE\u5F55\uFF0C\u4E14 zip \u5185\u8DEF\u5F84\u4F7F\u7528\u82F1\u6587\uFF09"}}catch(a){const u=a instanceof Error?a.message:String(a);return f.warn("[agent:%s] zip \u5BFC\u5165\u5931\u8D25: %s",e,u),{ok:!1,error:`zip \u5BFC\u5165\u5931\u8D25: ${u}`}}finally{await C(o,3,100).catch(()=>{})}});return i.queue=s.catch(()=>{}),s}async installFromDirectory(e,t,n,r){const i=this.loadManifestOnly(t);if(!i.ok)return i;const s=i.manifest,o=s.name;if(o===$)return{ok:!1,error:`\u63D2\u4EF6\u540D ${o} \u4E3A\u7CFB\u7EDF\u4FDD\u7559\u540D\u79F0\uFF0C\u4E0D\u5141\u8BB8\u5B89\u88C5\u540C\u540D\u63D2\u4EF6`};const a=this.validateUserConfigValues(s,r??{});if(a)return{ok:!1,error:a};const u=this.loadPluginFromDir(e,t,n,new Date().toISOString(),r??{});if(!u.ok)return f.warn("[agent:%s] \u63D2\u4EF6\u88C5\u8F7D\u6821\u9A8C\u5931\u8D25\uFF08%s\uFF09: %s",e.agentId,n,u.error),u;const c=m(this.rootDir,"cache",N(e.agentId),o),d=t===c,y=e.plugins.get(o);if(y&&this.stopAllListeners(y),!d)try{await C(c),await re(t,c)}catch(h){const P=h instanceof Error?h.message:String(h);return f.warn("[agent:%s] \u63D2\u4EF6\u79FB\u52A8\u5931\u8D25\uFF08%s\uFF09: %s",e.agentId,n,P),y&&this.startAllListeners(e,y),{ok:!1,error:`\u63D2\u4EF6\u79FB\u52A8\u5931\u8D25: ${P}`}}const p=this.loadPluginFromDir(e,c,n,new Date().toISOString(),r??{});if(!p.ok){if(f.warn("[agent:%s] \u63D2\u4EF6\u88C5\u8F7D\u5931\u8D25\uFF08%s\uFF09: %s",e.agentId,n,p.error),!d)try{await re(c,t)}catch(h){f.warn("[agent:%s] \u88C5\u8F7D\u5931\u8D25\u540E\u65E0\u6CD5\u79FB\u56DE\u6E90\u76EE\u5F55\uFF08%s\uFF09\uFF0C\u5DF2\u4FDD\u7559\u7F13\u5B58\u526F\u672C",e.agentId,h instanceof Error?h.message:String(h))}if(y)try{this.startAllListeners(e,y)}catch(h){f.warn("[agent:%s] \u6062\u590D\u65E7\u5B9E\u4F8B\u76D1\u542C\u5931\u8D25: %s",e.agentId,h instanceof Error?h.message:String(h))}return p}const g=p.plugin;return e.plugins.set(g.name,g),this.bumpCatalogRevision(e),this.persistInstalled(e),this.startAllListeners(e,g),f.info("[agent:%s] \u63D2\u4EF6\u5DF2\u5B89\u88C5: %s@%s",e.agentId,g.name,g.version??"?"),this.notifyPluginsChanged(e.agentId),{ok:!0,summary:this.toSummary(g)}}async uninstallPlugin(e,t){const n=(t.name??"").trim(),r=e.plugins.get(n);return r?(this.stopAllListeners(r),e.plugins.delete(n),e.pendingExposed.delete(n),e.exposedThisSession.has(n)&&this.pushDeprecatedNotice(e,n,"\u5DF2\u88AB\u5378\u8F7D"),this.bumpCatalogRevision(e),this.readSharedManifest().some(s=>s.pluginName===n)&&this.removeRuntimeLink(e.agentId,n),this.persistInstalled(e),await C(r.dir),f.info("[agent:%s] \u63D2\u4EF6\u5DF2\u5378\u8F7D: %s",e.agentId,n),this.notifyPluginsChanged(e.agentId),{ok:!0}):{ok:!1,error:`\u63D2\u4EF6 ${n} \u672A\u5B89\u88C5`}}async reloadPlugin(e,t){const n=(t.name??"").trim(),r=e.plugins.get(n);if(!r)return{ok:!1,error:`\u63D2\u4EF6 ${n} \u672A\u5B89\u88C5`};const i=this.loadPluginFromDir(e,r.dir,r.source,r.installedAt,r.configValues);if(!i.ok)return{ok:!1,error:`\u91CD\u8F7D\u5931\u8D25\uFF08\u4FDD\u7559\u65E7\u7248\u672C\u8FD0\u884C\uFF09: ${i.error}`};const s=i.plugin;return this.stopAllListeners(r),e.plugins.set(n,s),this.bumpCatalogRevision(e),this.persistInstalled(e),this.startAllListeners(e,s),f.info("[agent:%s] \u63D2\u4EF6\u5DF2\u91CD\u8F7D: %s",e.agentId,n),this.notifyPluginsChanged(e.agentId),{ok:!0,summary:this.toSummary(s)}}async setEnabled(e,t,n){const r=(t.name??"").trim(),i=e.plugins.get(r);return i?(i.enabled=n,this.bumpCatalogRevision(e),n?this.startAllListeners(e,i):(e.pendingExposed.delete(r),e.exposedThisSession.has(r)&&this.pushDeprecatedNotice(e,r,"\u5DF2\u505C\u7528"),this.stopAllListeners(i)),this.persistInstalled(e),this.notifyPluginsChanged(e.agentId),{ok:!0,summary:this.toSummary(i)}):{ok:!1,error:`\u63D2\u4EF6 ${r} \u672A\u5B89\u88C5`}}deployedDir(){return m(this.rootDir,"deployed")}deployedManifestFile(){return m(this.deployedDir(),"manifest.json")}deployedPluginDir(e){if(!V(e))throw new Error(`\u975E\u6CD5\u63D2\u4EF6\u540D\uFF08\u4EC5\u5141\u8BB8 ${z}\uFF09: ${JSON.stringify(e)}`);const t=m(this.deployedDir(),e),n=Z(this.deployedDir());if(Z(t)!==m(n,e))throw new Error(`\u63D2\u4EF6\u76EE\u5F55\u8D8A\u51FA\u90E8\u7F72\u533A: ${e}`);return t}legacySharedDir(){return m(this.rootDir,"shared")}readSharedManifest(){try{const e=JSON.parse(k(this.deployedManifestFile(),"utf8"));return Array.isArray(e.plugins)?e.plugins.filter(t=>t&&V(t.pluginName)):[]}catch{return[]}}writeSharedManifest(e){T(this.deployedDir(),{recursive:!0}),H(this.deployedManifestFile(),`${JSON.stringify({version:2,plugins:e},null,2)}
8
- `,"utf8")}async migrateLegacySharedIfNeeded(){try{if(w(this.deployedManifestFile()))return;const e=m(this.legacySharedDir(),"manifest.json");if(!w(e))return;const t=JSON.parse(k(e,"utf8")),n=Array.isArray(t.plugins)?t.plugins:[];if(n.length===0)return;const r=[];for(const i of n){const s=m(this.legacySharedDir(),i.zipFile);if(!(!i.pluginName||!w(s)))try{const o=await this.deployPluginZipToPersistentDir(k(s),i.pluginName);if(!o)continue;r.push(o),f.info("[shared] \u65E7\u5171\u4EAB\u63D2\u4EF6\u8FC1\u79FB\u5230\u90E8\u7F72\u533A: %s",i.pluginName)}catch(o){f.warn("[shared] \u65E7\u5171\u4EAB\u63D2\u4EF6 %s \u8FC1\u79FB\u5931\u8D25: %s",i.pluginName,o instanceof Error?o.message:String(o))}}r.length>0&&this.writeSharedManifest(r),E(this.legacySharedDir(),{recursive:!0,force:!0})}catch(e){f.warn("[shared] \u65E7\u5171\u4EAB\u63D2\u4EF6\u8FC1\u79FB\u672A\u6267\u884C\uFF08\u4E0B\u6B21\u91CD\u8BD5\uFF09: %s",e instanceof Error?e.message:String(e))}}deployedPluginHealthy(e){return w(m(this.deployedPluginDir(e),"plugin.json"))}runtimeDirFor(e){return this.runtimeRootDir?m(this.runtimeRootDir,N(e)):ce(e)}runtimeLinkPath(e,t){return m(this.runtimeDirFor(e),t)}ensureRuntimeLink(e,t){const n=this.runtimeLinkPath(e,t),r=this.deployedPluginDir(t);if(!w(m(r,"plugin.json")))return!1;T(this.runtimeDirFor(e),{recursive:!0});try{if(w(n)){let i=!1;try{i=ie(n).isSymbolicLink()}catch{i=!1}if(i)try{return x(n),!0}catch{}E(n,{recursive:!0,force:!0})}return se(r,n,Le),f.info("[agent:%s] \u63D2\u4EF6\u8FD0\u884C\u65F6\u94FE\u63A5\u5DF2\u5EFA\u7ACB: %s \u2192 %s",e,n,r),!0}catch(i){return f.warn("[agent:%s] \u63D2\u4EF6\u8FD0\u884C\u65F6\u94FE\u63A5\u5931\u8D25\uFF08%s \u2192 %s\uFF09: %s",e,t,r,i instanceof Error?i.message:String(i)),!1}}removeRuntimeLink(e,t){const n=this.runtimeLinkPath(e,t);try{w(n)&&(E(n,{recursive:!0,force:!0}),f.info("[agent:%s] \u63D2\u4EF6\u8FD0\u884C\u65F6\u94FE\u63A5\u5DF2\u79FB\u9664: %s",e,t))}catch(r){f.warn("[agent:%s] \u63D2\u4EF6\u8FD0\u884C\u65F6\u94FE\u63A5\u79FB\u9664\u5931\u8D25\uFF08%s\uFF09: %s",e,t,r instanceof Error?r.message:String(r))}}async saveSharedPlugin(e,t,n=!0,r){if(!e||e.length===0)return{ok:!1,error:"zip \u5305\u5185\u5BB9\u4E3A\u7A7A"};await this.migrateLegacySharedIfNeeded();const i=m(this.rootDir,"tmp",`deploy-${Date.now()}-${Math.random().toString(36).slice(2,8)}`);try{const s=await q(e,i),o=this.loadManifestOnly(s.pluginDir);if(!o.ok)return o;const a=o.manifest.name,u=this.readSharedManifest().find(g=>g.pluginName===a);if(u&&u.sha256===r&&this.deployedPluginHealthy(a))return{ok:!0,pluginName:a};await this.suspendDeployedPluginAcrossAgents(a),T(this.deployedDir(),{recursive:!0});const c=this.deployedPluginDir(a),d=m(this.deployedDir(),`.old-${a}-${Date.now()}-${Math.random().toString(36).slice(2,8)}`);if(w(c))try{j(c,d)}catch{E(c,{recursive:!0,force:!0})}try{F(s.pluginDir,c,{recursive:!0,filter:g=>!/[\\/]\.git([\\/]|$)/.test(g)&&!/[\\/]node_modules([\\/]|$)/.test(g)})}catch(g){throw w(d)&&(E(c,{recursive:!0,force:!0}),j(d,c)),g}w(d)&&E(d,{recursive:!0,force:!0}),await W(this.deployedManifestFile(),async()=>{const g=this.readSharedManifest().filter(h=>h.pluginName!==a);g.push({pluginName:a,zipFile:u?.zipFile??`${a}.zip`,fileName:t,defaultEnabled:n,sha256:r}),this.writeSharedManifest(g)}),f.info("[shared] \u63D2\u4EF6\u5DF2\u90E8\u7F72\u5230 bridge: %s\uFF08\u6765\u6E90 %s%s\uFF09",a,t,r?`, sha256=${r.slice(0,12)}\u2026`:"");const p=(await this.applySharedToKnownAgents()).find(g=>g.installed.includes(a));return p&&f.info("[shared] \u5DF2\u540C\u6B65\u5230\u8FD0\u884C\u4E2D agent: %s",p.agentId),{ok:!0,pluginName:a}}catch(s){const o=s instanceof Error?s.message:String(s);return f.warn("[shared] \u63D2\u4EF6\u90E8\u7F72\u5931\u8D25\uFF08%s\uFF09: %s",t,o),{ok:!1,error:`\u63D2\u4EF6\u90E8\u7F72\u5931\u8D25: ${o}`}}finally{await C(i,3,100).catch(()=>{})}}async deployPluginZipToPersistentDir(e,t){if(!e||e.length===0)return null;const n=m(this.rootDir,"tmp",`migrate-${Date.now()}-${Math.random().toString(36).slice(2,8)}`);try{const r=await q(e,n),i=this.loadManifestOnly(r.pluginDir);if(!i.ok)return null;const s=i.manifest.name;if(t&&s!==t)return null;T(this.deployedDir(),{recursive:!0});const o=this.deployedPluginDir(s);return w(o)&&E(o,{recursive:!0,force:!0}),F(r.pluginDir,o,{recursive:!0,filter:a=>!/[\\/]\.git([\\/]|$)/.test(a)&&!/[\\/]node_modules([\\/]|$)/.test(a)}),{pluginName:s,zipFile:`${s}.zip`,fileName:`${s}.zip`,defaultEnabled:!0}}finally{E(n,{recursive:!0,force:!0})}}async suspendDeployedPluginAcrossAgents(e){for(const t of[...this.agents.values()]){if(!t.hydrated)continue;const n=t.queue.then(async()=>{const r=t.plugins.get(e);r&&(this.stopAllListeners(r),t.plugins.delete(e),this.bumpCatalogRevision(t),f.info("[agent:%s] \u5DF2\u6458\u9664\u63D2\u4EF6\u7B49\u5F85\u90E8\u7F72\u533A\u66F4\u65B0: %s",t.agentId,e))});t.queue=n.catch(()=>{}),await n}}async applySharedToKnownAgents(){const e=[];for(const t of this.agents.values()){if(!t.hydrated)continue;const n=await this.syncSharedIntoStateQueued(t);n.length>0&&e.push({agentId:t.agentId,installed:n})}return e}async syncSharedIntoStateQueued(e){const t=e.queue.then(()=>this.syncSharedIntoState(e));return e.queue=t.catch(()=>[]),t}effectiveSharedEnabled(e,t){return Se(e,"plugins",t.pluginName)&&(t.defaultEnabled??!0)}async pullTemplatePluginsFromCapabilities(e){const t=we(e.agentId);if(!t)return;const n=this.readSharedManifest();for(const[r,i]of Object.entries(t)){if(!i.url)continue;const s=n.find(a=>a.pluginName===r);if(!s||!s.sha256||s.sha256===i.sha256&&this.deployedPluginHealthy(r)||this.templatePullInFlight.has(r))continue;this.templatePullInFlight.add(r);const o=m(this.rootDir,"tmp",`pull-${N(e.agentId)}-${Date.now()}-${Math.random().toString(36).slice(2,8)}`);try{T(o,{recursive:!0});let a=`${r}.zip`;try{const y=decodeURIComponent(i.url.split("/").pop()||"");y.toLowerCase().endsWith(".zip")&&(a=pe(y,`${r}.zip`))}catch{}const u=await ge({downloadUrl:i.url,fileName:a,sha256:i.sha256},o);if(!u)continue;const c=k(u.outputPath),d=await this.saveSharedPlugin(c,u.fileName,s.defaultEnabled??!0,i.sha256);d.ok?f.info("[agent:%s] \u5DF2\u90E8\u7F72\u63D2\u4EF6\u81EA\u52A8\u5BF9\u8D26\u66F4\u65B0\u6210\u529F: %s",e.agentId,d.pluginName??r):f.warn("[agent:%s] \u5DF2\u90E8\u7F72\u63D2\u4EF6\u66F4\u65B0\u5931\u8D25: %s: %s",e.agentId,r,d.error)}catch(a){f.warn("[agent:%s] \u5DF2\u90E8\u7F72\u63D2\u4EF6 %s \u66F4\u65B0\u5931\u8D25: %s",e.agentId,r,a instanceof Error?a.message:String(a))}finally{this.templatePullInFlight.delete(r),await C(o,3,100).catch(()=>{})}}}queueTemplatePull(e){this.backgroundTemplatePulls.has(e.agentId)||(this.backgroundTemplatePulls.add(e.agentId),this.pullTemplatePluginsFromCapabilities(e).catch(t=>{f.warn("[agent:%s] \u540E\u53F0\u63D2\u4EF6\u5BF9\u8D26\u66F4\u65B0\u5931\u8D25: %s",e.agentId,t instanceof Error?t.message:String(t))}).finally(()=>{this.backgroundTemplatePulls.delete(e.agentId)}))}async syncSharedIntoState(e){this.queueTemplatePull(e);const t=this.readSharedManifest(),n=new Set,r=[];let i=0;for(const s of t)if(n.add(s.pluginName),this.effectiveSharedEnabled(e.agentId,s)){const a=e.plugins.get(s.pluginName);if(!this.ensureRuntimeLink(e.agentId,s.pluginName))continue;const u=this.runtimeLinkPath(e.agentId,s.pluginName);if(!a){const c=this.loadPluginFromDir(e,u,`shared:${s.fileName}`,new Date().toISOString(),{});c.ok?(e.plugins.set(c.plugin.name,c.plugin),r.push(c.plugin.name),f.info("[agent:%s] \u5DF2\u90E8\u7F72\u63D2\u4EF6\u5DF2\u6309\u5F00\u542F\u6001\u52A0\u8F7D: %s",e.agentId,s.pluginName)):f.warn("[agent:%s] \u5DF2\u90E8\u7F72\u63D2\u4EF6\u52A0\u8F7D\u5931\u8D25: %s: %s",e.agentId,s.pluginName,c.error)}}else{const a=e.plugins.get(s.pluginName);a&&(this.stopAllListeners(a),e.plugins.delete(s.pluginName),i++),this.removeRuntimeLink(e.agentId,s.pluginName)}return this.cleanupRuntimeDir(e,n),(r.length>0||i>0)&&this.bumpCatalogRevision(e),this.persistInstalled(e),r}cleanupRuntimeDir(e,t){const n=this.runtimeDirFor(e.agentId);try{if(!w(n))return;const r=new Set(t);for(const i of x(n))!r.has(i)&&!e.plugins.has(i)&&this.removeRuntimeLink(e.agentId,i)}catch{}}async applyCapabilities(e){const t=await this.hydrate(e);await this.pullTemplatePluginsFromCapabilities(t),await this.syncSharedIntoState(t)}exposePlugin(e,t){if(!t)return;const n=this.agentState(e);n.pendingExposed.add(t),n.exposedThisSession.add(t),f.debug("[agent:%s] \u63D2\u4EF6\u5DF2\u89E6\u53D1\u5F85\u66B4\u9732: %s",e,t)}async drainEvents(e,t={}){const n=await this.hydrate(e);this.ensureListenersRunning(n);const r=n.buffer.drain(t),i=await this.consumeExposedCatalog(n);return{revision:r.revision,events:r.events,catalog:i,compactionSeq:n.compactionSeq}}async consumeExposedCatalog(e){if(e.pendingExposed.size===0)return null;const t=await this.getCatalog(e.agentId),n=[...e.pendingExposed];e.pendingExposed.clear();const r=t.plugins.filter(i=>n.includes(i.plugin));return r.length===0?null:{revision:t.revision,plugins:r}}pushDeprecatedNotice(e,t,n){e.buffer.push({plugin:t,event:"plugin-deprecated",priority:"urgent",receivedAt:Date.now(),message:{msgId:`plugin-deprecated-${t}-${Date.now()}`,channel:"plugin-event",senderId:`plugin:${t}`,senderName:`\u63D2\u4EF6[${t}]`,receiverId:e.agentId||void 0,content:`\u3010\u7CFB\u7EDF\u63D0\u793A\u3011\u63D2\u4EF6 ${t} ${n}\uFF0C\u5176\u63D0\u4F9B\u7684\u5DE5\u5177\u4E0D\u518D\u53EF\u8C03\u7528\u3002\u5982\u4ECD\u9700\u4F7F\u7528\u8BF7\u91CD\u65B0\u5B89\u88C5/\u542F\u7528\u8BE5\u63D2\u4EF6\u3002`,requireReply:!1,role:"system",timestamp:new Date().toISOString()}})}markAgentCompacted(e){const t=this.agentState(e);t.compactionSeq++,f.debug("[agent:%s] \u4E0A\u4E0B\u6587\u538B\u7F29\u6807\u8BB0: compactionSeq=%d",e,t.compactionSeq)}async enqueueExternalEvent(e,t,n){const r=await this.hydrate(e),i=r.plugins.get(t);if(!i||!i.enabled)return{ok:!1,error:`\u63D2\u4EF6 ${t} \u672A\u5B89\u88C5\u6216\u5DF2\u505C\u7528`};const s=typeof n.event=="string"?n.event:"",o=i.listeners.find(a=>a.transport.type==="http-callback"&&(!s||a.event===s));return o?(this.enqueueEvent(r,i,o,n),{ok:!0}):{ok:!1,error:`\u63D2\u4EF6 ${t} \u65E0\u5339\u914D\u7684 http-callback \u76D1\u542C\u5668\uFF08event=${s||"(\u7A7A)"}\uFF09`}}bumpCatalogRevision(e){e.catalogRevision++}agentState(e){let t=this.agents.get(e);return t||(t={agentId:e,plugins:new Map,buffer:new ve(e),hydrated:!1,queue:Promise.resolve(),catalogRevision:0,eventSeq:0,compactionSeq:0,pendingExposed:new Set,exposedThisSession:new Set},this.agents.set(e,t)),t}async hydrate(e){const t=this.agentState(e);return t.hydratePromise||(t.hydratePromise=this.doHydrate(t).catch(n=>{throw t.hydratePromise=void 0,n})),await t.hydratePromise,t}async doHydrate(e){const t=e.agentId;await this.migrateLegacySharedIfNeeded();const n=this.installedFile(t);if(!w(n)){await this.syncSharedIntoState(e).catch(()=>{}),e.hydrated=!0;return}try{const r=JSON.parse(k(n,"utf8")),i=this.readSecrets(t);for(const s of r.plugins??[]){if(String(s.source||"").startsWith("shared:"))continue;const a=m(this.rootDir,"cache",N(t),s.name);if(!w(m(a,"plugin.json"))){f.warn("[agent:%s] \u5DF2\u5B89\u88C5\u63D2\u4EF6\u76EE\u5F55\u7F3A\u5931\uFF0C\u8DF3\u8FC7: %s",t,s.name);continue}const u={...s.config,...i[s.name]??{}},c=this.loadPluginFromDir(e,a,s.source,s.installedAt,u);if(c.ok){const d=c.plugin;d.enabled=s.enabled,e.plugins.set(d.name,d)}else f.warn("[agent:%s] \u63D2\u4EF6\u88C5\u8F7D\u5931\u8D25: %s: %s",t,s.name,c.error)}}catch(r){const i=r instanceof Error?r.message:String(r);f.error("[agent:%s] installed.json \u89E3\u6790\u5931\u8D25: %s",t,i)}await this.syncSharedIntoState(e).catch(r=>{f.warn("[agent:%s] \u5171\u4EAB\u63D2\u4EF6\u540C\u6B65\u5931\u8D25: %s",t,r instanceof Error?r.message:String(r))}),e.hydrated=!0}installedFile(e){return m(this.rootDir,"agents",N(e),"installed.json")}persistInstalled(e){this.persistSecrets(e);const t=this.installedFile(e.agentId);T(U(t),{recursive:!0});const n=[...e.plugins.values()].map(r=>({name:r.name,source:r.source,installedAt:r.installedAt,enabled:r.enabled,config:this.stripSensitiveValues(r)}));H(t,`${JSON.stringify({version:1,plugins:n},null,2)}
9
- `,"utf8")}sensitiveKeysOf(e){return(e.userConfig??[]).filter(t=>t?.sensitive===!0&&typeof t.key=="string").map(t=>t.key)}stripSensitiveValues(e){const t=new Set(this.sensitiveKeysOf(e)),n={};for(const[r,i]of Object.entries(e.configValues))t.has(r)||(n[r]=i);return n}secretsFile(e){return m(this.rootDir,"agents",N(e),"secrets.json")}readSecrets(e){try{const t=JSON.parse(k(this.secretsFile(e),"utf8"));if(!v(t)||!v(t.secrets))return{};const n={};for(const[r,i]of Object.entries(t.secrets)){if(!v(i))continue;const s={};for(const[o,a]of Object.entries(i))typeof a=="string"&&(s[o]=a);n[r]=s}return n}catch{return{}}}persistSecrets(e){const t={};for(const r of e.plugins.values()){const i={};for(const s of this.sensitiveKeysOf(r)){const o=r.configValues[s];typeof o=="string"&&o.length>0&&(i[s]=o)}Object.keys(i).length>0&&(t[r.name]=i)}const n=this.secretsFile(e.agentId);if(Object.keys(t).length===0){try{E(n,{force:!0})}catch{}return}T(U(n),{recursive:!0}),H(n,`${JSON.stringify({version:1,secrets:t},null,2)}
10
- `,{encoding:"utf8",mode:384})}readJsonFile(e){if(!w(e))return{ok:!0,data:{}};try{const t=JSON.parse(k(e,"utf8"));return v(t)?{ok:!0,data:t}:{ok:!1,error:`${e}: \u6839\u8282\u70B9\u987B\u4E3A\u5BF9\u8C61`}}catch(t){const n=t instanceof Error?t.message:String(t);return{ok:!1,error:`${e}: JSON \u89E3\u6790\u5931\u8D25: ${n}`}}}loadManifestOnly(e){const t=this.readJsonFile(m(e,"plugin.json"));if(!t.ok)return t;const n=t.data,r=_e(n);return r?{ok:!1,error:r}:{ok:!0,manifest:n}}validateUserConfigValues(e,t){const n=Array.isArray(e.userConfig)?e.userConfig:[],r={...t};for(const i of n){if(!i||typeof i.key!="string"||!/^[A-Za-z_][A-Za-z0-9_]*$/.test(i.key))return"plugin.json: userConfig.key \u975E\u6CD5\uFF08\u987B\u4E3A\u73AF\u5883\u53D8\u91CF\u540D\uFF09";if(!(typeof r[i.key]=="string"&&r[i.key].length>0)&&i.required){const o=i.default!==void 0&&typeof i.default=="string"?i.default:"";if(!o)return`\u7F3A\u5C11\u5FC5\u9700\u914D\u7F6E ${i.key}${i.description?`\uFF08${i.description}\uFF09`:""}\uFF0C\u5B89\u88C5\u65F6\u8BF7\u5728 config \u4E2D\u63D0\u4F9B`;r[i.key]=o}}return null}loadPluginFromDir(e,t,n,r,i){const s=this.loadManifestOnly(t);if(!s.ok)return s;const o=s.manifest,a=m(t,o.tools??"tools/tools.json"),u=this.readJsonFile(a);if(!u.ok)return u;const c=[],d=Array.isArray(u.data.tools)?u.data.tools:[];for(const S of d){const L=Fe(S);if(L)return{ok:!1,error:`${o.tools??"tools/tools.json"}: ${L}`};c.push(S)}const y=m(t,o.listeners??"listeners/listeners.json"),p=this.readJsonFile(y);if(!p.ok)return p;const g=[],h=Array.isArray(p.data.listeners)?p.data.listeners:[];for(const S of h){const L=xe(S);if(L)return{ok:!1,error:`${o.listeners??"listeners/listeners.json"}: ${L}`};g.push(S)}const P=Array.isArray(o.userConfig)?o.userConfig:[],A=this.validateUserConfigValues(o,i);if(A)return{ok:!1,error:A};const O={...i};for(const S of P){if(!S||typeof S.key!="string")continue;!(typeof O[S.key]=="string"&&O[S.key].length>0)&&S.required&&S.default!==void 0&&typeof S.default=="string"&&(O[S.key]=S.default)}const M=o.commands;let K;if(typeof M=="string"&&M.trim()){const S=m(t,M.trim());w(S)&&(K=S)}return{ok:!0,plugin:{name:o.name,version:typeof o.version=="string"?o.version:void 0,description:typeof o.description=="string"?o.description:void 0,source:n,installedAt:r,dir:t,enabled:!0,tools:c,listeners:g,commandDir:K,userConfig:P,configValues:O,status:"enabled",runtimes:g.map(S=>({def:S,stopping:!1,restarts:0,logs:[]})),moduleCache:new Map,importNonce:++this.moduleNonce}}}ensureListenersRunning(e){for(const t of e.plugins.values())if(t.enabled)for(const n of t.runtimes)!n.child&&!n.timer&&!n.backoffTimer&&!n.stopping&&this.startListener(e,t,n)}startAllListeners(e,t){for(const n of t.runtimes)this.stopListener(n),t.enabled&&this.startListener(e,t,n)}stopAllListeners(e){for(const t of e.runtimes)this.stopListener(t)}startListener(e,t,n){const r=n.def.transport??{type:"command-stream"};if(r.type==="http-callback"){n.stopping=!1;return}if(r.type==="poll-command"){const i=Math.max(5e3,r.intervalMs??3e4);n.stopping=!1,n.timer=setInterval(()=>{this.pollListenerOnce(e,t,n)},i),this.pollListenerOnce(e,t,n);return}if(!r.command){n.lastError="command-stream \u7F3A\u5C11 command",b(n,`ERROR ${n.lastError}`);return}n.stopping=!1,this.spawnListenerChild(e,t,n)}spawnListenerChild(e,t,n){const i=n.def.transport?.command??"",s=Y(i,{});try{b(n,`spawn: ${s.join(" ")}`);const o=_(s[0],s.slice(1),{cwd:t.dir,env:this.buildPluginEnv(t,e.agentId),shell:!1,windowsHide:!0,stdio:["ignore","pipe","pipe"]});n.child=o,n.lastError=void 0;let a="";o.stdout?.on("data",u=>{a+=u.toString("utf8");let c=a.indexOf(`
6
+ - action=uninstall\uFF1A\u5378\u8F7D\u5E76\u5220\u9664\u63D2\u4EF6\u76EE\u5F55\uFF08\u4E0D\u53EF\u9006\uFF0C\u9700\u7528\u6237\u660E\u786E\u8981\u6C42\uFF09\u3002`,ke={type:"object",properties:{action:{type:"string",enum:["install","uninstall","reload","enable","disable","list"],description:"\u751F\u547D\u5468\u671F\u52A8\u4F5C"},name:{type:"string",description:"\u63D2\u4EF6\u540D\uFF08uninstall/reload/enable/disable \u5FC5\u586B\uFF09"},source:{type:"string",description:'install \u6765\u6E90\uFF0C\u5F53\u524D\u652F\u6301 "local:<\u4EFB\u610F\u63D2\u4EF6\u76EE\u5F55\u7EDD\u5BF9\u8DEF\u5F84>"\uFF08\u5B89\u88C5\u65F6\u81EA\u52A8\u79FB\u52A8\u5230\u672C agent \u63D2\u4EF6\u4F4D\u7F6E\u540E\u52A0\u8F7D\uFF09'},config:{type:"object",description:"install \u65F6\u63D2\u4EF6 userConfig \u58F0\u660E\u7684\u914D\u7F6E\u503C\uFF08\u952E\u503C\u5BF9\uFF09",additionalProperties:{type:"string"}}},required:["action"],additionalProperties:!1},Pe=new Set(["install","uninstall","reload","enable","disable","list"]);function ee(){const l=fe();return l&&l!=="unknown"?l:void 0}function be(){return oe(new URL("./builtin-commands/",import.meta.url))}const Ee=200,M=256*1024,De=4*1024,te=6e4,z=6e4,Ae=/^[a-zA-Z0-9_][a-zA-Z0-9_-]*$/,H=/^[a-z0-9][a-z0-9-]*$/,Ne=["system.","aws-","acode-"],Ce=/^[A-Za-z_][A-Za-z0-9_]*$/,Le=process.platform==="win32"?"junction":"dir",Ie=/[^\x20-\x7E]/,Oe=6e4,V=20,ne=80;function v(l){return typeof l=="object"&&l!==null&&!Array.isArray(l)}function O(l,e){let t=l;for(const n of e.split(".")){if(!v(t))return;t=t[n]}return t}function D(l,e){return l.length<=e?l:`${l.slice(0,e)}\u2026(\u622A\u65AD,\u5171 ${l.length} \u5B57\u7B26)`}async function T(l,e=8,t=200){for(let n=0;;n++)try{P(l,{recursive:!0,force:!0});return}catch(r){if(n>=e-1)throw r;await new Promise(i=>setTimeout(i,t))}}async function re(l,e){N(J(e),{recursive:!0});try{j(l,e);return}catch(t){const n=t?.code;if(!n||!["EXDEV","EPERM","EACCES","EBUSY","EINVAL"].includes(n))throw t}F(l,e,{recursive:!0,filter:t=>!/[\\/]\.git([\\/]|$)/.test(t)&&!/[\\/]node_modules([\\/]|$)/.test(t)}),await T(l)}function A(l,e){l.logs.push(`${new Date().toISOString()} ${e}`),l.logs.length>Ee&&l.logs.shift()}function G(l,e,t="params"){if(!v(l))return[];const n=[],r=l.type;if(typeof r=="string"&&!Te(r,e))return[`${t}: \u671F\u671B ${r}\uFF0C\u5B9E\u9645 ${Me(e)}`];if(Array.isArray(l.enum)&&l.enum.length>0&&(l.enum.some(s=>JSON.stringify(s)===JSON.stringify(e))||n.push(`${t}: \u503C ${JSON.stringify(e)} \u4E0D\u5728\u679A\u4E3E ${JSON.stringify(l.enum)} \u5185`)),r==="object"&&v(e)){const i=v(l.properties)?l.properties:{},s=Array.isArray(l.required)?l.required:[];for(const o of s)(!(o in e)||e[o]===void 0)&&n.push(`${t}.${o}: \u5FC5\u586B\u53C2\u6570\u7F3A\u5931`);for(const[o,a]of Object.entries(i))o in e&&e[o]!==void 0&&n.push(...G(a,e[o],`${t}.${o}`));if(l.additionalProperties===!1)for(const o of Object.keys(e))o in i||n.push(`${t}.${o}: \u4E0D\u5141\u8BB8\u7684\u672A\u77E5\u53C2\u6570\uFF08schema additionalProperties=false\uFF09`)}return r==="array"&&Array.isArray(e)&&v(l.items)&&e.forEach((i,s)=>{n.push(...G(l.items,i,`${t}[${s}]`))}),n}function Te(l,e){switch(l){case"string":return typeof e=="string";case"number":return typeof e=="number"&&Number.isFinite(e);case"boolean":return typeof e=="boolean";case"object":return v(e);case"array":return Array.isArray(e);case"null":return e===null;default:return!0}}function Me(l){return l===null?"null":Array.isArray(l)?"array":typeof l}class Re{constructor(e={}){this.agents=new Map,this.moduleNonce=0,this.templatePullInFlight=new Set,this.backgroundTemplatePulls=new Set,this.rootDir=e.rootDir??de(),this.runtimeRootDir=e.runtimeRootDir}forAgent(e){return{listPlugins:()=>this.list(e),getCatalog:()=>this.getCatalog(e),getToolSchema:t=>this.getToolSchema(e,t),invokeTool:(t,n,r,i)=>this.invokeTool(e,t,n,r,i),manage:t=>this.manage(e,t),getCommandDirs:()=>this.getCommandDirs(e),exposePlugin:t=>this.exposePlugin(e,t)}}setOnPluginsChanged(e){this.onPluginsChanged=e}notifyPluginsChanged(e){try{this.onPluginsChanged?.(e)}catch(t){f.warn("[agent:%s] onPluginsChanged \u56DE\u8C03\u5931\u8D25: %s",e,t instanceof Error?t.message:String(t))}}async getCommandDirs(e){return[...(await this.hydrate(e)).plugins.values()].filter(n=>n.enabled&&n.commandDir).map(n=>n.commandDir)}async getPluginCommands(e){const t=await this.hydrate(e),n=[],r=be(),i=this.parseCommandDir(k,r);i.length===0&&f.warn("[plugin-manager] \u5185\u7F6E\u547D\u4EE4\u76EE\u5F55\u4E0D\u53EF\u8BFB\u6216\u4E3A\u7A7A: %s\uFF08/create-plugin \u4E0D\u53EF\u7528\uFF0C\u8BF7\u68C0\u67E5\u5B89\u88C5\u5305\u662F\u5426\u5B8C\u6574\uFF09",r),n.push(...i);for(const s of t.plugins.values())!s.enabled||!s.commandDir||n.push(...this.parsePluginCommandDir(s));return n}parsePluginCommandDir(e){return this.parseCommandDir(e.name,e.commandDir)}parseCommandDir(e,t){const n=[];if(!t)return n;try{for(const r of x(t)){if(!r.endsWith(".md"))continue;const i=m(t,r);try{const s=le(i,b(i,"utf8"));s.plugin=e,n.push(s)}catch(s){f.warn("[plugin:%s] \u547D\u4EE4\u89E3\u6790\u5931\u8D25 %s: %s",e,r,s instanceof Error?s.message:String(s))}}}catch{}return n}async list(e){const t=await this.hydrate(e),n=new Map;for(const r of t.plugins.values()){const i=this.toSummary(r);n.set(i.name,i)}n.has(k)||n.set(k,{name:k,version:ee(),description:X,status:"enabled",enabled:!0,source:"builtin",installedAt:new Date().toISOString(),toolCount:1,tools:[{name:"plugin-manager.manage",description:"\u63D2\u4EF6\u751F\u547D\u5468\u671F\u7BA1\u7406\uFF08install/uninstall/reload/disable/enable/list\uFF09"}],listeners:[],builtin:!0});for(const r of this.readSharedManifest()){const i=r.pluginName;if(!this.deployedPluginHealthy(i))continue;const o=n.get(i);if(o){String(o.source||"").startsWith("shared:")&&(o.enabled=this.effectiveSharedEnabled(e,r));continue}n.set(i,{name:i,version:this.deployedPluginVersion(i),status:"enabled",enabled:this.effectiveSharedEnabled(e,r),source:`shared:${r.fileName??`${i}.zip`}`,installedAt:new Date().toISOString(),toolCount:0,listeners:[]})}return[...n.values()].sort((r,i)=>r.name.localeCompare(i.name))}deployedPluginVersion(e){try{const t=JSON.parse(b(m(this.deployedPluginDir(e),"plugin.json"),"utf8"));return typeof t.version=="string"?t.version:void 0}catch{return}}async getCatalog(e){const t=await this.hydrate(e),n=[];for(const r of t.plugins.values()){if(!r.enabled||r.status==="error")continue;const i=r.tools.slice(0,V).map(s=>({name:s.name,description:D(s.title||s.description,ne),requiredParams:this.requiredParamsOf(s)}));r.tools.length>V&&i.push({name:`(\u53E6\u6709 ${r.tools.length-V} \u4E2A\u5DE5\u5177\u672A\u5217\u51FA)`,description:'\u7528 function_call {action:"catalog"} \u67E5\u770B\u5168\u91CF',requiredParams:void 0}),n.push({plugin:r.name,version:r.version,description:r.description,status:r.status,tools:i})}return n.push({plugin:k,version:ee(),description:X,status:"enabled",tools:[{name:"manage",description:D(Q,ne),requiredParams:["action"]}]}),{revision:t.catalogRevision,plugins:n}}async getToolSchema(e,t){const n=ue(t);if(!n)return null;if(n.plugin===k&&n.tool==="manage")return{plugin:k,name:"manage",description:Q,inputSchema:ke};const i=(await this.hydrate(e)).plugins.get(n.plugin);if(!i||!i.enabled)return null;const s=i.tools.find(o=>o.name===n.tool);return s?{plugin:i.name,name:s.name,title:s.title,description:s.description,inputSchema:s.inputSchema??{type:"object",properties:{}}}:null}async invokeTool(e,t,n,r,i){if(t===k&&n==="manage"){const u=this.buildManageRequest(r);if(!u)return{ok:!1,error:"plugin-manager.manage \u7F3A\u5C11 action"};const c=await this.manage(e,u);if(!c.ok)return{ok:!1,error:c.error??"\u63D2\u4EF6\u7BA1\u7406\u64CD\u4F5C\u5931\u8D25"};const d={ok:!0};return c.plugins&&(d.plugins=c.plugins),c.summary&&(d.summary=c.summary),{ok:!0,result:d}}const s=await this.hydrate(e),o=s.plugins.get(t);if(!o)return{ok:!1,error:`\u63D2\u4EF6 ${t} \u672A\u5B89\u88C5\uFF08\u53EF\u7528\u63D2\u4EF6: ${[...s.plugins.keys()].join(", ")||"\u65E0"}\uFF09`};if(!o.enabled)return{ok:!1,error:`\u63D2\u4EF6 ${t} \u5DF2\u505C\u7528\uFF0C\u53EF\u8BA9\u7528\u6237\u5728\u9762\u677F\u6216\u7528 plugin-manager.manage enable \u542F\u7528`};const a=o.tools.find(u=>u.name===n);if(!a)return{ok:!1,error:`\u63D2\u4EF6 ${t} \u65E0\u5DE5\u5177 ${n}\uFF08\u53EF\u7528: ${o.tools.map(u=>u.name).join(", ")||"\u65E0"}\uFF09`};if(a.inputSchema){const u=G(a.inputSchema,r);if(u.length>0)return{ok:!1,error:`\u53C2\u6570\u6821\u9A8C\u5931\u8D25: ${u.join("; ")}`,inputSchema:a.inputSchema}}return this.executeHandler(e,o,a,r,i)}buildManageRequest(e){const t=e.action;if(typeof t!="string"||!Pe.has(t))return null;const n={action:t};if(typeof e.name=="string"&&e.name.trim()&&(n.name=e.name.trim()),typeof e.source=="string"&&e.source.trim()&&(n.source=e.source.trim()),e.config&&typeof e.config=="object"&&!Array.isArray(e.config)){const r={};for(const[i,s]of Object.entries(e.config))typeof s=="string"&&(r[i]=s);n.config=r}return n}async executeHandler(e,t,n,r,i){const s=Date.now(),o=n.handler??{type:"process"};try{return o.type==="mcp"?{ok:!1,error:"handler.type=mcp \u5C06\u5728\u540E\u7EED\u7248\u672C\u652F\u6301\uFF0C\u8BF7\u6539\u7528 process/module handler"}:o.type==="module"?{ok:!0,result:await this.invokeModuleHandler(t,o,r,e,i),durationMs:Date.now()-s}:!o.command||!o.command.trim()?{ok:!1,error:`\u5DE5\u5177 ${n.name} \u7684 process handler \u7F3A\u5C11 command`}:{ok:!0,result:await this.invokeProcessHandler(t,o,r,e,i),durationMs:Date.now()-s}}catch(a){return{ok:!1,error:a instanceof Error?a.message:String(a),durationMs:Date.now()-s}}}async invokeProcessHandler(e,t,n,r,i){const s=K(t.command??"",{params:n});if(s.length===0)throw new Error("process handler command \u4E3A\u7A7A");const o=typeof t.timeoutMs=="number"&&t.timeoutMs>0?t.timeoutMs:te,a=new AbortController,u=()=>a.abort();i?.signal?.addEventListener("abort",u,{once:!0});const c=setTimeout(()=>a.abort(),o);try{return await new Promise((d,y)=>{f.info("[plugin:%s] spawn: %s",e.name,s.join(" "));const p=_(s[0],s.slice(1),{cwd:e.dir,env:this.buildPluginEnv(e,r),shell:t.shell===!0,windowsHide:!0,signal:a.signal});let g="",h="";p.stdin?.on("error",()=>{}),p.stdout?.on("data",$=>{g.length<M&&(g+=$.toString("utf8"))}),p.stderr?.on("data",$=>{h.length<M&&(h+=$.toString("utf8"))}),p.on("error",$=>{y(new Error(`\u63D2\u4EF6\u8FDB\u7A0B\u542F\u52A8\u5931\u8D25: ${$.message}`))}),p.on("close",$=>{const E=g.trim();if($!==0){const C=D(h.trim()||E||"(\u65E0\u8F93\u51FA)",600);y(new Error(a.signal.aborted?`\u63D2\u4EF6\u8FDB\u7A0B\u8D85\u65F6(${o}ms)\u6216\u88AB\u4E2D\u6B62`:`\u63D2\u4EF6\u8FDB\u7A0B\u9000\u51FA\u7801 ${$}: ${C}`));return}if(!E){d({ok:!0});return}try{d(JSON.parse(E))}catch{d(E)}});try{t.stdin==="params"?p.stdin?.end(`${JSON.stringify(n)}
7
+ `):p.stdin?.end()}catch{}})}finally{clearTimeout(c),i?.signal?.removeEventListener("abort",u)}}async invokeModuleHandler(e,t,n,r,i){if(!t.module)throw new Error("module handler \u7F3A\u5C11 module \u8DEF\u5F84");const s=m(e.dir,t.module);let o=e.moduleCache.get(s);o||(o=await import(`${ae(s).href}?acode_nonce=${e.importNonce}`),e.moduleCache.set(s,o));const a=t.export||"default",c=o[a];if(typeof c!="function")throw new Error(`\u6A21\u5757 ${t.module} \u672A\u5BFC\u51FA\u51FD\u6570 ${a}`);const d=typeof t.timeoutMs=="number"&&t.timeoutMs>0?t.timeoutMs:te;let y;const p=Promise.resolve().then(()=>c(n,{agentId:r,signal:i?.signal,pluginRoot:e.dir}));try{return await Promise.race([p,new Promise((g,h)=>{y=setTimeout(()=>h(new Error(`\u63D2\u4EF6\u6A21\u5757\u6267\u884C\u8D85\u65F6(${d}ms)`)),d)})])}finally{clearTimeout(y)}}buildPluginEnv(e,t){const n={};for(const i of["PATH","HOME","USERPROFILE","SystemRoot","COMSPEC","TEMP","TMP","LANG","TZ"]){const s=process.env[i];s!==void 0&&(n[i]=s)}n.ACODE_PLUGIN_ROOT=e.dir,n.ACODE_AGENT_ID=t,n.ACODE_PLUGIN_NAME=e.name;const r=new Set((e.userConfig??[]).map(i=>i.key));for(const[i,s]of Object.entries(e.configValues))r.has(i)&&(!Ce.test(i)||he.has(i.toUpperCase())||(n[i]=s));return n}async manage(e,t){const n=this.agentState(e),r=n.queue.then(async()=>{const i=await this.hydrate(e);return this.doManage(i,t)});return n.queue=r.catch(()=>{}),r}async doManage(e,t){if(t.name===k&&(t.action==="uninstall"||t.action==="disable"||t.action==="enable"||t.action==="reload"))return{ok:!1,error:`\u5185\u7F6E\u7CFB\u7EDF\u63D2\u4EF6 ${k} \u4E0D\u53EF${t.action==="uninstall"?"\u5378\u8F7D":t.action==="reload"?"\u91CD\u8F7D":"\u505C\u7528/\u542F\u7528"}`};switch(t.action){case"list":return{ok:!0,plugins:await this.list(e.agentId)};case"install":return this.installPlugin(e,t);case"uninstall":return this.uninstallPlugin(e,t);case"reload":return this.reloadPlugin(e,t);case"enable":case"disable":return this.setEnabled(e,t,t.action==="enable");default:return{ok:!1,error:`\u672A\u77E5 action: ${String(t.action)}`}}}async installPlugin(e,t){const n=(t.source??"").trim();if(!n)return{ok:!1,error:"install \u9700\u8981 source\uFF08\u5F53\u524D\u652F\u6301 local:<\u63D2\u4EF6\u76EE\u5F55\u7EDD\u5BF9\u8DEF\u5F84>\uFF09"};const r=n.split(":",1)[0];if(r!=="local")return{ok:!1,error:`\u6682\u4E0D\u652F\u6301\u63D2\u4EF6\u6765\u6E90 "${r}:"\uFF08npm:/git: \u5728\u8DEF\u7EBF\u56FE\u4E2D\uFF1Bzip \u5305\u8BF7\u7528\u9762\u677F\u5BFC\u5165\u6216 POST /runtime/plugins/:agentId/upload\uFF09`};const i=n.slice(6).trim();return!i||!w(m(i,"plugin.json"))?{ok:!1,error:`\u63D2\u4EF6\u76EE\u5F55\u4E0D\u5B58\u5728\u6216\u7F3A\u5C11 plugin.json: ${i}`}:this.installFromDirectory(e,i,n,t.config)}async installFromZip(e,t,n,r){if(!t||t.length===0)return{ok:!1,error:"zip \u5305\u5185\u5BB9\u4E3A\u7A7A"};const i=this.agentState(e),s=i.queue.then(async()=>{await this.hydrate(e);const o=m(this.rootDir,"tmp",`upload-${Date.now()}-${Math.random().toString(36).slice(2,8)}`);try{const a=await U(t,o);return w(m(a.pluginDir,"plugin.json"))?(f.info("[agent:%s] zip \u5BFC\u5165: %s\uFF08%d \u4E2A\u6587\u4EF6\uFF09",e,n,a.fileCount),await this.installFromDirectory(i,a.pluginDir,`upload:${n}`,r)):{ok:!1,error:"zip \u5185\u672A\u627E\u5230 plugin.json\uFF08\u8BF7\u6253\u5305\u63D2\u4EF6\u76EE\u5F55\uFF0C\u4E14 zip \u5185\u8DEF\u5F84\u4F7F\u7528\u82F1\u6587\uFF09"}}catch(a){const u=a instanceof Error?a.message:String(a);return f.warn("[agent:%s] zip \u5BFC\u5165\u5931\u8D25: %s",e,u),{ok:!1,error:`zip \u5BFC\u5165\u5931\u8D25: ${u}`}}finally{await T(o,3,100).catch(()=>{})}});return i.queue=s.catch(()=>{}),s}async installFromDirectory(e,t,n,r){const i=this.loadManifestOnly(t);if(!i.ok)return i;const s=i.manifest,o=s.name;if(o===k)return{ok:!1,error:`\u63D2\u4EF6\u540D ${o} \u4E3A\u7CFB\u7EDF\u4FDD\u7559\u540D\u79F0\uFF0C\u4E0D\u5141\u8BB8\u5B89\u88C5\u540C\u540D\u63D2\u4EF6`};const a=this.validateUserConfigValues(s,r??{});if(a)return{ok:!1,error:a};const u=this.loadPluginFromDir(e,t,n,new Date().toISOString(),r??{});if(!u.ok)return f.warn("[agent:%s] \u63D2\u4EF6\u88C5\u8F7D\u6821\u9A8C\u5931\u8D25\uFF08%s\uFF09: %s",e.agentId,n,u.error),u;const c=m(this.rootDir,"cache",I(e.agentId),o),d=t===c,y=e.plugins.get(o);if(y&&this.stopAllListeners(y),!d)try{await T(c),await re(t,c)}catch(h){const $=h instanceof Error?h.message:String(h);return f.warn("[agent:%s] \u63D2\u4EF6\u79FB\u52A8\u5931\u8D25\uFF08%s\uFF09: %s",e.agentId,n,$),y&&this.startAllListeners(e,y),{ok:!1,error:`\u63D2\u4EF6\u79FB\u52A8\u5931\u8D25: ${$}`}}const p=this.loadPluginFromDir(e,c,n,new Date().toISOString(),r??{});if(!p.ok){if(f.warn("[agent:%s] \u63D2\u4EF6\u88C5\u8F7D\u5931\u8D25\uFF08%s\uFF09: %s",e.agentId,n,p.error),!d)try{await re(c,t)}catch(h){f.warn("[agent:%s] \u88C5\u8F7D\u5931\u8D25\u540E\u65E0\u6CD5\u79FB\u56DE\u6E90\u76EE\u5F55\uFF08%s\uFF09\uFF0C\u5DF2\u4FDD\u7559\u7F13\u5B58\u526F\u672C",e.agentId,h instanceof Error?h.message:String(h))}if(y)try{this.startAllListeners(e,y)}catch(h){f.warn("[agent:%s] \u6062\u590D\u65E7\u5B9E\u4F8B\u76D1\u542C\u5931\u8D25: %s",e.agentId,h instanceof Error?h.message:String(h))}return p}const g=p.plugin;return e.plugins.set(g.name,g),this.bumpCatalogRevision(e),this.persistInstalled(e),this.startAllListeners(e,g),f.info("[agent:%s] \u63D2\u4EF6\u5DF2\u5B89\u88C5: %s@%s",e.agentId,g.name,g.version??"?"),this.notifyPluginsChanged(e.agentId),{ok:!0,summary:this.toSummary(g)}}async uninstallPlugin(e,t){const n=(t.name??"").trim(),r=e.plugins.get(n);return r?(this.stopAllListeners(r),e.plugins.delete(n),e.pendingExposed.delete(n),e.exposedThisSession.has(n)&&this.pushDeprecatedNotice(e,n,"\u5DF2\u88AB\u5378\u8F7D"),this.bumpCatalogRevision(e),this.readSharedManifest().some(s=>s.pluginName===n)&&this.removeRuntimeLink(e.agentId,n),this.persistInstalled(e),await T(r.dir),f.info("[agent:%s] \u63D2\u4EF6\u5DF2\u5378\u8F7D: %s",e.agentId,n),this.notifyPluginsChanged(e.agentId),{ok:!0}):{ok:!1,error:`\u63D2\u4EF6 ${n} \u672A\u5B89\u88C5`}}async reloadPlugin(e,t){const n=(t.name??"").trim(),r=e.plugins.get(n);if(!r)return{ok:!1,error:`\u63D2\u4EF6 ${n} \u672A\u5B89\u88C5`};const i=this.loadPluginFromDir(e,r.dir,r.source,r.installedAt,r.configValues);if(!i.ok)return{ok:!1,error:`\u91CD\u8F7D\u5931\u8D25\uFF08\u4FDD\u7559\u65E7\u7248\u672C\u8FD0\u884C\uFF09: ${i.error}`};const s=i.plugin;return this.stopAllListeners(r),e.plugins.set(n,s),this.bumpCatalogRevision(e),this.persistInstalled(e),this.startAllListeners(e,s),f.info("[agent:%s] \u63D2\u4EF6\u5DF2\u91CD\u8F7D: %s",e.agentId,n),this.notifyPluginsChanged(e.agentId),{ok:!0,summary:this.toSummary(s)}}async setEnabled(e,t,n){const r=(t.name??"").trim(),i=e.plugins.get(r);return i?(i.enabled=n,this.bumpCatalogRevision(e),n?this.startAllListeners(e,i):(e.pendingExposed.delete(r),e.exposedThisSession.has(r)&&this.pushDeprecatedNotice(e,r,"\u5DF2\u505C\u7528"),this.stopAllListeners(i)),this.persistInstalled(e),this.notifyPluginsChanged(e.agentId),{ok:!0,summary:this.toSummary(i)}):{ok:!1,error:`\u63D2\u4EF6 ${r} \u672A\u5B89\u88C5`}}deployedDir(){return m(this.rootDir,"deployed")}deployedManifestFile(){return m(this.deployedDir(),"manifest.json")}deployedPluginDir(e){if(!B(e))throw new Error(`\u975E\u6CD5\u63D2\u4EF6\u540D\uFF08\u4EC5\u5141\u8BB8 ${H}\uFF09: ${JSON.stringify(e)}`);const t=m(this.deployedDir(),e),n=Y(this.deployedDir());if(Y(t)!==m(n,e))throw new Error(`\u63D2\u4EF6\u76EE\u5F55\u8D8A\u51FA\u90E8\u7F72\u533A: ${e}`);return t}legacySharedDir(){return m(this.rootDir,"shared")}readSharedManifest(){try{const e=JSON.parse(b(this.deployedManifestFile(),"utf8"));return Array.isArray(e.plugins)?e.plugins.filter(t=>t&&B(t.pluginName)):[]}catch{return[]}}writeSharedManifest(e){N(this.deployedDir(),{recursive:!0}),q(this.deployedManifestFile(),`${JSON.stringify({version:2,plugins:e},null,2)}
8
+ `,"utf8")}async migrateLegacySharedIfNeeded(){try{if(w(this.deployedManifestFile()))return;const e=m(this.legacySharedDir(),"manifest.json");if(!w(e))return;const t=JSON.parse(b(e,"utf8")),n=Array.isArray(t.plugins)?t.plugins:[];if(n.length===0)return;const r=[];for(const i of n){const s=m(this.legacySharedDir(),i.zipFile);if(!(!i.pluginName||!w(s)))try{const o=await this.deployPluginZipToPersistentDir(b(s),i.pluginName);if(!o)continue;r.push(o),f.info("[shared] \u65E7\u5171\u4EAB\u63D2\u4EF6\u8FC1\u79FB\u5230\u90E8\u7F72\u533A: %s",i.pluginName)}catch(o){f.warn("[shared] \u65E7\u5171\u4EAB\u63D2\u4EF6 %s \u8FC1\u79FB\u5931\u8D25: %s",i.pluginName,o instanceof Error?o.message:String(o))}}r.length>0&&this.writeSharedManifest(r),P(this.legacySharedDir(),{recursive:!0,force:!0})}catch(e){f.warn("[shared] \u65E7\u5171\u4EAB\u63D2\u4EF6\u8FC1\u79FB\u672A\u6267\u884C\uFF08\u4E0B\u6B21\u91CD\u8BD5\uFF09: %s",e instanceof Error?e.message:String(e))}}deployedPluginHealthy(e){return w(m(this.deployedPluginDir(e),"plugin.json"))}runtimeDirFor(e){return this.runtimeRootDir?m(this.runtimeRootDir,I(e)):ce(e)}runtimeLinkPath(e,t){return m(this.runtimeDirFor(e),t)}ensureRuntimeLink(e,t){const n=this.runtimeLinkPath(e,t),r=this.deployedPluginDir(t);if(!w(m(r,"plugin.json")))return!1;N(this.runtimeDirFor(e),{recursive:!0});try{if(w(n)){let i=!1;try{i=ie(n).isSymbolicLink()}catch{i=!1}if(i)try{return x(n),!0}catch{}P(n,{recursive:!0,force:!0})}return se(r,n,Le),f.info("[agent:%s] \u63D2\u4EF6\u8FD0\u884C\u65F6\u94FE\u63A5\u5DF2\u5EFA\u7ACB: %s \u2192 %s",e,n,r),!0}catch(i){return f.warn("[agent:%s] \u63D2\u4EF6\u8FD0\u884C\u65F6\u94FE\u63A5\u5931\u8D25\uFF08%s \u2192 %s\uFF09: %s",e,t,r,i instanceof Error?i.message:String(i)),!1}}removeRuntimeLink(e,t){const n=this.runtimeLinkPath(e,t);try{w(n)&&(P(n,{recursive:!0,force:!0}),f.info("[agent:%s] \u63D2\u4EF6\u8FD0\u884C\u65F6\u94FE\u63A5\u5DF2\u79FB\u9664: %s",e,t))}catch(r){f.warn("[agent:%s] \u63D2\u4EF6\u8FD0\u884C\u65F6\u94FE\u63A5\u79FB\u9664\u5931\u8D25\uFF08%s\uFF09: %s",e,t,r instanceof Error?r.message:String(r))}}async saveSharedPlugin(e,t,n=!0,r){if(!e||e.length===0)return{ok:!1,error:"zip \u5305\u5185\u5BB9\u4E3A\u7A7A"};await this.migrateLegacySharedIfNeeded();const i=m(this.rootDir,"tmp",`deploy-${Date.now()}-${Math.random().toString(36).slice(2,8)}`);try{const s=await U(e,i),o=this.loadManifestOnly(s.pluginDir);if(!o.ok)return o;const a=o.manifest.name,u=this.readSharedManifest().find(g=>g.pluginName===a);if(u&&u.sha256===r&&this.deployedPluginHealthy(a))return{ok:!0,pluginName:a};await this.suspendDeployedPluginAcrossAgents(a),N(this.deployedDir(),{recursive:!0});const c=this.deployedPluginDir(a),d=m(this.deployedDir(),`.old-${a}-${Date.now()}-${Math.random().toString(36).slice(2,8)}`);if(w(c))try{j(c,d)}catch{P(c,{recursive:!0,force:!0})}try{F(s.pluginDir,c,{recursive:!0,filter:g=>!/[\\/]\.git([\\/]|$)/.test(g)&&!/[\\/]node_modules([\\/]|$)/.test(g)})}catch(g){throw w(d)&&(P(c,{recursive:!0,force:!0}),j(d,c)),g}w(d)&&P(d,{recursive:!0,force:!0}),await W(this.deployedManifestFile(),async()=>{const g=this.readSharedManifest().filter(h=>h.pluginName!==a);g.push({pluginName:a,zipFile:u?.zipFile??`${a}.zip`,fileName:t,defaultEnabled:n,sha256:r}),this.writeSharedManifest(g)}),f.info("[shared] \u63D2\u4EF6\u5DF2\u90E8\u7F72\u5230 bridge: %s\uFF08\u6765\u6E90 %s%s\uFF09",a,t,r?`, sha256=${r.slice(0,12)}\u2026`:"");const p=(await this.applySharedToKnownAgents()).find(g=>g.installed.includes(a));return p&&f.info("[shared] \u5DF2\u540C\u6B65\u5230\u8FD0\u884C\u4E2D agent: %s",p.agentId),{ok:!0,pluginName:a}}catch(s){const o=s instanceof Error?s.message:String(s);return f.warn("[shared] \u63D2\u4EF6\u90E8\u7F72\u5931\u8D25\uFF08%s\uFF09: %s",t,o),{ok:!1,error:`\u63D2\u4EF6\u90E8\u7F72\u5931\u8D25: ${o}`}}finally{await T(i,3,100).catch(()=>{})}}async deployPluginZipToPersistentDir(e,t){if(!e||e.length===0)return null;const n=m(this.rootDir,"tmp",`migrate-${Date.now()}-${Math.random().toString(36).slice(2,8)}`);try{const r=await U(e,n),i=this.loadManifestOnly(r.pluginDir);if(!i.ok)return null;const s=i.manifest.name;if(t&&s!==t)return null;N(this.deployedDir(),{recursive:!0});const o=this.deployedPluginDir(s);return w(o)&&P(o,{recursive:!0,force:!0}),F(r.pluginDir,o,{recursive:!0,filter:a=>!/[\\/]\.git([\\/]|$)/.test(a)&&!/[\\/]node_modules([\\/]|$)/.test(a)}),{pluginName:s,zipFile:`${s}.zip`,fileName:`${s}.zip`,defaultEnabled:!0}}finally{P(n,{recursive:!0,force:!0})}}async suspendDeployedPluginAcrossAgents(e){for(const t of[...this.agents.values()]){if(!t.hydrated)continue;const n=t.queue.then(async()=>{const r=t.plugins.get(e);r&&(this.stopAllListeners(r),t.plugins.delete(e),this.bumpCatalogRevision(t),f.info("[agent:%s] \u5DF2\u6458\u9664\u63D2\u4EF6\u7B49\u5F85\u90E8\u7F72\u533A\u66F4\u65B0: %s",t.agentId,e))});t.queue=n.catch(()=>{}),await n}}async applySharedToKnownAgents(){const e=[];for(const t of this.agents.values()){if(!t.hydrated)continue;const n=await this.syncSharedIntoStateQueued(t);n.length>0&&e.push({agentId:t.agentId,installed:n})}return e}async syncSharedIntoStateQueued(e){const t=e.queue.then(()=>this.syncSharedIntoState(e));return e.queue=t.catch(()=>[]),t}effectiveSharedEnabled(e,t){return we(e,"plugins",t.pluginName)&&(t.defaultEnabled??!0)}async pullTemplatePluginsFromCapabilities(e){const t=ve(e.agentId);if(!t)return;const n=this.readSharedManifest();for(const[r,i]of Object.entries(t)){if(!i.url)continue;const s=n.find(a=>a.pluginName===r);if(!s||!s.sha256||s.sha256===i.sha256&&this.deployedPluginHealthy(r)||this.templatePullInFlight.has(r))continue;this.templatePullInFlight.add(r);const o=m(this.rootDir,"tmp",`pull-${I(e.agentId)}-${Date.now()}-${Math.random().toString(36).slice(2,8)}`);try{N(o,{recursive:!0});let a=`${r}.zip`;try{const y=decodeURIComponent(i.url.split("/").pop()||"");y.toLowerCase().endsWith(".zip")&&(a=pe(y,`${r}.zip`))}catch{}const u=await ge({downloadUrl:i.url,fileName:a,sha256:i.sha256},o);if(!u)continue;const c=b(u.outputPath),d=await this.saveSharedPlugin(c,u.fileName,s.defaultEnabled??!0,i.sha256);d.ok?f.info("[agent:%s] \u5DF2\u90E8\u7F72\u63D2\u4EF6\u81EA\u52A8\u5BF9\u8D26\u66F4\u65B0\u6210\u529F: %s",e.agentId,d.pluginName??r):f.warn("[agent:%s] \u5DF2\u90E8\u7F72\u63D2\u4EF6\u66F4\u65B0\u5931\u8D25: %s: %s",e.agentId,r,d.error)}catch(a){f.warn("[agent:%s] \u5DF2\u90E8\u7F72\u63D2\u4EF6 %s \u66F4\u65B0\u5931\u8D25: %s",e.agentId,r,a instanceof Error?a.message:String(a))}finally{this.templatePullInFlight.delete(r),await T(o,3,100).catch(()=>{})}}}queueTemplatePull(e){this.backgroundTemplatePulls.has(e.agentId)||(this.backgroundTemplatePulls.add(e.agentId),this.pullTemplatePluginsFromCapabilities(e).catch(t=>{f.warn("[agent:%s] \u540E\u53F0\u63D2\u4EF6\u5BF9\u8D26\u66F4\u65B0\u5931\u8D25: %s",e.agentId,t instanceof Error?t.message:String(t))}).finally(()=>{this.backgroundTemplatePulls.delete(e.agentId)}))}async syncSharedIntoState(e){this.queueTemplatePull(e);const t=this.readSharedManifest(),n=new Set,r=[];let i=0;for(const s of t)if(n.add(s.pluginName),this.effectiveSharedEnabled(e.agentId,s)){const a=e.plugins.get(s.pluginName);if(!this.ensureRuntimeLink(e.agentId,s.pluginName))continue;const u=this.runtimeLinkPath(e.agentId,s.pluginName);if(!a){const c=this.loadPluginFromDir(e,u,`shared:${s.fileName}`,new Date().toISOString(),{});c.ok?(e.plugins.set(c.plugin.name,c.plugin),r.push(c.plugin.name),f.info("[agent:%s] \u5DF2\u90E8\u7F72\u63D2\u4EF6\u5DF2\u6309\u5F00\u542F\u6001\u52A0\u8F7D: %s",e.agentId,s.pluginName)):f.warn("[agent:%s] \u5DF2\u90E8\u7F72\u63D2\u4EF6\u52A0\u8F7D\u5931\u8D25: %s: %s",e.agentId,s.pluginName,c.error)}}else{const a=e.plugins.get(s.pluginName);a&&(this.stopAllListeners(a),e.plugins.delete(s.pluginName),i++),this.removeRuntimeLink(e.agentId,s.pluginName)}return this.cleanupRuntimeDir(e,n),(r.length>0||i>0)&&this.bumpCatalogRevision(e),this.persistInstalled(e),r}cleanupRuntimeDir(e,t){const n=this.runtimeDirFor(e.agentId);try{if(!w(n))return;const r=new Set(t);for(const i of x(n))!r.has(i)&&!e.plugins.has(i)&&this.removeRuntimeLink(e.agentId,i)}catch{}}async applyCapabilities(e){const t=await this.hydrate(e);await this.pullTemplatePluginsFromCapabilities(t),await this.syncSharedIntoState(t)}exposePlugin(e,t){if(!t)return;const n=this.agentState(e);n.pendingExposed.add(t),n.exposedThisSession.add(t),f.debug("[agent:%s] \u63D2\u4EF6\u5DF2\u89E6\u53D1\u5F85\u66B4\u9732: %s",e,t)}async drainEvents(e,t={}){const n=await this.hydrate(e);this.ensureListenersRunning(n);const r=n.buffer.drain(t),i=await this.consumeExposedCatalog(n);return{revision:r.revision,events:r.events,catalog:i,compactionSeq:n.compactionSeq}}async consumeExposedCatalog(e){if(e.pendingExposed.size===0)return null;const t=await this.getCatalog(e.agentId),n=[...e.pendingExposed];e.pendingExposed.clear();const r=t.plugins.filter(i=>n.includes(i.plugin));return r.length===0?null:{revision:t.revision,plugins:r}}pushDeprecatedNotice(e,t,n){e.buffer.push({plugin:t,event:"plugin-deprecated",priority:"urgent",receivedAt:Date.now(),message:{msgId:`plugin-deprecated-${t}-${Date.now()}`,channel:"plugin-event",senderId:`plugin:${t}`,senderName:`\u63D2\u4EF6[${t}]`,receiverId:e.agentId||void 0,content:`\u3010\u7CFB\u7EDF\u63D0\u793A\u3011\u63D2\u4EF6 ${t} ${n}\uFF0C\u5176\u63D0\u4F9B\u7684\u5DE5\u5177\u4E0D\u518D\u53EF\u8C03\u7528\u3002\u5982\u4ECD\u9700\u4F7F\u7528\u8BF7\u91CD\u65B0\u5B89\u88C5/\u542F\u7528\u8BE5\u63D2\u4EF6\u3002`,requireReply:!1,role:"system",timestamp:new Date().toISOString()}})}markAgentCompacted(e){const t=this.agentState(e);t.compactionSeq++,f.debug("[agent:%s] \u4E0A\u4E0B\u6587\u538B\u7F29\u6807\u8BB0: compactionSeq=%d",e,t.compactionSeq)}async enqueueExternalEvent(e,t,n){const r=await this.hydrate(e),i=r.plugins.get(t);if(!i||!i.enabled)return{ok:!1,error:`\u63D2\u4EF6 ${t} \u672A\u5B89\u88C5\u6216\u5DF2\u505C\u7528`};const s=typeof n.event=="string"?n.event:"",o=i.listeners.find(a=>a.transport.type==="http-callback"&&(!s||a.event===s));return o?(this.enqueueEvent(r,i,o,n),{ok:!0}):{ok:!1,error:`\u63D2\u4EF6 ${t} \u65E0\u5339\u914D\u7684 http-callback \u76D1\u542C\u5668\uFF08event=${s||"(\u7A7A)"}\uFF09`}}bumpCatalogRevision(e){e.catalogRevision++}agentState(e){let t=this.agents.get(e);return t||(t={agentId:e,plugins:new Map,buffer:new $e(e),hydrated:!1,queue:Promise.resolve(),catalogRevision:0,eventSeq:0,compactionSeq:0,pendingExposed:new Set,exposedThisSession:new Set},this.agents.set(e,t)),t}async hydrate(e){const t=this.agentState(e);return t.hydratePromise||(t.hydratePromise=this.doHydrate(t).catch(n=>{throw t.hydratePromise=void 0,n})),await t.hydratePromise,t}async doHydrate(e){const t=e.agentId;await this.migrateLegacySharedIfNeeded();const n=this.installedFile(t);if(!w(n)){await this.syncSharedIntoState(e).catch(()=>{}),e.hydrated=!0;return}try{const r=JSON.parse(b(n,"utf8")),i=this.readSecrets(t);for(const s of r.plugins??[]){if(String(s.source||"").startsWith("shared:"))continue;const a=m(this.rootDir,"cache",I(t),s.name);if(!w(m(a,"plugin.json"))){f.warn("[agent:%s] \u5DF2\u5B89\u88C5\u63D2\u4EF6\u76EE\u5F55\u7F3A\u5931\uFF0C\u8DF3\u8FC7: %s",t,s.name);continue}const u={...s.config,...i[s.name]??{}},c=this.loadPluginFromDir(e,a,s.source,s.installedAt,u);if(c.ok){const d=c.plugin;d.enabled=s.enabled,e.plugins.set(d.name,d)}else f.warn("[agent:%s] \u63D2\u4EF6\u88C5\u8F7D\u5931\u8D25: %s: %s",t,s.name,c.error)}}catch(r){const i=r instanceof Error?r.message:String(r);f.error("[agent:%s] installed.json \u89E3\u6790\u5931\u8D25: %s",t,i)}await this.syncSharedIntoState(e).catch(r=>{f.warn("[agent:%s] \u5171\u4EAB\u63D2\u4EF6\u540C\u6B65\u5931\u8D25: %s",t,r instanceof Error?r.message:String(r))}),e.hydrated=!0}installedFile(e){return m(this.rootDir,"agents",I(e),"installed.json")}persistInstalled(e){this.persistSecrets(e);const t=this.installedFile(e.agentId);N(J(t),{recursive:!0});const n=[...e.plugins.values()].map(r=>({name:r.name,source:r.source,installedAt:r.installedAt,enabled:r.enabled,config:this.stripSensitiveValues(r)}));q(t,`${JSON.stringify({version:1,plugins:n},null,2)}
9
+ `,"utf8")}sensitiveKeysOf(e){return(e.userConfig??[]).filter(t=>t?.sensitive===!0&&typeof t.key=="string").map(t=>t.key)}stripSensitiveValues(e){const t=new Set(this.sensitiveKeysOf(e)),n={};for(const[r,i]of Object.entries(e.configValues))t.has(r)||(n[r]=i);return n}secretsFile(e){return m(this.rootDir,"agents",I(e),"secrets.json")}readSecrets(e){try{const t=JSON.parse(b(this.secretsFile(e),"utf8"));if(!v(t)||!v(t.secrets))return{};const n={};for(const[r,i]of Object.entries(t.secrets)){if(!v(i))continue;const s={};for(const[o,a]of Object.entries(i))typeof a=="string"&&(s[o]=a);n[r]=s}return n}catch{return{}}}persistSecrets(e){const t={};for(const r of e.plugins.values()){const i={};for(const s of this.sensitiveKeysOf(r)){const o=r.configValues[s];typeof o=="string"&&o.length>0&&(i[s]=o)}Object.keys(i).length>0&&(t[r.name]=i)}const n=this.secretsFile(e.agentId);if(Object.keys(t).length===0){try{P(n,{force:!0})}catch{}return}N(J(n),{recursive:!0}),q(n,`${JSON.stringify({version:1,secrets:t},null,2)}
10
+ `,{encoding:"utf8",mode:384})}readJsonFile(e){if(!w(e))return{ok:!0,data:{}};try{const t=JSON.parse(b(e,"utf8"));return v(t)?{ok:!0,data:t}:{ok:!1,error:`${e}: \u6839\u8282\u70B9\u987B\u4E3A\u5BF9\u8C61`}}catch(t){const n=t instanceof Error?t.message:String(t);return{ok:!1,error:`${e}: JSON \u89E3\u6790\u5931\u8D25: ${n}`}}}loadManifestOnly(e){const t=this.readJsonFile(m(e,"plugin.json"));if(!t.ok)return t;const n=t.data,r=_e(n);return r?{ok:!1,error:r}:{ok:!0,manifest:n}}validateUserConfigValues(e,t){const n=Array.isArray(e.userConfig)?e.userConfig:[],r={...t};for(const i of n){if(!i||typeof i.key!="string"||!/^[A-Za-z_][A-Za-z0-9_]*$/.test(i.key))return"plugin.json: userConfig.key \u975E\u6CD5\uFF08\u987B\u4E3A\u73AF\u5883\u53D8\u91CF\u540D\uFF09";if(!(typeof r[i.key]=="string"&&r[i.key].length>0)&&i.required){const o=i.default!==void 0&&typeof i.default=="string"?i.default:"";if(!o)return`\u7F3A\u5C11\u5FC5\u9700\u914D\u7F6E ${i.key}${i.description?`\uFF08${i.description}\uFF09`:""}\uFF0C\u5B89\u88C5\u65F6\u8BF7\u5728 config \u4E2D\u63D0\u4F9B`;r[i.key]=o}}return null}loadPluginFromDir(e,t,n,r,i){const s=this.loadManifestOnly(t);if(!s.ok)return s;const o=s.manifest,a=m(t,o.tools??"tools/tools.json"),u=this.readJsonFile(a);if(!u.ok)return u;const c=[],d=Array.isArray(u.data.tools)?u.data.tools:[];for(const S of d){const L=Fe(S);if(L)return{ok:!1,error:`${o.tools??"tools/tools.json"}: ${L}`};c.push(S)}const y=m(t,o.listeners??"listeners/listeners.json"),p=this.readJsonFile(y);if(!p.ok)return p;const g=[],h=Array.isArray(p.data.listeners)?p.data.listeners:[];for(const S of h){const L=xe(S);if(L)return{ok:!1,error:`${o.listeners??"listeners/listeners.json"}: ${L}`};g.push(S)}const $=Array.isArray(o.userConfig)?o.userConfig:[],E=this.validateUserConfigValues(o,i);if(E)return{ok:!1,error:E};const C={...i};for(const S of $){if(!S||typeof S.key!="string")continue;!(typeof C[S.key]=="string"&&C[S.key].length>0)&&S.required&&S.default!==void 0&&typeof S.default=="string"&&(C[S.key]=S.default)}const R=o.commands;let Z;if(typeof R=="string"&&R.trim()){const S=m(t,R.trim());w(S)&&(Z=S)}return{ok:!0,plugin:{name:o.name,version:typeof o.version=="string"?o.version:void 0,description:typeof o.description=="string"?o.description:void 0,source:n,installedAt:r,dir:t,enabled:!0,tools:c,listeners:g,commandDir:Z,userConfig:$,configValues:C,status:"enabled",runtimes:g.map(S=>({def:S,stopping:!1,restarts:0,logs:[]})),moduleCache:new Map,importNonce:++this.moduleNonce}}}ensureListenersRunning(e){for(const t of e.plugins.values())if(t.enabled)for(const n of t.runtimes)!n.child&&!n.timer&&!n.backoffTimer&&!n.stopping&&this.startListener(e,t,n)}startAllListeners(e,t){for(const n of t.runtimes)this.stopListener(n),t.enabled&&this.startListener(e,t,n)}stopAllListeners(e){for(const t of e.runtimes)this.stopListener(t)}startListener(e,t,n){const r=n.def.transport??{type:"command-stream"};if(r.type==="http-callback"){n.stopping=!1;return}if(r.type==="poll-command"){const i=Math.max(5e3,r.intervalMs??3e4);n.stopping=!1,n.timer=setInterval(()=>{this.pollListenerOnce(e,t,n)},i),this.pollListenerOnce(e,t,n);return}if(!r.command){n.lastError="command-stream \u7F3A\u5C11 command",A(n,`ERROR ${n.lastError}`);return}n.stopping=!1,this.spawnListenerChild(e,t,n)}spawnListenerChild(e,t,n){const i=n.def.transport?.command??"",s=K(i,{});try{A(n,`spawn: ${s.join(" ")}`);const o=_(s[0],s.slice(1),{cwd:t.dir,env:this.buildPluginEnv(t,e.agentId),shell:!1,windowsHide:!0,stdio:["ignore","pipe","pipe"]});n.child=o,n.lastError=void 0;let a="";o.stdout?.on("data",u=>{a+=u.toString("utf8");let c=a.indexOf(`
11
11
  `);for(;c>=0;){const d=a.slice(0,c).trim();a=a.slice(c+1),d&&this.handleListenerLine(e,t,n,d),c=a.indexOf(`
12
- `)}a.length>1024*1024&&(a=a.slice(-4096))}),o.stderr?.on("data",u=>{b(n,`stderr: ${D(u.toString("utf8").trimEnd(),400)}`)}),o.on("error",u=>{n.lastError=`\u8FDB\u7A0B\u542F\u52A8\u5931\u8D25: ${u.message}`,b(n,`ERROR ${n.lastError}`)}),o.on("close",u=>{n.child=void 0,!n.stopping&&(n.lastError=`\u76D1\u542C\u8FDB\u7A0B\u9000\u51FA\uFF08code=${u??"signal"}\uFF09`,b(n,`exit code=${u??"signal"}\uFF0C\u51C6\u5907\u91CD\u542F`),this.scheduleListenerRestart(e,t,n))})}catch(o){const a=o instanceof Error?o.message:String(o);n.lastError=a,b(n,`ERROR spawn: ${a}`),this.scheduleListenerRestart(e,t,n)}}scheduleListenerRestart(e,t,n){if(n.stopping)return;const r=Math.max(500,n.def.transport?.restartBackoffMs??2e3),i=Math.min(Ie,r*2**Math.min(n.restarts,6));n.restarts++,b(n,`restart #${n.restarts} in ${i}ms`),n.backoffTimer=setTimeout(()=>{n.backoffTimer=void 0,n.stopping||this.spawnListenerChild(e,t,n)},i)}async pollListenerOnce(e,t,n){if(n.polling)return;const r=n.def.transport?.command??"",i=Y(r,{});if(i.length===0)return;n.polling=!0;const s=new AbortController,o=setTimeout(()=>s.abort(),J);try{const a=await new Promise((u,c)=>{const d=_(i[0],i.slice(1),{cwd:t.dir,env:this.buildPluginEnv(t,e.agentId),shell:!1,windowsHide:!0,stdio:["ignore","pipe","pipe"],signal:s.signal});let y="",p="";d.stdout?.on("data",h=>{y.length<R&&(y+=h.toString("utf8"))}),d.stderr?.on("data",h=>{p.length<R&&(p+=h.toString("utf8"))});const g=()=>s.signal.aborted;d.on("error",h=>{c(g()?new Error(`poll \u8D85\u65F6(${J}ms)`):h)}),d.on("close",h=>{g()?c(new Error(`poll \u8D85\u65F6(${J}ms)`)):h===0?u(y):c(new Error(`exit ${h}: ${D(p||y,300)}`))})});n.lastError=void 0;for(const u of a.split(`
13
- `)){const c=u.trim();c&&this.handleListenerLine(e,t,n,c)}}catch(a){const u=a instanceof Error?a.message:String(a);n.lastError=u,b(n,`poll \u5931\u8D25: ${u}`)}finally{clearTimeout(o),n.polling=!1}}stopListener(e){if(e.stopping=!0,e.restarts=0,e.child){try{e.child.kill()}catch{}e.child=void 0}e.timer&&(clearInterval(e.timer),e.timer=void 0),e.backoffTimer&&(clearTimeout(e.backoffTimer),e.backoffTimer=void 0)}handleListenerLine(e,t,n,r){b(n,`event: ${D(r,300)}`);let i;try{i=JSON.parse(r)}catch{n.lastError="\u4E8B\u4EF6\u884C\u4E0D\u662F\u5408\u6CD5 JSON\uFF08\u8981\u6C42 JSONL\uFF09";return}if(!v(i))return;const s=typeof i.event=="string"?i.event:n.def.event,o=s===n.def.event?n.def:t.listeners.find(a=>a.event===s);o&&(o.delivery&&o.delivery!=="poll"&&f.debug("[plugin:%s] delivery=%s \u6682\u6309 poll \u4EA4\u4ED8",t.name,o.delivery),this.enqueueEvent(e,t,o,i))}enqueueEvent(e,t,n,r){for(const[p,g]of Object.entries(n.matcher??{})){const h=I(r,p);if(!(Array.isArray(g)?g:[g]).some(A=>JSON.stringify(A)===JSON.stringify(h)))return}let i;if(n.dedupKey){const p=I(r,n.dedupKey);p!=null&&(i=D(String(p),256))}e.eventSeq++;const s=D(He(r.data??r),Ae),o=n.promptTemplate?je(n.promptTemplate,r):`\u3010\u63D2\u4EF6\u4E8B\u4EF6\u3011${t.name} \xB7 ${n.event}${n.description?`
12
+ `)}a.length>1024*1024&&(a=a.slice(-4096))}),o.stderr?.on("data",u=>{A(n,`stderr: ${D(u.toString("utf8").trimEnd(),400)}`)}),o.on("error",u=>{n.lastError=`\u8FDB\u7A0B\u542F\u52A8\u5931\u8D25: ${u.message}`,A(n,`ERROR ${n.lastError}`)}),o.on("close",u=>{n.child=void 0,!n.stopping&&(n.lastError=`\u76D1\u542C\u8FDB\u7A0B\u9000\u51FA\uFF08code=${u??"signal"}\uFF09`,A(n,`exit code=${u??"signal"}\uFF0C\u51C6\u5907\u91CD\u542F`),this.scheduleListenerRestart(e,t,n))})}catch(o){const a=o instanceof Error?o.message:String(o);n.lastError=a,A(n,`ERROR spawn: ${a}`),this.scheduleListenerRestart(e,t,n)}}scheduleListenerRestart(e,t,n){if(n.stopping)return;const r=Math.max(500,n.def.transport?.restartBackoffMs??2e3),i=Math.min(Oe,r*2**Math.min(n.restarts,6));n.restarts++,A(n,`restart #${n.restarts} in ${i}ms`),n.backoffTimer=setTimeout(()=>{n.backoffTimer=void 0,n.stopping||this.spawnListenerChild(e,t,n)},i)}async pollListenerOnce(e,t,n){if(n.polling)return;const r=n.def.transport?.command??"",i=K(r,{});if(i.length===0)return;n.polling=!0;const s=new AbortController,o=setTimeout(()=>s.abort(),z);try{const a=await new Promise((u,c)=>{const d=_(i[0],i.slice(1),{cwd:t.dir,env:this.buildPluginEnv(t,e.agentId),shell:!1,windowsHide:!0,stdio:["ignore","pipe","pipe"],signal:s.signal});let y="",p="";d.stdout?.on("data",h=>{y.length<M&&(y+=h.toString("utf8"))}),d.stderr?.on("data",h=>{p.length<M&&(p+=h.toString("utf8"))});const g=()=>s.signal.aborted;d.on("error",h=>{c(g()?new Error(`poll \u8D85\u65F6(${z}ms)`):h)}),d.on("close",h=>{g()?c(new Error(`poll \u8D85\u65F6(${z}ms)`)):h===0?u(y):c(new Error(`exit ${h}: ${D(p||y,300)}`))})});n.lastError=void 0;for(const u of a.split(`
13
+ `)){const c=u.trim();c&&this.handleListenerLine(e,t,n,c)}}catch(a){const u=a instanceof Error?a.message:String(a);n.lastError=u,A(n,`poll \u5931\u8D25: ${u}`)}finally{clearTimeout(o),n.polling=!1}}stopListener(e){if(e.stopping=!0,e.restarts=0,e.child){try{e.child.kill()}catch{}e.child=void 0}e.timer&&(clearInterval(e.timer),e.timer=void 0),e.backoffTimer&&(clearTimeout(e.backoffTimer),e.backoffTimer=void 0)}handleListenerLine(e,t,n,r){A(n,`event: ${D(r,300)}`);let i;try{i=JSON.parse(r)}catch{n.lastError="\u4E8B\u4EF6\u884C\u4E0D\u662F\u5408\u6CD5 JSON\uFF08\u8981\u6C42 JSONL\uFF09";return}if(!v(i))return;const s=typeof i.event=="string"?i.event:n.def.event,o=s===n.def.event?n.def:t.listeners.find(a=>a.event===s);o&&(o.delivery&&o.delivery!=="poll"&&f.debug("[plugin:%s] delivery=%s \u6682\u6309 poll \u4EA4\u4ED8",t.name,o.delivery),this.enqueueEvent(e,t,o,i))}enqueueEvent(e,t,n,r){for(const[p,g]of Object.entries(n.matcher??{})){const h=O(r,p);if(!(Array.isArray(g)?g:[g]).some(E=>JSON.stringify(E)===JSON.stringify(h)))return}let i;if(n.dedupKey){const p=O(r,n.dedupKey);p!=null&&(i=D(String(p),256))}e.eventSeq++;const s=D(qe(r.data??r),De),o=n.promptTemplate?je(n.promptTemplate,r):`\u3010\u63D2\u4EF6\u4E8B\u4EF6\u3011${t.name} \xB7 ${n.event}${n.description?`
14
14
  ${n.description}`:""}`,a=(n.toolHints??[]).join(","),u=`${o}
15
- [plugin-event] plugin=${t.name} event=${n.event}`+(a?` toolHints=${a}`:"")+` payload=${s}`,c={msgId:D(i?`plugin-event-${t.name}-${i}`:`plugin-event-${t.name}-${n.event}-${e.eventSeq}`,512),channel:"plugin-event",senderId:`plugin:${t.name}`,senderName:`\u63D2\u4EF6[${t.name}]`,receiverId:e.agentId||void 0,content:u,requireReply:!1,role:"system",timestamp:new Date().toISOString()},d=n.priority??"normal";e.buffer.push({plugin:t.name,event:n.event,priority:d,dedupKey:i,receivedAt:Date.now(),message:c})&&this.exposePlugin(e.agentId,t.name)}requiredParamsOf(e){const t=e.inputSchema;if(!(!t||!Array.isArray(t.required)))return t.required.filter(n=>typeof n=="string")}toSummary(e){return{name:e.name,version:e.version,description:e.description,status:e.status,enabled:e.enabled,source:e.source,installedAt:e.installedAt,toolCount:e.tools.length,tools:e.tools.map(t=>({name:t.name,title:t.title,description:t.description})),listeners:e.runtimes.map(t=>({event:t.def.event,delivery:t.def.delivery??"poll",running:!!(t.child||t.timer)||t.def.transport?.type==="http-callback",error:t.lastError})),running:e.runtimes.some(t=>!!(t.child||t.timer)||t.def.transport?.type==="http-callback"),error:e.error}}async getLogs(e,t){const n=await this.hydrate(e);if(t===$)return{ok:!0,logs:[`\u2500\u2500 ${$} \u4E3A\u7CFB\u7EDF\u5185\u7F6E\u63D2\u4EF6\uFF08\u65E0\u9700\u5B89\u88C5\uFF09\uFF0C\u65E0\u72EC\u7ACB\u76D1\u542C\u5668\u8FD0\u884C\u65E5\u5FD7\u3002`,"\u5176\u751F\u547D\u5468\u671F\u64CD\u4F5C\uFF08install/reload/disable/enable/list\uFF09\u7531 bridge plugin-manager \u5904\u7406\uFF0C\u53EF\u901A\u8FC7\u300C\u91CD\u8F7D/\u542F\u7528/\u505C\u7528\u300D\u6309\u94AE\u89C2\u5BDF\u72B6\u6001\u53D8\u5316\u3002"]};const r=n.plugins.get(t);if(!r)return{ok:!1,error:`\u63D2\u4EF6 ${t} \u672A\u5B89\u88C5`,logs:[]};const i=[];for(const s of r.runtimes)i.push(`\u2500\u2500 listener ${s.def.event} (${s.def.transport?.type}) ${s.lastError?`[error: ${s.lastError}]`:""}`),i.push(...s.logs);return{ok:!0,logs:i}}async stopAgent(e){const t=this.agents.get(e);if(t){for(const n of t.plugins.values())this.stopAllListeners(n);this.agents.delete(e)}}async stopAll(){for(const e of[...this.agents.keys()])await this.stopAgent(e)}async listDeployed(){await this.migrateLegacySharedIfNeeded();const e=this.readSharedManifest(),t=[];for(const n of e){const r=this.deployedPluginDir(n.pluginName),i=this.deployedPluginHealthy(n.pluginName);let s;if(i)try{const o=JSON.parse(k(m(r,"plugin.json"),"utf8"));typeof o.version=="string"&&(s=o.version)}catch{}t.push({pluginName:n.pluginName,version:s,fileName:n.fileName??`${n.pluginName}.zip`,defaultEnabled:n.defaultEnabled!==!1,sha256:n.sha256,deployed:i})}return t}deployedDefaultEnabled(){const e=this.readSharedManifest(),t={};for(const n of e)t[n.pluginName]=n.defaultEnabled!==!1;return t}async removeDeployedPlugin(e){if(!V(e))return{ok:!1,error:"pluginName \u975E\u6CD5\uFF08\u987B\u4E3A kebab-case\uFF0C1~64 \u5B57\u7B26\uFF09"};await this.migrateLegacySharedIfNeeded();for(const t of[...this.agents.values()]){if(!t.hydrated)continue;const n=t.queue.then(async()=>{const r=t.plugins.get(e);r&&(this.stopAllListeners(r),t.plugins.delete(e)),this.removeRuntimeLink(t.agentId,e),this.persistInstalled(t)});t.queue=n.catch(()=>{}),await n}await W(this.deployedManifestFile(),async()=>{const t=this.readSharedManifest().filter(n=>n.pluginName!==e);this.writeSharedManifest(t)});try{E(this.deployedPluginDir(e),{recursive:!0,force:!0})}catch(t){return{ok:!1,error:`\u90E8\u7F72\u76EE\u5F55\u6E05\u7406\u5931\u8D25: ${t instanceof Error?t.message:String(t)}`}}return f.info("[shared] \u63D2\u4EF6\u5DF2\u4ECE bridge \u79FB\u9664\u90E8\u7F72: %s",e),{ok:!0}}}function V(l){return typeof l=="string"&&l.length>0&&l.length<=64&&z.test(l)}function _e(l){const e=l.name;if(typeof e!="string"||!z.test(e))return`plugin.json: name \u975E\u6CD5\uFF08\u987B\u4E3A kebab-case\uFF09: ${String(e)}`;if(e.length>64)return"plugin.json: name \u8FC7\u957F\uFF08\u226464\uFF09";for(const t of be)if(e===t.replace(/\.$/,"")||e.startsWith(t))return`plugin.json: name \u4F7F\u7528\u4E86\u4FDD\u7559\u524D\u7F00 ${t}`;return Ne.test(e)?"plugin.json: name \u542B\u975E ASCII \u5B57\u7B26\uFF08\u540C\u5F62\u5B57\u9632\u62A4\uFF09":l.version!==void 0&&typeof l.version!="string"?"plugin.json: version \u987B\u4E3A\u5B57\u7B26\u4E32":l.userConfig!==void 0&&!Array.isArray(l.userConfig)?"plugin.json: userConfig \u987B\u4E3A\u6570\u7EC4":null}function Fe(l){if(!v(l))return"\u5DE5\u5177\u6761\u76EE\u987B\u4E3A\u5BF9\u8C61";const e=l.name;if(typeof e!="string"||!De.test(e))return`\u5DE5\u5177 name \u975E\u6CD5: ${String(e)}`;if(typeof l.description!="string"||!l.description.trim())return`\u5DE5\u5177 ${e} \u7F3A\u5C11 description`;const t=l.handler;if(!v(t))return`\u5DE5\u5177 ${e} \u7F3A\u5C11 handler`;const n=t.type;return n!=="process"&&n!=="module"&&n!=="mcp"?`\u5DE5\u5177 ${e} handler.type \u975E\u6CD5: ${String(n)}`:n==="process"&&typeof t.command!="string"?`\u5DE5\u5177 ${e} \u7684 process handler \u7F3A\u5C11 command`:n==="module"&&typeof t.module!="string"?`\u5DE5\u5177 ${e} \u7684 module handler \u7F3A\u5C11 module`:l.inputSchema!==void 0&&!v(l.inputSchema)?`\u5DE5\u5177 ${e} inputSchema \u987B\u4E3A\u5BF9\u8C61`:null}function xe(l){if(!v(l))return"\u76D1\u542C\u5668\u6761\u76EE\u987B\u4E3A\u5BF9\u8C61";if(typeof l.event!="string"||!l.event.trim())return"\u76D1\u542C\u5668\u7F3A\u5C11 event";const e=l.transport;if(!v(e))return`\u76D1\u542C\u5668 ${String(l.event)} \u7F3A\u5C11 transport`;const t=e.type;if(t!=="command-stream"&&t!=="poll-command"&&t!=="http-callback")return`\u76D1\u542C\u5668 ${String(l.event)} transport.type \u975E\u6CD5: ${String(t)}`;if((t==="command-stream"||t==="poll-command")&&typeof e.command!="string")return`\u76D1\u542C\u5668 ${String(l.event)} \u7684 ${t} transport \u7F3A\u5C11 command`;const n=l.delivery;return n!==void 0&&n!=="poll"&&n!=="force"&&n!=="wake"?`\u76D1\u542C\u5668 ${String(l.event)} delivery \u975E\u6CD5: ${String(n)}`:null}function Y(l,e){return l.trim().split(/\s+/).map(t=>{const n=/^\{\{(.+)\}\}$/.exec(t);if(n){const r=I(e,n[1].trim());return r==null?"":typeof r=="string"?r:JSON.stringify(r)}return t.replace(/\{\{(.+?)\}\}/g,(r,i)=>{const s=I(e,i.trim());return s==null?"":typeof s=="string"?s:JSON.stringify(s)})}).filter(t=>t!=="")}function je(l,e){return l.replace(/\{\{(.+?)\}\}/g,(t,n)=>{let r=I(e,n.trim());return r===void 0&&!n.trim().startsWith("params.")&&(r=I(e,`data.${n.trim()}`)),r==null?"":typeof r=="string"?r:JSON.stringify(r)})}function He(l){try{return JSON.stringify(l)??"null"}catch{return"(\u4E0D\u53EF\u5E8F\u5217\u5316\u7684\u4E8B\u4EF6\u8D1F\u8F7D)"}}const Ue=new Me;me("plugins",()=>Ue.deployedDefaultEnabled());const tt=()=>ye("plugins");export{X as BUILTIN_PLUGIN_DESCRIPTION,Q as BUILTIN_PLUGIN_MANAGE_DESC,$ as BUILTIN_PLUGIN_NAME,Me as PluginManager,Ee as getBuiltinCommandDir,V as isValidPluginName,Ue as pluginManager,tt as reconcilePluginsDefaultsFromDeployed,Y as renderCommandArgv,B as validateAgainstSchema,_e as validateManifest};
15
+ [plugin-event] plugin=${t.name} event=${n.event}`+(a?` toolHints=${a}`:"")+` payload=${s}`,c={msgId:D(i?`plugin-event-${t.name}-${i}`:`plugin-event-${t.name}-${n.event}-${e.eventSeq}`,512),channel:"plugin-event",senderId:`plugin:${t.name}`,senderName:`\u63D2\u4EF6[${t.name}]`,receiverId:e.agentId||void 0,content:u,requireReply:!1,role:"system",timestamp:new Date().toISOString()},d=n.priority??"normal";e.buffer.push({plugin:t.name,event:n.event,priority:d,dedupKey:i,receivedAt:Date.now(),message:c})&&this.exposePlugin(e.agentId,t.name)}requiredParamsOf(e){const t=e.inputSchema;if(!(!t||!Array.isArray(t.required)))return t.required.filter(n=>typeof n=="string")}toSummary(e){return{name:e.name,version:e.version,description:e.description,status:e.status,enabled:e.enabled,source:e.source,installedAt:e.installedAt,toolCount:e.tools.length,tools:e.tools.map(t=>({name:t.name,title:t.title,description:t.description})),listeners:e.runtimes.map(t=>({event:t.def.event,delivery:t.def.delivery??"poll",running:!!(t.child||t.timer)||t.def.transport?.type==="http-callback",error:t.lastError})),running:e.runtimes.some(t=>!!(t.child||t.timer)||t.def.transport?.type==="http-callback"),error:e.error}}async getLogs(e,t){const n=await this.hydrate(e);if(t===k)return{ok:!0,logs:[`\u2500\u2500 ${k} \u4E3A\u7CFB\u7EDF\u5185\u7F6E\u63D2\u4EF6\uFF08\u65E0\u9700\u5B89\u88C5\uFF09\uFF0C\u65E0\u72EC\u7ACB\u76D1\u542C\u5668\u8FD0\u884C\u65E5\u5FD7\u3002`,"\u5176\u751F\u547D\u5468\u671F\u64CD\u4F5C\uFF08install/reload/disable/enable/list\uFF09\u7531 bridge plugin-manager \u5904\u7406\uFF0C\u53EF\u901A\u8FC7\u300C\u91CD\u8F7D/\u542F\u7528/\u505C\u7528\u300D\u6309\u94AE\u89C2\u5BDF\u72B6\u6001\u53D8\u5316\u3002"]};const r=n.plugins.get(t);if(!r)return{ok:!1,error:`\u63D2\u4EF6 ${t} \u672A\u5B89\u88C5`,logs:[]};const i=[];for(const s of r.runtimes)i.push(`\u2500\u2500 listener ${s.def.event} (${s.def.transport?.type}) ${s.lastError?`[error: ${s.lastError}]`:""}`),i.push(...s.logs);return{ok:!0,logs:i}}async stopAgent(e){const t=this.agents.get(e);if(t){for(const n of t.plugins.values())this.stopAllListeners(n);this.agents.delete(e)}}async stopAll(){for(const e of[...this.agents.keys()])await this.stopAgent(e)}async listDeployed(){await this.migrateLegacySharedIfNeeded();const e=this.readSharedManifest(),t=[];for(const n of e){const r=this.deployedPluginDir(n.pluginName),i=this.deployedPluginHealthy(n.pluginName);let s;if(i)try{const o=JSON.parse(b(m(r,"plugin.json"),"utf8"));typeof o.version=="string"&&(s=o.version)}catch{}t.push({pluginName:n.pluginName,version:s,fileName:n.fileName??`${n.pluginName}.zip`,defaultEnabled:n.defaultEnabled!==!1,sha256:n.sha256,deployed:i})}return t}deployedDefaultEnabled(){const e=this.readSharedManifest(),t={};for(const n of e)t[n.pluginName]=n.defaultEnabled!==!1;return t}async removeDeployedPlugin(e){if(!B(e))return{ok:!1,error:"pluginName \u975E\u6CD5\uFF08\u987B\u4E3A kebab-case\uFF0C1~64 \u5B57\u7B26\uFF09"};await this.migrateLegacySharedIfNeeded();for(const t of[...this.agents.values()]){if(!t.hydrated)continue;const n=t.queue.then(async()=>{const r=t.plugins.get(e);r&&(this.stopAllListeners(r),t.plugins.delete(e)),this.removeRuntimeLink(t.agentId,e),this.persistInstalled(t)});t.queue=n.catch(()=>{}),await n}await W(this.deployedManifestFile(),async()=>{const t=this.readSharedManifest().filter(n=>n.pluginName!==e);this.writeSharedManifest(t)});try{P(this.deployedPluginDir(e),{recursive:!0,force:!0})}catch(t){return{ok:!1,error:`\u90E8\u7F72\u76EE\u5F55\u6E05\u7406\u5931\u8D25: ${t instanceof Error?t.message:String(t)}`}}return f.info("[shared] \u63D2\u4EF6\u5DF2\u4ECE bridge \u79FB\u9664\u90E8\u7F72: %s",e),{ok:!0}}}function B(l){return typeof l=="string"&&l.length>0&&l.length<=64&&H.test(l)}function _e(l){const e=l.name;if(typeof e!="string"||!H.test(e))return`plugin.json: name \u975E\u6CD5\uFF08\u987B\u4E3A kebab-case\uFF09: ${String(e)}`;if(e.length>64)return"plugin.json: name \u8FC7\u957F\uFF08\u226464\uFF09";for(const t of Ne)if(e===t.replace(/\.$/,"")||e.startsWith(t))return`plugin.json: name \u4F7F\u7528\u4E86\u4FDD\u7559\u524D\u7F00 ${t}`;return Ie.test(e)?"plugin.json: name \u542B\u975E ASCII \u5B57\u7B26\uFF08\u540C\u5F62\u5B57\u9632\u62A4\uFF09":l.version!==void 0&&typeof l.version!="string"?"plugin.json: version \u987B\u4E3A\u5B57\u7B26\u4E32":l.userConfig!==void 0&&!Array.isArray(l.userConfig)?"plugin.json: userConfig \u987B\u4E3A\u6570\u7EC4":null}function Fe(l){if(!v(l))return"\u5DE5\u5177\u6761\u76EE\u987B\u4E3A\u5BF9\u8C61";const e=l.name;if(typeof e!="string"||!Ae.test(e))return`\u5DE5\u5177 name \u975E\u6CD5: ${String(e)}`;if(typeof l.description!="string"||!l.description.trim())return`\u5DE5\u5177 ${e} \u7F3A\u5C11 description`;const t=l.handler;if(!v(t))return`\u5DE5\u5177 ${e} \u7F3A\u5C11 handler`;const n=t.type;return n!=="process"&&n!=="module"&&n!=="mcp"?`\u5DE5\u5177 ${e} handler.type \u975E\u6CD5: ${String(n)}`:n==="process"&&typeof t.command!="string"?`\u5DE5\u5177 ${e} \u7684 process handler \u7F3A\u5C11 command`:n==="module"&&typeof t.module!="string"?`\u5DE5\u5177 ${e} \u7684 module handler \u7F3A\u5C11 module`:l.inputSchema!==void 0&&!v(l.inputSchema)?`\u5DE5\u5177 ${e} inputSchema \u987B\u4E3A\u5BF9\u8C61`:null}function xe(l){if(!v(l))return"\u76D1\u542C\u5668\u6761\u76EE\u987B\u4E3A\u5BF9\u8C61";if(typeof l.event!="string"||!l.event.trim())return"\u76D1\u542C\u5668\u7F3A\u5C11 event";const e=l.transport;if(!v(e))return`\u76D1\u542C\u5668 ${String(l.event)} \u7F3A\u5C11 transport`;const t=e.type;if(t!=="command-stream"&&t!=="poll-command"&&t!=="http-callback")return`\u76D1\u542C\u5668 ${String(l.event)} transport.type \u975E\u6CD5: ${String(t)}`;if((t==="command-stream"||t==="poll-command")&&typeof e.command!="string")return`\u76D1\u542C\u5668 ${String(l.event)} \u7684 ${t} transport \u7F3A\u5C11 command`;const n=l.delivery;return n!==void 0&&n!=="poll"&&n!=="force"&&n!=="wake"?`\u76D1\u542C\u5668 ${String(l.event)} delivery \u975E\u6CD5: ${String(n)}`:null}function K(l,e){return l.trim().split(/\s+/).map(t=>{const n=/^\{\{(.+)\}\}$/.exec(t);if(n){const r=O(e,n[1].trim());return r==null?"":typeof r=="string"?r:JSON.stringify(r)}return t.replace(/\{\{(.+?)\}\}/g,(r,i)=>{const s=O(e,i.trim());return s==null?"":typeof s=="string"?s:JSON.stringify(s)})}).filter(t=>t!=="")}function je(l,e){return l.replace(/\{\{(.+?)\}\}/g,(t,n)=>{let r=O(e,n.trim());return r===void 0&&!n.trim().startsWith("params.")&&(r=O(e,`data.${n.trim()}`)),r==null?"":typeof r=="string"?r:JSON.stringify(r)})}function qe(l){try{return JSON.stringify(l)??"null"}catch{return"(\u4E0D\u53EF\u5E8F\u5217\u5316\u7684\u4E8B\u4EF6\u8D1F\u8F7D)"}}const Je=new Re;ye("plugins",()=>Je.deployedDefaultEnabled());const nt=()=>Se("plugins");export{X as BUILTIN_PLUGIN_DESCRIPTION,Q as BUILTIN_PLUGIN_MANAGE_DESC,k as BUILTIN_PLUGIN_NAME,Re as PluginManager,be as getBuiltinCommandDir,B as isValidPluginName,Je as pluginManager,nt as reconcilePluginsDefaultsFromDeployed,K as renderCommandArgv,G as validateAgainstSchema,_e as validateManifest};
16
16
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  export declare function isProcessRunningAsync(pid: number): Promise<boolean>;
4
4
 
5
- export declare function isProcessRunning(pid: number): boolean;
5
+ export declare function isProcessRunning(pid: number): Promise<boolean>;
6
6
 
7
7
  export interface ProcessInfo {
8
8
  pid: number;
@@ -16,6 +16,25 @@ export declare function findClaudeCodeProcesses(): Promise<ProcessInfo[]>;
16
16
 
17
17
  export declare function findOrphanProcessByAgentId(agentId: string): Promise<ProcessInfo | undefined>;
18
18
 
19
+ interface ProcEntry {
20
+ processId: number;
21
+ parentProcessId: number;
22
+ name: string;
23
+ commandLine: string | null;
24
+ }
25
+
26
+ export interface ProcessSnapshotEntry extends ProcEntry {
27
+ creationDate?: string | null;
28
+ workingSetSize?: number | null;
29
+ handleCount?: number | null;
30
+ }
31
+
32
+ export interface ProcessSnapshot {
33
+ entries: ProcessSnapshotEntry[];
34
+ }
35
+
36
+ export declare function captureProcessSnapshot(): Promise<ProcessSnapshot | undefined>;
37
+
19
38
  export declare function findOrphanProcessByWorkspace(workspacePath: string): Promise<ProcessInfo | undefined>;
20
39
 
21
40
  export declare function terminateProcess(pid: number): boolean;
@@ -32,7 +51,7 @@ export declare function detectOrphanProcesses(persistedSessions: Array<{
32
51
  pid?: number;
33
52
  workspacePath?: string;
34
53
  command?: string;
35
- }>): Promise<Array<{
54
+ }>, snapshot?: ProcessSnapshot): Promise<Array<{
36
55
  agentId: string;
37
56
  process: ProcessInfo;
38
57
  sessionInfo: {
@@ -56,7 +75,7 @@ export declare function checkProcessHealth(pid: number, agentId: string): Promis
56
75
  export declare function checkAllSessionsHealth(sessions: Array<{
57
76
  agentId: string;
58
77
  pid?: number;
59
- }>): Promise<Map<string, ProcessHealthStatus>>;
78
+ }>, snapshot?: ProcessSnapshot): Promise<Map<string, ProcessHealthStatus>>;
60
79
 
61
80
  export type ProcessManagementStatus = 'managed' | 'orphan' | 'unknown';
62
81
 
@@ -73,3 +92,4 @@ export declare function discoverAllProcessesFull(registryExport: Array<{
73
92
  agentId: string;
74
93
  pid: number;
75
94
  }>): Promise<DiscoveredProcessInfo[]>;
95
+ export {};
@@ -1,21 +1,21 @@
1
- import{execSync as O,exec as k}from"child_process";import h from"os";import{promisify as M}from"util";const g=M(k);import{createLogger as b}from"../utils/logger.js";const a=b("process-detector");async function m(n,t=15e3){const r=Buffer.from(n,"utf16le").toString("base64"),{stdout:s}=await g(`powershell -NoProfile -NonInteractive -EncodedCommand ${r}`,{encoding:"utf8",timeout:t,windowsHide:!0,maxBuffer:10*1024*1024});return s.replace(/#\s*<\s*CLIXML[\s\S]*?(?=#<\s*CLIXML|$)/g,"").trim()}async function w(n){try{if(h.platform()==="win32"){const{stdout:t}=await g(`tasklist /FI "PID eq ${n}" /NH /FO CSV`,{encoding:"utf8",timeout:5e3,windowsHide:!0});return t.includes(String(n))}else return process.kill(n,0),!0}catch{return!1}}function z(n){try{return h.platform()==="win32"?O(`tasklist /FI "PID eq ${n}" /NH /FO CSV`,{encoding:"utf8",timeout:5e3,windowsHide:!0}).includes(String(n)):(process.kill(n,0),!0)}catch{return!1}}async function I(){const n=h.platform(),t=[];try{n==="win32"?t.push(...await A()):t.push(...await N())}catch(e){a.debug("Failed to list processes:",e)}return t}async function A(){const n=[];try{const e=await m(`Get-CimInstance Win32_Process -Filter "Name LIKE '%node%' OR Name LIKE '%claude%' OR Name LIKE '%opencode%' OR Name LIKE '%python%'" | Select-Object ProcessId, CommandLine | ConvertTo-Json -Compress`,1e4);if(!e||!e.trim())return n;let r;try{const s=JSON.parse(e);r=Array.isArray(s)?s:[s]}catch{return n}for(const s of r){if(!s.ProcessId||!s.CommandLine)continue;const i=s.CommandLine;if($(i)){const d=y(i);n.push({pid:s.ProcessId,command:i,agentId:d})}}}catch(t){a.debug("PowerShell process query failed, trying wmic fallback:",t),n.push(...await F())}return n}async function F(){const n=[];try{const{stdout:t}=await g(`wmic process where "name like '%node%' or name like '%claude%' or name like '%opencode%'" get processid,commandline /format:list`,{encoding:"utf8",timeout:5e3,windowsHide:!0}),e=t.split(`
2
- `);let r=null,s=null;for(const i of e){const d=i.trim();if(d.startsWith("CommandLine=")?s=d.substring(12):d.startsWith("ProcessId=")&&(r=d.substring(10)),r&&s){if($(s)){const c=y(s);n.push({pid:parseInt(r,10),command:s,agentId:c})}r=null,s=null}}}catch(t){a.debug("wmic process query failed:",t)}return n}async function N(){const n=[];try{const{stdout:t}=await g('ps aux | grep -E "claude|claude-code|opencode" | grep -v grep',{encoding:"utf8",timeout:5e3}),e=t.split(`
3
- `).filter(r=>r.trim());for(const r of e){const s=r.trim().split(/\s+/);if(s.length>=2){const i=parseInt(s[1],10),d=s.slice(10).join(" ");if($(d)){const c=y(d);n.push({pid:i,command:d,agentId:c})}}}}catch(t){a.debug("ps process query failed:",t)}return n}function $(n){if(!n)return!1;const t=n.toLowerCase();return!!(t.includes("claude")||t.includes("@anthropic-ai/claude-code")||t.includes("opencode")||t.includes("open-code")||t.includes("opencode.exe")||t.includes("opencode.cmd")||t.includes("aws-client-agent-mcp")||t.includes("aws-client-agent")||t.includes("acode")&&t.includes("sdk")||t.includes("cc-switch-sdk")||t.includes("cc-switch"))}function y(n){if(!n)return;const t=n.match(/AWS_AGENT_ID=(\S+)/);if(t)return C(t[1]);const e=n.match(/--agent-id[=\s]+(\S+)/);if(e)return C(e[1]);const r=n.match(/--id[=\s]+(\S+)/);if(r)return C(r[1])}function C(n){if(!n)return n;const t=n[0],e=n[n.length-1];return(t==='"'||t==="'")&&t===e?n.slice(1,-1):n}async function x(n){const e=(await I()).find(r=>r.agentId===n);if(e)return e;if(h.platform()==="win32"){const r=await T(n);if(r)return r;const s=await R(n);if(s)return s}}async function T(n){try{const t=`$targetId = '${n}'; $procs = Get-CimInstance Win32_Process | Where-Object { $_.CommandLine -and ($_.Name -like '*node*' -or $_.Name -like '*claude*' -or $_.Name -like '*opencode*') }; foreach ($proc in $procs) { if ($proc.CommandLine -like "*$targetId*") { @{ProcessId=$proc.ProcessId; CommandLine=$proc.CommandLine; AgentId=$targetId} | ConvertTo-Json -Compress } }`,e=await m(t,1e4);if(!e||!e.trim())return;const r=e.trim().split(`
4
- `).filter(s=>s.trim());for(const s of r)try{const i=JSON.parse(s.trim());if(i.ProcessId)return{pid:i.ProcessId,command:i.CommandLine||"",agentId:i.AgentId||n}}catch{}}catch(t){a.debug("PowerShell env var query failed:",t)}}async function R(n){try{const e=await m("Get-CimInstance Win32_Process | Select-Object ProcessId, ParentProcessId, Name, CommandLine | ConvertTo-Json -Compress",15e3);return!e||!e.trim()?void 0:await W(e.trim(),n)}catch(t){a.debug("[findOrphanByAncestorEnvSearch] Failed:",t)}}async function W(n,t){let e;try{const o=n.replace(/#\s*<\s*CLIXML[\s\S]*?(?=\{|\[|$)/g,"").trim(),u=B(o),l=JSON.parse(u);e=Array.isArray(l)?l:[l]}catch(o){a.debug(`[searchOrphanInProcessTree] JSON parse failed, raw length=${n.length}`,o);return}if(!e.length)return;const r=new Map;for(const o of e)o.processId&&r.set(o.processId,o);function s(o){const u=o.name.toLowerCase(),l=(o.commandLine||"").toLowerCase();return!!(u.includes("claude")||l.includes("claude")||l.includes("@anthropic-ai/claude-code")||l.includes("cli.js")||u.includes("opencode")||l.includes("opencode")||l.includes("serve")&&l.includes("--port"))}function i(o){const u=o.toLowerCase();return u==="powershell.exe"||u==="cmd.exe"||u==="pwsh.exe"||u==="bash.exe"}function d(o){let u=o;const l=10;for(let P=0;P<l;P++){const p=r.get(u);if(!p)break;if(i(p.name)){const f=r.get(p.parentProcessId);if(f&&f.name.toLowerCase()==="node.exe"){const S=(f.commandLine||"").toLowerCase();if(S.includes("runtime-bridge")||S.includes("agentswork"))return a.debug(`[searchOrphanInProcessTree] Found bridge ancestor chain: agent(${o}) -> shell(${p.processId}) -> node(${f.processId})`),{shellPid:p.processId,shellCmd:p.commandLine||""}}}if(u=p.parentProcessId,u<=0)break}return null}for(const o of e){if(!s(o))continue;const u=d(o.processId);if(u){if(u.shellCmd.toLowerCase().includes(t.toLowerCase()))return a.info(`[searchOrphanInProcessTree] Found orphan by tree search (agentId verified): agentId=${t}, pid=${o.processId}, name=${o.name}`),{pid:o.processId,command:o.commandLine||"",agentId:t};const p=e.filter(f=>s(f)&&d(f.processId));if(p.length===1)return a.info(`[searchOrphanInProcessTree] Found orphan by tree search (single candidate): agentId=${t}, pid=${o.processId}, name=${o.name}`),{pid:o.processId,command:o.commandLine||"",agentId:t};a.debug(`[searchOrphanInProcessTree] Multiple candidates found (${p.length}), cannot determine which belongs to agentId=${t}`)}}const c=e.filter(o=>s(o)&&!d(o.processId));for(const o of c)if(await _(o.processId,t))return a.info(`[searchOrphanInProcessTree] Found orphan by env verification: agentId=${t}, pid=${o.processId}, name=${o.name}`),{pid:o.processId,command:o.commandLine||"",agentId:t}}function B(n){const t=n.indexOf("["),e=n.indexOf("{");let r=-1;return t>=0&&e>=0?r=Math.min(t,e):t>=0?r=t:e>=0&&(r=e),r<0?n:n.substring(r)}async function _(n,t){try{const e=`
1
+ import{exec as O}from"child_process";import h from"os";import{promisify as A}from"util";const g=A(O);import{createLogger as F}from"../utils/logger.js";const d=F("process-detector");async function l(n,r=15e3){const e=Buffer.from(n,"utf16le").toString("base64"),{stdout:t}=await g(`powershell -NoProfile -NonInteractive -EncodedCommand ${e}`,{encoding:"utf8",timeout:r,windowsHide:!0,maxBuffer:10*1024*1024});return t.replace(/#\s*<\s*CLIXML[\s\S]*?(?=#<\s*CLIXML|$)/g,"").trim()}async function P(n){try{if(h.platform()==="win32"){const{stdout:r}=await g(`tasklist /FI "PID eq ${n}" /NH /FO CSV`,{encoding:"utf8",timeout:5e3,windowsHide:!0});return r.includes(String(n))}else return process.kill(n,0),!0}catch{return!1}}function Z(n){return P(n)}async function w(){const n=h.platform(),r=[];try{n==="win32"?r.push(...await N()):r.push(...await W())}catch(s){d.debug("Failed to list processes:",s)}return r}async function N(){const n=[];try{const s=await l(`Get-CimInstance Win32_Process -Filter "Name LIKE '%node%' OR Name LIKE '%claude%' OR Name LIKE '%opencode%' OR Name LIKE '%python%'" | Select-Object ProcessId, CommandLine | ConvertTo-Json -Compress`,1e4);if(!s||!s.trim())return n;let e;try{const t=JSON.parse(s);e=Array.isArray(t)?t:[t]}catch{return n}for(const t of e){if(!t.ProcessId||!t.CommandLine)continue;const o=t.CommandLine;if(y(o)){const i=$(o);n.push({pid:t.ProcessId,command:o,agentId:i})}}}catch(r){d.debug("PowerShell process query failed, trying wmic fallback:",r),n.push(...await T())}return n}async function T(){const n=[];try{const{stdout:r}=await g(`wmic process where "name like '%node%' or name like '%claude%' or name like '%opencode%'" get processid,commandline /format:list`,{encoding:"utf8",timeout:5e3,windowsHide:!0}),s=r.split(`
2
+ `);let e=null,t=null;for(const o of s){const i=o.trim();if(i.startsWith("CommandLine=")?t=i.substring(12):i.startsWith("ProcessId=")&&(e=i.substring(10)),e&&t){if(y(t)){const a=$(t);n.push({pid:parseInt(e,10),command:t,agentId:a})}e=null,t=null}}}catch(r){d.debug("wmic process query failed:",r)}return n}async function W(){const n=[];try{const{stdout:r}=await g('ps aux | grep -E "claude|claude-code|opencode" | grep -v grep',{encoding:"utf8",timeout:5e3}),s=r.split(`
3
+ `).filter(e=>e.trim());for(const e of s){const t=e.trim().split(/\s+/);if(t.length>=2){const o=parseInt(t[1],10),i=t.slice(10).join(" ");if(y(i)){const a=$(i);n.push({pid:o,command:i,agentId:a})}}}}catch(r){d.debug("ps process query failed:",r)}return n}function y(n){if(!n)return!1;const r=n.toLowerCase();return!!(r.includes("claude")||r.includes("@anthropic-ai/claude-code")||r.includes("opencode")||r.includes("open-code")||r.includes("opencode.exe")||r.includes("opencode.cmd")||r.includes("aws-client-agent-mcp")||r.includes("aws-client-agent")||r.includes("acode")&&r.includes("sdk")||r.includes("cc-switch-sdk")||r.includes("cc-switch"))}function $(n){if(!n)return;const r=n.match(/AWS_AGENT_ID=(\S+)/);if(r)return C(r[1]);const s=n.match(/--agent-id[=\s]+(\S+)/);if(s)return C(s[1]);const e=n.match(/--id[=\s]+(\S+)/);if(e)return C(e[1])}function C(n){if(!n)return n;const r=n[0],s=n[n.length-1];return(r==='"'||r==="'")&&r===s?n.slice(1,-1):n}async function x(n){const s=(await w()).find(e=>e.agentId===n);if(s)return s;if(h.platform()==="win32"){const e=await B(n);if(e)return e;const t=await R(n);if(t)return t}}async function B(n){try{const r=`$targetId = '${n}'; $procs = Get-CimInstance Win32_Process | Where-Object { $_.CommandLine -and ($_.Name -like '*node*' -or $_.Name -like '*claude*' -or $_.Name -like '*opencode*') }; foreach ($proc in $procs) { if ($proc.CommandLine -like "*$targetId*") { @{ProcessId=$proc.ProcessId; CommandLine=$proc.CommandLine; AgentId=$targetId} | ConvertTo-Json -Compress } }`,s=await l(r,1e4);if(!s||!s.trim())return;const e=s.trim().split(`
4
+ `).filter(t=>t.trim());for(const t of e)try{const o=JSON.parse(t.trim());if(o.ProcessId)return{pid:o.ProcessId,command:o.CommandLine||"",agentId:o.AgentId||n}}catch{}}catch(r){d.debug("PowerShell env var query failed:",r)}}async function R(n){try{const s=await l("Get-CimInstance Win32_Process | Select-Object ProcessId, ParentProcessId, Name, CommandLine | ConvertTo-Json -Compress",15e3);return!s||!s.trim()?void 0:await E(s.trim(),n)}catch(r){d.debug("[findOrphanByAncestorEnvSearch] Failed:",r)}}async function ee(){if(h.platform()!=="win32")return;const r=await l("Get-CimInstance Win32_Process | Select-Object ProcessId, ParentProcessId, Name, CommandLine, CreationDate, WorkingSetSize, HandleCount | ConvertTo-Json -Compress",15e3);if(!r||!r.trim())throw new Error("empty Win32_Process snapshot output");const s=r.replace(/#\s*<\s*CLIXML[\s\S]*?(?=\{|\[|$)/g,"").trim(),e=M(s),t=JSON.parse(e),o=Array.isArray(t)?t:[t],i=[];for(const a of o){const c=Number(a?.ProcessId);!Number.isFinite(c)||c<=0||i.push({processId:c,parentProcessId:Number(a?.ParentProcessId)||0,name:String(a?.Name??""),commandLine:a?.CommandLine??null,creationDate:a?.CreationDate??null,workingSetSize:a?.WorkingSetSize??null,handleCount:a?.HandleCount??null})}return{entries:i}}function L(n,r){return n.entries.some(s=>s.processId===r)}function _(n){const r=[];for(const s of n.entries){const e=s.commandLine;if(!s.processId||!e)continue;const t=s.name.toLowerCase();!t.includes("node")&&!t.includes("claude")&&!t.includes("opencode")&&!t.includes("python")||y(e)&&r.push({pid:s.processId,command:e,agentId:$(e)})}return r}function v(n,r){const s=r.toLowerCase();for(const e of n.entries){const t=e.commandLine;if(!t)continue;const o=e.name.toLowerCase();if(!(!o.includes("node")&&!o.includes("claude")&&!o.includes("opencode"))&&t.toLowerCase().includes(s))return{pid:e.processId,command:t,agentId:r}}}async function E(n,r){let s;try{const e=n.replace(/#\s*<\s*CLIXML[\s\S]*?(?=\{|\[|$)/g,"").trim(),t=M(e),o=JSON.parse(t);s=Array.isArray(o)?o:[o]}catch(e){d.debug(`[searchOrphanInProcessTree] JSON parse failed, raw length=${n.length}`,e);return}return k(s,r,e=>G(e,r))}async function k(n,r,s){if(!n.length)return;const e=new Map;for(const c of n)c.processId&&e.set(c.processId,c);function t(c){const u=c.name.toLowerCase(),p=(c.commandLine||"").toLowerCase();return!!(u.includes("claude")||p.includes("claude")||p.includes("@anthropic-ai/claude-code")||p.includes("cli.js")||u.includes("opencode")||p.includes("opencode")||p.includes("serve")&&p.includes("--port"))}function o(c){const u=c.toLowerCase();return u==="powershell.exe"||u==="cmd.exe"||u==="pwsh.exe"||u==="bash.exe"}function i(c){let u=c;const p=10;for(let I=0;I<p;I++){const m=e.get(u);if(!m)break;if(o(m.name)){const f=e.get(m.parentProcessId);if(f&&f.name.toLowerCase()==="node.exe"){const S=(f.commandLine||"").toLowerCase();if(S.includes("runtime-bridge")||S.includes("agentswork"))return d.debug(`[searchOrphanInProcessTree] Found bridge ancestor chain: agent(${c}) -> shell(${m.processId}) -> node(${f.processId})`),{shellPid:m.processId,shellCmd:m.commandLine||""}}}if(u=m.parentProcessId,u<=0)break}return null}for(const c of n){if(!t(c))continue;const u=i(c.processId);if(u){if(u.shellCmd.toLowerCase().includes(r.toLowerCase()))return d.info(`[searchOrphanInProcessTree] Found orphan by tree search (agentId verified): agentId=${r}, pid=${c.processId}, name=${c.name}`),{pid:c.processId,command:c.commandLine||"",agentId:r};const m=n.filter(f=>t(f)&&i(f.processId));if(m.length===1)return d.info(`[searchOrphanInProcessTree] Found orphan by tree search (single candidate): agentId=${r}, pid=${c.processId}, name=${c.name}`),{pid:c.processId,command:c.commandLine||"",agentId:r};d.debug(`[searchOrphanInProcessTree] Multiple candidates found (${m.length}), cannot determine which belongs to agentId=${r}`)}}const a=n.filter(c=>t(c)&&!i(c.processId));for(const c of a)if(await s(c.processId))return d.info(`[searchOrphanInProcessTree] Found orphan by env verification: agentId=${r}, pid=${c.processId}, name=${c.name}`),{pid:c.processId,command:c.commandLine||"",agentId:r}}function H(n,r){const s=r.toLowerCase(),e=new Map;for(const t of n.entries)t.processId&&e.set(t.processId,t);return t=>{const o=e.get(t);if(o&&(o.commandLine||"").toLowerCase().includes(s))return!0;const i=o?e.get(o.parentProcessId):void 0;if(i&&(i.commandLine||"").toLowerCase().includes(s))return!0;const a=i?e.get(i.parentProcessId):void 0;return!!(a&&(a.commandLine||"").toLowerCase().includes(s))}}async function D(n,r,s){const e=s.find(o=>o.agentId===n);if(e)return e;const t=v(r,n);return t||await k(r.entries,n,H(r,n))}function M(n){const r=n.indexOf("["),s=n.indexOf("{");let e=-1;return r>=0&&s>=0?e=Math.min(r,s):r>=0?e=r:s>=0&&(e=s),e<0?n:n.substring(e)}async function G(n,r){try{const s=`
5
5
  try {
6
6
  $proc = Get-CimInstance Win32_Process -Filter "ProcessId = ${n}" -ErrorAction SilentlyContinue
7
- if ($proc -and $proc.CommandLine -like '*${t}*') { 'MATCH' } else { 'NOMATCH' }
7
+ if ($proc -and $proc.CommandLine -like '*${r}*') { 'MATCH' } else { 'NOMATCH' }
8
8
  } catch { 'ERROR' }
9
- `;if((await m(e,5e3)).trim()==="MATCH")return!0;const s=`
9
+ `;if((await l(s,5e3)).trim()==="MATCH")return!0;const t=`
10
10
  try {
11
11
  $proc = Get-CimInstance Win32_Process -Filter "ProcessId = ${n}" -ErrorAction SilentlyContinue
12
12
  if ($proc) {
13
13
  $parentPid = $proc.ParentProcessId
14
14
  $parent = Get-CimInstance Win32_Process -Filter "ProcessId = $parentPid" -ErrorAction SilentlyContinue
15
- if ($parent -and $parent.CommandLine -like '*${t}*') { 'MATCH' } else { 'NOMATCH' }
15
+ if ($parent -and $parent.CommandLine -like '*${r}*') { 'MATCH' } else { 'NOMATCH' }
16
16
  } else { 'NOPROC' }
17
17
  } catch { 'ERROR' }
18
- `;if((await m(s,5e3)).trim()==="MATCH")return!0;const d=`
18
+ `;if((await l(t,5e3)).trim()==="MATCH")return!0;const i=`
19
19
  try {
20
20
  $proc = Get-CimInstance Win32_Process -Filter "ProcessId = ${n}" -ErrorAction SilentlyContinue
21
21
  if ($proc) {
@@ -24,11 +24,11 @@ import{execSync as O,exec as k}from"child_process";import h from"os";import{prom
24
24
  if ($parent) {
25
25
  $grandParentPid = $parent.ParentProcessId
26
26
  $grandParent = Get-CimInstance Win32_Process -Filter "ProcessId = $grandParentPid" -ErrorAction SilentlyContinue
27
- if ($grandParent -and $grandParent.CommandLine -like '*${t}*') { 'MATCH' } else { 'NOMATCH' }
27
+ if ($grandParent -and $grandParent.CommandLine -like '*${r}*') { 'MATCH' } else { 'NOMATCH' }
28
28
  } else { 'NOPARENT' }
29
29
  } else { 'NOPROC' }
30
30
  } catch { 'ERROR' }
31
- `;return(await m(d,5e3)).trim()==="MATCH"}catch(e){return a.debug(`[verifyProcessAgentId] Failed for pid=${n}, agentId=${t}:`,e),!1}}async function K(n){if(n)try{const t=await I(),e=n.replace(/\\/g,"/").toLowerCase();for(const r of t)if(r.command.replace(/\\/g,"/").toLowerCase().includes(e))return a.info(`[findOrphanProcessByWorkspace] Found process by workspace: pid=${r.pid}, workspace=${n}`),r;if(h.platform()==="win32"){const s=`
31
+ `;return(await l(i,5e3)).trim()==="MATCH"}catch(s){return d.debug(`[verifyProcessAgentId] Failed for pid=${n}, agentId=${r}:`,s),!1}}async function ne(n){if(n)try{const r=await w(),s=n.replace(/\\/g,"/").toLowerCase();for(const e of r)if(e.command.replace(/\\/g,"/").toLowerCase().includes(s))return d.info(`[findOrphanProcessByWorkspace] Found process by workspace: pid=${e.pid}, workspace=${n}`),e;if(h.platform()==="win32"){const t=`
32
32
  $targetPath = '${n.replace(/'/g,"''")}'.ToLower().Replace('\\', '/')
33
33
  $procs = Get-CimInstance Win32_Process | Where-Object {
34
34
  $_.CommandLine -and ($_.Name -like '*node*' -or $_.Name -like '*claude*' -or $_.Name -like '*opencode*')
@@ -39,7 +39,7 @@ import{execSync as O,exec as k}from"child_process";import h from"os";import{prom
39
39
  @{ProcessId=$proc.ProcessId; CommandLine=$proc.CommandLine} | ConvertTo-Json -Compress
40
40
  }
41
41
  }
42
- `,i=await m(s,1e4);if(i&&i.trim()){const d=i.trim().split(`
43
- `).filter(c=>c.trim());for(const c of d)try{const o=JSON.parse(c.trim());if(o.ProcessId)return a.info(`[findOrphanProcessByWorkspace] Found process by PowerShell workspace search: pid=${o.ProcessId}`),{pid:o.ProcessId,command:o.CommandLine||""}}catch{}}}}catch(t){a.debug("[findOrphanProcessByWorkspace] Failed:",t)}}function v(n){try{return process.kill(n,"SIGTERM"),!0}catch(t){return a.warn(`Failed to terminate process ${n}:`,t),!1}}async function E(n){const t={terminated:0,failed:0};if(h.platform()==="win32")try{await g(`taskkill /PID ${n} /T /F`,{encoding:"utf8",timeout:5e3,windowsHide:!0}),t.terminated++,a.info(`Terminated process tree for pid=${n}`)}catch(e){const r=e;a.warn(`Failed to terminate process tree for pid=${n}:`,r.message),t.failed++}else{const e=await L(n);a.debug(`Found ${e.length} child processes for pid=${n}`);for(const r of e){const s=await E(r);t.terminated+=s.terminated,t.failed+=s.failed}v(n)?t.terminated++:t.failed++}return t}async function L(n){try{const{stdout:t}=await g(`pgrep -P ${n}`,{encoding:"utf8",timeout:3e3}),e=t.trim().split(`
44
- `).filter(Boolean).map(Number),r=[];for(const s of e)r.push(s),r.push(...await L(s));return r}catch{return[]}}async function U(n,t=5e3){const e=Date.now();for(;Date.now()-e<t;){if(!await w(n))return!0;const r=Math.min(100,t-(Date.now()-e));r>0&&await new Promise(s=>setTimeout(s,r))}return!1}async function V(n){const t=[];for(const e of n)if(e.pid&&await w(e.pid)){const s=(await I()).find(i=>i.pid===e.pid);s?(t.push({agentId:e.agentId,process:s,sessionInfo:{workspacePath:e.workspacePath,command:e.command}}),a.info(`Found orphan process by PID: agentId=${e.agentId}, pid=${e.pid}`)):(t.push({agentId:e.agentId,process:{pid:e.pid,command:e.command||"(unknown - persisted session)",agentId:e.agentId},sessionInfo:{workspacePath:e.workspacePath,command:e.command}}),a.info(`Found orphan process by PID (no cmd match): agentId=${e.agentId}, pid=${e.pid}`))}for(const e of n)if(!e.pid&&e.agentId){const r=await x(e.agentId);r&&!t.some(s=>s.agentId===e.agentId)&&(t.push({agentId:e.agentId,process:r,sessionInfo:{workspacePath:e.workspacePath,command:e.command}}),a.info(`Found orphan process by agentId: agentId=${e.agentId}, pid=${r.pid}`))}return t}async function H(n,t){const e={pid:n,agentId:t,alive:!1,cpu:0,memoryMB:0,status:"dead",lastUpdate:new Date};try{if(!await w(n))return e.status="dead",a.debug(`Process ${n} is not running`),e;e.alive=!0;const{cpu:r,memoryMB:s}=await D(n);return e.cpu=r,e.memoryMB=s,s>2048?e.status="high_memory":r>100?e.status="high_cpu":e.status="healthy",a.debug(`Process ${n} health: CPU=${r}%, Memory=${s}MB, Status=${e.status}`),e}catch(r){return a.warn(`Failed to check health for process ${n}:`,r),e.status="dead",e}}async function D(n){if(h.platform()==="win32"){const e=`Get-CimInstance Win32_Process -Filter "ProcessId=${n}" | Select-Object @{Name='CPU';Expression={$_.WorkingSetSize/1MB}}, @{Name='Mem';Expression={$_.WorkingSetSize/1MB}} | ConvertTo-Json -Compress`;try{const r=await m(e,5e3);if(!r||!r.trim())return{cpu:0,memoryMB:0};const s=JSON.parse(r);return{cpu:0,memoryMB:Math.round((s.WorkingSetSize||0)/1024/1024)}}catch{return{cpu:0,memoryMB:0}}}else try{const{stdout:e}=await g(`ps -p ${n} -o %cpu=,rss=`,{encoding:"utf8",timeout:5e3}),r=e.trim().split(/\s+/);if(r.length>=2)return{cpu:parseFloat(r[0])||0,memoryMB:Math.round(parseInt(r[1],10)/1024)}}catch{return{cpu:0,memoryMB:0}}return{cpu:0,memoryMB:0}}async function X(n){const t=new Map,e=n.filter(r=>r.pid).map(async r=>{const s=await H(r.pid,r.agentId);t.set(r.agentId,s)});return await Promise.all(e),t}async function Q(n=new Set,t=new Set){const e=[],r=await I();for(const s of r){const i=n.has(s.pid),d=s.agentId?t.has(s.agentId):!1;e.push({...s,isRunning:!0,managementStatus:i||d?"managed":"orphan",sessionId:void 0,lastSeen:new Date().toISOString()})}return e}async function Y(n){const t=new Set(n.map(c=>c.pid)),e=new Set(n.map(c=>c.agentId)),r=new Map(n.map(c=>[c.pid,c])),s=[],i=new Set,d=await I();for(const c of d){i.add(c.pid);const o=t.has(c.pid),u=c.agentId?e.has(c.agentId):!1,l=r.get(c.pid),P=c.agentId||l?.agentId;s.push({...c,agentId:P,isRunning:!0,managementStatus:o||u?"managed":"orphan",sessionId:void 0,lastSeen:new Date().toISOString()})}for(const c of n)!i.has(c.pid)&&!await w(c.pid)&&s.push({pid:c.pid,command:"(process exited)",agentId:c.agentId,isRunning:!1,managementStatus:"unknown",lastSeen:void 0});return s}export{X as checkAllSessionsHealth,H as checkProcessHealth,V as detectOrphanProcesses,Q as discoverAllProcesses,Y as discoverAllProcessesFull,I as findClaudeCodeProcesses,x as findOrphanProcessByAgentId,K as findOrphanProcessByWorkspace,z as isProcessRunning,w as isProcessRunningAsync,v as terminateProcess,E as terminateProcessTree,U as waitForProcessExit};
42
+ `,o=await l(t,1e4);if(o&&o.trim()){const i=o.trim().split(`
43
+ `).filter(a=>a.trim());for(const a of i)try{const c=JSON.parse(a.trim());if(c.ProcessId)return d.info(`[findOrphanProcessByWorkspace] Found process by PowerShell workspace search: pid=${c.ProcessId}`),{pid:c.ProcessId,command:c.CommandLine||""}}catch{}}}}catch(r){d.debug("[findOrphanProcessByWorkspace] Failed:",r)}}function J(n){try{return process.kill(n,"SIGTERM"),!0}catch(r){return d.warn(`Failed to terminate process ${n}:`,r),!1}}async function j(n){const r={terminated:0,failed:0};if(h.platform()==="win32")try{await g(`taskkill /PID ${n} /T /F`,{encoding:"utf8",timeout:5e3,windowsHide:!0}),r.terminated++,d.info(`Terminated process tree for pid=${n}`)}catch(s){const e=s;d.warn(`Failed to terminate process tree for pid=${n}:`,e.message),r.failed++}else{const s=await b(n);d.debug(`Found ${s.length} child processes for pid=${n}`);for(const e of s){const t=await j(e);r.terminated+=t.terminated,r.failed+=t.failed}J(n)?r.terminated++:r.failed++}return r}async function b(n){try{const{stdout:r}=await g(`pgrep -P ${n}`,{encoding:"utf8",timeout:3e3}),s=r.trim().split(`
44
+ `).filter(Boolean).map(Number),e=[];for(const t of s)e.push(t),e.push(...await b(t));return e}catch{return[]}}async function te(n,r=5e3){const s=Date.now();for(;Date.now()-s<r;){if(!await P(n))return!0;const e=Math.min(100,r-(Date.now()-s));e>0&&await new Promise(t=>setTimeout(t,e))}return!1}async function re(n,r){if(r)return await z(n,r);const s=[];for(const e of n)if(e.pid&&await P(e.pid)){const o=(await w()).find(i=>i.pid===e.pid);o?(s.push({agentId:e.agentId,process:o,sessionInfo:{workspacePath:e.workspacePath,command:e.command}}),d.info(`Found orphan process by PID: agentId=${e.agentId}, pid=${e.pid}`)):(s.push({agentId:e.agentId,process:{pid:e.pid,command:e.command||"(unknown - persisted session)",agentId:e.agentId},sessionInfo:{workspacePath:e.workspacePath,command:e.command}}),d.info(`Found orphan process by PID (no cmd match): agentId=${e.agentId}, pid=${e.pid}`))}for(const e of n)if(!e.pid&&e.agentId){const t=await x(e.agentId);t&&!s.some(o=>o.agentId===e.agentId)&&(s.push({agentId:e.agentId,process:t,sessionInfo:{workspacePath:e.workspacePath,command:e.command}}),d.info(`Found orphan process by agentId: agentId=${e.agentId}, pid=${t.pid}`))}return s}async function z(n,r){const s=[],e=_(r);for(const t of n)if(t.pid&&L(r,t.pid)){const o=e.find(i=>i.pid===t.pid);o?(s.push({agentId:t.agentId,process:o,sessionInfo:{workspacePath:t.workspacePath,command:t.command}}),d.info(`Found orphan process by PID: agentId=${t.agentId}, pid=${t.pid}`)):(s.push({agentId:t.agentId,process:{pid:t.pid,command:t.command||"(unknown - persisted session)",agentId:t.agentId},sessionInfo:{workspacePath:t.workspacePath,command:t.command}}),d.info(`Found orphan process by PID (no cmd match): agentId=${t.agentId}, pid=${t.pid}`))}for(const t of n)if(!t.pid&&t.agentId){const o=await D(t.agentId,r,e);o&&!s.some(i=>i.agentId===t.agentId)&&(s.push({agentId:t.agentId,process:o,sessionInfo:{workspacePath:t.workspacePath,command:t.command}}),d.info(`Found orphan process by agentId: agentId=${t.agentId}, pid=${o.pid}`))}return s}async function U(n,r){const s={pid:n,agentId:r,alive:!1,cpu:0,memoryMB:0,status:"dead",lastUpdate:new Date};try{if(!await P(n))return s.status="dead",d.debug(`Process ${n} is not running`),s;s.alive=!0;const{cpu:e,memoryMB:t}=await q(n);return s.cpu=e,s.memoryMB=t,t>2048?s.status="high_memory":e>100?s.status="high_cpu":s.status="healthy",d.debug(`Process ${n} health: CPU=${e}%, Memory=${t}MB, Status=${s.status}`),s}catch(e){return d.warn(`Failed to check health for process ${n}:`,e),s.status="dead",s}}async function q(n){if(h.platform()==="win32"){const s=`Get-CimInstance Win32_Process -Filter "ProcessId=${n}" | Select-Object @{Name='CPU';Expression={$_.WorkingSetSize/1MB}}, @{Name='Mem';Expression={$_.WorkingSetSize/1MB}} | ConvertTo-Json -Compress`;try{const e=await l(s,5e3);if(!e||!e.trim())return{cpu:0,memoryMB:0};const t=JSON.parse(e);return{cpu:0,memoryMB:Math.round((t.WorkingSetSize||0)/1024/1024)}}catch{return{cpu:0,memoryMB:0}}}else try{const{stdout:s}=await g(`ps -p ${n} -o %cpu=,rss=`,{encoding:"utf8",timeout:5e3}),e=s.trim().split(/\s+/);if(e.length>=2)return{cpu:parseFloat(e[0])||0,memoryMB:Math.round(parseInt(e[1],10)/1024)}}catch{return{cpu:0,memoryMB:0}}return{cpu:0,memoryMB:0}}async function se(n,r){const s=new Map;if(r){for(const t of n)t.pid&&s.set(t.agentId,K(t.pid,t.agentId,r));return s}const e=n.filter(t=>t.pid).map(async t=>{const o=await U(t.pid,t.agentId);s.set(t.agentId,o)});return await Promise.all(e),s}function K(n,r,s){const e={pid:n,agentId:r,alive:!1,cpu:0,memoryMB:0,status:"dead",lastUpdate:new Date};return L(s,n)?(e.alive=!0,e.cpu=0,e.memoryMB=0,e.status="healthy",d.debug(`Process ${n} health: CPU=0%, Memory=0MB, Status=healthy`),e):(e.status="dead",d.debug(`Process ${n} is not running`),e)}async function oe(n=new Set,r=new Set){const s=[],e=await w();for(const t of e){const o=n.has(t.pid),i=t.agentId?r.has(t.agentId):!1;s.push({...t,isRunning:!0,managementStatus:o||i?"managed":"orphan",sessionId:void 0,lastSeen:new Date().toISOString()})}return s}async function ce(n){const r=new Set(n.map(a=>a.pid)),s=new Set(n.map(a=>a.agentId)),e=new Map(n.map(a=>[a.pid,a])),t=[],o=new Set,i=await w();for(const a of i){o.add(a.pid);const c=r.has(a.pid),u=a.agentId?s.has(a.agentId):!1,p=e.get(a.pid),I=a.agentId||p?.agentId;t.push({...a,agentId:I,isRunning:!0,managementStatus:c||u?"managed":"orphan",sessionId:void 0,lastSeen:new Date().toISOString()})}for(const a of n)!o.has(a.pid)&&!await P(a.pid)&&t.push({pid:a.pid,command:"(process exited)",agentId:a.agentId,isRunning:!1,managementStatus:"unknown",lastSeen:void 0});return t}export{ee as captureProcessSnapshot,se as checkAllSessionsHealth,U as checkProcessHealth,re as detectOrphanProcesses,oe as discoverAllProcesses,ce as discoverAllProcessesFull,w as findClaudeCodeProcesses,x as findOrphanProcessByAgentId,ne as findOrphanProcessByWorkspace,Z as isProcessRunning,P as isProcessRunningAsync,J as terminateProcess,j as terminateProcessTree,te as waitForProcessExit};
45
45
 
@@ -0,0 +1,3 @@
1
+
2
+
3
+ export declare function buildRuntimeResourcesSnapshot(agentId: string | undefined): Promise<string | null>;
@@ -0,0 +1,3 @@
1
+ import d from"axios";import{getBrowserPool as m}from"../browser/browser-pool.js";import{getAcodeBgManager as f}from"./acode-bg-manager.js";import{resolveSchedulerBaseUrl as g}from"../config.js";import{ptySessions as p}from"../routes/pty.js";import{getRuntimeAccessToken as l}from"./runtime-binding.js";import{subAgentManager as h}from"./sub-agent-manager-instance.js";import{createLogger as $}from"../utils/logger.js";const c=$("runtime-resources"),w=3e3,i=20;function s(r,e){const t=String(r??"").replace(/\s+/g," ").trim();return t.length>e?`${t.slice(0,e)}\u2026`:t}function b(r){if(typeof r!="number"||!Number.isFinite(r)||r<=0)return"";const e=new Date(r),t=n=>String(n).padStart(2,"0");return`${t(e.getHours())}:${t(e.getMinutes())}`}async function k(r){try{const e=await f();return e?.listTasksWithReconcile?(await e.listTasksWithReconcile(r,"running")).filter(n=>n.status==="running").slice(0,i).map(n=>{const o=b(n.startedAt),a=n.description?s(n.description,60):s(n.commandPreview||n.command,80);return{kind:"background commands",text:`${n.taskId} \`${a}\`${o?` (since ${o})`:""}`}}):[]}catch(e){return c.warn(`collect background commands failed: ${e?.message}`),[]}}function y(r){try{const e=[];for(const t of p.values()){if(t.ownerUserId!==r||t.status!=="running")continue;if(e.length>=i)break;const n=s(t.title||t.shell,60);e.push({kind:"terminals",text:`${t.id} ${n} (running)`})}return e}catch(e){return c.warn(`collect terminals failed: ${e?.message}`),[]}}function S(r){try{return h.listActiveByParent(r).slice(0,i).map(t=>({kind:"sub-agents",text:`${t.subId} ${t.subagentType} "${s(t.description,60)}" (running)`}))}catch(e){return c.warn(`collect sub-agents failed: ${e?.message}`),[]}}function v(r){try{return m().listSessions(r).slice(0,i).map(t=>{const n=s(t.title||t.browserId,40),o=s(t.currentUrl,80);return{kind:"browsers",text:`"${n}"${o?` ${o}`:""}`}})}catch(e){return c.warn(`collect browsers failed: ${e?.message}`),[]}}function u(r,e){if(!Array.isArray(e))return[];const t=[];for(const n of e){if(t.length>=i)break;const o=s(String(n?.name??n?.docId??""),60);if(!o)continue;const a=String(n?.permission??"").trim();t.push({kind:r,text:`${o}${a?` (${a})`:""}`})}return t}async function x(r){try{const{url:e}=g();if(!e)return[];const t=l(e)||l();if(!t)return[];const o=(await d.get(`${e}/api/runtime/agent-resources`,{params:{agentId:r},headers:{"X-Runtime-Token":t},timeout:w})).data??{};return[...u("office docs",o.officeDocs),...u("pencil docs",o.pencilDocs),...u("draw docs",o.drawDocs)]}catch(e){return c.warn(`collect java docs failed (office/pencil/draw omitted): agentId=${r}, error=${e?.message}`),[]}}function A(r){const e=new Map;for(const n of r){const o=e.get(n.kind);o?o.push(n.text):e.set(n.kind,[n.text])}const t=["[Runtime resources \u2014 live snapshot taken after context compaction.]","These already exist and are still running/available. Reuse them instead of creating duplicates","(do not start another dev server, open another browser, or redraw an existing document).","Details (output, page content, document body) are not included \u2014 query them when needed."];for(const[n,o]of e)t.push(`- ${n} (${o.length}): ${o.join("; ")}`);return t.join(`
2
+ `)}async function j(r){if(!r)return null;try{const[e,t]=await Promise.all([k(r),x(r)]),n=[...e,...y(r),...S(r),...v(r),...t];return n.length===0?null:A(n)}catch(e){return c.warn(`build snapshot failed: ${e?.message}`),null}}export{j as buildRuntimeResourcesSnapshot};
3
+
@@ -1,5 +1,6 @@
1
1
 
2
2
  import { type AxiosResponse } from "axios";
3
+ import type { RuntimeToolBatchMetrics } from "../adapter/types.js";
3
4
  import type { Session } from "../types.js";
4
5
  import { RingBuffer, type RingBufferEntry, type RingBufferSlice } from "./ring-buffer.js";
5
6
 
@@ -19,7 +20,13 @@ export interface BridgeEventPayload {
19
20
  readonly actionInput?: string;
20
21
  readonly actionResult?: string;
21
22
  readonly actionId?: string;
23
+
24
+ readonly actionError?: string;
22
25
  readonly parentId?: string;
26
+
27
+ readonly batchId?: string;
28
+
29
+ readonly batchMetrics?: RuntimeToolBatchMetrics;
23
30
  readonly inputTokens?: number;
24
31
  readonly outputTokens?: number;
25
32
 
@@ -46,7 +53,13 @@ interface RuntimeStatusActionInfo {
46
53
  actionResult?: string;
47
54
  actionId?: string;
48
55
 
56
+ actionError?: string;
57
+
49
58
  parentId?: string;
59
+
60
+ batchId?: string;
61
+
62
+ batchMetrics?: RuntimeToolBatchMetrics;
50
63
  }
51
64
  export interface RuntimeCallbackAuthOptions {
52
65
  runtimeAccessToken?: string;
@@ -1,5 +1,5 @@
1
- import h from"axios";import{resolveSchedulerBaseUrlFrom as M}from"../config.js";import{requestRuntimeAccessTokenRefreshForServer as C}from"../services/auto-register.js";import{logger as p}from"../utils/logger.js";import{agentEventStore as S}from"./agent-event-store.js";import{scheduleEventPush as $}from"./event-delta-pusher.js";import{RingBuffer as P}from"./ring-buffer.js";import{getRuntimeAccessToken as A}from"./runtime-binding.js";const B=new P(2e3);function m(e,t=y(e)){const c=e?.runtimeAccessToken||A(t)||A();return c?{"X-Runtime-Token":c}:void 0}function x(e){if(e)return{schedulerBaseUrl:e.schedulerBaseUrl}}function y(e){return M(e?.schedulerBaseUrl).url}const O=100;function w(e){if(typeof e!="object"||e===null)return;const t=e.response;if(typeof t!="object"||t===null)return;const c=t.status;return typeof c=="number"?c:void 0}let L=null;async function R(e){if(L)return L;L=(async()=>{try{const t=await C(e);return t.success&&t.runtimeAccessToken?(p.info("[session-output] Runtime token refreshed after 401"),!0):(p.warn("[session-output] Runtime token refresh failed",{error:t.error}),!1)}catch(t){return p.warn("[session-output] Runtime token refresh threw",{error:t}),!1}})();try{return await L}finally{L=null}}const _=8e3,g=64*1024,v=32*1024,E=15e3,U=new Map;async function J(e,t,c,n,r,o,u,s){const i={agentId:e,sessionId:t,status:c};u!==void 0&&(i.timestamp=u),n&&(n.actionType&&(i.actionType=n.actionType),n.actionLabel&&(i.actionLabel=n.actionLabel),n.actionDetail&&(i.actionDetail=n.actionDetail),n.actionInput&&(i.actionInput=n.actionInput),n.actionResult&&(i.actionResult=n.actionResult),n.actionId&&(i.actionId=n.actionId),n.parentId&&(i.parentId=n.parentId)),r&&(i.inputTokens=r.inputTokens,i.outputTokens=r.outputTokens,r.contextLimit&&(i.contextLimit=r.contextLimit),r.maxOutput&&(i.maxOutput=r.maxOutput),r.inputLimit&&(i.inputLimit=r.inputLimit),r.compactionThreshold&&(i.compactionThreshold=r.compactionThreshold),r.cacheHitTokens&&(i.cacheHitTokens=r.cacheHitTokens),r.cacheMissTokens&&(i.cacheMissTokens=r.cacheMissTokens)),s&&(i.sourceEventType=s),process.env.ACODE_TOKEN_DEBUG==="1"&&(i.inputTokens!==void 0||i.outputTokens!==void 0||i.cacheHitTokens!==void 0||i.cacheMissTokens!==void 0)&&console.log(`[TokenDebug][SendStatus] status=${c} inputTokens=${i.inputTokens??"(none)"} outputTokens=${i.outputTokens??"(none)"} cacheHitTokens=${i.cacheHitTokens??"(none)"} cacheMissTokens=${i.cacheMissTokens??"(none)"} contextLimit=${i.contextLimit??"(none)"} actionType=${i.actionType??"(none)"}`);const a=y(o),k=m(o,a);if(!k){p.warn("Skip runtime status callback because runtime token is missing",{agentId:e,sessionId:t,status:c,schedulerBaseUrl:a});return}const f=n?.actionType==="context_compaction";f&&p.info("[compaction-diag] sendStatus enter",{agentId:e,sessionId:t,status:c,actionId:n?.actionId,parentId:n?.parentId,actionLabel:n?.actionLabel});try{const l=await h.post(`${a}/api/runtime/callback/status`,i,{headers:k,timeout:15e3});if(f){const d=l?.data;p.info("[compaction-diag] sendStatus success",{agentId:e,actionId:n?.actionId,actionLabel:n?.actionLabel,httpStatus:l?.status,ignored:d?.ignored,responseBody:d})}return l}catch(l){if(w(l)===401&&await R(a)){const T=m(x(o),a);if(T)try{const b=await h.post(`${a}/api/runtime/callback/status`,i,{headers:T,timeout:15e3});if(f){const H=b?.data;p.info("[compaction-diag] sendStatus retry success",{agentId:e,actionId:n?.actionId,actionLabel:n?.actionLabel,httpStatus:b?.status,ignored:H?.ignored})}return b}catch(b){p.warn("Runtime status callback retry failed after token refresh",{agentId:e,sessionId:t,status:c,error:b});return}}p.warn("Runtime status callback failed",{agentId:e,sessionId:t,status:c,schedulerBaseUrl:a,error:l});return}finally{const l={category:"status",agentId:e,sessionId:t,status:c,actionType:n?.actionType,actionLabel:n?.actionLabel,actionDetail:n?.actionDetail,actionInput:n?.actionInput,actionResult:n?.actionResult,actionId:n?.actionId,parentId:n?.parentId,inputTokens:r?.inputTokens,outputTokens:r?.outputTokens,cacheHitTokens:r?.cacheHitTokens,cacheMissTokens:r?.cacheMissTokens,sourceEventType:s};B.append(l);const d=S.append(e,l);$(e,d,o)}}async function D(e,t,c,n,r,o,u){const s=y(o);try{const i=m(o,s);if(!i){p.warn("Skip runtime output callback because runtime token is missing",{agentId:e,sessionId:c,schedulerBaseUrl:s});return}const a={headers:i,timeout:E};u&&(a.signal=u),await h.post(`${s}/api/runtime/callback/output`,{agentId:e,output:t,sessionId:c,seq:n,...r},a)}catch(i){if(u?.aborted||i?.name==="AbortError"||i?.code==="ERR_CANCELED")throw i;if(w(i)===401&&await R(s)){const k=m(x(o),s);if(k)try{const f={headers:k,timeout:E};u&&(f.signal=u),await h.post(`${s}/api/runtime/callback/output`,{agentId:e,output:t,sessionId:c,seq:n,...r},f);return}catch{}}throw p.warn("Runtime output callback failed",{agentId:e,sessionId:c,error:i}),i}finally{const i=t.length>_?`...(truncated)
2
- ${t.slice(-_)}`:t,a={category:"output",agentId:e,sessionId:c,output:i,seq:n,sourceEventType:r?.sourceEventType,logLevel:r?.logLevel,logCategory:r?.logCategory};B.appendOrMerge(a,f=>{const l=f.data;if(l.category!=="output"||l.sessionId!==c||l.sourceEventType!==r?.sourceEventType||Date.now()-f.timestamp>1e4)return!1;const d=(l.output||"").length,T=(a.output||"").length;return d+T<=_},(f,l)=>{const d=f.output||"",T=l.output||"";return d.includes(T)?f:{...f,output:`${d}${T}`}});const k=S.appendOrMergeOutput(e,a);$(e,k,o)}}async function V(e,t,c,n,r){const o=y(n),u={agentId:e,sessionId:t,questions:c,...r?{toolCallId:r}:{}};try{const s=m(n,o);if(!s)return;await h.post(`${o}/api/runtime/callback/question`,u,{headers:s})}catch(s){if(w(s)===401&&await R(o)){const a=m(x(n),o);if(a)try{await h.post(`${o}/api/runtime/callback/question`,u,{headers:a});return}catch{}}}finally{const s={category:"question",agentId:e,sessionId:t,...r?{toolCallId:r}:{},questions:c};B.append(s);const i=S.append(e,s);$(e,i,n)}}async function Y(e,t,c,n){const r=y(n),o={agentId:e,sessionId:t,...c};try{const u=m(n,r);if(!u)return;await h.post(`${r}/api/runtime/callback/tool-auth`,o,{headers:u})}catch(u){if(w(u)===401&&await R(r)){const i=m(x(n),r);if(i)try{await h.post(`${r}/api/runtime/callback/tool-auth`,o,{headers:i});return}catch{}}}}async function Z(e){const t=y();try{const c=m(void 0,t);if(!c)return;await h.post(`${t}/api/runtime/callback/file-changed`,e,{headers:c})}catch(c){if(w(c)===401&&await R(t)){const r=m(void 0,t);if(r)try{await h.post(`${t}/api/runtime/callback/file-changed`,e,{headers:r});return}catch{}}}finally{const c={category:"file_changed",agentId:"",sessionId:null,workspacePath:e.workspacePath,filePath:e.filePath,eventType:e.eventType,size:e.size};B.append(c)}}function I(e,t){const c=U.get(e);if(!c||!t)return;const n=`${c.outputBuffer}${t}`;if(n.length<=g){c.outputBuffer=n;return}const o=`\r
3
- [AgentsWorkStudio: omitted ${n.length-g} chars of old terminal output]\r
4
- `,u=Math.max(0,g-o.length);c.outputBuffer=`${o}${n.slice(-u)}`}function F(e){const t=U.get(e);t&&(t.flushTimer||(t.flushTimer=setTimeout(()=>{t.flushTimer=null,q(e).catch(()=>{})},O)))}async function q(e){const t=U.get(e);if(!t||t.flushInFlight||!t.outputBuffer)return;const c=t.outputBuffer.slice(0,v);t.outputBuffer=t.outputBuffer.slice(v);const n=(async()=>{const r=t.seq+1;t.seq=r,await D(t.agentId,c,e,r),U.get(e)?.outputBuffer&&F(e)})();t.flushInFlight=n;try{await n}finally{const r=U.get(e);r&&(r.flushInFlight=null)}}export{I as appendSessionOutput,B as bridgeEventBuffer,q as flushSessionOutput,F as scheduleOutputFlush,Z as sendFileChanged,D as sendOutput,V as sendQuestionRequest,J as sendStatus,Y as sendToolAuthRequest,U as sessions};
1
+ import h from"axios";import{resolveSchedulerBaseUrlFrom as H}from"../config.js";import{requestRuntimeAccessTokenRefreshForServer as C}from"../services/auto-register.js";import{logger as f}from"../utils/logger.js";import{agentEventStore as S}from"./agent-event-store.js";import{scheduleEventPush as $}from"./event-delta-pusher.js";import{RingBuffer as P}from"./ring-buffer.js";import{getRuntimeAccessToken as _}from"./runtime-binding.js";const B=new P(2e3);function m(t,r=y(t)){const c=t?.runtimeAccessToken||_(r)||_();return c?{"X-Runtime-Token":c}:void 0}function x(t){if(t)return{schedulerBaseUrl:t.schedulerBaseUrl}}function y(t){return H(t?.schedulerBaseUrl).url}const O=100;function w(t){if(typeof t!="object"||t===null)return;const r=t.response;if(typeof r!="object"||r===null)return;const c=r.status;return typeof c=="number"?c:void 0}let L=null;async function R(t){if(L)return L;L=(async()=>{try{const r=await C(t);return r.success&&r.runtimeAccessToken?(f.info("[session-output] Runtime token refreshed after 401"),!0):(f.warn("[session-output] Runtime token refresh failed",{error:r.error}),!1)}catch(r){return f.warn("[session-output] Runtime token refresh threw",{error:r}),!1}})();try{return await L}finally{L=null}}const E=8e3,M=64*1024,g=32*1024,A=15e3,U=new Map;async function J(t,r,c,e,i,o,u,s){const n={agentId:t,sessionId:r,status:c};u!==void 0&&(n.timestamp=u),e&&(e.actionType&&(n.actionType=e.actionType),e.actionLabel&&(n.actionLabel=e.actionLabel),e.actionDetail&&(n.actionDetail=e.actionDetail),e.actionInput&&(n.actionInput=e.actionInput),e.actionResult&&(n.actionResult=e.actionResult),e.actionError&&(n.actionError=e.actionError),e.actionId&&(n.actionId=e.actionId),e.parentId&&(n.parentId=e.parentId),e.batchId&&(n.batchId=e.batchId),e.batchMetrics&&(n.batchMetrics=e.batchMetrics)),i&&(n.inputTokens=i.inputTokens,n.outputTokens=i.outputTokens,i.contextLimit&&(n.contextLimit=i.contextLimit),i.maxOutput&&(n.maxOutput=i.maxOutput),i.inputLimit&&(n.inputLimit=i.inputLimit),i.compactionThreshold&&(n.compactionThreshold=i.compactionThreshold),i.cacheHitTokens!==void 0&&(n.cacheHitTokens=i.cacheHitTokens),i.cacheMissTokens!==void 0&&(n.cacheMissTokens=i.cacheMissTokens)),s&&(n.sourceEventType=s),process.env.ACODE_TOKEN_DEBUG==="1"&&(n.inputTokens!==void 0||n.outputTokens!==void 0||n.cacheHitTokens!==void 0||n.cacheMissTokens!==void 0)&&console.log(`[TokenDebug][SendStatus] status=${c} inputTokens=${n.inputTokens??"(none)"} outputTokens=${n.outputTokens??"(none)"} cacheHitTokens=${n.cacheHitTokens??"(none)"} cacheMissTokens=${n.cacheMissTokens??"(none)"} contextLimit=${n.contextLimit??"(none)"} actionType=${n.actionType??"(none)"}`);const a=y(o),k=m(o,a);if(!k){f.warn("Skip runtime status callback because runtime token is missing",{agentId:t,sessionId:r,status:c,schedulerBaseUrl:a});return}const p=e?.actionType==="context_compaction";p&&f.info("[compaction-diag] sendStatus enter",{agentId:t,sessionId:r,status:c,actionId:e?.actionId,parentId:e?.parentId,actionLabel:e?.actionLabel});try{const l=await h.post(`${a}/api/runtime/callback/status`,n,{headers:k,timeout:15e3});if(p){const d=l?.data;f.info("[compaction-diag] sendStatus success",{agentId:t,actionId:e?.actionId,actionLabel:e?.actionLabel,httpStatus:l?.status,ignored:d?.ignored,responseBody:d})}return l}catch(l){if(w(l)===401&&await R(a)){const T=m(x(o),a);if(T)try{const b=await h.post(`${a}/api/runtime/callback/status`,n,{headers:T,timeout:15e3});if(p){const v=b?.data;f.info("[compaction-diag] sendStatus retry success",{agentId:t,actionId:e?.actionId,actionLabel:e?.actionLabel,httpStatus:b?.status,ignored:v?.ignored})}return b}catch(b){f.warn("Runtime status callback retry failed after token refresh",{agentId:t,sessionId:r,status:c,error:b});return}}f.warn("Runtime status callback failed",{agentId:t,sessionId:r,status:c,schedulerBaseUrl:a,error:l});return}finally{const l={category:"status",agentId:t,sessionId:r,status:c,actionType:e?.actionType,actionLabel:e?.actionLabel,actionDetail:e?.actionDetail,actionInput:e?.actionInput,actionResult:e?.actionResult,actionError:e?.actionError,actionId:e?.actionId,parentId:e?.parentId,batchId:e?.batchId,batchMetrics:e?.batchMetrics,inputTokens:i?.inputTokens,outputTokens:i?.outputTokens,cacheHitTokens:i?.cacheHitTokens,cacheMissTokens:i?.cacheMissTokens,sourceEventType:s};B.append(l);const d=S.append(t,l);$(t,d,o)}}async function D(t,r,c,e,i,o,u){const s=y(o);try{const n=m(o,s);if(!n){f.warn("Skip runtime output callback because runtime token is missing",{agentId:t,sessionId:c,schedulerBaseUrl:s});return}const a={headers:n,timeout:A};u&&(a.signal=u),await h.post(`${s}/api/runtime/callback/output`,{agentId:t,output:r,sessionId:c,seq:e,...i},a)}catch(n){if(u?.aborted||n?.name==="AbortError"||n?.code==="ERR_CANCELED")throw n;if(w(n)===401&&await R(s)){const k=m(x(o),s);if(k)try{const p={headers:k,timeout:A};u&&(p.signal=u),await h.post(`${s}/api/runtime/callback/output`,{agentId:t,output:r,sessionId:c,seq:e,...i},p);return}catch{}}throw f.warn("Runtime output callback failed",{agentId:t,sessionId:c,error:n}),n}finally{const n=r.length>E?`...(truncated)
2
+ ${r.slice(-E)}`:r,a={category:"output",agentId:t,sessionId:c,output:n,seq:e,sourceEventType:i?.sourceEventType,logLevel:i?.logLevel,logCategory:i?.logCategory};B.appendOrMerge(a,p=>{const l=p.data;if(l.category!=="output"||l.sessionId!==c||l.sourceEventType!==i?.sourceEventType||Date.now()-p.timestamp>1e4)return!1;const d=(l.output||"").length,T=(a.output||"").length;return d+T<=E},(p,l)=>{const d=p.output||"",T=l.output||"";return d.includes(T)?p:{...p,output:`${d}${T}`}});const k=S.appendOrMergeOutput(t,a);$(t,k,o)}}async function V(t,r,c,e,i){const o=y(e),u={agentId:t,sessionId:r,questions:c,...i?{toolCallId:i}:{}};try{const s=m(e,o);if(!s)return;await h.post(`${o}/api/runtime/callback/question`,u,{headers:s})}catch(s){if(w(s)===401&&await R(o)){const a=m(x(e),o);if(a)try{await h.post(`${o}/api/runtime/callback/question`,u,{headers:a});return}catch{}}}finally{const s={category:"question",agentId:t,sessionId:r,...i?{toolCallId:i}:{},questions:c};B.append(s);const n=S.append(t,s);$(t,n,e)}}async function Y(t,r,c,e){const i=y(e),o={agentId:t,sessionId:r,...c};try{const u=m(e,i);if(!u)return;await h.post(`${i}/api/runtime/callback/tool-auth`,o,{headers:u})}catch(u){if(w(u)===401&&await R(i)){const n=m(x(e),i);if(n)try{await h.post(`${i}/api/runtime/callback/tool-auth`,o,{headers:n});return}catch{}}}}async function Z(t){const r=y();try{const c=m(void 0,r);if(!c)return;await h.post(`${r}/api/runtime/callback/file-changed`,t,{headers:c})}catch(c){if(w(c)===401&&await R(r)){const i=m(void 0,r);if(i)try{await h.post(`${r}/api/runtime/callback/file-changed`,t,{headers:i});return}catch{}}}finally{const c={category:"file_changed",agentId:"",sessionId:null,workspacePath:t.workspacePath,filePath:t.filePath,eventType:t.eventType,size:t.size};B.append(c)}}function I(t,r){const c=U.get(t);if(!c||!r)return;const e=`${c.outputBuffer}${r}`;if(e.length<=M){c.outputBuffer=e;return}const o=`\r
3
+ [AgentsWorkStudio: omitted ${e.length-M} chars of old terminal output]\r
4
+ `,u=Math.max(0,M-o.length);c.outputBuffer=`${o}${e.slice(-u)}`}function F(t){const r=U.get(t);r&&(r.flushTimer||(r.flushTimer=setTimeout(()=>{r.flushTimer=null,q(t).catch(()=>{})},O)))}async function q(t){const r=U.get(t);if(!r||r.flushInFlight||!r.outputBuffer)return;const c=r.outputBuffer.slice(0,g);r.outputBuffer=r.outputBuffer.slice(g);const e=(async()=>{const i=r.seq+1;r.seq=i,await D(r.agentId,c,t,i),U.get(t)?.outputBuffer&&F(t)})();r.flushInFlight=e;try{await e}finally{const i=U.get(t);i&&(i.flushInFlight=null)}}export{I as appendSessionOutput,B as bridgeEventBuffer,q as flushSessionOutput,F as scheduleOutputFlush,Z as sendFileChanged,D as sendOutput,V as sendQuestionRequest,J as sendStatus,Y as sendToolAuthRequest,U as sessions};
5
5