aws-runtime-bridge 1.9.1 → 1.9.5

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 (66) hide show
  1. package/dist/config.d.ts +5 -4
  2. package/dist/config.d.ts.map +1 -1
  3. package/dist/config.js +25 -4
  4. package/dist/index.js +20 -4
  5. package/dist/middleware/auth.d.ts +8 -0
  6. package/dist/middleware/auth.d.ts.map +1 -1
  7. package/dist/middleware/auth.js +44 -0
  8. package/dist/routes/ai-sources.js +18 -14
  9. package/dist/routes/dashboard.d.ts +8 -0
  10. package/dist/routes/dashboard.d.ts.map +1 -0
  11. package/dist/routes/dashboard.js +1347 -0
  12. package/dist/routes/instance.d.ts +1 -0
  13. package/dist/routes/instance.d.ts.map +1 -1
  14. package/dist/routes/instance.js +53 -4
  15. package/dist/routes/instance.test.js +4 -0
  16. package/dist/routes/processes.js +1 -1
  17. package/dist/routes/runtime-binding.d.ts.map +1 -1
  18. package/dist/routes/runtime-binding.js +37 -0
  19. package/dist/routes/sessions.js +7 -7
  20. package/dist/routes/terminal.d.ts.map +1 -1
  21. package/dist/routes/terminal.js +143 -33
  22. package/dist/services/agent-process-manager.d.ts +12 -0
  23. package/dist/services/agent-process-manager.d.ts.map +1 -1
  24. package/dist/services/agent-process-manager.js +47 -13
  25. package/dist/services/auto-register.d.ts.map +1 -1
  26. package/dist/services/auto-register.js +4 -5
  27. package/dist/services/mcp-launch-binding-queue.d.ts +5 -0
  28. package/dist/services/mcp-launch-binding-queue.d.ts.map +1 -1
  29. package/dist/services/mcp-launch-binding-queue.js +17 -0
  30. package/dist/services/mcp-launch-binding-queue.test.js +16 -1
  31. package/dist/services/orphan-monitor.js +2 -2
  32. package/dist/services/panel-auth.d.ts +26 -0
  33. package/dist/services/panel-auth.d.ts.map +1 -0
  34. package/dist/services/panel-auth.js +105 -0
  35. package/dist/services/process-detector.d.ts +16 -9
  36. package/dist/services/process-detector.d.ts.map +1 -1
  37. package/dist/services/process-detector.js +136 -66
  38. package/dist/services/session-output.d.ts.map +1 -1
  39. package/dist/services/session-output.js +106 -6
  40. package/package/aws-client-agent-mcp/dist/agent-client.d.ts +20 -0
  41. package/package/aws-client-agent-mcp/dist/agent-client.d.ts.map +1 -1
  42. package/package/aws-client-agent-mcp/dist/agent-client.js +71 -2
  43. package/package/aws-client-agent-mcp/dist/agent-client.js.map +1 -1
  44. package/package/aws-client-agent-mcp/dist/constants.d.ts +4 -1
  45. package/package/aws-client-agent-mcp/dist/constants.d.ts.map +1 -1
  46. package/package/aws-client-agent-mcp/dist/constants.js +5 -1
  47. package/package/aws-client-agent-mcp/dist/constants.js.map +1 -1
  48. package/package/aws-client-agent-mcp/dist/http-client.d.ts +17 -1
  49. package/package/aws-client-agent-mcp/dist/http-client.d.ts.map +1 -1
  50. package/package/aws-client-agent-mcp/dist/http-client.js +124 -28
  51. package/package/aws-client-agent-mcp/dist/http-client.js.map +1 -1
  52. package/package/aws-client-agent-mcp/dist/http-client.test.js +108 -2
  53. package/package/aws-client-agent-mcp/dist/http-client.test.js.map +1 -1
  54. package/package/aws-client-agent-mcp/dist/mcp-server.d.ts +5 -0
  55. package/package/aws-client-agent-mcp/dist/mcp-server.d.ts.map +1 -1
  56. package/package/aws-client-agent-mcp/dist/mcp-server.js +53 -3
  57. package/package/aws-client-agent-mcp/dist/mcp-server.js.map +1 -1
  58. package/package/aws-client-agent-mcp/dist/runtime-launch-binding.d.ts.map +1 -1
  59. package/package/aws-client-agent-mcp/dist/runtime-launch-binding.js +79 -28
  60. package/package/aws-client-agent-mcp/dist/runtime-launch-binding.js.map +1 -1
  61. package/package/aws-client-agent-mcp/dist/runtime-launch-binding.test.js +35 -0
  62. package/package/aws-client-agent-mcp/dist/runtime-launch-binding.test.js.map +1 -1
  63. package/package/aws-client-agent-mcp/dist/types.d.ts +9 -0
  64. package/package/aws-client-agent-mcp/dist/types.d.ts.map +1 -1
  65. package/package/aws-client-agent-mcp/dist/types.js.map +1 -1
  66. package/package.json +1 -1
