aws-runtime-bridge 1.9.153 → 1.9.168

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 (164) hide show
  1. package/CHANGELOG.md +766 -0
  2. package/dist/adapter/AcodeSdkAdapter.d.ts +57 -6
  3. package/dist/adapter/AcodeSdkAdapter.js +4 -8
  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 -20
  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/acode-todos.js +1 -1
  23. package/dist/routes/background-tasks.js +3 -3
  24. package/dist/routes/capabilities.js +1 -1
  25. package/dist/routes/dashboard.d.ts +2 -0
  26. package/dist/routes/dashboard.js +4 -4
  27. package/dist/routes/git.js +22 -22
  28. package/dist/routes/instance.js +1 -1
  29. package/dist/routes/launch.js +10 -10
  30. package/dist/routes/ltr.js +1 -1
  31. package/dist/routes/mcp-extra.js +2 -2
  32. package/dist/routes/mcp.d.ts +4 -0
  33. package/dist/routes/mcp.js +1 -1
  34. package/dist/routes/plugins.js +1 -1
  35. package/dist/routes/pty.d.ts +11 -3
  36. package/dist/routes/pty.js +3 -3
  37. package/dist/routes/runtime-binding.js +1 -1
  38. package/dist/routes/sessions.d.ts +18 -74
  39. package/dist/routes/sessions.js +1 -1
  40. package/dist/routes/skills.js +1 -1
  41. package/dist/routes/sub-agents.js +8 -8
  42. package/dist/routes/terminal.d.ts +24 -2
  43. package/dist/routes/terminal.js +34 -36
  44. package/dist/services/agent-process-manager.js +1 -1
  45. package/dist/services/agent-pty-manager.js +4 -4
  46. package/dist/services/aws-client-agent-mcp.js +2 -2
  47. package/dist/services/capability-config.d.ts +8 -0
  48. package/dist/services/capability-config.js +2 -2
  49. package/dist/services/desktop-mcp-manager.d.ts +3 -1
  50. package/dist/services/desktop-mcp-manager.js +1 -1
  51. package/dist/services/instance-ai-config-service.js +1 -1
  52. package/dist/services/instance-features.d.ts +26 -2
  53. package/dist/services/instance-features.js +1 -1
  54. package/dist/services/instance-init-service.js +1 -1
  55. package/dist/services/launch-manager.d.ts +9 -1
  56. package/dist/services/launch-manager.js +6 -6
  57. package/dist/services/launch-metrics.d.ts +1 -1
  58. package/dist/services/launch-metrics.js +4 -3
  59. package/dist/services/mcp-deploy.d.ts +4 -0
  60. package/dist/services/mcp-env-injector.d.ts +12 -0
  61. package/dist/services/mcp-env-injector.js +2 -0
  62. package/dist/services/mcp-launch-binding-queue.d.ts +8 -0
  63. package/dist/services/mcp-launch-binding-queue.js +1 -1
  64. package/dist/services/orphan-monitor.js +1 -1
  65. package/dist/services/panel-env.d.ts +6 -2
  66. package/dist/services/panel-env.js +1 -1
  67. package/dist/services/plugin-manager.js +9 -9
  68. package/dist/services/process-detector.d.ts +23 -3
  69. package/dist/services/process-detector.js +13 -13
  70. package/dist/services/runtime-resources-snapshot.d.ts +3 -0
  71. package/dist/services/runtime-resources-snapshot.js +3 -0
  72. package/dist/services/session-output.d.ts +13 -0
  73. package/dist/services/session-output.js +4 -4
  74. package/dist/services/tunnel-client.js +1 -1
  75. package/dist/services/workspace-files.js +1 -1
  76. package/dist/services/workspace-watch.js +1 -1
  77. package/dist/types.d.ts +4 -0
  78. package/dist/utils/env-safety.d.ts +15 -0
  79. package/dist/utils/env-safety.js +2 -0
  80. package/dist/utils/lifecycle-log.d.ts +2 -0
  81. package/dist/utils/lifecycle-log.js +3 -0
  82. package/dist/utils/mcp-utils.js +1 -1
  83. package/package/acode/dist/ask-user-question-tool.js +1 -1
  84. package/package/acode/dist/await-complete-tool.js +1 -1
  85. package/package/acode/dist/background-command-manager.js +4 -4
  86. package/package/acode/dist/background-command-tools.js +1 -1
  87. package/package/acode/dist/built-in-file-tools.d.ts +31 -2
  88. package/package/acode/dist/built-in-file-tools.js +2 -2
  89. package/package/acode/dist/built-in-symbols-tool.js +1 -1
  90. package/package/acode/dist/builtins/shellCommandPreparation.d.ts +2 -0
  91. package/package/acode/dist/builtins/shellCommandPreparation.js +2 -2
  92. package/package/acode/dist/compaction.d.ts +10 -0
  93. package/package/acode/dist/compaction.js +6 -6
  94. package/package/acode/dist/context-overflow.d.ts +19 -0
  95. package/package/acode/dist/context-overflow.js +2 -0
  96. package/package/acode/dist/grammars/grammars/tree-sitter-lua.wasm +0 -0
  97. package/package/acode/dist/index.d.ts +4 -1
  98. package/package/acode/dist/index.js +1 -1
  99. package/package/acode/dist/mcpToolNames.d.ts +4 -0
  100. package/package/acode/dist/mcpToolNames.js +1 -1
  101. package/package/acode/dist/parsers/ast-cache.d.ts +12 -1
  102. package/package/acode/dist/parsers/ast-cache.js +1 -1
  103. package/package/acode/dist/parsers/language-queries.js +1 -1
  104. package/package/acode/dist/parsers/symbol-extractor.js +2 -2
  105. package/package/acode/dist/parsers/tree-sitter-loader.d.ts +1 -1
  106. package/package/acode/dist/parsers/tree-sitter-loader.js +1 -1
  107. package/package/acode/dist/plugin-types.d.ts +5 -0
  108. package/package/acode/dist/plugin-types.js +1 -0
  109. package/package/acode/dist/read-file-state.d.ts +48 -0
  110. package/package/acode/dist/read-file-state.js +2 -0
  111. package/package/acode/dist/runtime-environment.d.ts +2 -0
  112. package/package/acode/dist/runtime-environment.js +3 -2
  113. package/package/acode/dist/runtime.d.ts +124 -10
  114. package/package/acode/dist/runtime.js +27 -23
  115. package/package/acode/dist/skill-tool.js +3 -3
  116. package/package/acode/dist/sub-agent-manager.js +1 -1
  117. package/package/acode/dist/sub-agent-tools.js +5 -5
  118. package/package/acode/dist/todo-tool.js +3 -3
  119. package/package/acode/dist/tool-allocation.js +1 -1
  120. package/package/acode/dist/tool-concurrency/index.d.ts +5 -0
  121. package/package/acode/dist/tool-concurrency/index.js +2 -0
  122. package/package/acode/dist/tool-concurrency/observability.d.ts +46 -0
  123. package/package/acode/dist/tool-concurrency/observability.js +3 -0
  124. package/package/acode/dist/tool-concurrency/resource-lock.d.ts +25 -0
  125. package/package/acode/dist/tool-concurrency/resource-lock.js +2 -0
  126. package/package/acode/dist/tool-concurrency/scheduler.d.ts +30 -0
  127. package/package/acode/dist/tool-concurrency/scheduler.js +2 -0
  128. package/package/acode/dist/tool-concurrency/types.d.ts +80 -0
  129. package/package/acode/dist/tool-concurrency/types.js +2 -0
  130. package/package/acode/dist/tool-group-manager.d.ts +128 -0
  131. package/package/acode/dist/tool-group-manager.js +18 -0
  132. package/package/acode/dist/types.d.ts +20 -2
  133. package/package/acode/package.json +3 -3
  134. package/package/aws-client-agent-mcp/README.md +1 -0
  135. package/package/aws-client-agent-mcp/dist/agent-client.d.ts +20 -32
  136. package/package/aws-client-agent-mcp/dist/agent-client.js +1 -1
  137. package/package/aws-client-agent-mcp/dist/http-client.d.ts +10 -0
  138. package/package/aws-client-agent-mcp/dist/http-client.js +1 -1
  139. package/package/aws-client-agent-mcp/dist/logger.d.ts +2 -1
  140. package/package/aws-client-agent-mcp/dist/logger.js +2 -2
  141. package/package/aws-client-agent-mcp/dist/mcp-server.d.ts +65 -10
  142. package/package/aws-client-agent-mcp/dist/mcp-server.js +30 -30
  143. package/package/aws-client-agent-mcp/dist/mcp-tools.d.ts +42 -7
  144. package/package/aws-client-agent-mcp/dist/mcp-tools.js +196 -21
  145. package/package/aws-client-agent-mcp/dist/memory-store.d.ts +2 -0
  146. package/package/aws-client-agent-mcp/dist/memory-store.js +3 -3
  147. package/package/aws-client-agent-mcp/dist/message-buffer.js +1 -1
  148. package/package/aws-client-agent-mcp/dist/office/office-equation.d.ts +5 -0
  149. package/package/aws-client-agent-mcp/dist/office/office-equation.js +2 -0
  150. package/package/aws-client-agent-mcp/dist/office/office-image.d.ts +12 -0
  151. package/package/aws-client-agent-mcp/dist/office/office-image.js +2 -0
  152. package/package/aws-client-agent-mcp/dist/office/office-workspace.d.ts +40 -0
  153. package/package/aws-client-agent-mcp/dist/office/office-workspace.js +2 -0
  154. package/package/aws-client-agent-mcp/dist/status-reporter.js +1 -1
  155. package/package/aws-client-agent-mcp/dist/tool-groups.d.ts +4 -0
  156. package/package/aws-client-agent-mcp/dist/tool-groups.js +2 -2
  157. package/package/aws-client-agent-mcp/dist/types.d.ts +56 -3
  158. package/package/aws-client-agent-mcp/dist/websocket-client.js +1 -1
  159. package/package/aws-client-agent-mcp/package.json +2 -1
  160. package/package.json +1 -1
  161. package/package/acode/dist/capability-prompt.d.ts +0 -16
  162. package/package/acode/dist/capability-prompt.js +0 -3
  163. package/package/acode/dist/plugin-tools.d.ts +0 -14
  164. package/package/acode/dist/plugin-tools.js +0 -9
