aws-runtime-bridge 1.5.0 → 1.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (62) hide show
  1. package/README.md +1 -1
  2. package/dist/adapter/AdapterRegistry.d.ts +1 -1
  3. package/dist/adapter/AdapterRegistry.d.ts.map +1 -1
  4. package/dist/adapter/AdapterRegistry.js +0 -2
  5. package/dist/adapter/ClaudeSdkAdapter.d.ts +4 -0
  6. package/dist/adapter/ClaudeSdkAdapter.d.ts.map +1 -1
  7. package/dist/adapter/ClaudeSdkAdapter.js +11 -2
  8. package/dist/adapter/CodexSdkAdapter.js +1 -1
  9. package/dist/adapter/OpencodeSdkAdapter.js +2 -2
  10. package/dist/adapter/types.d.ts +10 -0
  11. package/dist/adapter/types.d.ts.map +1 -1
  12. package/dist/index.js +14 -43
  13. package/dist/middleware/auth.d.ts +5 -0
  14. package/dist/middleware/auth.d.ts.map +1 -1
  15. package/dist/middleware/auth.js +9 -1
  16. package/dist/routes/file-browser.d.ts.map +1 -1
  17. package/dist/routes/file-browser.js +21 -1
  18. package/dist/routes/file-browser.test.js +9 -0
  19. package/dist/routes/instance.d.ts +10 -0
  20. package/dist/routes/instance.d.ts.map +1 -1
  21. package/dist/routes/instance.js +93 -2
  22. package/dist/routes/instance.test.js +50 -0
  23. package/dist/routes/pty.d.ts +106 -0
  24. package/dist/routes/pty.d.ts.map +1 -0
  25. package/dist/routes/pty.js +526 -0
  26. package/dist/routes/pty.test.d.ts +2 -0
  27. package/dist/routes/pty.test.d.ts.map +1 -0
  28. package/dist/routes/pty.test.js +73 -0
  29. package/dist/routes/sessions.d.ts +1 -1
  30. package/dist/routes/sessions.d.ts.map +1 -1
  31. package/dist/routes/sessions.js +32 -213
  32. package/dist/routes/terminal.d.ts +32 -3
  33. package/dist/routes/terminal.d.ts.map +1 -1
  34. package/dist/routes/terminal.js +411 -243
  35. package/dist/routes/terminal.test.js +105 -29
  36. package/dist/services/agent-process-manager.d.ts +2 -2
  37. package/dist/services/agent-process-manager.d.ts.map +1 -1
  38. package/dist/services/agent-process-manager.js +3 -3
  39. package/dist/services/process-detector.d.ts +2 -4
  40. package/dist/services/process-detector.d.ts.map +1 -1
  41. package/dist/services/process-detector.js +9 -16
  42. package/dist/services/process-registry.d.ts +2 -2
  43. package/dist/services/process-registry.d.ts.map +1 -1
  44. package/dist/services/process-registry.js +1 -1
  45. package/dist/services/session-output.d.ts +15 -5
  46. package/dist/services/session-output.d.ts.map +1 -1
  47. package/dist/services/session-output.js +33 -3
  48. package/dist/services/session-output.test.js +43 -29
  49. package/dist/services/terminal-persistence.d.ts +9 -0
  50. package/dist/services/terminal-persistence.d.ts.map +1 -1
  51. package/dist/services/terminal-persistence.js +20 -0
  52. package/dist/services/tool-installer.d.ts +10 -0
  53. package/dist/services/tool-installer.d.ts.map +1 -1
  54. package/dist/services/tool-installer.js +126 -5
  55. package/dist/services/tool-installer.test.js +32 -1
  56. package/dist/services/workspace-files.d.ts +14 -0
  57. package/dist/services/workspace-files.d.ts.map +1 -1
  58. package/dist/services/workspace-files.js +52 -0
  59. package/dist/services/workspace-files.test.js +85 -1
  60. package/dist/types.d.ts +8 -4
  61. package/dist/types.d.ts.map +1 -1
  62. package/package.json +2 -1