package/dist/config.d.ts CHANGED
@@ -87,8 +87,9 @@ export declare const AUTO_REGISTER_ROLE_NAME: string;
87
87
  export declare const AUTO_REGISTER_WORKSPACE_PATH: string;
88
88
  /** 注册 IP(优先),兼容 EasyTier 虚拟 IP */
89
89
  export declare const AUTO_REGISTER_VIRTUAL_IP: string;
90
- /** 注册重试次数 */
91
- export declare const AUTO_REGISTER_MAX_RETRIES: number;
92
- /** 注册重试间隔(毫秒) */
93
- export declare const AUTO_REGISTER_RETRY_INTERVAL: number;
90
+ /**
91
+ * 读取 aws-runtime-bridge package.json 中的版本号。
92
+ * 缓存结果,仅在首次调用时读取文件。
93
+ */
94
+ export declare function getBridgeVersion(): string;
94
95
  //# sourceMappingURL=config.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
package/dist/config.js CHANGED
@@ -6,6 +6,7 @@
6
6
  import { homedir } from "node:os";
7
7
  import path from "node:path";
8
8
  import fs from "node:fs";
9
+ import { fileURLToPath } from "node:url";
9
10
  /** 服务端口 */
10
11
  export const port = Number(process.env.AWS_RUNTIME_BRIDGE_PORT || 18081);
11
12
  /** 默认调度器基础 URL */
@@ -219,7 +220,27 @@ export const AUTO_REGISTER_ROLE_NAME = process.env.AWS_ROLE_NAME || "";
219
220
  export const AUTO_REGISTER_WORKSPACE_PATH = process.env.AWS_WORKSPACE_PATH || "";
220
221
  /** 注册 IP(优先),兼容 EasyTier 虚拟 IP */
221
222
  export const AUTO_REGISTER_VIRTUAL_IP = process.env.AWS_REGISTER_IP || process.env.AWS_VIRTUAL_IP || "";
222
- /** 注册重试次数 */
223
- export const AUTO_REGISTER_MAX_RETRIES = Number(process.env.AWS_REGISTER_MAX_RETRIES || 5);
224
- /** 注册重试间隔(毫秒) */
225
- export const AUTO_REGISTER_RETRY_INTERVAL = Number(process.env.AWS_REGISTER_RETRY_INTERVAL || 5000);
223
+ let cachedBridgeVersion;
224
+ /**
225
+ * 读取 aws-runtime-bridge package.json 中的版本号。
226
+ * 缓存结果,仅在首次调用时读取文件。
227
+ */
228
+ export function getBridgeVersion() {
229
+ if (cachedBridgeVersion !== undefined) {
230
+ return cachedBridgeVersion;
231
+ }
232
+ let version = "unknown";
233
+ try {
234
+ const currentDir = path.dirname(fileURLToPath(import.meta.url));
235
+ const pkgPath = path.resolve(currentDir, "..", "package.json");
236
+ if (fs.existsSync(pkgPath)) {
237
+ const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf-8"));
238
+ version = pkg.version || "unknown";
239
+ }
240
+ }
241
+ catch {
242
+ // fallback
243
+ }
244
+ cachedBridgeVersion = version;
245
+ return version;
246
+ }
package/dist/index.js CHANGED
@@ -25,6 +25,7 @@ import { processesRouter } from "./routes/processes.js";
25
25
  import { systemMetricsRouter } from "./routes/system-metrics.js";
26
26
  import { attachPtyWebSocketServer, closeAllPtySessions, ptyRouter, ptySessions, } from "./routes/pty.js";