@@ -0,0 +1,18 @@
1
+ const b="mcp:";function $(h){return`${b}${h}`}function S(h){return h.startsWith(b)}class N{constructor(e){this.groups=new Map,this.expandedGroups=new Set,this.stateOf=e.stateOf}register(e){this.groups.set(e.key,e)}unregister(e){this.groups.delete(e),this.expandedGroups.delete(e)}getRegistration(e){return this.groups.get(e)}getAllGroups(){return Array.from(this.groups.values())}getConfigState(e){return this.stateOf(e)??"disabled"}isEnabled(e){return this.getConfigState(e)!=="disabled"}isExpanded(e){return this.expandedGroups.has(e)}expand(e){return this.groups.has(e)?this.expandedGroups.has(e)?0:(this.expandedGroups.add(e),1):-1}collapse(e){return this.groups.has(e)?this.expandedGroups.delete(e)?1:0:-1}resetExpanded(){this.expandedGroups.clear()}shouldShowToLLM(e){if(!e)return!0;const o=this.groups.get(e);if(!o)return!0;const s=this.getConfigState(e);return s==="disabled"?!1:s==="collapsed"&&o.collapsible?this.expandedGroups.has(e):!0}getGroupForExposedName(e){const o=e.indexOf("__"),s=o>0?e.slice(0,o):void 0,c=o>=0&&o<e.length-2?e.slice(o+2):void 0,r=()=>[...this.groups].filter(([,t])=>!t.serverName);for(const[t,a]of r())if(!(!a.toolNames||a.toolNames.length===0)){for(const d of a.toolNames)if(e===d||c!==void 0&&c===d)return t}for(const[t,a]of r())if(e.startsWith(`${t}_`)||c!==void 0&&(c.startsWith(`${t}_`)||c===t))return t;if(s){for(const[t,a]of this.groups)if(a.serverName&&a.serverName===s)return t}}findGroupByServerName(e){for(const[o,s]of this.groups)if(s.serverName===e)return o}shouldShowToLLMByName(e){const o=this.getGroupForExposedName(e);return this.shouldShowToLLM(o)}claimedToolNamesBySubGroups(){const e=new Set;for(const o of this.groups.values())if(!o.serverName)for(const s of o.toolNames??[])e.add(s);return e}listToolManifests(e,o){const s=this.groups.get(e);if(!s)return[];if(s.toolNames&&s.toolNames.length>0)return o.filter(r=>{const t=r.exposedName.includes("__")?r.exposedName.slice(r.exposedName.indexOf("__")+2):r.exposedName;return s.toolNames.includes(t)}).map(r=>({name:r.exposedName,description:r.description,inputSchema:r.inputSchema}));const c=`${e}_`;return o.filter(r=>{const t=r.exposedName.includes("__")?r.exposedName.slice(r.exposedName.indexOf("__")+2):r.exposedName;return t===e||t.startsWith(c)}).map(r=>({name:r.exposedName,description:r.description,inputSchema:r.inputSchema}))}buildCapabilityPrompt(){const e=[],o=[],s=[];for(const t of this.groups.values()){const a=this.getConfigState(t.key);a==="disabled"?s.push(t):a==="collapsed"&&t.collapsible?o.push(t):e.push(t)}const c=t=>`- ${t.key}\uFF1A${t.label}${t.summary?` \u2014\u2014 ${t.summary}`:""}`,r=["## \u53EF\u7528\u80FD\u529B",""];if(e.length>0||o.length>0){r.push("\u5DF2\u5F00\u542F\uFF1A");for(const t of e)r.push(`${c(t)}\uFF08\u5DE5\u5177\u5DF2\u53EF\u76F4\u63A5\u8C03\u7528\uFF09`);for(const t of o)r.push(`${c(t)}\uFF08\u5DE5\u5177\u5DF2\u6536\u8D77\uFF09`);o.length>0&&(r.push(""),r.push('\u6807\u8BB0\u300C\u5DE5\u5177\u5DF2\u6536\u8D77\u300D\u7684\u80FD\u529B\uFF1A\u5DE5\u5177\u9ED8\u8BA4\u6536\u8D77\u4EE5\u4FDD\u6301\u5DE5\u5177\u5217\u8868\u7A33\u5B9A\u5E76\u8282\u7701\u4E0A\u4E0B\u6587\uFF0C\u4EFB\u52A1\u9700\u8981\u65F6\u5148\u8C03\u7528 expand_tools({ group: "<\u4E0A\u8FF0\u7EC4 key>" }) \u5C55\u5F00\uFF0C\u5DE5\u5177\u5B9A\u4E49\u968F\u7ED3\u679C\u8FD4\u56DE\u540E\u5373\u53EF\u7ECF call_tool \u8C03\u7528\u3002\u6BCF\u6B21\u53EA\u80FD\u5C55\u5F00\u4E00\u4E2A\u7EC4\u3002group \u53C2\u6570\u5FC5\u987B\u9010\u5B57\u53D6\u81EA\u4E0A\u65B9\u6E05\u5355\u91CC\u7684\u7EC4 key\uFF1B\u6E05\u5355\u5916\u7684 key\uFF08\u5305\u62EC\u6309 mcp:{server\u540D} \u81EA\u884C\u63A8\u6D4B\u62FC\u51FA\u7684\uFF09\u5E76\u4E0D\u5B58\u5728\uFF0Cexpand_tools \u53EA\u4F1A\u8FD4\u56DE\u300C\u672A\u77E5\u5DE5\u5177\u7EC4\u300D\u2014\u2014\u9700\u8981\u6E05\u5355\u5916\u7684\u80FD\u529B\u65F6\u8BF4\u660E\u5B83\u672A\u5F00\u542F\u6216\u4E0D\u53EF\u7528\uFF0C\u4E0D\u8981\u81C6\u9020 key \u91CD\u8BD5\u3002'))}else r.push("\u5F53\u524D\u6CA1\u6709\u5DF2\u5F00\u542F\u7684\u6269\u5C55\u80FD\u529B\u3002");if(s.length>0){r.push(""),r.push("\u672A\u5F00\u542F\uFF08\u5DE5\u5177\u4E0D\u5728\u4F60\u7684\u5217\u8868\u4E2D\uFF09\u3002\u82E5\u4EFB\u52A1\u786E\u5B9E\u9700\u8981\uFF0C\u8BF7\u544A\u77E5\u7528\u6237\u53BB\u300C\u80FD\u529B\u914D\u7F6E\u300D\u4E2D\u5F00\u542F\u5BF9\u5E94\u5F00\u5173\uFF0C\u4E0D\u8981\u81EA\u884C\u5047\u8BBE\u4F60\u6709\u8BE5\u80FD\u529B\uFF1A");for(const t of s)r.push(`${c(t)}\uFF08\u9700\u7528\u6237\u5728\u300C\u80FD\u529B\u914D\u7F6E\u300D\u4E2D\u5F00\u542F\uFF09`)}return r.join(`
2
+ `)}registerFromMeta(e,o,s,c){this.groups.has(e)||this.register({key:e,label:o??e,summary:s??"",collapsible:!0})}addToolName(e,o){const s=this.groups.get(e);s&&(s.toolNames&&s.toolNames.includes(o)||(s.toolNames?s.toolNames.push(o):s.toolNames=[o]))}}function k(h){const{toolGroupManager:e,getAllTools:o,capabilityToolRelay:s}=h,c=()=>{const r=[];for(const t of e.getAllGroups())!t.collapsible||e.getConfigState(t.key)!=="collapsed"||r.push(`- ${t.key}\uFF1A${t.label}${t.summary?` \u2014\u2014 ${t.summary}`:""}`);return r.length===0?"":`
3
+
4
+ \u5F53\u524D\u53EF\u5C55\u5F00\u7684\u6536\u7EB3\u7EC4\uFF1A
5
+ `+r.join(`
6
+ `)};return{kind:"builtin",toolName:"expand_tools",exposedName:"expand_tools",description:'\u5C55\u5F00/\u6536\u8D77\u6536\u7EB3\u5DE5\u5177\u7EC4\u3002\u6536\u7EB3\u7EC4\u7684\u5DE5\u5177\u9ED8\u8BA4\u4E0D\u51FA\u73B0\u5728\u5DE5\u5177\u5217\u8868\u4E2D\uFF1B\u5C55\u5F00\u540E\u5DE5\u5177\u5B9A\u4E49\u968F\u672C\u5DE5\u5177\u7ED3\u679C\u8FD4\u56DE\uFF0C\u53EF\u7ECF call_tool \u8C03\u7528\u3002\u53C2\u6570\uFF1Agroup \u4E3A\u5177\u4F53\u7EC4 key\uFF08\u5982 pencil\u3001task\u3001mcp:my-server\uFF09\uFF0Caction \u4E3A "expand"\uFF08\u9ED8\u8BA4\uFF09\u6216 "collapse"\u3002\u4E0D\u652F\u6301\u6279\u91CF\u64CD\u4F5C\uFF1A\u6BCF\u6B21\u53EA\u80FD\u6307\u5B9A\u4E00\u4E2A\u7EC4\uFF0C\u591A\u7EC4\u9700\u5206\u6B21\u8C03\u7528\u3002',inputSchema:{type:"object",properties:{group:{type:"string",description:'\u7EC4 key\uFF08\u5982 pencil / task / mcp:my-server\uFF09\u3002\u5FC5\u987B\u6307\u5B9A\u5177\u4F53\u7EC4\uFF0C\u4E0D\u652F\u6301 "all" \u4E4B\u7C7B\u7684\u6279\u91CF\u53D6\u503C\u3002'},action:{type:"string",enum:["expand","collapse"],default:"expand",description:"expand=\u5C55\u5F00\uFF0Ccollapse=\u6536\u8D77"}},required:["group"],additionalProperties:!1},async execute(r){const t=String(r.group??"").trim(),a=String(r.action??"expand").trim();if(!t)return{ok:!1,error:"\u7F3A\u5C11 group \u53C2\u6570",hint:c()};if(a==="collapse"){const g=e.collapse(t);if(g<0)return{ok:!1,error:`\u672A\u77E5\u5DE5\u5177\u7EC4: ${t}`};if(s?.handlesGroup(t))try{await s.collapse(t)}catch{}return g===0?{ok:!0,status:"already-collapsed",group:t}:{ok:!0,status:"collapsed",group:t,hint:"\u5982\u9700\u91CD\u65B0\u4F7F\u7528\uFF0C\u8BF7\u518D\u6B21\u8C03\u7528 expand_tools\u3002"}}const d=e.getRegistration(t);if(!d){const g=c();return{ok:!1,error:`\u672A\u77E5\u5DE5\u5177\u7EC4: ${t}`,hint:g}}if(e.getConfigState(t)==="disabled")return{ok:!1,error:`\u80FD\u529B\u300C${d.label}\u300D\u672A\u5F00\u542F\uFF0C\u8BF7\u5728\u300C\u80FD\u529B\u914D\u7F6E\u300D\u4E2D\u5F00\u542F\u540E\u518D\u5C55\u5F00`};if(s?.handlesGroup(t)){let g;try{g=await s.expand(t)}catch(u){return{ok:!1,error:`\u5C55\u5F00\u300C${d.label}\u300D\u5931\u8D25: ${u instanceof Error?u.message:String(u)}`}}const n=e.expand(t);return{ok:!0,status:n===0?"already-expanded":"expanded",group:t,toolCount:g.length,tools:g,hint:n===0?"\u8BE5\u7EC4\u5DF2\u5728\u5C55\u5F00\u72B6\u6001\uFF0C\u53EF\u76F4\u63A5\u7ECF call_tool \u8C03\u7528\u3002":"\u5DE5\u5177\u5DF2\u5C55\u5F00\uFF0C\u4E0B\u4E00\u6761\u6D88\u606F\u5373\u53EF\u7ECF call_tool \u8C03\u7528\u3002"}}const i=e.expand(t);if(i<0)return{ok:!1,error:`\u672A\u77E5\u5DE5\u5177\u7EC4: ${t}`};const p=e.listToolManifests(t,o());return i===0?{ok:!0,status:"already-expanded",group:t,toolCount:p.length,tools:p,hint:"\u8BE5\u7EC4\u5DF2\u5728\u5C55\u5F00\u72B6\u6001\uFF0C\u53EF\u76F4\u63A5\u7ECF call_tool \u8C03\u7528\u3002"}:{ok:!0,status:"expanded",group:t,toolCount:p.length,tools:p,hint:"\u5DE5\u5177\u5DF2\u5C55\u5F00\uFF0C\u4E0B\u4E00\u6761\u6D88\u606F\u5373\u53EF\u7ECF call_tool \u8C03\u7528\u3002"}}}}function G(h){const{toolGroupManager:e,pluginBridge:o,findTool:s,dispatchTool:c,capabilityToolRelay:r}=h,t=(a,d)=>{if(r?.handlesTool(a))return!1;const f=d??e.getGroupForExposedName(a);return f&&!e.getRegistration(f)?!1:!f||!e.getRegistration(f).collapsible?!0:e.getConfigState(f)==="expanded"};return{kind:"builtin",toolName:"call_tool",exposedName:"call_tool",description:`\u4E2D\u8F6C\u8C03\u7528\u300C\u4E0D\u5728\u4F60\u7684\u5DE5\u5177\u5217\u8868\u4E2D\u300D\u7684\u5DE5\u5177\u3002\u4EC5\u6709\u4E24\u7C7B\u5DE5\u5177\u9700\u8981\u7ECF\u672C\u62A5\u6587\u53D1\u9001\uFF1A
7
+ 1) \u5DF2\u6536\u7EB3\u7684\u5DE5\u5177\u7EC4\uFF1A\u5148 expand_tools({ group }) \u5C55\u5F00\uFF0C\u518D\u7528 call_tool({ name: "<\u5DE5\u5177\u540D>", arguments: {...} }) \u8C03\u7528\uFF1B
8
+ 2) \u63D2\u4EF6\u5DE5\u5177\uFF1Aname \u4E3A"\u63D2\u4EF6\u540D.\u5DE5\u5177\u540D"\u9650\u5B9A\u540D\uFF08\u5982 "wechat-cli.send_msg"\uFF09\u3002
9
+
10
+ \u7981\u6B62\u7528\u9014\uFF08\u4F1A\u88AB\u62D2\u7EDD\uFF09\uFF1A\u5BF9\u5DE5\u5177\u5217\u8868\u4E2D**\u5DF2\u7ECF\u80FD\u76F4\u63A5\u8C03\u7528**\u7684\u5DE5\u5177\uFF08poll_message\u3001read_file\u3001browser_*\uFF08\u5C55\u5F00\u6001\u9664\u5916\uFF09\u7B49\uFF09\u8D70 call_tool\u3002\u76F4\u63A5\u8C03\u7528\u66F4\u7701\u4E00\u8F6E\u53C2\u6570\u6821\u9A8C\uFF0C\u4E14\u80FD\u4FDD\u6301\u5E76\u53D1/\u53EA\u8BFB\u8C03\u5EA6\u4E0E\u5DE5\u5177\u8C03\u7528\u7EDF\u8BA1\u7684\u51C6\u786E\u6027\u2014\u2014call_tool \u4E00\u5B9A\u662F\u72EC\u5360\u7684\uFF0C\u4F1A\u628A\u53EA\u8BFB\u5DE5\u5177\u964D\u7EA7\u4E3A\u4E32\u884C\u3002
11
+
12
+ \u63D2\u4EF6\u5DE5\u5177\u6A21\u5F0F\uFF08\u53EF\u9009\u63D2\u4EF6\uFF09\uFF1A
13
+ - action="catalog"\uFF1A\u8FD4\u56DE\u5F53\u524D\u5168\u90E8\u63D2\u4EF6\u76EE\u5F55\uFF08\u7D27\u51D1\uFF09
14
+ - action="schema" + tool="\u63D2\u4EF6\u540D.\u5DE5\u5177\u540D"\uFF1A\u8FD4\u56DE\u8BE5\u5DE5\u5177\u7684\u5B8C\u6574 inputSchema
15
+ - action="call"\uFF08\u9ED8\u8BA4\uFF09+ name="\u63D2\u4EF6\u540D.\u5DE5\u5177\u540D" + arguments={...}\uFF1A\u8C03\u7528\u63D2\u4EF6\u5DE5\u5177
16
+
17
+ \u8BF4\u660E\uFF1A\u53EA\u8C03\u5EA6\u5DF2\u5C55\u5F00\u7684\u6536\u7EB3\u7EC4\u5DE5\u5177\u4E0E\u63D2\u4EF6\u5DE5\u5177\uFF1B\u672A\u5C55\u5F00\u7684\u6536\u7EB3\u7EC4\u88AB\u62D2\u7EDD\u5E76\u5F15\u5BFC\u8C03\u7528 expand_tools\uFF1B\u5DF2\u76F4\u63A5\u53EF\u89C1\u7684\u5DE5\u5177\u88AB\u62D2\u7EDD\u5E76\u5F15\u5BFC\u76F4\u63A5\u8C03\u7528\u3002`,inputSchema:{type:"object",properties:{name:{type:"string",description:"\u5DE5\u5177\u540D\uFF08\u4EC5\u9650\u5DF2\u6536\u7EB3/\u5DF2\u5C55\u5F00\u7684\u5DE5\u5177\u7EC4\u5185\u5DE5\u5177\uFF0C\u5982 pencil_create_document\uFF09\uFF0C\u6216\u63D2\u4EF6\u9650\u5B9A\u540D\uFF08\u5982 wechat-cli.send_msg\uFF09"},arguments:{type:"object",description:"\u5DE5\u5177\u53C2\u6570\uFF08\u5BF9\u8C61\uFF0C\u53EF\u7701\u7565\uFF09"},action:{type:"string",enum:["call","catalog","schema"],default:"call",description:"call=\u8C03\u7528\u5DE5\u5177\uFF1Bcatalog=\u53D6\u63D2\u4EF6\u76EE\u5F55\uFF1Bschema=\u53D6\u63D2\u4EF6\u5DE5\u5177\u5B8C\u6574\u5B9A\u4E49"},tool:{type:"string",description:'action=schema \u65F6\u6307\u5B9A\u63D2\u4EF6\u5DE5\u5177\u9650\u5B9A\u540D\uFF08\u5982 "wechat-cli.send_msg"\uFF09\uFF1B\u4E5F\u652F\u6301 "\u63D2\u4EF6\u540D.*"'}},additionalProperties:!1},async execute(a,d){const f=String(a.action??"call").trim();if(f==="catalog"){if(!o)return{error:"\u63D2\u4EF6\u7CFB\u7EDF\u672A\u542F\u7528"};try{return await o.getCatalog()}catch(n){return{error:`\u63D2\u4EF6\u76EE\u5F55\u67E5\u8BE2\u5931\u8D25: ${n instanceof Error?n.message:String(n)}`}}}if(f==="schema"){if(!o)return{error:"\u63D2\u4EF6\u7CFB\u7EDF\u672A\u542F\u7528"};const n=String(a.tool??"").trim();if(!n)return{error:'\u7F3A\u5C11 tool \u53C2\u6570\uFF08\u9650\u5B9A\u540D "\u63D2\u4EF6\u540D.\u5DE5\u5177\u540D"\uFF09'};try{if(n.endsWith(".*")){const m=n.slice(0,-2),x=await o.getCatalog(),l=x.plugins.find(_=>_.plugin===m);if(!l)return{error:`\u63D2\u4EF6 ${m} \u672A\u5B89\u88C5\u6216\u5DF2\u505C\u7528`,catalog:x.plugins};const y=await Promise.all(l.tools.map(_=>o.getToolSchema(`${m}.${_.name}`)));return{plugin:m,schemas:y.filter(Boolean)}}const u=await o.getToolSchema(n);return u||{error:`\u672A\u77E5\u63D2\u4EF6\u5DE5\u5177: ${n}\uFF08\u53EF\u5148 action=catalog \u67E5\u770B\u76EE\u5F55\uFF09`}}catch(u){return{error:`\u63D2\u4EF6 schema \u67E5\u8BE2\u5931\u8D25: ${u instanceof Error?u.message:String(u)}`}}}const i=String(a.name??"").trim();if(!i)return{error:"\u7F3A\u5C11 name \u53C2\u6570\uFF08\u5DE5\u5177\u540D\u6216\u63D2\u4EF6\u9650\u5B9A\u540D\uFF09"};if(i.includes(".")){if(!o)return{error:"\u63D2\u4EF6\u7CFB\u7EDF\u672A\u542F\u7528"};const n=i.indexOf(".");if(n<=0||n>=i.length-1)return{error:`\u63D2\u4EF6\u9650\u5B9A\u540D\u4E0D\u5408\u6CD5: ${i}\uFF08\u5E94\u4E3A "\u63D2\u4EF6\u540D.\u5DE5\u5177\u540D"\uFF09`};const u=i.slice(0,n),m=i.slice(n+1);if(!m.trim())return{error:`\u63D2\u4EF6\u9650\u5B9A\u540D\u4E0D\u5408\u6CD5: ${i}\uFF08\u7F3A\u5C11\u5DE5\u5177\u540D\uFF09`};const x=a.arguments&&typeof a.arguments=="object"&&!Array.isArray(a.arguments)?a.arguments:{};try{const l=await o.invokeTool(u,m.trim(),x,{toolCallId:d?.toolCallId});if(l.ok)return l.result??{ok:!0};const y={error:l.error??"\u63D2\u4EF6\u5DE5\u5177\u8C03\u7528\u5931\u8D25"};return l.inputSchema!==void 0&&(y.inputSchema=l.inputSchema),typeof l.durationMs=="number"&&(y.durationMs=l.durationMs),y}catch(l){return{error:`\u63D2\u4EF6\u8C03\u7528\u5931\u8D25: ${l instanceof Error?l.message:String(l)}`}}}const p=s(i);if(!p){if(r?.handlesTool(i)){const n=e.getGroupForExposedName(i),u=n?e.getRegistration(n):void 0,m=n?e.getConfigState(n):"disabled";if(!n||!u||m==="disabled")return{error:`\u5DE5\u5177 ${i} \u6240\u5C5E\u7684\u80FD\u529B\u672A\u5F00\u542F\uFF0C\u8BF7\u544A\u77E5\u7528\u6237\u53BB\u300C\u80FD\u529B\u914D\u7F6E\u300D\u4E2D\u5F00\u542F`};if(!e.isExpanded(n))return{error:`\u5DE5\u5177\u96C6\u300C${u.label}\u300D\u5C1A\u672A\u5C55\u5F00\uFF0C\u8BF7\u5148\u8C03\u7528 expand_tools({ group: "${n}" }) \u5C55\u5F00\u540E\u518D\u8C03\u7528`,group:n};const x=a.arguments&&typeof a.arguments=="object"&&!Array.isArray(a.arguments)?a.arguments:{};try{const l=await r.call(i,x);return l.ok?l.result??{ok:!0}:{error:l.error??`\u8C03\u7528\u5DE5\u5177 ${i} \u5931\u8D25`}}catch(l){return{error:`\u8C03\u7528\u5DE5\u5177 ${i} \u5931\u8D25: ${l instanceof Error?l.message:String(l)}`}}}return{error:`\u672A\u77E5\u5DE5\u5177: ${i}\uFF08\u5DE5\u5177\u4E0D\u5728\u5F53\u524D\u4F1A\u8BDD\u7684\u5DE5\u5177\u5217\u8868\u4E2D\uFF09\u3002\u82E5\u5C5E\u4E8E\u5DF2\u5C55\u5F00\u7684\u6536\u7EB3\u7EC4\uFF0C\u68C0\u67E5\u5DE5\u5177\u540D\u662F\u5426\u6B63\u786E\u3002`}}if(t(i,p.group))return{error:`\u5DE5\u5177 ${i} \u672C\u5C31\u5728\u4F60\u7684\u5DE5\u5177\u5217\u8868\u4E2D\uFF0C\u53EF\u76F4\u63A5\u8C03\u7528\uFF0C\u65E0\u9700\u7ECF call_tool \u4E2D\u8F6C\u3002call_tool \u4EC5\u7528\u4E8E\uFF1A\u2460 expand_tools \u5C55\u5F00\u540E\u7684\u6536\u7EB3\u7EC4\u5DE5\u5177\uFF1B\u2461 \u63D2\u4EF6\u5DE5\u5177\uFF08"\u63D2\u4EF6\u540D.\u5DE5\u5177\u540D"\uFF09\u3002`};if(p.group){const n=e.getRegistration(p.group);if(n&&n.collapsible){const u=e.getConfigState(p.group);if(u==="disabled")return{error:`\u5DE5\u5177 ${i} \u6240\u5C5E\u7684\u80FD\u529B\u300C${n.label}\u300D\u672A\u5F00\u542F\uFF0C\u8BF7\u544A\u77E5\u7528\u6237\u53BB\u300C\u80FD\u529B\u914D\u7F6E\u300D\u4E2D\u5F00\u542F`};if(u==="collapsed"&&!e.isExpanded(p.group))return{error:`\u5DE5\u5177\u96C6\u300C${n.label}\u300D\u5C1A\u672A\u5C55\u5F00\uFF0C\u8BF7\u5148\u8C03\u7528 expand_tools({ group: "${p.group}" }) \u5C55\u5F00\u540E\u518D\u8C03\u7528`,group:p.group}}}const g=a.arguments&&typeof a.arguments=="object"&&!Array.isArray(a.arguments)?a.arguments:{};try{return await c(i,g,{toolCallId:d?.toolCallId})}catch(n){return{error:`\u8C03\u7528\u5DE5\u5177 ${i} \u5931\u8D25: ${n instanceof Error?n.message:String(n)}`}}}}}export{b as MCP_GROUP_KEY_PREFIX,N as ToolGroupManager,G as createCallToolTool,k as createExpandToolsTool,S as isMcpGroupKey,$ as mcpGroupKeyOf};
18
+
@@ -2,7 +2,7 @@ import type { SubAgentManager } from "./sub-agent-manager.js";
2
2
  import type { ACodeMcpConnection } from "./runtime.js";
3
3
  import type { TerminalManager } from "./terminal-types.js";
4
4
  import type { ACodePluginBridge } from "./plugin-types.js";