package/README.md CHANGED
@@ -58,7 +58,7 @@ If an existing runtime binding still stores an old scheduler URL such as `http:/
58
58
  `aws-runtime-bridge` 命令仍作为兼容别名保留。安装 `aws-runtime-bridge` 后,包内会随附
59
59
  `aws-client-agent-mcp` 的编译产物;bridge 启动时只负责准备该 MCP 产物,不再在 Agent 启动时默认动态注入 `aws-mcp`。
60
60
 
61
- 请在面板中为目标运行时安装/配置 MCP;这样 Claude Code、Codex、OpenCode、PTY 等不同启动模式都走一致的持久化 MCP 配置链路。
61
+ 请在面板中为目标运行时安装/配置 MCP;这样 Claude Code、Codex、OpenCode SDK 启动模式都走一致的持久化 MCP 配置链路。
62
62
 
63
63
  如需使用自定义 MCP 可执行文件,可设置:
64
64
 
@@ -2,7 +2,7 @@
2
2
  * Adapter 注册表 —— 管理 Provider ID → Adapter 实例的映射
3
3
  */
4
4
  import type { BaseProviderAdapter } from './types.js';
5
- export type AdapterType = 'claude-sdk' | 'codex-sdk' | 'opencode-sdk' | 'pty';
5
+ export type AdapterType = 'claude-sdk' | 'codex-sdk' | 'opencode-sdk';
6
6
  /**
7
7
  * Adapter 注册表
8
8
  * 管理所有 Provider Adapter 实例的生命周期
@@ -1 +1 @@
1
- {"version":3,"file":"AdapterRegistry.d.ts","sourceRoot":"","sources":["../../src/adapter/AdapterRegistry.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAEtD,MAAM,MAAM,WAAW,GAAG,YAAY,GAAG,WAAW,GAAG,cAAc,GAAG,KAAK,CAAC;AAE9E;;;GAGG;AACH,qBAAa,eAAe;IAC1B,OAAO,CAAC,QAAQ,CAA+C;IAE/D;;;;OAIG;IACH,QAAQ,CAAC,OAAO,EAAE,mBAAmB,GAAG,IAAI;IAO5C;;;;OAIG;IACH,GAAG,CAAC,UAAU,EAAE,MAAM,GAAG,mBAAmB;IAU5C;;;;OAIG;IACH,SAAS,CAAC,WAAW,EAAE,WAAW,GAAG,mBAAmB;IASxD;;;OAGG;IACH,GAAG,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO;IAIhC;;OAEG;IACH,gBAAgB,IAAI,MAAM,EAAE;IAI5B;;OAEG;IACH,MAAM,IAAI,mBAAmB,EAAE;IAI/B;;OAEG;IACH,OAAO,IAAI,IAAI;IAWf;;OAEG;IACH,OAAO,CAAC,SAAS;CAclB;AAGD,eAAO,MAAM,eAAe,iBAAwB,CAAC"}
1
+ {"version":3,"file":"AdapterRegistry.d.ts","sourceRoot":"","sources":["../../src/adapter/AdapterRegistry.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAEtD,MAAM,MAAM,WAAW,GAAG,YAAY,GAAG,WAAW,GAAG,cAAc,CAAC;AAEtE;;;GAGG;AACH,qBAAa,eAAe;IAC1B,OAAO,CAAC,QAAQ,CAA+C;IAE/D;;;;OAIG;IACH,QAAQ,CAAC,OAAO,EAAE,mBAAmB,GAAG,IAAI;IAO5C;;;;OAIG;IACH,GAAG,CAAC,UAAU,EAAE,MAAM,GAAG,mBAAmB;IAU5C;;;;OAIG;IACH,SAAS,CAAC,WAAW,EAAE,WAAW,GAAG,mBAAmB;IASxD;;;OAGG;IACH,GAAG,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO;IAIhC;;OAEG;IACH,gBAAgB,IAAI,MAAM,EAAE;IAI5B;;OAEG;IACH,MAAM,IAAI,mBAAmB,EAAE;IAI/B;;OAEG;IACH,OAAO,IAAI,IAAI;IAWf;;OAEG;IACH,OAAO,CAAC,SAAS;CAYlB;AAGD,eAAO,MAAM,eAAe,iBAAwB,CAAC"}
@@ -89,8 +89,6 @@ export class AdapterRegistry {
89
89
  return providerId === 'codex';
90
90
  case 'opencode-sdk':
91
91
  return providerId === 'opencode';
92
- case 'pty':
93
- return providerId === 'pty';
94
92
  default:
95
93
  return false;
96
94
  }
@@ -73,6 +73,10 @@ export declare class ClaudeSdkAdapter extends EventEmitter implements BaseProvid
73
73
  private isTaskPollingIdleCommand;
74
74
  private isMessagePollingIdleCommand;
75
75
  private buildMessagePollingIdlePrompt;
76
+ /**
77
+ * 发送手动快捷键 token 序列,和空闲自动命令共用解析逻辑。
78
+ */
79
+ sendShortcutInput(sessionId: string, command: string): Promise<void>;
76
80
  /**
77
81
  * 执行空闲命令(支持 [enter], [wait:n] 等 token)
78
82
  */
@@ -1 +1 @@
1
- {"version":3,"file":"ClaudeSdkAdapter.d.ts","sourceRoot":"","sources":["../../src/adapter/ClaudeSdkAdapter.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ClaudeSdkAdapter.d.ts","sourceRoot":"","sources":["../../src/adapter/ClaudeSdkAdapter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAGH,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAMtC,OAAO,KAAK,EACV,mBAAmB,EACnB,oBAAoB,EAGpB,mBAAmB,EACnB,aAAa,EACd,MAAM,YAAY,CAAC;AAwHpB;;GAEG;AACH,qBAAa,gBAAiB,SAAQ,YAAa,YAAW,mBAAmB;IAC/E,QAAQ,CAAC,UAAU,iBAAiB;IACpC,QAAQ,CAAC,WAAW,iBAAiB;IAErC,OAAO,CAAC,QAAQ,CAA0C;IAC1D,OAAO,CAAC,UAAU,CAAoC;IACtD,OAAO,CAAC,YAAY,CAAuD;IAC3E,OAAO,CAAC,gBAAgB,CAA2C;IACnE,OAAO,CAAC,SAAS,CAAiB;IAGlC,OAAO,CAAC,kBAAkB,CAGZ;IAGd,OAAO,CAAC,gBAAgB,CAGV;IAGd,OAAO,CAAC,gBAAgB,CAAkC;IAG1D,OAAO,CAAC,eAAe,CAA0D;IAGjF,OAAO,CAAC,gBAAgB,CAAkC;IAIpD,YAAY,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,oBAAoB,GAAG,OAAO,CAAC,IAAI,CAAC;IAyF5E,WAAW,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAwCpE;;;OAGG;IACH,OAAO,CAAC,mBAAmB;IAmDrB,gBAAgB,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAYnE,kBAAkB,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAqBrF,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAOlD,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IA+BxD,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,mBAAmB,EAAE;IAIzD,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO;IAItC,oBAAoB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAI3D,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,aAAa,GAAG,SAAS;IAI9D,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAIpD,OAAO,IAAI,IAAI;IAoBf,OAAO,CAAC,YAAY,CAAiF;IACrG,OAAO,CAAC,UAAU,CAA0C;IAC5D,OAAO,CAAC,cAAc,CAAkC;IAExD;;OAEG;IACH,eAAe,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE;QAAE,gBAAgB,EAAE,MAAM,CAAC;QAAC,eAAe,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;IASzG;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAuB1B;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAQzB;;OAEG;IACH,OAAO,CAAC,cAAc;IAuCtB;;OAEG;IACH,OAAO,CAAC,cAAc;IAqBtB,OAAO,CAAC,wBAAwB;IAShC,OAAO,CAAC,2BAA2B;IAUnC,OAAO,CAAC,6BAA6B;IAIrC;;OAEG;IACG,iBAAiB,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAI1E;;OAEG;YACW,kBAAkB;IA+DhC;;OAEG;IACH,OAAO,CAAC,cAAc;IAItB;;;OAGG;IACG,aAAa,CACjB,SAAS,EAAE,MAAM,EACjB,iBAAiB,EAAE,MAAM,EACzB,MAAM,EAAE,oBAAoB,GAC3B,OAAO,CAAC,IAAI,CAAC;YAyBF,OAAO;IAarB;;;OAGG;IACH,OAAO,CAAC,oBAAoB;IA8F5B;;OAEG;IACH,OAAO,CAAC,wBAAwB;IAMhC;;OAEG;IACH,OAAO,CAAC,yBAAyB;IAsCjC,OAAO,CAAC,wBAAwB;IAYhC,OAAO,CAAC,+BAA+B;IAIvC,OAAO,CAAC,oBAAoB;IAK5B,OAAO,CAAC,qBAAqB;IAO7B;;OAEG;IACH,OAAO,CAAC,uBAAuB;IAsB/B,OAAO,CAAC,iBAAiB;IAmFzB,OAAO,CAAC,uBAAuB;YAqCjB,aAAa;IAwB7B,OAAO,CAAC,gBAAgB;IAqKtB,OAAO,CAAC,aAAa;IAuErB;;;;;;OAMG;IACH,OAAO,CAAC,iBAAiB;IAuHzB;;;;OAIG;IACH,OAAO,CAAC,qBAAqB;IAa7B,OAAO,CAAC,SAAS;IAIjB,OAAO,CAAC,cAAc;CAWvB"}
@@ -463,6 +463,12 @@ export class ClaudeSdkAdapter extends EventEmitter {
463
463
  buildMessagePollingIdlePrompt() {
464
464
  return '请调用 poll_message 工具阻塞等待新消息;收到消息后再处理消息内容。';
465
465
  }
466
+ /**
467
+ * 发送手动快捷键 token 序列,和空闲自动命令共用解析逻辑。
468
+ */
469
+ async sendShortcutInput(sessionId, command) {
470
+ await this.executeIdleCommand(sessionId, command);
471
+ }
466
472
  /**
467
473
  * 执行空闲命令(支持 [enter], [wait:n] 等 token)
468
474
  */
@@ -921,12 +927,13 @@ export class ClaudeSdkAdapter extends EventEmitter {
921
927
  case 'tool_use_start':
922
928
  // AI 正在调用工具
923
929
  {
924
- const actionInfo = getToolActionInfo(msg.tool_name, msg.tool_input);
930
+ const actionInfo = { ...getToolActionInfo(msg.tool_name, msg.tool_input), actionId: msg.tool_use_id };
925
931
  session.status = 'tool_using';
926
932
  this.emit('status-change', sessionId, 'tool_using', {
927
933
  actionType: actionInfo.actionType,
928
934
  actionLabel: actionInfo.actionLabel,
929
935
  actionDetail: actionInfo.actionDetail,
936
+ actionId: actionInfo.actionId,
930
937
  });
931
938
  this.stopIdleDetection(sessionId);
932
939
  this.handleToolUse(sessionId, session, msg, timestamp);
@@ -1141,13 +1148,14 @@ export class ClaudeSdkAdapter extends EventEmitter {
1141
1148
  }
1142
1149
  }
1143
1150
  // 获取工具动作分类信息(使用完整参数)
1144
- const actionInfo = getToolActionInfo(recentInfo.name, toolInput);
1151
+ const actionInfo = { ...getToolActionInfo(recentInfo.name, toolInput), actionId: toolId };
1145
1152
  // 更新状态
1146
1153
  session.status = 'tool_using';
1147
1154
  this.emit('status-change', sessionId, 'tool_using', {
1148
1155
  actionType: actionInfo.actionType,
1149
1156
  actionLabel: actionInfo.actionLabel,
1150
1157
  actionDetail: actionInfo.actionDetail,
1158
+ actionId: actionInfo.actionId,
1151
1159
  });
1152
1160
  this.stopIdleDetection(sessionId);
1153
1161
  // 发送工具调用开始事件(此时有完整参数)
@@ -1162,6 +1170,7 @@ export class ClaudeSdkAdapter extends EventEmitter {
1162
1170
  actionType: actionInfo.actionType,
1163
1171
  actionLabel: actionInfo.actionLabel,
1164
1172
  actionDetail: actionInfo.actionDetail,
1173
+ actionId: actionInfo.actionId,
1165
1174
  },
1166
1175
  });
1167
1176
  // 记录到消息历史
@@ -663,7 +663,7 @@ export class CodexSdkAdapter extends EventEmitter {
663
663
  handleToolLikeItem(sessionId, session, item) {
664
664
  if (!session.emittedToolStarts.has(item.id)) {
665
665
  session.emittedToolStarts.add(item.id);
666
- const actionInfo = getToolActionInfo(item.toolName, item.toolInput, item.metadata);
666
+ const actionInfo = { ...getToolActionInfo(item.toolName, item.toolInput, item.metadata), actionId: item.id };
667
667
  this.emitEvent({
668
668
  type: 'tool_use_start',
669
669
  sessionId,
@@ -630,7 +630,7 @@ export class OpencodeSdkAdapter extends EventEmitter {
630
630
  if (session.emittedToolStarts.has(toolUseId))
631
631
  return;
632
632
  session.emittedToolStarts.add(toolUseId);
633
- const actionInfo = getToolActionInfo(toolName, toolInput, metadata);
633
+ const actionInfo = { ...getToolActionInfo(toolName, toolInput, metadata), actionId: toolUseId };
634
634
  this.emitEvent({
635
635
  type: 'tool_use_start',
636
636
  sessionId,
@@ -650,7 +650,7 @@ export class OpencodeSdkAdapter extends EventEmitter {
650
650
  };
651
651
  if (state.status === 'running') {
652
652
  emitToolStart();
653
- const actionInfo = getToolActionInfo(toolName, toolInput, metadata);
653
+ const actionInfo = { ...getToolActionInfo(toolName, toolInput, metadata), actionId: toolUseId };
654
654
  this.emit('status-change', sessionId, 'tool_using', actionInfo);
655
655
  }
656
656
  else if (state.status === 'completed') {
@@ -81,6 +81,10 @@ export interface ProviderEvent {
81
81
  actionLabel?: string;
82
82
  /** 工具动作详情(tool_use_start) */
83
83
  actionDetail?: string;
84
+ /** 工具调用关联 ID(tool_use_start / tool_use_end) */
85
+ actionId?: string;
86
+ /** 工具返回数据(tool_use_end) */
87
+ actionResult?: string;
84
88
  };
85
89
  }
86
90
  export interface AdapterSessionConfig {
@@ -230,6 +234,12 @@ export declare abstract class BaseProviderAdapter extends EventEmitter {
230
234
  idleInputCommand: string;
231
235
  nonInputCommand: string;
232
236
  }): void;
237
+ /**
238
+ * 发送快捷键 token 序列(如 [enter]、[ctrl+c]),复用 SDK 输入流但不创建普通用户消息。
239
+ * @param sessionId 会话 ID
240
+ * @param command 快捷 token 文本
241
+ */
242
+ abstract sendShortcutInput?(sessionId: string, command: string): Promise<void>;
233
243
  /**
234
244
  * 中止当前正在执行的轮次(软中断)
235
245
  * 会话保持活跃,用户可继续发送新消息。
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/adapter/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/adapter/types.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -21,8 +21,8 @@ import { gitRouter } from "./routes/git.js";
21
21
  import { fileBrowserRouter } from "./routes/file-browser.js";
22
22
  import { aiSourcesRouter } from "./routes/ai-sources.js";
23
23
  import { processesRouter } from "./routes/processes.js";
24
+ import { attachPtyWebSocketServer, closeAllPtySessions, ptyRouter, ptySessions, } from "./routes/pty.js";
24
25
  import { runtimeBindingRouter, logRuntimeBindingStartupState, } from "./routes/runtime-binding.js";
25
- import { sessions, flushSessionOutput } from "./services/session-output.js";
26
26
  import { loadPersistedSessions, savePersistedSessions, } from "./services/terminal-persistence.js";
27
27
  import { detectOrphanProcesses } from "./services/process-detector.js";
28
28
  import { startOrphanMonitor, stopOrphanMonitor, } from "./services/orphan-monitor.js";
@@ -124,7 +124,7 @@ async function rebuildProcessRegistry() {
124
124
  pid: s.pid,
125
125
  workspacePath: s.workspacePath,
126
126
  command: s.command,
127
- mode: s.mode || "pty",
127
+ mode: "sdk",
128
128
  })));
129
129
  logger.info(`[runtime-bridge] 进程注册表重建完成: ${persistedSessions.length} 条记录`);
130
130
  }
@@ -175,12 +175,11 @@ async function detectOrphansOnStartup() {
175
175
  pid: s.pid,
176
176
  workspacePath: s.workspacePath,
177
177
  command: s.command,
178
- mode: s.mode || "pty",
178
+ mode: "sdk",
179
179
  })));
180
180
  return;
181
181
  }
182
182
  logger.info(`[runtime-bridge] ★ Bridge 重启,检测 ${persistedSessions.length} 个持久化会话的孤儿进程...`);
183
- // ★★★ 修复:不再区分 SDK 和 PTY 模式,全部清理
184
183
  // bridge 重启 = 整个运行环境重启,所有 agent 都应该被终止
185
184
  const orphans = detectOrphanProcesses(persistedSessions.map((s) => ({
186
185
  agentId: s.agentId,
@@ -264,6 +263,7 @@ app.use("/runtime", sessionsRouter);
264
263
  app.use("/runtime", processesRouter);
265
264
  app.use("/runtime", gitRouter);
266
265
  app.use("/runtime", aiSourcesRouter);
266
+ app.use("/pty", ptyRouter);
267
267
  app.use("/api/file-browser", fileBrowserRouter);
268
268
  /**
269
269
  * 启动 HTTP 服务并对端口占用给出可诊断错误,避免未捕获异常直接崩溃。
@@ -272,6 +272,7 @@ function startServer() {
272
272
  const server = app.listen(port, () => {
273
273
  logger.info(`[runtime-bridge] listening on ${port}`);
274
274
  });
275
+ attachPtyWebSocketServer(server);
275
276
  server.on("error", (error) => {
276
277
  if (error.code === "EADDRINUSE") {
277
278
  logger.error(`[runtime-bridge] port ${port} is already in use. ` +
@@ -288,11 +289,10 @@ function startServer() {
288
289
  * 优雅关闭处理
289
290
  *
290
291
  * 在收到终止信号时:
291
- * 1. 停止所有 PTY 会话(杀死终端进程)
292
- * 2. 停止所有 SDK 会话(终止 Agent 进程)
293
- * 3. 验证所有进程已终止
294
- * 4. 清空持久化状态(避免恢复残留会话)
295
- * 5. 关闭 HTTP 服务器
292
+ * 1. 停止所有 SDK 会话(终止 Agent 进程)
293
+ * 2. 验证所有进程已终止
294
+ * 3. 清空持久化状态(避免恢复残留会话)
295
+ * 4. 关闭 HTTP 服务器
296
296
  *
297
297
  * ★★★ 修复:添加 preserveSessions 参数
298
298
  * - preserveSessions=true: aws-mcp-server 触发的关闭,保留会话状态
@@ -318,39 +318,7 @@ async function gracefulShutdown(signal, server, preserveSessions = false) {
318
318
  logger.info(`[runtime-bridge] 收到 ${signal} 信号,开始优雅关闭... (preserveSessions=${preserveSessions})`);
319
319
  const startTime = Date.now();
320
320
  try {
321
- // 1. 停止所有 PTY 会话
322
- const ptyCount = sessions.size;
323
- logger.info(`[runtime-bridge] 正在停止 ${ptyCount} 个 PTY 会话...`);
324
- for (const [sessionId, session] of sessions.entries()) {
325
- try {
326
- // 清理定时器
327
- if (session.flushTimer) {
328
- clearTimeout(session.flushTimer);
329
- session.flushTimer = null;
330
- }
331
- // 刷新剩余输出
332
- try {
333
- await flushSessionOutput(sessionId);
334
- }
335
- catch {
336
- // 忽略刷新错误
337
- }
338
- // 杀死 PTY 进程
339
- try {
340
- session.ptyProcess.kill();
341
- logger.info(`[runtime-bridge] PTY 会话 ${sessionId} 已终止 (PID: ${session.ptyProcess.pid})`);
342
- }
343
- catch {
344
- // 忽略终止错误
345
- }
346
- sessions.delete(sessionId);
347
- }
348
- catch (e) {
349
- const err = e;
350
- logger.error(`[runtime-bridge] PTY 会话 ${sessionId} 终止失败:`, err.message);
351
- }
352
- }
353
- // 2. 停止所有 SDK 会话
321
+ // 1. 停止所有 SDK 会话
354
322
  const sdkCount = sdkSessions.size;
355
323
  logger.info(`[runtime-bridge] 正在停止 ${sdkCount} 个 SDK 会话...`);
356
324
  for (const [sessionId, entry] of sdkSessions.entries()) {
@@ -379,6 +347,9 @@ async function gracefulShutdown(signal, server, preserveSessions = false) {
379
347
  sdkSessions.delete(sessionId);
380
348
  }
381
349
  }
350
+ const ptyCount = ptySessions.size;
351
+ logger.info(`[runtime-bridge] 正在停止 ${ptyCount} 个 PTY 会话...`);
352
+ closeAllPtySessions("shutdown");
382
353
  // 3. 停止孤儿进程监控
383
354
  logger.info("[runtime-bridge] 正在停止孤儿进程监控...");
384
355
  stopOrphanMonitor();
@@ -440,7 +411,7 @@ async function gracefulShutdown(signal, server, preserveSessions = false) {
440
411
  }
441
412
  // 8. 关闭 HTTP 服务器
442
413
  const elapsed = Date.now() - startTime;
443
- logger.info(`[runtime-bridge] 优雅关闭完成 (耗时 ${elapsed}ms),停止 ${ptyCount} PTY + ${sdkCount} SDK 会话`);
414
+ logger.info(`[runtime-bridge] 优雅关闭完成 (耗时 ${elapsed}ms),停止 ${sdkCount} SDK 会话`);
444
415
  server.close(() => {
445
416
  logger.info("[runtime-bridge] HTTP 服务器已关闭");
446
417
  process.exit(0);
@@ -4,6 +4,11 @@
4
4
  * 验证请求头中的 X-Runtime-Token 是否为已配对的 connectionKey 或 runtime binding token。
5
5
  */
6
6
  import type { Request, Response, NextFunction } from "express";
7
+ /**
8
+ * 校验 runtime token。
9
+ * 主流程:复用 REST 中间件的 runtime binding token 与 connectionKey 校验逻辑,供 WebSocket upgrade 使用。
10
+ */
11
+ export declare function isRuntimeTokenValid(token: unknown): boolean;
7
12
  /**
8
13
  * Token 验证中间件
9
14
  * 检查请求头中的 X-Runtime-Token 或 Authorization: Bearer 是否有效。
@@ -1 +1 @@
1
- {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/middleware/auth.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AA8B/D;;;;;GAKG;AACH,wBAAgB,aAAa,CAC3B,GAAG,EAAE,OAAO,EACZ,GAAG,EAAE,QAAQ,EACb,IAAI,EAAE,YAAY,GACjB,IAAI,CAmBN"}
1
+ {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/middleware/auth.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AA8B/D;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAG3D;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAC3B,GAAG,EAAE,OAAO,EACZ,GAAG,EAAE,QAAQ,EACb,IAAI,EAAE,YAAY,GACjB,IAAI,CAmBN"}
@@ -23,6 +23,14 @@ function validateConfiguredToken(token) {
23
23
  }
24
24
  return false;
25
25
  }
26
+ /**
27
+ * 校验 runtime token。
28
+ * 主流程:复用 REST 中间件的 runtime binding token 与 connectionKey 校验逻辑,供 WebSocket upgrade 使用。
29
+ */
30
+ export function isRuntimeTokenValid(token) {
31
+ const normalized = String(token || "").trim();
32
+ return validateRuntimeBindingToken(normalized) || validateConfiguredToken(normalized);
33
+ }
26
34
  /**
27
35
  * Token 验证中间件
28
36
  * 检查请求头中的 X-Runtime-Token 或 Authorization: Bearer 是否有效。
@@ -31,7 +39,7 @@ function validateConfiguredToken(token) {
31
39
  */
32
40
  export function validateToken(req, res, next) {
33
41
  const token = extractRuntimeToken(req);
34
- if (validateRuntimeBindingToken(token) || validateConfiguredToken(token)) {
42
+ if (isRuntimeTokenValid(token)) {
35
43
  next();
36
44
  return;
37
45
  }
@@ -1 +1 @@
1
- {"version":3,"file":"file-browser.d.ts","sourceRoot":"","sources":["../../src/routes/file-browser.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAOH,OAAO,MAAM,MAAM,QAAQ,CAAC;AAsB5B,eAAO,MAAM,iBAAiB,4CAAW,CAAC;AAE1C,eAAO,MAAM,2BAA2B,OAAO,CAAC;AAqChD,wBAAgB,kCAAkC,CAAC,KAAK,EAAE,MAAM,CAAC,WAAW,GAAG;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE,CAUvI;AAED,wBAAgB,iCAAiC,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,EAAE,CAgBzF"}
1
+ {"version":3,"file":"file-browser.d.ts","sourceRoot":"","sources":["../../src/routes/file-browser.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAOH,OAAO,MAAM,MAAM,QAAQ,CAAC;AAuB5B,eAAO,MAAM,iBAAiB,4CAAW,CAAC;AAE1C,eAAO,MAAM,2BAA2B,OAAO,CAAC;AAqChD,wBAAgB,kCAAkC,CAAC,KAAK,EAAE,MAAM,CAAC,WAAW,GAAG;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE,CAUvI;AAED,wBAAgB,iCAAiC,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,EAAE,CAgBzF"}
@@ -11,7 +11,7 @@ import multer from 'multer';
11
11
  import { allowHostFileBrowser } from '../config.js';
12
12
  import { validateToken } from '../middleware/auth.js';
13
13
  import { createLogger } from '../utils/logger.js';
14
- import { createWorkspaceEntry, deleteWorkspaceEntry, extractWorkspaceArchive, listWorkspaceDirectory, previewWorkspaceDocument, readWorkspaceFile, renameWorkspaceEntry, resolveWorkspaceDownloadTarget, streamWorkspaceDirectoryZip, uploadWorkspaceFiles, writeWorkspaceFile, } from '../services/workspace-files.js';
14
+ import { createWorkspaceEntry, deleteWorkspaceEntry, extractWorkspaceArchive, listWorkspaceDirectory, moveWorkspaceEntry, previewWorkspaceDocument, readWorkspaceFile, renameWorkspaceEntry, resolveWorkspaceDownloadTarget, streamWorkspaceDirectoryZip, uploadWorkspaceFiles, writeWorkspaceFile, } from '../services/workspace-files.js';
15
15
  import { unwatchWorkspaceFile, watchWorkspaceFile } from '../services/workspace-watch.js';
16
16
  const log = createLogger('file-browser');
17
17
  export const fileBrowserRouter = Router();
@@ -335,6 +335,26 @@ fileBrowserRouter.post('/workspace/rename', validateToken, async (req, res) => {
335
335
  res.status(400).json({ error: err.message });
336
336
  }
337
337
  });
338
+ /**
339
+ * 移动工作区中的文件或目录到另一个工作区目录
340
+ * POST /api/file-browser/workspace/move
341
+ */
342
+ fileBrowserRouter.post('/workspace/move', validateToken, async (req, res) => {
343
+ try {
344
+ const { workspacePath, targetPath, destinationPath } = req.body || {};
345
+ const result = await moveWorkspaceEntry({
346
+ workspacePath: String(workspacePath || ''),
347
+ targetPath: String(targetPath || ''),
348
+ destinationPath: String(destinationPath || '')
349
+ });
350
+ res.json(result);
351
+ }
352
+ catch (error) {
353
+ const err = error;
354
+ log.error('failed to move workspace entry:', err);
355
+ res.status(400).json({ error: err.message });
356
+ }
357
+ });
338
358
  /**
339
359
  * 删除工作区中的文件或目录
340
360
  * POST /api/file-browser/workspace/delete
@@ -63,6 +63,15 @@ describe('file-browser route validation', () => {
63
63
  expect(validateDeleteRequest({}).valid).toBe(false);
64
64
  expect(validateDeleteRequest({ workspacePath: '/p', targetPath: '/p/file' }).valid).toBe(true);
65
65
  });
66
+ it('validates move request', () => {
67
+ const validateMoveRequest = (body) => {
68
+ if (!body.workspacePath || !body.targetPath || !body.destinationPath)
69
+ return { valid: false, error: 'workspacePath, targetPath, and destinationPath are required' };
70
+ return { valid: true };
71
+ };
72
+ expect(validateMoveRequest({}).valid).toBe(false);
73
+ expect(validateMoveRequest({ workspacePath: '/p', targetPath: '/p/file', destinationPath: '/p/dest' }).valid).toBe(true);
74
+ });
66
75
  });
67
76
  describe('file-browser response building', () => {
68
77
  it('builds correct list response', () => {
@@ -1,3 +1,4 @@
1
+ import type { ToolInstallStatus } from "../types.js";
1
2
  export declare function setGracefulShutdownFn(fn: (signal: string, preserveSessions: boolean) => Promise<void>): void;
2
3
  export declare const instanceRouter: import("express-serve-static-core").Router;
3
4
  export declare function buildConnectionCheckResponse(connectionKeyMd5: string): {
@@ -37,5 +38,14 @@ export declare function buildSchedulerPingFailureResponse(error: Error, configur
37
38
  * Main flow: never silently pick the first target; require an explicit scheduler URL or future scheduler identity routing.
38
39
  */
39
40
  export declare function buildAmbiguousSchedulerBaseUrlResponse(targetUrls: string[]): AmbiguousSchedulerBaseUrlResponse;
41
+ /**
42
+ * 构建工具状态检测目标列表。
43
+ * 主流程:合并实例启用工具与配置面板固定展示工具,避免历史状态缺少 Codex 时前端误判为待检测。
44
+ */
45
+ export declare function buildToolStatusDetectionTargets(enabledTools: string[]): string[];
46
+ /**
47
+ * 汇总卸载后仍可执行的工具,用于避免把部分卸载误报为成功。
48
+ */
49
+ export declare function buildUninstallFailureMessage(requestedTools: string[], toolStatus: Record<string, ToolInstallStatus>): string;
40
50
  export {};
41
51
  //# sourceMappingURL=instance.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"instance.d.ts","sourceRoot":"","sources":["../../src/routes/instance.ts"],"names":[],"mappings":"AA6BA,wBAAgB,qBAAqB,CACnC,EAAE,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,gBAAgB,EAAE,OAAO,KAAK,OAAO,CAAC,IAAI,CAAC,GAC/D,IAAI,CAEN;AAED,eAAO,MAAM,cAAc,4CAAW,CAAC;AAyBvC,wBAAgB,4BAA4B,CAAC,gBAAgB,EAAE,MAAM,GAAG;IACtE,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE;QACJ,EAAE,EAAE,OAAO,CAAC;QACZ,aAAa,CAAC,EAAE,SAAS,CAAC;QAC1B,oBAAoB,EAAE,OAAO,CAAC;QAC9B,qBAAqB,EAAE,OAAO,CAAC;QAC/B,KAAK,CAAC,EAAE,MAAM,CAAC;KAChB,CAAC;CACH,CAqCA;AAED,MAAM,WAAW,4BAA4B;IAC3C,EAAE,EAAE,KAAK,CAAC;IACV,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,EAAE,gBAAgB,CAAC;IAC/B,aAAa,EAAE,SAAS,CAAC;IACzB,gBAAgB,EAAE,MAAM,CAAC;IACzB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,UAAU,iCAAiC;IACzC,EAAE,EAAE,KAAK,CAAC;IACV,KAAK,EAAE,8BAA8B,CAAC;IACtC,YAAY,EAAE,gBAAgB,CAAC;IAC/B,aAAa,EAAE,SAAS,CAAC;IACzB,gBAAgB,EAAE,MAAM,CAAC;IACzB,sBAAsB,EAAE,MAAM,EAAE,CAAC;IACjC,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;;GAGG;AACH,wBAAgB,iCAAiC,CAC/C,KAAK,EAAE,KAAK,EACZ,0BAA0B,EAAE,MAAM,GACjC,4BAA4B,CAiB9B;AAED;;;GAGG;AACH,wBAAgB,sCAAsC,CACpD,UAAU,EAAE,MAAM,EAAE,GACnB,iCAAiC,CAUnC"}
1
+ {"version":3,"file":"instance.d.ts","sourceRoot":"","sources":["../../src/routes/instance.ts"],"names":[],"mappings":"AAsBA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAYrD,wBAAgB,qBAAqB,CACnC,EAAE,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,gBAAgB,EAAE,OAAO,KAAK,OAAO,CAAC,IAAI,CAAC,GAC/D,IAAI,CAEN;AAED,eAAO,MAAM,cAAc,4CAAW,CAAC;AAyBvC,wBAAgB,4BAA4B,CAAC,gBAAgB,EAAE,MAAM,GAAG;IACtE,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE;QACJ,EAAE,EAAE,OAAO,CAAC;QACZ,aAAa,CAAC,EAAE,SAAS,CAAC;QAC1B,oBAAoB,EAAE,OAAO,CAAC;QAC9B,qBAAqB,EAAE,OAAO,CAAC;QAC/B,KAAK,CAAC,EAAE,MAAM,CAAC;KAChB,CAAC;CACH,CAqCA;AAED,MAAM,WAAW,4BAA4B;IAC3C,EAAE,EAAE,KAAK,CAAC;IACV,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,EAAE,gBAAgB,CAAC;IAC/B,aAAa,EAAE,SAAS,CAAC;IACzB,gBAAgB,EAAE,MAAM,CAAC;IACzB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,UAAU,iCAAiC;IACzC,EAAE,EAAE,KAAK,CAAC;IACV,KAAK,EAAE,8BAA8B,CAAC;IACtC,YAAY,EAAE,gBAAgB,CAAC;IAC/B,aAAa,EAAE,SAAS,CAAC;IACzB,gBAAgB,EAAE,MAAM,CAAC;IACzB,sBAAsB,EAAE,MAAM,EAAE,CAAC;IACjC,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;;GAGG;AACH,wBAAgB,iCAAiC,CAC/C,KAAK,EAAE,KAAK,EACZ,0BAA0B,EAAE,MAAM,GACjC,4BAA4B,CAiB9B;AAED;;;GAGG;AACH,wBAAgB,sCAAsC,CACpD,UAAU,EAAE,MAAM,EAAE,GACnB,iCAAiC,CAUnC;AAED;;;GAGG;AACH,wBAAgB,+BAA+B,CAAC,YAAY,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,CAQhF;AAED;;GAEG;AACH,wBAAgB,4BAA4B,CAC1C,cAAc,EAAE,MAAM,EAAE,EACxB,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,iBAAiB,CAAC,GAC5C,MAAM,CAaR"}
@@ -8,10 +8,11 @@ import { loadInstanceState, saveInstanceState, } from "../services/instance-stat
8
8
  import { initInstance } from "../services/instance-init-service.js";
9
9
  import { discoverCcSwitchConfiguredItems, loadCcSwitchSdk } from "../services/cc-switch-sdk.js";
10
10
  import { syncLegacyStateFromSdk } from "../services/instance-init-service.js";
11
- import { detectToolStatuses, ensureToolsInstalled, SUPPORTED_INSTALLABLE_TOOLS, } from "../services/tool-installer.js";
11
+ import { detectToolStatuses, ensureToolsInstalled, SUPPORTED_INSTALLABLE_TOOLS, SUPPORTED_UNINSTALLABLE_TOOLS, uninstallTools, } from "../services/tool-installer.js";
12
12
  import { getConfiguredConnectionKeys } from "../services/auto-register.js";
13
13
  import { createLogger } from "../utils/logger.js";
14
14
  const log = createLogger("instance");
15
+ const PANEL_TOOL_STATUS_KEYS = ["claude", "opencode", "codex"];
15
16
  // ★★★ 导出 gracefulShutdown 的触发函数
16
17
  // 用于 aws-mcp-server 通知 bridge 保留会话状态关闭
17
18
  let gracefulShutdownFn = null;
@@ -106,6 +107,31 @@ export function buildAmbiguousSchedulerBaseUrlResponse(targetUrls) {
106
107
  hint: "Multiple autoRegisterTargets.serverUrl values were found, so bridge cannot safely infer which scheduler /runtime/ping should call back. Set AWS_RUNTIME_SCHEDULER_BASE_URL explicitly, or use future schedulerId/token-bound multi-scheduler routing.",
107
108
  };
108
109
  }
110
+ /**
111
+ * 构建工具状态检测目标列表。
112
+ * 主流程:合并实例启用工具与配置面板固定展示工具,避免历史状态缺少 Codex 时前端误判为待检测。
113
+ */
114
+ export function buildToolStatusDetectionTargets(enabledTools) {
115
+ return Array.from(new Set([...enabledTools, ...PANEL_TOOL_STATUS_KEYS]
116
+ .map((tool) => String(tool || "").trim().toLowerCase())
117
+ .filter(Boolean)));
118
+ }
119
+ /**
120
+ * 汇总卸载后仍可执行的工具,用于避免把部分卸载误报为成功。
121
+ */
122
+ export function buildUninstallFailureMessage(requestedTools, toolStatus) {
123
+ const failedTools = requestedTools.filter((tool) => toolStatus[tool]?.installed);
124
+ if (failedTools.length === 0) {
125
+ return "";
126
+ }
127
+ return failedTools
128
+ .map((tool) => {
129
+ const status = toolStatus[tool];
130
+ const detail = status?.error || status?.executable || "command is still available";
131
+ return `${tool}: ${detail}`;
132
+ })
133
+ .join("; ");
134
+ }
109
135
  instanceRouter.get("/healthz", (_req, res) => {
110
136
  res.json({
111
137
  ok: true,
@@ -182,7 +208,7 @@ instanceRouter.post("/cc-switch/state", validateToken, async (req, res) => {
182
208
  const imported = await discoverCcSwitchConfiguredItems(sdk);
183
209
  const synced = await syncLegacyStateFromSdk(agentId, sdk);
184
210
  const state = synced.state;
185
- const toolStatus = await detectToolStatuses(state.enabledTools || []);
211
+ const toolStatus = await detectToolStatuses(buildToolStatusDetectionTargets(state.enabledTools || []));
186
212
  res.json({
187
213
  ok: true,
188
214
  agentId: String(agentId),
@@ -247,6 +273,71 @@ instanceRouter.post("/cc-switch/install-tools", validateToken, async (req, res)
247
273
  res.status(400).json({ error: err?.message || "install tools failed" });
248
274
  }
249
275
  });
276
+ instanceRouter.post("/cc-switch/uninstall-tools", validateToken, async (req, res) => {
277
+ const { agentId, tools } = req.body || {};
278
+ if (!agentId) {
279
+ res.status(400).json({ error: "agentId is required" });
280
+ return;
281
+ }
282
+ const requestedTools = Array.isArray(tools)
283
+ ? tools
284
+ .map((tool) => String(tool || "")
285
+ .trim()
286
+ .toLowerCase())
287
+ .filter(Boolean)
288
+ : [];
289
+ const supportedUninstallableTools = new Set(SUPPORTED_UNINSTALLABLE_TOOLS);
290
+ const uninstallableTools = requestedTools.filter((tool) => supportedUninstallableTools.has(tool));
291
+ if (uninstallableTools.length === 0) {
292
+ res.status(400).json({
293
+ error: `tools must include ${SUPPORTED_UNINSTALLABLE_TOOLS.join(", ")}`,
294
+ });
295
+ return;
296
+ }
297
+ try {
298
+ const state = await loadInstanceState(agentId);
299
+ const uninstallableToolSet = new Set(uninstallableTools);
300
+ const enabledTools = (state.enabledTools || []).filter((tool) => !uninstallableToolSet.has(String(tool || "").trim().toLowerCase()));
301
+ const uninstalledToolStatus = await uninstallTools(uninstallableTools);
302
+ const refreshedToolStatus = await detectToolStatuses([
303
+ ...enabledTools,
304
+ ...uninstallableTools,
305
+ ]);
306
+ const nextToolStatus = {
307
+ ...refreshedToolStatus,
308
+ ...uninstalledToolStatus,
309
+ };
310
+ const uninstallFailureMessage = buildUninstallFailureMessage(uninstallableTools, nextToolStatus);
311
+ const nextEnabledTools = uninstallFailureMessage
312
+ ? state.enabledTools || []
313
+ : enabledTools;
314
+ const savedState = await saveInstanceState(agentId, {
315
+ ...state,
316
+ enabledTools: nextEnabledTools,
317
+ toolStatus: nextToolStatus,
318
+ });
319
+ if (uninstallFailureMessage) {
320
+ res.status(400).json({
321
+ ok: false,
322
+ agentId: String(agentId),
323
+ error: `uninstall incomplete: ${uninstallFailureMessage}`,
324
+ toolStatus: nextToolStatus,
325
+ state: savedState,
326
+ });
327
+ return;
328
+ }
329
+ res.json({
330
+ ok: true,
331
+ agentId: String(agentId),
332
+ toolStatus: nextToolStatus,
333
+ state: savedState,
334
+ });
335
+ }
336
+ catch (error) {
337
+ const err = error;
338
+ res.status(400).json({ error: err?.message || "uninstall tools failed" });
339
+ }
340
+ });
250
341
  /**
251
342
  * ★★★ 新增:aws-mcp-server 通知 bridge 准备重启
252
343
  * POST /runtime/prepare-restart