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.
- package/CHANGELOG.md +766 -0
- package/dist/adapter/AcodeSdkAdapter.d.ts +57 -6
- package/dist/adapter/AcodeSdkAdapter.js +4 -8
- package/dist/adapter/ClaudeSdkAdapter.d.ts +2 -0
- package/dist/adapter/ClaudeSdkAdapter.js +3 -3
- package/dist/adapter/CodexSdkAdapter.d.ts +2 -0
- package/dist/adapter/CodexSdkAdapter.js +3 -3
- package/dist/adapter/OpencodeSdkAdapter.d.ts +2 -0
- package/dist/adapter/OpencodeSdkAdapter.js +3 -3
- package/dist/adapter/prompts.d.ts +1 -1
- package/dist/adapter/prompts.js +1 -1
- package/dist/adapter/types.d.ts +41 -20
- package/dist/adapter/types.js +1 -1
- package/dist/browser/frame-encode.d.ts +25 -0
- package/dist/browser/frame-encode.js +2 -0
- package/dist/browser/screencast-differ.d.ts +2 -3
- package/dist/browser/screencast-differ.js +1 -1
- package/dist/browser/screencast-manager.js +1 -1
- package/dist/browser/types.d.ts +5 -1
- package/dist/browser/types.js +1 -1
- package/dist/desktop/desktop-mcp-client.js +2 -2
- package/dist/routes/acode-todos.js +1 -1
- package/dist/routes/background-tasks.js +3 -3
- package/dist/routes/capabilities.js +1 -1
- package/dist/routes/dashboard.d.ts +2 -0
- package/dist/routes/dashboard.js +4 -4
- package/dist/routes/git.js +22 -22
- package/dist/routes/instance.js +1 -1
- package/dist/routes/launch.js +10 -10
- package/dist/routes/ltr.js +1 -1
- package/dist/routes/mcp-extra.js +2 -2
- package/dist/routes/mcp.d.ts +4 -0
- package/dist/routes/mcp.js +1 -1
- package/dist/routes/plugins.js +1 -1
- package/dist/routes/pty.d.ts +11 -3
- package/dist/routes/pty.js +3 -3
- package/dist/routes/runtime-binding.js +1 -1
- package/dist/routes/sessions.d.ts +18 -74
- package/dist/routes/sessions.js +1 -1
- package/dist/routes/skills.js +1 -1
- package/dist/routes/sub-agents.js +8 -8
- package/dist/routes/terminal.d.ts +24 -2
- package/dist/routes/terminal.js +34 -36
- package/dist/services/agent-process-manager.js +1 -1
- package/dist/services/agent-pty-manager.js +4 -4
- package/dist/services/aws-client-agent-mcp.js +2 -2
- package/dist/services/capability-config.d.ts +8 -0
- package/dist/services/capability-config.js +2 -2
- package/dist/services/desktop-mcp-manager.d.ts +3 -1
- package/dist/services/desktop-mcp-manager.js +1 -1
- package/dist/services/instance-ai-config-service.js +1 -1
- package/dist/services/instance-features.d.ts +26 -2
- package/dist/services/instance-features.js +1 -1
- package/dist/services/instance-init-service.js +1 -1
- package/dist/services/launch-manager.d.ts +9 -1
- package/dist/services/launch-manager.js +6 -6
- package/dist/services/launch-metrics.d.ts +1 -1
- package/dist/services/launch-metrics.js +4 -3
- package/dist/services/mcp-deploy.d.ts +4 -0
- package/dist/services/mcp-env-injector.d.ts +12 -0
- package/dist/services/mcp-env-injector.js +2 -0
- package/dist/services/mcp-launch-binding-queue.d.ts +8 -0
- package/dist/services/mcp-launch-binding-queue.js +1 -1
- package/dist/services/orphan-monitor.js +1 -1
- package/dist/services/panel-env.d.ts +6 -2
- package/dist/services/panel-env.js +1 -1
- package/dist/services/plugin-manager.js +9 -9
- package/dist/services/process-detector.d.ts +23 -3
- package/dist/services/process-detector.js +13 -13
- package/dist/services/runtime-resources-snapshot.d.ts +3 -0
- package/dist/services/runtime-resources-snapshot.js +3 -0
- package/dist/services/session-output.d.ts +13 -0
- package/dist/services/session-output.js +4 -4
- package/dist/services/tunnel-client.js +1 -1
- package/dist/services/workspace-files.js +1 -1
- package/dist/services/workspace-watch.js +1 -1
- package/dist/types.d.ts +4 -0
- package/dist/utils/env-safety.d.ts +15 -0
- package/dist/utils/env-safety.js +2 -0
- package/dist/utils/lifecycle-log.d.ts +2 -0
- package/dist/utils/lifecycle-log.js +3 -0
- package/dist/utils/mcp-utils.js +1 -1
- package/package/acode/dist/ask-user-question-tool.js +1 -1
- package/package/acode/dist/await-complete-tool.js +1 -1
- package/package/acode/dist/background-command-manager.js +4 -4
- package/package/acode/dist/background-command-tools.js +1 -1
- package/package/acode/dist/built-in-file-tools.d.ts +31 -2
- package/package/acode/dist/built-in-file-tools.js +2 -2
- package/package/acode/dist/built-in-symbols-tool.js +1 -1
- package/package/acode/dist/builtins/shellCommandPreparation.d.ts +2 -0
- package/package/acode/dist/builtins/shellCommandPreparation.js +2 -2
- package/package/acode/dist/compaction.d.ts +10 -0
- package/package/acode/dist/compaction.js +6 -6
- package/package/acode/dist/context-overflow.d.ts +19 -0
- package/package/acode/dist/context-overflow.js +2 -0
- package/package/acode/dist/grammars/grammars/tree-sitter-lua.wasm +0 -0
- package/package/acode/dist/index.d.ts +4 -1
- package/package/acode/dist/index.js +1 -1
- package/package/acode/dist/mcpToolNames.d.ts +4 -0
- package/package/acode/dist/mcpToolNames.js +1 -1
- package/package/acode/dist/parsers/ast-cache.d.ts +12 -1
- package/package/acode/dist/parsers/ast-cache.js +1 -1
- package/package/acode/dist/parsers/language-queries.js +1 -1
- package/package/acode/dist/parsers/symbol-extractor.js +2 -2
- package/package/acode/dist/parsers/tree-sitter-loader.d.ts +1 -1
- package/package/acode/dist/parsers/tree-sitter-loader.js +1 -1
- package/package/acode/dist/plugin-types.d.ts +5 -0
- package/package/acode/dist/plugin-types.js +1 -0
- package/package/acode/dist/read-file-state.d.ts +48 -0
- package/package/acode/dist/read-file-state.js +2 -0
- package/package/acode/dist/runtime-environment.d.ts +2 -0
- package/package/acode/dist/runtime-environment.js +3 -2
- package/package/acode/dist/runtime.d.ts +124 -10
- package/package/acode/dist/runtime.js +27 -23
- package/package/acode/dist/skill-tool.js +3 -3
- package/package/acode/dist/sub-agent-manager.js +1 -1
- package/package/acode/dist/sub-agent-tools.js +5 -5
- package/package/acode/dist/todo-tool.js +3 -3
- package/package/acode/dist/tool-allocation.js +1 -1
- package/package/acode/dist/tool-concurrency/index.d.ts +5 -0
- package/package/acode/dist/tool-concurrency/index.js +2 -0
- package/package/acode/dist/tool-concurrency/observability.d.ts +46 -0
- package/package/acode/dist/tool-concurrency/observability.js +3 -0
- package/package/acode/dist/tool-concurrency/resource-lock.d.ts +25 -0
- package/package/acode/dist/tool-concurrency/resource-lock.js +2 -0
- package/package/acode/dist/tool-concurrency/scheduler.d.ts +30 -0
- package/package/acode/dist/tool-concurrency/scheduler.js +2 -0
- package/package/acode/dist/tool-concurrency/types.d.ts +80 -0
- package/package/acode/dist/tool-concurrency/types.js +2 -0
- package/package/acode/dist/tool-group-manager.d.ts +128 -0
- package/package/acode/dist/tool-group-manager.js +18 -0
- package/package/acode/dist/types.d.ts +20 -2
- package/package/acode/package.json +3 -3
- package/package/aws-client-agent-mcp/README.md +1 -0
- package/package/aws-client-agent-mcp/dist/agent-client.d.ts +20 -32
- package/package/aws-client-agent-mcp/dist/agent-client.js +1 -1
- package/package/aws-client-agent-mcp/dist/http-client.d.ts +10 -0
- package/package/aws-client-agent-mcp/dist/http-client.js +1 -1
- package/package/aws-client-agent-mcp/dist/logger.d.ts +2 -1
- package/package/aws-client-agent-mcp/dist/logger.js +2 -2
- package/package/aws-client-agent-mcp/dist/mcp-server.d.ts +65 -10
- package/package/aws-client-agent-mcp/dist/mcp-server.js +30 -30
- package/package/aws-client-agent-mcp/dist/mcp-tools.d.ts +42 -7
- package/package/aws-client-agent-mcp/dist/mcp-tools.js +196 -21
- package/package/aws-client-agent-mcp/dist/memory-store.d.ts +2 -0
- package/package/aws-client-agent-mcp/dist/memory-store.js +3 -3
- package/package/aws-client-agent-mcp/dist/message-buffer.js +1 -1
- package/package/aws-client-agent-mcp/dist/office/office-equation.d.ts +5 -0
- package/package/aws-client-agent-mcp/dist/office/office-equation.js +2 -0
- package/package/aws-client-agent-mcp/dist/office/office-image.d.ts +12 -0
- package/package/aws-client-agent-mcp/dist/office/office-image.js +2 -0
- package/package/aws-client-agent-mcp/dist/office/office-workspace.d.ts +40 -0
- package/package/aws-client-agent-mcp/dist/office/office-workspace.js +2 -0
- package/package/aws-client-agent-mcp/dist/status-reporter.js +1 -1
- package/package/aws-client-agent-mcp/dist/tool-groups.d.ts +4 -0
- package/package/aws-client-agent-mcp/dist/tool-groups.js +2 -2
- package/package/aws-client-agent-mcp/dist/types.d.ts +56 -3
- package/package/aws-client-agent-mcp/dist/websocket-client.js +1 -1
- package/package/aws-client-agent-mcp/package.json +2 -1
- package/package.json +1 -1
- package/package/acode/dist/capability-prompt.d.ts +0 -16
- package/package/acode/dist/capability-prompt.js +0 -3
- package/package/acode/dist/plugin-tools.d.ts +0 -14
- 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
|
-
${
|
|
3
|
-
${
|
|
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.
|
|
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,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,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""")}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",
|
|
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{
|
|
2
|
-
`)}export{r as BRIDGE_LAZY_CAPABILITIES,
|
|
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
|
|
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
|
|
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,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
|
-
|