5
- import type { CapabilityState } from "./capability-prompt.js";
5
+ import type { CapabilityState } from "./tool-group-manager.js";
6
6
  export interface ACodeMcpServerSpec {
7
7
  type?: "stdio" | "sse" | "http";
8
8
  command?: string;
@@ -11,6 +11,10 @@ export interface ACodeMcpServerSpec {
11
11
  cwd?: string;
12
12
  url?: string;
13
13
  headers?: Record<string, string>;
14
+
15
+ collapsed?: boolean;
16
+
17
+ description?: string;
14
18
  [key: string]: unknown;
15
19
  }
16
20
  export interface ACodeConfigFile {
@@ -59,7 +63,7 @@ export interface ACodeSkillGroup {
59
63
  exists: boolean;
60
64
  skills: ACodeSkillMetadata[];
61
65
  }
62
- export type ACodeEventType = "session_started" | "startup_phase" | "ai_request" | "thinking_delta" | "assistant_delta" | "command_output" | "command_status" | "mcp_status" | "skill_status" | "warning" | "turn_complete" | "session_complete" | "context_compaction" | "question_request" | "tool_permission_request" | "error" | "background_command_completed";
66
+ export type ACodeEventType = "session_started" | "startup_phase" | "ai_request" | "iteration_usage" | "thinking_delta" | "assistant_delta" | "command_output" | "command_status" | "mcp_status" | "skill_status" | "warning" | "turn_complete" | "session_complete" | "context_compaction" | "question_request" | "tool_permission_request" | "error" | "background_command_completed";
63
67
  export interface ACodeEvent {
64
68
  type: ACodeEventType;
65
69
  sessionId: string;
@@ -119,6 +123,8 @@ export interface ACodeRuntimeConfig {
119
123
  rolePrompt?: string;
120
124
 
121
125
  memory?: string;
126
+
127
+ resumeContext?: string;
122
128
  env?: Record<string, string>;
123
129
  commandDirs?: string[];
124
130
  hooks?: ACodeHookHandler[];
@@ -142,6 +148,14 @@ export interface ACodeRuntimeConfig {
142
148
 
143
149
  toolPermissionPolicy?: import("./built-in-file-tools.js").ToolPermissionPolicy;
144
150
 
151
+ enableStaleFileGuard?: boolean;
152
+
153
+ toolConcurrency?: {
154
+ enabled?: boolean;
155
+ maxReadOnly?: number;
156
+ maxBash?: number;
157
+ };
158
+
145
159
  extraBuiltInTools?: import("./built-in-file-tools.js").ACodeBuiltInTool[];
146
160
 
147
161
  subAgentSuiteTools?: import("./built-in-file-tools.js").ACodeBuiltInTool[];
@@ -149,6 +163,10 @@ export interface ACodeRuntimeConfig {
149
163
  subAgentSuiteToolProvider?: (patterns: string[]) => Promise<import("./built-in-file-tools.js").ACodeBuiltInTool[]>;
150
164
 
151
165
  capabilityState?: (featureKey: string) => CapabilityState;
166
+
167
+ capabilityToolRelay?: import("./tool-group-manager.js").CapabilityToolRelay;
168
+
169
+ runtimeResourcesProvider?: () => Promise<string | null | undefined>;
152
170
  }
153
171
  export interface ACodeResolvedProviderConfig {
154
172
  model: string;
@@ -15,11 +15,11 @@
15
15
  "acode": "dist/cli.js"
16
16
  },
17
17
  "scripts": {
18
- "build": "tsc -p tsconfig.json && cpy grammars/** dist/grammars --parents --skip-exist && node ../../scripts/minify-dist.mjs",
19
- "build:force": "tsc -p tsconfig.json && cpy grammars/** dist/grammars --parents && node ../../scripts/minify-dist.mjs",
18
+ "build": "tsc -p tsconfig.json && cpy grammars/** dist/grammars --parents && node ../../scripts/minify-dist.mjs",
19
+ "build:incremental": "tsc -p tsconfig.json && cpy grammars/** dist/grammars --parents --skip-exist && node ../../scripts/minify-dist.mjs",
20
20
  "test": "vitest run",
21
21
  "test:watch": "vitest",
22
- "test:legacy": "tsx --test src/runtime.test.ts src/mcpToolNames.test.ts src/compaction.test.ts src/compaction-tree.test.ts",
22
+ "test:legacy": "tsx --test --test-force-exit src/runtime.test.ts src/mcpToolNames.test.ts src/compaction.test.ts src/compaction-tree.test.ts",
23
23
  "test:all": "npm run test:legacy && npm run test",
24
24
  "typecheck": "tsc -p tsconfig.json --noEmit"
25
25
  },
@@ -52,6 +52,7 @@ aws-client-agent-mcp
52
52
  | `AWS_HEARTBEAT_INTERVAL` | 心跳间隔(毫秒) | `3000` |
53
53
  | `AWS_HEARTBEAT_TIMEOUT` | 心跳超时时间(毫秒) | `9000` |
54
54
  | `AWS_MCP_HTTP_URL` | 调度中心 MCP HTTP 调用地址 | 根据 `AWS_SERVER_URL` 推导为 `/mcp/call` |
55
+ | `AWS_ATTACHMENT_MAX_SIZE_MB` | 附件单文件大小上限(MB)。服务端还会按流程线模板的按项上限(`maxSizeMb`,默认 200MB)二次校验 | `200` |
55
56
 
56
57
  > 注意:当前实现不再读取 `AWS_CONFIG_PATH`。作为 stdio MCP Server 运行时,stdout 必须只输出 JSON-RPC 消息,普通日志会输出到 stderr,避免污染 MCP 握手协议。
57
58
 
@@ -1,7 +1,7 @@
1
1
 
2
2
  import type { MemoryStats } from "./memory-store.js";
3
3
  import { StatusReporter } from "./status-reporter.js";
4
- import type { AgentConfig, BridgeToolManifest, BrowserListenerEvent, DirectMessage, DmHistoryResponse, FetchUnreadMessagesOptions, FinishTaskRollbackArgs, GroupHistoryResponse, GroupRoomsResponse, HireBatchResult, HireColleagueArgs, MessageHandler, OnlineListResponse, PluginCatalogSnapshot, ProfileInfo, RegisterResult, ServerConfig, SendDmResult, SendMessageResult, StartTaskRollbackArgs, TaskInstanceCommentArgs, UnreadMessagesResult } from "./types.js";
4
+ import type { AgentConfig, BrowserListenerEvent, Card, DirectMessage, DmHistoryResponse, FetchUnreadMessagesOptions, FinishTaskRollbackArgs, GroupHistoryResponse, GroupRoomsResponse, HireBatchResult, HireColleagueArgs, MessageHandler, OnlineListResponse, PluginCatalogSnapshot, ProfileInfo, ProjectMembersResponse, RegisterResult, ReplyToRef, ServerConfig, SendDmResult, SendMessageResult, StartTaskRollbackArgs, TaskInstanceCommentArgs, UnreadMessagesResult } from "./types.js";
5
5
  export type ProfileHandler = (profile: ProfileInfo) => void;
6
6
  export type AgentConfigHandler = (data: Record<string, unknown>) => void;
7
7
  export type SystemNotifyHandler = (data: Record<string, unknown>) => void;
@@ -52,30 +52,30 @@ export declare class AgentClient {
52
52
 
53
53
  discoverGroupRooms(): Promise<GroupRoomsResponse>;
54
54
 
55
+ listProjectMembers(): Promise<ProjectMembersResponse>;
56
+
55
57
  hireColleague(args: HireColleagueArgs): Promise<HireBatchResult>;
56
58
 
57
59
  callAgentScopedTool<T = unknown>(toolName: string, args: Record<string, unknown>): Promise<T>;
58
60
 
59
61
  reportMemoryStats(memoryStats: MemoryStats): Promise<void>;
60
62
 
61
- sendGroupMessage(content: string, projectId?: string, roomId?: string, card?: {
62
- type: "pencil" | "draw";
63
- docId: string;
64
- title?: string;
65
- description?: string;
66
- }): Promise<SendMessageResult>;
63
+ sendGroupMessage(content: string, projectId?: string, roomId?: string, card?: Card, replyTo?: ReplyToRef[]): Promise<SendMessageResult>;
67
64
 
68
- sendDirectMessage(targetId: string, content: string, waitReply?: boolean, replyToCallId?: string, timeoutMs?: number, card?: {
69
- type: "pencil" | "draw";
70
- docId: string;
71
- title?: string;
72
- description?: string;
73
- }): Promise<SendDmResult>;
65
+ sendDirectMessage(targetId: string, content: string, waitReply?: boolean, replyToCallId?: string, timeoutMs?: number, card?: Card, replyTo?: ReplyToRef[]): Promise<SendDmResult>;
74
66
 
75
67
  sendCallAndWaitReply(targetId: string, content: string, timeoutMs?: number): Promise<DirectMessage>;
76
68
 
77
69
  replyToCall(callId: string, targetId: string, content: string): Promise<SendDmResult>;
78
70
 
71
+ sendEmail(args: Record<string, unknown>): Promise<unknown>;
72
+
73
+ listEmails(args: Record<string, unknown>): Promise<unknown>;
74
+
75
+ readEmail(mailId: string): Promise<unknown>;
76
+
77
+ replyEmail(args: Record<string, unknown>): Promise<unknown>;
78
+
79
79
  getDmHistory(targetUserId?: string, limit?: number, since?: string): Promise<DmHistoryResponse>;
80
80
 
81
81
  getGroupHistory(limit?: number, roomId?: string, since?: string): Promise<GroupHistoryResponse>;
@@ -102,20 +102,6 @@ export declare class AgentClient {
102
102
 
103
103
  notifyBridgeForceMessage(): Promise<void>;
104
104
 
105
- setBridgeCapabilityTools(capability: string, action: "expand" | "collapse"): Promise<{
106
- ok: boolean;
107
- sessions?: number;
108
- tools?: number;
109
- manifests?: BridgeToolManifest[];
110
- error?: string;
111
- }>;
112
-
113
- callBridgeCapabilityTool(capability: string, toolName: string, args: unknown): Promise<{
114
- ok: boolean;
115
- result?: unknown;
116
- error?: string;
117
- }>;
118
-
119
105
  private fetchDirectMessagesWithRecovery;
120
106
 
121
107
  private isRecoverableLongPollError;
@@ -129,18 +115,20 @@ export declare class AgentClient {
129
115
 
130
116
  getMyTasks(): Promise<unknown[]>;
131
117
 
118
+ listTaskNodeIterations(args?: {
119
+ offset?: number;
120
+ limit?: number;
121
+ nodeTemplateId?: string;
122
+ }): Promise<unknown>;
123
+
132
124
  createTaskInstanceComment(args: TaskInstanceCommentArgs): Promise<unknown>;
133
125
 
134
- submitTaskResult(nodeId: string, outputPayload: string, changeLog?: unknown[]): Promise<unknown>;
126
+ submitTaskResult(nodeId: string, outputPayload: string, changeLog?: unknown[] | string, handoverNote?: string, deliverables?: unknown[]): Promise<unknown>;
135
127
 
136
128
  startTaskRollback(args: StartTaskRollbackArgs): Promise<unknown>;
137
129
 
138
130
  finishTaskRollback(args: FinishTaskRollbackArgs): Promise<unknown>;
139
131
 
140
- rejectTask(nodeId: string, reason: string): Promise<unknown>;
141
-
142
- terminateTask(taskInstanceId: string, reason: string): Promise<unknown>;
143
-
144
132
  getDebugLogConfig(): Promise<unknown>;
145
133
 
146
134
  queryDebugLogs(args: Record<string, unknown>): Promise<unknown>;
@@ -1,2 +1,2 @@
1
- import{configManager as h}from"./config.js";import{MESSAGE_POLL_INTERVAL_MS as I}from"./constants.js";import{HttpClient as f}from"./http-client.js";import{logger as s,setMcpNodeLogSink as w,updateStartupLogIdentity as u}from"./logger.js";import{claimRuntimeLaunchBindingDetailed as m}from"./runtime-launch-binding.js";import{StatusReporter as A}from"./status-reporter.js";import{WebSocketClient as p}from"./websocket-client.js";class T extends Error{constructor(e){super(e),this.name="PollLongPollTimeoutError"}}const C=27e4;class N{wsClient;httpClient;agentConfig;serverConfig;agentId=null;displayName=null;projectId=null;isRunning=!1;isDegradedMode=!1;messageHandler=null;profileHandler=null;configHandler=null;systemNotifyHandler=null;pollTimer=null;statusReporter=null;newCharacterHandler=null;runtimeTokenRefreshTimer=null;pendingLaunchBindingClaim=!1;cachedProfile=null;constructor(){h.loadConfig(),this.agentConfig=h.getAgentConfig(),this.serverConfig=h.getServerConfig(),this.wsClient=new p(this.serverConfig),this.httpClient=new f(this.serverConfig),this.setupWebSocketListeners()}async initialize(){const e=await m(this.agentConfig,this.serverConfig);if(e.status==="claimed"){this.applyLaunchBinding(e.binding);return}if(e.status==="unreachable"){this.pendingLaunchBindingClaim=!0,s.warn("[AgentClient] runtime-bridge \u672A\u5C31\u7EEA\uFF0C\u542F\u52A8\u7ED1\u5B9A\u8BA4\u9886\u5DF2\u6302\u8D77\uFF0C\u5C06\u5728\u6CE8\u518C\u91CD\u8BD5\u4E2D\u91CD\u65B0\u8BA4\u9886: %s",e.message);return}this.serverConfig.runtimeBridgeBaseUrl=void 0}applyLaunchBinding(e){h.applyRuntimeLaunchBinding(e),this.agentConfig=h.getAgentConfig(),this.serverConfig=h.getServerConfig(),this.wsClient=new p(this.serverConfig),this.httpClient=new f(this.serverConfig),this.setupWebSocketListeners()}async retryPendingLaunchBindingClaim(){if(!this.pendingLaunchBindingClaim)return!0;const e=await m(this.agentConfig,this.serverConfig);if(e.status==="claimed")return this.pendingLaunchBindingClaim=!1,s.info("[AgentClient] \u542F\u52A8\u7ED1\u5B9A\u8865\u8BA4\u9886\u6210\u529F\uFF0C\u7EE7\u7EED\u6CE8\u518C\u6D41\u7A0B"),this.applyLaunchBinding(e.binding),!0;if(e.status==="missing")return this.pendingLaunchBindingClaim=!1,this.serverConfig.runtimeBridgeBaseUrl=void 0,s.warn("[AgentClient] \u542F\u52A8\u7ED1\u5B9A\u8865\u8BA4\u9886\u672A\u627E\u5230\u5F85\u8BA4\u9886\u8BB0\u5F55\uFF0C\u6309\u65E0\u7ED1\u5B9A\u6A21\u5F0F\u7EE7\u7EED\u6CE8\u518C"),!1;const t=e.status==="unreachable"?e.message:e.reason;return s.warn("[AgentClient] \u542F\u52A8\u7ED1\u5B9A\u8865\u8BA4\u9886\u5931\u8D25\uFF0C\u4FDD\u7559\u6302\u8D77\u72B6\u6001\u7B49\u5F85\u4E0B\u6B21\u6CE8\u518C\u91CD\u8BD5: %s",t),!1}setupWebSocketListeners(){this.wsClient.on("directMessage",e=>{this.handleIncomingDm(e)}),this.wsClient.on("groupMessage",e=>{this.handleIncomingGroup(e)}),this.wsClient.on("meetingMessage",e=>{this.handleIncomingMeeting(e)}),this.wsClient.on("systemNotify",e=>{this.systemNotifyHandler?.(e)}),this.wsClient.on("profileInfo",e=>{s.info(`[AgentClient] WebSocket profileInfo \u4E8B\u4EF6\u89E6\u53D1\uFF0CdisplayName: ${e.displayName}`),this.handleProfileInfo(e)}),this.wsClient.on("agentConfig",e=>{s.info("[AgentClient] WebSocket agentConfig \u4E8B\u4EF6\u89E6\u53D1"),this.configHandler&&this.configHandler(e??{})}),this.wsClient.on("agentStatus",e=>{s.info(`[AgentClient] WebSocket agentStatus \u4E8B\u4EF6\u89E6\u53D1: ${e.status}`)}),this.wsClient.on("disconnected",(e,t)=>{const n=t?.toString()||"";s.warn("[AgentClient] WebSocket \u65AD\u5F00\u8FDE\u63A5: code=%s, reason=%s, agentId=%s, \u6B63\u5728\u81EA\u52A8\u91CD\u8FDE",e,n,this.agentId)}),this.wsClient.on("error",e=>{s.error("[AgentClient] WebSocket \u9519\u8BEF: %s, stack=%s",e.message,e.stack)}),this.wsClient.on("reconnectFailed",()=>{s.error("[AgentClient] \u91CD\u8FDE\u5931\u8D25\uFF08\u5DF2\u8FBE\u91CD\u8BD5\u4E0A\u9650\uFF09\uFF0C\u505C\u6B62\u6D88\u606F\u5FAA\u73AF, agentId=%s",this.agentId),this.stop()}),this.wsClient.on("tokenRejected",()=>{s.error("[AgentClient] runtime token \u88AB 1008 \u62D2\u7EDD\u4E14\u5237\u65B0\u65E0\u53D8\u5316\uFF0C\u8FDB\u5165\u6162\u901F\u91CD\u8BD5\u7B49\u5F85\u65B0 token \u7B7E\u53D1: agentId=%s",this.agentId)}),this.wsClient.on("tokenRefreshFailed",e=>{s.error("[AgentClient] runtime token \u5237\u65B0\u8FDE\u7EED\u5931\u8D25 %s \u6B21\uFF0C\u8FDB\u5165\u6162\u901F\u91CD\u8BD5\u7B49\u5F85 bridge \u6062\u590D: agentId=%s",e,this.agentId)})}async register(){return s.info("[AgentClient] \u6B63\u5728\u6CE8\u518C Agent..."),await this.retryPendingLaunchBindingClaim(),this.hasPresetAgentId()?await this.registerWithExistingAgentId():await this.registerAsNewAgent()}hasPresetAgentId(){return!!(this.agentConfig.agentId&&this.agentConfig.agentId.trim().length>0)}async registerWithExistingAgentId(){const e=this.agentConfig.agentId;if(!e)throw new Error("Preset agentId is missing");this.agentId=e.trim();let t;try{t=await this.getProfileByAgentId(this.agentId)}catch(r){throw s.error("[AgentClient] getProfileByAgentId \u5931\u8D25 (presetAgentId=%s): %s",this.agentId,r instanceof Error?r.message:String(r)),r}this.displayName=t.displayName,this.projectId=t.projectId||null,s.info(`[AgentClient] \u4F7F\u7528\u9884\u8BBE AgentID \u7ED1\u5B9A\u5B9E\u4F8B: ${this.displayName} (${this.agentId})`),s.info(`[AgentClient] \u6240\u5C5E\u9879\u76EE: ${this.projectId||"(\u672A\u8BBE\u7F6E)"}`);try{await this.wsClient.connect(this.agentId)}catch(r){throw s.error("[AgentClient] WebSocket \u8FDE\u63A5\u5931\u8D25 (agentId=%s): %s",this.agentId,r instanceof Error?r.message:String(r)),r}s.info("[AgentClient] WebSocket \u8FDE\u63A5\u5DF2\u5EFA\u7ACB\uFF0CAgent \u73B0\u5728\u5DF2\u4E0A\u7EBF"),this.initializeStatusReporter();const n=await this.getProfileByAgentId(this.agentId);return this.displayName=n.displayName,this.projectId=n.projectId||null,u(n.roleName||"unknown-role",n.instanceName||this.agentId),{agentId:this.agentId,displayName:this.displayName,status:n.isOnline?"online":"offline",projectId:n.projectId,workspacePath:n.workspacePath,runtimeStatus:n.runtimeStatus,runtimeSessionId:n.runtimeSessionId}}async registerAsNewAgent(){const e=await this.httpClient.callTool("register",{roleName:this.agentConfig.roleName,projectId:this.agentConfig.projectId,workspacePath:this.agentConfig.workspacePath,prompt:this.agentConfig.prompt,runtimeBridgeBaseUrl:this.serverConfig.runtimeBridgeBaseUrl}),t=e.agentId;if(!t)throw new Error("Registration failed: agentId was not returned");return this.agentId=t,this.displayName=e.displayName,this.projectId=e.projectId||null,u(this.agentConfig.roleName||"unknown-role",e.instanceName||t),s.info(`[AgentClient] \u6CE8\u518C\u6210\u529F: ${this.displayName} (${this.agentId})`),s.info(`[AgentClient] \u72B6\u6001: ${e.status}`),s.info(`[AgentClient] \u6240\u5C5E\u9879\u76EE: ${this.projectId||"(\u672A\u8BBE\u7F6E)"}`),await this.wsClient.connect(this.agentId),s.info("[AgentClient] WebSocket \u8FDE\u63A5\u5DF2\u5EFA\u7ACB\uFF0CAgent \u73B0\u5728\u5DF2\u4E0A\u7EBF"),this.initializeStatusReporter(),e.isExisting===!1&&this.newCharacterHandler&&this.newCharacterHandler(),e}async unregister(){s.info("[AgentClient] \u6B63\u5728\u6CE8\u9500 Agent..."),this.agentId&&await this.httpClient.callTool("unregister",{agentId:this.agentId}),this.stopRuntimeTokenRefresh(),this.wsClient.disconnect(),this.agentId=null,this.displayName=null,this.projectId=null,this.isRunning=!1,s.info("[AgentClient] \u5DF2\u6CE8\u9500")}async discoverColleagues(){return await this.httpClient.callTool("discover_colleague",{agentId:this.agentId})}async discoverGroupRooms(){return this.ensureRegistered(),await this.httpClient.callTool("discover_group_rooms",{agentId:this.agentId})}async hireColleague(e){return this.ensureRegistered(),await this.httpClient.callTool("hire_colleague",{...e,agentId:this.agentId})}async callAgentScopedTool(e,t){this.ensureRegistered();const n={...t,agentId:this.agentId};if(e==="create_meeting"){const r=typeof t.waitTimeoutMs=="number"?t.waitTimeoutMs:Number.NaN,i=Number.isFinite(r)&&r>0?Math.min(r,C):C;return await this.httpClient.callToolOnce(e,{...n,waitTimeoutMs:i},0)}return await this.httpClient.callTool(e,n)}async reportMemoryStats(e){await this.callAgentScopedTool("report_memory_stats",{memoryStats:e})}async sendGroupMessage(e,t,n,r){this.ensureRegistered();const i=t||this.projectId||this.agentConfig.projectId;return await this.httpClient.callTool("send_group_message",{agentId:this.agentId,projectId:i,roomId:n,content:e,card:r})}async sendDirectMessage(e,t,n=!1,r,i,a){this.ensureRegistered();const o={agentId:this.agentId,targetId:e,content:t,requireReply:n,waitReply:n,replyToCallId:r,card:a};if(typeof i=="number"&&i>0&&(o.timeoutMs=i),n){const g=typeof i=="number"&&i>0?i+3e4:0;return await this.httpClient.callToolOnce("send_dm",o,g)}return await this.httpClient.callTool("send_dm",o)}async sendCallAndWaitReply(e,t,n=6e4){const r=await this.sendDirectMessage(e,t,!0,void 0,n);if(r.reply)return r.reply;throw new Error("No reply received for call-style direct message before timeout")}async replyToCall(e,t,n){return await this.sendDirectMessage(t,n,!1,e)}async getDmHistory(e,t=50,n){this.ensureRegistered();const r={agentId:this.agentId,targetUserId:e,limit:t};return n&&(r.since=n),await this.httpClient.callTool("get_dm_history",r)}async getGroupHistory(e=50,t,n){if(this.ensureRegistered(),t){const l={projectId:this.projectId||this.agentConfig.projectId,roomId:t,limit:e};return n&&(l.since=n),await this.httpClient.callTool("get_group_history",l)}const r=await this.discoverGroupRooms(),i=this.projectId||this.agentConfig.projectId,a=this.collectRoomIds(r,i);if(a.length===0)return{messages:[],count:0};const g=(await Promise.all(a.map(async l=>{const c={projectId:i,roomId:l,limit:e};return n&&(c.since=n),await this.httpClient.callTool("get_group_history",c)}))).flatMap(l=>l.messages).sort((l,c)=>new Date(l.timestamp).getTime()-new Date(c.timestamp).getTime());return{messages:g,count:g.length}}async fetchUnreadMessages(e={}){this.ensureRegistered();const t=this.projectId||this.agentConfig.projectId,n={agentId:this.agentId,blockIfEmpty:e.blockIfEmpty??!1};e.since&&(n.since=e.since),e.blockTimeoutMs&&e.blockTimeoutMs>0&&(n.blockTimeoutMs=e.blockTimeoutMs),e.preemptiveJoinWaitMs!==void 0&&e.preemptiveJoinWaitMs!==null&&e.preemptiveJoinWaitMs>=0&&(n.preemptiveJoinWaitMs=e.preemptiveJoinWaitMs);const r=e.includePipelineTasks?"poll_message":"get_dm_messages";s.info("[AgentClient] fetchUnreadMessages \u5165\u53E3: tool=%s, blockIfEmpty=%s, blockTimeoutMs=%s, pollMessageTimeoutMs=%s, skipGroupMessages=%s, preemptiveJoinWaitMs=%s, agentId=%s",r,String(e.blockIfEmpty??!1),String(e.blockTimeoutMs??"-"),String(e.pollMessageTimeoutMs??"-"),String(e.skipGroupMessages??!1),String(e.preemptiveJoinWaitMs??"-"),this.agentId);const i=await this.fetchDirectMessagesWithRecovery(r,n,e.pollMessageTimeoutMs,e.propagatePollTimeout===!0);if(s.info("[AgentClient] fetchUnreadMessages \u79C1\u4FE1\u9636\u6BB5\u8FD4\u56DE: %s \u6761",Array.isArray(i.messages)?i.messages.length:0),e.skipGroupMessages)return s.info("[AgentClient] \u4F1A\u8BAE\u5FEB\u901F hydrate \u5DF2\u53D6\u5F97\u79C1\u4FE1\u54CD\u5E94\uFF0C\u8DF3\u8FC7\u7FA4\u804A\u53D1\u73B0\u5E76\u7ACB\u5373\u8FD4\u56DE: directMessages=%s",Array.isArray(i.messages)?i.messages.length:0),{directMessages:Array.isArray(i.messages)?i.messages:[],groupMessages:[]};let a;try{a=await this.discoverGroupRooms()}catch(l){s.warn("[AgentClient] \u53D1\u73B0\u7FA4\u623F\u95F4\u5931\u8D25\uFF0C\u672C\u6B21\u6309\u65E0\u7FA4\u6D88\u606F\u5904\u7406\uFF08\u5DF2\u53D6\u5230\u7684\u79C1\u4FE1\u4E0D\u53D7\u5F71\u54CD\uFF09: %s",l instanceof Error?l.message:String(l)),a={groups:[]}}const o=this.collectRoomIds(a,t),g=await Promise.all(o.map(async l=>{const c={agentId:this.agentId,projectId:t,roomId:l};e.since&&(c.since=e.since);try{return await this.httpClient.callTool("get_group_messages",c)}catch(d){return s.warn("[AgentClient] \u8DF3\u8FC7\u7FA4\u623F\u95F4\u672A\u8BFB\u8865\u62C9\u5931\u8D25: roomId=%s, error=%s",l,d instanceof Error?d.message:String(d)),{messages:[],currentReadPos:0,hasMore:!1}}}));return{directMessages:Array.isArray(i.messages)?i.messages:[],groupMessages:g.flatMap(l=>this.normalizeGroupMessages(l)).sort((l,c)=>new Date(l.timestamp).getTime()-new Date(c.timestamp).getTime())}}async markDmRead(e){if(e.length===0)return new Set;this.ensureRegistered();try{const t=await this.httpClient.callTool("mark_dm_read",{agentId:this.agentId,msgIds:e}),n=new Set(Array.isArray(t?.deliverableMsgIds)?t.deliverableMsgIds:[]),r=e.filter(i=>!n.has(i));return r.length>0?s.warn("[AgentClient] mark_dm_read \u786E\u8BA4\u540E\u5C06\u6709 %d \u6761\u6D88\u606F\u88AB\u4E22\u5F03\u4E0D\u4EA4\u4ED8: \u8BF7\u6C42=%s, \u53EF\u4EA4\u4ED8=%s, \u88AB\u4E22\u5F03=%s",r.length,JSON.stringify(e),JSON.stringify([...n]),JSON.stringify(r)):s.info("[AgentClient] mark_dm_read \u786E\u8BA4\u5B8C\u6210: %d \u6761\u5168\u90E8\u53EF\u4EA4\u4ED8",e.length),n}catch(t){throw s.warn("[AgentClient] mark_dm_read \u8BF7\u6C42\u5931\u8D25\uFF08\u5C06\u964D\u7EA7\u4E3A\u76F4\u63A5\u4EA4\u4ED8\uFF09: %s",t instanceof Error?t.message:String(t)),t}}async markGroupRead(e,t){if(t.length===0)return new Set;this.ensureRegistered();const n=await this.httpClient.callTool("mark_group_read",{agentId:this.agentId,roomId:e,msgIds:t});return new Set(Array.isArray(n?.deliverableMsgIds)?n.deliverableMsgIds:[])}async markNotificationRead(e){if(e.length!==0){this.ensureRegistered();try{await this.httpClient.callTool("mark_notification_read",{agentId:this.agentId,msgIds:e})}catch{}}}async markMeetingRead(e){if(e.length!==0){this.ensureRegistered();try{await this.httpClient.callTool("mark_meeting_read",{agentId:this.agentId,msgIds:e})}catch{}}}async fetchBrowserListenerEvents(){const e=this.serverConfig.runtimeBridgeBaseUrl,t=this.agentId;if(!e||!t)return s.info("[AgentClient] fetchBrowserListenerEvents \u8DF3\u8FC7: bridgeBaseUrl=%s, agentId=%s",e||"(\u7A7A)",t||"(\u7A7A)"),[];try{const n=`${e}/runtime/browser-listeners/${encodeURIComponent(t)}/events`,r=this.serverConfig.runtimeAccessToken||"";s.debug("[AgentClient] \u62C9\u53D6\u76D1\u542C\u5668\u4E8B\u4EF6: url=%s, tokenLen=%d",n,r.length);const i=await fetch(n,{method:"GET",headers:{"X-Runtime-Token":r},signal:AbortSignal.timeout(3e3)});if(!i.ok)return s.warn("[AgentClient] \u62C9\u53D6\u76D1\u542C\u5668\u4E8B\u4EF6\u5931\u8D25: HTTP %s, url=%s",i.status,n),[];const a=await i.json();return!a.ok||!Array.isArray(a.events)?(s.warn("[AgentClient] \u62C9\u53D6\u76D1\u542C\u5668\u4E8B\u4EF6\u54CD\u5E94\u5F02\u5E38: ok=%s, eventsType=%s",a.ok,Array.isArray(a.events)?"array":typeof a.events),[]):(s.debug("[AgentClient] \u62C9\u53D6\u76D1\u542C\u5668\u4E8B\u4EF6\u6210\u529F: %d \u6761\u4E8B\u4EF6",a.events.length),a.events)}catch(n){return s.warn("[AgentClient] \u62C9\u53D6\u76D1\u542C\u5668\u4E8B\u4EF6\u5F02\u5E38: %s",n instanceof Error?n.message:String(n)),[]}}async fetchPluginEvents(){const e=this.serverConfig.runtimeBridgeBaseUrl,t=this.agentId;if(!e||!t)return{revision:0,events:[],catalog:null,compactionSeq:0};try{const n=`${e}/runtime/plugin-events/${encodeURIComponent(t)}/events`,r=this.serverConfig.runtimeAccessToken||"",i=await fetch(n,{method:"GET",headers:{"X-Runtime-Token":r},signal:AbortSignal.timeout(3e3)});if(!i.ok)return s.warn("[AgentClient] \u62C9\u53D6\u63D2\u4EF6\u4E8B\u4EF6\u5931\u8D25: HTTP %s, url=%s",i.status,n),{revision:0,events:[],catalog:null,compactionSeq:0};const a=await i.json();return!a.ok||!Array.isArray(a.events)?(s.warn("[AgentClient] \u62C9\u53D6\u63D2\u4EF6\u4E8B\u4EF6\u54CD\u5E94\u5F02\u5E38: ok=%s",String(a.ok)),{revision:0,events:[],catalog:null,compactionSeq:0}):(s.debug("[AgentClient] \u62C9\u53D6\u63D2\u4EF6\u4E8B\u4EF6\u6210\u529F: %d \u6761\u4E8B\u4EF6, revision=%s, catalog=%s, compactionSeq=%s",a.events.length,String(a.revision??0),a.catalog?`${a.catalog.plugins.length} \u4E2A\u63D2\u4EF6`:"null",String(a.compactionSeq??0)),{revision:a.revision??0,events:a.events,catalog:a.catalog??null,compactionSeq:typeof a.compactionSeq=="number"&&Number.isFinite(a.compactionSeq)?a.compactionSeq:0})}catch(n){return s.warn("[AgentClient] \u62C9\u53D6\u63D2\u4EF6\u4E8B\u4EF6\u5F02\u5E38: %s",n instanceof Error?n.message:String(n)),{revision:0,events:[],catalog:null,compactionSeq:0}}}async notifyBridgeForceMessage(){const e=this.serverConfig.runtimeBridgeBaseUrl,t=this.agentId;if(!(!e||!t))try{const n=`${e}/runtime/sessions/${encodeURIComponent(t)}/notify-force-message`,r=this.serverConfig.runtimeAccessToken||"",i=await fetch(n,{method:"POST",headers:{"X-Runtime-Token":r},signal:AbortSignal.timeout(3e3)});i.ok||s.warn("[AgentClient] \u901A\u77E5 bridge \u5F3A\u5236\u6D88\u606F\u5931\u8D25: HTTP %s, url=%s",i.status,n)}catch(n){s.warn("[AgentClient] \u901A\u77E5 bridge \u5F3A\u5236\u6D88\u606F\u5F02\u5E38: %s",n instanceof Error?n.message:String(n))}}async setBridgeCapabilityTools(e,t){const n=this.serverConfig.runtimeBridgeBaseUrl,r=this.agentId;if(!n||!r)return{ok:!1,error:"\u7F3A\u5C11 bridge \u5730\u5740\u6216 agentId"};try{const i=`${n}/runtime/sessions/${encodeURIComponent(r)}/capability-tools`,a=await fetch(i,{method:"POST",headers:{"Content-Type":"application/json","X-Runtime-Token":this.serverConfig.runtimeAccessToken||""},body:JSON.stringify({capability:e,action:t}),signal:AbortSignal.timeout(5e3)}),o=await a.json().catch(()=>null);return!a.ok||o?.ok===!1?(s.warn("[AgentClient] \u56DE\u4F20\u80FD\u529B\u5DE5\u5177\u5207\u6362\u5931\u8D25: HTTP %s, url=%s",a.status,i),{ok:!1,error:o?.error||`HTTP ${a.status}`}):{ok:!0,sessions:o?.changed?.sessions??0,tools:o?.changed?.tools??0,manifests:Array.isArray(o?.manifests)?o.manifests:void 0}}catch(i){return s.warn("[AgentClient] \u56DE\u4F20\u80FD\u529B\u5DE5\u5177\u5207\u6362\u5F02\u5E38: %s",i instanceof Error?i.message:String(i)),{ok:!1,error:i instanceof Error?i.message:String(i)}}}async callBridgeCapabilityTool(e,t,n){const r=this.serverConfig.runtimeBridgeBaseUrl,i=this.agentId;if(!r||!i)return{ok:!1,error:"\u7F3A\u5C11 bridge \u5730\u5740\u6216 agentId"};try{const a=`${r}/runtime/sessions/${encodeURIComponent(i)}/capability-tools/call`,o=await fetch(a,{method:"POST",headers:{"Content-Type":"application/json","X-Runtime-Token":this.serverConfig.runtimeAccessToken||""},body:JSON.stringify({capability:e,tool:t,arguments:n??{}}),signal:AbortSignal.timeout(55e3)}),g=await o.json().catch(()=>null);return!o.ok||g?.ok===!1?(s.warn("[AgentClient] \u6865\u63A5\u80FD\u529B\u5DE5\u5177\u6267\u884C\u5931\u8D25: HTTP %s, url=%s, tool=%s",o.status,a,t),{ok:!1,error:g?.error||`HTTP ${o.status}`}):{ok:!0,result:g?.result}}catch(a){return s.warn("[AgentClient] \u6865\u63A5\u80FD\u529B\u5DE5\u5177\u6267\u884C\u5F02\u5E38: %s",a instanceof Error?a.message:String(a)),{ok:!1,error:a instanceof Error?a.message:String(a)}}}async fetchDirectMessagesWithRecovery(e,t,n,r=!1){if(e==="poll_message"){s.info("[AgentClient] fetchDirectMessagesWithRecovery \u5165\u53E3: tool=poll_message, pollMessageTimeoutMs=%s, agentId=%s",String(n??"(\u9ED8\u8BA4)"),String(t?.agentId??""));try{const i=await this.httpClient.callToolOnce(e,t,n);return s.info("[AgentClient] fetchDirectMessagesWithRecovery poll_message \u6210\u529F\u8FD4\u56DE: %s \u6761",Array.isArray(i?.messages)?i.messages.length:0),i}catch(i){if(this.isRecoverableLongPollError(i)){if(r)throw new T(i instanceof Error?i.message:String(i));return s.warn("[AgentClient] poll_message \u5355\u6B21\u957F\u8F6E\u8BE2\u8D85\u65F6\uFF0C\u6309\u7A7A\u7ED3\u679C\u9000\u907F\u540E\u7EE7\u7EED\u7B49\u5F85:",i),{messages:[]}}throw i}}return await this.httpClient.callTool(e,t)}isRecoverableLongPollError(e){return e instanceof Error?/MCP tool poll_message call failed: 503(?:\s|$)/.test(e.message)||/MCP tool poll_message timed out after \d+ms/.test(e.message):!1}normalizeGroupMessages(e){return Array.isArray(e.messages)?e.messages.filter(t=>!!(t&&typeof t=="object"&&typeof t.msgId=="number"&&typeof t.senderId=="string"&&typeof t.content=="string"&&typeof t.timestamp=="string")):[]}collectRoomIds(e,t){const n=e.groups.filter(r=>r.projectId===t).map(r=>r.id);return Array.from(new Set(n))}async getProfile(){this.ensureRegistered();const e=this.agentId;if(!e)throw new Error("Agent is not registered");return{...await this.getProfileByAgentId(e),describe:this.agentConfig.describe}}async getProfileByAgentId(e){return await this.httpClient.callTool("get_profile",{agentId:e})}async getMyTasks(){return this.ensureRegistered(),await this.httpClient.callTool("my_task",{agentId:this.agentId})}async createTaskInstanceComment(e){this.ensureRegistered();const t={agentId:this.agentId,...e};return await this.httpClient.callTool("create_task_instance_comment",t)}async submitTaskResult(e,t,n){this.ensureRegistered();const r={agentId:this.agentId,nodeId:e,outputPayload:t};return n&&Array.isArray(n)&&n.length>0&&(r.changeLog=n),await this.httpClient.callTool("submit_task_result",r)}async startTaskRollback(e){return this.ensureRegistered(),await this.httpClient.callTool("start_task_rollback",{agentId:this.agentId,...e})}async finishTaskRollback(e){return this.ensureRegistered(),await this.httpClient.callTool("finish_task_rollback",{agentId:this.agentId,...e})}async rejectTask(e,t){return this.ensureRegistered(),await this.httpClient.callTool("reject_task",{agentId:this.agentId,nodeId:e,reason:t})}async terminateTask(e,t){return this.ensureRegistered(),await this.httpClient.callTool("terminate_task",{agentId:this.agentId,taskInstanceId:e,reason:t})}async getDebugLogConfig(){return await this.httpClient.callTool("get_debug_log_config",{agentId:this.agentId})}async queryDebugLogs(e){return this.ensureRegistered(),await this.httpClient.callTool("query_debug_logs",{...e})}async queryFileChangesHistory(e){return this.ensureRegistered(),await this.httpClient.callTool("query_file_changes_history",{...e})}async getRuntimeFeatures(){return await this.httpClient.fetchRuntimeFeatures()}async listLaunchConfigs(){return this.ensureRegistered(),await this.httpClient.callTool("launch_config_list",{})}async createLaunchConfig(e){return this.ensureRegistered(),await this.httpClient.callTool("launch_config_create",{...e})}async updateLaunchConfig(e){return this.ensureRegistered(),await this.httpClient.callTool("launch_config_update",{...e})}async deleteLaunchConfig(e){return this.ensureRegistered(),await this.httpClient.callTool("launch_config_delete",{configId:e})}async startLaunchConfig(e){this.ensureRegistered();const t=Math.max(0,Math.min(3e5,Number(e.wait_timeout_ms)||0));return t>0?await this.httpClient.callToolOnce("launch_config_start",e,t+6e4):await this.httpClient.callTool("launch_config_start",{...e})}async restartLaunchConfig(e){this.ensureRegistered();const t=Math.max(0,Math.min(3e5,Number(e.wait_timeout_ms)||0));return t>0?await this.httpClient.callToolOnce("launch_config_restart",e,t+6e4):await this.httpClient.callTool("launch_config_restart",{...e})}async stopLaunchConfig(e){return this.ensureRegistered(),await this.httpClient.callTool("launch_config_stop",{configId:e})}async getLaunchLogs(e){return this.ensureRegistered(),await this.httpClient.callTool("launch_config_logs",{...e})}async listLaunchRuns(){return this.ensureRegistered(),await this.httpClient.callTool("launch_config_status",{})}start(e,t){if(this.isRunning){s.warn("[AgentClient] \u6D88\u606F\u5FAA\u73AF\u5DF2\u5728\u8FD0\u884C\u4E2D");return}this.isDegradedMode||this.ensureRegistered(),this.messageHandler=e,this.profileHandler=t?.profileHandler||null,this.configHandler=t?.configHandler||null,this.systemNotifyHandler=t?.systemNotifyHandler||null,this.isRunning=!0,s.info(`[AgentClient] start() \u88AB\u8C03\u7528\uFF0CcachedProfile: ${this.cachedProfile?"\u5B58\u5728":"\u4E0D\u5B58\u5728"}, profileHandler: ${this.profileHandler?"\u5DF2\u8BBE\u7F6E":"\u672A\u8BBE\u7F6E"}, \u964D\u7EA7\u6A21\u5F0F: ${this.isDegradedMode?"\u662F":"\u5426"}`),this.cachedProfile&&this.profileHandler&&(s.info(`[AgentClient] \u5904\u7406\u7F13\u5B58\u7684 Profile \u4FE1\u606F: ${this.cachedProfile.displayName}`),this.profileHandler(this.cachedProfile),this.cachedProfile=null),t?.pollMode??!1?(s.warn("[AgentClient] \u542F\u52A8\u6D88\u606F\u4E3B\u5FAA\u73AF\uFF08HTTP\u8F6E\u8BE2\u6A21\u5F0F - \u4E0D\u63A8\u8350\uFF09"),this.messageLoop()):s.info("[AgentClient] \u542F\u52A8\u6D88\u606F\u4E3B\u5FAA\u73AF\uFF08WebSocket\u63A8\u9001\u6A21\u5F0F - \u63A8\u8350\uFF09")}stop(){this.isRunning=!1,this.pollTimer&&(clearTimeout(this.pollTimer),this.pollTimer=null),this.stopRuntimeTokenRefresh(),s.info("[AgentClient] \u6D88\u606F\u4E3B\u5FAA\u73AF\u5DF2\u505C\u6B62")}async messageLoop(){for(;this.isRunning;)try{await this.delay(I)}catch(e){s.error("[AgentClient] \u6D88\u606F\u5FAA\u73AF\u9519\u8BEF:",e),await this.delay(5e3)}}handleIncomingDm(e){e.senderId!==this.agentId&&this.processMessage(e)}handleIncomingGroup(e){e.senderId!==this.agentId&&this.processMessage(e)}handleIncomingMeeting(e){!e||e.senderId===this.agentId||this.processMessage(e)}handleProfileInfo(e){s.info(`[AgentClient] \u6536\u5230 Profile \u4FE1\u606F: ${e.displayName} (${e.roleName})`),e.projectId&&(this.projectId=e.projectId,s.info(`[AgentClient] \u66F4\u65B0\u6240\u5C5E\u9879\u76EE: ${this.projectId}`)),e.roleName&&e.roleName!==this.agentConfig.roleName&&(s.info(`[AgentClient] \u540C\u6B65\u89D2\u8272\u540D: "${this.agentConfig.roleName||"(\u7A7A)"}" -> "${e.roleName}"`),this.agentConfig.roleName=e.roleName),e.roleName&&u(e.roleName,e.instanceName||this.agentId||""),this.profileHandler?this.profileHandler(e):(s.info("[AgentClient] profileHandler \u672A\u8BBE\u7F6E\uFF0C\u7F13\u5B58 Profile \u4FE1\u606F"),this.cachedProfile=e)}async processMessage(e){if(!this.messageHandler)return;const t=typeof e.msgId=="string";s.info(`[AgentClient] \u6536\u5230${t?"\u79C1\u4FE1":"\u7FA4\u6D88\u606F"}\u6765\u81EA ${e.senderName}: ${e.content.substring(0,50)}...`);try{const n=await this.messageHandler(e);if(t){const r=e;r.requireReply&&r.callId&&await this.replyToCall(r.callId,r.senderId,n||"\u5DF2\u6536\u5230\u6D88\u606F\uFF0C\u6B63\u5728\u5904\u7406\u4E2D...")}}catch(n){const r=typeof e.msgId=="string";if(s.error("[AgentClient] \u5904\u7406\u6D88\u606F\u5931\u8D25: type=%s, senderId=%s, senderName=%s, msgId=%s, error=%s",r?"\u79C1\u4FE1":"\u7FA4\u6D88\u606F",e.senderId,e.senderName,e.msgId,n instanceof Error?n.message:String(n)),r){const i=e;i.requireReply&&i.callId&&await this.replyToCall(i.callId,i.senderId,`\u5904\u7406\u5931\u8D25: ${n}`)}}}ensureRegistered(){if(!this.agentId)throw new Error("Agent is not registered")}delay(e){return new Promise(t=>{this.pollTimer=setTimeout(t,e)})}onNewCharacter(e){this.newCharacterHandler=e}getState(){return{agentId:this.agentId,displayName:this.displayName,projectId:this.projectId,isConnected:this.wsClient.isConnected(),isRunning:this.isRunning}}getAgentConfig(){return this.agentConfig}getServerConfig(){return this.serverConfig}reloadConfig(){h.loadConfig(),this.agentConfig=h.getAgentConfig(),s.info(`[AgentClient] \u914D\u7F6E\u5DF2\u91CD\u65B0\u52A0\u8F7D\uFF0C\u89D2\u8272: ${this.agentConfig.roleName}`)}enterDegradedMode(){this.isDegradedMode=!0,s.warn("[AgentClient] \u8FDB\u5165\u964D\u7EA7\u6A21\u5F0F\uFF0C\u5C06\u5728\u540E\u53F0\u6301\u7EED\u5C1D\u8BD5\u91CD\u8FDE")}exitDegradedMode(){this.isDegradedMode=!1,s.info("[AgentClient] \u9000\u51FA\u964D\u7EA7\u6A21\u5F0F")}isInDegradedMode(){return this.isDegradedMode}async retryRegistrationInBackground(e,t){let n=0;(async()=>{for(;this.isDegradedMode;)try{s.info(`[AgentClient] \u964D\u7EA7\u6A21\u5F0F\uFF1A\u5C1D\u8BD5\u91CD\u65B0\u6CE8\u518C (${n+1}/${t===-1?"\u65E0\u9650":t})`);const i=await this.register();s.info(`[AgentClient] \u964D\u7EA7\u6A21\u5F0F\uFF1A\u6CE8\u518C\u6210\u529F - ${i.displayName} (${i.agentId})`),this.exitDegradedMode(),this.messageHandler&&this.start(this.messageHandler);return}catch(i){n++;const a=i instanceof Error?i.message:String(i);if(s.warn(`[AgentClient] \u964D\u7EA7\u6A21\u5F0F\uFF1A\u6CE8\u518C\u5931\u8D25 (${n}/${t===-1?"\u65E0\u9650":t}): ${a}`),t>0&&n>=t){s.error("[AgentClient] \u964D\u7EA7\u6A21\u5F0F\uFF1A\u8FBE\u5230\u6700\u5927\u91CD\u8BD5\u6B21\u6570\uFF0C\u505C\u6B62\u91CD\u8FDE"),this.isDegradedMode=!1;return}await new Promise(o=>setTimeout(o,e))}})().catch(i=>{s.error("[AgentClient] \u964D\u7EA7\u6A21\u5F0F\u540E\u53F0\u91CD\u8BD5\u5FAA\u73AF\u5F02\u5E38\u9000\u51FA: error=%s, stack=%s",i instanceof Error?i.message:String(i),i instanceof Error?i.stack:"(no stack)")})}initializeStatusReporter(){if(!this.agentId){s.warn("[AgentClient] \u65E0\u6CD5\u521D\u59CB\u5316\u72B6\u6001\u62A5\u544A\u5668\uFF1AagentId \u4E3A\u7A7A");return}this.statusReporter=new A({agentId:this.agentId,sendStatusUpdate:e=>{this.wsClient.send({type:"AGENT_STATUS",data:e,timestamp:new Date().toISOString()})}}),w(e=>this.reportMcpNodeLog(e)),this.startRuntimeTokenRefresh(),s.info("[AgentClient] \u72B6\u6001\u62A5\u544A\u5668\u5DF2\u521D\u59CB\u5316")}startRuntimeTokenRefresh(){this.stopRuntimeTokenRefresh();const e=this.serverConfig.runtimeTokenRefreshIntervalMs;if(!e||e<=0){s.warn("[AgentClient] runtimeTokenRefreshIntervalMs \u672A\u914D\u7F6E\u6216\u65E0\u6548\uFF0C\u8DF3\u8FC7\u4E3B\u52A8\u7EED\u671F");return}const t=this.agentId;if(!t){s.warn("[AgentClient] agentId \u4E3A\u7A7A\uFF0C\u8DF3\u8FC7\u4E3B\u52A8\u7EED\u671F");return}this.runtimeTokenRefreshTimer=setInterval(async()=>{try{await this.httpClient.refreshRuntimeAccessToken(t)&&s.info("[AgentClient] runtimeAccessToken \u5DF2\u4E3B\u52A8\u7EED\u671F")}catch(n){s.warn("[AgentClient] \u4E3B\u52A8\u7EED\u671F runtimeAccessToken \u5931\u8D25: %s",n instanceof Error?n.message:String(n)),n instanceof Error&&n.stack&&s.warn("[AgentClient] \u4E3B\u52A8\u7EED\u671F\u5F02\u5E38\u5806\u6808:",n.stack)}},e),this.runtimeTokenRefreshTimer.unref?.(),s.info(`[AgentClient] runtime token \u4E3B\u52A8\u7EED\u671F\u5DF2\u542F\u52A8\uFF0C\u95F4\u9694 ${e}ms`)}stopRuntimeTokenRefresh(){this.runtimeTokenRefreshTimer&&(clearInterval(this.runtimeTokenRefreshTimer),this.runtimeTokenRefreshTimer=null)}reportMcpNodeLog(e){const t=this.wsClient;!this.agentId||!this.wsClient.isConnected()||typeof t.sendMcpNodeLog!="function"||t.sendMcpNodeLog(e)}getStatusReporter(){return this.statusReporter}}export{N as AgentClient,T as PollLongPollTimeoutError};
1
+ import{configManager as c}from"./config.js";import{MESSAGE_POLL_INTERVAL_MS as I}from"./constants.js";import{HttpClient as f}from"./http-client.js";import{logger as i,setMcpNodeLogSink as w,updateStartupLogIdentity as u}from"./logger.js";import{claimRuntimeLaunchBindingDetailed as m}from"./runtime-launch-binding.js";import{StatusReporter as A}from"./status-reporter.js";import{WebSocketClient as p}from"./websocket-client.js";class T extends Error{constructor(e){super(e),this.name="PollLongPollTimeoutError"}}const C=27e4;class N{wsClient;httpClient;agentConfig;serverConfig;agentId=null;displayName=null;projectId=null;isRunning=!1;isDegradedMode=!1;messageHandler=null;profileHandler=null;configHandler=null;systemNotifyHandler=null;pollTimer=null;statusReporter=null;newCharacterHandler=null;runtimeTokenRefreshTimer=null;pendingLaunchBindingClaim=!1;cachedProfile=null;constructor(){c.loadConfig(),this.agentConfig=c.getAgentConfig(),this.serverConfig=c.getServerConfig(),this.wsClient=new p(this.serverConfig),this.httpClient=new f(this.serverConfig),this.setupWebSocketListeners()}async initialize(){const e=await m(this.agentConfig,this.serverConfig);if(e.status==="claimed"){this.applyLaunchBinding(e.binding);return}if(e.status==="unreachable"){this.pendingLaunchBindingClaim=!0,i.warn("[AgentClient] runtime-bridge \u672A\u5C31\u7EEA\uFF0C\u542F\u52A8\u7ED1\u5B9A\u8BA4\u9886\u5DF2\u6302\u8D77\uFF0C\u5C06\u5728\u6CE8\u518C\u91CD\u8BD5\u4E2D\u91CD\u65B0\u8BA4\u9886: %s",e.message);return}this.serverConfig.runtimeBridgeBaseUrl=void 0}applyLaunchBinding(e){c.applyRuntimeLaunchBinding(e),this.agentConfig=c.getAgentConfig(),this.serverConfig=c.getServerConfig(),this.wsClient=new p(this.serverConfig),this.httpClient=new f(this.serverConfig),this.setupWebSocketListeners()}async retryPendingLaunchBindingClaim(){if(!this.pendingLaunchBindingClaim)return!0;const e=await m(this.agentConfig,this.serverConfig);if(e.status==="claimed")return this.pendingLaunchBindingClaim=!1,i.info("[AgentClient] \u542F\u52A8\u7ED1\u5B9A\u8865\u8BA4\u9886\u6210\u529F\uFF0C\u7EE7\u7EED\u6CE8\u518C\u6D41\u7A0B"),this.applyLaunchBinding(e.binding),!0;if(e.status==="missing")return this.pendingLaunchBindingClaim=!1,this.serverConfig.runtimeBridgeBaseUrl=void 0,i.warn("[AgentClient] \u542F\u52A8\u7ED1\u5B9A\u8865\u8BA4\u9886\u672A\u627E\u5230\u5F85\u8BA4\u9886\u8BB0\u5F55\uFF0C\u6309\u65E0\u7ED1\u5B9A\u6A21\u5F0F\u7EE7\u7EED\u6CE8\u518C"),!1;const t=e.status==="unreachable"?e.message:e.reason;return i.warn("[AgentClient] \u542F\u52A8\u7ED1\u5B9A\u8865\u8BA4\u9886\u5931\u8D25\uFF0C\u4FDD\u7559\u6302\u8D77\u72B6\u6001\u7B49\u5F85\u4E0B\u6B21\u6CE8\u518C\u91CD\u8BD5: %s",t),!1}setupWebSocketListeners(){this.wsClient.on("directMessage",e=>{this.handleIncomingDm(e)}),this.wsClient.on("groupMessage",e=>{this.handleIncomingGroup(e)}),this.wsClient.on("meetingMessage",e=>{this.handleIncomingMeeting(e)}),this.wsClient.on("systemNotify",e=>{this.systemNotifyHandler?.(e)}),this.wsClient.on("profileInfo",e=>{i.info(`[AgentClient] WebSocket profileInfo \u4E8B\u4EF6\u89E6\u53D1\uFF0CdisplayName: ${e.displayName}`),this.handleProfileInfo(e)}),this.wsClient.on("agentConfig",e=>{i.info("[AgentClient] WebSocket agentConfig \u4E8B\u4EF6\u89E6\u53D1"),this.configHandler&&this.configHandler(e??{})}),this.wsClient.on("agentStatus",e=>{i.info(`[AgentClient] WebSocket agentStatus \u4E8B\u4EF6\u89E6\u53D1: ${e.status}`)}),this.wsClient.on("disconnected",(e,t)=>{const n=t?.toString()||"";i.warn("[AgentClient] WebSocket \u65AD\u5F00\u8FDE\u63A5: code=%s, reason=%s, agentId=%s, \u6B63\u5728\u81EA\u52A8\u91CD\u8FDE",e,n,this.agentId)}),this.wsClient.on("error",e=>{i.error("[AgentClient] WebSocket \u9519\u8BEF: %s, stack=%s",e.message,e.stack)}),this.wsClient.on("reconnectFailed",()=>{i.error("[AgentClient] \u91CD\u8FDE\u5931\u8D25\uFF08\u5DF2\u8FBE\u91CD\u8BD5\u4E0A\u9650\uFF09\uFF0C\u505C\u6B62\u6D88\u606F\u5FAA\u73AF, agentId=%s",this.agentId),this.stop()}),this.wsClient.on("tokenRejected",()=>{i.error("[AgentClient] runtime token \u88AB 1008 \u62D2\u7EDD\u4E14\u5237\u65B0\u65E0\u53D8\u5316\uFF0C\u8FDB\u5165\u6162\u901F\u91CD\u8BD5\u7B49\u5F85\u65B0 token \u7B7E\u53D1: agentId=%s",this.agentId)}),this.wsClient.on("tokenRefreshFailed",e=>{i.error("[AgentClient] runtime token \u5237\u65B0\u8FDE\u7EED\u5931\u8D25 %s \u6B21\uFF0C\u8FDB\u5165\u6162\u901F\u91CD\u8BD5\u7B49\u5F85 bridge \u6062\u590D: agentId=%s",e,this.agentId)})}async register(){return i.info("[AgentClient] \u6B63\u5728\u6CE8\u518C Agent..."),await this.retryPendingLaunchBindingClaim(),this.hasPresetAgentId()?await this.registerWithExistingAgentId():await this.registerAsNewAgent()}hasPresetAgentId(){return!!(this.agentConfig.agentId&&this.agentConfig.agentId.trim().length>0)}async registerWithExistingAgentId(){const e=this.agentConfig.agentId;if(!e)throw new Error("Preset agentId is missing");this.agentId=e.trim();let t;try{t=await this.getProfileByAgentId(this.agentId)}catch(r){throw i.error("[AgentClient] getProfileByAgentId \u5931\u8D25 (presetAgentId=%s): %s",this.agentId,r instanceof Error?r.message:String(r)),r}this.displayName=t.displayName,this.projectId=t.projectId||null,i.info(`[AgentClient] \u4F7F\u7528\u9884\u8BBE AgentID \u7ED1\u5B9A\u5B9E\u4F8B: ${this.displayName} (${this.agentId})`),i.info(`[AgentClient] \u6240\u5C5E\u9879\u76EE: ${this.projectId||"(\u672A\u8BBE\u7F6E)"}`);try{await this.wsClient.connect(this.agentId)}catch(r){throw i.error("[AgentClient] WebSocket \u8FDE\u63A5\u5931\u8D25 (agentId=%s): %s",this.agentId,r instanceof Error?r.message:String(r)),r}i.info("[AgentClient] WebSocket \u8FDE\u63A5\u5DF2\u5EFA\u7ACB\uFF0CAgent \u73B0\u5728\u5DF2\u4E0A\u7EBF"),this.initializeStatusReporter();const n=await this.getProfileByAgentId(this.agentId);return this.displayName=n.displayName,this.projectId=n.projectId||null,u(n.roleName||"unknown-role",n.instanceName||this.agentId),{agentId:this.agentId,displayName:this.displayName,status:n.isOnline?"online":"offline",projectId:n.projectId,workspacePath:n.workspacePath,runtimeStatus:n.runtimeStatus,runtimeSessionId:n.runtimeSessionId}}async registerAsNewAgent(){const e=await this.httpClient.callTool("register",{roleName:this.agentConfig.roleName,projectId:this.agentConfig.projectId,workspacePath:this.agentConfig.workspacePath,prompt:this.agentConfig.prompt,runtimeBridgeBaseUrl:this.serverConfig.runtimeBridgeBaseUrl}),t=e.agentId;if(!t)throw new Error("Registration failed: agentId was not returned");return this.agentId=t,this.displayName=e.displayName,this.projectId=e.projectId||null,u(this.agentConfig.roleName||"unknown-role",e.instanceName||t),i.info(`[AgentClient] \u6CE8\u518C\u6210\u529F: ${this.displayName} (${this.agentId})`),i.info(`[AgentClient] \u72B6\u6001: ${e.status}`),i.info(`[AgentClient] \u6240\u5C5E\u9879\u76EE: ${this.projectId||"(\u672A\u8BBE\u7F6E)"}`),await this.wsClient.connect(this.agentId),i.info("[AgentClient] WebSocket \u8FDE\u63A5\u5DF2\u5EFA\u7ACB\uFF0CAgent \u73B0\u5728\u5DF2\u4E0A\u7EBF"),this.initializeStatusReporter(),e.isExisting===!1&&this.newCharacterHandler&&this.newCharacterHandler(),e}async unregister(){i.info("[AgentClient] \u6B63\u5728\u6CE8\u9500 Agent..."),this.agentId&&await this.httpClient.callTool("unregister",{agentId:this.agentId}),this.stopRuntimeTokenRefresh(),this.wsClient.disconnect(),this.agentId=null,this.displayName=null,this.projectId=null,this.isRunning=!1,i.info("[AgentClient] \u5DF2\u6CE8\u9500")}async discoverColleagues(){return await this.httpClient.callTool("discover_colleague",{agentId:this.agentId})}async discoverGroupRooms(){return this.ensureRegistered(),await this.httpClient.callTool("discover_group_rooms",{agentId:this.agentId})}async listProjectMembers(){return this.ensureRegistered(),await this.httpClient.callTool("list_project_members",{agentId:this.agentId})}async hireColleague(e){return this.ensureRegistered(),await this.httpClient.callTool("hire_colleague",{...e,agentId:this.agentId})}async callAgentScopedTool(e,t){this.ensureRegistered();const n={...t,agentId:this.agentId};if(e==="create_meeting"){const r=typeof t.waitTimeoutMs=="number"?t.waitTimeoutMs:Number.NaN,s=Number.isFinite(r)&&r>0?Math.min(r,C):C;return await this.httpClient.callToolOnce(e,{...n,waitTimeoutMs:s},0)}return await this.httpClient.callTool(e,n)}async reportMemoryStats(e){await this.callAgentScopedTool("report_memory_stats",{memoryStats:e})}async sendGroupMessage(e,t,n,r,s){this.ensureRegistered();const a=t||this.projectId||this.agentConfig.projectId;return await this.httpClient.callTool("send_group_message",{agentId:this.agentId,projectId:a,roomId:n,content:e,card:r,replyTo:s})}async sendDirectMessage(e,t,n=!1,r,s,a,h){this.ensureRegistered();const g={agentId:this.agentId,targetId:e,content:t,requireReply:n,waitReply:n,replyToCallId:r,card:a,replyTo:h};if(typeof s=="number"&&s>0&&(g.timeoutMs=s),n){const o=typeof s=="number"&&s>0?s+3e4:0;return await this.httpClient.callToolOnce("send_dm",g,o)}return await this.httpClient.callTool("send_dm",g)}async sendCallAndWaitReply(e,t,n=6e4){const r=await this.sendDirectMessage(e,t,!0,void 0,n);if(r.reply)return r.reply;throw new Error("No reply received for call-style direct message before timeout")}async replyToCall(e,t,n){return await this.sendDirectMessage(t,n,!1,e)}async sendEmail(e){return await this.callAgentScopedTool("send_email",e)}async listEmails(e){return await this.callAgentScopedTool("list_emails",e)}async readEmail(e){return await this.callAgentScopedTool("read_email",{mailId:e})}async replyEmail(e){return await this.callAgentScopedTool("reply_email",e)}async getDmHistory(e,t=50,n){this.ensureRegistered();const r={agentId:this.agentId,targetUserId:e,limit:t};return n&&(r.since=n),await this.httpClient.callTool("get_dm_history",r)}async getGroupHistory(e=50,t,n){if(this.ensureRegistered(),t){const o={projectId:this.projectId||this.agentConfig.projectId,roomId:t,limit:e};return n&&(o.since=n),await this.httpClient.callTool("get_group_history",o)}const r=await this.discoverGroupRooms(),s=this.projectId||this.agentConfig.projectId,a=this.collectRoomIds(r,s);if(a.length===0)return{messages:[],count:0};const g=(await Promise.all(a.map(async o=>{const l={projectId:s,roomId:o,limit:e};return n&&(l.since=n),await this.httpClient.callTool("get_group_history",l)}))).flatMap(o=>o.messages).sort((o,l)=>new Date(o.timestamp).getTime()-new Date(l.timestamp).getTime());return{messages:g,count:g.length}}async fetchUnreadMessages(e={}){this.ensureRegistered();const t=this.projectId||this.agentConfig.projectId,n={agentId:this.agentId,blockIfEmpty:e.blockIfEmpty??!1};e.since&&(n.since=e.since),e.blockTimeoutMs&&e.blockTimeoutMs>0&&(n.blockTimeoutMs=e.blockTimeoutMs),e.preemptiveJoinWaitMs!==void 0&&e.preemptiveJoinWaitMs!==null&&e.preemptiveJoinWaitMs>=0&&(n.preemptiveJoinWaitMs=e.preemptiveJoinWaitMs);const r=e.includePipelineTasks?"poll_message":"get_dm_messages";i.info("[AgentClient] fetchUnreadMessages \u5165\u53E3: tool=%s, blockIfEmpty=%s, blockTimeoutMs=%s, pollMessageTimeoutMs=%s, skipGroupMessages=%s, preemptiveJoinWaitMs=%s, agentId=%s",r,String(e.blockIfEmpty??!1),String(e.blockTimeoutMs??"-"),String(e.pollMessageTimeoutMs??"-"),String(e.skipGroupMessages??!1),String(e.preemptiveJoinWaitMs??"-"),this.agentId);const s=await this.fetchDirectMessagesWithRecovery(r,n,e.pollMessageTimeoutMs,e.propagatePollTimeout===!0);if(i.info("[AgentClient] fetchUnreadMessages \u79C1\u4FE1\u9636\u6BB5\u8FD4\u56DE: %s \u6761",Array.isArray(s.messages)?s.messages.length:0),e.skipGroupMessages)return i.info("[AgentClient] \u4F1A\u8BAE\u5FEB\u901F hydrate \u5DF2\u53D6\u5F97\u79C1\u4FE1\u54CD\u5E94\uFF0C\u8DF3\u8FC7\u7FA4\u804A\u53D1\u73B0\u5E76\u7ACB\u5373\u8FD4\u56DE: directMessages=%s",Array.isArray(s.messages)?s.messages.length:0),{directMessages:Array.isArray(s.messages)?s.messages:[],groupMessages:[]};let a;try{a=await this.discoverGroupRooms()}catch(o){i.warn("[AgentClient] \u53D1\u73B0\u7FA4\u623F\u95F4\u5931\u8D25\uFF0C\u672C\u6B21\u6309\u65E0\u7FA4\u6D88\u606F\u5904\u7406\uFF08\u5DF2\u53D6\u5230\u7684\u79C1\u4FE1\u4E0D\u53D7\u5F71\u54CD\uFF09: %s",o instanceof Error?o.message:String(o)),a={groups:[]}}const h=this.collectRoomIds(a,t),g=await Promise.all(h.map(async o=>{const l={agentId:this.agentId,projectId:t,roomId:o};e.since&&(l.since=e.since);try{return await this.httpClient.callTool("get_group_messages",l)}catch(d){return i.warn("[AgentClient] \u8DF3\u8FC7\u7FA4\u623F\u95F4\u672A\u8BFB\u8865\u62C9\u5931\u8D25: roomId=%s, error=%s",o,d instanceof Error?d.message:String(d)),{messages:[],currentReadPos:0,hasMore:!1}}}));return{directMessages:Array.isArray(s.messages)?s.messages:[],groupMessages:g.flatMap(o=>this.normalizeGroupMessages(o)).sort((o,l)=>new Date(o.timestamp).getTime()-new Date(l.timestamp).getTime())}}async markDmRead(e){if(e.length===0)return new Set;this.ensureRegistered();try{const t=await this.httpClient.callTool("mark_dm_read",{agentId:this.agentId,msgIds:e}),n=new Set(Array.isArray(t?.deliverableMsgIds)?t.deliverableMsgIds:[]),r=e.filter(s=>!n.has(s));return r.length>0?i.warn("[AgentClient] mark_dm_read \u786E\u8BA4\u540E\u5C06\u6709 %d \u6761\u6D88\u606F\u88AB\u4E22\u5F03\u4E0D\u4EA4\u4ED8: \u8BF7\u6C42=%s, \u53EF\u4EA4\u4ED8=%s, \u88AB\u4E22\u5F03=%s",r.length,JSON.stringify(e),JSON.stringify([...n]),JSON.stringify(r)):i.info("[AgentClient] mark_dm_read \u786E\u8BA4\u5B8C\u6210: %d \u6761\u5168\u90E8\u53EF\u4EA4\u4ED8",e.length),n}catch(t){throw i.warn("[AgentClient] mark_dm_read \u8BF7\u6C42\u5931\u8D25\uFF08\u5C06\u964D\u7EA7\u4E3A\u76F4\u63A5\u4EA4\u4ED8\uFF09: %s",t instanceof Error?t.message:String(t)),t}}async markGroupRead(e,t){if(t.length===0)return new Set;this.ensureRegistered();const n=await this.httpClient.callTool("mark_group_read",{agentId:this.agentId,roomId:e,msgIds:t});return new Set(Array.isArray(n?.deliverableMsgIds)?n.deliverableMsgIds:[])}async markNotificationRead(e){if(e.length!==0){this.ensureRegistered();try{await this.httpClient.callTool("mark_notification_read",{agentId:this.agentId,msgIds:e})}catch{}}}async markMeetingRead(e){if(e.length!==0){this.ensureRegistered();try{await this.httpClient.callTool("mark_meeting_read",{agentId:this.agentId,msgIds:e})}catch{}}}async fetchBrowserListenerEvents(){const e=this.serverConfig.runtimeBridgeBaseUrl,t=this.agentId;if(!e||!t)return i.info("[AgentClient] fetchBrowserListenerEvents \u8DF3\u8FC7: bridgeBaseUrl=%s, agentId=%s",e||"(\u7A7A)",t||"(\u7A7A)"),[];try{const n=`${e}/runtime/browser-listeners/${encodeURIComponent(t)}/events`,r=this.serverConfig.runtimeAccessToken||"";i.debug("[AgentClient] \u62C9\u53D6\u76D1\u542C\u5668\u4E8B\u4EF6: url=%s, tokenLen=%d",n,r.length);const s=await fetch(n,{method:"GET",headers:{"X-Runtime-Token":r},signal:AbortSignal.timeout(3e3)});if(!s.ok)return i.warn("[AgentClient] \u62C9\u53D6\u76D1\u542C\u5668\u4E8B\u4EF6\u5931\u8D25: HTTP %s, url=%s",s.status,n),[];const a=await s.json();return!a.ok||!Array.isArray(a.events)?(i.warn("[AgentClient] \u62C9\u53D6\u76D1\u542C\u5668\u4E8B\u4EF6\u54CD\u5E94\u5F02\u5E38: ok=%s, eventsType=%s",a.ok,Array.isArray(a.events)?"array":typeof a.events),[]):(i.debug("[AgentClient] \u62C9\u53D6\u76D1\u542C\u5668\u4E8B\u4EF6\u6210\u529F: %d \u6761\u4E8B\u4EF6",a.events.length),a.events)}catch(n){return i.warn("[AgentClient] \u62C9\u53D6\u76D1\u542C\u5668\u4E8B\u4EF6\u5F02\u5E38: %s",n instanceof Error?n.message:String(n)),[]}}async fetchPluginEvents(){const e=this.serverConfig.runtimeBridgeBaseUrl,t=this.agentId;if(!e||!t)return{revision:0,events:[],catalog:null,compactionSeq:0};try{const n=`${e}/runtime/plugin-events/${encodeURIComponent(t)}/events`,r=this.serverConfig.runtimeAccessToken||"",s=await fetch(n,{method:"GET",headers:{"X-Runtime-Token":r},signal:AbortSignal.timeout(3e3)});if(!s.ok)return i.warn("[AgentClient] \u62C9\u53D6\u63D2\u4EF6\u4E8B\u4EF6\u5931\u8D25: HTTP %s, url=%s",s.status,n),{revision:0,events:[],catalog:null,compactionSeq:0};const a=await s.json();return!a.ok||!Array.isArray(a.events)?(i.warn("[AgentClient] \u62C9\u53D6\u63D2\u4EF6\u4E8B\u4EF6\u54CD\u5E94\u5F02\u5E38: ok=%s",String(a.ok)),{revision:0,events:[],catalog:null,compactionSeq:0}):(i.debug("[AgentClient] \u62C9\u53D6\u63D2\u4EF6\u4E8B\u4EF6\u6210\u529F: %d \u6761\u4E8B\u4EF6, revision=%s, catalog=%s, compactionSeq=%s",a.events.length,String(a.revision??0),a.catalog?`${a.catalog.plugins.length} \u4E2A\u63D2\u4EF6`:"null",String(a.compactionSeq??0)),{revision:a.revision??0,events:a.events,catalog:a.catalog??null,compactionSeq:typeof a.compactionSeq=="number"&&Number.isFinite(a.compactionSeq)?a.compactionSeq:0})}catch(n){return i.warn("[AgentClient] \u62C9\u53D6\u63D2\u4EF6\u4E8B\u4EF6\u5F02\u5E38: %s",n instanceof Error?n.message:String(n)),{revision:0,events:[],catalog:null,compactionSeq:0}}}async notifyBridgeForceMessage(){const e=this.serverConfig.runtimeBridgeBaseUrl,t=this.agentId;if(!(!e||!t))try{const n=`${e}/runtime/sessions/${encodeURIComponent(t)}/notify-force-message`,r=this.serverConfig.runtimeAccessToken||"",s=await fetch(n,{method:"POST",headers:{"X-Runtime-Token":r},signal:AbortSignal.timeout(3e3)});s.ok||i.warn("[AgentClient] \u901A\u77E5 bridge \u5F3A\u5236\u6D88\u606F\u5931\u8D25: HTTP %s, url=%s",s.status,n)}catch(n){i.warn("[AgentClient] \u901A\u77E5 bridge \u5F3A\u5236\u6D88\u606F\u5F02\u5E38: %s",n instanceof Error?n.message:String(n))}}async fetchDirectMessagesWithRecovery(e,t,n,r=!1){if(e==="poll_message"){i.info("[AgentClient] fetchDirectMessagesWithRecovery \u5165\u53E3: tool=poll_message, pollMessageTimeoutMs=%s, agentId=%s",String(n??"(\u9ED8\u8BA4)"),String(t?.agentId??""));try{const s=await this.httpClient.callToolOnce(e,t,n);return i.info("[AgentClient] fetchDirectMessagesWithRecovery poll_message \u6210\u529F\u8FD4\u56DE: %s \u6761",Array.isArray(s?.messages)?s.messages.length:0),s}catch(s){if(this.isRecoverableLongPollError(s)){if(r)throw new T(s instanceof Error?s.message:String(s));return i.warn("[AgentClient] poll_message \u5355\u6B21\u957F\u8F6E\u8BE2\u8D85\u65F6\uFF0C\u6309\u7A7A\u7ED3\u679C\u9000\u907F\u540E\u7EE7\u7EED\u7B49\u5F85:",s),{messages:[]}}throw s}}return await this.httpClient.callTool(e,t)}isRecoverableLongPollError(e){return e instanceof Error?/MCP tool poll_message call failed: 503(?:\s|$)/.test(e.message)||/MCP tool poll_message timed out after \d+ms/.test(e.message):!1}normalizeGroupMessages(e){return Array.isArray(e.messages)?e.messages.filter(t=>!!(t&&typeof t=="object"&&typeof t.msgId=="number"&&typeof t.senderId=="string"&&typeof t.content=="string"&&typeof t.timestamp=="string")):[]}collectRoomIds(e,t){const n=e.groups.filter(r=>r.projectId===t).map(r=>r.id);return Array.from(new Set(n))}async getProfile(){this.ensureRegistered();const e=this.agentId;if(!e)throw new Error("Agent is not registered");return{...await this.getProfileByAgentId(e),describe:this.agentConfig.describe}}async getProfileByAgentId(e){return await this.httpClient.callTool("get_profile",{agentId:e})}async getMyTasks(){return this.ensureRegistered(),await this.httpClient.callTool("my_task",{agentId:this.agentId})}async listTaskNodeIterations(e={}){return this.ensureRegistered(),await this.httpClient.callTool("list_task_node_iterations",{agentId:this.agentId,...e})}async createTaskInstanceComment(e){this.ensureRegistered();const t={agentId:this.agentId,...e};return await this.httpClient.callTool("create_task_instance_comment",t)}async submitTaskResult(e,t,n,r,s){this.ensureRegistered();const a={agentId:this.agentId,nodeId:e,outputPayload:t};return(Array.isArray(n)&&n.length>0||typeof n=="string"&&n.trim().length>0)&&(a.changeLog=n),typeof r=="string"&&r.trim().length>0&&(a.handoverNote=r),s&&Array.isArray(s)&&s.length>0&&(a.deliverables=s),await this.httpClient.callTool("submit_task_result",a)}async startTaskRollback(e){return this.ensureRegistered(),await this.httpClient.callTool("start_task_rollback",{agentId:this.agentId,...e})}async finishTaskRollback(e){return this.ensureRegistered(),await this.httpClient.callTool("finish_task_rollback",{agentId:this.agentId,...e})}async getDebugLogConfig(){return await this.httpClient.callTool("get_debug_log_config",{agentId:this.agentId})}async queryDebugLogs(e){return this.ensureRegistered(),await this.httpClient.callTool("query_debug_logs",{...e})}async queryFileChangesHistory(e){return this.ensureRegistered(),await this.httpClient.callTool("query_file_changes_history",{...e})}async getRuntimeFeatures(){return await this.httpClient.fetchRuntimeFeatures()}async listLaunchConfigs(){return this.ensureRegistered(),await this.httpClient.callTool("launch_config_list",{})}async createLaunchConfig(e){return this.ensureRegistered(),await this.httpClient.callTool("launch_config_create",{...e})}async updateLaunchConfig(e){return this.ensureRegistered(),await this.httpClient.callTool("launch_config_update",{...e})}async deleteLaunchConfig(e){return this.ensureRegistered(),await this.httpClient.callTool("launch_config_delete",{configId:e})}async startLaunchConfig(e){this.ensureRegistered();const t=Math.max(0,Math.min(3e5,Number(e.wait_timeout_ms)||0));return t>0?await this.httpClient.callToolOnce("launch_config_start",e,t+6e4):await this.httpClient.callTool("launch_config_start",{...e})}async restartLaunchConfig(e){this.ensureRegistered();const t=Math.max(0,Math.min(3e5,Number(e.wait_timeout_ms)||0));return t>0?await this.httpClient.callToolOnce("launch_config_restart",e,t+6e4):await this.httpClient.callTool("launch_config_restart",{...e})}async stopLaunchConfig(e){return this.ensureRegistered(),await this.httpClient.callTool("launch_config_stop",{configId:e})}async getLaunchLogs(e){return this.ensureRegistered(),await this.httpClient.callTool("launch_config_logs",{...e})}async listLaunchRuns(){return this.ensureRegistered(),await this.httpClient.callTool("launch_config_status",{})}start(e,t){if(this.isRunning){i.warn("[AgentClient] \u6D88\u606F\u5FAA\u73AF\u5DF2\u5728\u8FD0\u884C\u4E2D");return}this.isDegradedMode||this.ensureRegistered(),this.messageHandler=e,this.profileHandler=t?.profileHandler||null,this.configHandler=t?.configHandler||null,this.systemNotifyHandler=t?.systemNotifyHandler||null,this.isRunning=!0,i.info(`[AgentClient] start() \u88AB\u8C03\u7528\uFF0CcachedProfile: ${this.cachedProfile?"\u5B58\u5728":"\u4E0D\u5B58\u5728"}, profileHandler: ${this.profileHandler?"\u5DF2\u8BBE\u7F6E":"\u672A\u8BBE\u7F6E"}, \u964D\u7EA7\u6A21\u5F0F: ${this.isDegradedMode?"\u662F":"\u5426"}`),this.cachedProfile&&this.profileHandler&&(i.info(`[AgentClient] \u5904\u7406\u7F13\u5B58\u7684 Profile \u4FE1\u606F: ${this.cachedProfile.displayName}`),this.profileHandler(this.cachedProfile),this.cachedProfile=null),t?.pollMode??!1?(i.warn("[AgentClient] \u542F\u52A8\u6D88\u606F\u4E3B\u5FAA\u73AF\uFF08HTTP\u8F6E\u8BE2\u6A21\u5F0F - \u4E0D\u63A8\u8350\uFF09"),this.messageLoop()):i.info("[AgentClient] \u542F\u52A8\u6D88\u606F\u4E3B\u5FAA\u73AF\uFF08WebSocket\u63A8\u9001\u6A21\u5F0F - \u63A8\u8350\uFF09")}stop(){this.isRunning=!1,this.pollTimer&&(clearTimeout(this.pollTimer),this.pollTimer=null),this.stopRuntimeTokenRefresh(),i.info("[AgentClient] \u6D88\u606F\u4E3B\u5FAA\u73AF\u5DF2\u505C\u6B62")}async messageLoop(){for(;this.isRunning;)try{await this.delay(I)}catch(e){i.error("[AgentClient] \u6D88\u606F\u5FAA\u73AF\u9519\u8BEF:",e),await this.delay(5e3)}}handleIncomingDm(e){e.senderId!==this.agentId&&this.processMessage(e)}handleIncomingGroup(e){e.senderId!==this.agentId&&this.processMessage(e)}handleIncomingMeeting(e){!e||e.senderId===this.agentId||this.processMessage(e)}handleProfileInfo(e){i.info(`[AgentClient] \u6536\u5230 Profile \u4FE1\u606F: ${e.displayName} (${e.roleName})`),e.projectId&&(this.projectId=e.projectId,i.info(`[AgentClient] \u66F4\u65B0\u6240\u5C5E\u9879\u76EE: ${this.projectId}`)),e.roleName&&e.roleName!==this.agentConfig.roleName&&(i.info(`[AgentClient] \u540C\u6B65\u89D2\u8272\u540D: "${this.agentConfig.roleName||"(\u7A7A)"}" -> "${e.roleName}"`),this.agentConfig.roleName=e.roleName),e.roleName&&u(e.roleName,e.instanceName||this.agentId||""),this.profileHandler?this.profileHandler(e):(i.info("[AgentClient] profileHandler \u672A\u8BBE\u7F6E\uFF0C\u7F13\u5B58 Profile \u4FE1\u606F"),this.cachedProfile=e)}async processMessage(e){if(!this.messageHandler)return;const t=typeof e.msgId=="string";i.info(`[AgentClient] \u6536\u5230${t?"\u79C1\u4FE1":"\u7FA4\u6D88\u606F"}\u6765\u81EA ${e.senderName}: ${e.content.substring(0,50)}...`);try{const n=await this.messageHandler(e);if(t){const r=e;r.requireReply&&r.callId&&await this.replyToCall(r.callId,r.senderId,n||"\u5DF2\u6536\u5230\u6D88\u606F\uFF0C\u6B63\u5728\u5904\u7406\u4E2D...")}}catch(n){const r=typeof e.msgId=="string";if(i.error("[AgentClient] \u5904\u7406\u6D88\u606F\u5931\u8D25: type=%s, senderId=%s, senderName=%s, msgId=%s, error=%s",r?"\u79C1\u4FE1":"\u7FA4\u6D88\u606F",e.senderId,e.senderName,e.msgId,n instanceof Error?n.message:String(n)),r){const s=e;s.requireReply&&s.callId&&await this.replyToCall(s.callId,s.senderId,`\u5904\u7406\u5931\u8D25: ${n}`)}}}ensureRegistered(){if(!this.agentId)throw new Error("Agent is not registered")}delay(e){return new Promise(t=>{this.pollTimer=setTimeout(t,e)})}onNewCharacter(e){this.newCharacterHandler=e}getState(){return{agentId:this.agentId,displayName:this.displayName,projectId:this.projectId,isConnected:this.wsClient.isConnected(),isRunning:this.isRunning}}getAgentConfig(){return this.agentConfig}getServerConfig(){return this.serverConfig}reloadConfig(){c.loadConfig(),this.agentConfig=c.getAgentConfig(),i.info(`[AgentClient] \u914D\u7F6E\u5DF2\u91CD\u65B0\u52A0\u8F7D\uFF0C\u89D2\u8272: ${this.agentConfig.roleName}`)}enterDegradedMode(){this.isDegradedMode=!0,i.warn("[AgentClient] \u8FDB\u5165\u964D\u7EA7\u6A21\u5F0F\uFF0C\u5C06\u5728\u540E\u53F0\u6301\u7EED\u5C1D\u8BD5\u91CD\u8FDE")}exitDegradedMode(){this.isDegradedMode=!1,i.info("[AgentClient] \u9000\u51FA\u964D\u7EA7\u6A21\u5F0F")}isInDegradedMode(){return this.isDegradedMode}async retryRegistrationInBackground(e,t){let n=0;(async()=>{for(;this.isDegradedMode;)try{i.info(`[AgentClient] \u964D\u7EA7\u6A21\u5F0F\uFF1A\u5C1D\u8BD5\u91CD\u65B0\u6CE8\u518C (${n+1}/${t===-1?"\u65E0\u9650":t})`);const s=await this.register();i.info(`[AgentClient] \u964D\u7EA7\u6A21\u5F0F\uFF1A\u6CE8\u518C\u6210\u529F - ${s.displayName} (${s.agentId})`),this.exitDegradedMode(),this.messageHandler&&this.start(this.messageHandler);return}catch(s){n++;const a=s instanceof Error?s.message:String(s);if(i.warn(`[AgentClient] \u964D\u7EA7\u6A21\u5F0F\uFF1A\u6CE8\u518C\u5931\u8D25 (${n}/${t===-1?"\u65E0\u9650":t}): ${a}`),t>0&&n>=t){i.error("[AgentClient] \u964D\u7EA7\u6A21\u5F0F\uFF1A\u8FBE\u5230\u6700\u5927\u91CD\u8BD5\u6B21\u6570\uFF0C\u505C\u6B62\u91CD\u8FDE"),this.isDegradedMode=!1;return}await new Promise(h=>setTimeout(h,e))}})().catch(s=>{i.error("[AgentClient] \u964D\u7EA7\u6A21\u5F0F\u540E\u53F0\u91CD\u8BD5\u5FAA\u73AF\u5F02\u5E38\u9000\u51FA: error=%s, stack=%s",s instanceof Error?s.message:String(s),s instanceof Error?s.stack:"(no stack)")})}initializeStatusReporter(){if(!this.agentId){i.warn("[AgentClient] \u65E0\u6CD5\u521D\u59CB\u5316\u72B6\u6001\u62A5\u544A\u5668\uFF1AagentId \u4E3A\u7A7A");return}this.statusReporter=new A({agentId:this.agentId,sendStatusUpdate:e=>{this.wsClient.send({type:"AGENT_STATUS",data:e,timestamp:new Date().toISOString()})}}),w(e=>this.reportMcpNodeLog(e)),this.startRuntimeTokenRefresh(),i.info("[AgentClient] \u72B6\u6001\u62A5\u544A\u5668\u5DF2\u521D\u59CB\u5316")}startRuntimeTokenRefresh(){this.stopRuntimeTokenRefresh();const e=this.serverConfig.runtimeTokenRefreshIntervalMs;if(!e||e<=0){i.warn("[AgentClient] runtimeTokenRefreshIntervalMs \u672A\u914D\u7F6E\u6216\u65E0\u6548\uFF0C\u8DF3\u8FC7\u4E3B\u52A8\u7EED\u671F");return}const t=this.agentId;if(!t){i.warn("[AgentClient] agentId \u4E3A\u7A7A\uFF0C\u8DF3\u8FC7\u4E3B\u52A8\u7EED\u671F");return}this.runtimeTokenRefreshTimer=setInterval(async()=>{try{await this.httpClient.refreshRuntimeAccessToken(t)&&i.info("[AgentClient] runtimeAccessToken \u5DF2\u4E3B\u52A8\u7EED\u671F")}catch(n){i.warn("[AgentClient] \u4E3B\u52A8\u7EED\u671F runtimeAccessToken \u5931\u8D25: %s",n instanceof Error?n.message:String(n)),n instanceof Error&&n.stack&&i.warn("[AgentClient] \u4E3B\u52A8\u7EED\u671F\u5F02\u5E38\u5806\u6808:",n.stack)}},e),this.runtimeTokenRefreshTimer.unref?.(),i.info(`[AgentClient] runtime token \u4E3B\u52A8\u7EED\u671F\u5DF2\u542F\u52A8\uFF0C\u95F4\u9694 ${e}ms`)}stopRuntimeTokenRefresh(){this.runtimeTokenRefreshTimer&&(clearInterval(this.runtimeTokenRefreshTimer),this.runtimeTokenRefreshTimer=null)}reportMcpNodeLog(e){const t=this.wsClient;!this.agentId||!this.wsClient.isConnected()||typeof t.sendMcpNodeLog!="function"||t.sendMcpNodeLog(e)}getStatusReporter(){return this.statusReporter}}export{N as AgentClient,T as PollLongPollTimeoutError};
2
2
 
@@ -2,9 +2,19 @@
2
2
  import type { ServerConfig } from "./types.js";
3
3
  export interface McpToolResponse {
4
4
  error?: string;
5
+
6
+ errorCode?: string;
7
+
8
+ field?: string;
5
9
  [key: string]: unknown;
6
10
  }
7
11
 
12
+ export declare class McpToolError extends Error {
13
+ readonly errorCode?: string;
14
+ readonly field?: string;
15
+ constructor(message: string, errorCode?: string, field?: string);
16
+ }
17
+
8
18
  export declare function normalizeServerHttpBase(value: unknown, options?: {
9
19
  fromAgentWebSocketUrl?: boolean;
10
20
  }): string | undefined;
@@ -1,2 +1,2 @@
1
- import{logger as o}from"./logger.js";import{meetingDebugLog as h}from"./meeting-debug-log.js";const w=12e4,g=5e3,T=3e4,p=1e3;function d(l){const e=l.trim();return e?e.length<=p?e:`${e.slice(0,p)}...(truncated)`:""}function y(l){return l.replace(/^((?:https?|wss?):\/\/(?:\[[^\]]+\]|[^/:?#]+):\d+):\d+(?=\/|$)/i,"$1")}function C(l){const e=l.toLowerCase();return e==="localhost"||e==="::1"||e==="[::1]"?"127.0.0.1":e}function m(l,e={}){const r=k(l,e);if(r)try{const s=new URL(r);return s.pathname=s.pathname.includes("/mcp/call")?s.pathname:`${s.pathname.replace(/\/$/,"")}/mcp/call`,s.search="",s.hash="",s.toString()}catch{return r.endsWith("/mcp/call")?r:`${r}/mcp/call`}}function k(l,e={}){const r=String(l||"").trim();if(!r)return;const s=y(r);try{const t=new URL(s);t.protocol==="ws:"?t.protocol="http:":t.protocol==="wss:"?t.protocol="https:":t.protocol=t.protocol.toLowerCase(),t.hostname=C(t.hostname);const n=e.fromAgentWebSocketUrl?t.pathname.replace(/\/ws\/agent\/?$/,""):t.pathname;return t.pathname=n,t.search="",t.hash="",t.toString().replace(/\/+$/,"")}catch{return(e.fromAgentWebSocketUrl?s.replace(/\/ws\/agent\/?$/i,""):s).replace(/\/+$/,"")||void 0}}const $=6e5;class b{serverConfig;mcpHttpUrl;tokenRefreshPromise=null;constructor(e){this.serverConfig=e,this.mcpHttpUrl=this.resolveMcpHttpUrl()}async callTool(e,r){await this.ensureRuntimeAccessToken();const s=Date.now()+this.resolveRetryMaxAccumulatedMs();let t=0;for(;;){t++;let n;try{n=await this.executeToolRequest(e,r)}catch(a){if(Date.now()<s&&this.isTransientError(a)){await this.delayForRetry(s,e,t);continue}throw o.warn("[HttpClient] MCP tool %s \u8BF7\u6C42\u4E0D\u53EF\u6062\u590D\u5F02\u5E38 (attempt=%s): %s",e,t,a instanceof Error?a.message:String(a)),a}if(n.status===401){if(o.warn(`[HttpClient] MCP Tool ${e} \u8FD4\u56DE 401\uFF0C\u5C1D\u8BD5\u5411 bridge \u5237\u65B0 token`),await this.tryRefreshToken(r)){let c;try{c=await this.executeToolRequest(e,r)}catch(f){if(Date.now()<s&&this.isTransientError(f)){await this.delayForRetry(s,e,t);continue}throw o.warn("[HttpClient] MCP tool %s 401\u91CD\u8BD5\u5F02\u5E38 (attempt=%s): %s",e,t,f instanceof Error?f.message:String(f)),f}if(!c.ok){if(Date.now()<s&&this.isRetryableHttpStatus(c.status)){c.body&&await c.body.cancel().catch(()=>{}),await this.delayForRetry(s,e,t);continue}const f=typeof c.text=="function"?d(await c.text().catch(()=>"")):"";throw new Error(`MCP tool ${e} call failed: ${c.status} ${c.statusText}${f?` - ${f}`:""}`)}const u=await c.json();if(typeof u.error=="string"&&u.error.trim().length>0)throw new Error(`MCP tool ${e} failed: ${u.error}`);return u}o.warn("[HttpClient] token \u5237\u65B0\u5931\u8D25\u6216\u65E0\u65B0 token\uFF0C\u8FD4\u56DE\u539F\u59CB 401 \u9519\u8BEF")}if(!n.ok){if(Date.now()<s&&this.isRetryableHttpStatus(n.status)){n.body&&await n.body.cancel().catch(()=>{}),await this.delayForRetry(s,e,t);continue}const a=typeof n.text=="function"?d(await n.text().catch(()=>"")):"";throw new Error(`MCP tool ${e} call failed: ${n.status} ${n.statusText}${a?` - ${a}`:""}`)}const i=await n.json();if(typeof i.error=="string"&&i.error.trim().length>0)throw new Error(`MCP tool ${e} failed: ${i.error}`);return i}}async fetchRuntimeFeatures(){if(!this.serverConfig.runtimeAccessToken)throw new Error("fetch runtime features skipped: runtimeAccessToken not ready");const e=this.mcpHttpUrl.replace(/\/mcp\/call(\/)?$/,"/mcp/features$1");let r;try{r=await fetch(e,{method:"POST",headers:this.buildRequestHeaders(),body:JSON.stringify({}),signal:AbortSignal.timeout(5e3)})}catch(t){throw o.warn("[HttpClient] \u67E5\u8BE2\u80FD\u529B\u5F00\u5173\u8BF7\u6C42\u5931\u8D25: %s",t instanceof Error?t.message:String(t)),new Error(`fetch runtime features failed: ${t instanceof Error?t.message:String(t)}`)}if(!r.ok)throw o.warn("[HttpClient] \u67E5\u8BE2\u80FD\u529B\u5F00\u5173\u5931\u8D25: status=%s, statusText=%s",r.status,r.statusText),new Error(`fetch runtime features failed: ${r.status} ${r.statusText}`);const s=await r.json();return!s||typeof s.features!="object"||s.features===null?{}:s.features}async callToolOnce(e,r,s=$){await this.ensureRuntimeAccessToken(),o.info("[HttpClient] callToolOnce \u5F00\u59CB: tool=%s, timeoutMs=%d, url=%s, agentId=%s",e,s,this.mcpHttpUrl,String(r?.agentId??"")),e==="poll_message"&&h("http.callToolOnce.start",`tool=${e} timeoutMs=${s} preemptiveJoinWaitMs=${String(r?.preemptiveJoinWaitMs??"-")}`);const t=c=>fetch(this.mcpHttpUrl,{method:"POST",headers:this.buildRequestHeaders(),body:JSON.stringify({tool:e,arguments:r}),signal:c}),n=Date.now();let i=await this.singleFetchWithTimeout(t,s,e);if(o.info("[HttpClient] callToolOnce \u6536\u5230\u54CD\u5E94: tool=%s, status=%d, \u8017\u65F6=%dms",e,i.status,Date.now()-n),e==="poll_message"&&h("http.callToolOnce.response",`status=${i.status} elapsedMs=${Date.now()-n}`),i.status===401&&(o.warn(`[HttpClient] MCP Tool ${e} \u8FD4\u56DE 401\uFF0C\u5C1D\u8BD5\u5411 bridge \u5237\u65B0 token`),await this.tryRefreshToken(r)&&(i=await this.singleFetchWithTimeout(t,s,e),o.info("[HttpClient] callToolOnce token \u5237\u65B0\u540E\u91CD\u8BD5\u6536\u5230\u54CD\u5E94: tool=%s, status=%d, \u7D2F\u8BA1\u8017\u65F6=%dms",e,i.status,Date.now()-n))),!i.ok){const c=typeof i.text=="function"?d(await this.readTextWithTimeout(i,s,e).catch(()=>"")):"";throw o.info("[HttpClient] callToolOnce \u975E 2xx \u54CD\u5E94: tool=%s, status=%d, body=%s",e,i.status,c||"(\u7A7A)"),new Error(`MCP tool ${e} call failed: ${i.status} ${i.statusText}${c?` - ${c}`:""}`)}const a=await this.parseJsonWithTimeout(i,s,e);if(o.info("[HttpClient] callToolOnce \u5B8C\u6210: tool=%s, \u603B\u8017\u65F6=%dms, error=%s",e,Date.now()-n,typeof a.error=="string"?a.error:"(\u65E0)"),e==="poll_message"){const c=Array.isArray(a.messages)?a.messages:[];h("http.callToolOnce.parsed",`totalElapsedMs=${Date.now()-n} serverMessages=${c.length} `+JSON.stringify(c.map(u=>({msgId:u.msgId,channel:u.channel,sender:u.senderId}))))}if(typeof a.error=="string"&&a.error.trim().length>0)throw new Error(`MCP tool ${e} failed: ${a.error}`);return a}async readTextWithTimeout(e,r,s){if(r<=0)return await e.text();let t;try{return await Promise.race([e.text(),new Promise((n,i)=>{t=setTimeout(()=>i(new Error(`MCP tool ${s} timed out after ${r}ms`)),r)})])}finally{t!==void 0&&clearTimeout(t)}}async parseJsonWithTimeout(e,r,s){if(r<=0)return await e.json();let t;try{return await Promise.race([e.json(),new Promise((n,i)=>{t=setTimeout(()=>i(new Error(`MCP tool ${s} timed out after ${r}ms`)),r)})])}finally{t!==void 0&&clearTimeout(t)}}async singleFetchWithTimeout(e,r,s){const t=new AbortController;let n;r>0&&(n=setTimeout(()=>t.abort(),r));try{return await e(t.signal)}catch(i){throw t.signal.aborted?(s==="poll_message"&&h("http.callToolOnce.timeout",`timeoutMs=${r} \u670D\u52A1\u7AEF\u53EF\u80FD\u4ECD\u5728\u6267\u884C\u540C\u4E00\u8BF7\u6C42\uFF08Callable \u5360\u7EBF\u81F3\u9884\u7B97\u7ED3\u675F\uFF09`),new Error(`MCP tool ${s} timed out after ${r}ms`)):i}finally{n!==void 0&&clearTimeout(n)}}async executeToolRequest(e,r){return await this.fetchWithTimeout(this.mcpHttpUrl,{method:"POST",headers:this.buildRequestHeaders(),body:JSON.stringify({tool:e,arguments:r})},`MCP tool ${e}`)}async fetchWithTimeout(e,r,s){const t=this.resolveRequestTimeoutMs(),n=new AbortController,i=setTimeout(()=>n.abort(),t);try{return await fetch(e,{...r,signal:n.signal})}catch(a){throw n.signal.aborted?new Error(`${s} timed out after ${t}ms`):a}finally{clearTimeout(i)}}resolveRequestTimeoutMs(){const e=this.serverConfig.mcpHttpRequestTimeoutMs;return typeof e=="number"&&Number.isFinite(e)&&e>0?e:w}resolveRetryIntervalMs(){const e=this.serverConfig.mcpRetryIntervalMs;return typeof e=="number"&&Number.isFinite(e)&&e>=0?e:g}resolveRetryMaxAccumulatedMs(){const e=this.serverConfig.mcpRetryMaxAccumulatedMs;return typeof e=="number"&&Number.isFinite(e)&&e>=0?e:T}isTransientError(e){if(!(e instanceof Error))return!1;const r=e.message;return!!(/timed out after \d+ms/.test(r)||/fetch failed/i.test(r)||/network/i.test(r)||/ECONNREFUSED/i.test(r)||/ECONNRESET/i.test(r))}isRetryableHttpStatus(e){return e>=500||e===429}async delayForRetry(e,r,s){const t=e-Date.now(),n=Math.min(this.resolveRetryIntervalMs(),Math.max(0,t));o.warn(`[HttpClient] MCP tool ${r} \u8BF7\u6C42\u5931\u8D25\uFF0C${n}ms \u540E\u91CD\u8BD5 (\u7B2C${s}\u6B21)`),n>0&&await new Promise(i=>setTimeout(i,n))}buildRequestHeaders(){const e={"Content-Type":"application/json"};return this.serverConfig.runtimeAccessToken&&(e["X-Runtime-Token"]=this.serverConfig.runtimeAccessToken,e.Authorization=`Bearer ${this.serverConfig.runtimeAccessToken}`),e}async ensureRuntimeAccessToken(){if(this.serverConfig.runtimeAccessToken||!this.serverConfig.runtimeBridgeBaseUrl){o.info("[HttpClient] ensureRuntimeAccessToken: tokenLen=%d, bridgeBaseUrl=%s",(this.serverConfig.runtimeAccessToken||"").length,this.serverConfig.runtimeBridgeBaseUrl||"(\u7A7A)");return}throw new Error("runtimeAccessToken is required; MCP nodes must claim a session token from launch binding")}async tryRefreshToken(e){if(this.tokenRefreshPromise)return this.tokenRefreshPromise;this.tokenRefreshPromise=this.doRefreshToken(e);try{return await this.tokenRefreshPromise}finally{this.tokenRefreshPromise=null}}async doRefreshToken(e){const r=this.serverConfig.runtimeBridgeBaseUrl;if(!r)return o.warn("[HttpClient] \u65E0 runtimeBridgeBaseUrl\uFF0C\u65E0\u6CD5\u5237\u65B0 token"),!1;const s=String(e?.agentId||"").trim();if(!s)return o.warn("[HttpClient] \u65E0 agentId\uFF0C\u65E0\u6CD5\u5237\u65B0 token"),!1;try{const t=await fetch(`${r}/runtime/binding/refresh-token`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({agentId:s,currentToken:this.serverConfig.runtimeAccessToken||""})});if(!t.ok)return o.warn(`[HttpClient] bridge refresh-token \u8FD4\u56DE ${t.status}\uFF0C\u65E0\u6CD5\u5237\u65B0`),!1;const i=(await t.json()).runtimeAccessToken;return i?i===this.serverConfig.runtimeAccessToken?!1:(this.serverConfig.runtimeAccessToken=i,o.info("[HttpClient] runtimeAccessToken \u5DF2\u901A\u8FC7 bridge refresh \u66F4\u65B0"),!0):(o.warn("[HttpClient] bridge \u672A\u8FD4\u56DE\u65B0 token"),!1)}catch(t){return o.warn("[HttpClient] \u5237\u65B0 token \u5931\u8D25: %s",t instanceof Error?t.message:String(t)),t instanceof Error&&t.stack&&o.warn("[HttpClient] \u5237\u65B0 token \u5F02\u5E38\u5806\u6808:",t.stack),!1}}async refreshRuntimeAccessToken(e){return this.tryRefreshToken({agentId:e})}resolveMcpHttpUrl(){const e=this.serverConfig.mcpHttpUrl;if(e&&e.trim().length>0){const s=m(e);if(s)return s}const r=m(this.serverConfig.serverUrl,{fromAgentWebSocketUrl:!0});return r||this.serverConfig.serverUrl}getMcpHttpUrl(){return this.mcpHttpUrl}}export{b as HttpClient,k as normalizeServerHttpBase};
1
+ import{logger as c}from"./logger.js";import{meetingDebugLog as h}from"./meeting-debug-log.js";class g extends Error{errorCode;field;constructor(e,r,s){super(e),this.name="McpToolError",this.errorCode=r,this.field=s}}const w=12e4,T=5e3,y=3e4,p=1e3;function d(l){const e=l.trim();return e?e.length<=p?e:`${e.slice(0,p)}...(truncated)`:""}function C(l){return l.replace(/^((?:https?|wss?):\/\/(?:\[[^\]]+\]|[^/:?#]+):\d+):\d+(?=\/|$)/i,"$1")}function k(l){const e=l.toLowerCase();return e==="localhost"||e==="::1"||e==="[::1]"?"127.0.0.1":e}function m(l,e={}){const r=$(l,e);if(r)try{const s=new URL(r);return s.pathname=s.pathname.includes("/mcp/call")?s.pathname:`${s.pathname.replace(/\/$/,"")}/mcp/call`,s.search="",s.hash="",s.toString()}catch{return r.endsWith("/mcp/call")?r:`${r}/mcp/call`}}function $(l,e={}){const r=String(l||"").trim();if(!r)return;const s=C(r);try{const t=new URL(s);t.protocol==="ws:"?t.protocol="http:":t.protocol==="wss:"?t.protocol="https:":t.protocol=t.protocol.toLowerCase(),t.hostname=k(t.hostname);const n=e.fromAgentWebSocketUrl?t.pathname.replace(/\/ws\/agent\/?$/,""):t.pathname;return t.pathname=n,t.search="",t.hash="",t.toString().replace(/\/+$/,"")}catch{return(e.fromAgentWebSocketUrl?s.replace(/\/ws\/agent\/?$/i,""):s).replace(/\/+$/,"")||void 0}}const R=6e5;class M{serverConfig;mcpHttpUrl;tokenRefreshPromise=null;constructor(e){this.serverConfig=e,this.mcpHttpUrl=this.resolveMcpHttpUrl()}async callTool(e,r){await this.ensureRuntimeAccessToken();const s=Date.now()+this.resolveRetryMaxAccumulatedMs();let t=0;for(;;){t++;let n;try{n=await this.executeToolRequest(e,r)}catch(o){if(Date.now()<s&&this.isTransientError(o)){await this.delayForRetry(s,e,t);continue}throw c.warn("[HttpClient] MCP tool %s \u8BF7\u6C42\u4E0D\u53EF\u6062\u590D\u5F02\u5E38 (attempt=%s): %s",e,t,o instanceof Error?o.message:String(o)),o}if(n.status===401){if(c.warn(`[HttpClient] MCP Tool ${e} \u8FD4\u56DE 401\uFF0C\u5C1D\u8BD5\u5411 bridge \u5237\u65B0 token`),await this.tryRefreshToken(r)){let a;try{a=await this.executeToolRequest(e,r)}catch(f){if(Date.now()<s&&this.isTransientError(f)){await this.delayForRetry(s,e,t);continue}throw c.warn("[HttpClient] MCP tool %s 401\u91CD\u8BD5\u5F02\u5E38 (attempt=%s): %s",e,t,f instanceof Error?f.message:String(f)),f}if(!a.ok){if(Date.now()<s&&this.isRetryableHttpStatus(a.status)){a.body&&await a.body.cancel().catch(()=>{}),await this.delayForRetry(s,e,t);continue}const f=typeof a.text=="function"?d(await a.text().catch(()=>"")):"";throw new Error(`MCP tool ${e} call failed: ${a.status} ${a.statusText}${f?` - ${f}`:""}`)}const u=await a.json();if(typeof u.error=="string"&&u.error.trim().length>0)throw new Error(`MCP tool ${e} failed: ${u.error}`);return u}c.warn("[HttpClient] token \u5237\u65B0\u5931\u8D25\u6216\u65E0\u65B0 token\uFF0C\u8FD4\u56DE\u539F\u59CB 401 \u9519\u8BEF")}if(!n.ok){if(Date.now()<s&&this.isRetryableHttpStatus(n.status)){n.body&&await n.body.cancel().catch(()=>{}),await this.delayForRetry(s,e,t);continue}const o=typeof n.text=="function"?d(await n.text().catch(()=>"")):"";throw new Error(`MCP tool ${e} call failed: ${n.status} ${n.statusText}${o?` - ${o}`:""}`)}const i=await n.json();if(typeof i.error=="string"&&i.error.trim().length>0)throw new Error(`MCP tool ${e} failed: ${i.error}`);return i}}async fetchRuntimeFeatures(){if(!this.serverConfig.runtimeAccessToken)throw new Error("fetch runtime features skipped: runtimeAccessToken not ready");const e=this.mcpHttpUrl.replace(/\/mcp\/call(\/)?$/,"/mcp/features$1");let r;try{r=await fetch(e,{method:"POST",headers:this.buildRequestHeaders(),body:JSON.stringify({}),signal:AbortSignal.timeout(5e3)})}catch(t){throw c.warn("[HttpClient] \u67E5\u8BE2\u80FD\u529B\u5F00\u5173\u8BF7\u6C42\u5931\u8D25: %s",t instanceof Error?t.message:String(t)),new Error(`fetch runtime features failed: ${t instanceof Error?t.message:String(t)}`)}if(!r.ok)throw c.warn("[HttpClient] \u67E5\u8BE2\u80FD\u529B\u5F00\u5173\u5931\u8D25: status=%s, statusText=%s",r.status,r.statusText),new Error(`fetch runtime features failed: ${r.status} ${r.statusText}`);const s=await r.json();return!s||typeof s.features!="object"||s.features===null?{}:s.features}async callToolOnce(e,r,s=R){await this.ensureRuntimeAccessToken(),c.info("[HttpClient] callToolOnce \u5F00\u59CB: tool=%s, timeoutMs=%d, url=%s, agentId=%s",e,s,this.mcpHttpUrl,String(r?.agentId??"")),e==="poll_message"&&h("http.callToolOnce.start",`tool=${e} timeoutMs=${s} preemptiveJoinWaitMs=${String(r?.preemptiveJoinWaitMs??"-")}`);const t=a=>fetch(this.mcpHttpUrl,{method:"POST",headers:this.buildRequestHeaders(),body:JSON.stringify({tool:e,arguments:r}),signal:a}),n=Date.now();let i=await this.singleFetchWithTimeout(t,s,e);if(c.info("[HttpClient] callToolOnce \u6536\u5230\u54CD\u5E94: tool=%s, status=%d, \u8017\u65F6=%dms",e,i.status,Date.now()-n),e==="poll_message"&&h("http.callToolOnce.response",`status=${i.status} elapsedMs=${Date.now()-n}`),i.status===401&&(c.warn(`[HttpClient] MCP Tool ${e} \u8FD4\u56DE 401\uFF0C\u5C1D\u8BD5\u5411 bridge \u5237\u65B0 token`),await this.tryRefreshToken(r)&&(i=await this.singleFetchWithTimeout(t,s,e),c.info("[HttpClient] callToolOnce token \u5237\u65B0\u540E\u91CD\u8BD5\u6536\u5230\u54CD\u5E94: tool=%s, status=%d, \u7D2F\u8BA1\u8017\u65F6=%dms",e,i.status,Date.now()-n))),!i.ok){const a=typeof i.text=="function"?d(await this.readTextWithTimeout(i,s,e).catch(()=>"")):"";throw c.info("[HttpClient] callToolOnce \u975E 2xx \u54CD\u5E94: tool=%s, status=%d, body=%s",e,i.status,a||"(\u7A7A)"),new Error(`MCP tool ${e} call failed: ${i.status} ${i.statusText}${a?` - ${a}`:""}`)}const o=await this.parseJsonWithTimeout(i,s,e);if(c.info("[HttpClient] callToolOnce \u5B8C\u6210: tool=%s, \u603B\u8017\u65F6=%dms, error=%s",e,Date.now()-n,typeof o.error=="string"?o.error:"(\u65E0)"),e==="poll_message"){const a=Array.isArray(o.messages)?o.messages:[];h("http.callToolOnce.parsed",`totalElapsedMs=${Date.now()-n} serverMessages=${a.length} `+JSON.stringify(a.map(u=>({msgId:u.msgId,channel:u.channel,sender:u.senderId}))))}if(typeof o.error=="string"&&o.error.trim().length>0){const a=typeof o.errorCode=="string"?o.errorCode:void 0,u=typeof o.field=="string"?o.field:void 0;throw new g(`MCP tool ${e} failed: ${o.error}`,a,u)}return o}async readTextWithTimeout(e,r,s){if(r<=0)return await e.text();let t;try{return await Promise.race([e.text(),new Promise((n,i)=>{t=setTimeout(()=>i(new Error(`MCP tool ${s} timed out after ${r}ms`)),r)})])}finally{t!==void 0&&clearTimeout(t)}}async parseJsonWithTimeout(e,r,s){if(r<=0)return await e.json();let t;try{return await Promise.race([e.json(),new Promise((n,i)=>{t=setTimeout(()=>i(new Error(`MCP tool ${s} timed out after ${r}ms`)),r)})])}finally{t!==void 0&&clearTimeout(t)}}async singleFetchWithTimeout(e,r,s){const t=new AbortController;let n;r>0&&(n=setTimeout(()=>t.abort(),r));try{return await e(t.signal)}catch(i){throw t.signal.aborted?(s==="poll_message"&&h("http.callToolOnce.timeout",`timeoutMs=${r} \u670D\u52A1\u7AEF\u53EF\u80FD\u4ECD\u5728\u6267\u884C\u540C\u4E00\u8BF7\u6C42\uFF08Callable \u5360\u7EBF\u81F3\u9884\u7B97\u7ED3\u675F\uFF09`),new Error(`MCP tool ${s} timed out after ${r}ms`)):i}finally{n!==void 0&&clearTimeout(n)}}async executeToolRequest(e,r){return await this.fetchWithTimeout(this.mcpHttpUrl,{method:"POST",headers:this.buildRequestHeaders(),body:JSON.stringify({tool:e,arguments:r})},`MCP tool ${e}`)}async fetchWithTimeout(e,r,s){const t=this.resolveRequestTimeoutMs(),n=new AbortController,i=setTimeout(()=>n.abort(),t);try{return await fetch(e,{...r,signal:n.signal})}catch(o){throw n.signal.aborted?new Error(`${s} timed out after ${t}ms`):o}finally{clearTimeout(i)}}resolveRequestTimeoutMs(){const e=this.serverConfig.mcpHttpRequestTimeoutMs;return typeof e=="number"&&Number.isFinite(e)&&e>0?e:w}resolveRetryIntervalMs(){const e=this.serverConfig.mcpRetryIntervalMs;return typeof e=="number"&&Number.isFinite(e)&&e>=0?e:T}resolveRetryMaxAccumulatedMs(){const e=this.serverConfig.mcpRetryMaxAccumulatedMs;return typeof e=="number"&&Number.isFinite(e)&&e>=0?e:y}isTransientError(e){if(!(e instanceof Error))return!1;const r=e.message;return!!(/timed out after \d+ms/.test(r)||/fetch failed/i.test(r)||/network/i.test(r)||/ECONNREFUSED/i.test(r)||/ECONNRESET/i.test(r))}isRetryableHttpStatus(e){return e>=500||e===429}async delayForRetry(e,r,s){const t=e-Date.now(),n=Math.min(this.resolveRetryIntervalMs(),Math.max(0,t));c.warn(`[HttpClient] MCP tool ${r} \u8BF7\u6C42\u5931\u8D25\uFF0C${n}ms \u540E\u91CD\u8BD5 (\u7B2C${s}\u6B21)`),n>0&&await new Promise(i=>setTimeout(i,n))}buildRequestHeaders(){const e={"Content-Type":"application/json"};return this.serverConfig.runtimeAccessToken&&(e["X-Runtime-Token"]=this.serverConfig.runtimeAccessToken,e.Authorization=`Bearer ${this.serverConfig.runtimeAccessToken}`),e}async ensureRuntimeAccessToken(){if(this.serverConfig.runtimeAccessToken||!this.serverConfig.runtimeBridgeBaseUrl){c.info("[HttpClient] ensureRuntimeAccessToken: tokenLen=%d, bridgeBaseUrl=%s",(this.serverConfig.runtimeAccessToken||"").length,this.serverConfig.runtimeBridgeBaseUrl||"(\u7A7A)");return}throw new Error("runtimeAccessToken is required; MCP nodes must claim a session token from launch binding")}async tryRefreshToken(e){if(this.tokenRefreshPromise)return this.tokenRefreshPromise;this.tokenRefreshPromise=this.doRefreshToken(e);try{return await this.tokenRefreshPromise}finally{this.tokenRefreshPromise=null}}async doRefreshToken(e){const r=this.serverConfig.runtimeBridgeBaseUrl;if(!r)return c.warn("[HttpClient] \u65E0 runtimeBridgeBaseUrl\uFF0C\u65E0\u6CD5\u5237\u65B0 token"),!1;const s=String(e?.agentId||"").trim();if(!s)return c.warn("[HttpClient] \u65E0 agentId\uFF0C\u65E0\u6CD5\u5237\u65B0 token"),!1;try{const t=await fetch(`${r}/runtime/binding/refresh-token`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({agentId:s,currentToken:this.serverConfig.runtimeAccessToken||""})});if(!t.ok)return c.warn(`[HttpClient] bridge refresh-token \u8FD4\u56DE ${t.status}\uFF0C\u65E0\u6CD5\u5237\u65B0`),!1;const i=(await t.json()).runtimeAccessToken;return i?i===this.serverConfig.runtimeAccessToken?!1:(this.serverConfig.runtimeAccessToken=i,c.info("[HttpClient] runtimeAccessToken \u5DF2\u901A\u8FC7 bridge refresh \u66F4\u65B0"),!0):(c.warn("[HttpClient] bridge \u672A\u8FD4\u56DE\u65B0 token"),!1)}catch(t){return c.warn("[HttpClient] \u5237\u65B0 token \u5931\u8D25: %s",t instanceof Error?t.message:String(t)),t instanceof Error&&t.stack&&c.warn("[HttpClient] \u5237\u65B0 token \u5F02\u5E38\u5806\u6808:",t.stack),!1}}async refreshRuntimeAccessToken(e){return this.tryRefreshToken({agentId:e})}resolveMcpHttpUrl(){const e=this.serverConfig.mcpHttpUrl;if(e&&e.trim().length>0){const s=m(e);if(s)return s}const r=m(this.serverConfig.serverUrl,{fromAgentWebSocketUrl:!0});return r||this.serverConfig.serverUrl}getMcpHttpUrl(){return this.mcpHttpUrl}}export{M as HttpClient,g as McpToolError,$ as normalizeServerHttpBase};
2
2
 
@@ -21,7 +21,6 @@ export declare function buildStartupLogFilePath(options?: {
21
21
  export declare function initializeStartupLogFile(): string | null;
22
22
 
23
23
  export declare function updateStartupLogIdentity(roleName: string, instanceName: string): void;
24
-
25
24
  export declare function appendStartupLogLine(level: LogLevel, message: string): void;
26
25
 
27
26
  export declare function getStartupLogFilePath(): string | null;
@@ -34,3 +33,5 @@ export declare const logger: {
34
33
  warn: (...args: unknown[]) => void;
35
34
  error: (...args: unknown[]) => void;
36
35
  };
36
+
37
+ export declare function isDebugEnabled(): boolean;
@@ -1,3 +1,3 @@
1
- import*as u from"node:fs";import*as f from"node:os";import*as o from"node:path";import{format as m}from"node:util";const d=new Date,E=new Set(["0","false","off","no"]),S=200,L="aws-mcp-node";let t,c=null,g=null;const l=[];function s(e,r=2){return String(e).padStart(r,"0")}function N(e){return`${e.getFullYear()}-${s(e.getMonth()+1)}`}function M(e){return[s(e.getDate()),"-",s(e.getHours()),s(e.getMinutes()),s(e.getSeconds()),s(e.getMilliseconds(),3)].join("")}function _(e){const r=new RegExp("[\0-]","g");return e.replace(/[<>:"/\\|?*]/g,"_").replace(r,"_").replace(/\s+/g," ").trim().replace(/[. ]+$/g,"")||"workspace"}function h(e={}){const r=e.logDir||o.join(e.homeDir||f.homedir(),".aws-bridge","log"),n=_(e.roleName||process.env.AWS_ROLE_NAME||"unknown-role"),i=_(e.instanceName||process.env.AWS_AGENT_ID||"unknown-instance"),a=e.startupTime||d,w=N(a),D=`${M(a)}.log`;return o.join(r,"agent",L,`${n}-${i}`,w,D)}function $(){if(t!==void 0)return t;const e=String(process.env.AWS_MCP_FILE_LOG||"").trim().toLowerCase();if(E.has(e))return t=null,null;try{return c=process.env.AWS_MCP_LOG_DIR||void 0||o.join(f.homedir(),".aws-bridge","log"),t=h({logDir:c,roleName:process.env.AWS_ROLE_NAME||void 0,instanceName:process.env.AWS_AGENT_ID||void 0}),u.mkdirSync(o.dirname(t),{recursive:!0}),t}catch(r){return t=null,c=null,console.warn("[Logger] \u65E0\u6CD5\u521B\u5EFA MCP \u542F\u52A8\u65E5\u5FD7\u6587\u4EF6:",r),null}}function x(e,r){if(t==null||!c)return;const n=t,i=h({logDir:c,roleName:e,instanceName:r,startupTime:d});if(n!==i)try{u.mkdirSync(o.dirname(i),{recursive:!0}),u.renameSync(n,i),t=i,console.log(`[Logger] MCP \u542F\u52A8\u65E5\u5FD7\u8DEF\u5F84\u5DF2\u66F4\u65B0: ${n} -> ${i}`);const a=o.join(c,"agent",L);A(o.dirname(n),a)}catch(a){console.warn("[Logger] \u65E0\u6CD5\u66F4\u65B0 MCP \u542F\u52A8\u65E5\u5FD7\u8EAB\u4EFD\u6807\u8BC6:",a)}}function A(e,r){let n=o.normalize(e);const i=o.normalize(r),a=o.parse(n).root;for(;n!==i&&n!==a;){try{u.rmdirSync(n)}catch{break}n=o.dirname(n)}}function P(e,r){if(t===void 0)return;const n=t;if(n)try{u.appendFileSync(n,`${new Date().toISOString()} [${e.toUpperCase()}] ${r}
2
- `,"utf8")}catch{t=null}}function I(){return t??null}function y(e,r){P(e,m(...r))}function p(e,r){const n={level:e,message:m(...r),timestamp:new Date().toISOString()};if(y(e,r),F(n),!!process.stderr.isTTY)try{switch(e){case"info":console.error(...r);break;case"warn":console.warn(...r);break;case"error":console.error(...r);break}}catch{}}function O(e){if(g=e,!!e)for(const r of l)e(r)}function F(e){l.push(e),l.length>S&&l.splice(0,l.length-S),g&&g(e)}const b={debug:(...e)=>{},info:(...e)=>p("info",e),warn:(...e)=>p("warn",e),error:(...e)=>p("error",e)};export{P as appendStartupLogLine,h as buildStartupLogFilePath,M as formatLogFileTimestamp,N as formatLogYearMonth,I as getStartupLogFilePath,$ as initializeStartupLogFile,b as logger,_ as sanitizeLogFileNameSegment,O as setMcpNodeLogSink,x as updateStartupLogIdentity};
1
+ import*as u from"node:fs";import*as f from"node:os";import*as i from"node:path";import{format as m}from"node:util";const d=new Date,N=new Set(["0","false","off","no"]),L=200,S="aws-mcp-node";let n,s=null,g=null;const l=[];function c(e,r=2){return String(e).padStart(r,"0")}function P(e){return`${e.getFullYear()}-${c(e.getMonth()+1)}`}function A(e){return[c(e.getDate()),"-",c(e.getHours()),c(e.getMinutes()),c(e.getSeconds()),c(e.getMilliseconds(),3)].join("")}function h(e){const r=new RegExp("[\0-]","g");return e.replace(/[<>:"/\\|?*]/g,"_").replace(r,"_").replace(/\s+/g," ").trim().replace(/[. ]+$/g,"")||"workspace"}function _(e={}){const r=e.logDir||i.join(e.homeDir||f.homedir(),".aws-bridge","log"),t=h(e.roleName||process.env.AWS_ROLE_NAME||"unknown-role"),o=h(e.instanceName||process.env.AWS_AGENT_ID||"unknown-instance"),a=e.startupTime||d,E=P(a),M=`${A(a)}.log`;return i.join(r,"agent",S,`${t}-${o}`,E,M)}function x(){if(n!==void 0)return n;const e=String(process.env.AWS_MCP_FILE_LOG||"").trim().toLowerCase();if(N.has(e))return n=null,null;try{return s=process.env.AWS_MCP_LOG_DIR||void 0||i.join(f.homedir(),".aws-bridge","log"),n=_({logDir:s,roleName:process.env.AWS_ROLE_NAME||void 0,instanceName:process.env.AWS_AGENT_ID||void 0}),u.mkdirSync(i.dirname(n),{recursive:!0}),n}catch(r){return n=null,s=null,console.warn("[Logger] \u65E0\u6CD5\u521B\u5EFA MCP \u542F\u52A8\u65E5\u5FD7\u6587\u4EF6:",r),null}}function I(e,r){if(n==null||!s)return;const t=n,o=_({logDir:s,roleName:e,instanceName:r,startupTime:d});if(t!==o)try{u.mkdirSync(i.dirname(o),{recursive:!0}),u.renameSync(t,o),n=o,console.log(`[Logger] MCP \u542F\u52A8\u65E5\u5FD7\u8DEF\u5F84\u5DF2\u66F4\u65B0: ${t} -> ${o}`);const a=i.join(s,"agent",S);y(i.dirname(t),a)}catch(a){console.warn("[Logger] \u65E0\u6CD5\u66F4\u65B0 MCP \u542F\u52A8\u65E5\u5FD7\u8EAB\u4EFD\u6807\u8BC6:",a)}}function y(e,r){let t=i.normalize(e);const o=i.normalize(r),a=i.parse(t).root;for(;t!==o&&t!==a;){try{u.rmdirSync(t)}catch{break}t=i.dirname(t)}}let w=Promise.resolve(),D=!1;function C(e,r){if(n===void 0)return;const t=n;if(!t)return;const o=`${new Date().toISOString()} [${e.toUpperCase()}] ${r}
2
+ `;w=w.then(async()=>{if(n!==null)try{await u.promises.appendFile(t,o,"utf8")}catch{if(n=null,!D){D=!0;try{console.error("[Logger] MCP \u542F\u52A8\u65E5\u5FD7\u6587\u4EF6\u5199\u5165\u5931\u8D25\uFF0C\u5DF2\u5173\u95ED\u6587\u4EF6\u65E5\u5FD7:",t)}catch{}}}})}function O(){return n??null}function F(e,r){C(e,m(...r))}function p(e,r){const t={level:e,message:m(...r),timestamp:new Date().toISOString()};if(F(e,r),$(t),!!process.stderr.isTTY)try{switch(e){case"info":console.error(...r);break;case"warn":console.warn(...r);break;case"error":console.error(...r);break}}catch{}}function T(e){if(g=e,!!e)for(const r of l)e(r)}function $(e){l.push(e),l.length>L&&l.splice(0,l.length-L),g&&g(e)}const k={debug:(...e)=>{},info:(...e)=>p("info",e),warn:(...e)=>p("warn",e),error:(...e)=>p("error",e)};function v(){return!1}export{C as appendStartupLogLine,_ as buildStartupLogFilePath,A as formatLogFileTimestamp,P as formatLogYearMonth,O as getStartupLogFilePath,x as initializeStartupLogFile,v as isDebugEnabled,k as logger,h as sanitizeLogFileNameSegment,T as setMcpNodeLogSink,I as updateStartupLogIdentity};
3
3