aws-runtime-bridge 1.9.182 → 1.9.184
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 +82 -0
- package/dist/adapter/AcodeSdkAdapter.d.ts +30 -1
- package/dist/adapter/AcodeSdkAdapter.js +3 -3
- package/dist/adapter/ClaudeSdkAdapter.d.ts +3 -1
- package/dist/adapter/ClaudeSdkAdapter.js +3 -3
- package/dist/adapter/CodexSdkAdapter.d.ts +3 -1
- package/dist/adapter/CodexSdkAdapter.js +2 -2
- package/dist/adapter/OpencodeSdkAdapter.d.ts +3 -1
- package/dist/adapter/OpencodeSdkAdapter.js +3 -3
- package/dist/adapter/types.d.ts +7 -1
- package/dist/index.js +1 -1
- package/dist/routes/terminal.d.ts +13 -0
- package/dist/routes/terminal.js +28 -28
- package/dist/services/agent-ownership.d.ts +16 -0
- package/dist/services/agent-ownership.js +2 -2
- package/dist/services/plugin-deployment.d.ts +14 -0
- package/dist/services/plugin-deployment.js +2 -2
- package/dist/services/plugin-manager.d.ts +3 -0
- package/dist/services/plugin-manager.js +4 -4
- package/dist/services/plugin-runtime.d.ts +10 -2
- package/dist/services/user-scope.d.ts +1 -0
- package/dist/services/user-scope.js +1 -1
- package/package/acode/dist/background-command-manager.d.ts +22 -0
- package/package/acode/dist/background-command-manager.js +5 -5
- package/package/acode/dist/built-in-file-tools.js +2 -2
- package/package/acode/dist/hibernation-journal.d.ts +67 -0
- package/package/acode/dist/hibernation-journal.js +2 -0
- package/package/acode/dist/index.d.ts +1 -0
- package/package/acode/dist/index.js +1 -1
- package/package/acode/dist/runtime-environment.d.ts +4 -1
- package/package/acode/dist/runtime-environment.js +3 -3
- package/package/aws-client-agent-mcp/dist/agent-client.d.ts +7 -0
- package/package/aws-client-agent-mcp/dist/agent-client.js +1 -1
- package/package/aws-client-agent-mcp/dist/mcp-server.d.ts +2 -0
- package/package/aws-client-agent-mcp/dist/mcp-server.js +4 -4
- package/package/aws-client-agent-mcp/dist/mcp-tools.d.ts +8 -0
- package/package/aws-client-agent-mcp/dist/mcp-tools.js +20 -20
- package/package/aws-client-agent-mcp/dist/types.d.ts +5 -0
- package/package.json +1 -1
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
export declare const HIBERNATION_JOURNAL_VERSION = 1;
|
|
19
|
+
|
|
20
|
+
export type HibernationJournalReason = "periodic" | "clean";
|
|
21
|
+
export interface HibernationJournal {
|
|
22
|
+
version: number;
|
|
23
|
+
agentId: string;
|
|
24
|
+
|
|
25
|
+
sessionId: string;
|
|
26
|
+
|
|
27
|
+
savedAt: string;
|
|
28
|
+
reason: HibernationJournalReason;
|
|
29
|
+
messageCount: number;
|
|
30
|
+
|
|
31
|
+
transcript: unknown[];
|
|
32
|
+
|
|
33
|
+
tokenUsage?: {
|
|
34
|
+
inputTokens?: number | null;
|
|
35
|
+
outputTokens?: number | null;
|
|
36
|
+
totalInputTokens?: number | null;
|
|
37
|
+
totalOutputTokens?: number | null;
|
|
38
|
+
cacheHitTokens?: number | null;
|
|
39
|
+
cacheMissTokens?: number | null;
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
export declare function writeJournal(agentId: string, payload: {
|
|
46
|
+
sessionId: string;
|
|
47
|
+
reason: HibernationJournalReason;
|
|
48
|
+
transcript: unknown[];
|
|
49
|
+
tokenUsage?: HibernationJournal["tokenUsage"];
|
|
50
|
+
}): Promise<void>;
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
export declare function readJournal(agentId: string): Promise<HibernationJournal | null>;
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
export declare function deleteJournal(agentId: string): Promise<void>;
|
|
60
|
+
|
|
61
|
+
export declare const HIBERNATION_JOURNAL_TTL_MS: number;
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
export declare function sweepExpiredJournals(maxAgeMs?: number): Promise<number>;
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{promises as o}from"node:fs";import f from"node:path";import{renameWithRetry as A}from"./fs-utils.js";import{resolveAcodeHome as y}from"./paths.js";const m=1,p=4e3,d=16*1024*1024;function v(t){return String(t).replace(/[^a-zA-Z0-9_-]/g,"_")}function u(){return f.join(y(),"hibernation")}function g(t){return f.join(u(),`${v(t)}.json`)}function N(t){if(t.length<=p){let n=0;for(const e of t)if(n+=JSON.stringify(e??null).length,n>d)return S(t,I(t,n));return t}return t.slice(t.length-p)}function S(t,n){return n>=t.length?t.slice(-1):t.slice(n)}function I(t,n){const e=n-d,r=Math.max(1,Math.floor(n/t.length));return Math.min(t.length-1,Math.ceil(e/r*1.2))}const l=new Map;async function j(t,n){const e=g(t),r=N(n.transcript??[]),s={version:m,agentId:t,sessionId:n.sessionId,savedAt:new Date().toISOString(),reason:n.reason,messageCount:r.length,transcript:r,...n.tokenUsage?{tokenUsage:n.tokenUsage}:{}},c=(l.get(t)??Promise.resolve()).then(async()=>{await o.mkdir(u(),{recursive:!0});const a=`${e}.tmp`;await o.writeFile(a,JSON.stringify(s),"utf-8"),await A(a,e)});l.set(t,c.catch(()=>{})),await c}async function M(t){const n=g(t);let e;try{e=await o.readFile(n,"utf-8")}catch(i){return i?.code==="ENOENT",null}let r;try{r=JSON.parse(e)}catch{return await w(n,e),null}const s=x(r,t);return s||(await w(n,e),null)}function x(t,n){if(typeof t!="object"||t===null)return null;const e=t;return e.version!==m||typeof e.agentId!="string"||!e.agentId||typeof e.savedAt!="string"||!e.savedAt||!Array.isArray(e.transcript)||e.transcript.length===0?null:{version:m,agentId:e.agentId,sessionId:typeof e.sessionId=="string"?e.sessionId:"",savedAt:e.savedAt,reason:e.reason==="clean"?"clean":"periodic",messageCount:typeof e.messageCount=="number"?e.messageCount:e.transcript.length,transcript:e.transcript,tokenUsage:typeof e.tokenUsage=="object"&&e.tokenUsage!==null?e.tokenUsage:void 0}}async function w(t,n){try{await o.writeFile(`${t}.corrupt-${Date.now()}`,n,"utf-8")}catch{}}async function k(t){const e=(l.get(t)??Promise.resolve()).catch(()=>{}).then(async()=>{await o.rm(g(t),{force:!0})});l.set(t,e.catch(()=>{})),await e}const T=7*24*60*60*1e3;async function E(t=T){let n=0,e;try{e=await o.readdir(u())}catch{return 0}const r=Date.now();for(const s of e){if(!s.endsWith(".json"))continue;const i=f.join(u(),s);try{const c=await o.readFile(i,"utf-8");let a=0;try{const h=JSON.parse(c);typeof h.savedAt=="string"&&(a=Date.parse(h.savedAt))}catch{}(!Number.isFinite(a)||r-a>t)&&(await o.rm(i,{force:!0}),n+=1)}catch{}}return n}export{T as HIBERNATION_JOURNAL_TTL_MS,m as HIBERNATION_JOURNAL_VERSION,k as deleteJournal,M as readJournal,E as sweepExpiredJournals,j as writeJournal};
|
|
2
|
+
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export*from"./commands/commandRegistry.js";export*from"./commands/commandLoader.js";export*from"./commands/commandParser.js";export*from"./config.js";export*from"./hooks/hookBus.js";export*from"./runtime.js";export*from"./runtime-environment.js";export*from"./types.js";export*from"./sub-agent-types.js";export*from"./sub-agent-store.js";export*from"./sub-agent-manager.js";export*from"./sub-agent-tools.js";export*from"./built-in-file-tools.js";export*from"./read-file-state.js";export*from"./tool-concurrency/index.js";export*from"./terminal-types.js";export*from"./plugin-types.js";export*from"./tool-group-manager.js";export*from"./parsers/types.js";export*from"./parsers/tree-sitter-loader.js";export*from"./parsers/ast-cache.js";export*from"./parsers/language-detector.js";export*from"./parsers/language-queries.js";export*from"./parsers/symbol-extractor.js";export*from"./parsers/file-index.js";export*from"./built-in-symbols-tool.js";
|
|
1
|
+
export*from"./commands/commandRegistry.js";export*from"./commands/commandLoader.js";export*from"./commands/commandParser.js";export*from"./config.js";export*from"./hooks/hookBus.js";export*from"./runtime.js";export*from"./runtime-environment.js";export*from"./types.js";export*from"./sub-agent-types.js";export*from"./sub-agent-store.js";export*from"./sub-agent-manager.js";export*from"./sub-agent-tools.js";export*from"./built-in-file-tools.js";export*from"./read-file-state.js";export*from"./tool-concurrency/index.js";export*from"./terminal-types.js";export*from"./plugin-types.js";export*from"./tool-group-manager.js";export*from"./parsers/types.js";export*from"./parsers/tree-sitter-loader.js";export*from"./parsers/ast-cache.js";export*from"./parsers/language-detector.js";export*from"./parsers/language-queries.js";export*from"./parsers/symbol-extractor.js";export*from"./parsers/file-index.js";export*from"./built-in-symbols-tool.js";export*from"./hibernation-journal.js";
|
|
2
2
|
|
|
@@ -18,4 +18,7 @@ export declare function buildRuntimeEnvironmentPrompt(platform?: NodeJS.Platform
|
|
|
18
18
|
|
|
19
19
|
|
|
20
20
|
|
|
21
|
-
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
export declare function buildResumeContextBlock(snapshot: string, wakeNotice?: string): string;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import r from"node:os";import l from"node:path";import{shellExecutable as a}from"./builtins/shellCommandPreparation.js";function c(e=process.platform,
|
|
2
|
-
`)}function h(e){const n=e.trim();return
|
|
3
|
-
`)
|
|
1
|
+
import r from"node:os";import l from"node:path";import{shellExecutable as a}from"./builtins/shellCommandPreparation.js";function c(e=process.platform,t=r.release(),n=a()){const i=e==="win32"?"Windows":e==="darwin"?"macOS":e==="linux"?"Linux":e,o=l.basename(n.command).toLowerCase(),s=e==="win32"?`Shell: ${o} (Windows) \u2014 commands run in a Windows shell, not a POSIX shell; Unix-only commands (rm, grep, sed, ...) may be unavailable, prefer Windows equivalents (rd, findstr, ...) or the built-in file tools.`:`Shell: ${o} \u2014 commands run in a POSIX shell.`;return["[Runtime Environment]",`Platform: ${i} (${e}, release ${t})`,s,"Images: if an image is already at an http(s) URL (including signed URLs with query strings), call read_file with that URL directly \u2014 it is fetched in memory and never written to disk. Do NOT download it with Bash/curl/wget first."].join(`
|
|
2
|
+
`)}function h(e,t){const n=e.trim();if(!n)return"";const i=t?.trim();return["[Resume Context]","\u4EE5\u4E0B\u5185\u5BB9\u53D6\u81EA\u4F60\u4E0A\u4E00\u6B21\u8FD0\u884C\u5230\u8BE5\u5B9E\u4F8B\u4F11\u7720\u4E3A\u6B62\u7684\u8FDB\u5EA6\u5FEB\u7167\uFF08\u7531\u7CFB\u7EDF\u5728\u4F11\u7720\u65F6\u81EA\u52A8\u4FDD\u5B58\uFF09\u3002","\u5B83\u4E0D\u662F\u65B0\u7684\u7528\u6237\u6D88\u606F\uFF0C\u4E5F\u4E0D\u662F\u65B0\u7684\u4EFB\u52A1\u6307\u4EE4\uFF0C\u800C\u662F\u4F60\u81EA\u5DF1\u7684\u8BB0\u5FC6\u63A5\u7EED\u70B9\u3002","","\u63A5\u7EED\u89C4\u5219\uFF1A","1. \u4E0A\u8FF0\u5FEB\u7167\u91CC\u5DF2\u7ECF\u5B8C\u6210\u7684\u5DE5\u4F5C\u4E0D\u8981\u91CD\u505A\uFF0C\u5DF2\u786E\u8BA4\u7684\u7ED3\u8BBA\u76F4\u63A5\u6CBF\u7528\u3002","2. \u5FEB\u7167\u4E2D\u6807\u6CE8\u4E3A\u5F85\u5904\u7406/\u8FDB\u884C\u4E2D\u7684\u4E8B\u9879\uFF0C\u662F\u4F60\u8981\u7EE7\u7EED\u63A8\u8FDB\u7684\u76EE\u6807\u3002","3. \u82E5\u5FEB\u7167\u4FE1\u606F\u4E0D\u8DB3\u4EE5\u5224\u65AD\u4E0B\u4E00\u6B65\uFF0C\u5148\u8BFB\u53D6\u76F8\u5173\u6587\u4EF6\u6216\u8C03\u7528 poll_message \u83B7\u53D6\u6700\u65B0\u6D88\u606F\uFF0C\u518D\u884C\u52A8\u3002","","--- \u8FDB\u5EA6\u5FEB\u7167\u5F00\u59CB ---",n,"--- \u8FDB\u5EA6\u5FEB\u7167\u7ED3\u675F ---",...i?["",i]:[]].join(`
|
|
3
|
+
`)}export{h as buildResumeContextBlock,c as buildRuntimeEnvironmentPrompt};
|
|
4
4
|
|
|
@@ -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,a){this.ensureRegistered();const c=t||this.projectId||this.agentConfig.projectId;return await this.httpClient.callTool("send_group_message",{agentId:this.agentId,projectId:c,roomId:n,content:e,card:r,replyTo:s,...a?{voice:a}:{}})}async sendDirectMessage(e,t,n=!1,r,s,a,c,g,o){this.ensureRegistered();const l={agentId:this.agentId,targetId:e,content:t,requireReply:n,waitReply:n,replyToCallId:r,card:a,replyTo:c};if(typeof s=="number"&&s>0&&(l.timeoutMs=s),g?.priority&&g.priority!=="normal"&&(l.priority=g.priority,l.force=g.priority==="force",g.intent&&(l.intent=g.intent),g.ref&&(l.ref=g.ref),g.reason&&(l.reason=g.reason)),o&&(l.voice=o),n){const d=typeof s=="number"&&s>0?s+3e4:0;return await this.httpClient.callToolOnce("send_dm",l,d)}return await this.httpClient.callTool("send_dm",l)}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 markForceInjected(e){if(e.length===0)return new Set;this.ensureRegistered();try{const t=await this.httpClient.callTool("mark_force_injected",{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_force_injected \u786E\u8BA4\u540E\u5C06\u6709 %d \u6761\u5F3A\u5236\u6D88\u606F\u88AB\u4E22\u5F03\u4E0D\u4EA4\u4ED8: \u8BF7\u6C42=%s, \u53EF\u4EA4\u4ED8=%s",r.length,JSON.stringify(e),JSON.stringify([...n])):i.info("[AgentClient] mark_force_injected \u786E\u8BA4\u5B8C\u6210: %d \u6761\u5F3A\u5236\u6D88\u606F\u5DF2\u6CE8\u5165",e.length),n}catch(t){throw i.warn("[AgentClient] mark_force_injected \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 fetchCurrentAction(){const e=this.serverConfig.runtimeBridgeBaseUrl,t=this.agentId;if(!e||!t)return null;try{const n=`${e}/runtime/sessions/${encodeURIComponent(t)}/current-action`,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] \u67E5\u8BE2 bridge \u5F53\u524D\u52A8\u4F5C\u5931\u8D25: HTTP %s, url=%s",s.status,n),null;const a=await s.json();return a?.ok?a:null}catch(n){return i.warn("[AgentClient] \u67E5\u8BE2 bridge \u5F53\u524D\u52A8\u4F5C\u5F02\u5E38: %s",n instanceof Error?n.message:String(n)),null}}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};
|
|
1
|
+
import{configManager as c}from"./config.js";import{MESSAGE_POLL_INTERVAL_MS as I}from"./constants.js";import{HttpClient as f}from"./http-client.js";import{logger as i,setMcpNodeLogSink as w,updateStartupLogIdentity as u}from"./logger.js";import{claimRuntimeLaunchBindingDetailed as m}from"./runtime-launch-binding.js";import{StatusReporter as A}from"./status-reporter.js";import{WebSocketClient as p}from"./websocket-client.js";class T extends Error{constructor(e){super(e),this.name="PollLongPollTimeoutError"}}const C=27e4;class N{wsClient;httpClient;agentConfig;serverConfig;agentId=null;displayName=null;projectId=null;isRunning=!1;isDegradedMode=!1;messageHandler=null;profileHandler=null;configHandler=null;systemNotifyHandler=null;pollTimer=null;statusReporter=null;newCharacterHandler=null;runtimeTokenRefreshTimer=null;pendingLaunchBindingClaim=!1;cachedProfile=null;constructor(){c.loadConfig(),this.agentConfig=c.getAgentConfig(),this.serverConfig=c.getServerConfig(),this.wsClient=new p(this.serverConfig),this.httpClient=new f(this.serverConfig),this.setupWebSocketListeners()}async initialize(){const e=await m(this.agentConfig,this.serverConfig);if(e.status==="claimed"){this.applyLaunchBinding(e.binding);return}if(e.status==="unreachable"){this.pendingLaunchBindingClaim=!0,i.warn("[AgentClient] runtime-bridge \u672A\u5C31\u7EEA\uFF0C\u542F\u52A8\u7ED1\u5B9A\u8BA4\u9886\u5DF2\u6302\u8D77\uFF0C\u5C06\u5728\u6CE8\u518C\u91CD\u8BD5\u4E2D\u91CD\u65B0\u8BA4\u9886: %s",e.message);return}this.serverConfig.runtimeBridgeBaseUrl=void 0}applyLaunchBinding(e){c.applyRuntimeLaunchBinding(e),this.agentConfig=c.getAgentConfig(),this.serverConfig=c.getServerConfig(),this.wsClient=new p(this.serverConfig),this.httpClient=new f(this.serverConfig),this.setupWebSocketListeners()}async retryPendingLaunchBindingClaim(){if(!this.pendingLaunchBindingClaim)return!0;const e=await m(this.agentConfig,this.serverConfig);if(e.status==="claimed")return this.pendingLaunchBindingClaim=!1,i.info("[AgentClient] \u542F\u52A8\u7ED1\u5B9A\u8865\u8BA4\u9886\u6210\u529F\uFF0C\u7EE7\u7EED\u6CE8\u518C\u6D41\u7A0B"),this.applyLaunchBinding(e.binding),!0;if(e.status==="missing")return this.pendingLaunchBindingClaim=!1,this.serverConfig.runtimeBridgeBaseUrl=void 0,i.warn("[AgentClient] \u542F\u52A8\u7ED1\u5B9A\u8865\u8BA4\u9886\u672A\u627E\u5230\u5F85\u8BA4\u9886\u8BB0\u5F55\uFF0C\u6309\u65E0\u7ED1\u5B9A\u6A21\u5F0F\u7EE7\u7EED\u6CE8\u518C"),!1;const t=e.status==="unreachable"?e.message:e.reason;return i.warn("[AgentClient] \u542F\u52A8\u7ED1\u5B9A\u8865\u8BA4\u9886\u5931\u8D25\uFF0C\u4FDD\u7559\u6302\u8D77\u72B6\u6001\u7B49\u5F85\u4E0B\u6B21\u6CE8\u518C\u91CD\u8BD5: %s",t),!1}setupWebSocketListeners(){this.wsClient.on("directMessage",e=>{this.handleIncomingDm(e)}),this.wsClient.on("groupMessage",e=>{this.handleIncomingGroup(e)}),this.wsClient.on("meetingMessage",e=>{this.handleIncomingMeeting(e)}),this.wsClient.on("systemNotify",e=>{this.systemNotifyHandler?.(e)}),this.wsClient.on("profileInfo",e=>{i.info(`[AgentClient] WebSocket profileInfo \u4E8B\u4EF6\u89E6\u53D1\uFF0CdisplayName: ${e.displayName}`),this.handleProfileInfo(e)}),this.wsClient.on("agentConfig",e=>{i.info("[AgentClient] WebSocket agentConfig \u4E8B\u4EF6\u89E6\u53D1"),this.configHandler&&this.configHandler(e??{})}),this.wsClient.on("agentStatus",e=>{i.info(`[AgentClient] WebSocket agentStatus \u4E8B\u4EF6\u89E6\u53D1: ${e.status}`)}),this.wsClient.on("disconnected",(e,t)=>{const n=t?.toString()||"";i.warn("[AgentClient] WebSocket \u65AD\u5F00\u8FDE\u63A5: code=%s, reason=%s, agentId=%s, \u6B63\u5728\u81EA\u52A8\u91CD\u8FDE",e,n,this.agentId)}),this.wsClient.on("error",e=>{i.error("[AgentClient] WebSocket \u9519\u8BEF: %s, stack=%s",e.message,e.stack)}),this.wsClient.on("reconnectFailed",()=>{i.error("[AgentClient] \u91CD\u8FDE\u5931\u8D25\uFF08\u5DF2\u8FBE\u91CD\u8BD5\u4E0A\u9650\uFF09\uFF0C\u505C\u6B62\u6D88\u606F\u5FAA\u73AF, agentId=%s",this.agentId),this.stop()}),this.wsClient.on("tokenRejected",()=>{i.error("[AgentClient] runtime token \u88AB 1008 \u62D2\u7EDD\u4E14\u5237\u65B0\u65E0\u53D8\u5316\uFF0C\u8FDB\u5165\u6162\u901F\u91CD\u8BD5\u7B49\u5F85\u65B0 token \u7B7E\u53D1: agentId=%s",this.agentId)}),this.wsClient.on("tokenRefreshFailed",e=>{i.error("[AgentClient] runtime token \u5237\u65B0\u8FDE\u7EED\u5931\u8D25 %s \u6B21\uFF0C\u8FDB\u5165\u6162\u901F\u91CD\u8BD5\u7B49\u5F85 bridge \u6062\u590D: agentId=%s",e,this.agentId)})}async register(){return i.info("[AgentClient] \u6B63\u5728\u6CE8\u518C Agent..."),await this.retryPendingLaunchBindingClaim(),this.hasPresetAgentId()?await this.registerWithExistingAgentId():await this.registerAsNewAgent()}hasPresetAgentId(){return!!(this.agentConfig.agentId&&this.agentConfig.agentId.trim().length>0)}async registerWithExistingAgentId(){const e=this.agentConfig.agentId;if(!e)throw new Error("Preset agentId is missing");this.agentId=e.trim();let t;try{t=await this.getProfileByAgentId(this.agentId)}catch(r){throw i.error("[AgentClient] getProfileByAgentId \u5931\u8D25 (presetAgentId=%s): %s",this.agentId,r instanceof Error?r.message:String(r)),r}this.displayName=t.displayName,this.projectId=t.projectId||null,i.info(`[AgentClient] \u4F7F\u7528\u9884\u8BBE AgentID \u7ED1\u5B9A\u5B9E\u4F8B: ${this.displayName} (${this.agentId})`),i.info(`[AgentClient] \u6240\u5C5E\u9879\u76EE: ${this.projectId||"(\u672A\u8BBE\u7F6E)"}`);try{await this.wsClient.connect(this.agentId)}catch(r){throw i.error("[AgentClient] WebSocket \u8FDE\u63A5\u5931\u8D25 (agentId=%s): %s",this.agentId,r instanceof Error?r.message:String(r)),r}i.info("[AgentClient] WebSocket \u8FDE\u63A5\u5DF2\u5EFA\u7ACB\uFF0CAgent \u73B0\u5728\u5DF2\u4E0A\u7EBF"),this.initializeStatusReporter();const n=await this.getProfileByAgentId(this.agentId);return this.displayName=n.displayName,this.projectId=n.projectId||null,u(n.roleName||"unknown-role",n.instanceName||this.agentId),{agentId:this.agentId,displayName:this.displayName,status:n.isOnline?"online":"offline",projectId:n.projectId,workspacePath:n.workspacePath,runtimeStatus:n.runtimeStatus,runtimeSessionId:n.runtimeSessionId}}async registerAsNewAgent(){const e=await this.httpClient.callTool("register",{roleName:this.agentConfig.roleName,projectId:this.agentConfig.projectId,workspacePath:this.agentConfig.workspacePath,prompt:this.agentConfig.prompt,runtimeBridgeBaseUrl:this.serverConfig.runtimeBridgeBaseUrl}),t=e.agentId;if(!t)throw new Error("Registration failed: agentId was not returned");return this.agentId=t,this.displayName=e.displayName,this.projectId=e.projectId||null,u(this.agentConfig.roleName||"unknown-role",e.instanceName||t),i.info(`[AgentClient] \u6CE8\u518C\u6210\u529F: ${this.displayName} (${this.agentId})`),i.info(`[AgentClient] \u72B6\u6001: ${e.status}`),i.info(`[AgentClient] \u6240\u5C5E\u9879\u76EE: ${this.projectId||"(\u672A\u8BBE\u7F6E)"}`),await this.wsClient.connect(this.agentId),i.info("[AgentClient] WebSocket \u8FDE\u63A5\u5DF2\u5EFA\u7ACB\uFF0CAgent \u73B0\u5728\u5DF2\u4E0A\u7EBF"),this.initializeStatusReporter(),e.isExisting===!1&&this.newCharacterHandler&&this.newCharacterHandler(),e}async unregister(){i.info("[AgentClient] \u6B63\u5728\u6CE8\u9500 Agent..."),this.agentId&&await this.httpClient.callTool("unregister",{agentId:this.agentId}),this.stopRuntimeTokenRefresh(),this.wsClient.disconnect(),this.agentId=null,this.displayName=null,this.projectId=null,this.isRunning=!1,i.info("[AgentClient] \u5DF2\u6CE8\u9500")}async discoverColleagues(){return await this.httpClient.callTool("discover_colleague",{agentId:this.agentId})}async discoverGroupRooms(){return this.ensureRegistered(),await this.httpClient.callTool("discover_group_rooms",{agentId:this.agentId})}async listProjectMembers(){return this.ensureRegistered(),await this.httpClient.callTool("list_project_members",{agentId:this.agentId})}async hireColleague(e){return this.ensureRegistered(),await this.httpClient.callTool("hire_colleague",{...e,agentId:this.agentId})}async callAgentScopedTool(e,t){this.ensureRegistered();const n={...t,agentId:this.agentId};if(e==="create_meeting"){const r=typeof t.waitTimeoutMs=="number"?t.waitTimeoutMs:Number.NaN,s=Number.isFinite(r)&&r>0?Math.min(r,C):C;return await this.httpClient.callToolOnce(e,{...n,waitTimeoutMs:s},0)}return await this.httpClient.callTool(e,n)}async reportMemoryStats(e){await this.callAgentScopedTool("report_memory_stats",{memoryStats:e})}async sendGroupMessage(e,t,n,r,s,a){this.ensureRegistered();const h=t||this.projectId||this.agentConfig.projectId,g={agentId:this.agentId,projectId:h,roomId:n,content:e,card:r,replyTo:s,...a?{voice:a}:{}};return a?await this.httpClient.callToolOnce("send_group_message",g,9e5):await this.httpClient.callTool("send_group_message",g)}async sendDirectMessage(e,t,n=!1,r,s,a,h,g,o){this.ensureRegistered();const l={agentId:this.agentId,targetId:e,content:t,requireReply:n,waitReply:n,replyToCallId:r,card:a,replyTo:h};if(typeof s=="number"&&s>0&&(l.timeoutMs=s),g?.priority&&g.priority!=="normal"&&(l.priority=g.priority,l.force=g.priority==="force",g.intent&&(l.intent=g.intent),g.ref&&(l.ref=g.ref),g.reason&&(l.reason=g.reason)),o&&(l.voice=o),n){const d=typeof s=="number"&&s>0?s+3e4:0;return await this.httpClient.callToolOnce("send_dm",l,d)}return o&&!o.async?await this.httpClient.callToolOnce("send_dm",l,9e5):await this.httpClient.callTool("send_dm",l)}async getDmSendStatus(e){return this.ensureRegistered(),await this.httpClient.callTool("get_dm_send_status",{agentId:this.agentId,ticket:e})}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 h=this.collectRoomIds(a,t),g=await Promise.all(h.map(async o=>{const l={agentId:this.agentId,projectId:t,roomId:o};e.since&&(l.since=e.since);try{return await this.httpClient.callTool("get_group_messages",l)}catch(d){return i.warn("[AgentClient] \u8DF3\u8FC7\u7FA4\u623F\u95F4\u672A\u8BFB\u8865\u62C9\u5931\u8D25: roomId=%s, error=%s",o,d instanceof Error?d.message:String(d)),{messages:[],currentReadPos:0,hasMore:!1}}}));return{directMessages:Array.isArray(s.messages)?s.messages:[],groupMessages:g.flatMap(o=>this.normalizeGroupMessages(o)).sort((o,l)=>new Date(o.timestamp).getTime()-new Date(l.timestamp).getTime())}}async markDmRead(e){if(e.length===0)return new Set;this.ensureRegistered();try{const t=await this.httpClient.callTool("mark_dm_read",{agentId:this.agentId,msgIds:e}),n=new Set(Array.isArray(t?.deliverableMsgIds)?t.deliverableMsgIds:[]),r=e.filter(s=>!n.has(s));return r.length>0?i.warn("[AgentClient] mark_dm_read \u786E\u8BA4\u540E\u5C06\u6709 %d \u6761\u6D88\u606F\u88AB\u4E22\u5F03\u4E0D\u4EA4\u4ED8: \u8BF7\u6C42=%s, \u53EF\u4EA4\u4ED8=%s, \u88AB\u4E22\u5F03=%s",r.length,JSON.stringify(e),JSON.stringify([...n]),JSON.stringify(r)):i.info("[AgentClient] mark_dm_read \u786E\u8BA4\u5B8C\u6210: %d \u6761\u5168\u90E8\u53EF\u4EA4\u4ED8",e.length),n}catch(t){throw i.warn("[AgentClient] mark_dm_read \u8BF7\u6C42\u5931\u8D25\uFF08\u5C06\u964D\u7EA7\u4E3A\u76F4\u63A5\u4EA4\u4ED8\uFF09: %s",t instanceof Error?t.message:String(t)),t}}async markForceInjected(e){if(e.length===0)return new Set;this.ensureRegistered();try{const t=await this.httpClient.callTool("mark_force_injected",{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_force_injected \u786E\u8BA4\u540E\u5C06\u6709 %d \u6761\u5F3A\u5236\u6D88\u606F\u88AB\u4E22\u5F03\u4E0D\u4EA4\u4ED8: \u8BF7\u6C42=%s, \u53EF\u4EA4\u4ED8=%s",r.length,JSON.stringify(e),JSON.stringify([...n])):i.info("[AgentClient] mark_force_injected \u786E\u8BA4\u5B8C\u6210: %d \u6761\u5F3A\u5236\u6D88\u606F\u5DF2\u6CE8\u5165",e.length),n}catch(t){throw i.warn("[AgentClient] mark_force_injected \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 fetchCurrentAction(){const e=this.serverConfig.runtimeBridgeBaseUrl,t=this.agentId;if(!e||!t)return null;try{const n=`${e}/runtime/sessions/${encodeURIComponent(t)}/current-action`,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] \u67E5\u8BE2 bridge \u5F53\u524D\u52A8\u4F5C\u5931\u8D25: HTTP %s, url=%s",s.status,n),null;const a=await s.json();return a?.ok?a:null}catch(n){return i.warn("[AgentClient] \u67E5\u8BE2 bridge \u5F53\u524D\u52A8\u4F5C\u5F02\u5E38: %s",n instanceof Error?n.message:String(n)),null}}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(){c.loadConfig(),this.agentConfig=c.getAgentConfig(),i.info(`[AgentClient] \u914D\u7F6E\u5DF2\u91CD\u65B0\u52A0\u8F7D\uFF0C\u89D2\u8272: ${this.agentConfig.roleName}`)}enterDegradedMode(){this.isDegradedMode=!0,i.warn("[AgentClient] \u8FDB\u5165\u964D\u7EA7\u6A21\u5F0F\uFF0C\u5C06\u5728\u540E\u53F0\u6301\u7EED\u5C1D\u8BD5\u91CD\u8FDE")}exitDegradedMode(){this.isDegradedMode=!1,i.info("[AgentClient] \u9000\u51FA\u964D\u7EA7\u6A21\u5F0F")}isInDegradedMode(){return this.isDegradedMode}async retryRegistrationInBackground(e,t){let n=0;(async()=>{for(;this.isDegradedMode;)try{i.info(`[AgentClient] \u964D\u7EA7\u6A21\u5F0F\uFF1A\u5C1D\u8BD5\u91CD\u65B0\u6CE8\u518C (${n+1}/${t===-1?"\u65E0\u9650":t})`);const s=await this.register();i.info(`[AgentClient] \u964D\u7EA7\u6A21\u5F0F\uFF1A\u6CE8\u518C\u6210\u529F - ${s.displayName} (${s.agentId})`),this.exitDegradedMode(),this.messageHandler&&this.start(this.messageHandler);return}catch(s){n++;const a=s instanceof Error?s.message:String(s);if(i.warn(`[AgentClient] \u964D\u7EA7\u6A21\u5F0F\uFF1A\u6CE8\u518C\u5931\u8D25 (${n}/${t===-1?"\u65E0\u9650":t}): ${a}`),t>0&&n>=t){i.error("[AgentClient] \u964D\u7EA7\u6A21\u5F0F\uFF1A\u8FBE\u5230\u6700\u5927\u91CD\u8BD5\u6B21\u6570\uFF0C\u505C\u6B62\u91CD\u8FDE"),this.isDegradedMode=!1;return}await new Promise(h=>setTimeout(h,e))}})().catch(s=>{i.error("[AgentClient] \u964D\u7EA7\u6A21\u5F0F\u540E\u53F0\u91CD\u8BD5\u5FAA\u73AF\u5F02\u5E38\u9000\u51FA: error=%s, stack=%s",s instanceof Error?s.message:String(s),s instanceof Error?s.stack:"(no stack)")})}initializeStatusReporter(){if(!this.agentId){i.warn("[AgentClient] \u65E0\u6CD5\u521D\u59CB\u5316\u72B6\u6001\u62A5\u544A\u5668\uFF1AagentId \u4E3A\u7A7A");return}this.statusReporter=new A({agentId:this.agentId,sendStatusUpdate:e=>{this.wsClient.send({type:"AGENT_STATUS",data:e,timestamp:new Date().toISOString()})}}),w(e=>this.reportMcpNodeLog(e)),this.startRuntimeTokenRefresh(),i.info("[AgentClient] \u72B6\u6001\u62A5\u544A\u5668\u5DF2\u521D\u59CB\u5316")}startRuntimeTokenRefresh(){this.stopRuntimeTokenRefresh();const e=this.serverConfig.runtimeTokenRefreshIntervalMs;if(!e||e<=0){i.warn("[AgentClient] runtimeTokenRefreshIntervalMs \u672A\u914D\u7F6E\u6216\u65E0\u6548\uFF0C\u8DF3\u8FC7\u4E3B\u52A8\u7EED\u671F");return}const t=this.agentId;if(!t){i.warn("[AgentClient] agentId \u4E3A\u7A7A\uFF0C\u8DF3\u8FC7\u4E3B\u52A8\u7EED\u671F");return}this.runtimeTokenRefreshTimer=setInterval(async()=>{try{await this.httpClient.refreshRuntimeAccessToken(t)&&i.info("[AgentClient] runtimeAccessToken \u5DF2\u4E3B\u52A8\u7EED\u671F")}catch(n){i.warn("[AgentClient] \u4E3B\u52A8\u7EED\u671F runtimeAccessToken \u5931\u8D25: %s",n instanceof Error?n.message:String(n)),n instanceof Error&&n.stack&&i.warn("[AgentClient] \u4E3B\u52A8\u7EED\u671F\u5F02\u5E38\u5806\u6808:",n.stack)}},e),this.runtimeTokenRefreshTimer.unref?.(),i.info(`[AgentClient] runtime token \u4E3B\u52A8\u7EED\u671F\u5DF2\u542F\u52A8\uFF0C\u95F4\u9694 ${e}ms`)}stopRuntimeTokenRefresh(){this.runtimeTokenRefreshTimer&&(clearInterval(this.runtimeTokenRefreshTimer),this.runtimeTokenRefreshTimer=null)}reportMcpNodeLog(e){const t=this.wsClient;!this.agentId||!this.wsClient.isConnected()||typeof t.sendMcpNodeLog!="function"||t.sendMcpNodeLog(e)}getStatusReporter(){return this.statusReporter}}export{N as AgentClient,T as PollLongPollTimeoutError};
|
|
2
2
|
|