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
@@ -151,6 +151,8 @@ export interface MemoryStorePort {
151
151
  }
152
152
  export declare class MemoryStore implements MemoryStorePort {
153
153
  private readonly storePath;
154
+
155
+ private readonly domainJsonCache;
154
156
  constructor(storePath: string);
155
157
  private nowIso;
156
158
  private normalizeUri;
@@ -1,4 +1,4 @@
1
- const E=["recently_memory","agent_memory","project_memory","session_context"],h=["recently_memory","agent_memory"],C=64,R=32,Y=128,$=64,P=1024;function L(_){const e=String(_||"").trim().replace(/\\/g,"/");if(!e)return e;const r=e.startsWith("@/")?e.substring(1):e;return r.startsWith("./")?r:`./${r.replace(/^\/+/,"")}`}class T extends Error{details;constructor(e,r){super(e),this.name="MemoryCapacityError",this.details=r}}const b=/^([a-zA-Z_][a-zA-Z0-9_]*):\/\/(.*)$/,g="local",S=50,x=10;function D(_){const e=(_||"").trim();return e?e.split("|").map(r=>r.trim()).filter(Boolean).map(r=>r.split(/\s+/).filter(Boolean)):[]}function O(_,e){return _.length===0?!1:_.some(r=>r.every(i=>e.includes(i)))}class p{storePath;constructor(e){this.storePath=e}nowIso(){return new Date().toISOString()}normalizeUri(e){const r=String(e||"").trim(),i=b.exec(r);if(!i)throw new Error(`Invalid memory uri: ${e}`);const o=i[1],t=i[2];if(!o||!t)throw new Error(`Invalid memory uri: ${e}`);const n=o.toLowerCase(),c=t.replace(/^\/+|\/+$/g,"");if(!c)throw new Error(`Invalid memory uri path: ${e}`);return{uri:`${n}://${c}`,domain:n,path:c}}normalizeMemoryType(e,r=E){const i=String(e||"").trim();if(!r.includes(i))throw new Error(`Invalid memory_type: ${e}`);return i}ensureTypeMatch(e,r){if(r&&e.memory_type!==r)throw new Error(`Memory type mismatch: expected ${r}, actual ${e.memory_type}`)}async ensureStoreDir(){const{mkdir:e}=await import("node:fs/promises");await e(this.storePath,{recursive:!0})}async loadMemoryFile(e){const{readFile:r}=await import("node:fs/promises");try{const i=await r(e,"utf-8"),o=JSON.parse(i),t=o.by_uri&&typeof o.by_uri=="object"?o.by_uri:{},n={};for(const[c,a]of Object.entries(t)){const s=this.normalizeMemoryType(a.memory_type||"project_memory"),d=this.normalizeUri(a.uri||c),m=a;let l=m.memory_status;l||(m.update_status==="updating"?l="updating":m.recall_status==="recalling"?l="recalling":l="normal");const u={...a};delete u.update_status,delete u.recall_status,n[d.uri]={...u,uri:d.uri,domain:d.domain,path:d.path,memory_type:s,memory_status:l}}return{by_uri:n}}catch{return{by_uri:{}}}}async loadData(){const{readdir:e}=await import("node:fs/promises"),r=await import("node:path");try{const i=await e(this.storePath,{withFileTypes:!0}),o={by_uri:{}};for(const t of i){if(!t.isFile()||!t.name.endsWith(".json"))continue;const n=await this.loadMemoryFile(r.join(this.storePath,t.name));Object.assign(o.by_uri,n.by_uri)}return o}catch{return{by_uri:{}}}}async writeJsonAtomically(e,r){const{rename:i,rm:o,writeFile:t}=await import("node:fs/promises"),n=`${e}.${process.pid}.${Date.now()}.tmp`;try{await t(n,JSON.stringify(r,null,2),"utf-8"),await i(n,e)}catch(c){throw await o(n,{force:!0}),c}}async saveData(e){const{readdir:r,rm:i}=await import("node:fs/promises"),o=await import("node:path");await this.ensureStoreDir();const t=new Map;for(const a of Object.values(e.by_uri)){const s=t.get(a.domain)??{by_uri:{}};s.by_uri[a.uri]=a,t.set(a.domain,s)}for(const[a,s]of t.entries())await this.writeJsonAtomically(o.join(this.storePath,`${a}.json`),s);const n=new Set([...t.keys()].map(a=>`${a}.json`)),c=await r(this.storePath,{withFileTypes:!0});for(const a of c)a.isFile()&&a.name.endsWith(".json")&&!n.has(a.name)&&await i(o.join(this.storePath,a.name),{force:!0})}createEmptyStats(){return{total:0,listable:{count:0,limit:64,hardLimit:128,exceeded:!1,hardExceeded:!1},by_type:{recently_memory:{count:0,limit:32,hardLimit:64,exceeded:!1,hardExceeded:!1,listable:!0,domainCount:0,by_domain:{}},agent_memory:{count:0,limit:32,hardLimit:64,exceeded:!1,hardExceeded:!1,listable:!0,domainCount:0,by_domain:{}},project_memory:{count:0,limit:null,hardLimit:null,exceeded:!1,hardExceeded:!1,listable:!1,domainCount:0,by_domain:{}},session_context:{count:0,limit:null,hardLimit:1024,exceeded:!1,hardExceeded:!1,listable:!1,domainCount:0,by_domain:{}}}}}calculateStats(e){const r=this.createEmptyStats();for(const i of Object.values(e.by_uri)){r.total+=1;const o=r.by_type[i.memory_type];o.count+=1;const t=a=>h.includes(a)?32:null,n=a=>h.includes(a)?64:a==="session_context"?1024:null,c=o.by_domain[i.domain]??{count:0,limit:t(i.memory_type),hardLimit:n(i.memory_type),exceeded:!1,hardExceeded:!1};c.count+=1,o.by_domain[i.domain]=c,h.includes(i.memory_type)&&(r.listable.count+=1)}r.listable.exceeded=r.listable.count>r.listable.limit,r.listable.hardExceeded=r.listable.count>=r.listable.hardLimit;for(const i of E){const o=r.by_type[i];o.domainCount=Object.keys(o.by_domain).length,o.limit!==null&&o.hardLimit!==null&&(o.exceeded=o.domainCount>o.limit,o.hardExceeded=o.domainCount>=o.hardLimit);for(const t of Object.values(o.by_domain))t.limit!==null&&t.hardLimit!==null&&(t.exceeded=t.count>t.limit,t.hardExceeded=t.count>=t.hardLimit)}return r}generateId(e){return`${e.replace(/[^a-zA-Z0-9]+/g,"_").replace(/^_+|_+$/g,"")}_${Date.now().toString(36)}`}ensureListableMemoryCapacity(e,r,i){if(!h.includes(r))return;const t=this.calculateStats(e).by_type[r],n=t.by_domain[i.domain];if(!n&&t.domainCount>=64)throw new T(`Cannot create ${r}: hard domain type limit 64 reached. Please delete an existing ${r} domain type before creating a new ${r}.`,{code:"MEMORY_TYPE_LIMIT_REACHED",memory_type:r,limit:64,current:t.domainCount,recommended_actions:[`list_memories({ memory_type: '${r}' })`,`delete_memory({ uri, memory_type: '${r}' })`]});if(n&&n.count>=64)throw new T(`Cannot create ${r}: hard memory limit 64 reached under domain ${i.domain}. Please delete or archive existing ${i.domain}://${r} memories before creating a new one.`,{code:"MEMORY_TYPE_LIMIT_REACHED",memory_type:r,domain:i.domain,limit:64,current:n.count,recommended_actions:[`list_memories({ memory_type: '${r}' })`,`delete_memory({ uri, memory_type: '${r}' })`]})}ensureSessionContextCapacity(e,r,i){if(r!=="session_context")return;const o=Object.values(e.by_uri).filter(t=>t.memory_type==="session_context"&&t.domain===i.domain).length;if(o>=1024)throw new T(`Cannot create session_context: hard limit 1024 reached under domain ${i.domain}. Please delete existing session_context memories before creating a new one.`,{code:"MEMORY_TYPE_LIMIT_REACHED",memory_type:r,domain:i.domain,limit:1024,current:o,recommended_actions:["list_memories({ memory_type: 'session_context' })","delete_memory({ uri, memory_type: 'session_context' })"]})}async getStats(){const e=await this.loadData();return this.calculateStats(e)}static calcAgentMemoryExpiresAt(){return new Date(Date.now()+432e5).toISOString()}static isExpirableType(e){return e==="agent_memory"||e==="recently_memory"}async createMemory(e){const r=this.normalizeMemoryType(e.memory_type),i=this.normalizeUri(e.uri),o=await this.loadData();if(o.by_uri[i.uri])throw new Error(`Memory already exists: ${i.uri}`);this.ensureListableMemoryCapacity(o,r,i),this.ensureSessionContextCapacity(o,r,i);const t=this.nowIso(),n={id:this.generateId(i.uri),uri:i.uri,domain:i.domain,path:i.path,title:e.title||void 0,content:String(e.content||""),memory_type:r,createdAt:t,updatedAt:t,version:1,keywords:e.keywords,bound_files:e.bound_files,file_md5_map:e.file_md5_map||void 0,updating_agent_id:void 0,last_check_time:e.last_check_time||void 0,expiresAt:e.expiresAt||(p.isExpirableType(r)?p.calcAgentMemoryExpiresAt():void 0),memory_status:"normal"};return o.by_uri[i.uri]=n,await this.saveData(o),n}async readMemory(e){const r=this.normalizeUri(e.uri),i=typeof e.memory_type=="string"?this.normalizeMemoryType(e.memory_type):void 0,t=(await this.loadData()).by_uri[r.uri]??null;return t?(this.ensureTypeMatch(t,i),t):null}async updateMemory(e){const r=this.normalizeUri(e.uri),i=typeof e.memory_type=="string"?this.normalizeMemoryType(e.memory_type):void 0,o=await this.loadData(),t=o.by_uri[r.uri];if(!t)throw new Error(`Memory not found: ${r.uri}`);this.ensureTypeMatch(t,i);let n=t.content;if(typeof e.old_string=="string"&&typeof e.new_string=="string"){const m=e.old_string;if(!m)throw new Error("old_string cannot be empty when replacing");const l=n.split(m).length-1;if(l===0)throw new Error("old_string not found in memory content");if(l>1)throw new Error("old_string appears multiple times; replace is ambiguous");n=n.replace(m,e.new_string)}typeof e.append=="string"&&e.append.length>0&&(n=`${n}${e.append}`);const c=n!==t.content||typeof e.title=="string"&&e.title!==t.title,a=this.nowIso();let s=t.expiresAt;if(p.isExpirableType(t.memory_type))if(t.memory_type==="recently_memory")s=new Date(Date.now()+24*60*60*1e3).toISOString();else{const m=t.expiresAt?new Date(t.expiresAt):null,l=t.updatedAt?new Date(t.updatedAt):null,u=m&&l&&!isNaN(l.getTime())?Math.max(12*60*60*1e3,m.getTime()-l.getTime()):12*60*60*1e3;s=new Date(Date.now()+u*2).toISOString()}e.expiresAt!==void 0&&(s=e.expiresAt);const d={...t,content:n,title:e.title!==void 0?e.title:t.title,updatedAt:a,version:t.version+1,keywords:e.keywords!==void 0?e.keywords:t.keywords,bound_files:e.bound_files!==void 0?e.bound_files:t.bound_files,file_md5_map:e.file_md5_map!==void 0?e.file_md5_map:e.bound_files!==void 0?void 0:t.file_md5_map,memory_status:e.memory_status!==void 0?e.memory_status:t.memory_status==="updating"?"normal":t.memory_status||"normal",updating_agent_id:e.memory_status!==void 0?e.updating_agent_id||void 0:t.memory_status==="updating"?void 0:t.updating_agent_id,last_check_time:e.last_check_time!==void 0?e.last_check_time:t.last_check_time,expiresAt:s};return o.by_uri[r.uri]=d,await this.saveData(o),d}async deleteMemory(e){const r=this.normalizeUri(e.uri),i=typeof e.memory_type=="string"?this.normalizeMemoryType(e.memory_type):void 0,o=await this.loadData(),t=o.by_uri[r.uri];return t?(this.ensureTypeMatch(t,i),delete o.by_uri[r.uri],await this.saveData(o),!0):!1}async listExpiredRecentlyMemories(){const e=await this.loadData(),r=new Date,i=[];for(const o of Object.values(e.by_uri))o.memory_type!=="agent_memory"&&o.memory_type!=="recently_memory"||o.expiresAt&&(new Date(o.expiresAt)>r||o.memory_status==="recalling"&&o.updating_agent_id!==g||i.push(o));return i.sort((o,t)=>o.expiresAt.localeCompare(t.expiresAt))}async searchMemory(e){const r=await this.loadData(),o=String(e.query||"").trim().toLowerCase(),t=e.memory_type?this.normalizeMemoryType(e.memory_type):void 0,n=typeof e.limit=="number"&&e.limit>0?e.limit:10,c=e.keywords?.map(l=>l.toLowerCase()),a=e.keyword_mode==="all"?"all":"any",s=D(o);if(s.length===0&&(!c||c.length===0))return{query:o,results:[]};const d=new Set,m=[];for(const l of Object.values(r.by_uri)){if(t&&l.memory_type!==t||d.has(l.id))continue;let u=0;if(c&&c.length>0&&l.keywords){const f=l.keywords.map(y=>y.toLowerCase());if(a==="all"){if(c.every(w=>f.includes(w)))u+=10*c.length;else if(s.length===0)continue}else for(const y of c)f.includes(y)&&(u+=10)}if(s.length>0){const f=`${l.uri}
2
- ${l.title||""}
3
- ${l.content}`.toLowerCase();if(!O(s,f)&&u===0)continue;for(const y of s){const w=y.filter(M=>f.includes(M)).length;if(w>0){const M=l.uri.toLowerCase(),I=y.filter(A=>M.includes(A)).length;u+=w+I}}}u!==0&&(d.add(l.id),m.push({score:u,record:l}))}return m.sort((l,u)=>u.score!==l.score?u.score-l.score:u.record.updatedAt.localeCompare(l.record.updatedAt)),{query:o,results:m.slice(0,n).map(l=>l.record)}}async listByType(e){const r=e==="session_context"||e==="project_memory"?E:h,i=this.normalizeMemoryType(e,r),o=await this.loadData(),t=new Set,n=[];for(const c of Object.values(o.by_uri))c.memory_type===i&&(t.has(c.id)||(t.add(c.id),n.push(c)));return n.sort((c,a)=>a.updatedAt.localeCompare(c.updatedAt)),n}async listByFile(e,r){const i=await this.loadData(),o=typeof r=="object"&&r!==null?r.memory_type:r,t=o?this.normalizeMemoryType(o):void 0,n=L(e),c=new Set,a=[];for(const s of Object.values(i.by_uri))t&&s.memory_type!==t||c.has(s.id)||s.bound_files&&s.bound_files.length>0&&s.bound_files.some(m=>L(m)===n)&&(c.add(s.id),a.push(s));return a.sort((s,d)=>d.updatedAt.localeCompare(s.updatedAt)),a}async markExpiredMemoriesRecalling(e){const r=await this.listExpiredRecentlyMemories();if(r.length===0)return{marked:0,uris:[]};const i=r.filter(s=>s.memory_status!=="recalling"),o=e?i.filter(s=>e.includes(s.uri)):i.slice(0,S);if(o.length===0){const s=r.filter(d=>d.memory_status==="recalling").map(d=>d.uri);return{marked:s.length,uris:s}}const t=await this.loadData(),n=this.nowIso(),c=new Date(Date.now()+x*60*1e3).toISOString(),a=[];for(const s of o){const d=t.by_uri[s.uri];d&&(d.memory_status="recalling",d.updating_agent_id=g,d.lease_expires_at=c,d.updatedAt=n,d.version=(d.version||1)+1,a.push(s.uri))}return a.length>0&&await this.saveData(t),{marked:a.length,uris:a}}async clearRecallingExpiredMemories(e){const r=await this.loadData(),i=new Date,o=[];for(const t of Object.values(r.by_uri))p.isExpirableType(t.memory_type)&&t.memory_status==="recalling"&&t.updating_agent_id===g&&t.expiresAt&&(new Date(t.expiresAt)>i||o.push(t.uri));if(e){const t=new Set(e),n=o.filter(c=>t.has(c));o.length=0,o.push(...n)}if(o.length===0)return{deleted:0,uris:[]};for(const t of o)delete r.by_uri[t];return await this.saveData(r),{deleted:o.length,uris:o}}async claimMemoryUpdate(e,r,i){throw new Error("claimMemoryUpdate not supported in local MemoryStore")}async renewMemoryLease(e){throw new Error("renewMemoryLease not supported in local MemoryStore")}async releaseMemoryClaim(e){throw new Error("releaseMemoryClaim not supported in local MemoryStore")}async releaseAllMemoryClaims(){throw new Error("releaseAllMemoryClaims not supported in local MemoryStore")}async getMyClaimedUris(){throw new Error("getMyClaimedUris not supported in local MemoryStore")}}export{T as MemoryCapacityError,p as MemoryStore,L as normalizeBoundFilePath};
1
+ const E=["recently_memory","agent_memory","project_memory","session_context"],h=["recently_memory","agent_memory"],C=64,R=32,Y=128,$=64,P=1024;function L(y){const e=String(y||"").trim().replace(/\\/g,"/");if(!e)return e;const t=e.startsWith("@/")?e.substring(1):e;return t.startsWith("./")?t:`./${t.replace(/^\/+/,"")}`}class T extends Error{details;constructor(e,t){super(e),this.name="MemoryCapacityError",this.details=t}}const b=/^([a-zA-Z_][a-zA-Z0-9_]*):\/\/(.*)$/,g="local",S=50,x=10;function D(y){const e=(y||"").trim();return e?e.split("|").map(t=>t.trim()).filter(Boolean).map(t=>t.split(/\s+/).filter(Boolean)):[]}function O(y,e){return y.length===0?!1:y.some(t=>t.every(i=>e.includes(i)))}class p{storePath;domainJsonCache=new Map;constructor(e){this.storePath=e}nowIso(){return new Date().toISOString()}normalizeUri(e){const t=String(e||"").trim(),i=b.exec(t);if(!i)throw new Error(`Invalid memory uri: ${e}`);const o=i[1],r=i[2];if(!o||!r)throw new Error(`Invalid memory uri: ${e}`);const a=o.toLowerCase(),s=r.replace(/^\/+|\/+$/g,"");if(!s)throw new Error(`Invalid memory uri path: ${e}`);return{uri:`${a}://${s}`,domain:a,path:s}}normalizeMemoryType(e,t=E){const i=String(e||"").trim();if(!t.includes(i))throw new Error(`Invalid memory_type: ${e}`);return i}ensureTypeMatch(e,t){if(t&&e.memory_type!==t)throw new Error(`Memory type mismatch: expected ${t}, actual ${e.memory_type}`)}async ensureStoreDir(){const{mkdir:e}=await import("node:fs/promises");await e(this.storePath,{recursive:!0})}async loadMemoryFile(e){const{readFile:t}=await import("node:fs/promises");try{const i=await t(e,"utf-8"),o=JSON.parse(i),r=o.by_uri&&typeof o.by_uri=="object"?o.by_uri:{},a={};for(const[s,d]of Object.entries(r)){const n=this.normalizeMemoryType(d.memory_type||"project_memory"),l=this.normalizeUri(d.uri||s),m=d;let c=m.memory_status;c||(m.update_status==="updating"?c="updating":m.recall_status==="recalling"?c="recalling":c="normal");const u={...d};delete u.update_status,delete u.recall_status,a[l.uri]={...u,uri:l.uri,domain:l.domain,path:l.path,memory_type:n,memory_status:c}}return{by_uri:a}}catch{return{by_uri:{}}}}async loadData(){const{readdir:e}=await import("node:fs/promises"),t=await import("node:path");try{const i=await e(this.storePath,{withFileTypes:!0}),o={by_uri:{}};for(const r of i){if(!r.isFile()||!r.name.endsWith(".json"))continue;const a=await this.loadMemoryFile(t.join(this.storePath,r.name));Object.assign(o.by_uri,a.by_uri)}return o}catch{return{by_uri:{}}}}async writeJsonAtomically(e,t,i=JSON.stringify(t,null,2)){const{rename:o,rm:r,writeFile:a}=await import("node:fs/promises"),s=`${e}.${process.pid}.${Date.now()}.tmp`;try{await a(s,i,"utf-8"),await o(s,e)}catch(d){throw await r(s,{force:!0}),d}}async saveData(e){const{readFile:t,readdir:i,rm:o}=await import("node:fs/promises"),r=await import("node:path");await this.ensureStoreDir();const a=new Map;for(const n of Object.values(e.by_uri)){const l=a.get(n.domain)??{by_uri:{}};l.by_uri[n.uri]=n,a.set(n.domain,l)}for(const[n,l]of a.entries()){const m=r.join(this.storePath,`${n}.json`),c=JSON.stringify(l,null,2);if(this.domainJsonCache.get(m)===c)continue;let _;try{_=await t(m,"utf-8")}catch{_=void 0}if(_===c){this.domainJsonCache.set(m,c);continue}await this.writeJsonAtomically(m,l,c),this.domainJsonCache.set(m,c)}const s=new Set([...a.keys()].map(n=>`${n}.json`)),d=await i(this.storePath,{withFileTypes:!0});for(const n of d)if(n.isFile()&&n.name.endsWith(".json")&&!s.has(n.name)){const l=r.join(this.storePath,n.name);await o(l,{force:!0}),this.domainJsonCache.delete(l)}}createEmptyStats(){return{total:0,listable:{count:0,limit:64,hardLimit:128,exceeded:!1,hardExceeded:!1},by_type:{recently_memory:{count:0,limit:32,hardLimit:64,exceeded:!1,hardExceeded:!1,listable:!0,domainCount:0,by_domain:{}},agent_memory:{count:0,limit:32,hardLimit:64,exceeded:!1,hardExceeded:!1,listable:!0,domainCount:0,by_domain:{}},project_memory:{count:0,limit:null,hardLimit:null,exceeded:!1,hardExceeded:!1,listable:!1,domainCount:0,by_domain:{}},session_context:{count:0,limit:null,hardLimit:1024,exceeded:!1,hardExceeded:!1,listable:!1,domainCount:0,by_domain:{}}}}}calculateStats(e){const t=this.createEmptyStats();for(const i of Object.values(e.by_uri)){t.total+=1;const o=t.by_type[i.memory_type];o.count+=1;const r=d=>h.includes(d)?32:null,a=d=>h.includes(d)?64:d==="session_context"?1024:null,s=o.by_domain[i.domain]??{count:0,limit:r(i.memory_type),hardLimit:a(i.memory_type),exceeded:!1,hardExceeded:!1};s.count+=1,o.by_domain[i.domain]=s,h.includes(i.memory_type)&&(t.listable.count+=1)}t.listable.exceeded=t.listable.count>t.listable.limit,t.listable.hardExceeded=t.listable.count>=t.listable.hardLimit;for(const i of E){const o=t.by_type[i];o.domainCount=Object.keys(o.by_domain).length,o.limit!==null&&o.hardLimit!==null&&(o.exceeded=o.domainCount>o.limit,o.hardExceeded=o.domainCount>=o.hardLimit);for(const r of Object.values(o.by_domain))r.limit!==null&&r.hardLimit!==null&&(r.exceeded=r.count>r.limit,r.hardExceeded=r.count>=r.hardLimit)}return t}generateId(e){return`${e.replace(/[^a-zA-Z0-9]+/g,"_").replace(/^_+|_+$/g,"")}_${Date.now().toString(36)}`}ensureListableMemoryCapacity(e,t,i){if(!h.includes(t))return;const r=this.calculateStats(e).by_type[t],a=r.by_domain[i.domain];if(!a&&r.domainCount>=64)throw new T(`Cannot create ${t}: hard domain type limit 64 reached. Please delete an existing ${t} domain type before creating a new ${t}.`,{code:"MEMORY_TYPE_LIMIT_REACHED",memory_type:t,limit:64,current:r.domainCount,recommended_actions:[`list_memories({ memory_type: '${t}' })`,`delete_memory({ uri, memory_type: '${t}' })`]});if(a&&a.count>=64)throw new T(`Cannot create ${t}: hard memory limit 64 reached under domain ${i.domain}. Please delete or archive existing ${i.domain}://${t} memories before creating a new one.`,{code:"MEMORY_TYPE_LIMIT_REACHED",memory_type:t,domain:i.domain,limit:64,current:a.count,recommended_actions:[`list_memories({ memory_type: '${t}' })`,`delete_memory({ uri, memory_type: '${t}' })`]})}ensureSessionContextCapacity(e,t,i){if(t!=="session_context")return;const o=Object.values(e.by_uri).filter(r=>r.memory_type==="session_context"&&r.domain===i.domain).length;if(o>=1024)throw new T(`Cannot create session_context: hard limit 1024 reached under domain ${i.domain}. Please delete existing session_context memories before creating a new one.`,{code:"MEMORY_TYPE_LIMIT_REACHED",memory_type:t,domain:i.domain,limit:1024,current:o,recommended_actions:["list_memories({ memory_type: 'session_context' })","delete_memory({ uri, memory_type: 'session_context' })"]})}async getStats(){const e=await this.loadData();return this.calculateStats(e)}static calcAgentMemoryExpiresAt(){return new Date(Date.now()+432e5).toISOString()}static isExpirableType(e){return e==="agent_memory"||e==="recently_memory"}async createMemory(e){const t=this.normalizeMemoryType(e.memory_type),i=this.normalizeUri(e.uri),o=await this.loadData();if(o.by_uri[i.uri])throw new Error(`Memory already exists: ${i.uri}`);this.ensureListableMemoryCapacity(o,t,i),this.ensureSessionContextCapacity(o,t,i);const r=this.nowIso(),a={id:this.generateId(i.uri),uri:i.uri,domain:i.domain,path:i.path,title:e.title||void 0,content:String(e.content||""),memory_type:t,createdAt:r,updatedAt:r,version:1,keywords:e.keywords,bound_files:e.bound_files,file_md5_map:e.file_md5_map||void 0,updating_agent_id:void 0,last_check_time:e.last_check_time||void 0,expiresAt:e.expiresAt||(p.isExpirableType(t)?p.calcAgentMemoryExpiresAt():void 0),memory_status:"normal"};return o.by_uri[i.uri]=a,await this.saveData(o),a}async readMemory(e){const t=this.normalizeUri(e.uri),i=typeof e.memory_type=="string"?this.normalizeMemoryType(e.memory_type):void 0,r=(await this.loadData()).by_uri[t.uri]??null;return r?(this.ensureTypeMatch(r,i),r):null}async updateMemory(e){const t=this.normalizeUri(e.uri),i=typeof e.memory_type=="string"?this.normalizeMemoryType(e.memory_type):void 0,o=await this.loadData(),r=o.by_uri[t.uri];if(!r)throw new Error(`Memory not found: ${t.uri}`);this.ensureTypeMatch(r,i);let a=r.content;if(typeof e.old_string=="string"&&typeof e.new_string=="string"){const m=e.old_string;if(!m)throw new Error("old_string cannot be empty when replacing");const c=a.split(m).length-1;if(c===0)throw new Error("old_string not found in memory content");if(c>1)throw new Error("old_string appears multiple times; replace is ambiguous");a=a.replace(m,e.new_string)}typeof e.append=="string"&&e.append.length>0&&(a=`${a}${e.append}`);const s=a!==r.content||typeof e.title=="string"&&e.title!==r.title,d=this.nowIso();let n=r.expiresAt;if(p.isExpirableType(r.memory_type))if(r.memory_type==="recently_memory")n=new Date(Date.now()+24*60*60*1e3).toISOString();else{const m=r.expiresAt?new Date(r.expiresAt):null,c=r.updatedAt?new Date(r.updatedAt):null,u=m&&c&&!isNaN(c.getTime())?Math.max(12*60*60*1e3,m.getTime()-c.getTime()):12*60*60*1e3;n=new Date(Date.now()+u*2).toISOString()}e.expiresAt!==void 0&&(n=e.expiresAt);const l={...r,content:a,title:e.title!==void 0?e.title:r.title,updatedAt:d,version:r.version+1,keywords:e.keywords!==void 0?e.keywords:r.keywords,bound_files:e.bound_files!==void 0?e.bound_files:r.bound_files,file_md5_map:e.file_md5_map!==void 0?e.file_md5_map:e.bound_files!==void 0?void 0:r.file_md5_map,memory_status:e.memory_status!==void 0?e.memory_status:r.memory_status==="updating"?"normal":r.memory_status||"normal",updating_agent_id:e.memory_status!==void 0?e.updating_agent_id||void 0:r.memory_status==="updating"?void 0:r.updating_agent_id,last_check_time:e.last_check_time!==void 0?e.last_check_time:r.last_check_time,expiresAt:n};return o.by_uri[t.uri]=l,await this.saveData(o),l}async deleteMemory(e){const t=this.normalizeUri(e.uri),i=typeof e.memory_type=="string"?this.normalizeMemoryType(e.memory_type):void 0,o=await this.loadData(),r=o.by_uri[t.uri];return r?(this.ensureTypeMatch(r,i),delete o.by_uri[t.uri],await this.saveData(o),!0):!1}async listExpiredRecentlyMemories(){const e=await this.loadData(),t=new Date,i=[];for(const o of Object.values(e.by_uri))o.memory_type!=="agent_memory"&&o.memory_type!=="recently_memory"||o.expiresAt&&(new Date(o.expiresAt)>t||o.memory_status==="recalling"&&o.updating_agent_id!==g||i.push(o));return i.sort((o,r)=>o.expiresAt.localeCompare(r.expiresAt))}async searchMemory(e){const t=await this.loadData(),o=String(e.query||"").trim().toLowerCase(),r=e.memory_type?this.normalizeMemoryType(e.memory_type):void 0,a=typeof e.limit=="number"&&e.limit>0?e.limit:10,s=e.keywords?.map(c=>c.toLowerCase()),d=e.keyword_mode==="all"?"all":"any",n=D(o);if(n.length===0&&(!s||s.length===0))return{query:o,results:[]};const l=new Set,m=[];for(const c of Object.values(t.by_uri)){if(r&&c.memory_type!==r||l.has(c.id))continue;let u=0;if(s&&s.length>0&&c.keywords){const _=c.keywords.map(f=>f.toLowerCase());if(d==="all"){if(s.every(w=>_.includes(w)))u+=10*s.length;else if(n.length===0)continue}else for(const f of s)_.includes(f)&&(u+=10)}if(n.length>0){const _=`${c.uri}
2
+ ${c.title||""}
3
+ ${c.content}`.toLowerCase();if(!O(n,_)&&u===0)continue;for(const f of n){const w=f.filter(M=>_.includes(M)).length;if(w>0){const M=c.uri.toLowerCase(),I=f.filter(A=>M.includes(A)).length;u+=w+I}}}u!==0&&(l.add(c.id),m.push({score:u,record:c}))}return m.sort((c,u)=>u.score!==c.score?u.score-c.score:u.record.updatedAt.localeCompare(c.record.updatedAt)),{query:o,results:m.slice(0,a).map(c=>c.record)}}async listByType(e){const t=e==="session_context"||e==="project_memory"?E:h,i=this.normalizeMemoryType(e,t),o=await this.loadData(),r=new Set,a=[];for(const s of Object.values(o.by_uri))s.memory_type===i&&(r.has(s.id)||(r.add(s.id),a.push(s)));return a.sort((s,d)=>d.updatedAt.localeCompare(s.updatedAt)),a}async listByFile(e,t){const i=await this.loadData(),o=typeof t=="object"&&t!==null?t.memory_type:t,r=o?this.normalizeMemoryType(o):void 0,a=L(e),s=new Set,d=[];for(const n of Object.values(i.by_uri))r&&n.memory_type!==r||s.has(n.id)||n.bound_files&&n.bound_files.length>0&&n.bound_files.some(m=>L(m)===a)&&(s.add(n.id),d.push(n));return d.sort((n,l)=>l.updatedAt.localeCompare(n.updatedAt)),d}async markExpiredMemoriesRecalling(e){const t=await this.listExpiredRecentlyMemories();if(t.length===0)return{marked:0,uris:[]};const i=t.filter(n=>n.memory_status!=="recalling"),o=e?i.filter(n=>e.includes(n.uri)):i.slice(0,S);if(o.length===0){const n=t.filter(l=>l.memory_status==="recalling").map(l=>l.uri);return{marked:n.length,uris:n}}const r=await this.loadData(),a=this.nowIso(),s=new Date(Date.now()+x*60*1e3).toISOString(),d=[];for(const n of o){const l=r.by_uri[n.uri];l&&(l.memory_status="recalling",l.updating_agent_id=g,l.lease_expires_at=s,l.updatedAt=a,l.version=(l.version||1)+1,d.push(n.uri))}return d.length>0&&await this.saveData(r),{marked:d.length,uris:d}}async clearRecallingExpiredMemories(e){const t=await this.loadData(),i=new Date,o=[];for(const r of Object.values(t.by_uri))p.isExpirableType(r.memory_type)&&r.memory_status==="recalling"&&r.updating_agent_id===g&&r.expiresAt&&(new Date(r.expiresAt)>i||o.push(r.uri));if(e){const r=new Set(e),a=o.filter(s=>r.has(s));o.length=0,o.push(...a)}if(o.length===0)return{deleted:0,uris:[]};for(const r of o)delete t.by_uri[r];return await this.saveData(t),{deleted:o.length,uris:o}}async claimMemoryUpdate(e,t,i){throw new Error("claimMemoryUpdate not supported in local MemoryStore")}async renewMemoryLease(e){throw new Error("renewMemoryLease not supported in local MemoryStore")}async releaseMemoryClaim(e){throw new Error("releaseMemoryClaim not supported in local MemoryStore")}async releaseAllMemoryClaims(){throw new Error("releaseAllMemoryClaims not supported in local MemoryStore")}async getMyClaimedUris(){throw new Error("getMyClaimedUris not supported in local MemoryStore")}}export{T as MemoryCapacityError,p as MemoryStore,L as normalizeBoundFilePath};
4
4
 
@@ -1,2 +1,2 @@
1
- import{logger as r}from"./logger.js";import{meetingDebugFingerprint as h,meetingDebugFingerprints as c,meetingDebugLog as f}from"./meeting-debug-log.js";const u=500;function a(n){if(n.msgId===void 0||n.msgId===null)return;const e=n.channel;if(e==="meeting")return`meeting:${n.msgId}`;if(e==="meeting_invite")return`meeting_invite:${n.msgId}`;if(e==="notification")return`notification:${n.msgId}`;if(typeof n.msgId=="number"){const s=n.roomId;return`group:${typeof s=="string"?s:""}:${n.msgId}`}return n.msgId}class M{buffer=[];resolvers=[];onMessageArrived=null;isPolling=!1;seenMsgIds=new Map;setOnMessageArrived(e){this.onMessageArrived=e}setIsPolling(e){this.isPolling=e}markSeen(e){const s=a(e);s!==void 0&&(this.seenMsgIds.set(s,Date.now()),this.cleanupSeenMsgIds())}isDuplicate(e){const s=a(e);return s===void 0?!1:this.seenMsgIds.has(s)?!0:(this.seenMsgIds.set(s,Date.now()),this.cleanupSeenMsgIds(),!1)}cleanupSeenMsgIds(){if(this.seenMsgIds.size<=u)return;let e=0;const s=this.seenMsgIds.size-u;for(const t of this.seenMsgIds.keys()){if(e>=s)break;this.seenMsgIds.delete(t),e++}}push(e){if(this.isDuplicate(e)){r.info(`[MessageBuffer] \u5FFD\u7565\u91CD\u590D\u6D88\u606F\uFF0CmsgId: ${e.msgId}`);const s=e.channel;(s==="meeting"||s==="meeting_invite")&&f("buffer.push.duplicate-blocked",`${h(e)} content=${String(e.content??"").slice(0,120)}`);return}this.buffer.push(e),r.info(`[MessageBuffer] \u6D88\u606F\u5165\u7F13\u51B2\u533A\uFF0C\u5F53\u524D\u6570\u91CF: ${this.buffer.length}`);{const s=e.channel;(s==="meeting"||s==="meeting_invite")&&f("buffer.push.enqueued",`${h(e)} content=${String(e.content??"").slice(0,120)}`)}this.isPolling&&this.onMessageArrived&&(r.info("[MessageBuffer] \u68C0\u6D4B\u5230 poll \u7B49\u5F85\u4E2D\uFF0C\u89E6\u53D1\u6D88\u606F\u5230\u8FBE\u56DE\u8C03"),this.onMessageArrived()),this.tryDispatch()}setProfileMessage(e){r.info(`[MessageBuffer] \u6536\u5230 Profile \u63A8\u9001\uFF0CdisplayName: ${e.displayName}\u3002\u8EAB\u4EFD\u4FE1\u606F\u8BF7\u901A\u8FC7 get_profile \u83B7\u53D6\u3002`)}removeProfileMessage(){r.info("[MessageBuffer] removeProfileMessage \u88AB\u8C03\u7528\uFF0C\u5F53\u524D\u65E0\u9700\u79FB\u9664\u672A\u8BFB\u8EAB\u4EFD\u6D88\u606F")}hasProfileMessage(){return!1}wakeUpWaiters(){if(f("buffer.wakeUpWaiters",`bufferSize=${this.buffer.length} waiters=${this.resolvers.length}`),this.tryDispatch(),this.buffer.length===0&&this.resolvers.length>0){const e=this.resolvers.shift();e&&(this.updatePollingState(),r.info("[MessageBuffer] wakeUpWaiters: \u5524\u9192 poll \u8D70 hydrate \u91CD\u67E5"),e({directMessages:[],groupMessages:[]}))}}getProfileMessage(){return null}updatePollingState(){this.isPolling=this.resolvers.length>0}poll(e){if(r.info(`[MessageBuffer] poll() \u88AB\u8C03\u7528\uFF0Cbuffer: ${this.buffer.length}${e?`\uFF0C\u8D85\u65F6: ${e}ms`:""}`),this.buffer.length>0){const s=this.consumeAll();return r.info(`[MessageBuffer] poll \u7ACB\u5373\u8FD4\u56DE\uFF0C\u79C1\u804A: ${s.directMessages.length}\uFF0C\u7FA4\u804A: ${s.groupMessages.length}`),Promise.resolve(s)}return this.resolvers.length===0&&(this.isPolling=!0),new Promise(s=>{let t=null,i=!1;const o=l=>{if(i)return;i=!0;const g=this.resolvers.indexOf(o);g>-1&&this.resolvers.splice(g,1),t&&(clearTimeout(t),t=null),this.updatePollingState(),r.info(`[MessageBuffer] poll \u6536\u5230\u6D88\u606F\uFF0C\u79C1\u804A: ${l.directMessages.length}\uFF0C\u7FA4\u804A: ${l.groupMessages.length}`),s(l)};this.resolvers.push(o),this.tryDispatch(),e&&e>0&&(t=setTimeout(()=>{if(i)return;i=!0;const l=this.resolvers.indexOf(o);l>-1&&this.resolvers.splice(l,1),this.updatePollingState(),r.info(`[MessageBuffer] poll \u8D85\u65F6\uFF08${e}ms\uFF09\uFF0C\u8FD4\u56DE\u7A7A\u6D88\u606F`),s({directMessages:[],groupMessages:[]})},e))})}get(){if(this.buffer.length>0){const e=this.consumeAll();return r.info(`[MessageBuffer] get \u8FD4\u56DE\u6D88\u606F\uFF0C\u79C1\u804A: ${e.directMessages.length}\uFF0C\u7FA4\u804A: ${e.groupMessages.length}`),e}return{directMessages:[],groupMessages:[]}}takeForceDirectMessages(){const e=[],s=[];for(const t of this.buffer)this.isDirectMessage(t)&&t.force===!0?(this.markSeen(t),e.push(t)):s.push(t);return this.buffer=s,e.length>0&&(r.info(`[MessageBuffer] takeForceDirectMessages \u53D6\u8D70\u5F3A\u5236\u79C1\u4FE1 ${e.length} \u6761\uFF0C\u5269\u4F59 ${s.length} \u6761`),this.tryDispatch()),{directMessages:e,groupMessages:[]}}requeue(e){const s=[...e.directMessages,...e.groupMessages];s.length!==0&&(this.buffer.unshift(...s),r.info(`[MessageBuffer] requeue \u56DE\u6EDA\u672A\u4EA4\u4ED8\u6D88\u606F ${s.length} \u6761\uFF08\u79C1\u804A ${e.directMessages.length}\uFF0C\u7FA4\u804A ${e.groupMessages.length}\uFF09\uFF0C\u5F53\u524D\u6570\u91CF: ${this.buffer.length}`),this.tryDispatch())}size(){return this.buffer.length}clear(){this.buffer=[];for(const e of this.resolvers)e({directMessages:[],groupMessages:[]});this.resolvers=[],this.isPolling=!1,this.seenMsgIds.clear()}tryDispatch(){for(;this.resolvers.length>0&&this.buffer.length>0;){const e=this.resolvers.shift();if(e){const s=this.consumeAll();e(s)}}this.updatePollingState()}consumeAll(){const e=[],s=[];for(;this.buffer.length>0;){const i=this.buffer.shift();i&&(this.markSeen(i),this.isDirectMessage(i)?e.push(i):s.push(i))}const t=e.filter(i=>i.channel==="meeting"||i.channel==="meeting_invite");return t.length>0&&f("buffer.consumeAll",`consumed=${c(t)} dm=${e.length} gm=${s.length}`),{directMessages:e,groupMessages:s}}isDirectMessage(e){const s=e.channel;return s==="meeting"||s==="meeting_invite"?!0:typeof e.msgId=="string"}}export{M as MessageBuffer};
1
+ import{logger as r}from"./logger.js";import{meetingDebugFingerprint as h,meetingDebugFingerprints as c,meetingDebugLog as f}from"./meeting-debug-log.js";const u=500;function a(n){if(n.msgId===void 0||n.msgId===null)return;const e=n.channel;if(e==="meeting")return`meeting:${n.msgId}`;if(e==="meeting_invite")return`meeting_invite:${n.msgId}`;if(e==="notification")return`notification:${n.msgId}`;if(typeof n.msgId=="number"){const s=n.roomId;return`group:${typeof s=="string"?s:""}:${n.msgId}`}return n.msgId}class M{buffer=[];resolvers=[];onMessageArrived=null;isPolling=!1;seenMsgIds=new Map;setOnMessageArrived(e){this.onMessageArrived=e}setIsPolling(e){this.isPolling=e}markSeen(e){const s=a(e);s!==void 0&&(this.seenMsgIds.set(s,Date.now()),this.cleanupSeenMsgIds())}isDuplicate(e){const s=a(e);return s===void 0?!1:this.seenMsgIds.has(s)?!0:(this.seenMsgIds.set(s,Date.now()),this.cleanupSeenMsgIds(),!1)}cleanupSeenMsgIds(){if(this.seenMsgIds.size<=u)return;let e=0;const s=this.seenMsgIds.size-u;for(const t of this.seenMsgIds.keys()){if(e>=s)break;this.seenMsgIds.delete(t),e++}}push(e){if(this.isDuplicate(e)){r.info(`[MessageBuffer] \u5FFD\u7565\u91CD\u590D\u6D88\u606F\uFF0CmsgId: ${e.msgId}`);const s=e.channel;(s==="meeting"||s==="meeting_invite")&&f("buffer.push.duplicate-blocked",`${h(e)} content=${String(e.content??"").slice(0,120)}`);return}this.buffer.push(e),r.debug(`[MessageBuffer] \u6D88\u606F\u5165\u7F13\u51B2\u533A\uFF0C\u5F53\u524D\u6570\u91CF: ${this.buffer.length}`);{const s=e.channel;(s==="meeting"||s==="meeting_invite")&&f("buffer.push.enqueued",`${h(e)} content=${String(e.content??"").slice(0,120)}`)}this.isPolling&&this.onMessageArrived&&(r.debug("[MessageBuffer] \u68C0\u6D4B\u5230 poll \u7B49\u5F85\u4E2D\uFF0C\u89E6\u53D1\u6D88\u606F\u5230\u8FBE\u56DE\u8C03"),this.onMessageArrived()),this.tryDispatch()}setProfileMessage(e){r.info(`[MessageBuffer] \u6536\u5230 Profile \u63A8\u9001\uFF0CdisplayName: ${e.displayName}\u3002\u8EAB\u4EFD\u4FE1\u606F\u8BF7\u901A\u8FC7 get_profile \u83B7\u53D6\u3002`)}removeProfileMessage(){r.info("[MessageBuffer] removeProfileMessage \u88AB\u8C03\u7528\uFF0C\u5F53\u524D\u65E0\u9700\u79FB\u9664\u672A\u8BFB\u8EAB\u4EFD\u6D88\u606F")}hasProfileMessage(){return!1}wakeUpWaiters(){if(f("buffer.wakeUpWaiters",`bufferSize=${this.buffer.length} waiters=${this.resolvers.length}`),this.tryDispatch(),this.buffer.length===0&&this.resolvers.length>0){const e=this.resolvers.shift();e&&(this.updatePollingState(),r.info("[MessageBuffer] wakeUpWaiters: \u5524\u9192 poll \u8D70 hydrate \u91CD\u67E5"),e({directMessages:[],groupMessages:[]}))}}getProfileMessage(){return null}updatePollingState(){this.isPolling=this.resolvers.length>0}poll(e){if(r.debug(`[MessageBuffer] poll() \u88AB\u8C03\u7528\uFF0Cbuffer: ${this.buffer.length}${e?`\uFF0C\u8D85\u65F6: ${e}ms`:""}`),this.buffer.length>0){const s=this.consumeAll();return r.info(`[MessageBuffer] poll \u7ACB\u5373\u8FD4\u56DE\uFF0C\u79C1\u804A: ${s.directMessages.length}\uFF0C\u7FA4\u804A: ${s.groupMessages.length}`),Promise.resolve(s)}return this.resolvers.length===0&&(this.isPolling=!0),new Promise(s=>{let t=null,i=!1;const g=l=>{if(i)return;i=!0;const o=this.resolvers.indexOf(g);o>-1&&this.resolvers.splice(o,1),t&&(clearTimeout(t),t=null),this.updatePollingState(),r.info(`[MessageBuffer] poll \u6536\u5230\u6D88\u606F\uFF0C\u79C1\u804A: ${l.directMessages.length}\uFF0C\u7FA4\u804A: ${l.groupMessages.length}`),s(l)};this.resolvers.push(g),this.tryDispatch(),e&&e>0&&(t=setTimeout(()=>{if(i)return;i=!0;const l=this.resolvers.indexOf(g);l>-1&&this.resolvers.splice(l,1),this.updatePollingState(),r.info(`[MessageBuffer] poll \u8D85\u65F6\uFF08${e}ms\uFF09\uFF0C\u8FD4\u56DE\u7A7A\u6D88\u606F`),s({directMessages:[],groupMessages:[]})},e))})}get(){if(this.buffer.length>0){const e=this.consumeAll();return r.info(`[MessageBuffer] get \u8FD4\u56DE\u6D88\u606F\uFF0C\u79C1\u804A: ${e.directMessages.length}\uFF0C\u7FA4\u804A: ${e.groupMessages.length}`),e}return{directMessages:[],groupMessages:[]}}takeForceDirectMessages(){const e=[],s=[];for(const t of this.buffer)this.isDirectMessage(t)&&t.force===!0?(this.markSeen(t),e.push(t)):s.push(t);return this.buffer=s,e.length>0&&(r.info(`[MessageBuffer] takeForceDirectMessages \u53D6\u8D70\u5F3A\u5236\u79C1\u4FE1 ${e.length} \u6761\uFF0C\u5269\u4F59 ${s.length} \u6761`),this.tryDispatch()),{directMessages:e,groupMessages:[]}}requeue(e){const s=[...e.directMessages,...e.groupMessages];s.length!==0&&(this.buffer.unshift(...s),r.info(`[MessageBuffer] requeue \u56DE\u6EDA\u672A\u4EA4\u4ED8\u6D88\u606F ${s.length} \u6761\uFF08\u79C1\u804A ${e.directMessages.length}\uFF0C\u7FA4\u804A ${e.groupMessages.length}\uFF09\uFF0C\u5F53\u524D\u6570\u91CF: ${this.buffer.length}`),this.tryDispatch())}size(){return this.buffer.length}clear(){this.buffer=[];for(const e of this.resolvers)e({directMessages:[],groupMessages:[]});this.resolvers=[],this.isPolling=!1,this.seenMsgIds.clear()}tryDispatch(){for(;this.resolvers.length>0&&this.buffer.length>0;){const e=this.resolvers.shift();if(e){const s=this.consumeAll();e(s)}}this.updatePollingState()}consumeAll(){const e=[],s=[];for(;this.buffer.length>0;){const i=this.buffer.shift();i&&(this.markSeen(i),this.isDirectMessage(i)?e.push(i):s.push(i))}const t=e.filter(i=>i.channel==="meeting"||i.channel==="meeting_invite");return t.length>0&&f("buffer.consumeAll",`consumed=${c(t)} dm=${e.length} gm=${s.length}`),{directMessages:e,groupMessages:s}}isDirectMessage(e){const s=e.channel;return s==="meeting"||s==="meeting_invite"?!0:typeof e.msgId=="string"}}export{M as MessageBuffer};
2
2
 
@@ -0,0 +1,5 @@
1
+
2
+
3
+ export declare function latexToOmml(latex: string, displayMode?: boolean): string;
4
+
5
+ export declare function prepareOfficeEquationCommands(commands: unknown[]): void;
@@ -0,0 +1,2 @@
1
+ import S from"temml";const O="http://schemas.openxmlformats.org/officeDocument/2006/math",b=new Set(["\u2211","\u220F","\u2210","\u222B","\u222C","\u222D","\u222E","\u222F","\u22C3","\u22C2","\u2A04","\u2A01","\u2A02","\u2A00"]),T=new Set(["lim","max","min","sup","inf","det","dim","gcd","lcm","lg","ln","log"]),L=new Set(["\u02C6","~","\u203E","\u2192","\u2190","\u2194","\u02D9","\xA8","\u02D8","\u02C7","`","\xB4","\u23DE","\u23DF","\u20D7"]);function C(r){let e=0;const t={tag:"#root",attrs:{},children:[],text:""},m=[t];for(;e<r.length;){const n=r.indexOf("<",e);if(n<0){w(m[m.length-1],r.slice(e));break}n>e&&w(m[m.length-1],r.slice(e,n));const c=r.indexOf(">",n);if(c<0)break;const i=r.slice(n+1,c).trim();if(i.startsWith("?")||i.startsWith("!")){e=c+1;continue}if(i.startsWith("/")){const P=i.slice(1).trim();m.length>1&&m[m.length-1].tag===P&&m.pop(),e=c+1;continue}const o=i.endsWith("/"),u=o?i.slice(0,-1).trim():i,a=u.search(/\s/),h=a<0?u:u.slice(0,a),v=a<0?"":u.slice(a+1),$={tag:h,attrs:E(v),children:[],text:""};m[m.length-1].children.push($),o||m.push($),e=c+1}return t}function w(r,e){e&&(r.text+=e)}function E(r){const e={},t=/([\w:.-]+)\s*=\s*"([^"]*)"|([\w:.-]+)\s*=\s*'([^']*)'/g;let m;for(;(m=t.exec(r))!==null;)m[1]?e[m[1]]=m[2]??"":m[3]&&(e[m[3]]=m[4]??"");return e}function l(r){return r.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;")}function f(r){let e=r.text;for(const t of r.children)e+=f(t);return e}function d(r){return r.children.filter(e=>e.tag!=="mspace"&&!(e.tag==="#text"&&!e.text.trim()))}function s(r){switch(r.tag){case"math":case"mrow":case"semantics":return p(r);case"annotation":case"annotation-xml":return"";case"mi":case"mn":case"mo":case"mtext":{const e=f(r);return e?x(e,r.tag==="mi"&&/^[A-Za-z]$/.test(e)?"i":"p"):""}case"msup":return g(r,"sup");case"msub":return g(r,"sub");case"msubsup":return g(r,"subsup");case"mfrac":{const e=d(r),t=e[0]?s(e[0]):"",m=e[1]?s(e[1]):"";return`<m:f><m:fPr/><m:num>${t}</m:num><m:den>${m}</m:den></m:f>`}case"msqrt":return`<m:rad><m:radPr><m:degHide m:val="1"/></m:radPr><m:deg/><m:e>${p(r)}</m:e></m:rad>`;case"mroot":{const e=d(r),t=e[0]?s(e[0]):"";return`<m:rad><m:radPr/><m:deg>${e[1]?s(e[1]):""}</m:deg><m:e>${t}</m:e></m:rad>`}case"mover":case"munder":case"munderover":return X(r);case"mtable":return`<m:m>${M(r)}</m:m>`;case"mfenced":{const e=r.attrs.open??"(",t=r.attrs.close??")",m=p(r);return`<m:d><m:dPr><m:begChr m:val="${l(e)}"/><m:endChr m:val="${l(t)}"/></m:dPr><m:e>${m}</m:e></m:d>`}case"mspace":return"";case"mpadded":case"mstyle":case"menclose":return p(r);default:return p(r)}}function p(r){let e="";r.text.trim()&&(e+=x(r.text,"p"));const t=r.children;let m=0;for(;m<t.length;){const n=t[m];if(y(n)){const c=A(t,m+1);if(c>m){const o=f(n).trim(),u=f(t[c]).trim();let a="";for(let h=m+1;h<c;h++)a+=s(t[h]);e+=`<m:d><m:dPr><m:begChr m:val="${l(o)}"/><m:endChr m:val="${l(u)}"/></m:dPr><m:e>${a}</m:e></m:d>`,m=c+1;continue}if(n.attrs.stretchy==="true"&&c<0){const o=f(n).trim();let u="";for(let a=m+1;a<t.length;a++)u+=s(t[a]);e+=`<m:d><m:dPr><m:begChr m:val="${l(o)}"/><m:endChr m:val=""/></m:dPr><m:e>${u}</m:e></m:d>`,m=t.length;continue}}e+=s(n),m++}return e}function y(r){if(r.tag!=="mo")return!1;const e=f(r).trim();return["(","[","{","|","\u2016","\u27E8","\u230A","\u2308"].includes(e)?r.attrs.fence==="true"||r.attrs.stretchy==="true":!1}function A(r,e){let t=0;for(let m=e;m<r.length;m++){const n=r[m];if(y(n)){t++;continue}if(n.tag==="mo"&&n.attrs.fence==="true"&&n.attrs.form==="postfix"){if(t===0)return m;t--}}return-1}function x(r,e="p"){if(!r)return"";const t=r.replace(/\u2061|\u2062|\u2063|\u2064/g,"");return t?`<m:r><m:rPr><m:sty m:val="${e}"/></m:rPr><m:t xml:space="preserve">${l(t)}</m:t></m:r>`:""}function g(r,e){const t=d(r),m=t[0]?s(t[0]):"",n=t[0]?f(t[0]).trim():"";if(b.has(n)){const o=e!=="sup"&&t[1]?s(t[1]):"",u=e==="sup"?t[1]?s(t[1]):"":t[2]?s(t[2]):"";return`<m:nary><m:naryPr><m:chr m:val="${l(n)}"/><m:limLoc m:val="undOvr"/></m:naryPr><m:sub>${o}</m:sub><m:sup>${u}</m:sup><m:e/></m:nary>`}if(e==="sub"&&t[0]?.tag==="mi"&&T.has(n)){const o=t[1]?s(t[1]):"";return`<m:limLow><m:e>${m}</m:e><m:lim>${o}</m:lim></m:limLow>`}if(e==="sup"){const o=t[1]?s(t[1]):"";return`<m:sSup><m:e>${m}</m:e><m:sup>${o}</m:sup></m:sSup>`}if(e==="sub"){const o=t[1]?s(t[1]):"";return`<m:sSub><m:e>${m}</m:e><m:sub>${o}</m:sub></m:sSub>`}const c=t[1]?s(t[1]):"",i=t[2]?s(t[2]):"";return`<m:sSubSup><m:e>${m}</m:e><m:sub>${c}</m:sub><m:sup>${i}</m:sup></m:sSubSup>`}function X(r){const e=d(r),t=e[0],m=r.tag==="munderover"||r.tag==="munder"?e[1]:void 0,n=r.tag==="munderover"?e[2]:r.tag==="mover"?e[1]:void 0,c=t?f(t).trim():"";if(b.has(c)){const o=m?s(m):"",u=n?s(n):"";return`<m:nary><m:naryPr><m:chr m:val="${l(c)}"/><m:limLoc m:val="undOvr"/></m:naryPr><m:sub>${o}</m:sub><m:sup>${u}</m:sup><m:e/></m:nary>`}const i=n?f(n).trim():"";return n&&(L.has(i)||n.attrs.stretchy==="false")?`<m:acc><m:accPr><m:chr m:val="${l(i||"\u0302")}"/></m:accPr><m:e>${t?s(t):""}</m:e></m:acc>`:m&&n?`<m:limLow><m:e><m:limUpp><m:e>${t?s(t):""}</m:e><m:lim>${s(n)}</m:lim></m:limUpp></m:e><m:lim>${s(m)}</m:lim></m:limLow>`:m?`<m:limLow><m:e>${t?s(t):""}</m:e><m:lim>${s(m)}</m:lim></m:limLow>`:n?`<m:limUpp><m:e>${t?s(t):""}</m:e><m:lim>${s(n)}</m:lim></m:limUpp>`:t?s(t):""}function M(r){let e="";for(const t of r.children){if(t.tag!=="mtr")continue;const m=t.children.filter(n=>n.tag==="mtd");if(m.length===0){e+=`<m:mr><m:e>${p(t)}</m:e></m:mr>`;continue}e+="<m:mr>";for(const n of m)e+=`<m:e>${p(n)}</m:e>`;e+="</m:mr>"}return e}function R(r,e=!1){if(!r||!r.trim())throw new Error("\u516C\u5F0F LaTeX \u4E0D\u80FD\u4E3A\u7A7A");let t;try{t=S.renderToString(r,{displayMode:e,throwOnError:!0})}catch(i){throw new Error(`LaTeX \u89E3\u6790\u5931\u8D25: ${i instanceof Error?i.message:String(i)}\uFF08\u516C\u5F0F\uFF1A${r.slice(0,80)}\uFF09`)}const n=C(t).children.find(i=>i.tag==="math");if(!n)throw new Error(`LaTeX \u8F6C\u6362\u7ED3\u679C\u7F3A\u5C11 math \u6839\u5143\u7D20\uFF08\u516C\u5F0F\uFF1A${r.slice(0,80)}\uFF09`);const c=s(n);if(!c.trim())throw new Error(`\u516C\u5F0F\u8F6C\u6362\u7ED3\u679C\u4E3A\u7A7A\uFF08\u516C\u5F0F\uFF1A${r.slice(0,80)}\uFF09`);return`<m:oMath xmlns:m="${O}">${c}</m:oMath>`}function I(r){if(Array.isArray(r))for(const e of r){if(!e||typeof e!="object")continue;const t=e.props;if(!t||typeof t!="object")continue;const m=t.latex;!m||typeof m!="string"||!m.trim()||typeof t.omml=="string"&&t.omml.trim()||(t.omml=R(m,t.displayMode===!0))}}export{R as latexToOmml,I as prepareOfficeEquationCommands};
2
+
@@ -0,0 +1,12 @@
1
+
2
+
3
+ export interface ResolvedImage {
4
+ bytes: Buffer;
5
+ base64: string;
6
+ ext: string;
7
+ name: string;
8
+ }
9
+
10
+ export declare function officeResolveImageSource(source: string, workspaceRoot?: string): Promise<ResolvedImage>;
11
+
12
+ export declare function prepareOfficeImageCommands(commands: unknown[], workspaceRoot?: string): Promise<void>;
@@ -0,0 +1,2 @@
1
+ import x from"node:fs";import h from"node:path";import{officeWorkspaceRoot as u}from"./office-workspace.js";const c=8*1024*1024,l=[{magic:[137,80,78,71,13,10,26,10],ext:"png",mime:"image/png"},{magic:[255,216,255],ext:"jpg",mime:"image/jpeg"},{magic:[71,73,70,56,55,97],ext:"gif",mime:"image/gif"},{magic:[71,73,70,56,57,97],ext:"gif",mime:"image/gif"},{magic:[66,77],ext:"bmp",mime:"image/bmp"},{magic:[73,73,42,0],ext:"tif",mime:"image/tiff"},{magic:[77,77,0,42],ext:"tif",mime:"image/tiff"}],M=[82,73,70,70],d=15e3;async function E(t,o){if(!t||typeof t!="string"||!t.trim())throw new Error("\u56FE\u7247 source \u4E0D\u80FD\u4E3A\u7A7A\u3002\u6765\u6E90\uFF1A\u5DE5\u4F5C\u533A\u8DEF\u5F84\u3001http(s) URL\u3001data:image URL");const e=t.trim();if(e.startsWith("data:")){const m=/^data:image\/([a-zA-Z0-9+.-]+)(?:;base64)?,(.+)$/.exec(e);if(!m)throw new Error("data:image URL \u683C\u5F0F\u4E0D\u5408\u6CD5\uFF08\u9700\u8981 data:image/xxx;base64,...\uFF09");const a=m[1]?.toLowerCase().replace("jpeg","jpg")||"png";if(a==="webp"||a==="svg"||a==="ico")throw new Error(`\u4E0D\u652F\u6301\u7684\u56FE\u7247\u683C\u5F0F: ${a}\uFF0C\u4EC5\u652F\u6301 PNG/JPEG/GIF/BMP/TIFF`);const i=m[2]?.trim();if(!i)throw new Error("data:image URL \u5185\u5BB9\u4E3A\u7A7A");const s=Buffer.from(i,"base64");return w(s,a,`image.${a}`)}if(/^https?:\/\//i.test(e)){const m=await $(e);return p(m,e)}const r=o||u(),n=h.resolve(r,e);if(!x.existsSync(n))throw new Error(`\u56FE\u7247\u6587\u4EF6\u4E0D\u5B58\u5728: ${e}\uFF08\u89E3\u6790\u4E3A ${n}\uFF09`);const f=x.statSync(n);if(!f.isFile())throw new Error(`\u4E0D\u662F\u666E\u901A\u6587\u4EF6: ${e}`);if(f.size>c)throw new Error(`\u56FE\u7247\u6587\u4EF6\u8D85\u9650\uFF08\u4E0A\u9650 ${c/1024/1024}MB\uFF09: ${e}`);const g=x.readFileSync(n);return p(g,h.basename(n))}async function $(t){let o;try{o=new URL(t)}catch{throw new Error(`\u65E0\u6548\u7684\u56FE\u7247 URL: ${t}`)}if(o.protocol!=="http:"&&o.protocol!=="https:")throw new Error(`\u4E0D\u652F\u6301\u7684 URL \u534F\u8BAE: ${o.protocol}\uFF08\u4EC5\u652F\u6301 http/https\uFF09`);let e;try{e=await fetch(t,{signal:AbortSignal.timeout(d)})}catch(i){throw new Error(`\u56FE\u7247\u4E0B\u8F7D\u5931\u8D25: ${t}\uFF08${i instanceof Error?i.message:String(i)}\uFF09`)}if(!e.ok)throw new Error(`\u56FE\u7247\u4E0B\u8F7D\u5931\u8D25: ${t}\uFF08HTTP ${e.status}\uFF09`);const r=(e.headers.get("content-type")||"").split(";")[0]?.trim().toLowerCase()||"";if(r&&!r.startsWith("image/"))throw new Error(`URL \u8FD4\u56DE\u7684\u4E0D\u662F\u56FE\u7247\uFF08content-type: ${r}\uFF09: ${t}`);const n=Number(e.headers.get("content-length")||"");if(Number.isFinite(n)&&n>c)throw new Error(`\u56FE\u7247\u592A\u5927: ${t}\uFF08${n} > ${c} \u5B57\u8282\uFF09`);const f=e.body;if(!f){const i=Buffer.from(await e.arrayBuffer());if(i.length>c)throw new Error(`\u56FE\u7247\u592A\u5927: ${t}\uFF08${i.length} > ${c} \u5B57\u8282\uFF09`);return i}const g=f.getReader(),m=[];let a=0;for(;;){const{done:i,value:s}=await g.read();if(i)break;if(s){if(a+=s.byteLength,a>c)throw g.cancel().catch(()=>{}),new Error(`\u56FE\u7247\u592A\u5927: ${t}\uFF08> ${c/1024/1024}MB\uFF09`);m.push(Buffer.from(s))}}return Buffer.concat(m,a)}function p(t,o){if(t.length===0)throw new Error("\u56FE\u7247\u5185\u5BB9\u4E3A\u7A7A");if(t.length>c)throw new Error(`\u56FE\u7247\u8D85\u9650\uFF08\u4E0A\u9650 ${c/1024/1024}MB\uFF09`);const e=B(t);if(!e){const r=t.length>0?`0x${t.slice(0,4).toString("hex").toUpperCase()}`:"";throw new Error(`\u4E0D\u652F\u6301\u7684\u56FE\u7247\u683C\u5F0F\uFF08\u9B54\u6570 ${r}\uFF09\uFF0C\u4EC5\u652F\u6301 PNG/JPEG/GIF/BMP/TIFF`)}return w(t,e,o)}function w(t,o,e){return{bytes:t,base64:t.toString("base64"),ext:o,name:e.match(/[\w.-]+$/)?e:`image.${o}`}}function B(t){if(t.length<4||t[0]===82&&t[1]===73&&t[2]===70&&t[3]===70&&t.length>=12&&t[8]===87&&t[9]===69&&t[10]===66&&t[11]===80)return null;for(const o of l)if(t.length>=o.magic.length){let e=!0;for(let r=0;r<o.magic.length;r++)if(t[r]!==o.magic[r]){e=!1;break}if(e)return o.ext}return null}async function A(t,o){if(Array.isArray(t))for(const e of t){if(!e||typeof e!="object")continue;const r=e.props;if(!r||typeof r!="object")continue;const n=r.source;if(!n||typeof n!="string"||!n.trim()||r.imageBase64)continue;const f=await E(n,o);r.imageBase64=f.base64,r.imageName||(r.imageName=f.name)}}export{E as officeResolveImageSource,A as prepareOfficeImageCommands};
2
+
@@ -0,0 +1,40 @@
1
+
2
+
3
+ export declare function officeKindOf(filePath: string): "docx" | "xlsx" | "pptx" | null;
4
+
5
+ export declare function isLegacyOfficeExt(filePath: string): boolean;
6
+
7
+ export declare function modernOfficeFileName(filePath: string): string;
8
+
9
+ export declare function officeWorkspaceRoot(): string;
10
+
11
+ export declare function resolveOfficeFile(rawFile: string, workspaceRoot?: string): string;
12
+
13
+ export interface PackedOfficeFile {
14
+
15
+ absolutePath: string;
16
+
17
+ fileName: string;
18
+
19
+ fileBase64: string;
20
+
21
+ sizeKb: number;
22
+ }
23
+
24
+ export declare function packOfficeFile(rawFile: string, workspaceRoot?: string): PackedOfficeFile;
25
+
26
+ export declare const OFFICE_BACKUP_KEEP = 5;
27
+
28
+ export declare function backupOfficeFile(absolutePath: string, keep?: number): string | null;
29
+
30
+ export declare function writeOfficeFileAtomic(rawFile: string, fileBase64: string, workspaceRoot?: string): {
31
+ absolutePath: string;
32
+ sizeKb: number;
33
+ backupPath: string | null;
34
+ };
35
+
36
+ export declare function writeOfficeFileAtomicAs(rawFile: string, targetName: string, fileBase64: string, workspaceRoot?: string): {
37
+ absolutePath: string;
38
+ sizeKb: number;
39
+ backupPath: string | null;
40
+ };
@@ -0,0 +1,2 @@
1
+ import f from"node:fs";import o from"node:path";const h={".docx":"docx",".docm":"docx",".xlsx":"xlsx",".xlsm":"xlsx",".pptx":"pptx",".pptm":"pptx"},u={".doc":"docx",".xls":"xlsx",".ppt":"pptx"};function E(t){const e=o.extname(t).toLowerCase();return h[e]??u[e]??null}function F(t){return u[o.extname(t).toLowerCase()]!==void 0}function B(t){const e=o.extname(t).toLowerCase(),r=u[e];return r?t.slice(0,t.length-e.length)+"."+r:t}function a(){return o.resolve(process.env.AWS_WORKSPACE_PATH||process.cwd())}function x(t,e=a()){const r=t.trim();if(!r)throw new Error("file \u4E0D\u80FD\u4E3A\u7A7A");return o.resolve(e,r)}const m=16*1024*1024;function k(t,e=a()){const r=x(t,e),n=o.basename(r);if(!E(r))throw new Error(`\u4E0D\u652F\u6301\u7684\u6587\u6863\u7C7B\u578B: ${t}\uFF08\u4EC5\u652F\u6301 .docx/.docm\u3001.xlsx/.xlsm\u3001.pptx/.pptm\uFF0C\u4EE5\u53CA\u65E7\u7248 .doc/.xls/.ppt\uFF09`);let c;try{c=f.statSync(r)}catch{throw new Error(`\u6587\u4EF6\u4E0D\u5B58\u5728: ${t}\uFF08\u89E3\u6790\u4E3A ${r}\uFF09`)}if(!c.isFile())throw new Error(`\u4E0D\u662F\u666E\u901A\u6587\u4EF6: ${t}`);if(c.size>m)throw new Error(`\u6587\u4EF6\u8FC7\u5927\uFF08\u4E0A\u9650 ${Math.floor(m/1024/1024)}MB\uFF09: ${t}`);const i=f.readFileSync(r);return{absolutePath:r,fileName:n,fileBase64:i.toString("base64"),sizeKb:Math.ceil(i.length/1024)}}const y=5,l="-backup-";function S(t,e){return new RegExp(`^${$(t)}${l}\\d{8}-\\d{6}${$(e)}$`)}function $(t){return t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function d(t=new Date){const e=r=>String(r).padStart(2,"0");return`${t.getFullYear()}${e(t.getMonth()+1)}${e(t.getDate())}-${e(t.getHours())}${e(t.getMinutes())}${e(t.getSeconds())}`}function g(t,e=y){try{if(!f.existsSync(t)||!f.statSync(t).isFile())return null;const r=o.dirname(t),n=o.extname(t),c=o.basename(t,n);let s=o.join(r,`${c}${l}${d()}${n}`),p=1;for(;f.existsSync(s);)s=o.join(r,`${c}${l}${d()}-${p++}${n}`);return f.copyFileSync(t,s),A(r,c,n,e),s}catch{return null}}function A(t,e,r,n){if(!(n<=0))try{const c=S(e,r),i=f.readdirSync(t).filter(s=>c.test(s)).sort();for(;i.length>n;){const s=i.shift();s&&f.rmSync(o.join(t,s),{force:!0})}}catch{}}function C(t,e,r=a()){const n=x(t,r),c=g(n);return{...w(n,e,t),backupPath:c}}function K(t,e,r,n=a()){const c=x(t,n),i=o.basename(e);if(!i||i==="."||i==="..")throw new Error(`\u53E6\u5B58\u76EE\u6807\u6587\u4EF6\u540D\u4E0D\u5408\u6CD5: ${e}`);const s=o.join(o.dirname(c),i),p=g(s);return{...w(s,r,t),backupPath:p}}function w(t,e,r){const n=typeof e=="string"?e.trim():"";if(!n)throw new Error("\u8FD4\u56DE\u7684\u6587\u4EF6\u5185\u5BB9\u4E3A\u7A7A\uFF0C\u5DF2\u653E\u5F03\u5199\u56DE");if(!/^[A-Za-z0-9+/]+={0,2}$/.test(n)||n.length%4!==0)throw new Error("\u8FD4\u56DE\u7684 fileBase64 \u4E0D\u662F\u5408\u6CD5 Base64 \u5185\u5BB9");const c=Buffer.from(n,"base64");if(c.length===0)throw new Error("\u8FD4\u56DE\u7684\u6587\u4EF6\u5185\u5BB9\u4E3A\u7A7A\uFF0C\u5DF2\u653E\u5F03\u5199\u56DE");f.mkdirSync(o.dirname(t),{recursive:!0});const i=o.join(o.dirname(t),`.${o.basename(t)}.${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2,8)}.tmp`);f.writeFileSync(i,c);try{f.renameSync(i,t)}catch(s){try{f.rmSync(i,{force:!0})}catch{}throw new Error(`\u5199\u56DE\u5931\u8D25\uFF08\u6587\u4EF6\u53EF\u80FD\u6B63\u88AB\u5176\u4ED6\u7A0B\u5E8F\u5360\u7528\uFF09: ${r} - ${s instanceof Error?s.message:String(s)}`)}return{absolutePath:t,sizeKb:Math.ceil(c.length/1024)}}export{y as OFFICE_BACKUP_KEEP,g as backupOfficeFile,F as isLegacyOfficeExt,B as modernOfficeFileName,E as officeKindOf,a as officeWorkspaceRoot,k as packOfficeFile,x as resolveOfficeFile,C as writeOfficeFileAtomic,K as writeOfficeFileAtomicAs};
2
+
@@ -1,4 +1,4 @@
1
- import{EventEmitter as _}from"node:events";import{logger as h}from"./logger.js";const d="[temp clipboard paste file]",g=/[A-Z]:(?:\\\\|\\)[^\r\n"'`]*?(?:\\\\|\\)mini-term-clipboard(?:\\\\|\\)paste-\d+\.txt/gi,A=/\/[^\r\n"'`]*?\/mini-term-clipboard\/paste-\d+\.txt/gi,S=/mini-term-clipboard[\\/]paste-\d+\.txt/gi,w=new Set(["aws-mcp","agents-work-studio"]),m=500;function p(s){return s.replace(g,d).replace(A,d).replace(S,d)}const y=/^(password|passwd|secret|token|api[-_]?key|access[-_]?key|private[-_]?key|authorization|credential)/i;function f(s,e=0){if(e>8)return s;if(Array.isArray(s))return s.map(t=>f(t,e+1));if(s!==null&&typeof s=="object"){const t={};for(const[r,i]of Object.entries(s))typeof i=="string"&&y.test(r)?t[r]="[redacted]":t[r]=f(i,e+1);return t}return s}class u extends _{config;currentStatus="stopped";currentAction=null;constructor(e){super(),this.config=e}reportStarting(){this.updateStatus("starting")}reportRunning(){this.updateStatus("running")}reportWaitingInput(){this.updateStatus("waiting_input"),this.clearAction()}reportThinking(){this.updateStatus("thinking"),this.clearAction()}reportStopped(){this.updateStatus("stopped"),this.clearAction()}reportError(){this.updateStatus("error"),this.clearAction()}reportToolUse(e,t){const r=this.parseToolAction(e,t);this.updateStatus("tool_using",r.type,r.label,r.detail,void 0,this.formatToolInput(t))}reportToolResult(e){this.updateStatus("tool_using",this.currentAction?.type,this.currentAction?.label,this.currentAction?.detail,this.formatToolResult(e),this.currentAction?.input)}reportToolError(e){const t=e instanceof Error?e.message:String(e);this.updateStatus("error",this.currentAction?.type,this.currentAction?.label||"Tool call failed",this.currentAction?.detail,t,this.currentAction?.input),this.clearAction()}static KNOWN_MCP_TOOLS={get_colleague:"aws-mcp",get_group_rooms:"aws-mcp",get_profile:"aws-mcp",hire_colleague:"aws-mcp",send_group:"aws-mcp",send_private:"aws-mcp",poll_message:"aws-mcp",get_message:"aws-mcp",get_dm_history:"aws-mcp",get_group_history:"aws-mcp",my_task:"aws-mcp",create_task_instance_comment:"aws-mcp",submit_task_result:"aws-mcp",start_task_rollback:"aws-mcp",finish_task_rollback:"aws-mcp",reject_task:"aws-mcp",terminate_task:"aws-mcp",create_memory:"aws-mcp",read_memory:"aws-mcp",update_memory:"aws-mcp",delete_memory:"aws-mcp",search_memory:"aws-mcp",list_memories:"aws-mcp"};static canonicalizeMcpServer(e,t){const r=u.KNOWN_MCP_TOOLS[t.toLowerCase()];return r&&w.has(e.toLowerCase())?r:e}static formatMcpDetail(e,t){return e?t?`${u.canonicalizeMcpServer(e,t)}/${t}`:e:t}parseToolAction(e,t){const r=e.toLowerCase(),i=r.replace(/[_-]/g,""),a=(...n)=>{for(const c of n){if(typeof c=="string"&&c.trim())return p(c);if(Array.isArray(c)&&c.length>0){const l=c[0];if(typeof l=="string"&&l.trim())return p(l)}}};if(r.includes("skill")||r.includes("disclose"))return{type:"skill",label:"Calling skill",detail:t?.name?p(String(t.name)):void 0};const o=u.KNOWN_MCP_TOOLS[r];if(o)return{type:"mcp",label:"Calling MCP",detail:u.formatMcpDetail(o,e)};if(r.startsWith("mcp__")){const n=e.split("__"),c=n[1]||"",l=n.slice(2).join("__");return{type:"mcp",label:"Calling MCP",detail:u.formatMcpDetail(c,l)}}if(r.startsWith("mcp_")||r.includes("_mcp_"))return{type:"mcp",label:"Calling MCP",detail:e.replace(/^mcp_/,"").replace(/_/g," ")};if(r.includes("-mcp__")){const n=e.split("__"),c=n[0],l=n.slice(1).join("__");return{type:"mcp",label:"Calling MCP",detail:u.formatMcpDetail(c,l)}}if(i==="edit"||i==="editfile"||i==="strreplace"||i==="editcode"||i==="applypatch"||i==="multiedit")return{type:"edit_file",label:"\u7F16\u8F91\u6587\u4EF6",detail:a(t?.path,t?.file_path,t?.filePath,t?.target_file,t?.targetFile)};if(i==="write"||i==="writefile"||i==="fswrite")return{type:"write_file",label:"\u5199\u5165\u6587\u4EF6",detail:a(t?.path,t?.file_path,t?.filePath,t?.target_file,t?.targetFile)};if(i==="read"||i==="readfile"||i==="readcode"||i==="readmultiplefiles")return{type:"read_file",label:"\u8BFB\u53D6\u6587\u4EF6",detail:a(t?.path,t?.file_path,t?.filePath,t?.paths,t?.target_file,t?.targetFile)};if(i==="bash"||i==="execute"||i==="shell"||i==="pwsh"||i==="executepwsh"||i==="controlpwshprocess"||i==="runcommand"){const n=a(t?.command,t?.cmd,t?.argv);return{type:"bash",label:"\u6267\u884C\u547D\u4EE4",detail:n&&n.length>m?`${n.substring(0,m)}...\uFF08\u5185\u5BB9\u8FC7\u957F\uFF0C\u5DF2\u622A\u65AD\uFF09`:n}}return i==="search"||i==="grep"||i==="find"||i==="glob"||i==="grepsearch"||i==="filesearch"?{type:"search",label:"\u641C\u7D22\u6587\u4EF6",detail:t?.query?p(String(t.query)):void 0}:r.includes("web")||r.includes("fetch")||r.includes("http")?{type:"web",label:"\u7F51\u7EDC\u8BF7\u6C42",detail:t?.url?p(String(t.url)):void 0}:{type:"tool_using",label:"Calling tool",detail:e}}updateStatus(e,t,r,i,a,o){this.currentStatus=e,t&&(this.currentAction={type:t,label:r,detail:i,input:o});const n={agentId:this.config.agentId,status:e,actionType:t??void 0,actionLabel:t?this.currentAction?.label:void 0,actionDetail:t?this.currentAction?.detail:void 0,actionInput:t?this.currentAction?.input:void 0,actionResult:a,timestamp:new Date().toISOString()};h.info(`[StatusReporter] \u72B6\u6001\u66F4\u65B0: ${e}${r?` - ${r}`:""}`),this.config.sendStatusUpdate(n)}clearAction(){this.currentAction=null}formatToolInput(e){if(!(!e||Object.keys(e).length===0))try{const t=p(JSON.stringify(f(e),null,2)),r=6e3;return t.length<=r?t:`${t.slice(0,r)}
1
+ import{EventEmitter as _}from"node:events";import{logger as h}from"./logger.js";const d="[temp clipboard paste file]",g=/[A-Z]:(?:\\\\|\\)[^\r\n"'`]*?(?:\\\\|\\)mini-term-clipboard(?:\\\\|\\)paste-\d+\.txt/gi,A=/\/[^\r\n"'`]*?\/mini-term-clipboard\/paste-\d+\.txt/gi,S=/mini-term-clipboard[\\/]paste-\d+\.txt/gi,w=new Set(["aws-mcp","agents-work-studio"]),m=500;function p(s){return s.replace(g,d).replace(A,d).replace(S,d)}const y=/^(password|passwd|secret|token|api[-_]?key|access[-_]?key|private[-_]?key|authorization|credential)/i;function f(s,e=0){if(e>8)return s;if(Array.isArray(s))return s.map(t=>f(t,e+1));if(s!==null&&typeof s=="object"){const t={};for(const[r,i]of Object.entries(s))typeof i=="string"&&y.test(r)?t[r]="[redacted]":t[r]=f(i,e+1);return t}return s}class u extends _{config;currentStatus="stopped";currentAction=null;constructor(e){super(),this.config=e}reportStarting(){this.updateStatus("starting")}reportRunning(){this.updateStatus("running")}reportWaitingInput(){this.updateStatus("waiting_input"),this.clearAction()}reportThinking(){this.updateStatus("thinking"),this.clearAction()}reportStopped(){this.updateStatus("stopped"),this.clearAction()}reportError(){this.updateStatus("error"),this.clearAction()}reportToolUse(e,t){const r=this.parseToolAction(e,t);this.updateStatus("tool_using",r.type,r.label,r.detail,void 0,this.formatToolInput(t))}reportToolResult(e){this.updateStatus("tool_using",this.currentAction?.type,this.currentAction?.label,this.currentAction?.detail,this.formatToolResult(e),this.currentAction?.input)}reportToolError(e){const t=e instanceof Error?e.message:String(e);this.updateStatus("error",this.currentAction?.type,this.currentAction?.label||"Tool call failed",this.currentAction?.detail,t,this.currentAction?.input),this.clearAction()}static KNOWN_MCP_TOOLS={get_colleague:"aws-mcp",get_group_rooms:"aws-mcp",list_project_members:"aws-mcp",get_profile:"aws-mcp",hire_colleague:"aws-mcp",send_group:"aws-mcp",send_private:"aws-mcp",poll_message:"aws-mcp",get_message:"aws-mcp",get_dm_history:"aws-mcp",get_group_history:"aws-mcp",my_task:"aws-mcp",create_task_instance_comment:"aws-mcp",submit_task_result:"aws-mcp",start_task_rollback:"aws-mcp",finish_task_rollback:"aws-mcp",create_memory:"aws-mcp",read_memory:"aws-mcp",update_memory:"aws-mcp",delete_memory:"aws-mcp",search_memory:"aws-mcp",list_memories:"aws-mcp"};static canonicalizeMcpServer(e,t){const r=u.KNOWN_MCP_TOOLS[t.toLowerCase()];return r&&w.has(e.toLowerCase())?r:e}static formatMcpDetail(e,t){return e?t?`${u.canonicalizeMcpServer(e,t)}/${t}`:e:t}parseToolAction(e,t){const r=e.toLowerCase(),i=r.replace(/[_-]/g,""),a=(...n)=>{for(const c of n){if(typeof c=="string"&&c.trim())return p(c);if(Array.isArray(c)&&c.length>0){const l=c[0];if(typeof l=="string"&&l.trim())return p(l)}}};if(r.includes("skill")||r.includes("disclose"))return{type:"skill",label:"Calling skill",detail:t?.name?p(String(t.name)):void 0};const o=u.KNOWN_MCP_TOOLS[r];if(o)return{type:"mcp",label:"Calling MCP",detail:u.formatMcpDetail(o,e)};if(r.startsWith("mcp__")){const n=e.split("__"),c=n[1]||"",l=n.slice(2).join("__");return{type:"mcp",label:"Calling MCP",detail:u.formatMcpDetail(c,l)}}if(r.startsWith("mcp_")||r.includes("_mcp_"))return{type:"mcp",label:"Calling MCP",detail:e.replace(/^mcp_/,"").replace(/_/g," ")};if(r.includes("-mcp__")){const n=e.split("__"),c=n[0],l=n.slice(1).join("__");return{type:"mcp",label:"Calling MCP",detail:u.formatMcpDetail(c,l)}}if(i==="edit"||i==="editfile"||i==="strreplace"||i==="editcode"||i==="applypatch"||i==="multiedit")return{type:"edit_file",label:"\u7F16\u8F91\u6587\u4EF6",detail:a(t?.path,t?.file_path,t?.filePath,t?.target_file,t?.targetFile)};if(i==="write"||i==="writefile"||i==="fswrite")return{type:"write_file",label:"\u5199\u5165\u6587\u4EF6",detail:a(t?.path,t?.file_path,t?.filePath,t?.target_file,t?.targetFile)};if(i==="read"||i==="readfile"||i==="readcode"||i==="readmultiplefiles")return{type:"read_file",label:"\u8BFB\u53D6\u6587\u4EF6",detail:a(t?.path,t?.file_path,t?.filePath,t?.paths,t?.target_file,t?.targetFile)};if(i==="bash"||i==="execute"||i==="shell"||i==="pwsh"||i==="executepwsh"||i==="controlpwshprocess"||i==="runcommand"){const n=a(t?.command,t?.cmd,t?.argv);return{type:"bash",label:"\u6267\u884C\u547D\u4EE4",detail:n&&n.length>m?`${n.substring(0,m)}...\uFF08\u5185\u5BB9\u8FC7\u957F\uFF0C\u5DF2\u622A\u65AD\uFF09`:n}}return i==="search"||i==="grep"||i==="find"||i==="glob"||i==="grepsearch"||i==="filesearch"?{type:"search",label:"\u641C\u7D22\u6587\u4EF6",detail:t?.query?p(String(t.query)):void 0}:r.includes("web")||r.includes("fetch")||r.includes("http")?{type:"web",label:"\u7F51\u7EDC\u8BF7\u6C42",detail:t?.url?p(String(t.url)):void 0}:{type:"tool_using",label:"Calling tool",detail:e}}updateStatus(e,t,r,i,a,o){this.currentStatus=e,t&&(this.currentAction={type:t,label:r,detail:i,input:o});const n={agentId:this.config.agentId,status:e,actionType:t??void 0,actionLabel:t?this.currentAction?.label:void 0,actionDetail:t?this.currentAction?.detail:void 0,actionInput:t?this.currentAction?.input:void 0,actionResult:a,timestamp:new Date().toISOString()};h.info(`[StatusReporter] \u72B6\u6001\u66F4\u65B0: ${e}${r?` - ${r}`:""}`),this.config.sendStatusUpdate(n)}clearAction(){this.currentAction=null}formatToolInput(e){if(!(!e||Object.keys(e).length===0))try{const t=p(JSON.stringify(f(e),null,2)),r=6e3;return t.length<=r?t:`${t.slice(0,r)}
2
2
  ...(input too long, truncated)`}catch{return}}formatToolResult(e){let t;try{t=typeof e=="string"?e:JSON.stringify(e,null,2)}catch(o){t=`[Unable to serialize tool result: ${o instanceof Error?o.message:String(o)}]`}const r=t||String(e),i=4e3,a=p(r);return a.length<=i?a:`${a.slice(0,i)}
3
3
  ...(result too long, truncated)`}getCurrentStatus(){return{agentId:this.config.agentId,status:this.currentStatus,actionType:this.currentAction?.type,actionLabel:this.currentAction?.label,actionDetail:this.currentAction?.detail,actionInput:this.currentAction?.input,timestamp:new Date().toISOString()}}}export{u as StatusReporter,p as redactTransientClipboardPastePaths};
4
4
 
@@ -52,6 +52,10 @@ export declare function findBridgeCapabilityByToolName(toolName: string): Bridge
52
52
 
53
53
  export declare function collapsibleToolGroupKeys(): string[];
54
54
 
55
+ export declare const TOOL_GROUP_MANIFEST_PREFIX = "ACODE_TOOL_GROUPS_V1:";
56
+
57
+ export declare function buildToolGroupManifest(): string;
58
+
55
59
  export declare function resolveToolGroupState(group: ToolGroupDef, configState: FeatureState, expanded: boolean): ToolGroupState;
56
60
 
57
61
  export declare function buildToolGroupPrompt(collapsedGroups: readonly ToolGroupDef[]): string | undefined;
@@ -1,3 +1,3 @@
1
- import{DRAW_TOOL_NAMES as n,HIRE_TOOL_NAMES as u,LAUNCH_CONFIG_TOOL_NAMES as i,PENCIL_TOOL_NAMES as s}from"./mcp-tools.js";const d=new Set(["disabled","collapsed","expanded"]);function y(e){if(e===!0)return"expanded";if(e===!1)return"disabled";if(typeof e=="string"&&d.has(e))return e}const l=[{key:"launch",label:"\u542F\u52A8\u9879\u7BA1\u7406",featureKey:"agentSys.launchItem",toolNames:i,collapsible:!0,defaultState:"collapsed",summary:"\u7BA1\u7406\u5F00\u53D1\u670D\u52A1\u8FDB\u7A0B\uFF08\u542F\u52A8/\u505C\u6B62/\u91CD\u542F/\u67E5\u770B\u65E5\u5FD7\uFF09"},{key:"hire",label:"\u62DB\u8058\u5DE5\u5177",featureKey:"agentSys.hire",toolNames:u,collapsible:!0,defaultState:"collapsed",summary:"\u62DB\u8058\u65B0\u7684\u540C\u4E8B Agent\uFF08\u5355\u4E2A\u6216\u6279\u91CF\uFF09"},{key:"pencil",label:"\u8BBE\u8BA1\u753B\u5E03(pencil)",featureKey:"pencil",toolNames:s,collapsible:!0,defaultState:"disabled",summary:"UI design editor. Open-source Figma alternative."},{key:"draw",label:"\u7ED8\u56FE",featureKey:"draw",toolNames:n,collapsible:!0,defaultState:"disabled",summary:"\u7ED8\u5236 draw.io \u6D41\u7A0B\u56FE / \u6CF3\u9053\u56FE\uFF0C\u5BFC\u51FA XML"}],p=new Map(l.map(e=>[e.key,e])),f=(()=>{const e=new Map;for(const t of l)for(const a of t.toolNames)e.set(a,t);return e})();function m(e){return p.get(e)}const r=[{key:"browser",label:"\u6D4F\u89C8\u5668\u64CD\u4F5C",featureKey:"browser",defaultState:"collapsed",summary:"\u542F\u52A8\u6D4F\u89C8\u5668\u4F1A\u8BDD\u3001\u5BFC\u822A\u3001\u622A\u56FE\u4E0E\u9875\u9762\u4EA4\u4E92"},{key:"desktop",label:"\u684C\u9762\u64CD\u4F5C",featureKey:"desktop",defaultState:"collapsed",summary:"\u622A\u5C4F\u3001\u9F20\u6807\u952E\u76D8\u63A7\u5236\u4E0E UI \u81EA\u52A8\u5316\uFF08Computer Use\uFF09"}];function b(e){return r.find(t=>t.key===e)}function _(e){return f.get(e)}function S(e){const t=l.find(o=>o.featureKey===e);return t?t.defaultState:r.find(o=>o.featureKey===e)?.defaultState}function x(e){return r.find(t=>e.startsWith(`${t.key}_`))}function O(){return l.filter(e=>e.collapsible).map(e=>e.key)}function T(e,t,a){return e.featureKey&&t==="disabled"?"disabled":e.collapsible&&t==="collapsed"&&!a?"collapsed":"expanded"}function N(e){return e.length===0?void 0:["## \u6309\u9700\u5DE5\u5177\u96C6","","\u4EE5\u4E0B\u5DE5\u5177\u96C6\u9ED8\u8BA4\u6536\u8D77\u4EE5\u4FDD\u6301\u5DE5\u5177\u5217\u8868\u7A33\u5B9A\u5E76\u8282\u7701\u4E0A\u4E0B\u6587\u3002\u5F53\u4EFB\u52A1\u9700\u8981\u65F6\uFF0C\u5148\u8C03\u7528 expand_tools \u5C55\u5F00\uFF0C","\u5DE5\u5177\u5B9A\u4E49\uFF08\u540D\u79F0/\u8BF4\u660E/\u53C2\u6570 schema\uFF09\u968F expand_tools \u7684\u8FD4\u56DE\u7ED3\u679C\u4E0B\u53D1\uFF0C\u5F53\u8F6E\u5373\u53EF\u7ECF call_tool \u8C03\u7528\uFF1A",'call_tool({ name: "<\u5DE5\u5177\u540D>", arguments: {...} })',"",...e.map(a=>`- ${a.key}\uFF08${a.label}\uFF09\uFF1A${a.summary}`),"",'\u793A\u4F8B\uFF1Aexpand_tools({ group: "pencil" })'].join(`
2
- `)}export{r as BRIDGE_LAZY_CAPABILITIES,l as TOOL_GROUPS,N as buildToolGroupPrompt,O as collapsibleToolGroupKeys,S as defaultStateForFeatureKey,x as findBridgeCapabilityByToolName,b as findBridgeLazyCapability,m as findToolGroup,_ as findToolGroupByToolName,y as normalizeFeatureState,T as resolveToolGroupState};
1
+ import{DEBUG_LOG_TOOL_NAMES as n,DRAW_TOOL_NAMES as s,EMAIL_TOOL_NAMES as u,FILE_CHANGES_HISTORY_TOOL_NAMES as i,HIRE_TOOL_NAMES as d,LAUNCH_CONFIG_TOOL_NAMES as f,MEETING_TOOL_NAMES as p,OFFICE_TOOL_NAMES as c,PENCIL_TOOL_NAMES as m,TASK_TOOL_NAMES as y}from"./mcp-tools.js";const b=new Set(["disabled","collapsed","expanded"]);function T(e){if(e===!0)return"expanded";if(e===!1)return"disabled";if(typeof e=="string"&&b.has(e))return e}const a=[{key:"launch",label:"\u542F\u52A8\u9879\u7BA1\u7406",featureKey:"agentSys.launchItem",toolNames:f,collapsible:!0,defaultState:"collapsed",summary:"\u7BA1\u7406\u9879\u76EE\u4E2D\u4E1A\u52A1\u7A0B\u5E8F\u7684\u8D77\u505C\uFF0C\u82E5\u540E\u9762\u9700\u8981\u542F\u52A8\u9879\u76EE\u5E94\u4F7F\u7528\u6B64\u5DE5\u5177"},{key:"hire",label:"\u62DB\u8058\u5DE5\u5177",featureKey:"agentSys.hire",toolNames:d,collapsible:!0,defaultState:"collapsed",summary:"\u62DB\u8058\u65B0\u7684\u540C\u4E8B Agent\uFF08\u5355\u4E2A\u6216\u6279\u91CF\uFF09"},{key:"pencil",label:"\u8BBE\u8BA1\u753B\u5E03(pencil)",featureKey:"pencil",toolNames:m,collapsible:!0,defaultState:"collapsed",summary:"UI design editor. Open-source Figma alternative."},{key:"draw",label:"\u7ED8\u56FE",featureKey:"draw",toolNames:s,collapsible:!0,defaultState:"collapsed",summary:"\u7ED8\u5236 draw.io \u6D41\u7A0B\u56FE / \u6CF3\u9053\u56FE\uFF0C\u5BFC\u51FA XML"},{key:"office",label:"Office \u6587\u4EF6",featureKey:"office",toolNames:c,collapsible:!0,defaultState:"collapsed",summary:"\u521B\u5EFA\u4E0E\u7F16\u8F91 Word/Excel/PowerPoint\uFF08docx/xlsx/pptx\uFF0CApache POI \u683C\u5F0F\u5C42\uFF09\uFF1AWord \u652F\u6301 run/\u5355\u5143\u683C\u7EA7\u7CBE\u51C6\u7F16\u8F91\u3001\u6279\u6CE8\u3001\u4FEE\u8BA2\u3001\u516C\u5F0F\u3001\u76EE\u5F55\u9875\u7801\u3001\u4E09\u7EBF\u8868\u3001\u6807\u9898\u7F16\u53F7\u4E0E\u683C\u5F0F\u89C4\u8303\u68C0\u67E5/\u4E00\u952E\u4FEE\u6B63\uFF1B\u6821\u9A8C\u3001\u751F\u6210 HTML \u9884\u89C8\u3001\u5728 Dashboard \u9762\u677F\u4E2D\u5B9E\u65F6\u67E5\u770B\uFF0C\u53EF\u53D1\u6D88\u606F\u5361\u7247\u5206\u4EAB\u6587\u4EF6\uFF1B\u6587\u6863\u81EA\u52A8\u767B\u8BB0\u4E3A\u4E91\u6587\u6863\uFF0C\u652F\u6301\u5217\u51FA/\u5206\u4EAB\u7ED9\u5176\u4ED6 Agent \u534F\u4F5C\uFF08read|write\uFF09\u4E0E\u8FFD\u8D76\u53D8\u66F4"},{key:"task",label:"\u6D41\u7A0B\u4EFB\u52A1",featureKey:"collaboration.task",toolNames:y,collapsible:!0,defaultState:"collapsed",summary:"\u5904\u7406\u6D41\u7A0B\u7EBF\u4EFB\u52A1\uFF1A\u67E5\u770B\u5F53\u524D\u4EFB\u52A1\u3001\u63D0\u4EA4\u6267\u884C\u7ED3\u679C\u3001\u56DE\u9000\u4EFB\u52A1\u3001\u7ED9\u6D41\u7A0B\u5B9E\u4F8B\u7559\u8A00"},{key:"meeting",label:"\u4F1A\u8BAE",featureKey:"collaboration.meeting",toolNames:p,collapsible:!0,defaultState:"collapsed",summary:"\u521B\u5EFA/\u52A0\u5165\u4F1A\u8BAE\u3001\u53D1\u8A00\u3001\u67E5\u770B\u4F1A\u8BAE\u4FE1\u606F\u3001\u79BB\u5F00/\u7ED3\u675F\u4F1A\u8BAE"},{key:"debug",label:"\u8C03\u8BD5\u65E5\u5FD7",featureKey:"collaboration.debug",toolNames:n,collapsible:!0,defaultState:"collapsed",summary:"\u6309\u6761\u4EF6\u5206\u9875\u67E5\u8BE2 Debug \u65E5\u5FD7\u4E0E\u83B7\u53D6\u65E5\u5FD7\u4E0A\u62A5\u914D\u7F6E"},{key:"fileHistory",label:"\u6587\u4EF6\u53D8\u66F4\u5386\u53F2",featureKey:"collaboration.fileHistory",toolNames:i,collapsible:!0,defaultState:"collapsed",summary:"\u6309\u89D2\u8272/\u5B9E\u4F8B/\u6587\u4EF6\u8DEF\u5F84\u8FC7\u6EE4\u67E5\u8BE2\u6587\u4EF6\u53D8\u66F4\u5386\u53F2"},{key:"email",label:"\u90AE\u7BB1",featureKey:"email",toolNames:u,collapsible:!0,defaultState:"collapsed",summary:"\u6536\u53D1\u89D2\u8272\u5B9E\u4F8B\u57DF\u540D\u90AE\u7BB1\uFF08xxxxx@\u57DF\u540D\uFF09\uFF1A\u53D1\u4FE1\u3001\u5217\u90AE\u4EF6\u3001\u8BFB\u6B63\u6587\u4E0E\u9644\u4EF6\u3001\u56DE\u4FE1\u4FDD\u6301\u7EBF\u7A0B"}],_=new Map(a.map(e=>[e.key,e])),O=(()=>{const e=new Map;for(const t of a)for(const l of t.toolNames)e.set(l,t);return e})();function x(e){return _.get(e)}const r=[{key:"browser",label:"\u6D4F\u89C8\u5668\u64CD\u4F5C",featureKey:"browser",defaultState:"collapsed",summary:"\u542F\u52A8\u6D4F\u89C8\u5668\u4F1A\u8BDD\u3001\u5BFC\u822A\u3001\u622A\u56FE\u4E0E\u9875\u9762\u4EA4\u4E92"},{key:"desktop",label:"\u684C\u9762\u64CD\u4F5C",featureKey:"desktop",defaultState:"disabled",summary:"\u622A\u5C4F\u3001\u9F20\u6807\u952E\u76D8\u63A7\u5236\u4E0E UI \u81EA\u52A8\u5316\uFF08Computer Use\uFF09"}];function E(e){return r.find(t=>t.key===e)}function A(e){return O.get(e)}function L(e){const t=a.find(o=>o.featureKey===e);return t?t.defaultState:r.find(o=>o.featureKey===e)?.defaultState}function k(e){return r.find(t=>e.startsWith(`${t.key}_`))}function M(){return a.filter(e=>e.collapsible).map(e=>e.key)}const S="ACODE_TOOL_GROUPS_V1:";function I(){const e=a.filter(t=>t.collapsible).map(t=>({key:t.key,label:t.label,toolNames:[...t.toolNames]}));return`${S}${JSON.stringify({groups:e})}`}function K(e,t,l){return e.featureKey&&t==="disabled"?"disabled":e.collapsible&&t==="collapsed"&&!l?"collapsed":"expanded"}function g(e){return e.length===0?void 0:["## \u6309\u9700\u5DE5\u5177\u96C6","","\u4EE5\u4E0B\u5DE5\u5177\u96C6\u9ED8\u8BA4\u6536\u8D77\u4EE5\u4FDD\u6301\u5DE5\u5177\u5217\u8868\u7A33\u5B9A\u5E76\u8282\u7701\u4E0A\u4E0B\u6587\u3002\u5F53\u4EFB\u52A1\u9700\u8981\u65F6\uFF0C\u5148\u8C03\u7528 expand_tools \u5C55\u5F00\uFF0C","\u5DE5\u5177\u5B9A\u4E49\uFF08\u540D\u79F0/\u8BF4\u660E/\u53C2\u6570 schema\uFF09\u968F expand_tools \u7684\u8FD4\u56DE\u7ED3\u679C\u4E0B\u53D1\uFF0C\u5F53\u8F6E\u5373\u53EF\u7ECF call_tool \u8C03\u7528\uFF1A",'call_tool({ name: "<\u5DE5\u5177\u540D>", arguments: {...} })',"",...e.map(l=>`- ${l.key}\uFF08${l.label}\uFF09\uFF1A${l.summary}`),"",'\u793A\u4F8B\uFF1Aexpand_tools({ group: "pencil" })'].join(`
2
+ `)}export{r as BRIDGE_LAZY_CAPABILITIES,a as TOOL_GROUPS,S as TOOL_GROUP_MANIFEST_PREFIX,I as buildToolGroupManifest,g as buildToolGroupPrompt,M as collapsibleToolGroupKeys,L as defaultStateForFeatureKey,k as findBridgeCapabilityByToolName,E as findBridgeLazyCapability,x as findToolGroup,A as findToolGroupByToolName,T as normalizeFeatureState,K as resolveToolGroupState};
3
3
 
@@ -174,10 +174,49 @@ export interface GroupRoomInfo {
174
174
  export interface GroupRoomsResponse {
175
175
  groups: GroupRoomInfo[];
176
176
  }
177
+
178
+ export interface ProjectHumanMember {
179
+ userId: string;
180
+ nickname: string;
181
+
182
+ projectRole: string;
183
+
184
+ isOwner: boolean;
185
+
186
+ online: boolean;
187
+ avatarUrl?: string;
188
+ }
189
+ export interface ProjectMembersResponse {
190
+ projectId: string | null;
191
+ members: ProjectHumanMember[];
192
+ onlineCount?: number;
193
+ totalCount?: number;
194
+
195
+ note?: string;
196
+ }
197
+
198
+ export interface ReplyToRef {
199
+
200
+ messageId: string;
201
+
202
+ senderId?: string;
203
+
204
+ senderName?: string;
205
+
206
+ snapshot?: string;
207
+
208
+ prefix?: string;
209
+
210
+ suffix?: string;
211
+
212
+ pos?: number;
213
+ }
177
214
  export interface GroupMessage {
178
215
  msgId: number;
179
216
  senderId: string;
180
217
  senderName: string;
218
+
219
+ senderType?: "HUMAN" | "AGENT" | string;
181
220
  projectId?: string;
182
221
  roomId?: string;
183
222
 
@@ -185,6 +224,8 @@ export interface GroupMessage {
185
224
  content: string;
186
225
  timestamp: string;
187
226
 
227
+ replyTo?: ReplyToRef[];
228
+
188
229
  tokens?: TokenUsage;
189
230
 
190
231
  modelInfo?: ModelInfo;
@@ -216,6 +257,8 @@ export interface DirectMessage {
216
257
  callId?: string;
217
258
  senderId: string;
218
259
  senderName: string;
260
+
261
+ senderType?: "HUMAN" | "AGENT" | string;
219
262
  receiverId?: string;
220
263
  content: string;
221
264
  requireReply: boolean;
@@ -223,6 +266,8 @@ export interface DirectMessage {
223
266
  force?: boolean;
224
267
  prompt?: string;
225
268
 
269
+ replyTo?: ReplyToRef[];
270
+
226
271
  role?: 'system' | 'user' | 'assistant';
227
272
  timestamp: string;
228
273
 
@@ -426,15 +471,19 @@ export interface HireBatchResult {
426
471
  results: HireBatchItemResult[];
427
472
  }
428
473
 
429
- export type McpToolName = "get_colleague" | "get_group_rooms" | "get_profile" | "hire_colleague" | "send_group" | "send_private" | "poll_message" | "get_message" | "get_dm_history" | "get_group_history" | "start_listening" | "stop_listening";
474
+ export type McpToolName = "get_colleague" | "get_group_rooms" | "list_project_members" | "get_profile" | "hire_colleague" | "send_group" | "send_private" | "poll_message" | "get_message" | "get_dm_history" | "get_group_history" | "start_listening" | "stop_listening";
430
475
 
431
- export type CardType = "pencil" | "draw";
476
+ export type CardType = "pencil" | "draw" | "office";
432
477
 
433
478
  export interface Card {
434
479
 
435
480
  type: CardType;
436
481
 
437
- docId: string;
482
+ docId?: string;
483
+
484
+ filePath?: string;
485
+
486
+ previewUrl?: string;
438
487
 
439
488
  title?: string;
440
489
 
@@ -451,6 +500,8 @@ export interface SendPrivateArgs {
451
500
  attachments?: string[];
452
501
 
453
502
  card?: Card;
503
+
504
+ replyTo?: ReplyToRef[];
454
505
  }
455
506
 
456
507
  export interface SendGroupArgs {
@@ -461,6 +512,8 @@ export interface SendGroupArgs {
461
512
  attachments?: string[];
462
513
 
463
514
  card?: Card;
515
+
516
+ replyTo?: ReplyToRef[];
464
517
  }
465
518
 
466
519
  export interface GetDmHistoryArgs {
@@ -1,2 +1,2 @@
1
- import{EventEmitter as f}from"node:events";import c from"ws";import{logger as r}from"./logger.js";import{meetingDebugLog as u}from"./meeting-debug-log.js";const T=9e3,S=3e4,b=1e3,l=100,d=3,g=3,k=5,p=6e4,E=50,m=1e3;class _ extends f{ws=null;config;agentId=null;heartbeatTimer=null;heartbeatTimeoutTimer=null;reconnectAttempts=0;reconnectTimer=null;isManualClose=!1;websocketFactory;openedAt=null;lastRefreshedToken=null;consecutiveRefreshFailures=0;logBatchQueue=[];logBatchTimer=null;logSequenceNumber=0;pendingLogBatches=new Map;isProcessingLogBatch=!1;processedMsgIds=new Map;constructor(e,t){super(),this.config=e,this.websocketFactory=t??(s=>new c(s))}connect(e){return new Promise((t,s)=>{this.prepareConnection(e);const n=this.buildWebSocketUrl(e);r.info(`[WebSocket] \u6B63\u5728\u8FDE\u63A5: ${this.maskRuntimeTokenInUrl(n)}`);const{rejectOnce:o,resolveOnce:i}=this.createSettledHandlers(t,s);try{this.ws=this.websocketFactory(n),this.setupWebSocketEventHandlers(this.ws,o,i)}catch(a){o(a instanceof Error?a:new Error(String(a)))}})}prepareConnection(e){this.agentId=e,this.isManualClose=!1,this.ws&&this.ws.readyState!==c.CLOSED&&(this.ws.removeAllListeners(),this.ws.terminate())}buildWebSocketUrl(e){const t=new URL(this.config.serverUrl);t.searchParams.set("agentId",e);const s=this.config.runtimeAccessToken?.trim();return s&&t.searchParams.set("runtimeAccessToken",s),t.toString()}maskRuntimeTokenInUrl(e){try{const t=new URL(e);return t.searchParams.has("runtimeAccessToken")&&t.searchParams.set("runtimeAccessToken","***"),t.toString()}catch{return e.replace(/([?&]runtimeAccessToken=)[^&]*/u,"$1***")}}createSettledHandlers(e,t){let s=!1;return{rejectOnce:i=>{s||(s=!0,t(i))},resolveOnce:()=>{s||(s=!0,e())}}}setupWebSocketEventHandlers(e,t,s){let n=!1;e.on("open",()=>{n=!0,this.handleWebSocketOpen(s)}),e.on("message",o=>this.handleWebSocketMessage(o)),e.on("pong",()=>this.markHeartbeatReceived()),e.on("close",(o,i)=>this.handleWebSocketClose(o,i,n,t)),e.on("error",o=>this.handleWebSocketError(o,n,t))}handleWebSocketOpen(e){r.info("[WebSocket] \u8FDE\u63A5\u5DF2\u5EFA\u7ACB"),this.openedAt=Date.now(),this.lastRefreshedToken=null,this.clearReconnectTimer(),this.startHeartbeat(),this.emit("connected"),e()}handleWebSocketMessage(e){try{const t=JSON.parse(e.toString()),s=this.extractReliableMessageId(t),n=s!==null&&this.markMsgIdProcessed(s);if(this.acknowledgeReliableMessage(t),n){r.info("[WebSocket] \u5FFD\u7565\u91CD\u590D\u6295\u9012\u7684\u53EF\u9760\u6D88\u606F: msgId=%s, type=%s",s,t.type);return}this.handleMessage(t)}catch(t){const s=e.toString(),n=s.length>200?`${s.slice(0,200)}...(truncated, ${s.length} total)`:s;r.warn("[WebSocket] \u6D88\u606F\u89E3\u6790\u5931\u8D25, dataLength=%s, preview=%s:",s.length,n,t)}}extractReliableMessageId(e){const t=e.data;if(!t||typeof t!="object")return null;const s=t,n=String(s._msgId||"").trim(),o=s._requireAck===!0||s._requireAck==="true";return!n||!o?null:n}markMsgIdProcessed(e){if(this.processedMsgIds.has(e))return!0;if(this.processedMsgIds.set(e,Date.now()),this.processedMsgIds.size>m){let t=0;const s=this.processedMsgIds.size-m;for(const n of this.processedMsgIds.keys()){if(t>=s)break;this.processedMsgIds.delete(n),t++}}return!1}acknowledgeReliableMessage(e){const t=this.extractReliableMessageId(e);t&&this.send({type:"MESSAGE_ACK",data:{msgId:t},timestamp:new Date().toISOString()})}async handleWebSocketClose(e,t,s,n){const o=t.toString(),i=this.ws?.readyState;r.warn(`[WebSocket] \u8FDE\u63A5\u5173\u95ED: code=${e}, reason=${o}, readyState=${i}, opened=${s}, reconnectAttempts=${this.reconnectAttempts}`),this.stopHeartbeat(),this.clearHeartbeatTimeout(),this.emit("disconnected",e,t),this.openedAt!==null&&Date.now()-this.openedAt>=p&&(this.reconnectAttempts=0,this.consecutiveRefreshFailures=0),this.openedAt=null,s||n(new Error(`WebSocket \u8FDE\u63A5\u5728\u5EFA\u7ACB\u524D\u5173\u95ED: code=${e}, reason=${o}`)),this.isManualClose||(e===1008?await this.handleTokenExpiredAndReconnect():this.scheduleReconnect())}async handleTokenExpiredAndReconnect(){const e=await this.refreshRuntimeTokenOnPolicyRejection();if(e==="refreshed"){r.info("[WebSocket] runtime token \u5DF2\u5237\u65B0\uFF0C\u4F7F\u7528\u65B0 token \u91CD\u8FDE"),this.consecutiveRefreshFailures=0,this.scheduleReconnect();return}if(e==="unchanged"){r.warn("[WebSocket] bridge \u8FD4\u56DE token \u672A\u53D8\u5316\u4E14\u670D\u52A1\u7AEF 1008 \u62D2\u7EDD\uFF0C\u8FDB\u5165\u6162\u901F\u91CD\u8BD5\u7B49\u5F85\u65B0 token \u7B7E\u53D1"),this.emit("tokenRejected",this.config.runtimeAccessToken),this.enterSlowReconnect();return}if(this.consecutiveRefreshFailures+=1,this.consecutiveRefreshFailures>=g){r.error(`[WebSocket] runtime token \u5237\u65B0\u8FDE\u7EED\u5931\u8D25 ${this.consecutiveRefreshFailures} \u6B21\uFF0C\u964D\u7EA7\u4E3A\u6162\u901F\u91CD\u8BD5\u7B49\u5F85 bridge \u6062\u590D`),this.emit("tokenRefreshFailed",this.consecutiveRefreshFailures),this.enterSlowReconnect();return}r.warn(`[WebSocket] runtime token \u5237\u65B0\u5931\u8D25\uFF0C\u7B2C ${this.consecutiveRefreshFailures}/${g} \u6B21\u5C1D\u8BD5\u91CD\u8FDE`),this.scheduleReconnect()}enterSlowReconnect(){this.reconnectAttempts=Math.max(this.reconnectAttempts,k),this.scheduleReconnect()}async refreshRuntimeTokenOnPolicyRejection(){const e=this.config.runtimeBridgeBaseUrl;if(!e||!this.agentId)return"failed";const t=this.config.runtimeAccessToken||"",s=Math.min(this.config.mcpHttpRequestTimeoutMs??12e4,1e4),n=new AbortController,o=setTimeout(()=>n.abort(),s);try{const i=await fetch(`${e}/runtime/binding/refresh-token`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({agentId:this.agentId,currentToken:t,forceRefresh:!0}),signal:n.signal});if(!i.ok)return r.warn(`[WebSocket] bridge refresh-token \u8FD4\u56DE ${i.status}\uFF0C\u65E0\u6CD5\u5237\u65B0`),"failed";const h=(await i.json()).runtimeAccessToken;return!h||h===t?"unchanged":(this.config.runtimeAccessToken=h,this.lastRefreshedToken=t,r.info("[WebSocket] runtimeAccessToken \u5DF2\u901A\u8FC7 bridge refresh \u66F4\u65B0"),"refreshed")}catch(i){return i instanceof Error&&i.name==="AbortError"?r.warn(`[WebSocket] bridge refresh-token \u8D85\u65F6\uFF08${s}ms\uFF09`):(r.warn("[WebSocket] bridge refresh-token \u5F02\u5E38: %s",i instanceof Error?i.message:String(i)),i instanceof Error&&i.stack&&r.warn("[WebSocket] refresh-token \u5F02\u5E38\u5806\u6808:",i.stack.slice(0,2e3))),"failed"}finally{clearTimeout(o)}}handleWebSocketError(e,t,s){const n=this.ws?.readyState;r.error("[WebSocket] \u8FDE\u63A5\u9519\u8BEF: readyState=%s, opened=%s, reconnectAttempts=%s, message=%s",n,t,this.reconnectAttempts,e.message),r.error("[WebSocket] \u9519\u8BEF\u5806\u6808:",e.stack?.slice(0,2e3)),this.emit("error",e),t||s(e)}disconnect(){this.isManualClose=!0,this.stopHeartbeat(),this.clearHeartbeatTimeout(),this.clearReconnectTimer(),this.ws&&(this.ws.readyState===c.OPEN&&this.ws.close(1e3,"Agent logout"),this.ws=null),this.agentId=null,r.info("[WebSocket] \u5DF2\u65AD\u5F00\u8FDE\u63A5")}send(e){const t=this.ws?.readyState;if(!this.ws||t!==c.OPEN)return r.warn("[WebSocket] \u8FDE\u63A5\u672A\u5EFA\u7ACB\uFF0C\u65E0\u6CD5\u53D1\u9001\u6D88\u606F: readyState=%s, isManualClose=%s, agentId=%s",t,this.isManualClose,this.agentId),!1;try{return this.ws.send(JSON.stringify(e)),!0}catch(s){return r.error("[WebSocket] send() \u53D1\u9001\u6D88\u606F\u5F02\u5E38: readyState=%s, error=%s",t,s),!1}}sendMcpNodeLog(e){return this.isConnected()?(this.logBatchQueue.push(e),this.logBatchTimer||(this.logBatchTimer=setTimeout(()=>{this.logBatchTimer=null,this.flushLogBatch()},l)),!0):!1}flushLogBatch(){if(this.logBatchQueue.length===0||this.isProcessingLogBatch)return;const e=this.logBatchQueue.splice(0,E);if(e.length===0)return;this.isProcessingLogBatch=!0,this.logSequenceNumber+=1;const t=this.logSequenceNumber;new Promise((n,o)=>{this.pendingLogBatches.set(t,{logs:e,sequenceNumber:t,retryCount:0,resolve:n,reject:o})}).then(()=>{this.isProcessingLogBatch=!1,this.logBatchQueue.length>0&&(this.logBatchTimer=setTimeout(()=>{this.logBatchTimer=null,this.flushLogBatch()},l))}).catch(()=>{this.isProcessingLogBatch=!1}),this.sendLogBatch(t)}sendLogBatch(e){const t=this.pendingLogBatches.get(e);if(!t)return;this.send({type:"MCP_NODE_LOG_BATCH",data:{sequenceNumber:e,logs:t.logs},timestamp:new Date().toISOString()})||this.handleLogBatchSendFailure(e)}handleLogBatchSendFailure(e){const t=this.pendingLogBatches.get(e);t&&(t.retryCount+=1,t.retryCount<=d?(r.warn(`[WebSocket] \u65E5\u5FD7\u6279\u6B21 #${e} \u53D1\u9001\u5931\u8D25\uFF0C\u7B2C ${t.retryCount} \u6B21\u91CD\u8BD5`),setTimeout(()=>{this.sendLogBatch(e)},l*t.retryCount)):(r.error(`[WebSocket] \u65E5\u5FD7\u6279\u6B21 #${e} \u53D1\u9001\u5931\u8D25\uFF0C\u5DF2\u91CD\u8BD5 ${d} \u6B21\uFF0C\u4E22\u5F03`),this.pendingLogBatches.delete(e),t.reject(new Error(`\u65E5\u5FD7\u6279\u6B21 #${e} \u53D1\u9001\u5931\u8D25`))))}handleLogAck(e){const s=Number(e?.ackSequenceNumber);if(!s||!this.pendingLogBatches.has(s))return;const n=this.pendingLogBatches.get(s);n&&(this.pendingLogBatches.delete(s),n.resolve())}isConnected(){return this.ws!==null&&this.ws.readyState===c.OPEN}handleMessage(e){switch(e.type){case"GROUP_MSG":this.emit("groupMessage",e.data);break;case"DM_MSG":this.emit("directMessage",e.data);break;case"MEETING_MSG":u("ws.MEETING_MSG",`\u6536\u5230\u4F1A\u8BAE\u6D88\u606F WS \u63A8\u9001: msgId=${String(e.data?.msgId??"-")} content=${String(e.data?.content??"").slice(0,120)}`),this.emit("meetingMessage",e.data);break;case"SYSTEM_NOTIFY":u("ws.SYSTEM_NOTIFY",`type=${String(e.data?.type??"-")}`),this.emit("systemNotify",e.data);break;case"ONLINE_CHANGE":this.emit("onlineChange",e.data);break;case"HEARTBEAT":this.markHeartbeatReceived();break;case"PROFILE_INFO":r.info("[WebSocket] \u6536\u5230 PROFILE_INFO \u6D88\u606F"),this.emit("profileInfo",e.data);break;case"AGENT_CONFIG":r.info("[WebSocket] \u6536\u5230 AGENT_CONFIG \u6D88\u606F"),this.emit("agentConfig",e.data);break;case"AGENT_STATUS":r.info("[WebSocket] \u6536\u5230 AGENT_STATUS \u6D88\u606F"),this.emit("agentStatus",e.data);break;case"LOG_ACK":this.handleLogAck(e.data);break;case"GROUP_READ_RECEIPT":case"DM_READ_RECEIPT":case"TERMINAL_OUTPUT":case"TERMINAL_STATUS":case"MCP_NODE_LOG":case"AGENT_EVENTS_DELTA":break;default:r.warn("[WebSocket] \u672A\u77E5\u6D88\u606F\u7C7B\u578B:",e.type)}}startHeartbeat(){this.stopHeartbeat(),this.heartbeatTimer=setInterval(()=>{this.isConnected()&&(this.ensureHeartbeatTimeout(),this.sendProtocolPing(),this.send({type:"HEARTBEAT",data:"ping",timestamp:new Date().toISOString()}))},this.config.heartbeatInterval)}stopHeartbeat(){this.heartbeatTimer&&(clearInterval(this.heartbeatTimer),this.heartbeatTimer=null),this.clearHeartbeatTimeout()}sendProtocolPing(){if(!(!this.ws||this.ws.readyState!==c.OPEN))try{this.ws.ping()}catch(e){r.warn("[WebSocket] \u534F\u8BAE\u5C42 ping \u53D1\u9001\u5931\u8D25\uFF0C\u7EC8\u6B62\u8FDE\u63A5\u5E76\u91CD\u8FDE:",e instanceof Error?e.message:String(e)),this.ws.terminate()}}markHeartbeatReceived(){this.clearHeartbeatTimeout()}ensureHeartbeatTimeout(){this.heartbeatTimeoutTimer||(this.heartbeatTimeoutTimer=setTimeout(()=>{this.heartbeatTimeoutTimer=null,!(!this.ws||this.ws.readyState!==c.OPEN)&&(r.warn(`[WebSocket] ${this.resolveHeartbeatTimeout()}ms \u672A\u6536\u5230\u5FC3\u8DF3\u54CD\u5E94\uFF0C\u7EC8\u6B62\u8FDE\u63A5\u5E76\u89E6\u53D1\u91CD\u8FDE`),this.ws.terminate())},this.resolveHeartbeatTimeout()))}clearHeartbeatTimeout(){this.heartbeatTimeoutTimer&&(clearTimeout(this.heartbeatTimeoutTimer),this.heartbeatTimeoutTimer=null)}resolveHeartbeatTimeout(){return this.config.heartbeatTimeout??T}scheduleReconnect(){const e=this.config.maxReconnectAttempts!==-1;if(e&&this.reconnectAttempts>=this.config.maxReconnectAttempts){r.error("[WebSocket] \u91CD\u8FDE\u6B21\u6570\u5DF2\u8FBE\u4E0A\u9650\uFF0C\u653E\u5F03\u91CD\u8FDE"),this.emit("reconnectFailed");return}if(this.reconnectTimer)return;this.reconnectAttempts++;const t=Math.min(this.config.reconnectInterval*Math.pow(2,this.reconnectAttempts-1),this.config.reconnectMaxInterval??S),s=Math.random()*(this.config.reconnectJitterMs??b),n=Math.round(t+s),o=e?`\u7B2C ${this.reconnectAttempts}/${this.config.maxReconnectAttempts} \u6B21`:`\u7B2C ${this.reconnectAttempts} \u6B21\uFF08\u65E0\u9650\u91CD\u8BD5\u6A21\u5F0F\uFF09`;r.warn(`[WebSocket] ${n}ms \u540E\u5C1D\u8BD5${o}\u91CD\u8FDE (base=${Math.round(t)}ms, jitter=+${Math.round(s)}ms)...`),this.reconnectTimer=setTimeout(()=>{this.reconnectTimer=null,this.agentId&&this.connect(this.agentId).catch(i=>{const a=i instanceof Error?i.message:String(i),h=i instanceof Error?i.stack:void 0;r.warn("[WebSocket] \u91CD\u8FDE\u5931\u8D25 (attempt #%s), \u7EE7\u7EED\u91CD\u8BD5: %s",this.reconnectAttempts,a),h&&r.warn("[WebSocket] \u91CD\u8FDE\u5931\u8D25\u5806\u6808:",h.slice(0,2e3)),this.scheduleReconnect()})},n)}clearReconnectTimer(){this.reconnectTimer&&(clearTimeout(this.reconnectTimer),this.reconnectTimer=null)}}export{_ as WebSocketClient};
1
+ import{EventEmitter as f}from"node:events";import a from"ws";import{logger as r}from"./logger.js";import{meetingDebugLog as u}from"./meeting-debug-log.js";const T=9e3,S=3e4,b=1e3,l=100,d=3,g=3,k=5,p=6e4,E=50,m=1e3;class _ extends f{ws=null;config;agentId=null;heartbeatTimer=null;heartbeatTimeoutTimer=null;reconnectAttempts=0;reconnectTimer=null;isManualClose=!1;websocketFactory;openedAt=null;lastRefreshedToken=null;consecutiveRefreshFailures=0;logBatchQueue=[];logBatchTimer=null;logSequenceNumber=0;pendingLogBatches=new Map;isProcessingLogBatch=!1;processedMsgIds=new Map;constructor(e,t){super(),this.config=e,this.websocketFactory=t??(s=>new a(s))}connect(e){return new Promise((t,s)=>{this.prepareConnection(e);const n=this.buildWebSocketUrl(e);r.info(`[WebSocket] \u6B63\u5728\u8FDE\u63A5: ${this.maskRuntimeTokenInUrl(n)}`);const{rejectOnce:o,resolveOnce:i}=this.createSettledHandlers(t,s);try{this.ws=this.websocketFactory(n),this.setupWebSocketEventHandlers(this.ws,o,i)}catch(c){o(c instanceof Error?c:new Error(String(c)))}})}prepareConnection(e){this.agentId=e,this.isManualClose=!1,this.ws&&this.ws.readyState!==a.CLOSED&&(this.ws.removeAllListeners(),this.ws.terminate())}buildWebSocketUrl(e){const t=new URL(this.config.serverUrl);t.searchParams.set("agentId",e);const s=this.config.runtimeAccessToken?.trim();return s&&t.searchParams.set("runtimeAccessToken",s),t.toString()}maskRuntimeTokenInUrl(e){try{const t=new URL(e);return t.searchParams.has("runtimeAccessToken")&&t.searchParams.set("runtimeAccessToken","***"),t.toString()}catch{return e.replace(/([?&]runtimeAccessToken=)[^&]*/u,"$1***")}}createSettledHandlers(e,t){let s=!1;return{rejectOnce:i=>{s||(s=!0,t(i))},resolveOnce:()=>{s||(s=!0,e())}}}setupWebSocketEventHandlers(e,t,s){let n=!1;e.on("open",()=>{n=!0,this.handleWebSocketOpen(s)}),e.on("message",o=>this.handleWebSocketMessage(o)),e.on("pong",()=>this.markHeartbeatReceived()),e.on("close",(o,i)=>this.handleWebSocketClose(o,i,n,t)),e.on("error",o=>this.handleWebSocketError(o,n,t))}handleWebSocketOpen(e){r.info("[WebSocket] \u8FDE\u63A5\u5DF2\u5EFA\u7ACB"),this.openedAt=Date.now(),this.lastRefreshedToken=null,this.clearReconnectTimer(),this.startHeartbeat(),this.emit("connected"),e()}handleWebSocketMessage(e){try{const t=JSON.parse(e.toString()),s=this.extractReliableMessageId(t),n=s!==null&&this.markMsgIdProcessed(s);if(this.acknowledgeReliableMessage(t),n){r.info("[WebSocket] \u5FFD\u7565\u91CD\u590D\u6295\u9012\u7684\u53EF\u9760\u6D88\u606F: msgId=%s, type=%s",s,t.type);return}this.handleMessage(t)}catch(t){const s=e.toString(),n=s.length>200?`${s.slice(0,200)}...(truncated, ${s.length} total)`:s;r.warn("[WebSocket] \u6D88\u606F\u89E3\u6790\u5931\u8D25, dataLength=%s, preview=%s:",s.length,n,t)}}extractReliableMessageId(e){const t=e.data;if(!t||typeof t!="object")return null;const s=t,n=String(s._msgId||"").trim(),o=s._requireAck===!0||s._requireAck==="true";return!n||!o?null:n}markMsgIdProcessed(e){if(this.processedMsgIds.has(e))return!0;if(this.processedMsgIds.set(e,Date.now()),this.processedMsgIds.size>m){let t=0;const s=this.processedMsgIds.size-m;for(const n of this.processedMsgIds.keys()){if(t>=s)break;this.processedMsgIds.delete(n),t++}}return!1}acknowledgeReliableMessage(e){const t=this.extractReliableMessageId(e);t&&this.send({type:"MESSAGE_ACK",data:{msgId:t},timestamp:new Date().toISOString()})}async handleWebSocketClose(e,t,s,n){const o=t.toString(),i=this.ws?.readyState;r.warn(`[WebSocket] \u8FDE\u63A5\u5173\u95ED: code=${e}, reason=${o}, readyState=${i}, opened=${s}, reconnectAttempts=${this.reconnectAttempts}`),this.stopHeartbeat(),this.clearHeartbeatTimeout(),this.emit("disconnected",e,t),this.openedAt!==null&&Date.now()-this.openedAt>=p&&(this.reconnectAttempts=0,this.consecutiveRefreshFailures=0),this.openedAt=null,s||n(new Error(`WebSocket \u8FDE\u63A5\u5728\u5EFA\u7ACB\u524D\u5173\u95ED: code=${e}, reason=${o}`)),this.isManualClose||(e===1008?await this.handleTokenExpiredAndReconnect():this.scheduleReconnect())}async handleTokenExpiredAndReconnect(){const e=await this.refreshRuntimeTokenOnPolicyRejection();if(!this.isManualClose){if(e==="refreshed"){r.info("[WebSocket] runtime token \u5DF2\u5237\u65B0\uFF0C\u4F7F\u7528\u65B0 token \u91CD\u8FDE"),this.consecutiveRefreshFailures=0,this.scheduleReconnect();return}if(e==="unchanged"){r.warn("[WebSocket] bridge \u8FD4\u56DE token \u672A\u53D8\u5316\u4E14\u670D\u52A1\u7AEF 1008 \u62D2\u7EDD\uFF0C\u8FDB\u5165\u6162\u901F\u91CD\u8BD5\u7B49\u5F85\u65B0 token \u7B7E\u53D1"),this.emit("tokenRejected",this.config.runtimeAccessToken),this.enterSlowReconnect();return}if(this.consecutiveRefreshFailures+=1,this.consecutiveRefreshFailures>=g){r.error(`[WebSocket] runtime token \u5237\u65B0\u8FDE\u7EED\u5931\u8D25 ${this.consecutiveRefreshFailures} \u6B21\uFF0C\u964D\u7EA7\u4E3A\u6162\u901F\u91CD\u8BD5\u7B49\u5F85 bridge \u6062\u590D`),this.emit("tokenRefreshFailed",this.consecutiveRefreshFailures),this.enterSlowReconnect();return}r.warn(`[WebSocket] runtime token \u5237\u65B0\u5931\u8D25\uFF0C\u7B2C ${this.consecutiveRefreshFailures}/${g} \u6B21\u5C1D\u8BD5\u91CD\u8FDE`),this.scheduleReconnect()}}enterSlowReconnect(){this.reconnectAttempts=Math.max(this.reconnectAttempts,k),this.scheduleReconnect()}async refreshRuntimeTokenOnPolicyRejection(){const e=this.config.runtimeBridgeBaseUrl;if(!e||!this.agentId)return"failed";const t=this.config.runtimeAccessToken||"",s=Math.min(this.config.mcpHttpRequestTimeoutMs??12e4,1e4),n=new AbortController,o=setTimeout(()=>n.abort(),s);try{const i=await fetch(`${e}/runtime/binding/refresh-token`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({agentId:this.agentId,currentToken:t,forceRefresh:!0}),signal:n.signal});if(!i.ok)return r.warn(`[WebSocket] bridge refresh-token \u8FD4\u56DE ${i.status}\uFF0C\u65E0\u6CD5\u5237\u65B0`),"failed";const h=(await i.json()).runtimeAccessToken;return!h||h===t?"unchanged":(this.config.runtimeAccessToken=h,this.lastRefreshedToken=t,r.info("[WebSocket] runtimeAccessToken \u5DF2\u901A\u8FC7 bridge refresh \u66F4\u65B0"),"refreshed")}catch(i){return i instanceof Error&&i.name==="AbortError"?r.warn(`[WebSocket] bridge refresh-token \u8D85\u65F6\uFF08${s}ms\uFF09`):(r.warn("[WebSocket] bridge refresh-token \u5F02\u5E38: %s",i instanceof Error?i.message:String(i)),i instanceof Error&&i.stack&&r.warn("[WebSocket] refresh-token \u5F02\u5E38\u5806\u6808:",i.stack.slice(0,2e3))),"failed"}finally{clearTimeout(o)}}handleWebSocketError(e,t,s){const n=this.ws?.readyState;r.error("[WebSocket] \u8FDE\u63A5\u9519\u8BEF: readyState=%s, opened=%s, reconnectAttempts=%s, message=%s",n,t,this.reconnectAttempts,e.message),r.error("[WebSocket] \u9519\u8BEF\u5806\u6808:",e.stack?.slice(0,2e3)),this.emit("error",e),t||s(e)}disconnect(){this.isManualClose=!0,this.stopHeartbeat(),this.clearHeartbeatTimeout(),this.clearReconnectTimer(),this.ws&&(this.ws.readyState===a.OPEN?this.ws.close(1e3,"Agent logout"):this.ws.readyState!==a.CLOSED&&this.ws.terminate(),this.ws=null),this.agentId=null,r.info("[WebSocket] \u5DF2\u65AD\u5F00\u8FDE\u63A5")}send(e){const t=this.ws?.readyState;if(!this.ws||t!==a.OPEN)return r.warn("[WebSocket] \u8FDE\u63A5\u672A\u5EFA\u7ACB\uFF0C\u65E0\u6CD5\u53D1\u9001\u6D88\u606F: readyState=%s, isManualClose=%s, agentId=%s",t,this.isManualClose,this.agentId),!1;try{return this.ws.send(JSON.stringify(e)),!0}catch(s){return r.error("[WebSocket] send() \u53D1\u9001\u6D88\u606F\u5F02\u5E38: readyState=%s, error=%s",t,s),!1}}sendMcpNodeLog(e){return this.isConnected()?(this.logBatchQueue.push(e),this.logBatchTimer||(this.logBatchTimer=setTimeout(()=>{this.logBatchTimer=null,this.flushLogBatch()},l)),!0):!1}flushLogBatch(){if(this.logBatchQueue.length===0||this.isProcessingLogBatch)return;const e=this.logBatchQueue.splice(0,E);if(e.length===0)return;this.isProcessingLogBatch=!0,this.logSequenceNumber+=1;const t=this.logSequenceNumber;new Promise((n,o)=>{this.pendingLogBatches.set(t,{logs:e,sequenceNumber:t,retryCount:0,resolve:n,reject:o})}).then(()=>{this.isProcessingLogBatch=!1,this.logBatchQueue.length>0&&(this.logBatchTimer=setTimeout(()=>{this.logBatchTimer=null,this.flushLogBatch()},l))}).catch(()=>{this.isProcessingLogBatch=!1}),this.sendLogBatch(t)}sendLogBatch(e){const t=this.pendingLogBatches.get(e);if(!t)return;this.send({type:"MCP_NODE_LOG_BATCH",data:{sequenceNumber:e,logs:t.logs},timestamp:new Date().toISOString()})||this.handleLogBatchSendFailure(e)}handleLogBatchSendFailure(e){const t=this.pendingLogBatches.get(e);t&&(t.retryCount+=1,t.retryCount<=d?(r.warn(`[WebSocket] \u65E5\u5FD7\u6279\u6B21 #${e} \u53D1\u9001\u5931\u8D25\uFF0C\u7B2C ${t.retryCount} \u6B21\u91CD\u8BD5`),setTimeout(()=>{this.sendLogBatch(e)},l*t.retryCount)):(r.error(`[WebSocket] \u65E5\u5FD7\u6279\u6B21 #${e} \u53D1\u9001\u5931\u8D25\uFF0C\u5DF2\u91CD\u8BD5 ${d} \u6B21\uFF0C\u4E22\u5F03`),this.pendingLogBatches.delete(e),t.reject(new Error(`\u65E5\u5FD7\u6279\u6B21 #${e} \u53D1\u9001\u5931\u8D25`))))}handleLogAck(e){const s=Number(e?.ackSequenceNumber);if(!s||!this.pendingLogBatches.has(s))return;const n=this.pendingLogBatches.get(s);n&&(this.pendingLogBatches.delete(s),n.resolve())}isConnected(){return this.ws!==null&&this.ws.readyState===a.OPEN}handleMessage(e){switch(e.type){case"GROUP_MSG":this.emit("groupMessage",e.data);break;case"DM_MSG":this.emit("directMessage",e.data);break;case"MEETING_MSG":u("ws.MEETING_MSG",`\u6536\u5230\u4F1A\u8BAE\u6D88\u606F WS \u63A8\u9001: msgId=${String(e.data?.msgId??"-")} content=${String(e.data?.content??"").slice(0,120)}`),this.emit("meetingMessage",e.data);break;case"SYSTEM_NOTIFY":u("ws.SYSTEM_NOTIFY",`type=${String(e.data?.type??"-")}`),this.emit("systemNotify",e.data);break;case"ONLINE_CHANGE":this.emit("onlineChange",e.data);break;case"HEARTBEAT":this.markHeartbeatReceived();break;case"PROFILE_INFO":r.info("[WebSocket] \u6536\u5230 PROFILE_INFO \u6D88\u606F"),this.emit("profileInfo",e.data);break;case"AGENT_CONFIG":r.info("[WebSocket] \u6536\u5230 AGENT_CONFIG \u6D88\u606F"),this.emit("agentConfig",e.data);break;case"AGENT_STATUS":r.info("[WebSocket] \u6536\u5230 AGENT_STATUS \u6D88\u606F"),this.emit("agentStatus",e.data);break;case"LOG_ACK":this.handleLogAck(e.data);break;case"GROUP_READ_RECEIPT":case"DM_READ_RECEIPT":case"TERMINAL_OUTPUT":case"TERMINAL_STATUS":case"MCP_NODE_LOG":case"AGENT_EVENTS_DELTA":break;default:r.warn("[WebSocket] \u672A\u77E5\u6D88\u606F\u7C7B\u578B:",e.type)}}startHeartbeat(){this.stopHeartbeat(),this.heartbeatTimer=setInterval(()=>{this.isConnected()&&(this.ensureHeartbeatTimeout(),this.sendProtocolPing(),this.send({type:"HEARTBEAT",data:"ping",timestamp:new Date().toISOString()}))},this.config.heartbeatInterval)}stopHeartbeat(){this.heartbeatTimer&&(clearInterval(this.heartbeatTimer),this.heartbeatTimer=null),this.clearHeartbeatTimeout()}sendProtocolPing(){if(!(!this.ws||this.ws.readyState!==a.OPEN))try{this.ws.ping()}catch(e){r.warn("[WebSocket] \u534F\u8BAE\u5C42 ping \u53D1\u9001\u5931\u8D25\uFF0C\u7EC8\u6B62\u8FDE\u63A5\u5E76\u91CD\u8FDE:",e instanceof Error?e.message:String(e)),this.ws.terminate()}}markHeartbeatReceived(){this.clearHeartbeatTimeout()}ensureHeartbeatTimeout(){this.heartbeatTimeoutTimer||(this.heartbeatTimeoutTimer=setTimeout(()=>{this.heartbeatTimeoutTimer=null,!(!this.ws||this.ws.readyState!==a.OPEN)&&(r.warn(`[WebSocket] ${this.resolveHeartbeatTimeout()}ms \u672A\u6536\u5230\u5FC3\u8DF3\u54CD\u5E94\uFF0C\u7EC8\u6B62\u8FDE\u63A5\u5E76\u89E6\u53D1\u91CD\u8FDE`),this.ws.terminate())},this.resolveHeartbeatTimeout()))}clearHeartbeatTimeout(){this.heartbeatTimeoutTimer&&(clearTimeout(this.heartbeatTimeoutTimer),this.heartbeatTimeoutTimer=null)}resolveHeartbeatTimeout(){return this.config.heartbeatTimeout??T}scheduleReconnect(){if(this.isManualClose)return;const e=this.config.maxReconnectAttempts!==-1;if(e&&this.reconnectAttempts>=this.config.maxReconnectAttempts){r.error("[WebSocket] \u91CD\u8FDE\u6B21\u6570\u5DF2\u8FBE\u4E0A\u9650\uFF0C\u653E\u5F03\u91CD\u8FDE"),this.emit("reconnectFailed");return}if(this.reconnectTimer)return;this.reconnectAttempts++;const t=Math.min(this.config.reconnectInterval*Math.pow(2,this.reconnectAttempts-1),this.config.reconnectMaxInterval??S),s=Math.random()*(this.config.reconnectJitterMs??b),n=Math.round(t+s),o=e?`\u7B2C ${this.reconnectAttempts}/${this.config.maxReconnectAttempts} \u6B21`:`\u7B2C ${this.reconnectAttempts} \u6B21\uFF08\u65E0\u9650\u91CD\u8BD5\u6A21\u5F0F\uFF09`;r.warn(`[WebSocket] ${n}ms \u540E\u5C1D\u8BD5${o}\u91CD\u8FDE (base=${Math.round(t)}ms, jitter=+${Math.round(s)}ms)...`),this.reconnectTimer=setTimeout(()=>{this.reconnectTimer=null,this.agentId&&this.connect(this.agentId).catch(i=>{const c=i instanceof Error?i.message:String(i),h=i instanceof Error?i.stack:void 0;r.warn("[WebSocket] \u91CD\u8FDE\u5931\u8D25 (attempt #%s), \u7EE7\u7EED\u91CD\u8BD5: %s",this.reconnectAttempts,c),h&&r.warn("[WebSocket] \u91CD\u8FDE\u5931\u8D25\u5806\u6808:",h.slice(0,2e3)),this.scheduleReconnect()})},n)}clearReconnectTimer(){this.reconnectTimer&&(clearTimeout(this.reconnectTimer),this.reconnectTimer=null)}}export{_ as WebSocketClient};
2
2
 
@@ -15,7 +15,7 @@
15
15
  "build": "tsc && node ../../scripts/minify-dist.mjs",
16
16
  "dev": "tsc --watch",
17
17
  "start": "node dist/index.js",
18
- "test": "npm run build && tsc -p tsconfig.test.json && node --test --test-timeout=60000 dist-test/*.test.js",
18
+ "test": "npm run build && tsc -p tsconfig.test.json && node --test --test-force-exit --test-timeout=60000 \"dist-test/**/*.test.js\"",
19
19
  "prepare": "npm run build",
20
20
  "lint": "eslint src --max-warnings 0",
21
21
  "lint:fix": "eslint src --fix",
@@ -34,6 +34,7 @@
34
34
  "dependencies": {
35
35
  "@modelcontextprotocol/sdk": "^1.27.1",
36
36
  "aws-runtime-bridge": "file:../..",
37
+ "temml": "^0.13.5",
37
38
  "ws": "^8.14.2",
38
39
  "yaml": "^2.3.4"
39
40
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "aws-runtime-bridge",
3
- "version": "1.9.153",
3
+ "version": "1.9.168",
4
4
  "description": "AgentsWorkStudio runtime bridge service for machine-level agent runtime integration",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -1,16 +0,0 @@
1
-
2
-
3
- export type CapabilityState = "disabled" | "collapsed" | "expanded";
4
-
5
- export interface CapabilityPromptEntry {
6
-
7
- featureKey: string;
8
-
9
- label: string;
10
-
11
- summary: string;
12
- }
13
-
14
- export declare const CAPABILITY_PROMPT_ENTRIES: readonly CapabilityPromptEntry[];
15
-
16
- export declare function buildCapabilityPrompt(stateOf: (featureKey: string) => CapabilityState | undefined): string;
@@ -1,3 +0,0 @@
1
- const o=[{featureKey:"agentSys.launchItem",label:"\u542F\u52A8\u9879\u7BA1\u7406",summary:"\u7BA1\u7406\u5F00\u53D1\u670D\u52A1\u8FDB\u7A0B\uFF08\u542F\u52A8 / \u505C\u6B62 / \u91CD\u542F / \u67E5\u770B\u65E5\u5FD7\uFF09"},{featureKey:"agentSys.hire",label:"\u62DB\u8058\u5DE5\u5177",summary:"\u62DB\u8058\u65B0\u7684\u540C\u4E8B Agent"},{featureKey:"pencil",label:"\u8BBE\u8BA1\u753B\u5E03(pencil)",summary:"UI design editor. Open-source Figma alternative."},{featureKey:"draw",label:"\u7ED8\u56FE",summary:"\u7ED8\u5236 draw.io \u6D41\u7A0B\u56FE / \u6CF3\u9053\u56FE\uFF0C\u5BFC\u51FA XML"},{featureKey:"browser",label:"\u6D4F\u89C8\u5668\u64CD\u4F5C",summary:"\u542F\u52A8\u6D4F\u89C8\u5668\u4F1A\u8BDD\u3001\u5BFC\u822A\u3001\u622A\u56FE\u4E0E\u9875\u9762\u4EA4\u4E92"},{featureKey:"desktop",label:"\u684C\u9762\u64CD\u4F5C",summary:"\u622A\u5C4F\u3001\u9F20\u6807\u952E\u76D8\u63A7\u5236\u4E0E UI \u81EA\u52A8\u5316\uFF08Computer Use\uFF09"}];function u(n){const l=[],a=[],t=[];for(const e of o){const r=n(e.featureKey)??"disabled";r==="disabled"?t.push(e):r==="collapsed"?a.push(e):l.push(e)}const s=["## \u53EF\u7528\u80FD\u529B",""];if(l.length>0||a.length>0){s.push("\u5DF2\u5F00\u542F\uFF1A");for(const e of l)s.push(`- ${e.label}\uFF1A${e.summary}\uFF08\u5DE5\u5177\u5DF2\u53EF\u76F4\u63A5\u8C03\u7528\uFF09`);for(const e of a)s.push(`- ${e.label}\uFF1A${e.summary}\uFF08\u5DE5\u5177\u5DF2\u6536\u8D77\uFF09`);a.length>0&&(s.push(""),s.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 \u5C55\u5F00\uFF0C\u5DE5\u5177\u5B9A\u4E49\u968F\u7ED3\u679C\u8FD4\u56DE\u540E\u5373\u53EF\u7ECF call_tool \u8C03\u7528\u3002"))}else s.push("\u5F53\u524D\u6CA1\u6709\u5DF2\u5F00\u542F\u7684\u6269\u5C55\u80FD\u529B\u3002");if(t.length>0){s.push(""),s.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 e of t)s.push(`- ${e.label}\uFF1A${e.summary}`)}return s.join(`
2
- `)}export{o as CAPABILITY_PROMPT_ENTRIES,u as buildCapabilityPrompt};
3
-
@@ -1,14 +0,0 @@
1
-
2
- import type { ACodeBuiltInTool } from "./built-in-file-tools.js";
3
- import type { ACodePluginBridge } from "./plugin-types.js";
4
- export interface PluginToolsDeps {
5
- pluginBridge?: ACodePluginBridge;
6
- }
7
-
8
- export declare function splitQualifiedToolName(qualifiedName: string): {
9
- plugin: string;
10
- tool: string;
11
- } | null;
12
- export declare function createPluginTools(deps: PluginToolsDeps): ACodeBuiltInTool[];
13
-
14
- export declare function buildPluginPrompt(): string;
@@ -1,9 +0,0 @@
1
- const h=/^[a-z0-9][a-z0-9-]*$/,d=`\u8C03\u7528\u63D2\u4EF6\u5C42\u6CE8\u5165\u7684\u5DE5\u5177\uFF08\u4E09\u65B9\u5DE5\u5177\u7ECF\u63D2\u4EF6\u63A5\u5165\u540E\u7684\u7EDF\u4E00\u8C03\u7528\u5165\u53E3\uFF09\u3002
2
- \u63D2\u4EF6\u5DE5\u5177\u4E0D\u5728\u4F60\u7684\u9759\u6001\u5DE5\u5177\u5217\u8868\u4E2D\uFF1A\u53EF\u7528\u5DE5\u5177\u7684\u7D27\u51D1\u76EE\u5F55\u968F poll_message \u7ED3\u679C\u7684 pluginCatalog \u5B57\u6BB5\u8FD4\u56DE\uFF08\u542B\u63D2\u4EF6\u540D\u3001\u5DE5\u5177\u540D\u3001\u4E00\u53E5\u8BDD\u63CF\u8FF0\u3001\u5FC5\u586B\u53C2\u6570\uFF09\uFF0C\u63D2\u4EF6\u4E8B\u4EF6\u6D88\u606F\u5C3E\u90E8\u4F1A\u9644 toolHints \u63D0\u793A\u5EFA\u8BAE\u8C03\u7528\u7684\u5DE5\u5177\u3002
3
- \u7528\u6CD5\uFF1A
4
- - action=call\uFF08\u9ED8\u8BA4\uFF09\uFF1Atool \u4F20\u9650\u5B9A\u540D "\u63D2\u4EF6\u540D.\u5DE5\u5177\u540D"\uFF08\u5982 "wechat-cli.send_msg"\uFF09\uFF0Cparams \u4F20\u52A8\u6001\u53C2\u6570\u5BF9\u8C61\uFF1B\u53C2\u6570\u6309\u63D2\u4EF6\u58F0\u660E\u7684 JSON Schema \u6821\u9A8C\uFF0C\u6821\u9A8C\u5931\u8D25\u65F6\u8FD4\u56DE\u7ED3\u679C\u4F1A\u9644\u5E26\u5B8C\u6574 inputSchema\uFF0C\u8BF7\u4FEE\u6B63\u540E\u91CD\u8BD5\u3002
5
- - action=schema\uFF1Atool \u4F20\u9650\u5B9A\u540D\uFF08\u652F\u6301 "\u63D2\u4EF6\u540D.*"\uFF09\uFF0C\u8FD4\u56DE\u8BE5\u5DE5\u5177\uFF08\u6216\u63D2\u4EF6\u5168\u90E8\u5DE5\u5177\uFF09\u7684\u5B8C\u6574 JSON Schema \u5B9A\u4E49\u3002\u76EE\u5F55\u63CF\u8FF0\u4E0D\u591F\u7528\u3001\u6216\u53C2\u6570\u6821\u9A8C\u53CD\u590D\u5931\u8D25\u65F6\u5148\u53D6 schema\u3002
6
- - action=catalog\uFF1A\u8FD4\u56DE\u5F53\u524D\u5168\u90E8\u63D2\u4EF6\u7684\u7D27\u51D1\u76EE\u5F55\uFF08\u5B89\u88C5\u65B0\u63D2\u4EF6\u540E\u53EF\u7528\u5B83\u7ACB\u5373\u611F\u77E5\uFF09\u3002
7
- \u6CE8\u610F\uFF1A\u63D2\u4EF6\u672A\u5B89\u88C5/\u5DF2\u505C\u7528/\u5DE5\u5177\u4E0D\u5B58\u5728\u65F6\u8FD4\u56DE\u660E\u786E\u9519\u8BEF\uFF0C\u4E0D\u8981\u51ED\u7A7A\u7F16\u9020\u5DE5\u5177\u540D\u3002`;function _(o){const t=o.indexOf(".");if(t<=0||t>=o.length-1)return null;const c=o.slice(0,t),a=o.slice(t+1);return!h.test(c)||!a.trim()?null:{plugin:c,tool:a.trim()}}function S(o){const t=o.pluginBridge;return t?[y(t)]:[]}function y(o){return{kind:"builtin",toolName:"function_call",exposedName:"function_call",category:"plugin",description:d,inputSchema:{type:"object",properties:{action:{type:"string",enum:["call","schema","catalog"],default:"call",description:"call=\u8C03\u7528\u63D2\u4EF6\u5DE5\u5177\uFF1Bschema=\u53D6\u5B8C\u6574\u53C2\u6570\u5B9A\u4E49\uFF1Bcatalog=\u53D6\u63D2\u4EF6\u5DE5\u5177\u76EE\u5F55"},tool:{type:"string",description:'\u9650\u5B9A\u540D "\u63D2\u4EF6\u540D.\u5DE5\u5177\u540D"\uFF08\u5982 "wechat-cli.send_msg"\uFF09\uFF1Baction=schema \u65F6\u652F\u6301 "\u63D2\u4EF6\u540D.*" \u53D6\u6574\u7EC4\u5B9A\u4E49'},params:{type:"object",description:"call \u7684\u52A8\u6001\u53C2\u6570\u5BF9\u8C61\uFF0C\u6309\u63D2\u4EF6\u58F0\u660E\u7684 inputSchema \u6821\u9A8C"}},required:["tool"],additionalProperties:!1},async execute(t,c){const a=typeof t.action=="string"?t.action:"call",n=typeof t.tool=="string"?t.tool.trim():"";try{if(a==="catalog")return await o.getCatalog();if(!n)return{error:'\u7F3A\u5C11 tool \u53C2\u6570\uFF08\u9650\u5B9A\u540D "\u63D2\u4EF6\u540D.\u5DE5\u5177\u540D"\uFF09'};if(a==="schema"){if(n.endsWith(".*")){const i=n.slice(0,-2),m=await o.getCatalog(),g=m.plugins.find(s=>s.plugin===i);if(!g)return{error:`\u63D2\u4EF6 ${i} \u672A\u5B89\u88C5\u6216\u5DF2\u505C\u7528`,catalog:m.plugins};const f=await Promise.all(g.tools.map(s=>o.getToolSchema(`${i}.${s.name}`)));return{plugin:i,schemas:f.filter(Boolean)}}const p=await o.getToolSchema(n);return p||{error:`\u672A\u77E5\u63D2\u4EF6\u5DE5\u5177: ${n}\uFF08\u53EF\u5148 action=catalog \u67E5\u770B\u76EE\u5F55\uFF09`}}if(a!=="call")return{error:`\u672A\u77E5 action: ${a}\uFF08\u5141\u8BB8\uFF1Acall / schema / catalog\uFF09`};const e=_(n);if(!e)return{error:`tool \u9650\u5B9A\u540D\u4E0D\u5408\u6CD5: ${n}\uFF08\u5E94\u4E3A "\u63D2\u4EF6\u540D.\u5DE5\u5177\u540D"\uFF0C\u63D2\u4EF6\u540D\u4E3A kebab-case\uFF09`};const u=t.params&&typeof t.params=="object"&&!Array.isArray(t.params)?t.params:{},l=await o.invokeTool(e.plugin,e.tool,u,{toolCallId:c?.toolCallId});if(l.ok)return l.result??{ok:!0};const r={error:l.error??"\u63D2\u4EF6\u5DE5\u5177\u8C03\u7528\u5931\u8D25"};return l.inputSchema!==void 0&&(r.inputSchema=l.inputSchema),typeof l.durationMs=="number"&&(r.durationMs=l.durationMs),r}catch(e){return{error:`function_call \u5931\u8D25: ${e instanceof Error?e.message:String(e)}`}}}}}function C(){return["## \u63D2\u4EF6\u7CFB\u7EDF",'- \u4E09\u65B9\u5DE5\u5177\u4EE5\u63D2\u4EF6\u5F62\u5F0F\u63A5\u5165\u3002\u63D2\u4EF6\u5DE5\u5177\u4E0D\u5728\u4F60\u7684\u9759\u6001\u5DE5\u5177\u5217\u8868\u4E2D\uFF1A\u7D27\u51D1\u76EE\u5F55\u968F poll_message \u7ED3\u679C\u7684 pluginCatalog \u5B57\u6BB5\u8FD4\u56DE\uFF1B\u7528 function_call \u8C03\u7528\uFF08tool="\u63D2\u4EF6\u540D.\u5DE5\u5177\u540D"\uFF0Cparams \u4E3A\u52A8\u6001\u53C2\u6570\uFF09\u3002','- \u53C2\u6570\u4E0D\u7B26\u5408\u63D2\u4EF6 schema \u65F6\uFF0Cfunction_call \u4F1A\u8FD4\u56DE\u9519\u8BEF\u5E76\u9644\u5B8C\u6574 inputSchema\uFF0C\u8BF7\u4FEE\u6B63\u540E\u91CD\u8BD5\uFF1B\u76EE\u5F55\u63CF\u8FF0\u4E0D\u8DB3\u65F6\u7528 function_call {action:"schema"} \u53D6\u5B8C\u6574\u5B9A\u4E49\u3002',"- \u63D2\u4EF6\u4E8B\u4EF6\u4EE5 [plugin-event] \u5F00\u5934\u7684\u6D88\u606F\u51FA\u73B0\u5728 poll_message \u7ED3\u679C\u4E2D\uFF0C\u6D88\u606F\u5C3E\u90E8\u6709 toolHints\uFF08\u5EFA\u8BAE\u8C03\u7528\u7684\u5DE5\u5177\uFF09\u4E0E payload\uFF08\u4E8B\u4EF6\u6570\u636E\uFF09\uFF0C\u6309\u63D0\u793A\u7528 function_call \u5904\u7406\u3002",'- \u63D2\u4EF6\u751F\u547D\u5468\u671F\uFF08\u5B89\u88C5/\u5378\u8F7D/\u91CD\u8F7D/\u542F\u505C/\u5217\u8868\uFF09\u4E5F\u662F\u63D2\u4EF6\u5DE5\u5177\uFF1A\u7ECF function_call \u8C03\u7528\u5185\u7F6E\u63D2\u4EF6 plugin-manager \u7684 manage \u5DE5\u5177\uFF0C\u5373 function_call {tool:"plugin-manager.manage", params:{action:"...", ...}}\uFF08plugin-manager \u5728 pluginCatalog \u4E2D\u53EF\u67E5\uFF09\u3002\u672A\u7ECF\u7528\u6237\u660E\u786E\u8981\u6C42\u4E0D\u8981\u5B89\u88C5\u6216\u5378\u8F7D\u63D2\u4EF6\u3002\u5F00\u53D1\u63D2\u4EF6\u5148\u7528\u5185\u7F6E /create-plugin \u547D\u4EE4\u83B7\u53D6\u5F00\u53D1\u89C4\u8303\uFF0C\u5199\u5B8C\u63D2\u4EF6\u76EE\u5F55\u540E\u518D\u7528 function_call \u8C03 plugin-manager.manage install \u751F\u6548\u3002'].join(`
8
- `)}export{C as buildPluginPrompt,S as createPluginTools,_ as splitQualifiedToolName};
9
-