27
27
  import { runtimeBindingRouter, logRuntimeBindingStartupState, } from "./routes/runtime-binding.js";
28
+ import { dashboardRouter } from "./routes/dashboard.js";
28
29
  import { loadPersistedSessions, savePersistedSessions, } from "./services/terminal-persistence.js";
29
30
  import { detectOrphanProcesses } from "./services/process-detector.js";
30
31
  import { startOrphanMonitor, stopOrphanMonitor, } from "./services/orphan-monitor.js";
@@ -193,7 +194,7 @@ async function detectOrphansOnStartup() {
193
194
  return;
194
195
  }
195
196
  logger.info(`[runtime-bridge] ★ 已显式启用启动清理,检测 ${persistedSessions.length} 个持久化会话的孤儿进程...`);
196
- const orphans = detectOrphanProcesses(persistedSessions.map((s) => ({
197
+ const orphans = await detectOrphanProcesses(persistedSessions.map((s) => ({
197
198
  agentId: s.agentId,
198
199
  pid: s.pid,
199
200
  workspacePath: s.workspacePath,
@@ -257,6 +258,20 @@ app.use(cors({
257
258
  callback(null, true);
258
259
  return;
259
260
  }
261
+ // 允许 bridge 自身端口的来源(dashboard/登录页面同源请求)
262
+ if (origin) {
263
+ try {
264
+ const url = new URL(origin);
265
+ if ((url.hostname === "localhost" || url.hostname === "127.0.0.1") &&
266
+ url.port === String(port)) {
267
+ callback(null, true);
268
+ return;
269
+ }
270
+ }
271
+ catch {
272
+ // URL 解析失败,继续拒绝
273
+ }
274
+ }
260
275
  callback(new Error(`[runtime-bridge] CORS origin is not allowed: ${origin}`));
261
276
  },
262
277
  }));
@@ -276,6 +291,7 @@ app.use("/runtime", gitRouter);
276
291
  app.use("/runtime", memoryRouter);
277
292
  app.use("/runtime", aiSourcesRouter);
278
293
  app.use("/pty", ptyRouter);
294
+ app.use("/", dashboardRouter);
279
295
  app.use("/api/file-browser", fileBrowserRouter);
280
296
  /**
281
297
  * 启动 HTTP 服务并对端口占用给出可诊断错误,避免未捕获异常直接崩溃。
@@ -388,7 +404,7 @@ async function gracefulShutdown(signal, server, preserveSessions = false) {
388
404
  const { loadPersistedSessions } = await import("./services/terminal-persistence.js");
389
405
  const persistedSessions = await loadPersistedSessions();
390
406
  if (persistedSessions.length > 0) {
391
- const orphans = detectOrphanProcesses(persistedSessions.map((s) => ({
407
+ const orphans = await detectOrphanProcesses(persistedSessions.map((s) => ({
392
408
  agentId: s.agentId,
393
409
  pid: s.pid,
394
410
  workspacePath: s.workspacePath,
@@ -399,7 +415,7 @@ async function gracefulShutdown(signal, server, preserveSessions = false) {
399
415
  for (const orphan of orphans) {
400
416
  if (orphan.process.pid) {
401
417
  // 使用进程树终止(跨平台)
402
- const result = terminateProcessTree(orphan.process.pid);
418
+ const result = await terminateProcessTree(orphan.process.pid);
403
419
  logger.info(`[runtime-bridge] 已强制终止残留进程树:agentId=${orphan.agentId}, PID=${orphan.process.pid}, 终止了 ${result.terminated} 个进程`);
404
420
  }
405
421
  }
@@ -455,7 +471,7 @@ async function gracefulShutdown(signal, server, preserveSessions = false) {
455
471
  setTimeout(() => {
456
472
  logger.warn("[runtime-bridge] 优雅关闭超时,强制退出");
457
473
  process.exit(1);
458
- }, 8000); // 增加到 8 秒,给进程终止更多时间
474
+ }, 15000);
459
475
  }
460
476
  catch (e) {
461
477
  const err = e;
@@ -2,6 +2,7 @@
2
2
  * Token 验证中间件
3
3
  *
4
4
  * 验证请求头中的 X-Runtime-Token 是否为已配对的 connectionKey 或 runtime binding token。
5
+ * 也提供联合中间件,同时支持面板 cookie 会话认证,用于可从面板 UI 触发的操作。
5
6
  */
6
7
  import type { Request, Response, NextFunction } from "express";
7
8
  /**
@@ -16,4 +17,11 @@ export declare function isRuntimeTokenValid(token: unknown): boolean;
16
17
  * 支持面板/服务器绑定时写入的动态令牌和 bridge 实例 connectionKey。
17
18
  */
18
19
  export declare function validateToken(req: Request, res: Response, next: NextFunction): void;
20
+ /**
21
+ * 联合中间件:同时支持 runtime token 和面板 cookie 会话。
22
+ * 面板前端调用时需要 cookie 认证(由浏览器自动附带),
23
+ * 调度中心/服务端调用时使用 X-Runtime-Token 或 Authorization: Bearer。
24
+ * 适用于可从面板 UI 或外部 API 两种途径触发的操作。
25
+ */
26
+ export declare function validateTokenOrPanelSession(req: Request, res: Response, next: NextFunction): void;
19
27
  //# sourceMappingURL=auth.d.ts.map
@@ -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;;;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"}
1
+ {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/middleware/auth.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AA+B/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;AAwBD;;;;;GAKG;AACH,wBAAgB,2BAA2B,CACzC,GAAG,EAAE,OAAO,EACZ,GAAG,EAAE,QAAQ,EACb,IAAI,EAAE,YAAY,GACjB,IAAI,CAgBN"}
@@ -2,9 +2,11 @@
2
2
  * Token 验证中间件
3
3
  *
4
4
  * 验证请求头中的 X-Runtime-Token 是否为已配对的 connectionKey 或 runtime binding token。
5
+ * 也提供联合中间件,同时支持面板 cookie 会话认证,用于可从面板 UI 触发的操作。
5
6
  */
6
7
  import { hasRuntimeBinding, validateRuntimeBindingToken, } from "../services/runtime-binding.js";
7
8
  import { getConfiguredConnectionKeys } from "../services/auto-register.js";
9
+ import { validateSession } from "../services/panel-auth.js";
8
10
  function extractRuntimeToken(req) {
9
11
  const headerToken = req.header("X-Runtime-Token");
10
12
  if (headerToken) {
@@ -52,3 +54,45 @@ export function validateToken(req, res, next) {
52
54
  }
53
55
  res.status(401).json({ error: "unauthorized" });
54
56
  }
57
+ // ── 面板 cookie 会话验证 ──────────────────────────────────────
58
+ const PANEL_COOKIE_NAME = "panel_sid";
59
+ function parseCookies(cookieHeader) {
60
+ const result = {};
61
+ if (!cookieHeader)
62
+ return result;
63
+ for (const part of cookieHeader.split(";")) {
64
+ const idx = part.indexOf("=");
65
+ if (idx === -1)
66
+ continue;
67
+ const key = part.slice(0, idx).trim();
68
+ const val = part.slice(idx + 1).trim();
69
+ if (key)
70
+ result[key] = val;
71
+ }
72
+ return result;
73
+ }
74
+ function extractPanelSessionToken(req) {
75
+ const cookies = parseCookies(req.headers.cookie);
76
+ return cookies[PANEL_COOKIE_NAME];
77
+ }
78
+ /**
79
+ * 联合中间件:同时支持 runtime token 和面板 cookie 会话。
80
+ * 面板前端调用时需要 cookie 认证(由浏览器自动附带),
81
+ * 调度中心/服务端调用时使用 X-Runtime-Token 或 Authorization: Bearer。
82
+ * 适用于可从面板 UI 或外部 API 两种途径触发的操作。
83
+ */
84
+ export function validateTokenOrPanelSession(req, res, next) {
85
+ // 优先检查 runtime token(服务端调用)
86
+ const token = extractRuntimeToken(req);
87
+ if (isRuntimeTokenValid(token)) {
88
+ next();
89
+ return;
90
+ }
91
+ // 回退检查面板 cookie 会话(浏览器调用)
92
+ const panelToken = extractPanelSessionToken(req);
93
+ if (panelToken && validateSession(panelToken)) {
94
+ next();
95
+ return;
96
+ }
97
+ res.status(401).json({ error: "unauthorized" });
98
+ }
@@ -26,12 +26,24 @@ function normalizeListedModels(payload) {
26
26
  }
27
27
  return [...ids];
28
28
  }
29
- async function fetchRemoteModelList(baseUrl, apiKey) {
29
+ async function fetchRemoteModelList(baseUrl, apiKey, protocolType) {
30
30
  const normalizedBaseUrl = baseUrl.replace(/\/+$/, '');
31
- const openAiCandidates = normalizedBaseUrl.endsWith('/v1')
31
+ if (protocolType === 'anthropic-compatible') {
32
+ const anthropicUrl = `${normalizedBaseUrl.endsWith('/v1') ? normalizedBaseUrl.replace(/\/v1$/, '') : normalizedBaseUrl}/v1/models`;
33
+ const response = await axios.get(anthropicUrl, {
34
+ headers: {
35
+ 'x-api-key': apiKey,
36
+ 'anthropic-version': '2023-06-01',
37
+ },
38
+ timeout: 10000,
39
+ });
40
+ return normalizeListedModels(response.data);
41
+ }
42
+ // Default: OpenAI-compatible
43
+ const candidates = normalizedBaseUrl.endsWith('/v1')
32
44
  ? [`${normalizedBaseUrl}/models`]
33
45
  : [`${normalizedBaseUrl}/models`, `${normalizedBaseUrl}/v1/models`];
34
- for (const candidate of openAiCandidates) {
46
+ for (const candidate of candidates) {
35
47
  try {
36
48
  const response = await axios.get(candidate, {
37
49
  headers: {
@@ -48,15 +60,7 @@ async function fetchRemoteModelList(baseUrl, apiKey) {
48
60
  // continue probing next compatible endpoint
49
61
  }
50
62
  }
51
- const anthropicCandidate = `${normalizedBaseUrl.endsWith('/v1') ? normalizedBaseUrl : `${normalizedBaseUrl}/v1`}/models`;
52
- const anthropicResponse = await axios.get(anthropicCandidate, {
53
- headers: {
54
- 'x-api-key': apiKey,
55
- 'anthropic-version': '2023-06-01',
56
- },
57
- timeout: 10000,
58
- });
59
- return normalizeListedModels(anthropicResponse.data);
63
+ return [];
60
64
  }
61
65
  aiSourcesRouter.post('/cc-switch/apply-ai-sources', validateToken, async (req, res) => {
62
66
  const { agentId, template, ccSwitchEnabledTools, acodeTemplateId, claudecodeTemplateId, codexTemplateId, opencodeTemplateId, acodeModelEffort, claudecodeModelEffort, codexModelEffort, opencodeModelEffort, acode, claudecode, codex, opencode, } = req.body || {};
@@ -100,7 +104,7 @@ aiSourcesRouter.post('/cc-switch/apply-ai-sources', validateToken, async (req, r
100
104
  }
101
105
  });
102
106
  aiSourcesRouter.post('/cc-switch/list-ai-models', validateToken, async (req, res) => {
103
- const { baseUrl, apiKey } = req.body || {};
107
+ const { baseUrl, apiKey, protocolType } = req.body || {};
104
108
  const normalizedBaseUrl = String(baseUrl || '').trim();
105
109
  const normalizedApiKey = String(apiKey || '').trim();
106
110
  if (!normalizedBaseUrl || !normalizedApiKey) {
@@ -108,7 +112,7 @@ aiSourcesRouter.post('/cc-switch/list-ai-models', validateToken, async (req, res
108
112
  return;
109
113
  }
110
114
  try {
111
- const models = await fetchRemoteModelList(normalizedBaseUrl, normalizedApiKey);
115
+ const models = await fetchRemoteModelList(normalizedBaseUrl, normalizedApiKey, protocolType);
112
116
  res.json({
113
117
  ok: true,
114
118
  models,
@@ -0,0 +1,8 @@
1
+ /**
2
+ * 仪表盘路由
3
+ *
4
+ * 提供 Bridge 状态看板的静态页面和数据聚合 API
5
+ * 支持中/英文界面,默认中文
6
+ */
7
+ export declare const dashboardRouter: import("express-serve-static-core").Router;
8
+ //# sourceMappingURL=dashboard.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dashboard.d.ts","sourceRoot":"","sources":["../../src/routes/dashboard.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AA+EH,eAAO,MAAM,eAAe,4CAAW,CAAC"}