aws-runtime-bridge 1.9.98 → 1.9.100
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/dist/adapter/AcodeSdkAdapter.d.ts +7 -1
- package/dist/adapter/AcodeSdkAdapter.js +5 -5
- package/dist/adapter/ClaudeSdkAdapter.d.ts +4 -0
- package/dist/adapter/ClaudeSdkAdapter.js +2 -2
- package/dist/adapter/CodexSdkAdapter.d.ts +2 -0
- package/dist/adapter/CodexSdkAdapter.js +3 -3
- package/dist/adapter/OpencodeSdkAdapter.d.ts +2 -0
- package/dist/adapter/OpencodeSdkAdapter.js +2 -2
- package/dist/adapter/idle-poll-loop.d.ts +4 -1
- package/dist/adapter/idle-poll-loop.js +1 -1
- package/dist/adapter/types.d.ts +4 -2
- package/dist/browser/browser-pool.d.ts +73 -0
- package/dist/browser/browser-pool.js +2 -0
- package/dist/browser/browser-profile-store.d.ts +28 -0
- package/dist/browser/browser-profile-store.js +2 -0
- package/dist/browser/built-in-browser-tools.d.ts +27 -0
- package/dist/browser/built-in-browser-tools.js +2 -0
- package/dist/browser/element-locator.d.ts +24 -0
- package/dist/browser/element-locator.js +2 -0
- package/dist/browser/element-picker.d.ts +17 -0
- package/dist/browser/element-picker.js +2 -0
- package/dist/browser/input-dispatcher.d.ts +34 -0
- package/dist/browser/input-dispatcher.js +2 -0
- package/dist/browser/listener-store.d.ts +32 -0
- package/dist/browser/listener-store.js +2 -0
- package/dist/browser/page-listener-manager.d.ts +106 -0
- package/dist/browser/page-listener-manager.js +307 -0
- package/dist/browser/page-listener-types.d.ts +90 -0
- package/dist/browser/page-listener-types.js +1 -0
- package/dist/browser/screencast-manager.d.ts +42 -0
- package/dist/browser/screencast-manager.js +2 -0
- package/dist/browser/snapshot-serializer.d.ts +15 -0
- package/dist/browser/snapshot-serializer.js +5 -0
- package/dist/browser/ssrf-guard.d.ts +15 -0
- package/dist/browser/ssrf-guard.js +2 -0
- package/dist/browser/stealth.d.ts +7 -0
- package/dist/browser/stealth.js +173 -0
- package/dist/browser/step-archive.d.ts +52 -0
- package/dist/browser/step-archive.js +2 -0
- package/dist/browser/types.d.ts +192 -0
- package/dist/browser/types.js +2 -0
- package/dist/browser/ws-server.d.ts +67 -0
- package/dist/browser/ws-server.js +2 -0
- package/dist/index.js +1 -1
- package/dist/middleware/auth.d.ts +2 -0
- package/dist/middleware/auth.js +1 -1
- package/dist/remote-desktop/computer-control.d.ts +30 -0
- package/dist/remote-desktop/computer-control.js +2 -0
- package/dist/remote-desktop/coords.d.ts +13 -0
- package/dist/remote-desktop/coords.js +2 -0
- package/dist/remote-desktop/frame-backpressure.d.ts +7 -0
- package/dist/remote-desktop/frame-backpressure.js +2 -0
- package/dist/remote-desktop/index.d.ts +7 -0
- package/dist/remote-desktop/index.js +4 -0
- package/dist/remote-desktop/input-backends/interface.d.ts +17 -0
- package/dist/remote-desktop/input-backends/interface.js +1 -0
- package/dist/remote-desktop/input-backends/key-map.d.ts +2 -0
- package/dist/remote-desktop/input-backends/key-map.js +2 -0
- package/dist/remote-desktop/input-dispatcher.d.ts +11 -0
- package/dist/remote-desktop/input-dispatcher.js +2 -0
- package/dist/remote-desktop/permission-manager.d.ts +7 -0
- package/dist/remote-desktop/permission-manager.js +2 -0
- package/dist/remote-desktop/screen-capture.d.ts +27 -0
- package/dist/remote-desktop/screen-capture.js +2 -0
- package/dist/remote-desktop/session-manager.d.ts +59 -0
- package/dist/remote-desktop/session-manager.js +2 -0
- package/dist/remote-desktop/system-backend.d.ts +65 -0
- package/dist/remote-desktop/system-backend.js +5 -0
- package/dist/remote-desktop/types.d.ts +68 -0
- package/dist/remote-desktop/types.js +1 -0
- package/dist/remote-desktop/ui-automation.d.ts +48 -0
- package/dist/remote-desktop/ui-automation.js +31 -0
- package/dist/remote-desktop/win32-api.d.ts +29 -0
- package/dist/remote-desktop/win32-api.js +2 -0
- package/dist/routes/background-tasks.d.ts +2 -0
- package/dist/routes/background-tasks.js +2 -0
- package/dist/routes/browser-listeners.d.ts +2 -0
- package/dist/routes/browser-listeners.js +2 -0
- package/dist/routes/browser-sessions.d.ts +2 -0
- package/dist/routes/browser-sessions.js +2 -0
- package/dist/routes/pty.js +3 -3
- package/dist/routes/terminal.js +30 -30
- package/dist/services/agent-pty-manager.d.ts +22 -0
- package/dist/services/agent-pty-manager.js +5 -0
- package/dist/services/browser-session-manager.d.ts +55 -0
- package/dist/services/browser-session-manager.js +12 -0
- package/dist/services/cli-commands.d.ts +4 -0
- package/dist/services/cli-commands.js +5 -5
- package/package/acode/dist/await-complete-tool.d.ts +17 -0
- package/package/acode/dist/await-complete-tool.js +21 -0
- package/package/acode/dist/background-command-manager.d.ts +148 -0
- package/package/acode/dist/background-command-manager.js +8 -0
- package/package/acode/dist/background-command-store.d.ts +46 -0
- package/package/acode/dist/background-command-store.js +2 -0
- package/package/acode/dist/background-command-tools.d.ts +5 -0
- package/package/acode/dist/background-command-tools.js +18 -0
- package/package/acode/dist/background-output-ringbuffer.d.ts +23 -0
- package/package/acode/dist/background-output-ringbuffer.js +3 -0
- package/package/acode/dist/built-in-file-tools.d.ts +8 -1
- package/package/acode/dist/built-in-file-tools.js +2 -2
- package/package/acode/dist/compaction.js +6 -6
- package/package/acode/dist/index.d.ts +1 -0
- package/package/acode/dist/index.js +1 -1
- package/package/acode/dist/runtime.d.ts +6 -0
- package/package/acode/dist/runtime.js +27 -27
- package/package/acode/dist/sub-agent-tools.d.ts +0 -1
- package/package/acode/dist/sub-agent-tools.js +11 -28
- package/package/acode/dist/terminal-tool.d.ts +7 -0
- package/package/acode/dist/terminal-tool.js +2 -0
- package/package/acode/dist/terminal-types.d.ts +38 -0
- package/package/acode/dist/terminal-types.js +1 -0
- package/package/acode/dist/types.d.ts +10 -1
- package/package/aws-client-agent-mcp/dist/agent-client.d.ts +3 -1
- package/package/aws-client-agent-mcp/dist/agent-client.js +1 -1
- package/package/aws-client-agent-mcp/dist/logger.d.ts +2 -0
- package/package/aws-client-agent-mcp/dist/logger.js +1 -1
- package/package/aws-client-agent-mcp/dist/mcp-server.d.ts +8 -0
- package/package/aws-client-agent-mcp/dist/mcp-server.js +30 -19
- package/package/aws-client-agent-mcp/dist/types.d.ts +25 -0
- package/package.json +6 -2
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
|
|
2
|
+
import type { ACodeBuiltInTool } from "./built-in-file-tools.js";
|
|
3
|
+
import type { TerminalManager } from "./terminal-types.js";
|
|
4
|
+
export interface TerminalToolDeps {
|
|
5
|
+
terminalManager?: TerminalManager;
|
|
6
|
+
}
|
|
7
|
+
export declare function createTerminalTool(agentId: string, deps: TerminalToolDeps): ACodeBuiltInTool;
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
const a=["create","write","read","kill","resize"],u='Open a persistent interactive terminal (real PTY) for commands that require stdin input or need to keep state (cwd/env) across multiple commands.\nExamples: ssh to a remote host, git push that prompts for credentials, entering a remote shell, or a multi-step shell workflow.\nUse action=create to start a shell session (returns session_id), action=write to send keystrokes/commands (must end with \\n to execute), action=read to get incremental output since last read (status=running|exited; needs_input hints the program is waiting for input), action=kill to terminate, action=resize to adjust size.\nFor non-interactive one-shot commands use the Bash tool; for long-running non-interactive builds/servers use Bash with run_in_background.\n\nAVOID entering interactive pagers (less/man/more/most) or full-screen TUIs (vim/nano/top/htop) inside this terminal \u2014 they wait for keystrokes that block agent progress. Prefer non-interactive alternatives: `git --no-pager log`, `git --no-pager diff`, `man <topic> | cat`, `cat <file>`, `head -n 200 <file>`, `grep -n <pattern> <file>`. If you DO enter a pager by accident, send `q` (to quit) immediately via action=write; if you see "(press RETURN)" / "Press ENTER to continue" hints, send a single `\\r` to dismiss them.';function p(c,d){const i=d.terminalManager;return{kind:"builtin",toolName:"Terminal",exposedName:"Terminal",description:u,inputSchema:{type:"object",properties:{action:{type:"string",enum:[...a],description:"create=new terminal session; write=send input/command (end with \\n); read=incremental output since last read; kill=terminate session; resize=adjust terminal size"},session_id:{type:"string",description:"Session id returned by action=create"},command:{type:"string",description:"For create: optional initial command (e.g. 'ssh user@host'). For write: text to send; MUST end with \\n to execute (e.g. 'ls -la\\n'). For password prompts send '<password>\\n'."},cwd:{type:"string",description:"create: initial working directory (must be within allowed workspace roots)"},shell:{type:"string",enum:["auto","bash","sh","zsh","fish","pwsh","powershell","cmd"],default:"auto",description:"create: login shell to spawn. 'auto' lets the bridge pick the platform default (Windows\u2192pwsh/powershell/cmd, Unix\u2192$SHELL/bash); recommended to avoid 'File not found' on Windows where bash is absent."},timeout_ms:{type:"number",description:"Reserved. Terminal sessions persist; an idle session is reclaimed after 30min of no agent activity. Long-running non-interactive commands should use Bash run_in_background instead."},cols:{type:"number",default:120,description:"terminal columns"},rows:{type:"number",default:30,description:"terminal rows"},read_lines:{type:"number",default:200,description:"read: max lines to return (tail); excess marked truncated"}},required:["action"],additionalProperties:!1},async execute(e){if(!i)return{error:"Terminal \u672A\u542F\u7528\uFF1Abridge \u672A\u6CE8\u5165 terminalManager"};const s=String(e.action??"");try{switch(s){case"create":{const t=typeof e.shell=="string"&&e.shell.trim()?e.shell.trim():"auto",n=typeof e.cwd=="string"&&e.cwd.trim()?e.cwd.trim():process.cwd(),r=typeof e.cols=="number"?e.cols:120,l=typeof e.rows=="number"?e.rows:30,m=typeof e.command=="string"?e.command:"",o=i.create({agentId:c,shell:t,cwd:n,cols:r,rows:l,preCommand:m});return{session_id:o.id,pid:o.pid??null,status:"running"}}case"write":{const t=String(e.session_id??"");if(!t)return{error:"write \u9700\u8981 session_id"};const n=typeof e.command=="string"?e.command:"";return i.write(t,n),{ok:!0}}case"read":{const t=String(e.session_id??"");if(!t)return{error:"read \u9700\u8981 session_id"};const n=typeof e.read_lines=="number"?e.read_lines:200;return i.read(t,{lines:n})}case"kill":{const t=String(e.session_id??"");return t?(i.kill(t),{ok:!0}):{error:"kill \u9700\u8981 session_id"}}case"resize":{const t=String(e.session_id??"");if(!t)return{error:"resize \u9700\u8981 session_id"};const n=typeof e.cols=="number"?e.cols:120,r=typeof e.rows=="number"?e.rows:30;return i.resize(t,n,r),{ok:!0}}default:return{error:`\u672A\u77E5 action: ${s}\uFF08\u5141\u8BB8\uFF1A${a.join(", ")}\uFF09`}}}catch(t){const n=t instanceof Error?t.message:String(t);return{error:`Terminal.${s} \u5931\u8D25\uFF1A${n}`}}}}}export{p as createTerminalTool};
|
|
2
|
+
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
|
|
2
|
+
export type TerminalAction = "create" | "write" | "read" | "kill" | "resize";
|
|
3
|
+
export interface TerminalCreateOpts {
|
|
4
|
+
agentId: string;
|
|
5
|
+
|
|
6
|
+
shell?: string;
|
|
7
|
+
|
|
8
|
+
cwd: string;
|
|
9
|
+
cols?: number;
|
|
10
|
+
rows?: number;
|
|
11
|
+
|
|
12
|
+
preCommand?: string;
|
|
13
|
+
}
|
|
14
|
+
export interface TerminalReadOpts {
|
|
15
|
+
|
|
16
|
+
lines?: number;
|
|
17
|
+
}
|
|
18
|
+
export interface TerminalReadResult {
|
|
19
|
+
status: "running" | "exited" | "closed";
|
|
20
|
+
exit_code: number | null;
|
|
21
|
+
|
|
22
|
+
output: string;
|
|
23
|
+
|
|
24
|
+
needs_input: boolean;
|
|
25
|
+
truncated: boolean;
|
|
26
|
+
}
|
|
27
|
+
export interface TerminalManager {
|
|
28
|
+
create(opts: TerminalCreateOpts): {
|
|
29
|
+
id: string;
|
|
30
|
+
pid: number | undefined;
|
|
31
|
+
};
|
|
32
|
+
write(id: string, data: string): void;
|
|
33
|
+
read(id: string, opts: TerminalReadOpts): TerminalReadResult;
|
|
34
|
+
kill(id: string): void;
|
|
35
|
+
resize(id: string, cols: number, rows: number): void;
|
|
36
|
+
|
|
37
|
+
killByAgent?(agentId: string): void;
|
|
38
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { SubAgentManager } from "./sub-agent-manager.js";
|
|
2
2
|
import type { SubAgentType } from "./sub-agent-types.js";
|
|
3
3
|
import type { ACodeMcpConnection } from "./runtime.js";
|
|
4
|
+
import type { TerminalManager } from "./terminal-types.js";
|
|
4
5
|
export interface ACodeMcpServerSpec {
|
|
5
6
|
type?: "stdio" | "sse" | "http";
|
|
6
7
|
command?: string;
|
|
@@ -57,7 +58,7 @@ export interface ACodeSkillGroup {
|
|
|
57
58
|
exists: boolean;
|
|
58
59
|
skills: ACodeSkillMetadata[];
|
|
59
60
|
}
|
|
60
|
-
export type ACodeEventType = "session_started" | "startup_phase" | "ai_request" | "thinking_delta" | "assistant_delta" | "command_output" | "command_status" | "mcp_status" | "skill_status" | "warning" | "turn_complete" | "session_complete" | "context_compaction" | "question_request" | "error";
|
|
61
|
+
export type ACodeEventType = "session_started" | "startup_phase" | "ai_request" | "thinking_delta" | "assistant_delta" | "command_output" | "command_status" | "mcp_status" | "skill_status" | "warning" | "turn_complete" | "session_complete" | "context_compaction" | "question_request" | "error" | "background_command_completed";
|
|
61
62
|
export interface ACodeEvent {
|
|
62
63
|
type: ACodeEventType;
|
|
63
64
|
sessionId: string;
|
|
@@ -120,6 +121,8 @@ export interface ACodeRuntimeConfig {
|
|
|
120
121
|
|
|
121
122
|
subAgentManager?: SubAgentManager;
|
|
122
123
|
|
|
124
|
+
terminalManager?: TerminalManager;
|
|
125
|
+
|
|
123
126
|
sharedMcpConnections?: ACodeMcpConnection[];
|
|
124
127
|
|
|
125
128
|
subAgentModel?: string;
|
|
@@ -129,6 +132,8 @@ export interface ACodeRuntimeConfig {
|
|
|
129
132
|
subagentType?: SubAgentType;
|
|
130
133
|
|
|
131
134
|
onFileChange?: import("./built-in-file-tools.js").OnAgentFileChange;
|
|
135
|
+
|
|
136
|
+
extraBuiltInTools?: import("./built-in-file-tools.js").ACodeBuiltInTool[];
|
|
132
137
|
}
|
|
133
138
|
export interface ACodeResolvedProviderConfig {
|
|
134
139
|
model: string;
|
|
@@ -142,6 +147,10 @@ export interface ACodeResolvedProviderConfig {
|
|
|
142
147
|
|
|
143
148
|
requestTotalTimeoutMs: number;
|
|
144
149
|
requestRetryCount: number;
|
|
150
|
+
|
|
151
|
+
requestFirstByteTimeoutMs: number;
|
|
152
|
+
|
|
153
|
+
requestStreamIdleTimeoutMs: number;
|
|
145
154
|
mcpToolTimeoutMs: number;
|
|
146
155
|
mcpPollingToolTimeoutMs: number;
|
|
147
156
|
supportsImageInput: boolean;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
|
|
2
2
|
import type { MemoryStats } from "./memory-store.js";
|
|
3
3
|
import { StatusReporter } from "./status-reporter.js";
|
|
4
|
-
import type { AgentConfig, DirectMessage, DmHistoryResponse, FetchUnreadMessagesOptions, FinishTaskRollbackArgs, GroupHistoryResponse, GroupRoomsResponse, HireBatchResult, HireColleagueArgs, HireColleaguesBatchArgs, HiredColleagueResult, MessageHandler, OnlineListResponse, ProfileInfo, RegisterResult, SendDmResult, SendMessageResult, StartTaskRollbackArgs, TaskInstanceCommentArgs, UnreadMessagesResult } from "./types.js";
|
|
4
|
+
import type { AgentConfig, BrowserListenerEvent, DirectMessage, DmHistoryResponse, FetchUnreadMessagesOptions, FinishTaskRollbackArgs, GroupHistoryResponse, GroupRoomsResponse, HireBatchResult, HireColleagueArgs, HireColleaguesBatchArgs, HiredColleagueResult, MessageHandler, OnlineListResponse, ProfileInfo, RegisterResult, SendDmResult, SendMessageResult, StartTaskRollbackArgs, TaskInstanceCommentArgs, UnreadMessagesResult } from "./types.js";
|
|
5
5
|
export type ProfileHandler = (profile: ProfileInfo) => void;
|
|
6
6
|
export declare class AgentClient {
|
|
7
7
|
private wsClient;
|
|
@@ -61,6 +61,8 @@ export declare class AgentClient {
|
|
|
61
61
|
|
|
62
62
|
fetchUnreadMessages(options?: FetchUnreadMessagesOptions): Promise<UnreadMessagesResult>;
|
|
63
63
|
|
|
64
|
+
fetchBrowserListenerEvents(): Promise<BrowserListenerEvent[]>;
|
|
65
|
+
|
|
64
66
|
private fetchDirectMessagesWithRecovery;
|
|
65
67
|
|
|
66
68
|
private isRecoverableLongPollError;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{configManager as g}from"./config.js";import{MESSAGE_POLL_INTERVAL_MS as p}from"./constants.js";import{HttpClient as m}from"./http-client.js";import{logger as s,setMcpNodeLogSink as C,updateStartupLogIdentity as f}from"./logger.js";import{claimRuntimeLaunchBinding as I}from"./runtime-launch-binding.js";import{StatusReporter as y}from"./status-reporter.js";import{WebSocketClient as u}from"./websocket-client.js";class _{wsClient;httpClient;agentConfig;serverConfig;agentId=null;displayName=null;projectName=null;isRunning=!1;isDegradedMode=!1;messageHandler=null;profileHandler=null;pollTimer=null;statusReporter=null;newCharacterHandler=null;runtimeTokenRefreshTimer=null;cachedProfile=null;constructor(){g.loadConfig(),this.agentConfig=g.getAgentConfig(),this.serverConfig=g.getServerConfig(),this.wsClient=new u(this.serverConfig),this.httpClient=new m(this.serverConfig),this.setupWebSocketListeners()}async initialize(){const e=await I(this.agentConfig,this.serverConfig);if(!e){this.serverConfig.runtimeBridgeBaseUrl=void 0;return}g.applyRuntimeLaunchBinding(e),this.agentConfig=g.getAgentConfig(),this.serverConfig=g.getServerConfig(),this.wsClient=new u(this.serverConfig),this.httpClient=new m(this.serverConfig),this.setupWebSocketListeners()}setupWebSocketListeners(){this.wsClient.on("directMessage",e=>{this.handleIncomingDm(e)}),this.wsClient.on("groupMessage",e=>{this.handleIncomingGroup(e)}),this.wsClient.on("profileInfo",e=>{s.info(`[AgentClient] WebSocket profileInfo \u4E8B\u4EF6\u89E6\u53D1\uFF0CdisplayName: ${e.displayName}`),this.handleProfileInfo(e)}),this.wsClient.on("agentStatus",e=>{s.info(`[AgentClient] WebSocket agentStatus \u4E8B\u4EF6\u89E6\u53D1: ${e.status}`)}),this.wsClient.on("disconnected",(e,t)=>{const n=t?.toString()||"";s.warn("[AgentClient] WebSocket \u65AD\u5F00\u8FDE\u63A5: code=%s, reason=%s, agentId=%s, \u6B63\u5728\u81EA\u52A8\u91CD\u8FDE",e,n,this.agentId)}),this.wsClient.on("error",e=>{s.error("[AgentClient] WebSocket \u9519\u8BEF: %s, stack=%s",e.message,e.stack)}),this.wsClient.on("reconnectFailed",()=>{s.error("[AgentClient] \u91CD\u8FDE\u5931\u8D25\uFF08\u5DF2\u8FBE\u91CD\u8BD5\u4E0A\u9650\uFF09\uFF0C\u505C\u6B62\u6D88\u606F\u5FAA\u73AF, agentId=%s",this.agentId),this.stop()})}async register(){return s.info("[AgentClient] \u6B63\u5728\u6CE8\u518C Agent..."),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(i){throw s.error("[AgentClient] getProfileByAgentId \u5931\u8D25 (presetAgentId=%s): %s",this.agentId,i instanceof Error?i.message:String(i)),i}this.displayName=t.displayName,this.projectName=t.projectName||null,s.info(`[AgentClient] \u4F7F\u7528\u9884\u8BBE AgentID \u7ED1\u5B9A\u5B9E\u4F8B: ${this.displayName} (${this.agentId})`),s.info(`[AgentClient] \u6240\u5C5E\u9879\u76EE: ${this.projectName||"(\u672A\u8BBE\u7F6E)"}`);try{await this.wsClient.connect(this.agentId)}catch(i){throw s.error("[AgentClient] WebSocket \u8FDE\u63A5\u5931\u8D25 (agentId=%s): %s",this.agentId,i instanceof Error?i.message:String(i)),i}s.info("[AgentClient] WebSocket \u8FDE\u63A5\u5DF2\u5EFA\u7ACB\uFF0CAgent \u73B0\u5728\u5DF2\u4E0A\u7EBF"),this.initializeStatusReporter();const n=await this.getProfileByAgentId(this.agentId);return this.displayName=n.displayName,this.projectName=n.projectName||null,f(n.roleName||"unknown-role",n.instanceName||this.agentId),{agentId:this.agentId,displayName:this.displayName,status:n.isOnline?"online":"offline",projectName:n.projectName,workspacePath:n.workspacePath,runtimeStatus:n.runtimeStatus,runtimeSessionId:n.runtimeSessionId}}async registerAsNewAgent(){const e=await this.httpClient.callTool("register",{roleName:this.agentConfig.roleName,projectName:this.agentConfig.projectName,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.projectName=e.projectName||null,f(this.agentConfig.roleName||"unknown-role",e.instanceName||t),s.info(`[AgentClient] \u6CE8\u518C\u6210\u529F: ${this.displayName} (${this.agentId})`),s.info(`[AgentClient] \u72B6\u6001: ${e.status}`),s.info(`[AgentClient] \u6240\u5C5E\u9879\u76EE: ${this.projectName||"(\u672A\u8BBE\u7F6E)"}`),await this.wsClient.connect(this.agentId),s.info("[AgentClient] WebSocket \u8FDE\u63A5\u5DF2\u5EFA\u7ACB\uFF0CAgent \u73B0\u5728\u5DF2\u4E0A\u7EBF"),this.initializeStatusReporter(),e.isExisting===!1&&this.newCharacterHandler&&this.newCharacterHandler(),e}async unregister(){s.info("[AgentClient] \u6B63\u5728\u6CE8\u9500 Agent..."),this.agentId&&await this.httpClient.callTool("unregister",{agentId:this.agentId}),this.stopRuntimeTokenRefresh(),this.wsClient.disconnect(),this.agentId=null,this.displayName=null,this.projectName=null,this.isRunning=!1,s.info("[AgentClient] \u5DF2\u6CE8\u9500")}async discoverColleagues(){return await this.httpClient.callTool("discover_colleague",{agentId:this.agentId})}async discoverGroupRooms(){return this.ensureRegistered(),await this.httpClient.callTool("discover_group_rooms",{agentId:this.agentId})}async hireColleague(e){return this.ensureRegistered(),await this.httpClient.callTool("hire_colleague",{agentId:this.agentId,...e})}async hireColleaguesBatch(e){return this.ensureRegistered(),await this.httpClient.callTool("hire_colleagues_batch",{agentId:this.agentId,...e})}async callAgentScopedTool(e,t){return this.ensureRegistered(),await this.httpClient.callTool(e,{agentId:this.agentId,...t})}async reportMemoryStats(e){await this.callAgentScopedTool("report_memory_stats",{memoryStats:e})}async sendGroupMessage(e,t,n){this.ensureRegistered();const i=t||this.projectName||this.agentConfig.projectName;return await this.httpClient.callTool("send_group_message",{agentId:this.agentId,projectName:i,roomId:n,content:e})}async sendDirectMessage(e,t,n=!1,i,r){this.ensureRegistered();const o={agentId:this.agentId,targetId:e,content:t,requireReply:n,waitReply:n,replyToCallId:i};if(typeof r=="number"&&r>0&&(o.timeoutMs=r),n){const h=typeof r=="number"&&r>0?r+3e4:0;return await this.httpClient.callToolOnce("send_dm",o,h)}return await this.httpClient.callTool("send_dm",o)}async sendCallAndWaitReply(e,t,n=6e4){const i=await this.sendDirectMessage(e,t,!0,void 0,n);if(i.reply)return i.reply;throw new Error("No reply received for call-style direct message before timeout")}async replyToCall(e,t,n){return await this.sendDirectMessage(t,n,!1,e)}async getDmHistory(e,t=50,n){this.ensureRegistered();const i={agentId:this.agentId,targetUserId:e,limit:t};return n&&(i.since=n),await this.httpClient.callTool("get_dm_history",i)}async getGroupHistory(e=50,t,n){if(this.ensureRegistered(),t){const a={projectName:this.projectName||this.agentConfig.projectName,roomId:t,limit:e};return n&&(a.since=n),await this.httpClient.callTool("get_group_history",a)}const i=await this.discoverGroupRooms(),r=this.projectName||this.agentConfig.projectName,o=this.collectRoomIds(i,r);if(o.length===0)return{messages:[],count:0};const c=(await Promise.all(o.map(async a=>{const l={projectName:r,roomId:a,limit:e};return n&&(l.since=n),await this.httpClient.callTool("get_group_history",l)}))).flatMap(a=>a.messages).sort((a,l)=>new Date(a.timestamp).getTime()-new Date(l.timestamp).getTime());return{messages:c,count:c.length}}async fetchUnreadMessages(e={}){this.ensureRegistered();const t=this.projectName||this.agentConfig.projectName,n={agentId:this.agentId,blockIfEmpty:e.blockIfEmpty??!1};e.since&&(n.since=e.since),e.blockTimeoutMs&&e.blockTimeoutMs>0&&(n.blockTimeoutMs=e.blockTimeoutMs);const i=e.includePipelineTasks?"poll_message":"get_dm_messages",r=await this.fetchDirectMessagesWithRecovery(i,n),o=await this.discoverGroupRooms(),h=this.collectRoomIds(o,t),c=await Promise.all(h.map(async a=>{const l={agentId:this.agentId,projectName:t,roomId:a};e.since&&(l.since=e.since);try{return await this.httpClient.callTool("get_group_messages",l)}catch(d){return s.warn("[AgentClient] \u8DF3\u8FC7\u7FA4\u623F\u95F4\u672A\u8BFB\u8865\u62C9\u5931\u8D25: roomId=%s, error=%s",a,d instanceof Error?d.message:String(d)),{messages:[],currentReadPos:0,hasMore:!1}}}));return{directMessages:Array.isArray(r.messages)?r.messages:[],groupMessages:c.flatMap(a=>this.normalizeGroupMessages(a)).sort((a,l)=>new Date(a.timestamp).getTime()-new Date(l.timestamp).getTime())}}async fetchDirectMessagesWithRecovery(e,t){if(e==="poll_message")try{return await this.httpClient.callToolOnce(e,t)}catch(n){if(this.isRecoverableLongPollError(n))return s.warn("[AgentClient] poll_message \u5355\u6B21\u957F\u8F6E\u8BE2\u8D85\u65F6\uFF0C\u6309\u7A7A\u7ED3\u679C\u9000\u907F\u540E\u7EE7\u7EED\u7B49\u5F85:",n),{messages:[]};throw n}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(i=>i.projectName===t).map(i=>i.id);return Array.from(new Set(n))}async getProfile(){this.ensureRegistered();const e=this.agentId;if(!e)throw new Error("Agent is not registered");return{...await this.getProfileByAgentId(e),describe:this.agentConfig.describe}}async getProfileByAgentId(e){return await this.httpClient.callTool("get_profile",{agentId:e})}async getMyTasks(){return this.ensureRegistered(),await this.httpClient.callTool("my_task",{agentId:this.agentId})}async createTaskInstanceComment(e){this.ensureRegistered();const t={agentId:this.agentId,...e};return await this.httpClient.callTool("create_task_instance_comment",t)}async submitTaskResult(e,t,n){this.ensureRegistered();const i={agentId:this.agentId,nodeId:e,outputPayload:t};return n&&Array.isArray(n)&&n.length>0&&(i.changeLog=n),await this.httpClient.callTool("submit_task_result",i)}async startTaskRollback(e){return this.ensureRegistered(),await this.httpClient.callTool("start_task_rollback",{agentId:this.agentId,...e})}async finishTaskRollback(e){return this.ensureRegistered(),await this.httpClient.callTool("finish_task_rollback",{agentId:this.agentId,...e})}async rejectTask(e,t){return this.ensureRegistered(),await this.httpClient.callTool("reject_task",{agentId:this.agentId,nodeId:e,reason:t})}async terminateTask(e,t){return this.ensureRegistered(),await this.httpClient.callTool("terminate_task",{agentId:this.agentId,taskInstanceId:e,reason:t})}start(e,t){if(this.isRunning){s.warn("[AgentClient] \u6D88\u606F\u5FAA\u73AF\u5DF2\u5728\u8FD0\u884C\u4E2D");return}this.isDegradedMode||this.ensureRegistered(),this.messageHandler=e,this.profileHandler=t?.profileHandler||null,this.isRunning=!0,s.info(`[AgentClient] start() \u88AB\u8C03\u7528\uFF0CcachedProfile: ${this.cachedProfile?"\u5B58\u5728":"\u4E0D\u5B58\u5728"}, profileHandler: ${this.profileHandler?"\u5DF2\u8BBE\u7F6E":"\u672A\u8BBE\u7F6E"}, \u964D\u7EA7\u6A21\u5F0F: ${this.isDegradedMode?"\u662F":"\u5426"}`),this.cachedProfile&&this.profileHandler&&(s.info(`[AgentClient] \u5904\u7406\u7F13\u5B58\u7684 Profile \u4FE1\u606F: ${this.cachedProfile.displayName}`),this.profileHandler(this.cachedProfile),this.cachedProfile=null),t?.pollMode??!1?(s.warn("[AgentClient] \u542F\u52A8\u6D88\u606F\u4E3B\u5FAA\u73AF\uFF08HTTP\u8F6E\u8BE2\u6A21\u5F0F - \u4E0D\u63A8\u8350\uFF09"),this.messageLoop()):s.info("[AgentClient] \u542F\u52A8\u6D88\u606F\u4E3B\u5FAA\u73AF\uFF08WebSocket\u63A8\u9001\u6A21\u5F0F - \u63A8\u8350\uFF09")}stop(){this.isRunning=!1,this.pollTimer&&(clearTimeout(this.pollTimer),this.pollTimer=null),this.stopRuntimeTokenRefresh(),s.info("[AgentClient] \u6D88\u606F\u4E3B\u5FAA\u73AF\u5DF2\u505C\u6B62")}async messageLoop(){for(;this.isRunning;)try{await this.delay(p)}catch(e){s.error("[AgentClient] \u6D88\u606F\u5FAA\u73AF\u9519\u8BEF:",e),await this.delay(5e3)}}handleIncomingDm(e){e.senderId!==this.agentId&&this.processMessage(e)}handleIncomingGroup(e){e.senderId!==this.agentId&&this.processMessage(e)}handleProfileInfo(e){s.info(`[AgentClient] \u6536\u5230 Profile \u4FE1\u606F: ${e.displayName} (${e.roleName})`),e.projectName&&(this.projectName=e.projectName,s.info(`[AgentClient] \u66F4\u65B0\u6240\u5C5E\u9879\u76EE: ${this.projectName}`)),e.roleName&&e.roleName!==this.agentConfig.roleName&&(s.info(`[AgentClient] \u540C\u6B65\u89D2\u8272\u540D: "${this.agentConfig.roleName||"(\u7A7A)"}" -> "${e.roleName}"`),this.agentConfig.roleName=e.roleName),e.roleName&&f(e.roleName,e.instanceName||this.agentId||""),this.profileHandler?this.profileHandler(e):(s.info("[AgentClient] profileHandler \u672A\u8BBE\u7F6E\uFF0C\u7F13\u5B58 Profile \u4FE1\u606F"),this.cachedProfile=e)}async processMessage(e){if(!this.messageHandler)return;const t=typeof e.msgId=="string";s.info(`[AgentClient] \u6536\u5230${t?"\u79C1\u4FE1":"\u7FA4\u6D88\u606F"}\u6765\u81EA ${e.senderName}: ${e.content.substring(0,50)}...`);try{const n=await this.messageHandler(e);if(t){const i=e;i.requireReply&&i.callId&&await this.replyToCall(i.callId,i.senderId,n||"\u5DF2\u6536\u5230\u6D88\u606F\uFF0C\u6B63\u5728\u5904\u7406\u4E2D...")}}catch(n){const i=typeof e.msgId=="string";if(s.error("[AgentClient] \u5904\u7406\u6D88\u606F\u5931\u8D25: type=%s, senderId=%s, senderName=%s, msgId=%s, error=%s",i?"\u79C1\u4FE1":"\u7FA4\u6D88\u606F",e.senderId,e.senderName,e.msgId,n instanceof Error?n.message:String(n)),i){const r=e;r.requireReply&&r.callId&&await this.replyToCall(r.callId,r.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,projectName:this.projectName,isConnected:this.wsClient.isConnected(),isRunning:this.isRunning}}getAgentConfig(){return this.agentConfig}reloadConfig(){g.loadConfig(),this.agentConfig=g.getAgentConfig(),s.info(`[AgentClient] \u914D\u7F6E\u5DF2\u91CD\u65B0\u52A0\u8F7D\uFF0C\u89D2\u8272: ${this.agentConfig.roleName}`)}enterDegradedMode(){this.isDegradedMode=!0,s.warn("[AgentClient] \u8FDB\u5165\u964D\u7EA7\u6A21\u5F0F\uFF0C\u5C06\u5728\u540E\u53F0\u6301\u7EED\u5C1D\u8BD5\u91CD\u8FDE")}exitDegradedMode(){this.isDegradedMode=!1,s.info("[AgentClient] \u9000\u51FA\u964D\u7EA7\u6A21\u5F0F")}isInDegradedMode(){return this.isDegradedMode}async retryRegistrationInBackground(e,t){let n=0;(async()=>{for(;this.isDegradedMode;)try{s.info(`[AgentClient] \u964D\u7EA7\u6A21\u5F0F\uFF1A\u5C1D\u8BD5\u91CD\u65B0\u6CE8\u518C (${n+1}/${t===-1?"\u65E0\u9650":t})`);const r=await this.register();s.info(`[AgentClient] \u964D\u7EA7\u6A21\u5F0F\uFF1A\u6CE8\u518C\u6210\u529F - ${r.displayName} (${r.agentId})`),this.exitDegradedMode(),this.messageHandler&&this.start(this.messageHandler);return}catch(r){n++;const o=r instanceof Error?r.message:String(r);if(s.warn(`[AgentClient] \u964D\u7EA7\u6A21\u5F0F\uFF1A\u6CE8\u518C\u5931\u8D25 (${n}/${t===-1?"\u65E0\u9650":t}): ${o}`),t>0&&n>=t){s.error("[AgentClient] \u964D\u7EA7\u6A21\u5F0F\uFF1A\u8FBE\u5230\u6700\u5927\u91CD\u8BD5\u6B21\u6570\uFF0C\u505C\u6B62\u91CD\u8FDE"),this.isDegradedMode=!1;return}await new Promise(h=>setTimeout(h,e))}})().catch(r=>{s.error("[AgentClient] \u964D\u7EA7\u6A21\u5F0F\u540E\u53F0\u91CD\u8BD5\u5FAA\u73AF\u5F02\u5E38\u9000\u51FA: error=%s, stack=%s",r instanceof Error?r.message:String(r),r instanceof Error?r.stack:"(no stack)")})}initializeStatusReporter(){if(!this.agentId){s.warn("[AgentClient] \u65E0\u6CD5\u521D\u59CB\u5316\u72B6\u6001\u62A5\u544A\u5668\uFF1AagentId \u4E3A\u7A7A");return}this.statusReporter=new y({agentId:this.agentId,sendStatusUpdate:e=>{this.wsClient.send({type:"AGENT_STATUS",data:e,timestamp:new Date().toISOString()})}}),C(e=>this.reportMcpNodeLog(e)),this.startRuntimeTokenRefresh(),s.info("[AgentClient] \u72B6\u6001\u62A5\u544A\u5668\u5DF2\u521D\u59CB\u5316")}startRuntimeTokenRefresh(){this.stopRuntimeTokenRefresh();const e=this.serverConfig.runtimeTokenRefreshIntervalMs;if(!e||e<=0){s.warn("[AgentClient] runtimeTokenRefreshIntervalMs \u672A\u914D\u7F6E\u6216\u65E0\u6548\uFF0C\u8DF3\u8FC7\u4E3B\u52A8\u7EED\u671F");return}const t=this.agentId;if(!t){s.warn("[AgentClient] agentId \u4E3A\u7A7A\uFF0C\u8DF3\u8FC7\u4E3B\u52A8\u7EED\u671F");return}this.runtimeTokenRefreshTimer=setInterval(async()=>{try{await this.httpClient.refreshRuntimeAccessToken(t)&&s.info("[AgentClient] runtimeAccessToken \u5DF2\u4E3B\u52A8\u7EED\u671F")}catch(n){s.warn("[AgentClient] \u4E3B\u52A8\u7EED\u671F runtimeAccessToken \u5931\u8D25: %s",n instanceof Error?n.message:String(n)),n instanceof Error&&n.stack&&s.warn("[AgentClient] \u4E3B\u52A8\u7EED\u671F\u5F02\u5E38\u5806\u6808:",n.stack)}},e),s.info(`[AgentClient] runtime token \u4E3B\u52A8\u7EED\u671F\u5DF2\u542F\u52A8\uFF0C\u95F4\u9694 ${e}ms`)}stopRuntimeTokenRefresh(){this.runtimeTokenRefreshTimer&&(clearInterval(this.runtimeTokenRefreshTimer),this.runtimeTokenRefreshTimer=null)}reportMcpNodeLog(e){const t=this.wsClient;!this.agentId||!this.wsClient.isConnected()||typeof t.sendMcpNodeLog!="function"||t.sendMcpNodeLog(e)}getStatusReporter(){return this.statusReporter}}export{_ as AgentClient};
|
|
1
|
+
import{configManager as g}from"./config.js";import{MESSAGE_POLL_INTERVAL_MS as p}from"./constants.js";import{HttpClient as m}from"./http-client.js";import{logger as s,setMcpNodeLogSink as C,updateStartupLogIdentity as f}from"./logger.js";import{claimRuntimeLaunchBinding as I}from"./runtime-launch-binding.js";import{StatusReporter as y}from"./status-reporter.js";import{WebSocketClient as u}from"./websocket-client.js";class _{wsClient;httpClient;agentConfig;serverConfig;agentId=null;displayName=null;projectName=null;isRunning=!1;isDegradedMode=!1;messageHandler=null;profileHandler=null;pollTimer=null;statusReporter=null;newCharacterHandler=null;runtimeTokenRefreshTimer=null;cachedProfile=null;constructor(){g.loadConfig(),this.agentConfig=g.getAgentConfig(),this.serverConfig=g.getServerConfig(),this.wsClient=new u(this.serverConfig),this.httpClient=new m(this.serverConfig),this.setupWebSocketListeners()}async initialize(){const e=await I(this.agentConfig,this.serverConfig);if(!e){this.serverConfig.runtimeBridgeBaseUrl=void 0;return}g.applyRuntimeLaunchBinding(e),this.agentConfig=g.getAgentConfig(),this.serverConfig=g.getServerConfig(),this.wsClient=new u(this.serverConfig),this.httpClient=new m(this.serverConfig),this.setupWebSocketListeners()}setupWebSocketListeners(){this.wsClient.on("directMessage",e=>{this.handleIncomingDm(e)}),this.wsClient.on("groupMessage",e=>{this.handleIncomingGroup(e)}),this.wsClient.on("profileInfo",e=>{s.info(`[AgentClient] WebSocket profileInfo \u4E8B\u4EF6\u89E6\u53D1\uFF0CdisplayName: ${e.displayName}`),this.handleProfileInfo(e)}),this.wsClient.on("agentStatus",e=>{s.info(`[AgentClient] WebSocket agentStatus \u4E8B\u4EF6\u89E6\u53D1: ${e.status}`)}),this.wsClient.on("disconnected",(e,t)=>{const n=t?.toString()||"";s.warn("[AgentClient] WebSocket \u65AD\u5F00\u8FDE\u63A5: code=%s, reason=%s, agentId=%s, \u6B63\u5728\u81EA\u52A8\u91CD\u8FDE",e,n,this.agentId)}),this.wsClient.on("error",e=>{s.error("[AgentClient] WebSocket \u9519\u8BEF: %s, stack=%s",e.message,e.stack)}),this.wsClient.on("reconnectFailed",()=>{s.error("[AgentClient] \u91CD\u8FDE\u5931\u8D25\uFF08\u5DF2\u8FBE\u91CD\u8BD5\u4E0A\u9650\uFF09\uFF0C\u505C\u6B62\u6D88\u606F\u5FAA\u73AF, agentId=%s",this.agentId),this.stop()})}async register(){return s.info("[AgentClient] \u6B63\u5728\u6CE8\u518C Agent..."),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(i){throw s.error("[AgentClient] getProfileByAgentId \u5931\u8D25 (presetAgentId=%s): %s",this.agentId,i instanceof Error?i.message:String(i)),i}this.displayName=t.displayName,this.projectName=t.projectName||null,s.info(`[AgentClient] \u4F7F\u7528\u9884\u8BBE AgentID \u7ED1\u5B9A\u5B9E\u4F8B: ${this.displayName} (${this.agentId})`),s.info(`[AgentClient] \u6240\u5C5E\u9879\u76EE: ${this.projectName||"(\u672A\u8BBE\u7F6E)"}`);try{await this.wsClient.connect(this.agentId)}catch(i){throw s.error("[AgentClient] WebSocket \u8FDE\u63A5\u5931\u8D25 (agentId=%s): %s",this.agentId,i instanceof Error?i.message:String(i)),i}s.info("[AgentClient] WebSocket \u8FDE\u63A5\u5DF2\u5EFA\u7ACB\uFF0CAgent \u73B0\u5728\u5DF2\u4E0A\u7EBF"),this.initializeStatusReporter();const n=await this.getProfileByAgentId(this.agentId);return this.displayName=n.displayName,this.projectName=n.projectName||null,f(n.roleName||"unknown-role",n.instanceName||this.agentId),{agentId:this.agentId,displayName:this.displayName,status:n.isOnline?"online":"offline",projectName:n.projectName,workspacePath:n.workspacePath,runtimeStatus:n.runtimeStatus,runtimeSessionId:n.runtimeSessionId}}async registerAsNewAgent(){const e=await this.httpClient.callTool("register",{roleName:this.agentConfig.roleName,projectName:this.agentConfig.projectName,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.projectName=e.projectName||null,f(this.agentConfig.roleName||"unknown-role",e.instanceName||t),s.info(`[AgentClient] \u6CE8\u518C\u6210\u529F: ${this.displayName} (${this.agentId})`),s.info(`[AgentClient] \u72B6\u6001: ${e.status}`),s.info(`[AgentClient] \u6240\u5C5E\u9879\u76EE: ${this.projectName||"(\u672A\u8BBE\u7F6E)"}`),await this.wsClient.connect(this.agentId),s.info("[AgentClient] WebSocket \u8FDE\u63A5\u5DF2\u5EFA\u7ACB\uFF0CAgent \u73B0\u5728\u5DF2\u4E0A\u7EBF"),this.initializeStatusReporter(),e.isExisting===!1&&this.newCharacterHandler&&this.newCharacterHandler(),e}async unregister(){s.info("[AgentClient] \u6B63\u5728\u6CE8\u9500 Agent..."),this.agentId&&await this.httpClient.callTool("unregister",{agentId:this.agentId}),this.stopRuntimeTokenRefresh(),this.wsClient.disconnect(),this.agentId=null,this.displayName=null,this.projectName=null,this.isRunning=!1,s.info("[AgentClient] \u5DF2\u6CE8\u9500")}async discoverColleagues(){return await this.httpClient.callTool("discover_colleague",{agentId:this.agentId})}async discoverGroupRooms(){return this.ensureRegistered(),await this.httpClient.callTool("discover_group_rooms",{agentId:this.agentId})}async hireColleague(e){return this.ensureRegistered(),await this.httpClient.callTool("hire_colleague",{agentId:this.agentId,...e})}async hireColleaguesBatch(e){return this.ensureRegistered(),await this.httpClient.callTool("hire_colleagues_batch",{agentId:this.agentId,...e})}async callAgentScopedTool(e,t){return this.ensureRegistered(),await this.httpClient.callTool(e,{agentId:this.agentId,...t})}async reportMemoryStats(e){await this.callAgentScopedTool("report_memory_stats",{memoryStats:e})}async sendGroupMessage(e,t,n){this.ensureRegistered();const i=t||this.projectName||this.agentConfig.projectName;return await this.httpClient.callTool("send_group_message",{agentId:this.agentId,projectName:i,roomId:n,content:e})}async sendDirectMessage(e,t,n=!1,i,r){this.ensureRegistered();const a={agentId:this.agentId,targetId:e,content:t,requireReply:n,waitReply:n,replyToCallId:i};if(typeof r=="number"&&r>0&&(a.timeoutMs=r),n){const h=typeof r=="number"&&r>0?r+3e4:0;return await this.httpClient.callToolOnce("send_dm",a,h)}return await this.httpClient.callTool("send_dm",a)}async sendCallAndWaitReply(e,t,n=6e4){const i=await this.sendDirectMessage(e,t,!0,void 0,n);if(i.reply)return i.reply;throw new Error("No reply received for call-style direct message before timeout")}async replyToCall(e,t,n){return await this.sendDirectMessage(t,n,!1,e)}async getDmHistory(e,t=50,n){this.ensureRegistered();const i={agentId:this.agentId,targetUserId:e,limit:t};return n&&(i.since=n),await this.httpClient.callTool("get_dm_history",i)}async getGroupHistory(e=50,t,n){if(this.ensureRegistered(),t){const o={projectName:this.projectName||this.agentConfig.projectName,roomId:t,limit:e};return n&&(o.since=n),await this.httpClient.callTool("get_group_history",o)}const i=await this.discoverGroupRooms(),r=this.projectName||this.agentConfig.projectName,a=this.collectRoomIds(i,r);if(a.length===0)return{messages:[],count:0};const c=(await Promise.all(a.map(async o=>{const l={projectName:r,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:c,count:c.length}}async fetchUnreadMessages(e={}){this.ensureRegistered();const t=this.projectName||this.agentConfig.projectName,n={agentId:this.agentId,blockIfEmpty:e.blockIfEmpty??!1};e.since&&(n.since=e.since),e.blockTimeoutMs&&e.blockTimeoutMs>0&&(n.blockTimeoutMs=e.blockTimeoutMs);const i=e.includePipelineTasks?"poll_message":"get_dm_messages",r=await this.fetchDirectMessagesWithRecovery(i,n),a=await this.discoverGroupRooms(),h=this.collectRoomIds(a,t),c=await Promise.all(h.map(async o=>{const l={agentId:this.agentId,projectName:t,roomId:o};e.since&&(l.since=e.since);try{return await this.httpClient.callTool("get_group_messages",l)}catch(d){return s.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(r.messages)?r.messages:[],groupMessages:c.flatMap(o=>this.normalizeGroupMessages(o)).sort((o,l)=>new Date(o.timestamp).getTime()-new Date(l.timestamp).getTime())}}async fetchBrowserListenerEvents(){const e=this.serverConfig.runtimeBridgeBaseUrl,t=this.agentId;if(!e||!t)return s.info("[AgentClient] fetchBrowserListenerEvents \u8DF3\u8FC7: bridgeBaseUrl=%s, agentId=%s",e||"(\u7A7A)",t||"(\u7A7A)"),[];try{const n=`${e}/runtime/browser-listeners/${encodeURIComponent(t)}/events`,i=this.serverConfig.runtimeAccessToken||"";s.debug("[AgentClient] \u62C9\u53D6\u76D1\u542C\u5668\u4E8B\u4EF6: url=%s, tokenLen=%d",n,i.length);const r=await fetch(n,{method:"GET",headers:{"X-Runtime-Token":i},signal:AbortSignal.timeout(3e3)});if(!r.ok)return s.warn("[AgentClient] \u62C9\u53D6\u76D1\u542C\u5668\u4E8B\u4EF6\u5931\u8D25: HTTP %s, url=%s",r.status,n),[];const a=await r.json();return!a.ok||!Array.isArray(a.events)?(s.warn("[AgentClient] \u62C9\u53D6\u76D1\u542C\u5668\u4E8B\u4EF6\u54CD\u5E94\u5F02\u5E38: ok=%s, eventsType=%s",a.ok,Array.isArray(a.events)?"array":typeof a.events),[]):(s.debug("[AgentClient] \u62C9\u53D6\u76D1\u542C\u5668\u4E8B\u4EF6\u6210\u529F: %d \u6761\u4E8B\u4EF6",a.events.length),a.events)}catch(n){return s.warn("[AgentClient] \u62C9\u53D6\u76D1\u542C\u5668\u4E8B\u4EF6\u5F02\u5E38: %s",n instanceof Error?n.message:String(n)),[]}}async fetchDirectMessagesWithRecovery(e,t){if(e==="poll_message")try{return await this.httpClient.callToolOnce(e,t)}catch(n){if(this.isRecoverableLongPollError(n))return s.warn("[AgentClient] poll_message \u5355\u6B21\u957F\u8F6E\u8BE2\u8D85\u65F6\uFF0C\u6309\u7A7A\u7ED3\u679C\u9000\u907F\u540E\u7EE7\u7EED\u7B49\u5F85:",n),{messages:[]};throw n}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(i=>i.projectName===t).map(i=>i.id);return Array.from(new Set(n))}async getProfile(){this.ensureRegistered();const e=this.agentId;if(!e)throw new Error("Agent is not registered");return{...await this.getProfileByAgentId(e),describe:this.agentConfig.describe}}async getProfileByAgentId(e){return await this.httpClient.callTool("get_profile",{agentId:e})}async getMyTasks(){return this.ensureRegistered(),await this.httpClient.callTool("my_task",{agentId:this.agentId})}async createTaskInstanceComment(e){this.ensureRegistered();const t={agentId:this.agentId,...e};return await this.httpClient.callTool("create_task_instance_comment",t)}async submitTaskResult(e,t,n){this.ensureRegistered();const i={agentId:this.agentId,nodeId:e,outputPayload:t};return n&&Array.isArray(n)&&n.length>0&&(i.changeLog=n),await this.httpClient.callTool("submit_task_result",i)}async startTaskRollback(e){return this.ensureRegistered(),await this.httpClient.callTool("start_task_rollback",{agentId:this.agentId,...e})}async finishTaskRollback(e){return this.ensureRegistered(),await this.httpClient.callTool("finish_task_rollback",{agentId:this.agentId,...e})}async rejectTask(e,t){return this.ensureRegistered(),await this.httpClient.callTool("reject_task",{agentId:this.agentId,nodeId:e,reason:t})}async terminateTask(e,t){return this.ensureRegistered(),await this.httpClient.callTool("terminate_task",{agentId:this.agentId,taskInstanceId:e,reason:t})}start(e,t){if(this.isRunning){s.warn("[AgentClient] \u6D88\u606F\u5FAA\u73AF\u5DF2\u5728\u8FD0\u884C\u4E2D");return}this.isDegradedMode||this.ensureRegistered(),this.messageHandler=e,this.profileHandler=t?.profileHandler||null,this.isRunning=!0,s.info(`[AgentClient] start() \u88AB\u8C03\u7528\uFF0CcachedProfile: ${this.cachedProfile?"\u5B58\u5728":"\u4E0D\u5B58\u5728"}, profileHandler: ${this.profileHandler?"\u5DF2\u8BBE\u7F6E":"\u672A\u8BBE\u7F6E"}, \u964D\u7EA7\u6A21\u5F0F: ${this.isDegradedMode?"\u662F":"\u5426"}`),this.cachedProfile&&this.profileHandler&&(s.info(`[AgentClient] \u5904\u7406\u7F13\u5B58\u7684 Profile \u4FE1\u606F: ${this.cachedProfile.displayName}`),this.profileHandler(this.cachedProfile),this.cachedProfile=null),t?.pollMode??!1?(s.warn("[AgentClient] \u542F\u52A8\u6D88\u606F\u4E3B\u5FAA\u73AF\uFF08HTTP\u8F6E\u8BE2\u6A21\u5F0F - \u4E0D\u63A8\u8350\uFF09"),this.messageLoop()):s.info("[AgentClient] \u542F\u52A8\u6D88\u606F\u4E3B\u5FAA\u73AF\uFF08WebSocket\u63A8\u9001\u6A21\u5F0F - \u63A8\u8350\uFF09")}stop(){this.isRunning=!1,this.pollTimer&&(clearTimeout(this.pollTimer),this.pollTimer=null),this.stopRuntimeTokenRefresh(),s.info("[AgentClient] \u6D88\u606F\u4E3B\u5FAA\u73AF\u5DF2\u505C\u6B62")}async messageLoop(){for(;this.isRunning;)try{await this.delay(p)}catch(e){s.error("[AgentClient] \u6D88\u606F\u5FAA\u73AF\u9519\u8BEF:",e),await this.delay(5e3)}}handleIncomingDm(e){e.senderId!==this.agentId&&this.processMessage(e)}handleIncomingGroup(e){e.senderId!==this.agentId&&this.processMessage(e)}handleProfileInfo(e){s.info(`[AgentClient] \u6536\u5230 Profile \u4FE1\u606F: ${e.displayName} (${e.roleName})`),e.projectName&&(this.projectName=e.projectName,s.info(`[AgentClient] \u66F4\u65B0\u6240\u5C5E\u9879\u76EE: ${this.projectName}`)),e.roleName&&e.roleName!==this.agentConfig.roleName&&(s.info(`[AgentClient] \u540C\u6B65\u89D2\u8272\u540D: "${this.agentConfig.roleName||"(\u7A7A)"}" -> "${e.roleName}"`),this.agentConfig.roleName=e.roleName),e.roleName&&f(e.roleName,e.instanceName||this.agentId||""),this.profileHandler?this.profileHandler(e):(s.info("[AgentClient] profileHandler \u672A\u8BBE\u7F6E\uFF0C\u7F13\u5B58 Profile \u4FE1\u606F"),this.cachedProfile=e)}async processMessage(e){if(!this.messageHandler)return;const t=typeof e.msgId=="string";s.info(`[AgentClient] \u6536\u5230${t?"\u79C1\u4FE1":"\u7FA4\u6D88\u606F"}\u6765\u81EA ${e.senderName}: ${e.content.substring(0,50)}...`);try{const n=await this.messageHandler(e);if(t){const i=e;i.requireReply&&i.callId&&await this.replyToCall(i.callId,i.senderId,n||"\u5DF2\u6536\u5230\u6D88\u606F\uFF0C\u6B63\u5728\u5904\u7406\u4E2D...")}}catch(n){const i=typeof e.msgId=="string";if(s.error("[AgentClient] \u5904\u7406\u6D88\u606F\u5931\u8D25: type=%s, senderId=%s, senderName=%s, msgId=%s, error=%s",i?"\u79C1\u4FE1":"\u7FA4\u6D88\u606F",e.senderId,e.senderName,e.msgId,n instanceof Error?n.message:String(n)),i){const r=e;r.requireReply&&r.callId&&await this.replyToCall(r.callId,r.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,projectName:this.projectName,isConnected:this.wsClient.isConnected(),isRunning:this.isRunning}}getAgentConfig(){return this.agentConfig}reloadConfig(){g.loadConfig(),this.agentConfig=g.getAgentConfig(),s.info(`[AgentClient] \u914D\u7F6E\u5DF2\u91CD\u65B0\u52A0\u8F7D\uFF0C\u89D2\u8272: ${this.agentConfig.roleName}`)}enterDegradedMode(){this.isDegradedMode=!0,s.warn("[AgentClient] \u8FDB\u5165\u964D\u7EA7\u6A21\u5F0F\uFF0C\u5C06\u5728\u540E\u53F0\u6301\u7EED\u5C1D\u8BD5\u91CD\u8FDE")}exitDegradedMode(){this.isDegradedMode=!1,s.info("[AgentClient] \u9000\u51FA\u964D\u7EA7\u6A21\u5F0F")}isInDegradedMode(){return this.isDegradedMode}async retryRegistrationInBackground(e,t){let n=0;(async()=>{for(;this.isDegradedMode;)try{s.info(`[AgentClient] \u964D\u7EA7\u6A21\u5F0F\uFF1A\u5C1D\u8BD5\u91CD\u65B0\u6CE8\u518C (${n+1}/${t===-1?"\u65E0\u9650":t})`);const r=await this.register();s.info(`[AgentClient] \u964D\u7EA7\u6A21\u5F0F\uFF1A\u6CE8\u518C\u6210\u529F - ${r.displayName} (${r.agentId})`),this.exitDegradedMode(),this.messageHandler&&this.start(this.messageHandler);return}catch(r){n++;const a=r instanceof Error?r.message:String(r);if(s.warn(`[AgentClient] \u964D\u7EA7\u6A21\u5F0F\uFF1A\u6CE8\u518C\u5931\u8D25 (${n}/${t===-1?"\u65E0\u9650":t}): ${a}`),t>0&&n>=t){s.error("[AgentClient] \u964D\u7EA7\u6A21\u5F0F\uFF1A\u8FBE\u5230\u6700\u5927\u91CD\u8BD5\u6B21\u6570\uFF0C\u505C\u6B62\u91CD\u8FDE"),this.isDegradedMode=!1;return}await new Promise(h=>setTimeout(h,e))}})().catch(r=>{s.error("[AgentClient] \u964D\u7EA7\u6A21\u5F0F\u540E\u53F0\u91CD\u8BD5\u5FAA\u73AF\u5F02\u5E38\u9000\u51FA: error=%s, stack=%s",r instanceof Error?r.message:String(r),r instanceof Error?r.stack:"(no stack)")})}initializeStatusReporter(){if(!this.agentId){s.warn("[AgentClient] \u65E0\u6CD5\u521D\u59CB\u5316\u72B6\u6001\u62A5\u544A\u5668\uFF1AagentId \u4E3A\u7A7A");return}this.statusReporter=new y({agentId:this.agentId,sendStatusUpdate:e=>{this.wsClient.send({type:"AGENT_STATUS",data:e,timestamp:new Date().toISOString()})}}),C(e=>this.reportMcpNodeLog(e)),this.startRuntimeTokenRefresh(),s.info("[AgentClient] \u72B6\u6001\u62A5\u544A\u5668\u5DF2\u521D\u59CB\u5316")}startRuntimeTokenRefresh(){this.stopRuntimeTokenRefresh();const e=this.serverConfig.runtimeTokenRefreshIntervalMs;if(!e||e<=0){s.warn("[AgentClient] runtimeTokenRefreshIntervalMs \u672A\u914D\u7F6E\u6216\u65E0\u6548\uFF0C\u8DF3\u8FC7\u4E3B\u52A8\u7EED\u671F");return}const t=this.agentId;if(!t){s.warn("[AgentClient] agentId \u4E3A\u7A7A\uFF0C\u8DF3\u8FC7\u4E3B\u52A8\u7EED\u671F");return}this.runtimeTokenRefreshTimer=setInterval(async()=>{try{await this.httpClient.refreshRuntimeAccessToken(t)&&s.info("[AgentClient] runtimeAccessToken \u5DF2\u4E3B\u52A8\u7EED\u671F")}catch(n){s.warn("[AgentClient] \u4E3B\u52A8\u7EED\u671F runtimeAccessToken \u5931\u8D25: %s",n instanceof Error?n.message:String(n)),n instanceof Error&&n.stack&&s.warn("[AgentClient] \u4E3B\u52A8\u7EED\u671F\u5F02\u5E38\u5806\u6808:",n.stack)}},e),s.info(`[AgentClient] runtime token \u4E3B\u52A8\u7EED\u671F\u5DF2\u542F\u52A8\uFF0C\u95F4\u9694 ${e}ms`)}stopRuntimeTokenRefresh(){this.runtimeTokenRefreshTimer&&(clearInterval(this.runtimeTokenRefreshTimer),this.runtimeTokenRefreshTimer=null)}reportMcpNodeLog(e){const t=this.wsClient;!this.agentId||!this.wsClient.isConnected()||typeof t.sendMcpNodeLog!="function"||t.sendMcpNodeLog(e)}getStatusReporter(){return this.statusReporter}}export{_ as AgentClient};
|
|
2
2
|
|
|
@@ -24,6 +24,8 @@ export declare function updateStartupLogIdentity(roleName: string, instanceName:
|
|
|
24
24
|
|
|
25
25
|
export declare function setMcpNodeLogSink(sink: McpNodeLogSink | null): void;
|
|
26
26
|
export declare const logger: {
|
|
27
|
+
|
|
28
|
+
debug: (..._args: unknown[]) => void;
|
|
27
29
|
info: (...args: unknown[]) => void;
|
|
28
30
|
warn: (...args: unknown[]) => void;
|
|
29
31
|
error: (...args: unknown[]) => void;
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import*as l from"node:fs";import*as m from"node:os";import*as i from"node:path";import{format as p}from"node:util";const d=new Date,E=new Set(["0","false","off","no"]),S=200,L="aws-mcp-node";let t,c=null,g=null;const u=[];function s(e,n=2){return String(e).padStart(n,"0")}function M(e){return`${e.getFullYear()}-${s(e.getMonth()+1)}`}function N(e){return[s(e.getDate()),"-",s(e.getHours()),s(e.getMinutes()),s(e.getSeconds()),s(e.getMilliseconds(),3)].join("")}function _(e){const n=new RegExp("[\0-]","g");return e.replace(/[<>:"/\\|?*]/g,"_").replace(n,"_").replace(/\s+/g," ").trim().replace(/[. ]+$/g,"")||"workspace"}function h(e={}){const n=e.logDir||i.join(e.homeDir||m.homedir(),".aws-bridge","log"),r=_(e.roleName||process.env.AWS_ROLE_NAME||"unknown-role"),o=_(e.instanceName||process.env.AWS_AGENT_ID||"unknown-instance"),a=e.startupTime||d,w=M(a),D=`${N(a)}.log`;return i.join(n,"agent",L,`${r}-${o}`,w,D)}function F(){if(t!==void 0)return t;const e=String(process.env.AWS_MCP_FILE_LOG||"").trim().toLowerCase();if(E.has(e))return t=null,null;try{return c=process.env.AWS_MCP_LOG_DIR||void 0||i.join(m.homedir(),".aws-bridge","log"),t=h({logDir:c,roleName:process.env.AWS_ROLE_NAME||void 0,instanceName:process.env.AWS_AGENT_ID||void 0}),l.mkdirSync(i.dirname(t),{recursive:!0}),t}catch(n){return t=null,c=null,console.warn("[Logger] \u65E0\u6CD5\u521B\u5EFA MCP \u542F\u52A8\u65E5\u5FD7\u6587\u4EF6:",n),null}}function $(e,n){if(t==null||!c)return;const r=t,o=h({logDir:c,roleName:e,instanceName:n,startupTime:d});if(r!==o)try{l.mkdirSync(i.dirname(o),{recursive:!0}),l.renameSync(r,o),t=o,console.log(`[Logger] MCP \u542F\u52A8\u65E5\u5FD7\u8DEF\u5F84\u5DF2\u66F4\u65B0: ${r} -> ${o}`);const a=i.join(c,"agent",L);A(i.dirname(r),a)}catch(a){console.warn("[Logger] \u65E0\u6CD5\u66F4\u65B0 MCP \u542F\u52A8\u65E5\u5FD7\u8EAB\u4EFD\u6807\u8BC6:",a)}}function A(e,n){let r=i.normalize(e);const o=i.normalize(n),a=i.parse(r).root;for(;r!==o&&r!==a;){try{l.rmdirSync(r)}catch{break}r=i.dirname(r)}}function P(e,n){if(t===void 0)return;const r=t;if(!r)return;const o=`${new Date().toISOString()} [${e.toUpperCase()}] ${p(...n)}
|
|
2
|
-
`;try{l.appendFileSync(r,o,"utf8")}catch(a){t=null,console.warn("[Logger] \u65E0\u6CD5\u5199\u5165 MCP \u542F\u52A8\u65E5\u5FD7\u6587\u4EF6:",a)}}function f(e,n){const r={level:e,message:p(...n),timestamp:new Date().toISOString()};switch(e){case"info":console.error(...n);break;case"warn":console.warn(...n);break;case"error":console.error(...n);break}P(e,n),C(r)}function I(e){if(g=e,!!e)for(const n of u)e(n)}function C(e){u.push(e),u.length>S&&u.splice(0,u.length-S),g&&g(e)}const O={info:(...e)=>f("info",e),warn:(...e)=>f("warn",e),error:(...e)=>f("error",e)};export{h as buildStartupLogFilePath,N as formatLogFileTimestamp,M as formatLogYearMonth,F as initializeStartupLogFile,O as logger,_ as sanitizeLogFileNameSegment,I as setMcpNodeLogSink,$ as updateStartupLogIdentity};
|
|
2
|
+
`;try{l.appendFileSync(r,o,"utf8")}catch(a){t=null,console.warn("[Logger] \u65E0\u6CD5\u5199\u5165 MCP \u542F\u52A8\u65E5\u5FD7\u6587\u4EF6:",a)}}function f(e,n){const r={level:e,message:p(...n),timestamp:new Date().toISOString()};switch(e){case"info":console.error(...n);break;case"warn":console.warn(...n);break;case"error":console.error(...n);break}P(e,n),C(r)}function I(e){if(g=e,!!e)for(const n of u)e(n)}function C(e){u.push(e),u.length>S&&u.splice(0,u.length-S),g&&g(e)}const O={debug:(...e)=>{},info:(...e)=>f("info",e),warn:(...e)=>f("warn",e),error:(...e)=>f("error",e)};export{h as buildStartupLogFilePath,N as formatLogFileTimestamp,M as formatLogYearMonth,F as initializeStartupLogFile,O as logger,_ as sanitizeLogFileNameSegment,I as setMcpNodeLogSink,$ as updateStartupLogIdentity};
|
|
3
3
|
|
|
@@ -159,6 +159,12 @@ export declare class McpServer {
|
|
|
159
159
|
private handleGetMessage;
|
|
160
160
|
|
|
161
161
|
private hydrateUnreadMessagesFromServer;
|
|
162
|
+
|
|
163
|
+
private hydrateBrowserListenerEvents;
|
|
164
|
+
|
|
165
|
+
private buildListenerEventNotification;
|
|
166
|
+
|
|
167
|
+
private formatChangeType;
|
|
162
168
|
private handleGetDmHistory;
|
|
163
169
|
private handleGetGroupHistory;
|
|
164
170
|
private handleSubmitTaskResult;
|
|
@@ -182,6 +188,8 @@ export declare class McpServer {
|
|
|
182
188
|
private sanitizeAgentIdForTodoFile;
|
|
183
189
|
|
|
184
190
|
private buildTodoReminderNotification;
|
|
191
|
+
|
|
192
|
+
private buildBackgroundTaskNotification;
|
|
185
193
|
start(): Promise<void>;
|
|
186
194
|
|
|
187
195
|
private startLeaseRenewal;
|