aws-runtime-bridge 1.9.170 → 1.9.172
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 +83 -0
- package/dist/adapter/AcodeSdkAdapter.d.ts +6 -12
- package/dist/adapter/AcodeSdkAdapter.js +3 -3
- package/dist/adapter/ClaudeSdkAdapter.d.ts +2 -0
- package/dist/adapter/ClaudeSdkAdapter.js +3 -3
- package/dist/adapter/types.d.ts +4 -7
- package/dist/index.js +1 -1
- package/dist/routes/terminal.d.ts +8 -0
- package/dist/routes/terminal.js +27 -33
- package/dist/services/agent-startup-memory.d.ts +11 -0
- package/dist/services/agent-startup-memory.js +8 -0
- package/dist/services/log-retention.d.ts +37 -0
- package/dist/services/log-retention.js +2 -0
- package/dist/services/request-invalid-dump.d.ts +21 -0
- package/dist/services/request-invalid-dump.js +2 -0
- package/dist/services/session-output.d.ts +2 -0
- package/dist/services/session-output.js +2 -2
- package/dist/utils/lifecycle-log.d.ts +2 -0
- package/dist/utils/lifecycle-log.js +2 -2
- package/package/acode/dist/ask-user-question-tool.d.ts +11 -1
- package/package/acode/dist/ask-user-question-tool.js +3 -3
- package/package/acode/dist/built-in-file-tools.js +2 -2
- package/package/acode/dist/compaction.d.ts +143 -31
- package/package/acode/dist/compaction.js +20 -6
- package/package/acode/dist/image-utils.js +1 -1
- package/package/acode/dist/runtime-environment.js +1 -1
- package/package/acode/dist/runtime.d.ts +13 -4
- package/package/acode/dist/runtime.js +31 -28
- package/package/acode/dist/types.d.ts +1 -1
- package/package/aws-client-agent-mcp/dist/agent-client.d.ts +2 -0
- package/package/aws-client-agent-mcp/dist/agent-client.js +1 -1
- package/package/aws-client-agent-mcp/dist/mcp-server.js +1 -1
- package/package/aws-client-agent-mcp/dist/mcp-tools.d.ts +4 -0
- package/package/aws-client-agent-mcp/dist/mcp-tools.js +32 -18
- package/package/aws-client-agent-mcp/dist/status-reporter.js +1 -1
- package/package/aws-client-agent-mcp/dist/tool-groups.js +2 -2
- package/package/aws-client-agent-mcp/dist/types.d.ts +15 -1
- package/package.json +1 -1
|
@@ -65,7 +65,7 @@ export interface ACodeSkillGroup {
|
|
|
65
65
|
exists: boolean;
|
|
66
66
|
skills: ACodeSkillMetadata[];
|
|
67
67
|
}
|
|
68
|
-
export type ACodeEventType = "session_started" | "startup_phase" | "ai_request" | "iteration_usage" | "thinking_delta" | "assistant_delta" | "command_output" | "command_status" | "mcp_status" | "skill_status" | "warning" | "turn_complete" | "session_complete" | "context_compaction" | "question_request" | "tool_permission_request" | "error" | "background_command_completed";
|
|
68
|
+
export type ACodeEventType = "session_started" | "startup_phase" | "ai_request" | "iteration_usage" | "thinking_delta" | "assistant_delta" | "command_output" | "command_status" | "mcp_status" | "skill_status" | "warning" | "turn_complete" | "session_complete" | "context_compaction" | "compaction_summary" | "question_request" | "tool_permission_request" | "error" | "background_command_completed";
|
|
69
69
|
export interface ACodeEvent {
|
|
70
70
|
type: ACodeEventType;
|
|
71
71
|
sessionId: string;
|
|
@@ -134,6 +134,8 @@ export declare class AgentClient {
|
|
|
134
134
|
|
|
135
135
|
queryFileChangesHistory(args: Record<string, unknown>): Promise<unknown>;
|
|
136
136
|
|
|
137
|
+
listColleagueEvents(args: Record<string, unknown>): Promise<unknown>;
|
|
138
|
+
|
|
137
139
|
getRuntimeFeatures(): Promise<Record<string, unknown>>;
|
|
138
140
|
|
|
139
141
|
listLaunchConfigs(): Promise<unknown>;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{configManager as h}from"./config.js";import{MESSAGE_POLL_INTERVAL_MS as I}from"./constants.js";import{HttpClient as f}from"./http-client.js";import{logger as i,setMcpNodeLogSink as w,updateStartupLogIdentity as u}from"./logger.js";import{claimRuntimeLaunchBindingDetailed as m}from"./runtime-launch-binding.js";import{StatusReporter as A}from"./status-reporter.js";import{WebSocketClient as p}from"./websocket-client.js";class T extends Error{constructor(e){super(e),this.name="PollLongPollTimeoutError"}}const C=27e4;class N{wsClient;httpClient;agentConfig;serverConfig;agentId=null;displayName=null;projectId=null;isRunning=!1;isDegradedMode=!1;messageHandler=null;profileHandler=null;configHandler=null;systemNotifyHandler=null;pollTimer=null;statusReporter=null;newCharacterHandler=null;runtimeTokenRefreshTimer=null;pendingLaunchBindingClaim=!1;cachedProfile=null;constructor(){h.loadConfig(),this.agentConfig=h.getAgentConfig(),this.serverConfig=h.getServerConfig(),this.wsClient=new p(this.serverConfig),this.httpClient=new f(this.serverConfig),this.setupWebSocketListeners()}async initialize(){const e=await m(this.agentConfig,this.serverConfig);if(e.status==="claimed"){this.applyLaunchBinding(e.binding);return}if(e.status==="unreachable"){this.pendingLaunchBindingClaim=!0,i.warn("[AgentClient] runtime-bridge \u672A\u5C31\u7EEA\uFF0C\u542F\u52A8\u7ED1\u5B9A\u8BA4\u9886\u5DF2\u6302\u8D77\uFF0C\u5C06\u5728\u6CE8\u518C\u91CD\u8BD5\u4E2D\u91CD\u65B0\u8BA4\u9886: %s",e.message);return}this.serverConfig.runtimeBridgeBaseUrl=void 0}applyLaunchBinding(e){h.applyRuntimeLaunchBinding(e),this.agentConfig=h.getAgentConfig(),this.serverConfig=h.getServerConfig(),this.wsClient=new p(this.serverConfig),this.httpClient=new f(this.serverConfig),this.setupWebSocketListeners()}async retryPendingLaunchBindingClaim(){if(!this.pendingLaunchBindingClaim)return!0;const e=await m(this.agentConfig,this.serverConfig);if(e.status==="claimed")return this.pendingLaunchBindingClaim=!1,i.info("[AgentClient] \u542F\u52A8\u7ED1\u5B9A\u8865\u8BA4\u9886\u6210\u529F\uFF0C\u7EE7\u7EED\u6CE8\u518C\u6D41\u7A0B"),this.applyLaunchBinding(e.binding),!0;if(e.status==="missing")return this.pendingLaunchBindingClaim=!1,this.serverConfig.runtimeBridgeBaseUrl=void 0,i.warn("[AgentClient] \u542F\u52A8\u7ED1\u5B9A\u8865\u8BA4\u9886\u672A\u627E\u5230\u5F85\u8BA4\u9886\u8BB0\u5F55\uFF0C\u6309\u65E0\u7ED1\u5B9A\u6A21\u5F0F\u7EE7\u7EED\u6CE8\u518C"),!1;const t=e.status==="unreachable"?e.message:e.reason;return i.warn("[AgentClient] \u542F\u52A8\u7ED1\u5B9A\u8865\u8BA4\u9886\u5931\u8D25\uFF0C\u4FDD\u7559\u6302\u8D77\u72B6\u6001\u7B49\u5F85\u4E0B\u6B21\u6CE8\u518C\u91CD\u8BD5: %s",t),!1}setupWebSocketListeners(){this.wsClient.on("directMessage",e=>{this.handleIncomingDm(e)}),this.wsClient.on("groupMessage",e=>{this.handleIncomingGroup(e)}),this.wsClient.on("meetingMessage",e=>{this.handleIncomingMeeting(e)}),this.wsClient.on("systemNotify",e=>{this.systemNotifyHandler?.(e)}),this.wsClient.on("profileInfo",e=>{i.info(`[AgentClient] WebSocket profileInfo \u4E8B\u4EF6\u89E6\u53D1\uFF0CdisplayName: ${e.displayName}`),this.handleProfileInfo(e)}),this.wsClient.on("agentConfig",e=>{i.info("[AgentClient] WebSocket agentConfig \u4E8B\u4EF6\u89E6\u53D1"),this.configHandler&&this.configHandler(e??{})}),this.wsClient.on("agentStatus",e=>{i.info(`[AgentClient] WebSocket agentStatus \u4E8B\u4EF6\u89E6\u53D1: ${e.status}`)}),this.wsClient.on("disconnected",(e,t)=>{const n=t?.toString()||"";i.warn("[AgentClient] WebSocket \u65AD\u5F00\u8FDE\u63A5: code=%s, reason=%s, agentId=%s, \u6B63\u5728\u81EA\u52A8\u91CD\u8FDE",e,n,this.agentId)}),this.wsClient.on("error",e=>{i.error("[AgentClient] WebSocket \u9519\u8BEF: %s, stack=%s",e.message,e.stack)}),this.wsClient.on("reconnectFailed",()=>{i.error("[AgentClient] \u91CD\u8FDE\u5931\u8D25\uFF08\u5DF2\u8FBE\u91CD\u8BD5\u4E0A\u9650\uFF09\uFF0C\u505C\u6B62\u6D88\u606F\u5FAA\u73AF, agentId=%s",this.agentId),this.stop()}),this.wsClient.on("tokenRejected",()=>{i.error("[AgentClient] runtime token \u88AB 1008 \u62D2\u7EDD\u4E14\u5237\u65B0\u65E0\u53D8\u5316\uFF0C\u8FDB\u5165\u6162\u901F\u91CD\u8BD5\u7B49\u5F85\u65B0 token \u7B7E\u53D1: agentId=%s",this.agentId)}),this.wsClient.on("tokenRefreshFailed",e=>{i.error("[AgentClient] runtime token \u5237\u65B0\u8FDE\u7EED\u5931\u8D25 %s \u6B21\uFF0C\u8FDB\u5165\u6162\u901F\u91CD\u8BD5\u7B49\u5F85 bridge \u6062\u590D: agentId=%s",e,this.agentId)})}async register(){return i.info("[AgentClient] \u6B63\u5728\u6CE8\u518C Agent..."),await this.retryPendingLaunchBindingClaim(),this.hasPresetAgentId()?await this.registerWithExistingAgentId():await this.registerAsNewAgent()}hasPresetAgentId(){return!!(this.agentConfig.agentId&&this.agentConfig.agentId.trim().length>0)}async registerWithExistingAgentId(){const e=this.agentConfig.agentId;if(!e)throw new Error("Preset agentId is missing");this.agentId=e.trim();let t;try{t=await this.getProfileByAgentId(this.agentId)}catch(r){throw i.error("[AgentClient] getProfileByAgentId \u5931\u8D25 (presetAgentId=%s): %s",this.agentId,r instanceof Error?r.message:String(r)),r}this.displayName=t.displayName,this.projectId=t.projectId||null,i.info(`[AgentClient] \u4F7F\u7528\u9884\u8BBE AgentID \u7ED1\u5B9A\u5B9E\u4F8B: ${this.displayName} (${this.agentId})`),i.info(`[AgentClient] \u6240\u5C5E\u9879\u76EE: ${this.projectId||"(\u672A\u8BBE\u7F6E)"}`);try{await this.wsClient.connect(this.agentId)}catch(r){throw i.error("[AgentClient] WebSocket \u8FDE\u63A5\u5931\u8D25 (agentId=%s): %s",this.agentId,r instanceof Error?r.message:String(r)),r}i.info("[AgentClient] WebSocket \u8FDE\u63A5\u5DF2\u5EFA\u7ACB\uFF0CAgent \u73B0\u5728\u5DF2\u4E0A\u7EBF"),this.initializeStatusReporter();const n=await this.getProfileByAgentId(this.agentId);return this.displayName=n.displayName,this.projectId=n.projectId||null,u(n.roleName||"unknown-role",n.instanceName||this.agentId),{agentId:this.agentId,displayName:this.displayName,status:n.isOnline?"online":"offline",projectId:n.projectId,workspacePath:n.workspacePath,runtimeStatus:n.runtimeStatus,runtimeSessionId:n.runtimeSessionId}}async registerAsNewAgent(){const e=await this.httpClient.callTool("register",{roleName:this.agentConfig.roleName,projectId:this.agentConfig.projectId,workspacePath:this.agentConfig.workspacePath,prompt:this.agentConfig.prompt,runtimeBridgeBaseUrl:this.serverConfig.runtimeBridgeBaseUrl}),t=e.agentId;if(!t)throw new Error("Registration failed: agentId was not returned");return this.agentId=t,this.displayName=e.displayName,this.projectId=e.projectId||null,u(this.agentConfig.roleName||"unknown-role",e.instanceName||t),i.info(`[AgentClient] \u6CE8\u518C\u6210\u529F: ${this.displayName} (${this.agentId})`),i.info(`[AgentClient] \u72B6\u6001: ${e.status}`),i.info(`[AgentClient] \u6240\u5C5E\u9879\u76EE: ${this.projectId||"(\u672A\u8BBE\u7F6E)"}`),await this.wsClient.connect(this.agentId),i.info("[AgentClient] WebSocket \u8FDE\u63A5\u5DF2\u5EFA\u7ACB\uFF0CAgent \u73B0\u5728\u5DF2\u4E0A\u7EBF"),this.initializeStatusReporter(),e.isExisting===!1&&this.newCharacterHandler&&this.newCharacterHandler(),e}async unregister(){i.info("[AgentClient] \u6B63\u5728\u6CE8\u9500 Agent..."),this.agentId&&await this.httpClient.callTool("unregister",{agentId:this.agentId}),this.stopRuntimeTokenRefresh(),this.wsClient.disconnect(),this.agentId=null,this.displayName=null,this.projectId=null,this.isRunning=!1,i.info("[AgentClient] \u5DF2\u6CE8\u9500")}async discoverColleagues(){return await this.httpClient.callTool("discover_colleague",{agentId:this.agentId})}async discoverGroupRooms(){return this.ensureRegistered(),await this.httpClient.callTool("discover_group_rooms",{agentId:this.agentId})}async listProjectMembers(){return this.ensureRegistered(),await this.httpClient.callTool("list_project_members",{agentId:this.agentId})}async hireColleague(e){return this.ensureRegistered(),await this.httpClient.callTool("hire_colleague",{...e,agentId:this.agentId})}async callAgentScopedTool(e,t){this.ensureRegistered();const n={...t,agentId:this.agentId};if(e==="create_meeting"){const r=typeof t.waitTimeoutMs=="number"?t.waitTimeoutMs:Number.NaN,s=Number.isFinite(r)&&r>0?Math.min(r,C):C;return await this.httpClient.callToolOnce(e,{...n,waitTimeoutMs:s},0)}return await this.httpClient.callTool(e,n)}async reportMemoryStats(e){await this.callAgentScopedTool("report_memory_stats",{memoryStats:e})}async sendGroupMessage(e,t,n,r,s){this.ensureRegistered();const a=t||this.projectId||this.agentConfig.projectId;return await this.httpClient.callTool("send_group_message",{agentId:this.agentId,projectId:a,roomId:n,content:e,card:r,replyTo:s})}async sendDirectMessage(e,t,n=!1,r,s,a,c){this.ensureRegistered();const g={agentId:this.agentId,targetId:e,content:t,requireReply:n,waitReply:n,replyToCallId:r,card:a,replyTo:c};if(typeof s=="number"&&s>0&&(g.timeoutMs=s),n){const o=typeof s=="number"&&s>0?s+3e4:0;return await this.httpClient.callToolOnce("send_dm",g,o)}return await this.httpClient.callTool("send_dm",g)}async sendCallAndWaitReply(e,t,n=6e4){const r=await this.sendDirectMessage(e,t,!0,void 0,n);if(r.reply)return r.reply;throw new Error("No reply received for call-style direct message before timeout")}async replyToCall(e,t,n){return await this.sendDirectMessage(t,n,!1,e)}async sendEmail(e){return await this.callAgentScopedTool("send_email",e)}async listEmails(e){return await this.callAgentScopedTool("list_emails",e)}async readEmail(e){return await this.callAgentScopedTool("read_email",{mailId:e})}async replyEmail(e){return await this.callAgentScopedTool("reply_email",e)}async ackEmail(e){return await this.callAgentScopedTool("ack_email",{mailId:e})}async getDmHistory(e,t=50,n){this.ensureRegistered();const r={agentId:this.agentId,targetUserId:e,limit:t};return n&&(r.since=n),await this.httpClient.callTool("get_dm_history",r)}async getGroupHistory(e=50,t,n){if(this.ensureRegistered(),t){const o={projectId:this.projectId||this.agentConfig.projectId,roomId:t,limit:e};return n&&(o.since=n),await this.httpClient.callTool("get_group_history",o)}const r=await this.discoverGroupRooms(),s=this.projectId||this.agentConfig.projectId,a=this.collectRoomIds(r,s);if(a.length===0)return{messages:[],count:0};const g=(await Promise.all(a.map(async o=>{const l={projectId:s,roomId:o,limit:e};return n&&(l.since=n),await this.httpClient.callTool("get_group_history",l)}))).flatMap(o=>o.messages).sort((o,l)=>new Date(o.timestamp).getTime()-new Date(l.timestamp).getTime());return{messages:g,count:g.length}}async fetchUnreadMessages(e={}){this.ensureRegistered();const t=this.projectId||this.agentConfig.projectId,n={agentId:this.agentId,blockIfEmpty:e.blockIfEmpty??!1};e.since&&(n.since=e.since),e.blockTimeoutMs&&e.blockTimeoutMs>0&&(n.blockTimeoutMs=e.blockTimeoutMs),e.preemptiveJoinWaitMs!==void 0&&e.preemptiveJoinWaitMs!==null&&e.preemptiveJoinWaitMs>=0&&(n.preemptiveJoinWaitMs=e.preemptiveJoinWaitMs);const r=e.includePipelineTasks?"poll_message":"get_dm_messages";i.info("[AgentClient] fetchUnreadMessages \u5165\u53E3: tool=%s, blockIfEmpty=%s, blockTimeoutMs=%s, pollMessageTimeoutMs=%s, skipGroupMessages=%s, preemptiveJoinWaitMs=%s, agentId=%s",r,String(e.blockIfEmpty??!1),String(e.blockTimeoutMs??"-"),String(e.pollMessageTimeoutMs??"-"),String(e.skipGroupMessages??!1),String(e.preemptiveJoinWaitMs??"-"),this.agentId);const s=await this.fetchDirectMessagesWithRecovery(r,n,e.pollMessageTimeoutMs,e.propagatePollTimeout===!0);if(i.info("[AgentClient] fetchUnreadMessages \u79C1\u4FE1\u9636\u6BB5\u8FD4\u56DE: %s \u6761",Array.isArray(s.messages)?s.messages.length:0),e.skipGroupMessages)return i.info("[AgentClient] \u4F1A\u8BAE\u5FEB\u901F hydrate \u5DF2\u53D6\u5F97\u79C1\u4FE1\u54CD\u5E94\uFF0C\u8DF3\u8FC7\u7FA4\u804A\u53D1\u73B0\u5E76\u7ACB\u5373\u8FD4\u56DE: directMessages=%s",Array.isArray(s.messages)?s.messages.length:0),{directMessages:Array.isArray(s.messages)?s.messages:[],groupMessages:[]};let a;try{a=await this.discoverGroupRooms()}catch(o){i.warn("[AgentClient] \u53D1\u73B0\u7FA4\u623F\u95F4\u5931\u8D25\uFF0C\u672C\u6B21\u6309\u65E0\u7FA4\u6D88\u606F\u5904\u7406\uFF08\u5DF2\u53D6\u5230\u7684\u79C1\u4FE1\u4E0D\u53D7\u5F71\u54CD\uFF09: %s",o instanceof Error?o.message:String(o)),a={groups:[]}}const c=this.collectRoomIds(a,t),g=await Promise.all(c.map(async o=>{const l={agentId:this.agentId,projectId:t,roomId:o};e.since&&(l.since=e.since);try{return await this.httpClient.callTool("get_group_messages",l)}catch(d){return i.warn("[AgentClient] \u8DF3\u8FC7\u7FA4\u623F\u95F4\u672A\u8BFB\u8865\u62C9\u5931\u8D25: roomId=%s, error=%s",o,d instanceof Error?d.message:String(d)),{messages:[],currentReadPos:0,hasMore:!1}}}));return{directMessages:Array.isArray(s.messages)?s.messages:[],groupMessages:g.flatMap(o=>this.normalizeGroupMessages(o)).sort((o,l)=>new Date(o.timestamp).getTime()-new Date(l.timestamp).getTime())}}async markDmRead(e){if(e.length===0)return new Set;this.ensureRegistered();try{const t=await this.httpClient.callTool("mark_dm_read",{agentId:this.agentId,msgIds:e}),n=new Set(Array.isArray(t?.deliverableMsgIds)?t.deliverableMsgIds:[]),r=e.filter(s=>!n.has(s));return r.length>0?i.warn("[AgentClient] mark_dm_read \u786E\u8BA4\u540E\u5C06\u6709 %d \u6761\u6D88\u606F\u88AB\u4E22\u5F03\u4E0D\u4EA4\u4ED8: \u8BF7\u6C42=%s, \u53EF\u4EA4\u4ED8=%s, \u88AB\u4E22\u5F03=%s",r.length,JSON.stringify(e),JSON.stringify([...n]),JSON.stringify(r)):i.info("[AgentClient] mark_dm_read \u786E\u8BA4\u5B8C\u6210: %d \u6761\u5168\u90E8\u53EF\u4EA4\u4ED8",e.length),n}catch(t){throw i.warn("[AgentClient] mark_dm_read \u8BF7\u6C42\u5931\u8D25\uFF08\u5C06\u964D\u7EA7\u4E3A\u76F4\u63A5\u4EA4\u4ED8\uFF09: %s",t instanceof Error?t.message:String(t)),t}}async markGroupRead(e,t){if(t.length===0)return new Set;this.ensureRegistered();const n=await this.httpClient.callTool("mark_group_read",{agentId:this.agentId,roomId:e,msgIds:t});return new Set(Array.isArray(n?.deliverableMsgIds)?n.deliverableMsgIds:[])}async markNotificationRead(e){if(e.length!==0){this.ensureRegistered();try{await this.httpClient.callTool("mark_notification_read",{agentId:this.agentId,msgIds:e})}catch{}}}async markMeetingRead(e){if(e.length!==0){this.ensureRegistered();try{await this.httpClient.callTool("mark_meeting_read",{agentId:this.agentId,msgIds:e})}catch{}}}async fetchBrowserListenerEvents(){const e=this.serverConfig.runtimeBridgeBaseUrl,t=this.agentId;if(!e||!t)return i.info("[AgentClient] fetchBrowserListenerEvents \u8DF3\u8FC7: bridgeBaseUrl=%s, agentId=%s",e||"(\u7A7A)",t||"(\u7A7A)"),[];try{const n=`${e}/runtime/browser-listeners/${encodeURIComponent(t)}/events`,r=this.serverConfig.runtimeAccessToken||"";i.debug("[AgentClient] \u62C9\u53D6\u76D1\u542C\u5668\u4E8B\u4EF6: url=%s, tokenLen=%d",n,r.length);const s=await fetch(n,{method:"GET",headers:{"X-Runtime-Token":r},signal:AbortSignal.timeout(3e3)});if(!s.ok)return i.warn("[AgentClient] \u62C9\u53D6\u76D1\u542C\u5668\u4E8B\u4EF6\u5931\u8D25: HTTP %s, url=%s",s.status,n),[];const a=await s.json();return!a.ok||!Array.isArray(a.events)?(i.warn("[AgentClient] \u62C9\u53D6\u76D1\u542C\u5668\u4E8B\u4EF6\u54CD\u5E94\u5F02\u5E38: ok=%s, eventsType=%s",a.ok,Array.isArray(a.events)?"array":typeof a.events),[]):(i.debug("[AgentClient] \u62C9\u53D6\u76D1\u542C\u5668\u4E8B\u4EF6\u6210\u529F: %d \u6761\u4E8B\u4EF6",a.events.length),a.events)}catch(n){return i.warn("[AgentClient] \u62C9\u53D6\u76D1\u542C\u5668\u4E8B\u4EF6\u5F02\u5E38: %s",n instanceof Error?n.message:String(n)),[]}}async fetchPluginEvents(){const e=this.serverConfig.runtimeBridgeBaseUrl,t=this.agentId;if(!e||!t)return{revision:0,events:[]};try{const n=`${e}/runtime/plugin-events/${encodeURIComponent(t)}/events`,r=this.serverConfig.runtimeAccessToken||"",s=await fetch(n,{method:"GET",headers:{"X-Runtime-Token":r},signal:AbortSignal.timeout(3e3)});if(!s.ok)return i.warn("[AgentClient] \u62C9\u53D6\u63D2\u4EF6\u4E8B\u4EF6\u5931\u8D25: HTTP %s, url=%s",s.status,n),{revision:0,events:[]};const a=await s.json();return!a.ok||!Array.isArray(a.events)?(i.warn("[AgentClient] \u62C9\u53D6\u63D2\u4EF6\u4E8B\u4EF6\u54CD\u5E94\u5F02\u5E38: ok=%s",String(a.ok)),{revision:0,events:[]}):(i.debug("[AgentClient] \u62C9\u53D6\u63D2\u4EF6\u4E8B\u4EF6\u6210\u529F: %d \u6761\u4E8B\u4EF6, revision=%s",a.events.length,String(a.revision??0)),{revision:a.revision??0,events:a.events})}catch(n){return i.warn("[AgentClient] \u62C9\u53D6\u63D2\u4EF6\u4E8B\u4EF6\u5F02\u5E38: %s",n instanceof Error?n.message:String(n)),{revision:0,events:[]}}}async notifyBridgeForceMessage(){const e=this.serverConfig.runtimeBridgeBaseUrl,t=this.agentId;if(!(!e||!t))try{const n=`${e}/runtime/sessions/${encodeURIComponent(t)}/notify-force-message`,r=this.serverConfig.runtimeAccessToken||"",s=await fetch(n,{method:"POST",headers:{"X-Runtime-Token":r},signal:AbortSignal.timeout(3e3)});s.ok||i.warn("[AgentClient] \u901A\u77E5 bridge \u5F3A\u5236\u6D88\u606F\u5931\u8D25: HTTP %s, url=%s",s.status,n)}catch(n){i.warn("[AgentClient] \u901A\u77E5 bridge \u5F3A\u5236\u6D88\u606F\u5F02\u5E38: %s",n instanceof Error?n.message:String(n))}}async fetchDirectMessagesWithRecovery(e,t,n,r=!1){if(e==="poll_message"){i.info("[AgentClient] fetchDirectMessagesWithRecovery \u5165\u53E3: tool=poll_message, pollMessageTimeoutMs=%s, agentId=%s",String(n??"(\u9ED8\u8BA4)"),String(t?.agentId??""));try{const s=await this.httpClient.callToolOnce(e,t,n);return i.info("[AgentClient] fetchDirectMessagesWithRecovery poll_message \u6210\u529F\u8FD4\u56DE: %s \u6761",Array.isArray(s?.messages)?s.messages.length:0),s}catch(s){if(this.isRecoverableLongPollError(s)){if(r)throw new T(s instanceof Error?s.message:String(s));return i.warn("[AgentClient] poll_message \u5355\u6B21\u957F\u8F6E\u8BE2\u8D85\u65F6\uFF0C\u6309\u7A7A\u7ED3\u679C\u9000\u907F\u540E\u7EE7\u7EED\u7B49\u5F85:",s),{messages:[]}}throw s}}return await this.httpClient.callTool(e,t)}isRecoverableLongPollError(e){return e instanceof Error?/MCP tool poll_message call failed: 503(?:\s|$)/.test(e.message)||/MCP tool poll_message timed out after \d+ms/.test(e.message):!1}normalizeGroupMessages(e){return Array.isArray(e.messages)?e.messages.filter(t=>!!(t&&typeof t=="object"&&typeof t.msgId=="number"&&typeof t.senderId=="string"&&typeof t.content=="string"&&typeof t.timestamp=="string")):[]}collectRoomIds(e,t){const n=e.groups.filter(r=>r.projectId===t).map(r=>r.id);return Array.from(new Set(n))}async getProfile(){this.ensureRegistered();const e=this.agentId;if(!e)throw new Error("Agent is not registered");return{...await this.getProfileByAgentId(e),describe:this.agentConfig.describe}}async getProfileByAgentId(e){return await this.httpClient.callTool("get_profile",{agentId:e})}async getMyTasks(){return this.ensureRegistered(),await this.httpClient.callTool("my_task",{agentId:this.agentId})}async listTaskNodeIterations(e={}){return this.ensureRegistered(),await this.httpClient.callTool("list_task_node_iterations",{agentId:this.agentId,...e})}async createTaskInstanceComment(e){this.ensureRegistered();const t={agentId:this.agentId,...e};return await this.httpClient.callTool("create_task_instance_comment",t)}async submitTaskResult(e,t,n,r,s){this.ensureRegistered();const a={agentId:this.agentId,nodeId:e,outputPayload:t};return(Array.isArray(n)&&n.length>0||typeof n=="string"&&n.trim().length>0)&&(a.changeLog=n),typeof r=="string"&&r.trim().length>0&&(a.handoverNote=r),s&&Array.isArray(s)&&s.length>0&&(a.deliverables=s),await this.httpClient.callTool("submit_task_result",a)}async startTaskRollback(e){return this.ensureRegistered(),await this.httpClient.callTool("start_task_rollback",{agentId:this.agentId,...e})}async finishTaskRollback(e){return this.ensureRegistered(),await this.httpClient.callTool("finish_task_rollback",{agentId:this.agentId,...e})}async getDebugLogConfig(){return await this.httpClient.callTool("get_debug_log_config",{agentId:this.agentId})}async queryDebugLogs(e){return this.ensureRegistered(),await this.httpClient.callTool("query_debug_logs",{...e})}async queryFileChangesHistory(e){return this.ensureRegistered(),await this.httpClient.callTool("query_file_changes_history",{...e})}async getRuntimeFeatures(){return await this.httpClient.fetchRuntimeFeatures()}async listLaunchConfigs(){return this.ensureRegistered(),await this.httpClient.callTool("launch_config_list",{})}async createLaunchConfig(e){return this.ensureRegistered(),await this.httpClient.callTool("launch_config_create",{...e})}async updateLaunchConfig(e){return this.ensureRegistered(),await this.httpClient.callTool("launch_config_update",{...e})}async deleteLaunchConfig(e){return this.ensureRegistered(),await this.httpClient.callTool("launch_config_delete",{configId:e})}async startLaunchConfig(e){this.ensureRegistered();const t=Math.max(0,Math.min(3e5,Number(e.wait_timeout_ms)||0));return t>0?await this.httpClient.callToolOnce("launch_config_start",e,t+6e4):await this.httpClient.callTool("launch_config_start",{...e})}async restartLaunchConfig(e){this.ensureRegistered();const t=Math.max(0,Math.min(3e5,Number(e.wait_timeout_ms)||0));return t>0?await this.httpClient.callToolOnce("launch_config_restart",e,t+6e4):await this.httpClient.callTool("launch_config_restart",{...e})}async stopLaunchConfig(e){return this.ensureRegistered(),await this.httpClient.callTool("launch_config_stop",{configId:e})}async getLaunchLogs(e){return this.ensureRegistered(),await this.httpClient.callTool("launch_config_logs",{...e})}async listLaunchRuns(){return this.ensureRegistered(),await this.httpClient.callTool("launch_config_status",{})}async listAbilityMarket(e={}){return this.ensureRegistered(),await this.httpClient.callTool("list_ability_market",{...e})}async installAbilityMarketItem(e){return this.ensureRegistered(),await this.httpClient.callTool("install_ability_market_item",{...e})}async uninstallAbilityMarketItem(e){return this.ensureRegistered(),await this.httpClient.callTool("uninstall_ability_market_item",{...e})}async abilityDevIde(e){return this.ensureRegistered(),await this.httpClient.callTool("ability_dev_ide",{...e})}async formalAbility(e){return this.ensureRegistered(),await this.httpClient.callTool("formal_ability",{...e})}async listMyAbilities(e={}){return this.ensureRegistered(),await this.httpClient.callTool("list_my_abilities",{...e})}start(e,t){if(this.isRunning){i.warn("[AgentClient] \u6D88\u606F\u5FAA\u73AF\u5DF2\u5728\u8FD0\u884C\u4E2D");return}this.isDegradedMode||this.ensureRegistered(),this.messageHandler=e,this.profileHandler=t?.profileHandler||null,this.configHandler=t?.configHandler||null,this.systemNotifyHandler=t?.systemNotifyHandler||null,this.isRunning=!0,i.info(`[AgentClient] start() \u88AB\u8C03\u7528\uFF0CcachedProfile: ${this.cachedProfile?"\u5B58\u5728":"\u4E0D\u5B58\u5728"}, profileHandler: ${this.profileHandler?"\u5DF2\u8BBE\u7F6E":"\u672A\u8BBE\u7F6E"}, \u964D\u7EA7\u6A21\u5F0F: ${this.isDegradedMode?"\u662F":"\u5426"}`),this.cachedProfile&&this.profileHandler&&(i.info(`[AgentClient] \u5904\u7406\u7F13\u5B58\u7684 Profile \u4FE1\u606F: ${this.cachedProfile.displayName}`),this.profileHandler(this.cachedProfile),this.cachedProfile=null),t?.pollMode??!1?(i.warn("[AgentClient] \u542F\u52A8\u6D88\u606F\u4E3B\u5FAA\u73AF\uFF08HTTP\u8F6E\u8BE2\u6A21\u5F0F - \u4E0D\u63A8\u8350\uFF09"),this.messageLoop()):i.info("[AgentClient] \u542F\u52A8\u6D88\u606F\u4E3B\u5FAA\u73AF\uFF08WebSocket\u63A8\u9001\u6A21\u5F0F - \u63A8\u8350\uFF09")}stop(){this.isRunning=!1,this.pollTimer&&(clearTimeout(this.pollTimer),this.pollTimer=null),this.stopRuntimeTokenRefresh(),i.info("[AgentClient] \u6D88\u606F\u4E3B\u5FAA\u73AF\u5DF2\u505C\u6B62")}async messageLoop(){for(;this.isRunning;)try{await this.delay(I)}catch(e){i.error("[AgentClient] \u6D88\u606F\u5FAA\u73AF\u9519\u8BEF:",e),await this.delay(5e3)}}handleIncomingDm(e){e.senderId!==this.agentId&&this.processMessage(e)}handleIncomingGroup(e){e.senderId!==this.agentId&&this.processMessage(e)}handleIncomingMeeting(e){!e||e.senderId===this.agentId||this.processMessage(e)}handleProfileInfo(e){i.info(`[AgentClient] \u6536\u5230 Profile \u4FE1\u606F: ${e.displayName} (${e.roleName})`),e.projectId&&(this.projectId=e.projectId,i.info(`[AgentClient] \u66F4\u65B0\u6240\u5C5E\u9879\u76EE: ${this.projectId}`)),e.roleName&&e.roleName!==this.agentConfig.roleName&&(i.info(`[AgentClient] \u540C\u6B65\u89D2\u8272\u540D: "${this.agentConfig.roleName||"(\u7A7A)"}" -> "${e.roleName}"`),this.agentConfig.roleName=e.roleName),e.roleName&&u(e.roleName,e.instanceName||this.agentId||""),this.profileHandler?this.profileHandler(e):(i.info("[AgentClient] profileHandler \u672A\u8BBE\u7F6E\uFF0C\u7F13\u5B58 Profile \u4FE1\u606F"),this.cachedProfile=e)}async processMessage(e){if(!this.messageHandler)return;const t=typeof e.msgId=="string";i.info(`[AgentClient] \u6536\u5230${t?"\u79C1\u4FE1":"\u7FA4\u6D88\u606F"}\u6765\u81EA ${e.senderName}: ${e.content.substring(0,50)}...`);try{const n=await this.messageHandler(e);if(t){const r=e;r.requireReply&&r.callId&&await this.replyToCall(r.callId,r.senderId,n||"\u5DF2\u6536\u5230\u6D88\u606F\uFF0C\u6B63\u5728\u5904\u7406\u4E2D...")}}catch(n){const r=typeof e.msgId=="string";if(i.error("[AgentClient] \u5904\u7406\u6D88\u606F\u5931\u8D25: type=%s, senderId=%s, senderName=%s, msgId=%s, error=%s",r?"\u79C1\u4FE1":"\u7FA4\u6D88\u606F",e.senderId,e.senderName,e.msgId,n instanceof Error?n.message:String(n)),r){const s=e;s.requireReply&&s.callId&&await this.replyToCall(s.callId,s.senderId,`\u5904\u7406\u5931\u8D25: ${n}`)}}}ensureRegistered(){if(!this.agentId)throw new Error("Agent is not registered")}delay(e){return new Promise(t=>{this.pollTimer=setTimeout(t,e)})}onNewCharacter(e){this.newCharacterHandler=e}getState(){return{agentId:this.agentId,displayName:this.displayName,projectId:this.projectId,isConnected:this.wsClient.isConnected(),isRunning:this.isRunning}}getAgentConfig(){return this.agentConfig}getServerConfig(){return this.serverConfig}reloadConfig(){h.loadConfig(),this.agentConfig=h.getAgentConfig(),i.info(`[AgentClient] \u914D\u7F6E\u5DF2\u91CD\u65B0\u52A0\u8F7D\uFF0C\u89D2\u8272: ${this.agentConfig.roleName}`)}enterDegradedMode(){this.isDegradedMode=!0,i.warn("[AgentClient] \u8FDB\u5165\u964D\u7EA7\u6A21\u5F0F\uFF0C\u5C06\u5728\u540E\u53F0\u6301\u7EED\u5C1D\u8BD5\u91CD\u8FDE")}exitDegradedMode(){this.isDegradedMode=!1,i.info("[AgentClient] \u9000\u51FA\u964D\u7EA7\u6A21\u5F0F")}isInDegradedMode(){return this.isDegradedMode}async retryRegistrationInBackground(e,t){let n=0;(async()=>{for(;this.isDegradedMode;)try{i.info(`[AgentClient] \u964D\u7EA7\u6A21\u5F0F\uFF1A\u5C1D\u8BD5\u91CD\u65B0\u6CE8\u518C (${n+1}/${t===-1?"\u65E0\u9650":t})`);const s=await this.register();i.info(`[AgentClient] \u964D\u7EA7\u6A21\u5F0F\uFF1A\u6CE8\u518C\u6210\u529F - ${s.displayName} (${s.agentId})`),this.exitDegradedMode(),this.messageHandler&&this.start(this.messageHandler);return}catch(s){n++;const a=s instanceof Error?s.message:String(s);if(i.warn(`[AgentClient] \u964D\u7EA7\u6A21\u5F0F\uFF1A\u6CE8\u518C\u5931\u8D25 (${n}/${t===-1?"\u65E0\u9650":t}): ${a}`),t>0&&n>=t){i.error("[AgentClient] \u964D\u7EA7\u6A21\u5F0F\uFF1A\u8FBE\u5230\u6700\u5927\u91CD\u8BD5\u6B21\u6570\uFF0C\u505C\u6B62\u91CD\u8FDE"),this.isDegradedMode=!1;return}await new Promise(c=>setTimeout(c,e))}})().catch(s=>{i.error("[AgentClient] \u964D\u7EA7\u6A21\u5F0F\u540E\u53F0\u91CD\u8BD5\u5FAA\u73AF\u5F02\u5E38\u9000\u51FA: error=%s, stack=%s",s instanceof Error?s.message:String(s),s instanceof Error?s.stack:"(no stack)")})}initializeStatusReporter(){if(!this.agentId){i.warn("[AgentClient] \u65E0\u6CD5\u521D\u59CB\u5316\u72B6\u6001\u62A5\u544A\u5668\uFF1AagentId \u4E3A\u7A7A");return}this.statusReporter=new A({agentId:this.agentId,sendStatusUpdate:e=>{this.wsClient.send({type:"AGENT_STATUS",data:e,timestamp:new Date().toISOString()})}}),w(e=>this.reportMcpNodeLog(e)),this.startRuntimeTokenRefresh(),i.info("[AgentClient] \u72B6\u6001\u62A5\u544A\u5668\u5DF2\u521D\u59CB\u5316")}startRuntimeTokenRefresh(){this.stopRuntimeTokenRefresh();const e=this.serverConfig.runtimeTokenRefreshIntervalMs;if(!e||e<=0){i.warn("[AgentClient] runtimeTokenRefreshIntervalMs \u672A\u914D\u7F6E\u6216\u65E0\u6548\uFF0C\u8DF3\u8FC7\u4E3B\u52A8\u7EED\u671F");return}const t=this.agentId;if(!t){i.warn("[AgentClient] agentId \u4E3A\u7A7A\uFF0C\u8DF3\u8FC7\u4E3B\u52A8\u7EED\u671F");return}this.runtimeTokenRefreshTimer=setInterval(async()=>{try{await this.httpClient.refreshRuntimeAccessToken(t)&&i.info("[AgentClient] runtimeAccessToken \u5DF2\u4E3B\u52A8\u7EED\u671F")}catch(n){i.warn("[AgentClient] \u4E3B\u52A8\u7EED\u671F runtimeAccessToken \u5931\u8D25: %s",n instanceof Error?n.message:String(n)),n instanceof Error&&n.stack&&i.warn("[AgentClient] \u4E3B\u52A8\u7EED\u671F\u5F02\u5E38\u5806\u6808:",n.stack)}},e),this.runtimeTokenRefreshTimer.unref?.(),i.info(`[AgentClient] runtime token \u4E3B\u52A8\u7EED\u671F\u5DF2\u542F\u52A8\uFF0C\u95F4\u9694 ${e}ms`)}stopRuntimeTokenRefresh(){this.runtimeTokenRefreshTimer&&(clearInterval(this.runtimeTokenRefreshTimer),this.runtimeTokenRefreshTimer=null)}reportMcpNodeLog(e){const t=this.wsClient;!this.agentId||!this.wsClient.isConnected()||typeof t.sendMcpNodeLog!="function"||t.sendMcpNodeLog(e)}getStatusReporter(){return this.statusReporter}}export{N as AgentClient,T as PollLongPollTimeoutError};
|
|
1
|
+
import{configManager as h}from"./config.js";import{MESSAGE_POLL_INTERVAL_MS as I}from"./constants.js";import{HttpClient as f}from"./http-client.js";import{logger as i,setMcpNodeLogSink as w,updateStartupLogIdentity as u}from"./logger.js";import{claimRuntimeLaunchBindingDetailed as m}from"./runtime-launch-binding.js";import{StatusReporter as A}from"./status-reporter.js";import{WebSocketClient as p}from"./websocket-client.js";class T extends Error{constructor(e){super(e),this.name="PollLongPollTimeoutError"}}const C=27e4;class N{wsClient;httpClient;agentConfig;serverConfig;agentId=null;displayName=null;projectId=null;isRunning=!1;isDegradedMode=!1;messageHandler=null;profileHandler=null;configHandler=null;systemNotifyHandler=null;pollTimer=null;statusReporter=null;newCharacterHandler=null;runtimeTokenRefreshTimer=null;pendingLaunchBindingClaim=!1;cachedProfile=null;constructor(){h.loadConfig(),this.agentConfig=h.getAgentConfig(),this.serverConfig=h.getServerConfig(),this.wsClient=new p(this.serverConfig),this.httpClient=new f(this.serverConfig),this.setupWebSocketListeners()}async initialize(){const e=await m(this.agentConfig,this.serverConfig);if(e.status==="claimed"){this.applyLaunchBinding(e.binding);return}if(e.status==="unreachable"){this.pendingLaunchBindingClaim=!0,i.warn("[AgentClient] runtime-bridge \u672A\u5C31\u7EEA\uFF0C\u542F\u52A8\u7ED1\u5B9A\u8BA4\u9886\u5DF2\u6302\u8D77\uFF0C\u5C06\u5728\u6CE8\u518C\u91CD\u8BD5\u4E2D\u91CD\u65B0\u8BA4\u9886: %s",e.message);return}this.serverConfig.runtimeBridgeBaseUrl=void 0}applyLaunchBinding(e){h.applyRuntimeLaunchBinding(e),this.agentConfig=h.getAgentConfig(),this.serverConfig=h.getServerConfig(),this.wsClient=new p(this.serverConfig),this.httpClient=new f(this.serverConfig),this.setupWebSocketListeners()}async retryPendingLaunchBindingClaim(){if(!this.pendingLaunchBindingClaim)return!0;const e=await m(this.agentConfig,this.serverConfig);if(e.status==="claimed")return this.pendingLaunchBindingClaim=!1,i.info("[AgentClient] \u542F\u52A8\u7ED1\u5B9A\u8865\u8BA4\u9886\u6210\u529F\uFF0C\u7EE7\u7EED\u6CE8\u518C\u6D41\u7A0B"),this.applyLaunchBinding(e.binding),!0;if(e.status==="missing")return this.pendingLaunchBindingClaim=!1,this.serverConfig.runtimeBridgeBaseUrl=void 0,i.warn("[AgentClient] \u542F\u52A8\u7ED1\u5B9A\u8865\u8BA4\u9886\u672A\u627E\u5230\u5F85\u8BA4\u9886\u8BB0\u5F55\uFF0C\u6309\u65E0\u7ED1\u5B9A\u6A21\u5F0F\u7EE7\u7EED\u6CE8\u518C"),!1;const t=e.status==="unreachable"?e.message:e.reason;return i.warn("[AgentClient] \u542F\u52A8\u7ED1\u5B9A\u8865\u8BA4\u9886\u5931\u8D25\uFF0C\u4FDD\u7559\u6302\u8D77\u72B6\u6001\u7B49\u5F85\u4E0B\u6B21\u6CE8\u518C\u91CD\u8BD5: %s",t),!1}setupWebSocketListeners(){this.wsClient.on("directMessage",e=>{this.handleIncomingDm(e)}),this.wsClient.on("groupMessage",e=>{this.handleIncomingGroup(e)}),this.wsClient.on("meetingMessage",e=>{this.handleIncomingMeeting(e)}),this.wsClient.on("systemNotify",e=>{this.systemNotifyHandler?.(e)}),this.wsClient.on("profileInfo",e=>{i.info(`[AgentClient] WebSocket profileInfo \u4E8B\u4EF6\u89E6\u53D1\uFF0CdisplayName: ${e.displayName}`),this.handleProfileInfo(e)}),this.wsClient.on("agentConfig",e=>{i.info("[AgentClient] WebSocket agentConfig \u4E8B\u4EF6\u89E6\u53D1"),this.configHandler&&this.configHandler(e??{})}),this.wsClient.on("agentStatus",e=>{i.info(`[AgentClient] WebSocket agentStatus \u4E8B\u4EF6\u89E6\u53D1: ${e.status}`)}),this.wsClient.on("disconnected",(e,t)=>{const n=t?.toString()||"";i.warn("[AgentClient] WebSocket \u65AD\u5F00\u8FDE\u63A5: code=%s, reason=%s, agentId=%s, \u6B63\u5728\u81EA\u52A8\u91CD\u8FDE",e,n,this.agentId)}),this.wsClient.on("error",e=>{i.error("[AgentClient] WebSocket \u9519\u8BEF: %s, stack=%s",e.message,e.stack)}),this.wsClient.on("reconnectFailed",()=>{i.error("[AgentClient] \u91CD\u8FDE\u5931\u8D25\uFF08\u5DF2\u8FBE\u91CD\u8BD5\u4E0A\u9650\uFF09\uFF0C\u505C\u6B62\u6D88\u606F\u5FAA\u73AF, agentId=%s",this.agentId),this.stop()}),this.wsClient.on("tokenRejected",()=>{i.error("[AgentClient] runtime token \u88AB 1008 \u62D2\u7EDD\u4E14\u5237\u65B0\u65E0\u53D8\u5316\uFF0C\u8FDB\u5165\u6162\u901F\u91CD\u8BD5\u7B49\u5F85\u65B0 token \u7B7E\u53D1: agentId=%s",this.agentId)}),this.wsClient.on("tokenRefreshFailed",e=>{i.error("[AgentClient] runtime token \u5237\u65B0\u8FDE\u7EED\u5931\u8D25 %s \u6B21\uFF0C\u8FDB\u5165\u6162\u901F\u91CD\u8BD5\u7B49\u5F85 bridge \u6062\u590D: agentId=%s",e,this.agentId)})}async register(){return i.info("[AgentClient] \u6B63\u5728\u6CE8\u518C Agent..."),await this.retryPendingLaunchBindingClaim(),this.hasPresetAgentId()?await this.registerWithExistingAgentId():await this.registerAsNewAgent()}hasPresetAgentId(){return!!(this.agentConfig.agentId&&this.agentConfig.agentId.trim().length>0)}async registerWithExistingAgentId(){const e=this.agentConfig.agentId;if(!e)throw new Error("Preset agentId is missing");this.agentId=e.trim();let t;try{t=await this.getProfileByAgentId(this.agentId)}catch(r){throw i.error("[AgentClient] getProfileByAgentId \u5931\u8D25 (presetAgentId=%s): %s",this.agentId,r instanceof Error?r.message:String(r)),r}this.displayName=t.displayName,this.projectId=t.projectId||null,i.info(`[AgentClient] \u4F7F\u7528\u9884\u8BBE AgentID \u7ED1\u5B9A\u5B9E\u4F8B: ${this.displayName} (${this.agentId})`),i.info(`[AgentClient] \u6240\u5C5E\u9879\u76EE: ${this.projectId||"(\u672A\u8BBE\u7F6E)"}`);try{await this.wsClient.connect(this.agentId)}catch(r){throw i.error("[AgentClient] WebSocket \u8FDE\u63A5\u5931\u8D25 (agentId=%s): %s",this.agentId,r instanceof Error?r.message:String(r)),r}i.info("[AgentClient] WebSocket \u8FDE\u63A5\u5DF2\u5EFA\u7ACB\uFF0CAgent \u73B0\u5728\u5DF2\u4E0A\u7EBF"),this.initializeStatusReporter();const n=await this.getProfileByAgentId(this.agentId);return this.displayName=n.displayName,this.projectId=n.projectId||null,u(n.roleName||"unknown-role",n.instanceName||this.agentId),{agentId:this.agentId,displayName:this.displayName,status:n.isOnline?"online":"offline",projectId:n.projectId,workspacePath:n.workspacePath,runtimeStatus:n.runtimeStatus,runtimeSessionId:n.runtimeSessionId}}async registerAsNewAgent(){const e=await this.httpClient.callTool("register",{roleName:this.agentConfig.roleName,projectId:this.agentConfig.projectId,workspacePath:this.agentConfig.workspacePath,prompt:this.agentConfig.prompt,runtimeBridgeBaseUrl:this.serverConfig.runtimeBridgeBaseUrl}),t=e.agentId;if(!t)throw new Error("Registration failed: agentId was not returned");return this.agentId=t,this.displayName=e.displayName,this.projectId=e.projectId||null,u(this.agentConfig.roleName||"unknown-role",e.instanceName||t),i.info(`[AgentClient] \u6CE8\u518C\u6210\u529F: ${this.displayName} (${this.agentId})`),i.info(`[AgentClient] \u72B6\u6001: ${e.status}`),i.info(`[AgentClient] \u6240\u5C5E\u9879\u76EE: ${this.projectId||"(\u672A\u8BBE\u7F6E)"}`),await this.wsClient.connect(this.agentId),i.info("[AgentClient] WebSocket \u8FDE\u63A5\u5DF2\u5EFA\u7ACB\uFF0CAgent \u73B0\u5728\u5DF2\u4E0A\u7EBF"),this.initializeStatusReporter(),e.isExisting===!1&&this.newCharacterHandler&&this.newCharacterHandler(),e}async unregister(){i.info("[AgentClient] \u6B63\u5728\u6CE8\u9500 Agent..."),this.agentId&&await this.httpClient.callTool("unregister",{agentId:this.agentId}),this.stopRuntimeTokenRefresh(),this.wsClient.disconnect(),this.agentId=null,this.displayName=null,this.projectId=null,this.isRunning=!1,i.info("[AgentClient] \u5DF2\u6CE8\u9500")}async discoverColleagues(){return await this.httpClient.callTool("discover_colleague",{agentId:this.agentId})}async discoverGroupRooms(){return this.ensureRegistered(),await this.httpClient.callTool("discover_group_rooms",{agentId:this.agentId})}async listProjectMembers(){return this.ensureRegistered(),await this.httpClient.callTool("list_project_members",{agentId:this.agentId})}async hireColleague(e){return this.ensureRegistered(),await this.httpClient.callTool("hire_colleague",{...e,agentId:this.agentId})}async callAgentScopedTool(e,t){this.ensureRegistered();const n={...t,agentId:this.agentId};if(e==="create_meeting"){const r=typeof t.waitTimeoutMs=="number"?t.waitTimeoutMs:Number.NaN,s=Number.isFinite(r)&&r>0?Math.min(r,C):C;return await this.httpClient.callToolOnce(e,{...n,waitTimeoutMs:s},0)}return await this.httpClient.callTool(e,n)}async reportMemoryStats(e){await this.callAgentScopedTool("report_memory_stats",{memoryStats:e})}async sendGroupMessage(e,t,n,r,s){this.ensureRegistered();const a=t||this.projectId||this.agentConfig.projectId;return await this.httpClient.callTool("send_group_message",{agentId:this.agentId,projectId:a,roomId:n,content:e,card:r,replyTo:s})}async sendDirectMessage(e,t,n=!1,r,s,a,c){this.ensureRegistered();const g={agentId:this.agentId,targetId:e,content:t,requireReply:n,waitReply:n,replyToCallId:r,card:a,replyTo:c};if(typeof s=="number"&&s>0&&(g.timeoutMs=s),n){const o=typeof s=="number"&&s>0?s+3e4:0;return await this.httpClient.callToolOnce("send_dm",g,o)}return await this.httpClient.callTool("send_dm",g)}async sendCallAndWaitReply(e,t,n=6e4){const r=await this.sendDirectMessage(e,t,!0,void 0,n);if(r.reply)return r.reply;throw new Error("No reply received for call-style direct message before timeout")}async replyToCall(e,t,n){return await this.sendDirectMessage(t,n,!1,e)}async sendEmail(e){return await this.callAgentScopedTool("send_email",e)}async listEmails(e){return await this.callAgentScopedTool("list_emails",e)}async readEmail(e){return await this.callAgentScopedTool("read_email",{mailId:e})}async replyEmail(e){return await this.callAgentScopedTool("reply_email",e)}async ackEmail(e){return await this.callAgentScopedTool("ack_email",{mailId:e})}async getDmHistory(e,t=50,n){this.ensureRegistered();const r={agentId:this.agentId,targetUserId:e,limit:t};return n&&(r.since=n),await this.httpClient.callTool("get_dm_history",r)}async getGroupHistory(e=50,t,n){if(this.ensureRegistered(),t){const o={projectId:this.projectId||this.agentConfig.projectId,roomId:t,limit:e};return n&&(o.since=n),await this.httpClient.callTool("get_group_history",o)}const r=await this.discoverGroupRooms(),s=this.projectId||this.agentConfig.projectId,a=this.collectRoomIds(r,s);if(a.length===0)return{messages:[],count:0};const g=(await Promise.all(a.map(async o=>{const l={projectId:s,roomId:o,limit:e};return n&&(l.since=n),await this.httpClient.callTool("get_group_history",l)}))).flatMap(o=>o.messages).sort((o,l)=>new Date(o.timestamp).getTime()-new Date(l.timestamp).getTime());return{messages:g,count:g.length}}async fetchUnreadMessages(e={}){this.ensureRegistered();const t=this.projectId||this.agentConfig.projectId,n={agentId:this.agentId,blockIfEmpty:e.blockIfEmpty??!1};e.since&&(n.since=e.since),e.blockTimeoutMs&&e.blockTimeoutMs>0&&(n.blockTimeoutMs=e.blockTimeoutMs),e.preemptiveJoinWaitMs!==void 0&&e.preemptiveJoinWaitMs!==null&&e.preemptiveJoinWaitMs>=0&&(n.preemptiveJoinWaitMs=e.preemptiveJoinWaitMs);const r=e.includePipelineTasks?"poll_message":"get_dm_messages";i.info("[AgentClient] fetchUnreadMessages \u5165\u53E3: tool=%s, blockIfEmpty=%s, blockTimeoutMs=%s, pollMessageTimeoutMs=%s, skipGroupMessages=%s, preemptiveJoinWaitMs=%s, agentId=%s",r,String(e.blockIfEmpty??!1),String(e.blockTimeoutMs??"-"),String(e.pollMessageTimeoutMs??"-"),String(e.skipGroupMessages??!1),String(e.preemptiveJoinWaitMs??"-"),this.agentId);const s=await this.fetchDirectMessagesWithRecovery(r,n,e.pollMessageTimeoutMs,e.propagatePollTimeout===!0);if(i.info("[AgentClient] fetchUnreadMessages \u79C1\u4FE1\u9636\u6BB5\u8FD4\u56DE: %s \u6761",Array.isArray(s.messages)?s.messages.length:0),e.skipGroupMessages)return i.info("[AgentClient] \u4F1A\u8BAE\u5FEB\u901F hydrate \u5DF2\u53D6\u5F97\u79C1\u4FE1\u54CD\u5E94\uFF0C\u8DF3\u8FC7\u7FA4\u804A\u53D1\u73B0\u5E76\u7ACB\u5373\u8FD4\u56DE: directMessages=%s",Array.isArray(s.messages)?s.messages.length:0),{directMessages:Array.isArray(s.messages)?s.messages:[],groupMessages:[]};let a;try{a=await this.discoverGroupRooms()}catch(o){i.warn("[AgentClient] \u53D1\u73B0\u7FA4\u623F\u95F4\u5931\u8D25\uFF0C\u672C\u6B21\u6309\u65E0\u7FA4\u6D88\u606F\u5904\u7406\uFF08\u5DF2\u53D6\u5230\u7684\u79C1\u4FE1\u4E0D\u53D7\u5F71\u54CD\uFF09: %s",o instanceof Error?o.message:String(o)),a={groups:[]}}const c=this.collectRoomIds(a,t),g=await Promise.all(c.map(async o=>{const l={agentId:this.agentId,projectId:t,roomId:o};e.since&&(l.since=e.since);try{return await this.httpClient.callTool("get_group_messages",l)}catch(d){return i.warn("[AgentClient] \u8DF3\u8FC7\u7FA4\u623F\u95F4\u672A\u8BFB\u8865\u62C9\u5931\u8D25: roomId=%s, error=%s",o,d instanceof Error?d.message:String(d)),{messages:[],currentReadPos:0,hasMore:!1}}}));return{directMessages:Array.isArray(s.messages)?s.messages:[],groupMessages:g.flatMap(o=>this.normalizeGroupMessages(o)).sort((o,l)=>new Date(o.timestamp).getTime()-new Date(l.timestamp).getTime())}}async markDmRead(e){if(e.length===0)return new Set;this.ensureRegistered();try{const t=await this.httpClient.callTool("mark_dm_read",{agentId:this.agentId,msgIds:e}),n=new Set(Array.isArray(t?.deliverableMsgIds)?t.deliverableMsgIds:[]),r=e.filter(s=>!n.has(s));return r.length>0?i.warn("[AgentClient] mark_dm_read \u786E\u8BA4\u540E\u5C06\u6709 %d \u6761\u6D88\u606F\u88AB\u4E22\u5F03\u4E0D\u4EA4\u4ED8: \u8BF7\u6C42=%s, \u53EF\u4EA4\u4ED8=%s, \u88AB\u4E22\u5F03=%s",r.length,JSON.stringify(e),JSON.stringify([...n]),JSON.stringify(r)):i.info("[AgentClient] mark_dm_read \u786E\u8BA4\u5B8C\u6210: %d \u6761\u5168\u90E8\u53EF\u4EA4\u4ED8",e.length),n}catch(t){throw i.warn("[AgentClient] mark_dm_read \u8BF7\u6C42\u5931\u8D25\uFF08\u5C06\u964D\u7EA7\u4E3A\u76F4\u63A5\u4EA4\u4ED8\uFF09: %s",t instanceof Error?t.message:String(t)),t}}async markGroupRead(e,t){if(t.length===0)return new Set;this.ensureRegistered();const n=await this.httpClient.callTool("mark_group_read",{agentId:this.agentId,roomId:e,msgIds:t});return new Set(Array.isArray(n?.deliverableMsgIds)?n.deliverableMsgIds:[])}async markNotificationRead(e){if(e.length!==0){this.ensureRegistered();try{await this.httpClient.callTool("mark_notification_read",{agentId:this.agentId,msgIds:e})}catch{}}}async markMeetingRead(e){if(e.length!==0){this.ensureRegistered();try{await this.httpClient.callTool("mark_meeting_read",{agentId:this.agentId,msgIds:e})}catch{}}}async fetchBrowserListenerEvents(){const e=this.serverConfig.runtimeBridgeBaseUrl,t=this.agentId;if(!e||!t)return i.info("[AgentClient] fetchBrowserListenerEvents \u8DF3\u8FC7: bridgeBaseUrl=%s, agentId=%s",e||"(\u7A7A)",t||"(\u7A7A)"),[];try{const n=`${e}/runtime/browser-listeners/${encodeURIComponent(t)}/events`,r=this.serverConfig.runtimeAccessToken||"";i.debug("[AgentClient] \u62C9\u53D6\u76D1\u542C\u5668\u4E8B\u4EF6: url=%s, tokenLen=%d",n,r.length);const s=await fetch(n,{method:"GET",headers:{"X-Runtime-Token":r},signal:AbortSignal.timeout(3e3)});if(!s.ok)return i.warn("[AgentClient] \u62C9\u53D6\u76D1\u542C\u5668\u4E8B\u4EF6\u5931\u8D25: HTTP %s, url=%s",s.status,n),[];const a=await s.json();return!a.ok||!Array.isArray(a.events)?(i.warn("[AgentClient] \u62C9\u53D6\u76D1\u542C\u5668\u4E8B\u4EF6\u54CD\u5E94\u5F02\u5E38: ok=%s, eventsType=%s",a.ok,Array.isArray(a.events)?"array":typeof a.events),[]):(i.debug("[AgentClient] \u62C9\u53D6\u76D1\u542C\u5668\u4E8B\u4EF6\u6210\u529F: %d \u6761\u4E8B\u4EF6",a.events.length),a.events)}catch(n){return i.warn("[AgentClient] \u62C9\u53D6\u76D1\u542C\u5668\u4E8B\u4EF6\u5F02\u5E38: %s",n instanceof Error?n.message:String(n)),[]}}async fetchPluginEvents(){const e=this.serverConfig.runtimeBridgeBaseUrl,t=this.agentId;if(!e||!t)return{revision:0,events:[]};try{const n=`${e}/runtime/plugin-events/${encodeURIComponent(t)}/events`,r=this.serverConfig.runtimeAccessToken||"",s=await fetch(n,{method:"GET",headers:{"X-Runtime-Token":r},signal:AbortSignal.timeout(3e3)});if(!s.ok)return i.warn("[AgentClient] \u62C9\u53D6\u63D2\u4EF6\u4E8B\u4EF6\u5931\u8D25: HTTP %s, url=%s",s.status,n),{revision:0,events:[]};const a=await s.json();return!a.ok||!Array.isArray(a.events)?(i.warn("[AgentClient] \u62C9\u53D6\u63D2\u4EF6\u4E8B\u4EF6\u54CD\u5E94\u5F02\u5E38: ok=%s",String(a.ok)),{revision:0,events:[]}):(i.debug("[AgentClient] \u62C9\u53D6\u63D2\u4EF6\u4E8B\u4EF6\u6210\u529F: %d \u6761\u4E8B\u4EF6, revision=%s",a.events.length,String(a.revision??0)),{revision:a.revision??0,events:a.events})}catch(n){return i.warn("[AgentClient] \u62C9\u53D6\u63D2\u4EF6\u4E8B\u4EF6\u5F02\u5E38: %s",n instanceof Error?n.message:String(n)),{revision:0,events:[]}}}async notifyBridgeForceMessage(){const e=this.serverConfig.runtimeBridgeBaseUrl,t=this.agentId;if(!(!e||!t))try{const n=`${e}/runtime/sessions/${encodeURIComponent(t)}/notify-force-message`,r=this.serverConfig.runtimeAccessToken||"",s=await fetch(n,{method:"POST",headers:{"X-Runtime-Token":r},signal:AbortSignal.timeout(3e3)});s.ok||i.warn("[AgentClient] \u901A\u77E5 bridge \u5F3A\u5236\u6D88\u606F\u5931\u8D25: HTTP %s, url=%s",s.status,n)}catch(n){i.warn("[AgentClient] \u901A\u77E5 bridge \u5F3A\u5236\u6D88\u606F\u5F02\u5E38: %s",n instanceof Error?n.message:String(n))}}async fetchDirectMessagesWithRecovery(e,t,n,r=!1){if(e==="poll_message"){i.info("[AgentClient] fetchDirectMessagesWithRecovery \u5165\u53E3: tool=poll_message, pollMessageTimeoutMs=%s, agentId=%s",String(n??"(\u9ED8\u8BA4)"),String(t?.agentId??""));try{const s=await this.httpClient.callToolOnce(e,t,n);return i.info("[AgentClient] fetchDirectMessagesWithRecovery poll_message \u6210\u529F\u8FD4\u56DE: %s \u6761",Array.isArray(s?.messages)?s.messages.length:0),s}catch(s){if(this.isRecoverableLongPollError(s)){if(r)throw new T(s instanceof Error?s.message:String(s));return i.warn("[AgentClient] poll_message \u5355\u6B21\u957F\u8F6E\u8BE2\u8D85\u65F6\uFF0C\u6309\u7A7A\u7ED3\u679C\u9000\u907F\u540E\u7EE7\u7EED\u7B49\u5F85:",s),{messages:[]}}throw s}}return await this.httpClient.callTool(e,t)}isRecoverableLongPollError(e){return e instanceof Error?/MCP tool poll_message call failed: 503(?:\s|$)/.test(e.message)||/MCP tool poll_message timed out after \d+ms/.test(e.message):!1}normalizeGroupMessages(e){return Array.isArray(e.messages)?e.messages.filter(t=>!!(t&&typeof t=="object"&&typeof t.msgId=="number"&&typeof t.senderId=="string"&&typeof t.content=="string"&&typeof t.timestamp=="string")):[]}collectRoomIds(e,t){const n=e.groups.filter(r=>r.projectId===t).map(r=>r.id);return Array.from(new Set(n))}async getProfile(){this.ensureRegistered();const e=this.agentId;if(!e)throw new Error("Agent is not registered");return{...await this.getProfileByAgentId(e),describe:this.agentConfig.describe}}async getProfileByAgentId(e){return await this.httpClient.callTool("get_profile",{agentId:e})}async getMyTasks(){return this.ensureRegistered(),await this.httpClient.callTool("my_task",{agentId:this.agentId})}async listTaskNodeIterations(e={}){return this.ensureRegistered(),await this.httpClient.callTool("list_task_node_iterations",{agentId:this.agentId,...e})}async createTaskInstanceComment(e){this.ensureRegistered();const t={agentId:this.agentId,...e};return await this.httpClient.callTool("create_task_instance_comment",t)}async submitTaskResult(e,t,n,r,s){this.ensureRegistered();const a={agentId:this.agentId,nodeId:e,outputPayload:t};return(Array.isArray(n)&&n.length>0||typeof n=="string"&&n.trim().length>0)&&(a.changeLog=n),typeof r=="string"&&r.trim().length>0&&(a.handoverNote=r),s&&Array.isArray(s)&&s.length>0&&(a.deliverables=s),await this.httpClient.callTool("submit_task_result",a)}async startTaskRollback(e){return this.ensureRegistered(),await this.httpClient.callTool("start_task_rollback",{agentId:this.agentId,...e})}async finishTaskRollback(e){return this.ensureRegistered(),await this.httpClient.callTool("finish_task_rollback",{agentId:this.agentId,...e})}async getDebugLogConfig(){return await this.httpClient.callTool("get_debug_log_config",{agentId:this.agentId})}async queryDebugLogs(e){return this.ensureRegistered(),await this.httpClient.callTool("query_debug_logs",{...e})}async queryFileChangesHistory(e){return this.ensureRegistered(),await this.httpClient.callTool("query_file_changes_history",{...e})}async listColleagueEvents(e){return this.ensureRegistered(),await this.httpClient.callTool("list_colleague_events",{...e})}async getRuntimeFeatures(){return await this.httpClient.fetchRuntimeFeatures()}async listLaunchConfigs(){return this.ensureRegistered(),await this.httpClient.callTool("launch_config_list",{})}async createLaunchConfig(e){return this.ensureRegistered(),await this.httpClient.callTool("launch_config_create",{...e})}async updateLaunchConfig(e){return this.ensureRegistered(),await this.httpClient.callTool("launch_config_update",{...e})}async deleteLaunchConfig(e){return this.ensureRegistered(),await this.httpClient.callTool("launch_config_delete",{configId:e})}async startLaunchConfig(e){this.ensureRegistered();const t=Math.max(0,Math.min(3e5,Number(e.wait_timeout_ms)||0));return t>0?await this.httpClient.callToolOnce("launch_config_start",e,t+6e4):await this.httpClient.callTool("launch_config_start",{...e})}async restartLaunchConfig(e){this.ensureRegistered();const t=Math.max(0,Math.min(3e5,Number(e.wait_timeout_ms)||0));return t>0?await this.httpClient.callToolOnce("launch_config_restart",e,t+6e4):await this.httpClient.callTool("launch_config_restart",{...e})}async stopLaunchConfig(e){return this.ensureRegistered(),await this.httpClient.callTool("launch_config_stop",{configId:e})}async getLaunchLogs(e){return this.ensureRegistered(),await this.httpClient.callTool("launch_config_logs",{...e})}async listLaunchRuns(){return this.ensureRegistered(),await this.httpClient.callTool("launch_config_status",{})}async listAbilityMarket(e={}){return this.ensureRegistered(),await this.httpClient.callTool("list_ability_market",{...e})}async installAbilityMarketItem(e){return this.ensureRegistered(),await this.httpClient.callTool("install_ability_market_item",{...e})}async uninstallAbilityMarketItem(e){return this.ensureRegistered(),await this.httpClient.callTool("uninstall_ability_market_item",{...e})}async abilityDevIde(e){return this.ensureRegistered(),await this.httpClient.callTool("ability_dev_ide",{...e})}async formalAbility(e){return this.ensureRegistered(),await this.httpClient.callTool("formal_ability",{...e})}async listMyAbilities(e={}){return this.ensureRegistered(),await this.httpClient.callTool("list_my_abilities",{...e})}start(e,t){if(this.isRunning){i.warn("[AgentClient] \u6D88\u606F\u5FAA\u73AF\u5DF2\u5728\u8FD0\u884C\u4E2D");return}this.isDegradedMode||this.ensureRegistered(),this.messageHandler=e,this.profileHandler=t?.profileHandler||null,this.configHandler=t?.configHandler||null,this.systemNotifyHandler=t?.systemNotifyHandler||null,this.isRunning=!0,i.info(`[AgentClient] start() \u88AB\u8C03\u7528\uFF0CcachedProfile: ${this.cachedProfile?"\u5B58\u5728":"\u4E0D\u5B58\u5728"}, profileHandler: ${this.profileHandler?"\u5DF2\u8BBE\u7F6E":"\u672A\u8BBE\u7F6E"}, \u964D\u7EA7\u6A21\u5F0F: ${this.isDegradedMode?"\u662F":"\u5426"}`),this.cachedProfile&&this.profileHandler&&(i.info(`[AgentClient] \u5904\u7406\u7F13\u5B58\u7684 Profile \u4FE1\u606F: ${this.cachedProfile.displayName}`),this.profileHandler(this.cachedProfile),this.cachedProfile=null),t?.pollMode??!1?(i.warn("[AgentClient] \u542F\u52A8\u6D88\u606F\u4E3B\u5FAA\u73AF\uFF08HTTP\u8F6E\u8BE2\u6A21\u5F0F - \u4E0D\u63A8\u8350\uFF09"),this.messageLoop()):i.info("[AgentClient] \u542F\u52A8\u6D88\u606F\u4E3B\u5FAA\u73AF\uFF08WebSocket\u63A8\u9001\u6A21\u5F0F - \u63A8\u8350\uFF09")}stop(){this.isRunning=!1,this.pollTimer&&(clearTimeout(this.pollTimer),this.pollTimer=null),this.stopRuntimeTokenRefresh(),i.info("[AgentClient] \u6D88\u606F\u4E3B\u5FAA\u73AF\u5DF2\u505C\u6B62")}async messageLoop(){for(;this.isRunning;)try{await this.delay(I)}catch(e){i.error("[AgentClient] \u6D88\u606F\u5FAA\u73AF\u9519\u8BEF:",e),await this.delay(5e3)}}handleIncomingDm(e){e.senderId!==this.agentId&&this.processMessage(e)}handleIncomingGroup(e){e.senderId!==this.agentId&&this.processMessage(e)}handleIncomingMeeting(e){!e||e.senderId===this.agentId||this.processMessage(e)}handleProfileInfo(e){i.info(`[AgentClient] \u6536\u5230 Profile \u4FE1\u606F: ${e.displayName} (${e.roleName})`),e.projectId&&(this.projectId=e.projectId,i.info(`[AgentClient] \u66F4\u65B0\u6240\u5C5E\u9879\u76EE: ${this.projectId}`)),e.roleName&&e.roleName!==this.agentConfig.roleName&&(i.info(`[AgentClient] \u540C\u6B65\u89D2\u8272\u540D: "${this.agentConfig.roleName||"(\u7A7A)"}" -> "${e.roleName}"`),this.agentConfig.roleName=e.roleName),e.roleName&&u(e.roleName,e.instanceName||this.agentId||""),this.profileHandler?this.profileHandler(e):(i.info("[AgentClient] profileHandler \u672A\u8BBE\u7F6E\uFF0C\u7F13\u5B58 Profile \u4FE1\u606F"),this.cachedProfile=e)}async processMessage(e){if(!this.messageHandler)return;const t=typeof e.msgId=="string";i.info(`[AgentClient] \u6536\u5230${t?"\u79C1\u4FE1":"\u7FA4\u6D88\u606F"}\u6765\u81EA ${e.senderName}: ${e.content.substring(0,50)}...`);try{const n=await this.messageHandler(e);if(t){const r=e;r.requireReply&&r.callId&&await this.replyToCall(r.callId,r.senderId,n||"\u5DF2\u6536\u5230\u6D88\u606F\uFF0C\u6B63\u5728\u5904\u7406\u4E2D...")}}catch(n){const r=typeof e.msgId=="string";if(i.error("[AgentClient] \u5904\u7406\u6D88\u606F\u5931\u8D25: type=%s, senderId=%s, senderName=%s, msgId=%s, error=%s",r?"\u79C1\u4FE1":"\u7FA4\u6D88\u606F",e.senderId,e.senderName,e.msgId,n instanceof Error?n.message:String(n)),r){const s=e;s.requireReply&&s.callId&&await this.replyToCall(s.callId,s.senderId,`\u5904\u7406\u5931\u8D25: ${n}`)}}}ensureRegistered(){if(!this.agentId)throw new Error("Agent is not registered")}delay(e){return new Promise(t=>{this.pollTimer=setTimeout(t,e)})}onNewCharacter(e){this.newCharacterHandler=e}getState(){return{agentId:this.agentId,displayName:this.displayName,projectId:this.projectId,isConnected:this.wsClient.isConnected(),isRunning:this.isRunning}}getAgentConfig(){return this.agentConfig}getServerConfig(){return this.serverConfig}reloadConfig(){h.loadConfig(),this.agentConfig=h.getAgentConfig(),i.info(`[AgentClient] \u914D\u7F6E\u5DF2\u91CD\u65B0\u52A0\u8F7D\uFF0C\u89D2\u8272: ${this.agentConfig.roleName}`)}enterDegradedMode(){this.isDegradedMode=!0,i.warn("[AgentClient] \u8FDB\u5165\u964D\u7EA7\u6A21\u5F0F\uFF0C\u5C06\u5728\u540E\u53F0\u6301\u7EED\u5C1D\u8BD5\u91CD\u8FDE")}exitDegradedMode(){this.isDegradedMode=!1,i.info("[AgentClient] \u9000\u51FA\u964D\u7EA7\u6A21\u5F0F")}isInDegradedMode(){return this.isDegradedMode}async retryRegistrationInBackground(e,t){let n=0;(async()=>{for(;this.isDegradedMode;)try{i.info(`[AgentClient] \u964D\u7EA7\u6A21\u5F0F\uFF1A\u5C1D\u8BD5\u91CD\u65B0\u6CE8\u518C (${n+1}/${t===-1?"\u65E0\u9650":t})`);const s=await this.register();i.info(`[AgentClient] \u964D\u7EA7\u6A21\u5F0F\uFF1A\u6CE8\u518C\u6210\u529F - ${s.displayName} (${s.agentId})`),this.exitDegradedMode(),this.messageHandler&&this.start(this.messageHandler);return}catch(s){n++;const a=s instanceof Error?s.message:String(s);if(i.warn(`[AgentClient] \u964D\u7EA7\u6A21\u5F0F\uFF1A\u6CE8\u518C\u5931\u8D25 (${n}/${t===-1?"\u65E0\u9650":t}): ${a}`),t>0&&n>=t){i.error("[AgentClient] \u964D\u7EA7\u6A21\u5F0F\uFF1A\u8FBE\u5230\u6700\u5927\u91CD\u8BD5\u6B21\u6570\uFF0C\u505C\u6B62\u91CD\u8FDE"),this.isDegradedMode=!1;return}await new Promise(c=>setTimeout(c,e))}})().catch(s=>{i.error("[AgentClient] \u964D\u7EA7\u6A21\u5F0F\u540E\u53F0\u91CD\u8BD5\u5FAA\u73AF\u5F02\u5E38\u9000\u51FA: error=%s, stack=%s",s instanceof Error?s.message:String(s),s instanceof Error?s.stack:"(no stack)")})}initializeStatusReporter(){if(!this.agentId){i.warn("[AgentClient] \u65E0\u6CD5\u521D\u59CB\u5316\u72B6\u6001\u62A5\u544A\u5668\uFF1AagentId \u4E3A\u7A7A");return}this.statusReporter=new A({agentId:this.agentId,sendStatusUpdate:e=>{this.wsClient.send({type:"AGENT_STATUS",data:e,timestamp:new Date().toISOString()})}}),w(e=>this.reportMcpNodeLog(e)),this.startRuntimeTokenRefresh(),i.info("[AgentClient] \u72B6\u6001\u62A5\u544A\u5668\u5DF2\u521D\u59CB\u5316")}startRuntimeTokenRefresh(){this.stopRuntimeTokenRefresh();const e=this.serverConfig.runtimeTokenRefreshIntervalMs;if(!e||e<=0){i.warn("[AgentClient] runtimeTokenRefreshIntervalMs \u672A\u914D\u7F6E\u6216\u65E0\u6548\uFF0C\u8DF3\u8FC7\u4E3B\u52A8\u7EED\u671F");return}const t=this.agentId;if(!t){i.warn("[AgentClient] agentId \u4E3A\u7A7A\uFF0C\u8DF3\u8FC7\u4E3B\u52A8\u7EED\u671F");return}this.runtimeTokenRefreshTimer=setInterval(async()=>{try{await this.httpClient.refreshRuntimeAccessToken(t)&&i.info("[AgentClient] runtimeAccessToken \u5DF2\u4E3B\u52A8\u7EED\u671F")}catch(n){i.warn("[AgentClient] \u4E3B\u52A8\u7EED\u671F runtimeAccessToken \u5931\u8D25: %s",n instanceof Error?n.message:String(n)),n instanceof Error&&n.stack&&i.warn("[AgentClient] \u4E3B\u52A8\u7EED\u671F\u5F02\u5E38\u5806\u6808:",n.stack)}},e),this.runtimeTokenRefreshTimer.unref?.(),i.info(`[AgentClient] runtime token \u4E3B\u52A8\u7EED\u671F\u5DF2\u542F\u52A8\uFF0C\u95F4\u9694 ${e}ms`)}stopRuntimeTokenRefresh(){this.runtimeTokenRefreshTimer&&(clearInterval(this.runtimeTokenRefreshTimer),this.runtimeTokenRefreshTimer=null)}reportMcpNodeLog(e){const t=this.wsClient;!this.agentId||!this.wsClient.isConnected()||typeof t.sendMcpNodeLog!="function"||t.sendMcpNodeLog(e)}getStatusReporter(){return this.statusReporter}}export{N as AgentClient,T as PollLongPollTimeoutError};
|
|
2
2
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import C from"node:fs";import W from"node:os";import f from"node:path";import{execFile as ee}from"node:child_process";import{fileURLToPath as te}from"node:url";import{Server as re}from"@modelcontextprotocol/sdk/server/index.js";import{StdioServerTransport as ie}from"@modelcontextprotocol/sdk/server/stdio.js";import{CallToolRequestSchema as se,ListToolsRequestSchema as ne}from"@modelcontextprotocol/sdk/types.js";import{AgentClient as oe,PollLongPollTimeoutError as ae}from"./agent-client.js";import{normalizeServerHttpBase as ce,McpToolError as le}from"./http-client.js";import{MCP_SERVER_NAME as me,MCP_SERVER_VERSION as de,REGISTER_MAX_RETRIES as B,REGISTER_RETRY_INTERVAL_MS as ue,DEGRADED_MODE_ENABLED as G,DEGRADED_MODE_RETRY_INTERVAL_MS as fe,DEGRADED_MODE_MAX_RETRIES as pe}from"./constants.js";import{resolveAcodeDataHome as K}from"./config.js";import{logger as c}from"./logger.js";import{meetingDebugFingerprints as L,meetingDebugLog as k}from"./meeting-debug-log.js";import{MCP_TOOLS as H,MEMORY_TOOL_NAMES as Y}from"./mcp-tools.js";import{TOOL_GROUPS as he,buildToolGroupManifest as ge,findToolGroupByToolName as ye,normalizeFeatureState as J}from"./tool-groups.js";import{MessageBuffer as _e}from"./message-buffer.js";import{ContextManager as we}from"./context-manager.js";import{officeKindOf as F,officeWorkspaceRoot as q,packOfficeFile as D,resolveOfficeFile as O,writeOfficeFileAtomic as x,writeOfficeFileAtomicAs as Se}from"./office/office-workspace.js";import{prepareOfficeImageCommands as Me,officeResolveImageSource as ve}from"./office/office-image.js";import{prepareOfficeEquationCommands as be}from"./office/office-equation.js";import{MemoryCapacityError as Te,MemoryStore as U}from"./memory-store.js";import{ServerMemoryStore as Ae}from"./server-memory-store.js";const Re=3e3,Ee=3e4,j=10,V=(()=>{const R=Number.parseInt(process.env.AWS_MCP_FILE_CHANGE_RENOTIFY_COOLDOWN_MS||"",10);return Number.isFinite(R)&&R>0?R:30*6e4})(),X=500,ke=30,Ie=new Set(["<",">",":",'"',"/","\\","|","?","*"]),Ce=200*1024*1024;function Pe(R=process.env.AWS_ATTACHMENT_MAX_SIZE_MB){const e=Number(R);return Number.isFinite(e)&&e>0?Math.floor(e)*1024*1024:Ce}const Z=Pe(),$e={".pdf":"application/pdf",".txt":"text/plain",".md":"text/markdown",".csv":"text/csv",".json":"application/json",".html":"text/html",".xml":"application/xml",".doc":"application/msword",".docx":"application/vnd.openxmlformats-officedocument.wordprocessingml.document",".xls":"application/vnd.ms-excel",".xlsx":"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",".ppt":"application/vnd.ms-powerpoint",".pptx":"application/vnd.openxmlformats-officedocument.presentationml.presentation",".zip":"application/zip",".gz":"application/gzip",".tar":"application/x-tar",".7z":"application/x-7z-compressed",".rar":"application/vnd.rar",".png":"image/png",".jpg":"image/jpeg",".jpeg":"image/jpeg",".gif":"image/gif",".webp":"image/webp",".svg":"image/svg+xml",".mp3":"audio/mpeg",".mp4":"video/mp4"};function Oe(R){return $e[f.extname(R).toLowerCase()]||"application/octet-stream"}function Ne(R){return(R||"").replace(/[|[\]\r\n]/g,"_").trim()||"\u6587\u4EF6"}function De(R){if(!Number.isFinite(R)||R<=0)return"0 B";const e=["B","KB","MB","GB"],t=Math.min(e.length-1,Math.floor(Math.log(R)/Math.log(1024)));return`${Number.parseFloat((R/1024**t).toFixed(2))} ${e[t]}`}function Fe(R){return`[\u6587\u4EF6: ${Ne(R.name)} | ${R.url} | ${R.mediaType||"application/octet-stream"} | ${De(R.size)}]`}function Le(R){return C.existsSync(f.join(R,"packages","cli","dist","index.mjs"))||C.existsSync(f.join(R,"packages","cli","src","index.ts"))}function Be(R){const e=[],t=String(process.env.AWS_OPEN_PENCIL_HOME||"").trim();t&&e.push(f.resolve(t));const r=f.resolve(R);e.push(f.join(r,"open-pencil")),e.push(f.resolve(te(new URL("../../../../open-pencil",import.meta.url))));for(let i=f.dirname(r);e.push(f.join(i,"open-pencil")),f.dirname(i)!==i;i=f.dirname(i));return{home:e.find(Le)??e[0],searched:e}}class v{server;agentClient;messageBuffer;memoryStore;roleMemoryStore;sessionContextMemoryStore;initialRoleName="";hasRoleName=!1;contextManager;isSubAgent;fileChangeNotifyHistory=new Map;featuresCache=null;static FEATURES_CACHE_TTL_MS=5e3;leaseRenewalTimer=null;activeLeaseUris=new Set;static LEASE_DURATION_MINUTES=10;static LEASE_RENEW_INTERVAL_MS=6e4;profileSynced=!1;urgentMeetingHydrateRequested=!1;urgentTaskHydrateRequested=!1;taskHydrateRetryBudget=0;static MEETING_HYDRATE_RETRY_COUNT=3;static MEETING_HYDRATE_RETRY_DELAY_MS=150;static MEETING_HYDRATE_TIMEOUT_REARM_DELAY_MS=1e4;meetingHydrateTimeoutRearmDelayMs=v.MEETING_HYDRATE_TIMEOUT_REARM_DELAY_MS;static MEETING_HYDRATE_POLL_TIMEOUT_MS=65e3;static MEETING_PREEMPTIVE_JOIN_WAIT_MS=45e3;static TASK_HYDRATE_RETRY_BUDGET=1;pendingPollMessage=null;syncRoleMemoryStore(e){if(c.info(`[McpServer] syncRoleMemoryStore \u88AB\u8C03\u7528: displayName=${e.displayName}, roleName="${e.roleName??"(\u7A7A)"}", id=${e.id}`),!e.roleName){c.warn(`[McpServer] syncRoleMemoryStore: profile.roleName \u4E3A\u7A7A\uFF0ChasRoleName \u4FDD\u6301 false\u3002profile=${JSON.stringify({id:e.id,displayName:e.displayName,roleName:e.roleName,instanceName:e.instanceName})}`);return}const t=v.sanitizeRoleDirectoryName(e.roleName);this.hasRoleName=!0,t!==this.initialRoleName&&(c.info(`[McpServer] \u89D2\u8272\u76EE\u5F55\u4E0E\u521D\u59CB\u503C\u4E0D\u4E00\u81F4\uFF0C\u91CD\u5EFA roleMemoryStore: "${this.initialRoleName}" -> "${t}"`),this.roleMemoryStore=new U(v.buildRoleMemoryStorePath(t)),this.initialRoleName=t)}maybeSyncPermanentMemoryToServer(){this.doMaybeSyncPermanentMemoryToServer().catch(e=>{c.warn("[McpServer] maybeSyncPermanentMemoryToServer \u5F02\u5E38: %s, stack=%s",e instanceof Error?e.message:String(e),e instanceof Error?e.stack:"(no stack)")})}async doMaybeSyncPermanentMemoryToServer(){c.info("[McpServer] maybeSyncPermanentMemoryToServer \u5F00\u59CB\uFF0CinitialRoleName="+this.initialRoleName);let e;try{e=await this.memoryStore.getStats()}catch(n){c.warn("[McpServer] \u83B7\u53D6 server \u8BB0\u5FC6\u7EDF\u8BA1\u5931\u8D25\uFF0C\u8DF3\u8FC7\u540C\u6B65:",n instanceof Error?n.message:n);return}const t=e.by_type.project_memory?.count??0;c.info(`[McpServer] server memory \u8BA1\u6570=${t}`);let r=[];try{r=await this.roleMemoryStore.listByType("project_memory"),c.info(`[McpServer] \u89D2\u8272\u5B50\u76EE\u5F55\u8BFB\u53D6\u5230 ${r.length} \u6761\u9879\u76EE\u8BB0\u5FC6`)}catch(n){c.warn("[McpServer] \u8BFB\u53D6\u89D2\u8272\u5B50\u76EE\u5F55\u9879\u76EE\u8BB0\u5FC6\u5931\u8D25:",n instanceof Error?n.message:n)}if(r.length===0){const n=f.dirname(v.buildRoleMemoryStorePath(this.initialRoleName));c.info(`[McpServer] \u5C1D\u8BD5\u4ECE\u9057\u7559\u76EE\u5F55\u8BFB\u53D6: ${n}`);try{const o=await new U(n).listByType("project_memory");o.length>0&&(c.info(`[McpServer] \u4ECE\u9057\u7559\u76EE\u5F55\u8BFB\u53D6\u5230 ${o.length} \u6761\u9879\u76EE\u8BB0\u5FC6`),r=o)}catch(a){c.warn("[McpServer] \u8BFB\u53D6\u9057\u7559\u76EE\u5F55\u9879\u76EE\u8BB0\u5FC6\u5931\u8D25:",a instanceof Error?a.message:a)}}if(r.length===0){c.info("[McpServer] \u672C\u5730\u4E5F\u65E0\u9879\u76EE\u8BB0\u5FC6\uFF0C\u8DF3\u8FC7\u540C\u6B65");return}if(t>=r.length){c.info(`[McpServer] \u670D\u52A1\u7AEF\u5DF2\u6709 ${t} \u6761 >= \u672C\u5730 ${r.length} \u6761\uFF0C\u65E0\u9700\u56DE\u586B`);return}c.info(`[McpServer] \u68C0\u6D4B\u5230\u7F3A\u91CF\uFF1A\u672C\u5730 ${r.length} \u6761 > \u670D\u52A1\u7AEF ${t} \u6761\uFF0C\u5F00\u59CB\u589E\u91CF\u56DE\u586B`);let s=0,i=0;for(const n of r)try{await this.memoryStore.createMemory({memory_type:"project_memory",uri:n.uri,title:n.title,content:n.content,keywords:n.keywords,bound_files:n.bound_files,file_md5_map:n.file_md5_map,last_check_time:n.last_check_time}),s++,c.info(`[McpServer] \u540C\u6B65\u9879\u76EE\u8BB0\u5FC6\u6210\u529F: ${n.uri}`)}catch(a){const o=a instanceof Error?a.message:String(a);o.includes("already exists")||o.includes("Memory already exists")||c.warn(`[McpServer] \u540C\u6B65\u9879\u76EE\u8BB0\u5FC6\u5931\u8D25 (${n.uri}): ${o}`),i++}c.info(`[McpServer] \u9879\u76EE\u8BB0\u5FC6\u540C\u6B65\u5B8C\u6210: \u6210\u529F ${s}, \u8DF3\u8FC7 ${i}, \u5171 ${r.length}`),await this.reportMemoryStatsToServer()}normalizeBoundFilePath(e){const t=String(e||"").trim().replace(/\\/g,"/");if(!t)return t;const r=t.startsWith("@/")?t.substring(1):t;return r.startsWith("./")?r:`./${r.replace(/^\/+/,"")}`}normalizeBoundFiles(e){return!e||!Array.isArray(e)?e:e.map(t=>this.normalizeBoundFilePath(String(t)))}async validateBoundFilesExist(e){if(!e||e.length===0)return;const t=process.env.AWS_WORKSPACE_PATH||process.cwd(),{access:r}=await import("node:fs/promises"),s=[];for(const i of e)try{const n=f.resolve(t,i);await r(n)}catch{s.push(i)}if(s.length>0)throw new Error(`\u7ED1\u5B9A\u7684\u6587\u4EF6\u4E0D\u5B58\u5728\uFF0C\u8BF7\u786E\u8BA4\u6587\u4EF6\u8DEF\u5F84\u6B63\u786E\u540E\u518D\u91CD\u65B0\u63D0\u4EA4:
|
|
2
2
|
${s.map(i=>` - ${i}`).join(`
|
|
3
|
-
`)}`)}toMemoryWriteResult(e){return{id:e.id,uri:e.uri,domain:e.domain,path:e.path,title:e.title,memory_type:e.memory_type,createdAt:e.createdAt,updatedAt:e.updatedAt,version:e.version,keywords:e.keywords,bound_files:e.bound_files}}toMemoryRecordWithMetadata(e){return{id:e.id,uri:e.uri,domain:e.domain,path:e.path,title:e.title,content:e.content,memory_type:e.memory_type,createdAt:e.createdAt,updatedAt:e.updatedAt,version:e.version,keywords:e.keywords,bound_files:e.bound_files,file_md5_map:e.file_md5_map,memory_status:e.memory_status,updating_agent_id:e.updating_agent_id,last_check_time:e.last_check_time,path_prefix:e.path_prefix,readonly:e.readonly,source_agent_id:e.source_agent_id,source_display_name:e.source_display_name,source_role_name:e.source_role_name,source_workspace_path:e.source_workspace_path}}constructor(){this.agentClient=new oe,this.messageBuffer=new _e,this.initialRoleName=v.resolveRoleMemoryDirectoryName(),this.hasRoleName=!!process.env.AWS_ROLE_NAME;const e=v.resolveMemoryStorePaths();this.memoryStore=new Ae(this.agentClient),this.roleMemoryStore=new U(e.rolePath),this.sessionContextMemoryStore=new U(f.join(f.dirname(e.rolePath),"..","session_context")),this.isSubAgent=process.env.AWS_SUB_AGENT==="true",this.contextManager=new we(this.sessionContextMemoryStore),this.server=new re({name:me,version:de},{capabilities:{tools:{}},instructions:ge()}),this.setupHandlers()}async resolveGroupConfigState(e){if(!e.featureKey)return"expanded";const t=v.GROUP_ENV_KEYS[e.key],{features:r,ok:s}=await this.fetchRuntimeFeaturesWithStatus();if(s&&Object.keys(r).length>0){const n=v.parentGateOf(e.featureKey);return n&&J(r[n])==="disabled"?"disabled":J(r[e.featureKey])??e.defaultState}if(!t)return e.defaultState;const i=process.env[t];return i==="collapsed"?"collapsed":i==="1"||i==="expanded"?"expanded":i===void 0||i===""?e.defaultState:"disabled"}async isToolGroupEnabled(e){return await this.resolveGroupConfigState(e)!=="disabled"}static GROUP_ENV_KEYS={launch:"AWS_LAUNCH_CONFIG_TOOLS",hire:"AWS_HIRE_TOOLS",pencil:"AWS_PENCIL_TOOLS",draw:"AWS_DRAW_TOOLS",office:"AWS_OFFICE_TOOLS",task:"AWS_COLLABORATION_TASK_TOOLS",meeting:"AWS_COLLABORATION_MEETING_TOOLS",debug:"AWS_COLLABORATION_DEBUG_TOOLS",fileHistory:"AWS_COLLABORATION_FILE_HISTORY_TOOLS",abilityMarket:"AWS_ABILITY_MARKET_TOOLS",abilityDev:"AWS_ABILITY_DEV_TOOLS"};static PARENT_GATE_PREFIXES=[["agentSys","agentSys."],["collaboration","collaboration."]];static parentGateOf(e){if(e){for(const[t,r]of v.PARENT_GATE_PREFIXES)if(e.startsWith(r))return t}}async filterDisabledGroups(){let e=H;for(const t of he)await this.resolveGroupConfigState(t)==="disabled"&&(e=e.filter(s=>!t.toolNames.has(s.name)));return e}setupHandlers(){this.server.setRequestHandler(ne,async()=>this.isSubAgent?{tools:H.filter(e=>Y.has(e.name))}:{tools:await this.filterDisabledGroups()}),this.server.setRequestHandler(se,async(e,t)=>{const{name:r,arguments:s}=e.params;try{const i=await this.handleToolCall(r,s,t?.signal);return{content:this.buildToolResultContent(i)}}catch(i){const n=i instanceof Error?i.message:String(i),a=i instanceof Te?{error:n,...i.details}:i instanceof le&&(i.errorCode||i.field)?{error:n,...i.errorCode?{errorCode:i.errorCode}:{},...i.field?{field:i.field}:{}}:{error:n};return c.error("[McpServer] \u5DE5\u5177\u8C03\u7528\u5F02\u5E38: tool=%s, error=%s, stack=%s",r,n,i instanceof Error?i.stack:"(no stack)"),{content:[{type:"text",text:JSON.stringify(a,null,2)}],isError:!0}}})}async handlePencilExportImage(e){const t=typeof e.savePath=="string"?e.savePath.trim():"",r=await this.agentClient.callAgentScopedTool("pencil_export_image",e),s=typeof r?.image=="string"?r.image:"";if(!s)return r;const i=s.startsWith("data:")?s.slice(s.indexOf(",")+1):s,n={...r};delete n.image,delete n.mimeType,n.sizeKb=Math.ceil(i.length*3/4/1024);try{const{mkdir:a,writeFile:o}=await import("node:fs/promises");let l;if(t){const m=f.resolve(process.env.AWS_WORKSPACE_PATH||process.cwd());l=f.resolve(m,t)}else{const p=(typeof r?.docId=="string"?r.docId:"").replace(/[^a-zA-Z0-9_-]/g,"").slice(0,40)||"doc",u=f.join(W.tmpdir(),"pencil-export");await a(u,{recursive:!0}),l=f.join(u,`${p}-${Date.now()}-${Math.random().toString(36).slice(2,8)}.png`)}return await a(f.dirname(l),{recursive:!0}),await o(l,Buffer.from(i,"base64")),{...n,savedTo:l,temp:!t}}catch(a){return{...n,savedTo:null,saveError:a instanceof Error?a.message:String(a)}}}static PENCIL_EXPORT_FORMATS=new Set(["svg","html","png","jpg","webp","pptx","fig","jsx"]);async handlePencilExportDocument(e){const t=typeof e.format=="string"&&e.format.trim()?e.format.trim().toLowerCase():"svg";if(!v.PENCIL_EXPORT_FORMATS.has(t))throw new Error(`\u4E0D\u652F\u6301\u7684\u5BFC\u51FA\u683C\u5F0F: ${t}\uFF08\u652F\u6301 svg/html/png/jpg/webp/pptx/fig/jsx\uFF1Bpdf \u6682\u4E0D\u652F\u6301\uFF09`);const r=typeof e.nodeId=="string"&&e.nodeId.trim()?e.nodeId.trim():"";if(t==="jsx"&&!r)throw new Error("jsx \u5BFC\u51FA\u9700\u8981\u4F20 nodeId\uFF08\u6765\u81EA pencil_get_tree\uFF09\uFF0C\u5B83\u6309\u5355\u8282\u70B9\u751F\u6210 React \u7EC4\u4EF6");const s=typeof e.savePath=="string"?e.savePath.trim():"",i=f.resolve(process.env.AWS_WORKSPACE_PATH||process.cwd()),n=await this.agentClient.callAgentScopedTool("pencil_export_document",e),a=typeof n?.snapshotJson=="string"?n.snapshotJson:"";if(!a)return n;const{mkdir:o,writeFile:l,stat:m}=await import("node:fs/promises"),u=(typeof n?.docId=="string"?n.docId:"").replace(/[^a-zA-Z0-9_-]/g,"").slice(0,40)||"doc",_=`${Date.now()}-${Math.random().toString(36).slice(2,8)}`,b=f.join(W.tmpdir(),"pencil-export");await o(b,{recursive:!0});const h=f.join(b,`${u}-${_}.snapshot.json`);await l(h,a,"utf8");const M=t,d=s?f.resolve(i,s):f.join(b,`${u}-${_}.${M}`),{home:y,searched:E}=Be(i),g=[{cmd:process.execPath,entry:f.join(y,"packages","cli","dist","index.mjs"),cwd:y},{cmd:"bun",entry:f.join(y,"packages","cli","src","index.ts"),cwd:y}].filter(I=>C.existsSync(I.entry));if(g.length===0)throw new Error(`\u672A\u627E\u5230 open-pencil CLI\uFF08\u5DF2\u67E5\u627E\u76EE\u5F55\uFF1A${E.join("\uFF1B")}\uFF09\uFF0C\u8BF7\u786E\u8BA4\u5B89\u88C5\u5E03\u5C40\u6216\u8BBE\u7F6E\u73AF\u5883\u53D8\u91CF AWS_OPEN_PENCIL_HOME \u6307\u5411 open-pencil \u4ED3\u5E93\u6839\u76EE\u5F55`);const S=["export",h,"--snapshot","-f",t,"-o",d];r&&S.push("--node",r),t==="html"&&S.push("--html","standalone"),(t==="png"||t==="jpg"||t==="webp")&&(typeof e.scale=="number"&&e.scale>0&&S.push("--scale",String(e.scale)),typeof e.quality=="number"&&e.quality>0&&S.push("--quality",String(e.quality)));const P=[];let w=!1;for(const I of g)try{await this.runPencilCli(I.cmd,[I.entry,...S],I.cwd),w=!0;break}catch($){P.push(`${f.basename(I.cmd)}: ${$ instanceof Error?$.message:String($)}`)}if(!w)throw new Error(`\u753B\u5E03\u5BFC\u51FA\u5931\u8D25\uFF08format=${t}\uFF09\uFF1A${P.join("\uFF1B")||"\u672A\u77E5\u9519\u8BEF"}`);let A=null;try{A=Math.ceil((await m(d)).size/1024)}catch{A=null}const T={...n};return delete T.snapshotJson,{...T,format:t,savedTo:d,temp:!s,sizeKb:A}}runPencilCli(e,t,r){return new Promise((s,i)=>{ee(e,t,{cwd:r,timeout:18e4,maxBuffer:16*1024*1024},(n,a,o)=>{if(n){const l=String(o||a||"").trim().split(/\r?\n/).filter(Boolean).slice(-3).join(" | ");i(new Error(l||n.message));return}s(String(a||""))})})}static DRAW_EXPORT_FORMATS=new Set(["xml","drawio"]);async handleDrawExportDocument(e){const t=typeof e.format=="string"&&e.format.trim()?e.format.trim().toLowerCase():"xml";if(t==="svg"||t==="png"||t==="jpg"||t==="webp")throw new Error(`${t} \u5BFC\u51FA\u9700\u8981\u7ED8\u56FE\u6E32\u67D3\u7BA1\u7EBF\uFF08\u9636\u6BB5 2\uFF09\uFF1B\u672C\u8F6E\u8BF7\u7528 format=xml \u5BFC\u51FA draw.io <mxfile> \u539F\u6587\uFF0C\u6216\u7528\u6587\u4EF6\u8BFB\u53D6\u5DE5\u5177\u67E5\u770B XML/\u5728\u652F\u6301 draw.io \u7684\u7F16\u8F91\u5668\u4E2D\u6253\u5F00`);if(!v.DRAW_EXPORT_FORMATS.has(t))throw new Error(`\u4E0D\u652F\u6301\u7684\u5BFC\u51FA\u683C\u5F0F: ${t}\uFF08\u672C\u8F6E\u652F\u6301 xml/drawio\uFF09`);const r=typeof e.savePath=="string"?e.savePath.trim():"",s=f.resolve(process.env.AWS_WORKSPACE_PATH||process.cwd()),i=await this.agentClient.callAgentScopedTool("draw_export_document",e),n=typeof i?.docXml=="string"?i.docXml:"";if(!n)return i;const{mkdir:a,writeFile:o,stat:l}=await import("node:fs/promises"),p=(typeof i?.docId=="string"?i.docId:"").replace(/[^a-zA-Z0-9_-]/g,"").slice(0,40)||"doc",u=`${Date.now()}-${Math.random().toString(36).slice(2,8)}`,_=f.join(W.tmpdir(),"draw-export");await a(_,{recursive:!0});const b=t,h=r?f.resolve(s,r):f.join(_,`${p}-${u}.${b}`);await a(f.dirname(h),{recursive:!0}),await o(h,n,"utf8");let M=null;try{M=Math.ceil((await l(h)).size/1024)}catch{M=null}const d={...i};return delete d.docXml,{...d,format:t,savedTo:h,temp:!r,sizeKb:M}}async handleDrawExportImage(e){const t=await this.agentClient.callAgentScopedTool("draw_export_image",e),r=typeof t?.image=="string"?t.image:"";if(!r)return t;const s=r.startsWith("data:")?r.slice(r.indexOf(",")+1):r,i=typeof e.savePath=="string"?e.savePath.trim():"",n={...t};delete n.image,delete n.mimeType,n.sizeKb=Math.ceil(s.length*3/4/1024);try{const{mkdir:a,writeFile:o}=await import("node:fs/promises");let l;if(i){const m=f.resolve(process.env.AWS_WORKSPACE_PATH||process.cwd());l=f.resolve(m,i)}else{const p=(typeof t?.docId=="string"?t.docId:"").replace(/[^a-zA-Z0-9_-]/g,"").slice(0,40)||"doc",u=f.join(W.tmpdir(),"draw-export");await a(u,{recursive:!0}),l=f.join(u,`${p}-${Date.now()}-${Math.random().toString(36).slice(2,8)}.png`)}return await a(f.dirname(l),{recursive:!0}),await o(l,Buffer.from(s,"base64")),{...n,savedTo:l,temp:!i}}catch(a){return{...n,savedTo:null,saveError:a instanceof Error?a.message:String(a)}}}async handleOfficeTool(e,t){switch(e){case"office_create":return await this.officeCreate(t);case"office_view":return await this.officeView(t);case"office_edit":return await this.officeEdit(t);case"office_validate":case"office_preview":return await this.officeFileForward(e,t);case"office_format":return await this.officeFormat(t);case"office_apply_profile":return await this.officeApplyProfile(t);case"office_generate_from_template":return await this.officeGenerateFromTemplate(t);case"office_open_document":return await this.officeOpenDocument(t);case"office_close_document":return await this.officeCloseDocument(t);case"office_list_open":return await this.officeListOpen(t);case"office_list_documents":return await this.officeListDocuments(t);case"office_delete_document":return await this.officeDeleteDocument(t);case"office_share_document":return await this.officeShareDocument(t);case"office_unshare_document":return await this.officeUnshareDocument(t);case"office_get_changes":return await this.officeGetChanges(t);default:throw new Error(`\u672A\u77E5\u7684 office \u5DE5\u5177: ${e}`)}}officeFileArg(e){const t=typeof e.file=="string"?e.file.trim():"";if(!t)throw new Error("file \u4E0D\u80FD\u4E3A\u7A7A");return t}backupReceipt(e){return e?{backupPath:e,backupHint:`\u5DF2\u81EA\u52A8\u5907\u4EFD\u539F\u6587\u4EF6\u5230 ${e}\uFF08\u4FDD\u7559\u6700\u8FD1\u82E5\u5E72\u4EFD\uFF09\uFF0C\u5982\u9700\u56DE\u6EDA\u53EF\u76F4\u63A5\u590D\u5236\u8986\u76D6`}:{}}async officeCreate(e){const t=this.officeFileArg(e),r=await this.agentClient.callAgentScopedTool("office_create",{fileName:f.basename(O(t)),locale:typeof e.locale=="string"&&e.locale.trim()?e.locale.trim():void 0,template:typeof e.template=="string"&&e.template.trim()?e.template.trim():void 0});if(r?.ok===!1||typeof r?.fileBase64!="string")return r;const s=x(t,String(r.fileBase64));return{ok:!0,file:t,kind:F(O(t))??void 0,savedTo:s.absolutePath,sizeKb:s.sizeKb,docId:typeof r.docId=="string"?r.docId:void 0,source:typeof r.source=="string"?r.source:void 0,fileUrl:typeof r.fileUrl=="string"?r.fileUrl:void 0,message:typeof r.message=="string"?r.message:`\u5DF2\u521B\u5EFA\u7A7A\u767D\u6587\u6863: ${t}`,hint:"\u6587\u6863\u5DF2\u540C\u6B65\u5230\u4E91\u6587\u6863\uFF08\u53EF\u5728 Dashboard \u9762\u677F\u67E5\u770B\u4E0E\u534F\u4F5C\uFF09\u3002\u7528 office_view \u4E86\u89E3\u7ED3\u6784\u540E\u5373\u53EF office_edit \u5199\u5165\u5185\u5BB9"}}async officeView(e){const t=D(this.officeFileArg(e)),r={fileName:t.fileName,fileBase64:t.fileBase64,mode:typeof e.mode=="string"&&e.mode.trim()?e.mode.trim():"text",start:typeof e.start=="number"?e.start:void 0,maxLines:typeof e.maxLines=="number"?e.maxLines:void 0,limit:typeof e.limit=="number"?e.limit:void 0,query:typeof e.query=="string"&&e.query.trim()?e.query.trim():void 0};return Array.isArray(e.paths)&&e.paths.length>0&&(r.paths=e.paths),await this.agentClient.callAgentScopedTool("office_view",r)}async officeEdit(e){const t=this.officeFileArg(e);if(!Array.isArray(e.commands)||e.commands.length===0)throw new Error("commands \u5FC5\u987B\u662F\u975E\u7A7A\u6570\u7EC4");await Me(e.commands,process.env.AWS_WORKSPACE_PATH||process.cwd()),be(e.commands);const r=D(t),s=typeof e.docId=="string"&&e.docId.trim()?e.docId.trim():void 0,i=await this.agentClient.callAgentScopedTool("office_edit",{fileName:r.fileName,fileBase64:r.fileBase64,commands:e.commands,bestEffort:e.bestEffort===!0,docId:s});if(i?.ok===!1)return i;const n={};typeof i?.docId=="string"&&(n.docId=i.docId),typeof i?.version=="number"&&(n.version=i.version),typeof i?.fileUrl=="string"&&(n.fileUrl=i.fileUrl);const a=Array.isArray(i?.warnings)&&i.warnings.length>0?{warnings:i.warnings}:{};if(typeof i?.fileBase64=="string"){const o=x(t,String(i.fileBase64));return{ok:!0,file:t,kind:F(O(t))??void 0,results:Array.isArray(i.results)?i.results:[],changed:!0,savedTo:o.absolutePath,sizeKb:o.sizeKb,...this.backupReceipt(o.backupPath),...a,...n}}return{ok:!0,results:Array.isArray(i?.results)?i.results:[],changed:!1,...a,...n}}async officeFormat(e){const t=this.officeFileArg(e),r=typeof e.action=="string"?e.action.trim():"",s=r==="dryRun"||r==="dryrun";if(!["check","fix","dryRun"].includes(r))throw new Error('action \u5FC5\u987B\u662F "check"\u3001"fix" \u6216 "dryRun"');const i={action:r,annotate:e.annotate===!0};if(typeof e.preset=="string"&&e.preset.trim()&&(i.preset=e.preset.trim()),e.rules&&typeof e.rules=="object"&&(i.rules=e.rules),typeof e.rulesFile=="string"&&e.rulesFile.trim()&&(i.rules=await this.readOfficeRulesFile(e.rulesFile.trim())),e.mergePreset===!0&&(i.mergePreset=!0),Array.isArray(e.exclude)&&e.exclude.length>0&&(i.exclude=e.exclude),!i.preset&&!i.rules)throw new Error("\u9700\u8981 preset\u3001rulesFile \u6216 rules \u4E4B\u4E00\u63D0\u4F9B\u683C\u5F0F\u89C4\u5219");const o=(typeof e.outputFile=="string"&&e.outputFile.trim()?e.outputFile.trim():"")||(i.annotate===!0&&r==="check"?this.deriveSiblingFileName(t,"-\u6807\u6CE8\u7248"):t),l=D(t),m=await this.agentClient.callAgentScopedTool("office_format",{fileName:l.fileName,fileBase64:l.fileBase64,...i});if(m?.ok===!1)return m;if(typeof m?.fileBase64=="string"&&!s&&(r==="fix"||i.annotate===!0)){const p=o!==t,u=p?Se(t,f.basename(o),String(m.fileBase64)):x(t,String(m.fileBase64)),{fileBase64:_,...b}=m;return{...b,file:t,...p?{outputFile:o,originalPreserved:!0}:{},kind:F(O(o))??void 0,savedTo:u.absolutePath,sizeKb:u.sizeKb,...this.backupReceipt(u.backupPath)}}if(typeof m?.fileBase64=="string"){const{fileBase64:p,...u}=m;return u}return m}deriveSiblingFileName(e,t){const r=O(e),s=f.extname(r),n=`${f.basename(r,s)}${t}${s}`;return f.isAbsolute(e)?f.join(f.dirname(r),n):n}async officeApplyProfile(e){const t=this.officeFileArg(e);if(typeof e.profile!="object"||e.profile===null)throw new Error("profile \u5FC5\u987B\u662F\u975E\u7A7A\u5BF9\u8C61");const r=D(t),s=await this.agentClient.callAgentScopedTool("office_apply_profile",{fileName:r.fileName,fileBase64:r.fileBase64,profile:e.profile});if(s?.ok===!1)return s;if(typeof s?.fileBase64=="string"&&s?.changed===!0){const i=x(t,String(s.fileBase64)),{fileBase64:n,...a}=s;return{...a,file:t,kind:F(O(t))??void 0,savedTo:i.absolutePath,sizeKb:i.sizeKb,...this.backupReceipt(i.backupPath)}}return{ok:!0,changed:!1,file:t,message:"\u6587\u6863\u683C\u5F0F\u5DF2\u4E0E Profile \u4E00\u81F4\uFF0C\u65E0\u9700\u4FEE\u6539"}}async officeGenerateFromTemplate(e){const t=this.officeFileArg(e),r=D(t);let s=e.content;Array.isArray(s)&&s.length>0&&(s=await Promise.all(s.map(async o=>{if(typeof o=="object"&&o!==null&&o.type==="image"){const l={...o};if(typeof l.source=="string"){const m=await ve(l.source,process.env.AWS_WORKSPACE_PATH||process.cwd());l.imageBase64=m.base64,l.imageName=m.name,delete l.source}}return o})));const i={fileName:r.fileName,fileBase64:r.fileBase64};e.variables&&typeof e.variables=="object"&&(i.variables=e.variables),Array.isArray(s)&&s.length>0&&(i.content=s),e.profile&&typeof e.profile=="object"&&(i.profile=e.profile);const n=typeof e.outputFile=="string"&&e.outputFile.trim()?e.outputFile.trim():t;n!==t&&(i.outputFileName=f.basename(O(n)),i.skipCloudSync=!0);const a=await this.agentClient.callAgentScopedTool("office_generate_from_template",i);if(a?.ok===!1)return a;if(typeof a?.fileBase64=="string"){const o=x(n,String(a.fileBase64)),{fileBase64:l,...m}=a;return{...m,file:n,template:n===t?void 0:t,kind:F(O(n))??void 0,savedTo:o.absolutePath,sizeKb:o.sizeKb,...this.backupReceipt(o.backupPath)}}return{ok:!0,changed:!1,file:t,message:"\u6A21\u677F\u672A\u53D1\u73B0\u5360\u4F4D\u7B26\u6216\u5185\u5BB9\u6E05\u5355\u4E3A\u7A7A"}}async readOfficeRulesFile(e){const t=await import("node:fs"),r=await import("node:path"),s=process.env.AWS_WORKSPACE_PATH||process.cwd(),i=r.resolve(s,e);if(!t.existsSync(i)||!t.statSync(i).isFile())throw new Error(`\u89C4\u5219\u6587\u4EF6\u4E0D\u5B58\u5728: ${e}\uFF08\u89E3\u6790\u4E3A ${i}\uFF09`);const n=t.readFileSync(i,"utf8"),a=r.extname(i).toLowerCase();try{if(a===".json")return JSON.parse(n);const l=(await import("yaml")).parse(n);if(!l||typeof l!="object"||Array.isArray(l))throw new Error("\u89C4\u5219\u6587\u4EF6\u5185\u5BB9\u5FC5\u987B\u662F\u5BF9\u8C61\uFF08\u542B rules[]/page/roles\uFF09");return l}catch(o){throw new Error(`\u89C4\u5219\u6587\u4EF6\u89E3\u6790\u5931\u8D25: ${e}\uFF08${o instanceof Error?o.message:String(o)}\uFF09`)}}async officeFileForward(e,t){const r=D(this.officeFileArg(t));return await this.agentClient.callAgentScopedTool(e,{fileName:r.fileName,fileBase64:r.fileBase64})}officeOpenFiles=[];async officeOpenDocument(e){const t=this.officeFileArg(e),r=O(t);if(!C.existsSync(r))return{ok:!1,error:`\u6587\u4EF6\u4E0D\u5B58\u5728: ${t}`};const s=C.statSync(r);if(!s.isFile())return{ok:!1,error:`\u8DEF\u5F84\u4E0D\u662F\u6587\u4EF6: ${t}`};const i=F(r);if(!i)return{ok:!1,error:`\u4E0D\u652F\u6301\u7684\u6587\u4EF6\u7C7B\u578B: ${t}\uFF08\u4EC5\u652F\u6301 .docx/.docm\u3001.xlsx/.xlsm\u3001.pptx/.pptm\uFF09`};const n=Math.ceil(s.size/1024);let a;try{a=D(t)}catch(m){return{ok:!1,error:m instanceof Error?m.message:String(m)}}const o=await this.agentClient.callAgentScopedTool("office_open_document",{fileName:a.fileName,fileBase64:a.fileBase64,workspacePath:q(),sourcePath:t});if(!o||o.ok===!1)return o??{ok:!1,error:"\u4E0A\u884C\u4E3A\u4E91\u6587\u6863\u5931\u8D25\uFF08\u670D\u52A1\u7AEF\u672A\u8FD4\u56DE\u7ED3\u679C\uFF09"};const l=this.officeOpenFiles.findIndex(m=>m.file===r);return l>=0?this.officeOpenFiles[l]={file:r,kind:i,sizeKb:n}:this.officeOpenFiles.push({file:r,kind:i,sizeKb:n}),{ok:!0,docId:typeof o.docId=="string"?o.docId:void 0,file:r,kind:i,sizeKb:n,workspacePath:q(),source:typeof o.source=="string"?o.source:"local",fileUrl:typeof o.fileUrl=="string"?o.fileUrl:void 0,version:typeof o.version=="number"?o.version:void 0,message:"\u5DF2\u4E0A\u4F20\u5E76\u6253\u5F00\u4E3A\u4E91\u6587\u6863\u3002\u5982\u9700\u8986\u76D6\u672C\u5730\u6587\u4EF6\uFF0C\u8BF7\u7F16\u8F91\u597D\u540E\u5BFC\u51FA\u8986\u76D6\u3002"}}async officeCloseDocument(e){return{ok:!0,closed:!0,message:"\u5DF2\u5173\u95ED Office \u6587\u6863\u9884\u89C8\u9762\u677F"}}async officeListOpen(e){return{ok:!0,files:this.officeOpenFiles,count:this.officeOpenFiles.length}}async officeListDocuments(e){const t=await this.agentClient.callAgentScopedTool("office_list_documents",{});return t&&t.ok!==!1&&typeof t.count!="number"&&Array.isArray(t.documents)?{...t,count:t.documents.length}:t}async officeDeleteDocument(e){const t=this.officeRequiredDocId(e);return await this.agentClient.callAgentScopedTool("office_delete_document",{docId:t})}async officeShareDocument(e){const t=this.officeRequiredDocId(e);if(!Array.isArray(e.members)||e.members.length===0)throw new Error("members \u5FC5\u987B\u662F\u975E\u7A7A\u6570\u7EC4\uFF08\u6BCF\u9879 {agentId, permission?: read|write}\uFF09");const r=typeof e.name=="string"&&e.name.trim()?e.name.trim():void 0;return await this.agentClient.callAgentScopedTool("office_share_document",{docId:t,members:e.members,name:r})}async officeUnshareDocument(e){const t=this.officeRequiredDocId(e),r=Array.isArray(e.agentIds)?e.agentIds:void 0;return await this.agentClient.callAgentScopedTool("office_unshare_document",{docId:t,agentIds:r})}async officeGetChanges(e){const t=this.officeRequiredDocId(e),r=typeof e.sinceVersion=="number"?e.sinceVersion:void 0;return await this.agentClient.callAgentScopedTool("office_get_changes",{docId:t,sinceVersion:r})}officeRequiredDocId(e){const t=typeof e.docId=="string"?e.docId.trim():"";if(!t)throw new Error("docId \u4E0D\u80FD\u4E3A\u7A7A");return t}async buildOfficeCardPayload(e){const t=typeof e.filePath=="string"?e.filePath.trim():"",r=typeof e.docId=="string"?e.docId.trim():"";if(t&&r)throw new Error(`office \u5361\u7247 filePath \u4E0E docId \u53EA\u80FD\u4E8C\u9009\u4E00\uFF08filePath=${t}, docId=${r}\uFF09`);if(!t&&!r)throw(typeof e.fileUrl=="string"?e.fileUrl.trim():"")?new Error("office \u5361\u7247\u4E0D\u63A5\u53D7\u76F4\u63A5\u4F20 fileUrl\uFF0C\u8BF7\u4F20 filePath\uFF08\u5DE5\u4F5C\u533A\u6587\u4EF6\u8DEF\u5F84\uFF09\u6216 docId\uFF08\u4E91\u6587\u6863 id\uFF09\u4E4B\u4E00"):new Error("office \u5361\u7247\u5FC5\u987B\u63D0\u4F9B filePath\uFF08\u5DE5\u4F5C\u533A\u6587\u4EF6\u8DEF\u5F84\uFF09\u6216 docId\uFF08\u4E91\u6587\u6863 id\uFF09\u4E4B\u4E00");if(r){const m={type:"office",docId:r};return typeof e.title=="string"&&e.title.trim()&&(m.title=e.title.trim()),typeof e.description=="string"&&e.description.trim()&&(m.description=e.description.trim()),m}const s=D(t),i=F(s.absolutePath);if(!i)throw new Error(`office \u5361\u7247\u4EC5\u652F\u6301 docx/xlsx/pptx \u6587\u6863\uFF08\u542B .docm/.xlsm/.pptm\uFF09: ${t}`);const a=(await this.uploadAttachmentFiles([s.absolutePath]))[0],o=a.name,l={type:"office",name:o,kind:i,fileUrl:a.url,sizeKb:Math.ceil(a.size/1024),title:typeof e.title=="string"&&e.title.trim()?e.title.trim():o,filePath:t,workspacePath:q()};return typeof e.description=="string"&&e.description.trim()&&(l.description=e.description.trim()),l}async prepareCardForSend(e){if(!e)return e;let t;if(typeof e=="string")try{t=JSON.parse(e)}catch{return e}else if(typeof e=="object")t=e;else return e;return t?.type!=="office"?e:await this.buildOfficeCardPayload(t)}stripRenderImageForReporting(e){if(e&&typeof e=="object"&&!Array.isArray(e)){const t=e;let r=null;if(typeof t.image=="string"){const i=t.image.length,n=Math.ceil(i*3/4/1024);r={...t,image:`<PNG base64 \u5DF2\u7701\u7565\uFF0C\u7EA6 ${n}KB\uFF0C\u6B63\u6587\u89C1 t_pencil_doc.render_image>`}}const s=r??t;if(typeof s.snapshotJson=="string"){const i=Math.ceil(s.snapshotJson.length/1024);r={...s,snapshotJson:`<GraphSnapshot JSON \u5DF2\u7701\u7565\uFF0C\u7EA6 ${i}KB\uFF0C\u6743\u5A01\u6570\u636E\u89C1 t_pencil_doc.snapshot>`}}if(r)return r}return e}buildToolResultContent(e){if(e&&typeof e=="object"&&!Array.isArray(e)){const t=e;if(typeof t.image=="string"&&typeof t.mimeType=="string"){const r={...t};delete r.image;const s=[{type:"image",data:t.image,mimeType:t.mimeType}];return Object.keys(r).length>0&&s.push({type:"text",text:JSON.stringify(r,null,2)}),s}}return[{type:"text",text:JSON.stringify(e,null,2)}]}async handleToolCall(e,t,r){const s=t?._aws_sub_agent===!0,i=t?._aws_silent_poll===!0,n=t?._aws_force_inject===!0,a={...t};delete a._aws_sub_agent,delete a._aws_silent_poll,delete a._aws_force_inject;const o=s?null:this.agentClient.getStatusReporter();o&&!i&&this.safeReportStatus(()=>o.reportToolUse(e,this.sanitizeToolUseArgs(e,a)));try{const l=await this.executeToolCall(e,a,{forceInject:n,signal:r});if(o&&!i){const m=this.stripAutoDelegateForReporting(l);m!==null&&(this.safeReportStatus(()=>o.reportToolResult(this.stripRenderImageForReporting(m))),this.safeReportStatus(()=>o.reportThinking()))}return l}catch(l){throw o&&!i&&this.safeReportStatus(()=>o.reportToolError(l)),l}}safeReportStatus(e){try{e()}catch(t){c.warn("[McpServer] \u72B6\u6001\u4E0A\u62A5\u5931\u8D25\uFF08\u5DF2\u5FFD\u7565\uFF0C\u4E0D\u5F71\u54CD\u5DE5\u5177\u8C03\u7528\uFF09: %s",t instanceof Error?t.message:String(t))}}async executeToolCall(e,t,r={}){if(this.isSubAgent&&!Y.has(e))throw new Error(`Sub-agent is not allowed to call tool: ${e}`);const s=ye(e);if(s&&await this.resolveGroupConfigState(s)==="disabled")throw new Error(`${s.label}\u80FD\u529B\u672A\u5F00\u542F\uFF08\u8BF7\u5148\u5728\u80FD\u529B\u914D\u7F6E\u4E2D\u5F00\u542F\u300C${s.label}\u300D\u540E\u518D\u8C03\u7528 ${e}\uFF09`);switch(e){case"get_colleague":return await this.agentClient.discoverColleagues();case"get_group_rooms":return await this.agentClient.discoverGroupRooms();case"get_profile":return await this.agentClient.getProfile();case"hire_colleague":return await this.handleHireColleague(t);case"send_group":return await this.handleSendGroup(t);case"send_private":return await this.handleSendPrivate(t);case"poll_message":return await this.handlePollMessage(r.signal);case"get_message":return this.handleGetMessage(r.forceInject===!0);case"get_dm_history":return await this.handleGetDmHistory(t);case"get_group_history":return await this.handleGetGroupHistory(t);case"create_meeting":case"leave_meeting":case"end_meeting":case"meeting_speak":case"get_meeting_info":case"my_meetings":return await this.agentClient.callAgentScopedTool(e,t);case"pencil_create_document":case"pencil_list_documents":case"pencil_open_document":case"pencil_close_document":case"pencil_get_tree":case"pencil_get_changes":case"pencil_create_nodes":case"pencil_update_nodes":case"pencil_delete_nodes":case"pencil_share_document":case"pencil_revoke_share":case"pencil_delete_document":case"pencil_rename_document":return await this.agentClient.callAgentScopedTool(e,t);case"pencil_export_image":return await this.handlePencilExportImage(t);case"pencil_export_document":return await this.handlePencilExportDocument(t);case"draw_create_document":case"draw_list_documents":case"draw_open_document":case"draw_close_document":case"draw_get_diagram":case"draw_get_changes":case"draw_create_cells":case"draw_update_cells":case"draw_delete_cells":case"draw_share_document":case"draw_revoke_share":case"draw_delete_document":case"draw_rename_document":return await this.agentClient.callAgentScopedTool(e,t);case"draw_export_image":return await this.handleDrawExportImage(t);case"draw_export_document":return await this.handleDrawExportDocument(t);case"office_create":case"office_view":case"office_edit":case"office_validate":case"office_preview":case"office_format":case"office_apply_profile":case"office_generate_from_template":case"office_open_document":case"office_close_document":case"office_list_open":case"office_list_documents":case"office_delete_document":case"office_share_document":case"office_unshare_document":case"office_get_changes":return await this.handleOfficeTool(e,t);case"my_task":return await this.agentClient.getMyTasks();case"create_task_instance_comment":return await this.handleCreateTaskInstanceComment(t);case"submit_task_result":return await this.handleSubmitTaskResult(t);case"start_task_rollback":return await this.handleStartTaskRollback(t);case"finish_task_rollback":return await this.handleFinishTaskRollback(t);case"list_task_node_iterations":return await this.agentClient.listTaskNodeIterations(t);case"create_memory":return await this.handleCreateMemory(t);case"read_memory":return await this.handleReadMemory(t);case"update_memory":return await this.handleUpdateMemory(t);case"delete_memory":return await this.handleDeleteMemory(t);case"search_memory":return await this.handleSearchMemory(t);case"list_memories":return await this.handleListMemories(t);case"get_memory_stats":return await this.handleGetMemoryStats(t);case"list_memories_by_file":return await this.handleListMemoriesByFile(t);case"abandon_memory_update":return await this.handleAbandonMemoryUpdate(t);case"memory_recurrence":return await this.handleMemoryRecurrence(t);case"memory_recurrence_complete":return await this.handleMemoryRecurrenceComplete(t);case"get_debug_log_config":return await this.agentClient.getDebugLogConfig();case"query_debug_logs":return await this.agentClient.queryDebugLogs(t);case"query_file_changes_history":return await this.agentClient.queryFileChangesHistory(t);case"launch_config_list":return await this.agentClient.listLaunchConfigs();case"launch_config_create":return await this.agentClient.createLaunchConfig(t);case"launch_config_update":return await this.agentClient.updateLaunchConfig(t);case"launch_config_delete":return await this.agentClient.deleteLaunchConfig(String(t?.configId??""));case"launch_config_start":return await this.agentClient.startLaunchConfig(t);case"launch_config_restart":return await this.agentClient.restartLaunchConfig(t);case"launch_config_stop":return await this.agentClient.stopLaunchConfig(String(t?.configId??""));case"launch_config_logs":return await this.agentClient.getLaunchLogs(t);case"launch_config_status":return await this.agentClient.listLaunchRuns();case"list_ability_market":return await this.agentClient.listAbilityMarket(t);case"install_ability_market_item":return await this.agentClient.installAbilityMarketItem(t);case"uninstall_ability_market_item":return await this.agentClient.uninstallAbilityMarketItem(t);case"ability_dev_ide":return await this.agentClient.abilityDevIde(t);case"formal_ability":return await this.agentClient.formalAbility(t);case"list_my_abilities":return await this.agentClient.listMyAbilities(t);default:throw new Error(`Unknown tool: ${e}`)}}async fetchRuntimeFeaturesWithStatus(){const e=Date.now();if(this.featuresCache&&e-this.featuresCache.fetchedAt<v.FEATURES_CACHE_TTL_MS)return{features:this.featuresCache.features,ok:this.featuresCache.ok};let t={},r=!1;try{t=await this.agentClient.getRuntimeFeatures(),r=!0}catch(s){c.warn("[McpServer] \u83B7\u53D6\u80FD\u529B\u5F00\u5173\u5931\u8D25\uFF0C\u6309\u542F\u52A8\u671F env \u515C\u5E95: %s",s instanceof Error?s.message:String(s))}return this.featuresCache={features:t,ok:r,fetchedAt:e},{features:t,ok:r}}static MEMORY_TYPES=["instance_memory","instance_long_memory","project_memory","session_context"];static MEMORY_TOOL_NAMES=new Set(["create_memory","read_memory","update_memory","delete_memory","search_memory","list_memories","get_memory_stats","list_memories_by_file","abandon_memory_update","memory_recurrence","memory_recurrence_complete"]);static findAgentsworkDirSync(e){const t=f.resolve(e),r=String(process.env.AWS_PROJECT_ROOT||"").trim(),s=r?f.resolve(r):null,n=s!==null&&v.isPathWithin(t,s)?s:null;let a=null,o=t;for(;;){if(C.existsSync(f.join(o,".git"))){a=o;break}if(n!==null&&o===n)break;const m=f.dirname(o);if(m===o)break;o=m}const l=a??n??t;for(o=t;;){const m=f.join(o,".agentswork");if(C.existsSync(m))return m;if(o===l)break;const p=f.dirname(o);if(p===o)break;o=p}return f.join(l,".agentswork")}static isPathWithin(e,t){const r=f.relative(t,e);return r===""||!r.startsWith(`..${f.sep}`)&&r!==".."&&!f.isAbsolute(r)}static sanitizeRoleDirectoryName(e){return String(e||"").trim().split("").map(r=>Ie.has(r)||r.charCodeAt(0)<32?"_":r).join("").replace(/^\.+|\.+$/g,"").trim()||"default-role"}static resolveRoleMemoryDirectoryName(){return v.sanitizeRoleDirectoryName(process.env.AWS_ROLE_NAME||"")}static buildRoleMemoryStorePath(e){const t=process.env.AWS_WORKSPACE_PATH||process.cwd(),r=v.findAgentsworkDirSync(t);return f.join(r,"memory","memory",v.sanitizeRoleDirectoryName(e))}static resolveMemoryStorePaths(){const e=String(process.env.AWS_MEMORY_STORE_PATH||"").trim();if(e)return{instancePath:e,rolePath:e};const t=process.env.AWS_WORKSPACE_PATH||process.cwd(),r=v.findAgentsworkDirSync(t),s=String(process.env.AWS_INSTANCE_MEMORY_STORE_PATH||"").trim()||f.join(r,"memory","server-managed"),i=String(process.env.AWS_ROLE_MEMORY_STORE_PATH||"").trim()||f.join(r,"memory","memory",v.resolveRoleMemoryDirectoryName());return{instancePath:s,rolePath:i}}getRequiredString(e,t){const r=e[t];if(typeof r!="string"||r.trim().length===0)throw new Error(`${t} is required`);return r}getOptionalString(e,t){const r=e[t];return typeof r=="string"?r:void 0}getOptionalNumber(e,t){const r=e[t];return typeof r=="number"?r:void 0}getOptionalStringArray(e,t){const r=e[t];return Array.isArray(r)?r.map(s=>String(s)):void 0}getOptionalMemoryType(e){const t=e.memory_type;if(t!==void 0)return this.parseMemoryType(t)}parseMemoryType(e){if(typeof e!="string")throw new Error(`Invalid memory_type: ${String(e)}`);const t=e.trim();if(!this.isMemoryType(t))throw new Error(`Invalid memory_type: ${e}`);return t}isMemoryType(e){return v.MEMORY_TYPES.some(t=>t===e)}getMemoryStoreForType(e){return this.memoryStore}async readMemoryFromScopedStores(e){if(e.memory_type)return await this.memoryStore.readMemory(e);const t=await this.memoryStore.readMemory({...e,memory_type:"project_memory"}).catch(()=>null);return t||await this.memoryStore.readMemory(e)}async backupProjectMemoryToLocal(e){try{const t=await this.memoryStore.readMemory({uri:e.uri,memory_type:"project_memory"});t&&(await this.roleMemoryStore.deleteMemory({uri:e.uri,memory_type:"project_memory"}).catch(()=>{}),await this.roleMemoryStore.createMemory(t))}catch(t){c.warn("[McpServer] backupProjectMemoryToLocal \u5931\u8D25: uri=%s",e.uri,t)}}async removeProjectMemoryLocalBackup(e){try{await this.roleMemoryStore.deleteMemory({uri:e,memory_type:"project_memory"})}catch(t){c.warn("[McpServer] removeProjectMemoryLocalBackup \u5931\u8D25: uri=%s",e,t)}}async findMemoryStoreForMutation(e){return e.memory_type?{store:this.memoryStore,memory_type:e.memory_type}:await this.memoryStore.readMemory({uri:e.uri,memory_type:"project_memory"}).catch(()=>null)?{store:this.memoryStore,memory_type:"project_memory"}:{store:this.memoryStore}}async reportMemoryStatsToServer(){const e=await this.memoryStore.getStats();try{await this.agentClient.reportMemoryStats(e)}catch(t){c.warn("[McpServer] \u4E0A\u62A5 memory \u7EDF\u8BA1\u5931\u8D25:",t)}}sanitizeToolUseArgs(e,t){if(!v.MEMORY_TOOL_NAMES.has(e))return t;const r={},s=this.getOptionalString(t,"uri"),i=this.getOptionalString(t,"memory_type"),n=this.getOptionalNumber(t,"limit");return s&&(r.uri=s),i&&(r.memory_type=i),typeof n=="number"&&(r.limit=n),e==="search_memory"&&(r.queryProvided=typeof t.query=="string"&&t.query.length>0,t.keyword_mode!==void 0&&(r.keyword_mode=t.keyword_mode)),r}stripAutoDelegateForReporting(e){if(!e||typeof e!="object")return e;const t=e,r=Array.isArray(t.directMessages)?t.directMessages:[],s=Array.isArray(t.groupMessages)?t.groupMessages:[],i=o=>!!o&&typeof o=="object"&&"_acodeAutoDelegate"in o;if(!r.some(i))return e;const a=r.filter(o=>!i(o));return a.length===0&&s.length===0?null:{...t,directMessages:a}}async handleCreateMemory(e){const t=this.normalizeBoundFiles(this.getOptionalStringArray(e,"bound_files"));await this.validateBoundFilesExist(t);let r,s;if(t&&t.length>0){r={};for(const a of t){const o=await this.calculateFileMd5(a);o&&(r[a]=o)}s=new Date().toISOString()}const i={memory_type:this.parseMemoryType(this.getRequiredString(e,"memory_type")),uri:this.getRequiredString(e,"uri"),title:this.getOptionalString(e,"title"),content:this.getRequiredString(e,"content"),keywords:this.getOptionalStringArray(e,"keywords"),bound_files:t,file_md5_map:r,last_check_time:s},n=await this.memoryStore.createMemory(i);return i.memory_type==="project_memory"&&this.backupProjectMemoryToLocal(i).catch(a=>{c.warn("[McpServer] \u5907\u4EFD project_memory \u5230\u672C\u5730\u5931\u8D25:",a)}),await this.reportMemoryStatsToServer(),this.toMemoryWriteResult(n)}async handleReadMemory(e){const t={uri:this.getRequiredString(e,"uri"),memory_type:this.getOptionalMemoryType(e)};return await this.readMemoryFromScopedStores(t)}async handleUpdateMemory(e){const t=typeof e.old_string=="string"||typeof e.new_string=="string",r=typeof e.old_string=="string"&&typeof e.new_string=="string",s=this.getOptionalString(e,"append");if(t&&!r)throw new Error("old_string and new_string must be provided together");const i={uri:this.getRequiredString(e,"uri"),memory_type:this.getOptionalMemoryType(e),title:this.getOptionalString(e,"title"),old_string:this.getOptionalString(e,"old_string"),new_string:this.getOptionalString(e,"new_string"),append:s,keywords:this.getOptionalStringArray(e,"keywords"),bound_files:this.normalizeBoundFiles(this.getOptionalStringArray(e,"bound_files"))},n=await this.findMemoryStoreForMutation(i),a=await n.store.readMemory({uri:i.uri,memory_type:n.memory_type??i.memory_type});i.bound_files!==void 0?await this.validateBoundFilesExist(i.bound_files):a?.bound_files&&a.bound_files.length>0&&await this.validateBoundFilesExist(a.bound_files);const o=i.bound_files??a?.bound_files;let l,m;if(o&&o.length>0){l={};for(const u of o){const _=await this.calculateFileMd5(u);_&&(l[u]=_)}m=new Date().toISOString()}const p=await n.store.updateMemory({...i,memory_type:n.memory_type??i.memory_type,file_md5_map:l,last_check_time:m});if(n.memory_type==="project_memory"&&this.backupProjectMemoryToLocal({...i,memory_type:"project_memory",file_md5_map:l,last_check_time:m}).catch(u=>{c.warn("[McpServer] \u5907\u4EFD project_memory \u66F4\u65B0\u5230\u672C\u5730\u5931\u8D25:",u)}),await this.reportMemoryStatsToServer(),n.memory_type==="project_memory"&&a?.memory_status==="updating")try{await this.memoryStore.releaseMemoryClaim(i.uri),this.activeLeaseUris.delete(i.uri),this.activeLeaseUris.size===0&&this.stopLeaseRenewal()}catch(u){c.warn("[McpServer] \u91CA\u653E memory claim \u5931\u8D25: uri=%s, error=%s",i.uri,u instanceof Error?u.message:String(u))}return this.toMemoryWriteResult(p)}async handleDeleteMemory(e){const t=typeof e.uri=="string"?e.uri:void 0,r=Array.isArray(e.memories)?e.memories:void 0;if(t&&r&&r.length>0)throw new Error("delete_memory \u4E0D\u652F\u6301\u540C\u65F6\u4F20\u5165 uri \u548C memories\uFF0C\u8BF7\u4E8C\u9009\u4E00");if(!t&&(!r||r.length===0))throw new Error("delete_memory \u9700\u8981 uri \u6216 memories \u53C2\u6570");if(t){const a=this.getOptionalMemoryType(e);return{deleted:await this.deleteMemorySingle(t,a)}}let s=0;const i=[],n=[];for(let a=0;a<r.length;a++){const o=r[a];if(typeof o!="object"||o===null){n.push({uri:String(o),reason:`memories[${a}] \u4E0D\u662F\u5BF9\u8C61`});continue}const l=o,m=typeof l.uri=="string"?l.uri:"";if(!m){n.push({uri:"",reason:`memories[${a}].uri \u7F3A\u5931`});continue}const p=typeof l.memory_type=="string"?this.parseMemoryType(l.memory_type):void 0;try{await this.deleteMemorySingle(m,p,!0)?s++:i.push(m)}catch(u){n.push({uri:m,reason:u instanceof Error?u.message:String(u)})}}return s>0&&await this.reportMemoryStatsToServer(),{deleted:s,not_found:i,failed:n}}async deleteMemorySingle(e,t,r=!1){const s={uri:e,memory_type:t},i=await this.findMemoryStoreForMutation(s),n=i.memory_type??s.memory_type,a=await i.store.deleteMemory({...s,memory_type:n});return a&&(n==="project_memory"&&this.removeProjectMemoryLocalBackup(e).catch(o=>{c.warn("[McpServer] \u5220\u9664 project_memory \u672C\u5730\u5907\u4EFD\u5931\u8D25:",o)}),r||await this.reportMemoryStatsToServer()),a}async handleSearchMemory(e){const t=this.getOptionalString(e,"scope"),r=t==="children"||t==="all"?t:"own",s=this.getOptionalString(e,"keyword_mode"),i=s==="all"?"all":s==="any"?"any":void 0,n={query:this.getRequiredString(e,"query"),limit:this.getOptionalNumber(e,"limit"),memory_type:this.getOptionalMemoryType(e),keywords:this.getOptionalStringArray(e,"keywords"),keyword_mode:i,scope:r};if(r==="children")return await this.memoryStore.searchMemory(n);const a=await this.searchOwnMemories(n);if(r==="own")return a;const o=await this.memoryStore.searchMemory({...n,scope:"children"});return this.mergeSearchResults(a,o,n.limit)}async searchOwnMemories(e){return await this.memoryStore.searchMemory(e)}mergeSearchResults(e,t,r){const s=new Set,i=typeof r=="number"&&r>0?r:10,n=[...e.results,...t.results].filter(a=>{const o=a.uri;return s.has(o)?!1:(s.add(o),!0)}).sort((a,o)=>o.updatedAt.localeCompare(a.updatedAt)).slice(0,i);return{query:e.query||t.query,results:n}}async handleListMemories(e){const t=this.getRequiredString(e,"memory_type"),r=this.getOptionalNumber(e,"offset"),s=this.getOptionalNumber(e,"limit"),i=Math.max(0,Math.floor(r??0)),n=s!==void 0&&s>=1?Math.floor(s):ke,a=await this.memoryStore.listByType(t),o=a.length,l=a.slice(i,i+n);return{memory_type:t,total:o,offset:i,limit:n,has_more:i+n<o,memories:l}}async handleGetMemoryStats(e){const t=await this.memoryStore.getStats(),r=this.getOptionalMemoryType(e);return r?{memory_type:r,total:t.by_type[r].count,by_type:{[r]:t.by_type[r]}}:t}async handleListMemoriesByFile(e){const t=this.getRequiredString(e,"file_path"),r=this.normalizeBoundFilePath(t),s=this.getOptionalMemoryType(e),i=this.getOptionalString(e,"scope"),n=i==="own"||i==="children"?i:"all",a=async()=>await this.memoryStore.listByFile(r,{memory_type:s,scope:"children"}).catch(()=>[]);if(n==="children"){const u=await a();return{file_path:r,count:u.length,memories:u.map(_=>this.toMemoryRecordWithMetadata(_))}}if(n==="own"){const u=await this.collectOwnMemoriesByFile(r,s);return{file_path:r,count:u.length,memories:u.map(_=>this.toMemoryRecordWithMetadata(_))}}const[o,l,m]=await Promise.all([this.memoryStore.listByFile(r,{memory_type:s,scope:"all"}).catch(()=>[]),this.searchChildMemoriesByFileLocal(r,s).catch(()=>[]),this.searchPeerMemoriesByFileLocal(r,s).catch(()=>[])]),p=this.mergeIdDedupe(this.mergeIdDedupe(o,l),m);return{file_path:r,count:p.length,memories:p.map(u=>this.toMemoryRecordWithMetadata(u))}}mergeIdDedupe(e,t){const r=new Set;for(const i of e)i.id&&r.add(i.id);const s=[...e];for(const i of t)i.id&&!r.has(i.id)&&(s.push(i),r.add(i.id));return s.sort((i,n)=>n.updatedAt.localeCompare(i.updatedAt)),s}async searchChildMemoriesByFileLocal(e,t){const r=process.env.AWS_WORKSPACE_PATH||process.cwd(),s=this.normalizeBoundFilePath(e),n=(s.startsWith("./")?s.substring(2):s).split("/"),a=[],o=new Set,{access:l,readdir:m,readFile:p}=await import("node:fs/promises");for(let u=n.length-1;u>=1;u--){const _=n.slice(0,u),h="./"+n.slice(u).join("/"),M=f.join(r,..._);if(M===r)continue;const d=f.join(M,".agentswork");try{await l(d)}catch{continue}const y=f.join(d,"memory","memory");let E;try{E=(await m(y,{withFileTypes:!0})).filter(S=>S.isDirectory()).map(S=>S.name)}catch{continue}for(const g of E){const S=f.join(y,g);let P;try{P=await m(S)}catch{continue}for(const w of P){if(!w.endsWith(".json"))continue;const A=f.join(S,w);let T;try{T=await p(A,"utf-8")}catch{continue}let I;try{I=JSON.parse(T)}catch{continue}if(I.by_uri)for(const[$,N]of Object.entries(I.by_uri)){if(!N)continue;const z=N.id||$;o.has(z)||t&&N.memory_type!==t||N.bound_files&&N.bound_files.length>0&&N.bound_files.some(Q=>this.normalizeBoundFilePath(Q)===h)&&(o.add(z),a.push({...N,uri:N.uri||$}))}}}}return a.sort((u,_)=>String(_.updatedAt??"").localeCompare(String(u.updatedAt??""))),a}async searchPeerMemoriesByFileLocal(e,t){if(!this.hasRoleName||!this.initialRoleName)return[];const r=process.env.AWS_WORKSPACE_PATH||process.cwd(),s=this.normalizeBoundFilePath(e),i=f.join(r,".agentswork","memory","memory"),{access:n,readdir:a,readFile:o}=await import("node:fs/promises");try{await n(i)}catch{return[]}let l;try{l=(await a(i,{withFileTypes:!0})).filter(_=>_.isDirectory()).map(_=>_.name)}catch{return[]}const m=[],p=new Set;for(const u of l){if(u===this.initialRoleName)continue;const _=f.join(i,u);let b;try{b=await a(_)}catch{continue}for(const h of b){if(!h.endsWith(".json"))continue;let M;try{M=JSON.parse(await o(f.join(_,h),"utf-8"))}catch{continue}if(M.by_uri)for(const[d,y]of Object.entries(M.by_uri)){if(!y)continue;const E=y.id||d;p.has(E)||y.memory_type==="project_memory"&&(t&&y.memory_type!==t||y.bound_files&&y.bound_files.length>0&&y.bound_files.some(S=>this.normalizeBoundFilePath(S)===s)&&(p.add(E),m.push({...y,uri:y.uri||d,readonly:!0,source_role_name:u})))}}}return m.sort((u,_)=>String(_.updatedAt??"").localeCompare(String(u.updatedAt??""))),m}async collectOwnMemoriesByFile(e,t){return await this.memoryStore.listByFile(e,{memory_type:t})}async handleAbandonMemoryUpdate(e){const t=this.getRequiredString(e,"uri"),r=this.getOptionalMemoryType(e),s=await this.memoryStore.readMemory({uri:t,memory_type:r});return s?.bound_files&&s.bound_files.length>0&&await this.validateBoundFilesExist(s.bound_files),await this.memoryStore.releaseMemoryClaim(t),s?.memory_type==="project_memory"&&this.backupProjectMemoryToLocal({uri:t,memory_type:"project_memory"}).catch(i=>{c.info(`[McpServer] abandon_memory_update: \u540C\u6B65\u672C\u5730\u5907\u4EFD\u5931\u8D25: ${t}`,i)}),this.activeLeaseUris.delete(t),this.activeLeaseUris.size===0&&this.stopLeaseRenewal(),{success:!0,uri:t,message:"Memory \u66F4\u65B0\u72B6\u6001\u5DF2\u6E05\u9664"}}async handleMemoryRecurrence(e){const t=Math.max(1,e?.limit??10);try{((await this.memoryStore.markExpiredMemoriesRecalling()).uris?.length??0)>0&&this.startLeaseRenewal()}catch(o){c.warn("[McpServer] \u539F\u5B50\u8BA4\u9886\u8FC7\u671F\u8BB0\u5FC6\u5931\u8D25: %s",o instanceof Error?o.message:String(o))}const r=await this.memoryStore.listExpiredRecentlyMemories();if(r.length===0)return{memories:[],count:0,limit:t,remaining:0,totalExpired:0,message:"\u6CA1\u6709\u5F85\u56DE\u5FC6\u7684\u5373\u5C06\u9057\u5FD8\u8BB0\u5FC6\u3002"};const i=[...r].sort((o,l)=>{const m=new Date(o.expiresAt||o.createdAt||0).getTime(),p=new Date(l.expiresAt||l.createdAt||0).getTime();return m-p}).slice(0,t),n=Math.max(0,r.length-i.length);return{memories:i.map(o=>({uri:o.uri,title:o.title,domain:o.domain,path:o.path,memory_status:"recalling",contentPreview:typeof o.content=="string"&&o.content.length>200?o.content.substring(0,200)+"...":o.content,createdAt:o.createdAt,updatedAt:o.updatedAt})),count:i.length,limit:t,remaining:n,totalExpired:r.length,message:n>0?`\u672C\u6B21\u5904\u7406 ${i.length} \u6761\u5373\u5C06\u9057\u5FD8\u7684\u8BB0\u5FC6\uFF08\u6700\u65E9\u8FC7\u671F\u4F18\u5148\uFF09\uFF0C\u5269\u4F59 ${n} \u6761\u5F85\u5904\u7406\u3002
|
|
3
|
+
`)}`)}toMemoryWriteResult(e){return{id:e.id,uri:e.uri,domain:e.domain,path:e.path,title:e.title,memory_type:e.memory_type,createdAt:e.createdAt,updatedAt:e.updatedAt,version:e.version,keywords:e.keywords,bound_files:e.bound_files}}toMemoryRecordWithMetadata(e){return{id:e.id,uri:e.uri,domain:e.domain,path:e.path,title:e.title,content:e.content,memory_type:e.memory_type,createdAt:e.createdAt,updatedAt:e.updatedAt,version:e.version,keywords:e.keywords,bound_files:e.bound_files,file_md5_map:e.file_md5_map,memory_status:e.memory_status,updating_agent_id:e.updating_agent_id,last_check_time:e.last_check_time,path_prefix:e.path_prefix,readonly:e.readonly,source_agent_id:e.source_agent_id,source_display_name:e.source_display_name,source_role_name:e.source_role_name,source_workspace_path:e.source_workspace_path}}constructor(){this.agentClient=new oe,this.messageBuffer=new _e,this.initialRoleName=v.resolveRoleMemoryDirectoryName(),this.hasRoleName=!!process.env.AWS_ROLE_NAME;const e=v.resolveMemoryStorePaths();this.memoryStore=new Ae(this.agentClient),this.roleMemoryStore=new U(e.rolePath),this.sessionContextMemoryStore=new U(f.join(f.dirname(e.rolePath),"..","session_context")),this.isSubAgent=process.env.AWS_SUB_AGENT==="true",this.contextManager=new we(this.sessionContextMemoryStore),this.server=new re({name:me,version:de},{capabilities:{tools:{}},instructions:ge()}),this.setupHandlers()}async resolveGroupConfigState(e){if(!e.featureKey)return"expanded";const t=v.GROUP_ENV_KEYS[e.key],{features:r,ok:s}=await this.fetchRuntimeFeaturesWithStatus();if(s&&Object.keys(r).length>0){const n=v.parentGateOf(e.featureKey);return n&&J(r[n])==="disabled"?"disabled":J(r[e.featureKey])??e.defaultState}if(!t)return e.defaultState;const i=process.env[t];return i==="collapsed"?"collapsed":i==="1"||i==="expanded"?"expanded":i===void 0||i===""?e.defaultState:"disabled"}async isToolGroupEnabled(e){return await this.resolveGroupConfigState(e)!=="disabled"}static GROUP_ENV_KEYS={launch:"AWS_LAUNCH_CONFIG_TOOLS",hire:"AWS_HIRE_TOOLS",pencil:"AWS_PENCIL_TOOLS",draw:"AWS_DRAW_TOOLS",office:"AWS_OFFICE_TOOLS",task:"AWS_COLLABORATION_TASK_TOOLS",meeting:"AWS_COLLABORATION_MEETING_TOOLS",debug:"AWS_COLLABORATION_DEBUG_TOOLS",fileHistory:"AWS_COLLABORATION_FILE_HISTORY_TOOLS",abilityMarket:"AWS_ABILITY_MARKET_TOOLS",abilityDev:"AWS_ABILITY_DEV_TOOLS"};static PARENT_GATE_PREFIXES=[["agentSys","agentSys."],["collaboration","collaboration."]];static parentGateOf(e){if(e){for(const[t,r]of v.PARENT_GATE_PREFIXES)if(e.startsWith(r))return t}}async filterDisabledGroups(){let e=H;for(const t of he)await this.resolveGroupConfigState(t)==="disabled"&&(e=e.filter(s=>!t.toolNames.has(s.name)));return e}setupHandlers(){this.server.setRequestHandler(ne,async()=>this.isSubAgent?{tools:H.filter(e=>Y.has(e.name))}:{tools:await this.filterDisabledGroups()}),this.server.setRequestHandler(se,async(e,t)=>{const{name:r,arguments:s}=e.params;try{const i=await this.handleToolCall(r,s,t?.signal);return{content:this.buildToolResultContent(i)}}catch(i){const n=i instanceof Error?i.message:String(i),a=i instanceof Te?{error:n,...i.details}:i instanceof le&&(i.errorCode||i.field)?{error:n,...i.errorCode?{errorCode:i.errorCode}:{},...i.field?{field:i.field}:{}}:{error:n};return c.error("[McpServer] \u5DE5\u5177\u8C03\u7528\u5F02\u5E38: tool=%s, error=%s, stack=%s",r,n,i instanceof Error?i.stack:"(no stack)"),{content:[{type:"text",text:JSON.stringify(a,null,2)}],isError:!0}}})}async handlePencilExportImage(e){const t=typeof e.savePath=="string"?e.savePath.trim():"",r=await this.agentClient.callAgentScopedTool("pencil_export_image",e),s=typeof r?.image=="string"?r.image:"";if(!s)return r;const i=s.startsWith("data:")?s.slice(s.indexOf(",")+1):s,n={...r};delete n.image,delete n.mimeType,n.sizeKb=Math.ceil(i.length*3/4/1024);try{const{mkdir:a,writeFile:o}=await import("node:fs/promises");let l;if(t){const m=f.resolve(process.env.AWS_WORKSPACE_PATH||process.cwd());l=f.resolve(m,t)}else{const p=(typeof r?.docId=="string"?r.docId:"").replace(/[^a-zA-Z0-9_-]/g,"").slice(0,40)||"doc",u=f.join(W.tmpdir(),"pencil-export");await a(u,{recursive:!0}),l=f.join(u,`${p}-${Date.now()}-${Math.random().toString(36).slice(2,8)}.png`)}return await a(f.dirname(l),{recursive:!0}),await o(l,Buffer.from(i,"base64")),{...n,savedTo:l,temp:!t}}catch(a){return{...n,savedTo:null,saveError:a instanceof Error?a.message:String(a)}}}static PENCIL_EXPORT_FORMATS=new Set(["svg","html","png","jpg","webp","pptx","fig","jsx"]);async handlePencilExportDocument(e){const t=typeof e.format=="string"&&e.format.trim()?e.format.trim().toLowerCase():"svg";if(!v.PENCIL_EXPORT_FORMATS.has(t))throw new Error(`\u4E0D\u652F\u6301\u7684\u5BFC\u51FA\u683C\u5F0F: ${t}\uFF08\u652F\u6301 svg/html/png/jpg/webp/pptx/fig/jsx\uFF1Bpdf \u6682\u4E0D\u652F\u6301\uFF09`);const r=typeof e.nodeId=="string"&&e.nodeId.trim()?e.nodeId.trim():"";if(t==="jsx"&&!r)throw new Error("jsx \u5BFC\u51FA\u9700\u8981\u4F20 nodeId\uFF08\u6765\u81EA pencil_get_tree\uFF09\uFF0C\u5B83\u6309\u5355\u8282\u70B9\u751F\u6210 React \u7EC4\u4EF6");const s=typeof e.savePath=="string"?e.savePath.trim():"",i=f.resolve(process.env.AWS_WORKSPACE_PATH||process.cwd()),n=await this.agentClient.callAgentScopedTool("pencil_export_document",e),a=typeof n?.snapshotJson=="string"?n.snapshotJson:"";if(!a)return n;const{mkdir:o,writeFile:l,stat:m}=await import("node:fs/promises"),u=(typeof n?.docId=="string"?n.docId:"").replace(/[^a-zA-Z0-9_-]/g,"").slice(0,40)||"doc",_=`${Date.now()}-${Math.random().toString(36).slice(2,8)}`,b=f.join(W.tmpdir(),"pencil-export");await o(b,{recursive:!0});const h=f.join(b,`${u}-${_}.snapshot.json`);await l(h,a,"utf8");const M=t,d=s?f.resolve(i,s):f.join(b,`${u}-${_}.${M}`),{home:y,searched:E}=Be(i),g=[{cmd:process.execPath,entry:f.join(y,"packages","cli","dist","index.mjs"),cwd:y},{cmd:"bun",entry:f.join(y,"packages","cli","src","index.ts"),cwd:y}].filter(I=>C.existsSync(I.entry));if(g.length===0)throw new Error(`\u672A\u627E\u5230 open-pencil CLI\uFF08\u5DF2\u67E5\u627E\u76EE\u5F55\uFF1A${E.join("\uFF1B")}\uFF09\uFF0C\u8BF7\u786E\u8BA4\u5B89\u88C5\u5E03\u5C40\u6216\u8BBE\u7F6E\u73AF\u5883\u53D8\u91CF AWS_OPEN_PENCIL_HOME \u6307\u5411 open-pencil \u4ED3\u5E93\u6839\u76EE\u5F55`);const S=["export",h,"--snapshot","-f",t,"-o",d];r&&S.push("--node",r),t==="html"&&S.push("--html","standalone"),(t==="png"||t==="jpg"||t==="webp")&&(typeof e.scale=="number"&&e.scale>0&&S.push("--scale",String(e.scale)),typeof e.quality=="number"&&e.quality>0&&S.push("--quality",String(e.quality)));const P=[];let w=!1;for(const I of g)try{await this.runPencilCli(I.cmd,[I.entry,...S],I.cwd),w=!0;break}catch($){P.push(`${f.basename(I.cmd)}: ${$ instanceof Error?$.message:String($)}`)}if(!w)throw new Error(`\u753B\u5E03\u5BFC\u51FA\u5931\u8D25\uFF08format=${t}\uFF09\uFF1A${P.join("\uFF1B")||"\u672A\u77E5\u9519\u8BEF"}`);let A=null;try{A=Math.ceil((await m(d)).size/1024)}catch{A=null}const T={...n};return delete T.snapshotJson,{...T,format:t,savedTo:d,temp:!s,sizeKb:A}}runPencilCli(e,t,r){return new Promise((s,i)=>{ee(e,t,{cwd:r,timeout:18e4,maxBuffer:16*1024*1024},(n,a,o)=>{if(n){const l=String(o||a||"").trim().split(/\r?\n/).filter(Boolean).slice(-3).join(" | ");i(new Error(l||n.message));return}s(String(a||""))})})}static DRAW_EXPORT_FORMATS=new Set(["xml","drawio"]);async handleDrawExportDocument(e){const t=typeof e.format=="string"&&e.format.trim()?e.format.trim().toLowerCase():"xml";if(t==="svg"||t==="png"||t==="jpg"||t==="webp")throw new Error(`${t} \u5BFC\u51FA\u9700\u8981\u7ED8\u56FE\u6E32\u67D3\u7BA1\u7EBF\uFF08\u9636\u6BB5 2\uFF09\uFF1B\u672C\u8F6E\u8BF7\u7528 format=xml \u5BFC\u51FA draw.io <mxfile> \u539F\u6587\uFF0C\u6216\u7528\u6587\u4EF6\u8BFB\u53D6\u5DE5\u5177\u67E5\u770B XML/\u5728\u652F\u6301 draw.io \u7684\u7F16\u8F91\u5668\u4E2D\u6253\u5F00`);if(!v.DRAW_EXPORT_FORMATS.has(t))throw new Error(`\u4E0D\u652F\u6301\u7684\u5BFC\u51FA\u683C\u5F0F: ${t}\uFF08\u672C\u8F6E\u652F\u6301 xml/drawio\uFF09`);const r=typeof e.savePath=="string"?e.savePath.trim():"",s=f.resolve(process.env.AWS_WORKSPACE_PATH||process.cwd()),i=await this.agentClient.callAgentScopedTool("draw_export_document",e),n=typeof i?.docXml=="string"?i.docXml:"";if(!n)return i;const{mkdir:a,writeFile:o,stat:l}=await import("node:fs/promises"),p=(typeof i?.docId=="string"?i.docId:"").replace(/[^a-zA-Z0-9_-]/g,"").slice(0,40)||"doc",u=`${Date.now()}-${Math.random().toString(36).slice(2,8)}`,_=f.join(W.tmpdir(),"draw-export");await a(_,{recursive:!0});const b=t,h=r?f.resolve(s,r):f.join(_,`${p}-${u}.${b}`);await a(f.dirname(h),{recursive:!0}),await o(h,n,"utf8");let M=null;try{M=Math.ceil((await l(h)).size/1024)}catch{M=null}const d={...i};return delete d.docXml,{...d,format:t,savedTo:h,temp:!r,sizeKb:M}}async handleDrawExportImage(e){const t=await this.agentClient.callAgentScopedTool("draw_export_image",e),r=typeof t?.image=="string"?t.image:"";if(!r)return t;const s=r.startsWith("data:")?r.slice(r.indexOf(",")+1):r,i=typeof e.savePath=="string"?e.savePath.trim():"",n={...t};delete n.image,delete n.mimeType,n.sizeKb=Math.ceil(s.length*3/4/1024);try{const{mkdir:a,writeFile:o}=await import("node:fs/promises");let l;if(i){const m=f.resolve(process.env.AWS_WORKSPACE_PATH||process.cwd());l=f.resolve(m,i)}else{const p=(typeof t?.docId=="string"?t.docId:"").replace(/[^a-zA-Z0-9_-]/g,"").slice(0,40)||"doc",u=f.join(W.tmpdir(),"draw-export");await a(u,{recursive:!0}),l=f.join(u,`${p}-${Date.now()}-${Math.random().toString(36).slice(2,8)}.png`)}return await a(f.dirname(l),{recursive:!0}),await o(l,Buffer.from(s,"base64")),{...n,savedTo:l,temp:!i}}catch(a){return{...n,savedTo:null,saveError:a instanceof Error?a.message:String(a)}}}async handleOfficeTool(e,t){switch(e){case"office_create":return await this.officeCreate(t);case"office_view":return await this.officeView(t);case"office_edit":return await this.officeEdit(t);case"office_validate":case"office_preview":return await this.officeFileForward(e,t);case"office_format":return await this.officeFormat(t);case"office_apply_profile":return await this.officeApplyProfile(t);case"office_generate_from_template":return await this.officeGenerateFromTemplate(t);case"office_open_document":return await this.officeOpenDocument(t);case"office_close_document":return await this.officeCloseDocument(t);case"office_list_open":return await this.officeListOpen(t);case"office_list_documents":return await this.officeListDocuments(t);case"office_delete_document":return await this.officeDeleteDocument(t);case"office_share_document":return await this.officeShareDocument(t);case"office_unshare_document":return await this.officeUnshareDocument(t);case"office_get_changes":return await this.officeGetChanges(t);default:throw new Error(`\u672A\u77E5\u7684 office \u5DE5\u5177: ${e}`)}}officeFileArg(e){const t=typeof e.file=="string"?e.file.trim():"";if(!t)throw new Error("file \u4E0D\u80FD\u4E3A\u7A7A");return t}backupReceipt(e){return e?{backupPath:e,backupHint:`\u5DF2\u81EA\u52A8\u5907\u4EFD\u539F\u6587\u4EF6\u5230 ${e}\uFF08\u4FDD\u7559\u6700\u8FD1\u82E5\u5E72\u4EFD\uFF09\uFF0C\u5982\u9700\u56DE\u6EDA\u53EF\u76F4\u63A5\u590D\u5236\u8986\u76D6`}:{}}async officeCreate(e){const t=this.officeFileArg(e),r=await this.agentClient.callAgentScopedTool("office_create",{fileName:f.basename(O(t)),locale:typeof e.locale=="string"&&e.locale.trim()?e.locale.trim():void 0,template:typeof e.template=="string"&&e.template.trim()?e.template.trim():void 0});if(r?.ok===!1||typeof r?.fileBase64!="string")return r;const s=x(t,String(r.fileBase64));return{ok:!0,file:t,kind:F(O(t))??void 0,savedTo:s.absolutePath,sizeKb:s.sizeKb,docId:typeof r.docId=="string"?r.docId:void 0,source:typeof r.source=="string"?r.source:void 0,fileUrl:typeof r.fileUrl=="string"?r.fileUrl:void 0,message:typeof r.message=="string"?r.message:`\u5DF2\u521B\u5EFA\u7A7A\u767D\u6587\u6863: ${t}`,hint:"\u6587\u6863\u5DF2\u540C\u6B65\u5230\u4E91\u6587\u6863\uFF08\u53EF\u5728 Dashboard \u9762\u677F\u67E5\u770B\u4E0E\u534F\u4F5C\uFF09\u3002\u7528 office_view \u4E86\u89E3\u7ED3\u6784\u540E\u5373\u53EF office_edit \u5199\u5165\u5185\u5BB9"}}async officeView(e){const t=D(this.officeFileArg(e)),r={fileName:t.fileName,fileBase64:t.fileBase64,mode:typeof e.mode=="string"&&e.mode.trim()?e.mode.trim():"text",start:typeof e.start=="number"?e.start:void 0,maxLines:typeof e.maxLines=="number"?e.maxLines:void 0,limit:typeof e.limit=="number"?e.limit:void 0,query:typeof e.query=="string"&&e.query.trim()?e.query.trim():void 0};return Array.isArray(e.paths)&&e.paths.length>0&&(r.paths=e.paths),await this.agentClient.callAgentScopedTool("office_view",r)}async officeEdit(e){const t=this.officeFileArg(e);if(!Array.isArray(e.commands)||e.commands.length===0)throw new Error("commands \u5FC5\u987B\u662F\u975E\u7A7A\u6570\u7EC4");await Me(e.commands,process.env.AWS_WORKSPACE_PATH||process.cwd()),be(e.commands);const r=D(t),s=typeof e.docId=="string"&&e.docId.trim()?e.docId.trim():void 0,i=await this.agentClient.callAgentScopedTool("office_edit",{fileName:r.fileName,fileBase64:r.fileBase64,commands:e.commands,bestEffort:e.bestEffort===!0,docId:s});if(i?.ok===!1)return i;const n={};typeof i?.docId=="string"&&(n.docId=i.docId),typeof i?.version=="number"&&(n.version=i.version),typeof i?.fileUrl=="string"&&(n.fileUrl=i.fileUrl);const a=Array.isArray(i?.warnings)&&i.warnings.length>0?{warnings:i.warnings}:{};if(typeof i?.fileBase64=="string"){const o=x(t,String(i.fileBase64));return{ok:!0,file:t,kind:F(O(t))??void 0,results:Array.isArray(i.results)?i.results:[],changed:!0,savedTo:o.absolutePath,sizeKb:o.sizeKb,...this.backupReceipt(o.backupPath),...a,...n}}return{ok:!0,results:Array.isArray(i?.results)?i.results:[],changed:!1,...a,...n}}async officeFormat(e){const t=this.officeFileArg(e),r=typeof e.action=="string"?e.action.trim():"",s=r==="dryRun"||r==="dryrun";if(!["check","fix","dryRun"].includes(r))throw new Error('action \u5FC5\u987B\u662F "check"\u3001"fix" \u6216 "dryRun"');const i={action:r,annotate:e.annotate===!0};if(typeof e.preset=="string"&&e.preset.trim()&&(i.preset=e.preset.trim()),e.rules&&typeof e.rules=="object"&&(i.rules=e.rules),typeof e.rulesFile=="string"&&e.rulesFile.trim()&&(i.rules=await this.readOfficeRulesFile(e.rulesFile.trim())),e.mergePreset===!0&&(i.mergePreset=!0),Array.isArray(e.exclude)&&e.exclude.length>0&&(i.exclude=e.exclude),!i.preset&&!i.rules)throw new Error("\u9700\u8981 preset\u3001rulesFile \u6216 rules \u4E4B\u4E00\u63D0\u4F9B\u683C\u5F0F\u89C4\u5219");const o=(typeof e.outputFile=="string"&&e.outputFile.trim()?e.outputFile.trim():"")||(i.annotate===!0&&r==="check"?this.deriveSiblingFileName(t,"-\u6807\u6CE8\u7248"):t),l=D(t),m=await this.agentClient.callAgentScopedTool("office_format",{fileName:l.fileName,fileBase64:l.fileBase64,...i});if(m?.ok===!1)return m;if(typeof m?.fileBase64=="string"&&!s&&(r==="fix"||i.annotate===!0)){const p=o!==t,u=p?Se(t,f.basename(o),String(m.fileBase64)):x(t,String(m.fileBase64)),{fileBase64:_,...b}=m;return{...b,file:t,...p?{outputFile:o,originalPreserved:!0}:{},kind:F(O(o))??void 0,savedTo:u.absolutePath,sizeKb:u.sizeKb,...this.backupReceipt(u.backupPath)}}if(typeof m?.fileBase64=="string"){const{fileBase64:p,...u}=m;return u}return m}deriveSiblingFileName(e,t){const r=O(e),s=f.extname(r),n=`${f.basename(r,s)}${t}${s}`;return f.isAbsolute(e)?f.join(f.dirname(r),n):n}async officeApplyProfile(e){const t=this.officeFileArg(e);if(typeof e.profile!="object"||e.profile===null)throw new Error("profile \u5FC5\u987B\u662F\u975E\u7A7A\u5BF9\u8C61");const r=D(t),s=await this.agentClient.callAgentScopedTool("office_apply_profile",{fileName:r.fileName,fileBase64:r.fileBase64,profile:e.profile});if(s?.ok===!1)return s;if(typeof s?.fileBase64=="string"&&s?.changed===!0){const i=x(t,String(s.fileBase64)),{fileBase64:n,...a}=s;return{...a,file:t,kind:F(O(t))??void 0,savedTo:i.absolutePath,sizeKb:i.sizeKb,...this.backupReceipt(i.backupPath)}}return{ok:!0,changed:!1,file:t,message:"\u6587\u6863\u683C\u5F0F\u5DF2\u4E0E Profile \u4E00\u81F4\uFF0C\u65E0\u9700\u4FEE\u6539"}}async officeGenerateFromTemplate(e){const t=this.officeFileArg(e),r=D(t);let s=e.content;Array.isArray(s)&&s.length>0&&(s=await Promise.all(s.map(async o=>{if(typeof o=="object"&&o!==null&&o.type==="image"){const l={...o};if(typeof l.source=="string"){const m=await ve(l.source,process.env.AWS_WORKSPACE_PATH||process.cwd());l.imageBase64=m.base64,l.imageName=m.name,delete l.source}}return o})));const i={fileName:r.fileName,fileBase64:r.fileBase64};e.variables&&typeof e.variables=="object"&&(i.variables=e.variables),Array.isArray(s)&&s.length>0&&(i.content=s),e.profile&&typeof e.profile=="object"&&(i.profile=e.profile);const n=typeof e.outputFile=="string"&&e.outputFile.trim()?e.outputFile.trim():t;n!==t&&(i.outputFileName=f.basename(O(n)),i.skipCloudSync=!0);const a=await this.agentClient.callAgentScopedTool("office_generate_from_template",i);if(a?.ok===!1)return a;if(typeof a?.fileBase64=="string"){const o=x(n,String(a.fileBase64)),{fileBase64:l,...m}=a;return{...m,file:n,template:n===t?void 0:t,kind:F(O(n))??void 0,savedTo:o.absolutePath,sizeKb:o.sizeKb,...this.backupReceipt(o.backupPath)}}return{ok:!0,changed:!1,file:t,message:"\u6A21\u677F\u672A\u53D1\u73B0\u5360\u4F4D\u7B26\u6216\u5185\u5BB9\u6E05\u5355\u4E3A\u7A7A"}}async readOfficeRulesFile(e){const t=await import("node:fs"),r=await import("node:path"),s=process.env.AWS_WORKSPACE_PATH||process.cwd(),i=r.resolve(s,e);if(!t.existsSync(i)||!t.statSync(i).isFile())throw new Error(`\u89C4\u5219\u6587\u4EF6\u4E0D\u5B58\u5728: ${e}\uFF08\u89E3\u6790\u4E3A ${i}\uFF09`);const n=t.readFileSync(i,"utf8"),a=r.extname(i).toLowerCase();try{if(a===".json")return JSON.parse(n);const l=(await import("yaml")).parse(n);if(!l||typeof l!="object"||Array.isArray(l))throw new Error("\u89C4\u5219\u6587\u4EF6\u5185\u5BB9\u5FC5\u987B\u662F\u5BF9\u8C61\uFF08\u542B rules[]/page/roles\uFF09");return l}catch(o){throw new Error(`\u89C4\u5219\u6587\u4EF6\u89E3\u6790\u5931\u8D25: ${e}\uFF08${o instanceof Error?o.message:String(o)}\uFF09`)}}async officeFileForward(e,t){const r=D(this.officeFileArg(t));return await this.agentClient.callAgentScopedTool(e,{fileName:r.fileName,fileBase64:r.fileBase64})}officeOpenFiles=[];async officeOpenDocument(e){const t=this.officeFileArg(e),r=O(t);if(!C.existsSync(r))return{ok:!1,error:`\u6587\u4EF6\u4E0D\u5B58\u5728: ${t}`};const s=C.statSync(r);if(!s.isFile())return{ok:!1,error:`\u8DEF\u5F84\u4E0D\u662F\u6587\u4EF6: ${t}`};const i=F(r);if(!i)return{ok:!1,error:`\u4E0D\u652F\u6301\u7684\u6587\u4EF6\u7C7B\u578B: ${t}\uFF08\u4EC5\u652F\u6301 .docx/.docm\u3001.xlsx/.xlsm\u3001.pptx/.pptm\uFF09`};const n=Math.ceil(s.size/1024);let a;try{a=D(t)}catch(m){return{ok:!1,error:m instanceof Error?m.message:String(m)}}const o=await this.agentClient.callAgentScopedTool("office_open_document",{fileName:a.fileName,fileBase64:a.fileBase64,workspacePath:q(),sourcePath:t});if(!o||o.ok===!1)return o??{ok:!1,error:"\u4E0A\u884C\u4E3A\u4E91\u6587\u6863\u5931\u8D25\uFF08\u670D\u52A1\u7AEF\u672A\u8FD4\u56DE\u7ED3\u679C\uFF09"};const l=this.officeOpenFiles.findIndex(m=>m.file===r);return l>=0?this.officeOpenFiles[l]={file:r,kind:i,sizeKb:n}:this.officeOpenFiles.push({file:r,kind:i,sizeKb:n}),{ok:!0,docId:typeof o.docId=="string"?o.docId:void 0,file:r,kind:i,sizeKb:n,workspacePath:q(),source:typeof o.source=="string"?o.source:"local",fileUrl:typeof o.fileUrl=="string"?o.fileUrl:void 0,version:typeof o.version=="number"?o.version:void 0,message:"\u5DF2\u4E0A\u4F20\u5E76\u6253\u5F00\u4E3A\u4E91\u6587\u6863\u3002\u5982\u9700\u8986\u76D6\u672C\u5730\u6587\u4EF6\uFF0C\u8BF7\u7F16\u8F91\u597D\u540E\u5BFC\u51FA\u8986\u76D6\u3002"}}async officeCloseDocument(e){return{ok:!0,closed:!0,message:"\u5DF2\u5173\u95ED Office \u6587\u6863\u9884\u89C8\u9762\u677F"}}async officeListOpen(e){return{ok:!0,files:this.officeOpenFiles,count:this.officeOpenFiles.length}}async officeListDocuments(e){const t=await this.agentClient.callAgentScopedTool("office_list_documents",{});return t&&t.ok!==!1&&typeof t.count!="number"&&Array.isArray(t.documents)?{...t,count:t.documents.length}:t}async officeDeleteDocument(e){const t=this.officeRequiredDocId(e);return await this.agentClient.callAgentScopedTool("office_delete_document",{docId:t})}async officeShareDocument(e){const t=this.officeRequiredDocId(e);if(!Array.isArray(e.members)||e.members.length===0)throw new Error("members \u5FC5\u987B\u662F\u975E\u7A7A\u6570\u7EC4\uFF08\u6BCF\u9879 {agentId, permission?: read|write}\uFF09");const r=typeof e.name=="string"&&e.name.trim()?e.name.trim():void 0;return await this.agentClient.callAgentScopedTool("office_share_document",{docId:t,members:e.members,name:r})}async officeUnshareDocument(e){const t=this.officeRequiredDocId(e),r=Array.isArray(e.agentIds)?e.agentIds:void 0;return await this.agentClient.callAgentScopedTool("office_unshare_document",{docId:t,agentIds:r})}async officeGetChanges(e){const t=this.officeRequiredDocId(e),r=typeof e.sinceVersion=="number"?e.sinceVersion:void 0;return await this.agentClient.callAgentScopedTool("office_get_changes",{docId:t,sinceVersion:r})}officeRequiredDocId(e){const t=typeof e.docId=="string"?e.docId.trim():"";if(!t)throw new Error("docId \u4E0D\u80FD\u4E3A\u7A7A");return t}async buildOfficeCardPayload(e){const t=typeof e.filePath=="string"?e.filePath.trim():"",r=typeof e.docId=="string"?e.docId.trim():"";if(t&&r)throw new Error(`office \u5361\u7247 filePath \u4E0E docId \u53EA\u80FD\u4E8C\u9009\u4E00\uFF08filePath=${t}, docId=${r}\uFF09`);if(!t&&!r)throw(typeof e.fileUrl=="string"?e.fileUrl.trim():"")?new Error("office \u5361\u7247\u4E0D\u63A5\u53D7\u76F4\u63A5\u4F20 fileUrl\uFF0C\u8BF7\u4F20 filePath\uFF08\u5DE5\u4F5C\u533A\u6587\u4EF6\u8DEF\u5F84\uFF09\u6216 docId\uFF08\u4E91\u6587\u6863 id\uFF09\u4E4B\u4E00"):new Error("office \u5361\u7247\u5FC5\u987B\u63D0\u4F9B filePath\uFF08\u5DE5\u4F5C\u533A\u6587\u4EF6\u8DEF\u5F84\uFF09\u6216 docId\uFF08\u4E91\u6587\u6863 id\uFF09\u4E4B\u4E00");if(r){const m={type:"office",docId:r};return typeof e.title=="string"&&e.title.trim()&&(m.title=e.title.trim()),typeof e.description=="string"&&e.description.trim()&&(m.description=e.description.trim()),m}const s=D(t),i=F(s.absolutePath);if(!i)throw new Error(`office \u5361\u7247\u4EC5\u652F\u6301 docx/xlsx/pptx \u6587\u6863\uFF08\u542B .docm/.xlsm/.pptm\uFF09: ${t}`);const a=(await this.uploadAttachmentFiles([s.absolutePath]))[0],o=a.name,l={type:"office",name:o,kind:i,fileUrl:a.url,sizeKb:Math.ceil(a.size/1024),title:typeof e.title=="string"&&e.title.trim()?e.title.trim():o,filePath:t,workspacePath:q()};return typeof e.description=="string"&&e.description.trim()&&(l.description=e.description.trim()),l}async prepareCardForSend(e){if(!e)return e;let t;if(typeof e=="string")try{t=JSON.parse(e)}catch{return e}else if(typeof e=="object")t=e;else return e;return t?.type!=="office"?e:await this.buildOfficeCardPayload(t)}stripRenderImageForReporting(e){if(e&&typeof e=="object"&&!Array.isArray(e)){const t=e;let r=null;if(typeof t.image=="string"){const i=t.image.length,n=Math.ceil(i*3/4/1024);r={...t,image:`<PNG base64 \u5DF2\u7701\u7565\uFF0C\u7EA6 ${n}KB\uFF0C\u6B63\u6587\u89C1 t_pencil_doc.render_image>`}}const s=r??t;if(typeof s.snapshotJson=="string"){const i=Math.ceil(s.snapshotJson.length/1024);r={...s,snapshotJson:`<GraphSnapshot JSON \u5DF2\u7701\u7565\uFF0C\u7EA6 ${i}KB\uFF0C\u6743\u5A01\u6570\u636E\u89C1 t_pencil_doc.snapshot>`}}if(r)return r}return e}buildToolResultContent(e){if(e&&typeof e=="object"&&!Array.isArray(e)){const t=e;if(typeof t.image=="string"&&typeof t.mimeType=="string"){const r={...t};delete r.image;const s=[{type:"image",data:t.image,mimeType:t.mimeType}];return Object.keys(r).length>0&&s.push({type:"text",text:JSON.stringify(r,null,2)}),s}}return[{type:"text",text:JSON.stringify(e,null,2)}]}async handleToolCall(e,t,r){const s=t?._aws_sub_agent===!0,i=t?._aws_silent_poll===!0,n=t?._aws_force_inject===!0,a={...t};delete a._aws_sub_agent,delete a._aws_silent_poll,delete a._aws_force_inject;const o=s?null:this.agentClient.getStatusReporter();o&&!i&&this.safeReportStatus(()=>o.reportToolUse(e,this.sanitizeToolUseArgs(e,a)));try{const l=await this.executeToolCall(e,a,{forceInject:n,signal:r});if(o&&!i){const m=this.stripAutoDelegateForReporting(l);m!==null&&(this.safeReportStatus(()=>o.reportToolResult(this.stripRenderImageForReporting(m))),this.safeReportStatus(()=>o.reportThinking()))}return l}catch(l){throw o&&!i&&this.safeReportStatus(()=>o.reportToolError(l)),l}}safeReportStatus(e){try{e()}catch(t){c.warn("[McpServer] \u72B6\u6001\u4E0A\u62A5\u5931\u8D25\uFF08\u5DF2\u5FFD\u7565\uFF0C\u4E0D\u5F71\u54CD\u5DE5\u5177\u8C03\u7528\uFF09: %s",t instanceof Error?t.message:String(t))}}async executeToolCall(e,t,r={}){if(this.isSubAgent&&!Y.has(e))throw new Error(`Sub-agent is not allowed to call tool: ${e}`);const s=ye(e);if(s&&await this.resolveGroupConfigState(s)==="disabled")throw new Error(`${s.label}\u80FD\u529B\u672A\u5F00\u542F\uFF08\u8BF7\u5148\u5728\u80FD\u529B\u914D\u7F6E\u4E2D\u5F00\u542F\u300C${s.label}\u300D\u540E\u518D\u8C03\u7528 ${e}\uFF09`);switch(e){case"get_colleague":return await this.agentClient.discoverColleagues();case"get_group_rooms":return await this.agentClient.discoverGroupRooms();case"get_profile":return await this.agentClient.getProfile();case"hire_colleague":return await this.handleHireColleague(t);case"send_group":return await this.handleSendGroup(t);case"send_private":return await this.handleSendPrivate(t);case"poll_message":return await this.handlePollMessage(r.signal);case"get_message":return this.handleGetMessage(r.forceInject===!0);case"get_dm_history":return await this.handleGetDmHistory(t);case"get_group_history":return await this.handleGetGroupHistory(t);case"create_meeting":case"leave_meeting":case"end_meeting":case"meeting_speak":case"get_meeting_info":case"my_meetings":return await this.agentClient.callAgentScopedTool(e,t);case"pencil_create_document":case"pencil_list_documents":case"pencil_open_document":case"pencil_close_document":case"pencil_get_tree":case"pencil_get_changes":case"pencil_create_nodes":case"pencil_update_nodes":case"pencil_delete_nodes":case"pencil_share_document":case"pencil_revoke_share":case"pencil_delete_document":case"pencil_rename_document":return await this.agentClient.callAgentScopedTool(e,t);case"pencil_export_image":return await this.handlePencilExportImage(t);case"pencil_export_document":return await this.handlePencilExportDocument(t);case"draw_create_document":case"draw_list_documents":case"draw_open_document":case"draw_close_document":case"draw_get_diagram":case"draw_get_changes":case"draw_create_cells":case"draw_update_cells":case"draw_delete_cells":case"draw_share_document":case"draw_revoke_share":case"draw_delete_document":case"draw_rename_document":return await this.agentClient.callAgentScopedTool(e,t);case"draw_export_image":return await this.handleDrawExportImage(t);case"draw_export_document":return await this.handleDrawExportDocument(t);case"office_create":case"office_view":case"office_edit":case"office_validate":case"office_preview":case"office_format":case"office_apply_profile":case"office_generate_from_template":case"office_open_document":case"office_close_document":case"office_list_open":case"office_list_documents":case"office_delete_document":case"office_share_document":case"office_unshare_document":case"office_get_changes":return await this.handleOfficeTool(e,t);case"my_task":return await this.agentClient.getMyTasks();case"create_task_instance_comment":return await this.handleCreateTaskInstanceComment(t);case"submit_task_result":return await this.handleSubmitTaskResult(t);case"start_task_rollback":return await this.handleStartTaskRollback(t);case"finish_task_rollback":return await this.handleFinishTaskRollback(t);case"list_task_node_iterations":return await this.agentClient.listTaskNodeIterations(t);case"create_memory":return await this.handleCreateMemory(t);case"read_memory":return await this.handleReadMemory(t);case"update_memory":return await this.handleUpdateMemory(t);case"delete_memory":return await this.handleDeleteMemory(t);case"search_memory":return await this.handleSearchMemory(t);case"list_memories":return await this.handleListMemories(t);case"get_memory_stats":return await this.handleGetMemoryStats(t);case"list_memories_by_file":return await this.handleListMemoriesByFile(t);case"abandon_memory_update":return await this.handleAbandonMemoryUpdate(t);case"memory_recurrence":return await this.handleMemoryRecurrence(t);case"memory_recurrence_complete":return await this.handleMemoryRecurrenceComplete(t);case"get_debug_log_config":return await this.agentClient.getDebugLogConfig();case"query_debug_logs":return await this.agentClient.queryDebugLogs(t);case"query_file_changes_history":return await this.agentClient.queryFileChangesHistory(t);case"list_colleague_events":return await this.agentClient.listColleagueEvents(t);case"launch_config_list":return await this.agentClient.listLaunchConfigs();case"launch_config_create":return await this.agentClient.createLaunchConfig(t);case"launch_config_update":return await this.agentClient.updateLaunchConfig(t);case"launch_config_delete":return await this.agentClient.deleteLaunchConfig(String(t?.configId??""));case"launch_config_start":return await this.agentClient.startLaunchConfig(t);case"launch_config_restart":return await this.agentClient.restartLaunchConfig(t);case"launch_config_stop":return await this.agentClient.stopLaunchConfig(String(t?.configId??""));case"launch_config_logs":return await this.agentClient.getLaunchLogs(t);case"launch_config_status":return await this.agentClient.listLaunchRuns();case"list_ability_market":return await this.agentClient.listAbilityMarket(t);case"install_ability_market_item":return await this.agentClient.installAbilityMarketItem(t);case"uninstall_ability_market_item":return await this.agentClient.uninstallAbilityMarketItem(t);case"ability_dev_ide":return await this.agentClient.abilityDevIde(t);case"formal_ability":return await this.agentClient.formalAbility(t);case"list_my_abilities":return await this.agentClient.listMyAbilities(t);default:throw new Error(`Unknown tool: ${e}`)}}async fetchRuntimeFeaturesWithStatus(){const e=Date.now();if(this.featuresCache&&e-this.featuresCache.fetchedAt<v.FEATURES_CACHE_TTL_MS)return{features:this.featuresCache.features,ok:this.featuresCache.ok};let t={},r=!1;try{t=await this.agentClient.getRuntimeFeatures(),r=!0}catch(s){c.warn("[McpServer] \u83B7\u53D6\u80FD\u529B\u5F00\u5173\u5931\u8D25\uFF0C\u6309\u542F\u52A8\u671F env \u515C\u5E95: %s",s instanceof Error?s.message:String(s))}return this.featuresCache={features:t,ok:r,fetchedAt:e},{features:t,ok:r}}static MEMORY_TYPES=["instance_memory","instance_long_memory","project_memory","session_context"];static MEMORY_TOOL_NAMES=new Set(["create_memory","read_memory","update_memory","delete_memory","search_memory","list_memories","get_memory_stats","list_memories_by_file","abandon_memory_update","memory_recurrence","memory_recurrence_complete"]);static findAgentsworkDirSync(e){const t=f.resolve(e),r=String(process.env.AWS_PROJECT_ROOT||"").trim(),s=r?f.resolve(r):null,n=s!==null&&v.isPathWithin(t,s)?s:null;let a=null,o=t;for(;;){if(C.existsSync(f.join(o,".git"))){a=o;break}if(n!==null&&o===n)break;const m=f.dirname(o);if(m===o)break;o=m}const l=a??n??t;for(o=t;;){const m=f.join(o,".agentswork");if(C.existsSync(m))return m;if(o===l)break;const p=f.dirname(o);if(p===o)break;o=p}return f.join(l,".agentswork")}static isPathWithin(e,t){const r=f.relative(t,e);return r===""||!r.startsWith(`..${f.sep}`)&&r!==".."&&!f.isAbsolute(r)}static sanitizeRoleDirectoryName(e){return String(e||"").trim().split("").map(r=>Ie.has(r)||r.charCodeAt(0)<32?"_":r).join("").replace(/^\.+|\.+$/g,"").trim()||"default-role"}static resolveRoleMemoryDirectoryName(){return v.sanitizeRoleDirectoryName(process.env.AWS_ROLE_NAME||"")}static buildRoleMemoryStorePath(e){const t=process.env.AWS_WORKSPACE_PATH||process.cwd(),r=v.findAgentsworkDirSync(t);return f.join(r,"memory","memory",v.sanitizeRoleDirectoryName(e))}static resolveMemoryStorePaths(){const e=String(process.env.AWS_MEMORY_STORE_PATH||"").trim();if(e)return{instancePath:e,rolePath:e};const t=process.env.AWS_WORKSPACE_PATH||process.cwd(),r=v.findAgentsworkDirSync(t),s=String(process.env.AWS_INSTANCE_MEMORY_STORE_PATH||"").trim()||f.join(r,"memory","server-managed"),i=String(process.env.AWS_ROLE_MEMORY_STORE_PATH||"").trim()||f.join(r,"memory","memory",v.resolveRoleMemoryDirectoryName());return{instancePath:s,rolePath:i}}getRequiredString(e,t){const r=e[t];if(typeof r!="string"||r.trim().length===0)throw new Error(`${t} is required`);return r}getOptionalString(e,t){const r=e[t];return typeof r=="string"?r:void 0}getOptionalNumber(e,t){const r=e[t];return typeof r=="number"?r:void 0}getOptionalStringArray(e,t){const r=e[t];return Array.isArray(r)?r.map(s=>String(s)):void 0}getOptionalMemoryType(e){const t=e.memory_type;if(t!==void 0)return this.parseMemoryType(t)}parseMemoryType(e){if(typeof e!="string")throw new Error(`Invalid memory_type: ${String(e)}`);const t=e.trim();if(!this.isMemoryType(t))throw new Error(`Invalid memory_type: ${e}`);return t}isMemoryType(e){return v.MEMORY_TYPES.some(t=>t===e)}getMemoryStoreForType(e){return this.memoryStore}async readMemoryFromScopedStores(e){if(e.memory_type)return await this.memoryStore.readMemory(e);const t=await this.memoryStore.readMemory({...e,memory_type:"project_memory"}).catch(()=>null);return t||await this.memoryStore.readMemory(e)}async backupProjectMemoryToLocal(e){try{const t=await this.memoryStore.readMemory({uri:e.uri,memory_type:"project_memory"});t&&(await this.roleMemoryStore.deleteMemory({uri:e.uri,memory_type:"project_memory"}).catch(()=>{}),await this.roleMemoryStore.createMemory(t))}catch(t){c.warn("[McpServer] backupProjectMemoryToLocal \u5931\u8D25: uri=%s",e.uri,t)}}async removeProjectMemoryLocalBackup(e){try{await this.roleMemoryStore.deleteMemory({uri:e,memory_type:"project_memory"})}catch(t){c.warn("[McpServer] removeProjectMemoryLocalBackup \u5931\u8D25: uri=%s",e,t)}}async findMemoryStoreForMutation(e){return e.memory_type?{store:this.memoryStore,memory_type:e.memory_type}:await this.memoryStore.readMemory({uri:e.uri,memory_type:"project_memory"}).catch(()=>null)?{store:this.memoryStore,memory_type:"project_memory"}:{store:this.memoryStore}}async reportMemoryStatsToServer(){const e=await this.memoryStore.getStats();try{await this.agentClient.reportMemoryStats(e)}catch(t){c.warn("[McpServer] \u4E0A\u62A5 memory \u7EDF\u8BA1\u5931\u8D25:",t)}}sanitizeToolUseArgs(e,t){if(!v.MEMORY_TOOL_NAMES.has(e))return t;const r={},s=this.getOptionalString(t,"uri"),i=this.getOptionalString(t,"memory_type"),n=this.getOptionalNumber(t,"limit");return s&&(r.uri=s),i&&(r.memory_type=i),typeof n=="number"&&(r.limit=n),e==="search_memory"&&(r.queryProvided=typeof t.query=="string"&&t.query.length>0,t.keyword_mode!==void 0&&(r.keyword_mode=t.keyword_mode)),r}stripAutoDelegateForReporting(e){if(!e||typeof e!="object")return e;const t=e,r=Array.isArray(t.directMessages)?t.directMessages:[],s=Array.isArray(t.groupMessages)?t.groupMessages:[],i=o=>!!o&&typeof o=="object"&&"_acodeAutoDelegate"in o;if(!r.some(i))return e;const a=r.filter(o=>!i(o));return a.length===0&&s.length===0?null:{...t,directMessages:a}}async handleCreateMemory(e){const t=this.normalizeBoundFiles(this.getOptionalStringArray(e,"bound_files"));await this.validateBoundFilesExist(t);let r,s;if(t&&t.length>0){r={};for(const a of t){const o=await this.calculateFileMd5(a);o&&(r[a]=o)}s=new Date().toISOString()}const i={memory_type:this.parseMemoryType(this.getRequiredString(e,"memory_type")),uri:this.getRequiredString(e,"uri"),title:this.getOptionalString(e,"title"),content:this.getRequiredString(e,"content"),keywords:this.getOptionalStringArray(e,"keywords"),bound_files:t,file_md5_map:r,last_check_time:s},n=await this.memoryStore.createMemory(i);return i.memory_type==="project_memory"&&this.backupProjectMemoryToLocal(i).catch(a=>{c.warn("[McpServer] \u5907\u4EFD project_memory \u5230\u672C\u5730\u5931\u8D25:",a)}),await this.reportMemoryStatsToServer(),this.toMemoryWriteResult(n)}async handleReadMemory(e){const t={uri:this.getRequiredString(e,"uri"),memory_type:this.getOptionalMemoryType(e)};return await this.readMemoryFromScopedStores(t)}async handleUpdateMemory(e){const t=typeof e.old_string=="string"||typeof e.new_string=="string",r=typeof e.old_string=="string"&&typeof e.new_string=="string",s=this.getOptionalString(e,"append");if(t&&!r)throw new Error("old_string and new_string must be provided together");const i={uri:this.getRequiredString(e,"uri"),memory_type:this.getOptionalMemoryType(e),title:this.getOptionalString(e,"title"),old_string:this.getOptionalString(e,"old_string"),new_string:this.getOptionalString(e,"new_string"),append:s,keywords:this.getOptionalStringArray(e,"keywords"),bound_files:this.normalizeBoundFiles(this.getOptionalStringArray(e,"bound_files"))},n=await this.findMemoryStoreForMutation(i),a=await n.store.readMemory({uri:i.uri,memory_type:n.memory_type??i.memory_type});i.bound_files!==void 0?await this.validateBoundFilesExist(i.bound_files):a?.bound_files&&a.bound_files.length>0&&await this.validateBoundFilesExist(a.bound_files);const o=i.bound_files??a?.bound_files;let l,m;if(o&&o.length>0){l={};for(const u of o){const _=await this.calculateFileMd5(u);_&&(l[u]=_)}m=new Date().toISOString()}const p=await n.store.updateMemory({...i,memory_type:n.memory_type??i.memory_type,file_md5_map:l,last_check_time:m});if(n.memory_type==="project_memory"&&this.backupProjectMemoryToLocal({...i,memory_type:"project_memory",file_md5_map:l,last_check_time:m}).catch(u=>{c.warn("[McpServer] \u5907\u4EFD project_memory \u66F4\u65B0\u5230\u672C\u5730\u5931\u8D25:",u)}),await this.reportMemoryStatsToServer(),n.memory_type==="project_memory"&&a?.memory_status==="updating")try{await this.memoryStore.releaseMemoryClaim(i.uri),this.activeLeaseUris.delete(i.uri),this.activeLeaseUris.size===0&&this.stopLeaseRenewal()}catch(u){c.warn("[McpServer] \u91CA\u653E memory claim \u5931\u8D25: uri=%s, error=%s",i.uri,u instanceof Error?u.message:String(u))}return this.toMemoryWriteResult(p)}async handleDeleteMemory(e){const t=typeof e.uri=="string"?e.uri:void 0,r=Array.isArray(e.memories)?e.memories:void 0;if(t&&r&&r.length>0)throw new Error("delete_memory \u4E0D\u652F\u6301\u540C\u65F6\u4F20\u5165 uri \u548C memories\uFF0C\u8BF7\u4E8C\u9009\u4E00");if(!t&&(!r||r.length===0))throw new Error("delete_memory \u9700\u8981 uri \u6216 memories \u53C2\u6570");if(t){const a=this.getOptionalMemoryType(e);return{deleted:await this.deleteMemorySingle(t,a)}}let s=0;const i=[],n=[];for(let a=0;a<r.length;a++){const o=r[a];if(typeof o!="object"||o===null){n.push({uri:String(o),reason:`memories[${a}] \u4E0D\u662F\u5BF9\u8C61`});continue}const l=o,m=typeof l.uri=="string"?l.uri:"";if(!m){n.push({uri:"",reason:`memories[${a}].uri \u7F3A\u5931`});continue}const p=typeof l.memory_type=="string"?this.parseMemoryType(l.memory_type):void 0;try{await this.deleteMemorySingle(m,p,!0)?s++:i.push(m)}catch(u){n.push({uri:m,reason:u instanceof Error?u.message:String(u)})}}return s>0&&await this.reportMemoryStatsToServer(),{deleted:s,not_found:i,failed:n}}async deleteMemorySingle(e,t,r=!1){const s={uri:e,memory_type:t},i=await this.findMemoryStoreForMutation(s),n=i.memory_type??s.memory_type,a=await i.store.deleteMemory({...s,memory_type:n});return a&&(n==="project_memory"&&this.removeProjectMemoryLocalBackup(e).catch(o=>{c.warn("[McpServer] \u5220\u9664 project_memory \u672C\u5730\u5907\u4EFD\u5931\u8D25:",o)}),r||await this.reportMemoryStatsToServer()),a}async handleSearchMemory(e){const t=this.getOptionalString(e,"scope"),r=t==="children"||t==="all"?t:"own",s=this.getOptionalString(e,"keyword_mode"),i=s==="all"?"all":s==="any"?"any":void 0,n={query:this.getRequiredString(e,"query"),limit:this.getOptionalNumber(e,"limit"),memory_type:this.getOptionalMemoryType(e),keywords:this.getOptionalStringArray(e,"keywords"),keyword_mode:i,scope:r};if(r==="children")return await this.memoryStore.searchMemory(n);const a=await this.searchOwnMemories(n);if(r==="own")return a;const o=await this.memoryStore.searchMemory({...n,scope:"children"});return this.mergeSearchResults(a,o,n.limit)}async searchOwnMemories(e){return await this.memoryStore.searchMemory(e)}mergeSearchResults(e,t,r){const s=new Set,i=typeof r=="number"&&r>0?r:10,n=[...e.results,...t.results].filter(a=>{const o=a.uri;return s.has(o)?!1:(s.add(o),!0)}).sort((a,o)=>o.updatedAt.localeCompare(a.updatedAt)).slice(0,i);return{query:e.query||t.query,results:n}}async handleListMemories(e){const t=this.getRequiredString(e,"memory_type"),r=this.getOptionalNumber(e,"offset"),s=this.getOptionalNumber(e,"limit"),i=Math.max(0,Math.floor(r??0)),n=s!==void 0&&s>=1?Math.floor(s):ke,a=await this.memoryStore.listByType(t),o=a.length,l=a.slice(i,i+n);return{memory_type:t,total:o,offset:i,limit:n,has_more:i+n<o,memories:l}}async handleGetMemoryStats(e){const t=await this.memoryStore.getStats(),r=this.getOptionalMemoryType(e);return r?{memory_type:r,total:t.by_type[r].count,by_type:{[r]:t.by_type[r]}}:t}async handleListMemoriesByFile(e){const t=this.getRequiredString(e,"file_path"),r=this.normalizeBoundFilePath(t),s=this.getOptionalMemoryType(e),i=this.getOptionalString(e,"scope"),n=i==="own"||i==="children"?i:"all",a=async()=>await this.memoryStore.listByFile(r,{memory_type:s,scope:"children"}).catch(()=>[]);if(n==="children"){const u=await a();return{file_path:r,count:u.length,memories:u.map(_=>this.toMemoryRecordWithMetadata(_))}}if(n==="own"){const u=await this.collectOwnMemoriesByFile(r,s);return{file_path:r,count:u.length,memories:u.map(_=>this.toMemoryRecordWithMetadata(_))}}const[o,l,m]=await Promise.all([this.memoryStore.listByFile(r,{memory_type:s,scope:"all"}).catch(()=>[]),this.searchChildMemoriesByFileLocal(r,s).catch(()=>[]),this.searchPeerMemoriesByFileLocal(r,s).catch(()=>[])]),p=this.mergeIdDedupe(this.mergeIdDedupe(o,l),m);return{file_path:r,count:p.length,memories:p.map(u=>this.toMemoryRecordWithMetadata(u))}}mergeIdDedupe(e,t){const r=new Set;for(const i of e)i.id&&r.add(i.id);const s=[...e];for(const i of t)i.id&&!r.has(i.id)&&(s.push(i),r.add(i.id));return s.sort((i,n)=>n.updatedAt.localeCompare(i.updatedAt)),s}async searchChildMemoriesByFileLocal(e,t){const r=process.env.AWS_WORKSPACE_PATH||process.cwd(),s=this.normalizeBoundFilePath(e),n=(s.startsWith("./")?s.substring(2):s).split("/"),a=[],o=new Set,{access:l,readdir:m,readFile:p}=await import("node:fs/promises");for(let u=n.length-1;u>=1;u--){const _=n.slice(0,u),h="./"+n.slice(u).join("/"),M=f.join(r,..._);if(M===r)continue;const d=f.join(M,".agentswork");try{await l(d)}catch{continue}const y=f.join(d,"memory","memory");let E;try{E=(await m(y,{withFileTypes:!0})).filter(S=>S.isDirectory()).map(S=>S.name)}catch{continue}for(const g of E){const S=f.join(y,g);let P;try{P=await m(S)}catch{continue}for(const w of P){if(!w.endsWith(".json"))continue;const A=f.join(S,w);let T;try{T=await p(A,"utf-8")}catch{continue}let I;try{I=JSON.parse(T)}catch{continue}if(I.by_uri)for(const[$,N]of Object.entries(I.by_uri)){if(!N)continue;const z=N.id||$;o.has(z)||t&&N.memory_type!==t||N.bound_files&&N.bound_files.length>0&&N.bound_files.some(Q=>this.normalizeBoundFilePath(Q)===h)&&(o.add(z),a.push({...N,uri:N.uri||$}))}}}}return a.sort((u,_)=>String(_.updatedAt??"").localeCompare(String(u.updatedAt??""))),a}async searchPeerMemoriesByFileLocal(e,t){if(!this.hasRoleName||!this.initialRoleName)return[];const r=process.env.AWS_WORKSPACE_PATH||process.cwd(),s=this.normalizeBoundFilePath(e),i=f.join(r,".agentswork","memory","memory"),{access:n,readdir:a,readFile:o}=await import("node:fs/promises");try{await n(i)}catch{return[]}let l;try{l=(await a(i,{withFileTypes:!0})).filter(_=>_.isDirectory()).map(_=>_.name)}catch{return[]}const m=[],p=new Set;for(const u of l){if(u===this.initialRoleName)continue;const _=f.join(i,u);let b;try{b=await a(_)}catch{continue}for(const h of b){if(!h.endsWith(".json"))continue;let M;try{M=JSON.parse(await o(f.join(_,h),"utf-8"))}catch{continue}if(M.by_uri)for(const[d,y]of Object.entries(M.by_uri)){if(!y)continue;const E=y.id||d;p.has(E)||y.memory_type==="project_memory"&&(t&&y.memory_type!==t||y.bound_files&&y.bound_files.length>0&&y.bound_files.some(S=>this.normalizeBoundFilePath(S)===s)&&(p.add(E),m.push({...y,uri:y.uri||d,readonly:!0,source_role_name:u})))}}}return m.sort((u,_)=>String(_.updatedAt??"").localeCompare(String(u.updatedAt??""))),m}async collectOwnMemoriesByFile(e,t){return await this.memoryStore.listByFile(e,{memory_type:t})}async handleAbandonMemoryUpdate(e){const t=this.getRequiredString(e,"uri"),r=this.getOptionalMemoryType(e),s=await this.memoryStore.readMemory({uri:t,memory_type:r});return s?.bound_files&&s.bound_files.length>0&&await this.validateBoundFilesExist(s.bound_files),await this.memoryStore.releaseMemoryClaim(t),s?.memory_type==="project_memory"&&this.backupProjectMemoryToLocal({uri:t,memory_type:"project_memory"}).catch(i=>{c.info(`[McpServer] abandon_memory_update: \u540C\u6B65\u672C\u5730\u5907\u4EFD\u5931\u8D25: ${t}`,i)}),this.activeLeaseUris.delete(t),this.activeLeaseUris.size===0&&this.stopLeaseRenewal(),{success:!0,uri:t,message:"Memory \u66F4\u65B0\u72B6\u6001\u5DF2\u6E05\u9664"}}async handleMemoryRecurrence(e){const t=Math.max(1,e?.limit??10);try{((await this.memoryStore.markExpiredMemoriesRecalling()).uris?.length??0)>0&&this.startLeaseRenewal()}catch(o){c.warn("[McpServer] \u539F\u5B50\u8BA4\u9886\u8FC7\u671F\u8BB0\u5FC6\u5931\u8D25: %s",o instanceof Error?o.message:String(o))}const r=await this.memoryStore.listExpiredRecentlyMemories();if(r.length===0)return{memories:[],count:0,limit:t,remaining:0,totalExpired:0,message:"\u6CA1\u6709\u5F85\u56DE\u5FC6\u7684\u5373\u5C06\u9057\u5FD8\u8BB0\u5FC6\u3002"};const i=[...r].sort((o,l)=>{const m=new Date(o.expiresAt||o.createdAt||0).getTime(),p=new Date(l.expiresAt||l.createdAt||0).getTime();return m-p}).slice(0,t),n=Math.max(0,r.length-i.length);return{memories:i.map(o=>({uri:o.uri,title:o.title,domain:o.domain,path:o.path,memory_status:"recalling",contentPreview:typeof o.content=="string"&&o.content.length>200?o.content.substring(0,200)+"...":o.content,createdAt:o.createdAt,updatedAt:o.updatedAt})),count:i.length,limit:t,remaining:n,totalExpired:r.length,message:n>0?`\u672C\u6B21\u5904\u7406 ${i.length} \u6761\u5373\u5C06\u9057\u5FD8\u7684\u8BB0\u5FC6\uFF08\u6700\u65E9\u8FC7\u671F\u4F18\u5148\uFF09\uFF0C\u5269\u4F59 ${n} \u6761\u5F85\u5904\u7406\u3002
|
|
4
4
|
\u8BF7\u5BA1\u67E5\u540E\u51B3\u5B9A\uFF08update_memory \u7EED\u671F\uFF0CTTL \xD72 / \u4E0D\u5904\u7406\uFF09\uFF0C
|
|
5
5
|
\u672C\u6279\u5BA1\u67E5\u5B8C\u6BD5\u540E\u8C03\u7528 memory_recurrence_complete(uris=[\u672C\u6279\u786E\u5B9A\u5220\u9664\u7684URI]) \u6E05\u7406\uFF0C\u518D\u8C03 memory_recurrence \u5904\u7406\u4E0B\u4E00\u6279\u3002`:`\u5DF2\u5904\u7406\u5168\u90E8 ${i.length} \u6761\u5373\u5C06\u9057\u5FD8\u7684\u8BB0\u5FC6\u3002
|
|
6
6
|
\u8BF7\u5BA1\u67E5\u540E\u51B3\u5B9A\uFF08update_memory \u7EED\u671F\uFF0CTTL \xD72 / \u4E0D\u5904\u7406\uFF09\uFF0C
|
|
@@ -11,6 +11,10 @@ export declare const LIST_PROJECT_MEMBERS_TOOL: Tool;
|
|
|
11
11
|
|
|
12
12
|
export declare const GET_PROFILE_TOOL: Tool;
|
|
13
13
|
|
|
14
|
+
export declare const LIST_COLLEAGUE_EVENTS_TOOL: Tool;
|
|
15
|
+
|
|
16
|
+
export declare const AGENT_OBSERVE_TOOL_NAMES: ReadonlySet<string>;
|
|
17
|
+
|
|
14
18
|
export declare const HIRE_COLLEAGUE_TOOL: Tool;
|
|
15
19
|
|
|
16
20
|
export declare const SEND_GROUP_TOOL: Tool;
|