aws-runtime-bridge 1.9.66 → 1.9.71

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 (34) hide show
  1. package/README.md +17 -1
  2. package/dist/config.d.ts +8 -3
  3. package/dist/config.d.ts.map +1 -1
  4. package/dist/config.js +56 -12
  5. package/dist/index.js +14 -7
  6. package/dist/routes/file-browser.d.ts.map +1 -1
  7. package/dist/routes/file-browser.js +7 -10
  8. package/dist/routes/instance.js +6 -3
  9. package/dist/services/auto-register.d.ts +25 -1
  10. package/dist/services/auto-register.d.ts.map +1 -1
  11. package/dist/services/auto-register.js +220 -33
  12. package/dist/services/cli-commands.d.ts.map +1 -1
  13. package/dist/services/cli-commands.js +1 -0
  14. package/dist/services/event-delta-pusher.js +1 -1
  15. package/dist/services/lifecycle-state.js +1 -1
  16. package/dist/services/mcp-launch-binding-queue.js +1 -1
  17. package/dist/services/orphan-monitor.d.ts +5 -0
  18. package/dist/services/orphan-monitor.d.ts.map +1 -1
  19. package/dist/services/orphan-monitor.js +48 -4
  20. package/dist/services/runtime-binding.d.ts +4 -5
  21. package/dist/services/runtime-binding.d.ts.map +1 -1
  22. package/dist/services/runtime-binding.js +14 -16
  23. package/dist/services/runtime-lifecycle-policy.d.ts +1 -0
  24. package/dist/services/runtime-lifecycle-policy.d.ts.map +1 -1
  25. package/dist/services/runtime-lifecycle-policy.js +1 -0
  26. package/dist/services/session-output.js +1 -1
  27. package/dist/services/startup-config-wizard.d.ts.map +1 -1
  28. package/dist/services/startup-config-wizard.js +10 -4
  29. package/dist/services/tunnel-client.d.ts +21 -0
  30. package/dist/services/tunnel-client.d.ts.map +1 -0
  31. package/dist/services/tunnel-client.js +398 -0
  32. package/dist/services/workspaceTaskChangeWatcher.js +1 -1
  33. package/dist/utils/file-utils.js +1 -1
  34. package/package.json +1 -1
package/README.md CHANGED
@@ -37,12 +37,26 @@ npm install -g .
37
37
  "serverUrl": "http://127.0.0.1:8080",
38
38
  "instanceName": "至强主机",
39
39
  "userKey": "aws_live_crh_g0GGrg5IntODg1sFwnas7qf4yGrcwoisDWPBtd8",
40
- "registerIp": "127.0.0.1"
40
+ "registerAddr": "127.0.0.1"
41
41
  }
42
42
  ]
43
43
  }
44
44
  ```
45
45
 
46
+ ### `registerAddr` 字段说明
47
+
48
+ `registerAddr` 用于告知调度中心如何回连本机 Bridge,支持三种写法:
49
+
50
+ | 写法 | 示例 | 解析结果 | 适用场景 |
51
+ | --- | --- | --- | --- |
52
+ | 完整 URL(含协议) | `https://bridge.example.com` | 原样使用 | Bridge 在反代后面或启用 TLS |
53
+ | `host:port` | `127.0.0.1:18081` | 自动补 `http://` 前缀 | http 直连 + 自定义端口 |
54
+ | 纯 `host` | `10.0.0.8` | 自动补 `http://` 前缀和 `AWS_RUNTIME_BRIDGE_PORT`(默认 18081) | http 直连 + 默认端口 |
55
+
56
+ > **TLS / 反代场景**:当 Bridge 部署在 Nginx/Caddy/Cloudflare 后面走 https 时,必须用完整 URL 形式(如 `https://bridge.example.com`),此时环境变量 `AWS_RUNTIME_BRIDGE_PORT` 不再生效。
57
+
58
+ > **向后兼容**:旧字段 `registerIp`(仅接受纯 IP)仍可读取,但已废弃,推荐迁移到 `registerAddr`。配置引导会在重新配置时自动将 `registerIp` 迁移为 `registerAddr` 并剥离老字段。
59
+
46
60
  如需在交互式终端中也强制跳过引导,可设置 `AWS_BRIDGE_SKIP_SETUP=true`;此时仍会生成随机 `connectionKey`。
47
61
 
48
62
  ```bash
@@ -90,6 +104,8 @@ sudo awsb service uninstall
90
104
  | --- | --- | --- |
91
105
  | `AWS_RUNTIME_BRIDGE_PORT` | Bridge HTTP 端口 | `18081` |
92
106
  | `AWS_RUNTIME_SCHEDULER_BASE_URL` | aws-mcp-server 地址;显式配置优先级最高,未配置且只有一个 `autoRegisterTargets[].serverUrl` 时自动使用该地址 | 单目标自动注册地址;否则 `http://localhost:8080` |
107
+ | `AWS_REGISTER_ADDR` | Bridge 对外注册地址,覆盖配置文件中的 `registerAddr`;支持 `host:port` / 纯 `host` / 完整 URL(`http(s)://...`) | 未设置时读取配置文件 |
108
+ | `AWS_REGISTER_IP` | 已废弃,仅做向后兼容;等同 `registerAddr` 但只接受纯 IP,端口由 `AWS_RUNTIME_BRIDGE_PORT` 决定 | 未设置时读取配置文件 |
93
109
  | `AWS_RUNTIME_HOME_DIR` | Bridge 管理配置与状态的主目录 | 当前用户 Home |
94
110
  | `AWS_RUNTIME_CORS_ORIGINS` | 允许访问 bridge 的来源,逗号分隔 | 本地开发地址 |
95
111
 
package/dist/config.d.ts CHANGED
@@ -7,11 +7,15 @@
7
7
  export declare const port: number;
8
8
  /** 默认调度器基础 URL */
9
9
  export declare const DEFAULT_SCHEDULER_BASE_URL = "http://localhost:8080";
10
- export type SchedulerBaseUrlSource = "request" | "env" | "single-auto-register-target" | "default" | "ambiguous-auto-register-targets";
10
+ export type SchedulerBaseUrlSource = "request" | "instance-id-match" | "env" | "single-auto-register-target" | "default" | "ambiguous-auto-register-targets";
11
11
  export interface SchedulerBaseUrlResolution {
12
12
  url: string;
13
13
  source: SchedulerBaseUrlSource;
14
14
  ambiguousTargetUrls: string[];
15
+ /** 匹配到的 target 的 instanceId(若有),用于 /ping 响应回传给 server */
16
+ instanceId?: string;
17
+ /** 匹配到的 target 的 instanceName(若有),用于 /ping 响应回传给 server */
18
+ instanceName?: string;
15
19
  }
16
20
  /**
17
21
  * 解析调度中心基础 URL。
@@ -20,9 +24,10 @@ export interface SchedulerBaseUrlResolution {
20
24
  export declare function resolveSchedulerBaseUrl(): SchedulerBaseUrlResolution;
21
25
  /**
22
26
  * 解析调度中心基础 URL。
23
- * 主流程:服务端请求携带的 scheduler 地址优先;再读显式环境变量;最后回退到单个自动注册目标或默认值。
27
+ * 主流程:服务端请求携带的 scheduler 地址优先;再按 instanceId/instanceName 在 config.json 中匹配 target;
28
+ * 再读显式环境变量;最后回退到单个自动注册目标或默认值。
24
29
  */
25
- export declare function resolveSchedulerBaseUrlFrom(requestSchedulerBaseUrl: unknown): SchedulerBaseUrlResolution;
30
+ export declare function resolveSchedulerBaseUrlFrom(requestSchedulerBaseUrl: unknown, instanceId?: unknown, instanceName?: unknown): SchedulerBaseUrlResolution;
26
31
  /** 调度器基础 URL(兼容旧导入;请求处理应优先调用 resolveSchedulerBaseUrl 获取最新值) */
27
32
  export declare const schedulerBaseUrl: string;
28
33
  /** Node 环境 */
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAOH,WAAW;AACX,eAAO,MAAM,IAAI,EAAE,MAElB,CAAC;AAEF,kBAAkB;AAClB,eAAO,MAAM,0BAA0B,0BAA0B,CAAC;AAElE,MAAM,MAAM,sBAAsB,GAC9B,SAAS,GACT,KAAK,GACL,6BAA6B,GAC7B,SAAS,GACT,iCAAiC,CAAC;AAEtC,MAAM,WAAW,0BAA0B;IACzC,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,sBAAsB,CAAC;IAC/B,mBAAmB,EAAE,MAAM,EAAE,CAAC;CAC/B;AA+ED;;;GAGG;AACH,wBAAgB,uBAAuB,IAAI,0BAA0B,CAEpE;AAED;;;GAGG;AACH,wBAAgB,2BAA2B,CACzC,uBAAuB,EAAE,OAAO,GAC/B,0BAA0B,CA4C5B;AAED,+DAA+D;AAC/D,eAAO,MAAM,gBAAgB,EAAE,MAEH,CAAC;AAE7B,cAAc;AACd,eAAO,MAAM,OAAO,EAAE,MAA8C,CAAC;AAErE,oCAAoC;AACpC,eAAO,MAAM,oBAAoB,EAAE,OACiB,CAAC;AAErD,8BAA8B;AAC9B,eAAO,MAAM,kBAAkB,EAAE,MAAM,EAMC,CAAC;AAEzC,gEAAgE;AAChE,wBAAgB,uBAAuB,IAAI,IAAI,CAAG;AAElD,eAAe;AACf,wBAAgB,iBAAiB,IAAI,MAAM,CAE1C;AAED,8CAA8C;AAC9C,wBAAgB,mBAAmB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAK/D;AAED,2BAA2B;AAC3B,wBAAgB,sBAAsB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAKlE;AAED,0BAA0B;AAC1B,wBAAgB,kBAAkB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAK9D;AAED,yBAAyB;AACzB,wBAAgB,qBAAqB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAKjE;AAED,wBAAwB;AACxB,wBAAgB,kBAAkB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAK9D;AAED,sBAAsB;AACtB,wBAAgB,kBAAkB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAK9D;AAED,yBAAyB;AACzB,wBAAgB,iBAAiB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAK7D;AAED,4BAA4B;AAC5B,wBAAgB,oBAAoB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAKhE;AAED,2BAA2B;AAC3B,wBAAgB,iBAAiB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAK7D;AAED;;GAEG;AAEH,yBAAyB;AACzB,eAAO,MAAM,oBAAoB,QAEhC,CAAC;AAEF,0CAA0C;AAC1C,eAAO,MAAM,sBAAsB,EACrB,MAAM,GAAG,OAAO,GAAG,QAAQ,CAAC;AAE1C,eAAe;AACf,eAAO,MAAM,mBAAmB,SACiB,CAAC;AAElD,iCAAiC;AACjC,eAAO,MAAM,2BAA2B,QAEvC,CAAC;AAEF,0CAA0C;AAC1C,eAAO,MAAM,oBAAoB,QAEhC,CAAC;AAEF,qCAAqC;AACrC,eAAO,MAAM,uBAAuB,QAEnC,CAAC;AAEF;;GAEG;AAEH,eAAe;AACf,eAAO,MAAM,qBAAqB,SAA2C,CAAC;AAE9E,YAAY;AACZ,eAAO,MAAM,uBAAuB,QAAkC,CAAC;AAEvE,iBAAiB;AACjB,eAAO,MAAM,sBAAsB,QAAiC,CAAC;AAErE,oBAAoB;AACpB,eAAO,MAAM,2BAA2B,QAAsC,CAAC;AAE/E,WAAW;AACX,eAAO,MAAM,0BAA0B,QAAqC,CAAC;AAE7E,WAAW;AACX,eAAO,MAAM,uBAAuB,QAAkC,CAAC;AAEvE,aAAa;AACb,eAAO,MAAM,4BAA4B,QACH,CAAC;AAEvC,kCAAkC;AAClC,eAAO,MAAM,wBAAwB,QAC4B,CAAC;AAIlE;;;GAGG;AACH,wBAAgB,gBAAgB,IAAI,MAAM,CAiBzC"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
package/dist/config.js CHANGED
@@ -46,32 +46,47 @@ function getAutoRegisterConfigFilePath() {
46
46
  const testHomeDir = String(process.env.AWS_TEST_HOME || "").trim();
47
47
  return path.join(testHomeDir || homedir(), ".aws-bridge", "config.json");
48
48
  }
49
- function readAutoRegisterTargetUrls() {
49
+ /** 读取 config.json 中的自动注册目标完整信息(含 instanceId / instanceName) */
50
+ function readAutoRegisterTargets() {
50
51
  const configPath = getAutoRegisterConfigFilePath();
51
52
  try {
52
53
  if (!fs.existsSync(configPath)) {
53
54
  return [];
54
55
  }
55
56
  const parsed = JSON.parse(fs.readFileSync(configPath, "utf-8"));
57
+ const normalizeTarget = (source) => {
58
+ const serverUrl = normalizeSchedulerHttpBaseUrl(source.serverUrl) ||
59
+ normalizeSchedulerHttpBaseUrl(source.schedulerBaseUrl);
60
+ return {
61
+ serverUrl,
62
+ instanceId: normalizeOptionalString(source.instanceId),
63
+ instanceName: normalizeOptionalString(source.instanceName),
64
+ };
65
+ };
56
66
  const rawTargets = Array.isArray(parsed.autoRegisterTargets)
57
67
  ? parsed.autoRegisterTargets
58
68
  : [];
59
- const targetUrls = rawTargets
69
+ const targets = rawTargets
60
70
  .filter((item) => Boolean(item && typeof item === "object" && !Array.isArray(item)))
61
- .map((target) => normalizeSchedulerHttpBaseUrl(target.serverUrl) ||
62
- normalizeSchedulerHttpBaseUrl(target.schedulerBaseUrl))
63
- .filter((url) => Boolean(url));
64
- if (targetUrls.length > 0) {
65
- return Array.from(new Set(targetUrls));
71
+ .map(normalizeTarget)
72
+ .filter((target) => Boolean(target.serverUrl));
73
+ if (targets.length > 0) {
74
+ return targets;
66
75
  }
67
- const topLevelUrl = normalizeSchedulerHttpBaseUrl(parsed.serverUrl) ||
68
- normalizeSchedulerHttpBaseUrl(parsed.schedulerBaseUrl);
69
- return topLevelUrl ? [topLevelUrl] : [];
76
+ const topLevel = normalizeTarget(parsed);
77
+ return topLevel.serverUrl ? [topLevel] : [];
70
78
  }
71
79
  catch {
72
80
  return [];
73
81
  }
74
82
  }
83
+ function readAutoRegisterTargetUrls() {
84
+ const targets = readAutoRegisterTargets();
85
+ const urls = targets
86
+ .map((target) => target.serverUrl)
87
+ .filter((url) => Boolean(url));
88
+ return Array.from(new Set(urls));
89
+ }
75
90
  /**
76
91
  * 解析调度中心基础 URL。
77
92
  * 主流程:显式环境变量优先;未配置时,单个自动注册目标可作为宿主机部署的零额外配置回退;多目标不静默取第一个。
@@ -81,9 +96,10 @@ export function resolveSchedulerBaseUrl() {
81
96
  }
82
97
  /**
83
98
  * 解析调度中心基础 URL。
84
- * 主流程:服务端请求携带的 scheduler 地址优先;再读显式环境变量;最后回退到单个自动注册目标或默认值。
99
+ * 主流程:服务端请求携带的 scheduler 地址优先;再按 instanceId/instanceName 在 config.json 中匹配 target;
100
+ * 再读显式环境变量;最后回退到单个自动注册目标或默认值。
85
101
  */
86
- export function resolveSchedulerBaseUrlFrom(requestSchedulerBaseUrl) {
102
+ export function resolveSchedulerBaseUrlFrom(requestSchedulerBaseUrl, instanceId, instanceName) {
87
103
  const normalizedRequestSchedulerBaseUrl = normalizeSchedulerHttpBaseUrl(requestSchedulerBaseUrl);
88
104
  if (normalizedRequestSchedulerBaseUrl) {
89
105
  return {
@@ -92,6 +108,34 @@ export function resolveSchedulerBaseUrlFrom(requestSchedulerBaseUrl) {
92
108
  ambiguousTargetUrls: [],
93
109
  };
94
110
  }
111
+ // 按 instanceId / instanceName 在 config.json autoRegisterTargets 中匹配 target
112
+ const trimmedInstanceId = typeof instanceId === "string" ? instanceId.trim() : "";
113
+ const trimmedInstanceName = typeof instanceName === "string" ? instanceName.trim() : "";
114
+ if (trimmedInstanceId || trimmedInstanceName) {
115
+ const targets = readAutoRegisterTargets();
116
+ // 优先按 instanceId 精确匹配
117
+ let matched;
118
+ if (trimmedInstanceId) {
119
+ matched = targets.find((target) => target.instanceId === trimmedInstanceId);
120
+ }
121
+ // 回退到按 instanceName 匹配(支持单独传 instanceName 的场景)
122
+ if (!matched && trimmedInstanceName) {
123
+ matched = targets.find((target) => target.instanceName === trimmedInstanceName);
124
+ }
125
+ // 兼容旧逻辑:instanceId 入参也曾用作 instanceName 匹配
126
+ if (!matched && trimmedInstanceId && !trimmedInstanceName) {
127
+ matched = targets.find((target) => target.instanceName === trimmedInstanceId);
128
+ }
129
+ if (matched?.serverUrl) {
130
+ return {
131
+ url: matched.serverUrl,
132
+ source: "instance-id-match",
133
+ ambiguousTargetUrls: [],
134
+ instanceId: matched.instanceId,
135
+ instanceName: matched.instanceName,
136
+ };
137
+ }
138
+ }
95
139
  const envSchedulerBaseUrl = normalizeSchedulerHttpBaseUrl(process.env.AWS_RUNTIME_SCHEDULER_BASE_URL);
96
140
  if (envSchedulerBaseUrl) {
97
141
  return {
package/dist/index.js CHANGED
@@ -37,7 +37,8 @@ import { startOrphanMonitor, stopOrphanMonitor, } from "./services/orphan-monito
37
37
  import { getAgentProcessManager } from "./services/agent-process-manager.js";
38
38
  import { adapterRegistry } from "./adapter/index.js";
39
39
  import { logger } from "./utils/logger.js";
40
- import { autoRegister, unregister, bridgeRestartCleanup, } from "./services/auto-register.js";
40
+ import { autoRegister, unregister, bridgeRestartCleanup, cancelBackgroundRegisterRetries, } from "./services/auto-register.js";
41
+ import { stopTunnelClient } from "./services/tunnel-client.js";
41
42
  import { ensureAwsClientAgentMcpReleased } from "./services/aws-client-agent-mcp.js";
42
43
  import { ensureAcodePackageReleased } from "./services/acode-package.js";
43
44
  import { ensureStartupConfig } from "./services/startup-config-wizard.js";
@@ -68,13 +69,13 @@ async function performAutoRegister() {
68
69
  // 检查注册状态
69
70
  const { loadConfig } = await import("./services/auto-register.js");
70
71
  const config = loadConfig();
71
- // 判断是否有配置(配置文件存在或环境变量设置了必填项)
72
- const hasConfig = config.tenantId && config.userKey;
72
+ // 判断是否有配置(userKey 为必填项;tenantId 可自动推导,不参与判断)
73
+ const hasConfig = Boolean(config.userKey);
73
74
  if (hasConfig && config.enabled) {
74
- // 有配置但注册失败,服务启动失败
75
- logger.error("[runtime-bridge] 自动注册已启用但注册失败,服务启动失败");
76
- logger.error("[runtime-bridge] 请检查调度中心是否可达、配置是否正确");
77
- process.exitCode = 1;
75
+ // 有配置但暂时注册失败(如 server 尚未启动):
76
+ // autoRegisterSingle 已调度后台持续重试,连上后自动完成注册与隧道建立,
77
+ // bridge 继续正常提供本地服务
78
+ logger.warn("[runtime-bridge] 自动注册暂时失败,将在后台持续重试直到与调度中心建立连接");
78
79
  }
79
80
  else {
80
81
  // 没有配置,正常启动服务
@@ -465,6 +466,12 @@ async function gracefulShutdown(signal, server, preserveSessions = false) {
465
466
  else {
466
467
  logger.info("[runtime-bridge] ★ 保留模式跳过实例注销,避免调度中心将 Agent 标记为 stopped");
467
468
  }
469
+ // 6.5 停止后台注册重试 + 关闭隧道客户端(若运行中)
470
+ cancelBackgroundRegisterRetries();
471
+ if (shutdownPlan.stopTunnelClient) {
472
+ logger.info("[runtime-bridge] 正在关闭隧道客户端...");
473
+ stopTunnelClient();
474
+ }
468
475
  // 7. ★★★ 修复:根据 preserveSessions 决定是否清空持久化状态
469
476
  // - preserveSessions=true (aws-mcp-server 触发): 保留会话状态,aws-mcp-server 重启后可恢复
470
477
  // - preserveSessions=false (bridge 自己关闭): 清空所有会话,agent 应被清理
@@ -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;AA2B5B,eAAO,MAAM,iBAAiB,4CAAW,CAAC;AAE1C,eAAO,MAAM,2BAA2B,OAAO,CAAC;AAUhD,UAAU,eAAe;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,OAAO,CAAC;CACtB;AAED,UAAU,mBAAmB;IAC3B,SAAS,EAAE,OAAO,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,eAAe,EAAE,CAAC;CAC1B;AAMD,UAAU,iBAAkB,SAAQ,eAAe;IACjD,QAAQ,CAAC,EAAE,iBAAiB,EAAE,CAAC;IAC/B,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,UAAU,qBAAsB,SAAQ,mBAAmB;IACzD,QAAQ,EAAE,MAAM,CAAC;IACjB,oBAAoB,EAAE,MAAM,CAAC;IAC7B,IAAI,EAAE,iBAAiB,EAAE,CAAC;CAC3B;AAED,UAAU,aAAa;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,OAAO,CAAC;IACjB,aAAa,EAAE,OAAO,CAAC;IACvB,QAAQ,EAAE,OAAO,CAAC;IAClB,QAAQ,EAAE,OAAO,CAAC;CACnB;AAiBD,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;AAyFD;;GAEG;AACH,wBAAsB,qBAAqB,CAAC,WAAW,SAAK,GAAG,OAAO,CAAC,qBAAqB,CAAC,CAkB5F;AAoCD,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,aAAa,EAAE,CAuBpE;AA6BD,wBAAgB,oBAAoB,CAAC,YAAY,EAAE,MAAM,EAAE,WAAW,EAAE,OAAO,EAAE,KAAK,EAAE,aAAa,EAAE,GAAG,OAAO,CAWhH"}
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;AA2B5B,eAAO,MAAM,iBAAiB,4CAAW,CAAC;AAE1C,eAAO,MAAM,2BAA2B,OAAO,CAAC;AAUhD,UAAU,eAAe;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,OAAO,CAAC;CACtB;AAED,UAAU,mBAAmB;IAC3B,SAAS,EAAE,OAAO,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,eAAe,EAAE,CAAC;CAC1B;AAMD,UAAU,iBAAkB,SAAQ,eAAe;IACjD,QAAQ,CAAC,EAAE,iBAAiB,EAAE,CAAC;IAC/B,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,UAAU,qBAAsB,SAAQ,mBAAmB;IACzD,QAAQ,EAAE,MAAM,CAAC;IACjB,oBAAoB,EAAE,MAAM,CAAC;IAC7B,IAAI,EAAE,iBAAiB,EAAE,CAAC;CAC3B;AAED,UAAU,aAAa;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,OAAO,CAAC;IACjB,aAAa,EAAE,OAAO,CAAC;IACvB,QAAQ,EAAE,OAAO,CAAC;IAClB,QAAQ,EAAE,OAAO,CAAC;CACnB;AAiBD,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;AAwFD;;GAEG;AACH,wBAAsB,qBAAqB,CAAC,WAAW,SAAK,GAAG,OAAO,CAAC,qBAAqB,CAAC,CAkB5F;AAoCD,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,aAAa,EAAE,CAuBpE;AA6BD,wBAAgB,oBAAoB,CAAC,YAAY,EAAE,MAAM,EAAE,WAAW,EAAE,OAAO,EAAE,KAAK,EAAE,aAAa,EAAE,GAAG,OAAO,CAWhH"}
@@ -84,21 +84,18 @@ async function listHostDirectories(requestPath = '') {
84
84
  const isWindows = platform === 'win32';
85
85
  if (!requestPath || requestPath === '') {
86
86
  if (isWindows) {
87
- const drives = [];
88
- for (let i = 67; i <= 90; i++) { // C to Z
89
- const drive = String.fromCharCode(i) + ':\\';
87
+ // 并行检测所有盘符(C-Z),避免串行 access 累加延迟
88
+ const driveLetters = Array.from({ length: 24 }, (_, i) => String.fromCharCode(67 + i) + ':\\');
89
+ const driveChecks = await Promise.all(driveLetters.map(async (drive) => {
90
90
  try {
91
91
  await fs.access(drive);
92
- drives.push({
93
- name: drive,
94
- path: drive,
95
- isDirectory: true
96
- });
92
+ return { name: drive, path: drive, isDirectory: true };
97
93
  }
98
94
  catch {
99
- // Drive not accessible, skip
95
+ return null;
100
96
  }
101
- }
97
+ }));
98
+ const drives = driveChecks.filter((d) => d !== null);
102
99
  return {
103
100
  isWindows: true,
104
101
  currentPath: '',
@@ -339,7 +339,7 @@ instanceRouter.get("/connection-check", (req, res) => {
339
339
  res.status(result.status).json(result.body);
340
340
  });
341
341
  instanceRouter.get("/ping", validateToken, async (req, res) => {
342
- const schedulerBaseUrlResolution = resolveSchedulerBaseUrlFrom(req.header("X-Scheduler-Base-Url"));
342
+ const schedulerBaseUrlResolution = resolveSchedulerBaseUrlFrom(req.header("X-Scheduler-Base-Url"), req.header("X-Bridge-Instance-Id"), req.header("X-Bridge-Instance-Name"));
343
343
  if (schedulerBaseUrlResolution.source === "ambiguous-auto-register-targets") {
344
344
  res
345
345
  .status(400)
@@ -348,7 +348,7 @@ instanceRouter.get("/ping", validateToken, async (req, res) => {
348
348
  }
349
349
  const schedulerBaseUrl = schedulerBaseUrlResolution.url;
350
350
  try {
351
- const runtimeAccessToken = getRuntimeAccessToken(undefined, schedulerBaseUrl);
351
+ const runtimeAccessToken = getRuntimeAccessToken(schedulerBaseUrl);
352
352
  if (!runtimeAccessToken) {
353
353
  res.status(401).json({ ok: false, error: "runtime_access_token_required" });
354
354
  return;
@@ -361,6 +361,9 @@ instanceRouter.get("/ping", validateToken, async (req, res) => {
361
361
  schedulerReachable: schedulerPing.schedulerReachable,
362
362
  tokenRefreshed: schedulerPing.tokenRefreshed,
363
363
  schedulerBaseUrl,
364
+ // 回传匹配到的 instanceId/instanceName,让 server 知道 bridge 实际绑定的是哪个
365
+ instanceId: schedulerBaseUrlResolution.instanceId,
366
+ instanceName: schedulerBaseUrlResolution.instanceName,
364
367
  });
365
368
  }
366
369
  catch (error) {
@@ -663,7 +666,7 @@ instanceRouter.post("/prepare-restart", validateToken, async (req, res) => {
663
666
  */
664
667
  instanceRouter.post("/update-bridge", validateTokenOrPanelSession, async (req, res) => {
665
668
  const command = resolveNpmExecutable();
666
- const args = ["install", "-g", "aws-runtime-bridge@latest"];
669
+ const args = ["install", "-g", "aws-runtime-bridge@latest", "--omit=optional"];
667
670
  const requestedByUserId = normalizeOptionalText(req.body?.requestedByUserId);
668
671
  try {
669
672
  if (!requestedByUserId) {
@@ -23,16 +23,36 @@ interface AutoRegisterConfig {
23
23
  connectionKey?: string;
24
24
  /** 实例名称(默认使用主机名) */
25
25
  instanceName?: string;
26
+ /** 实例 ID(可选,预声明时发送给 server 作为实例标识;注册成功后自动回填) */
27
+ instanceId?: string;
26
28
  /** 项目名称 */
27
29
  projectName?: string;
28
30
  /** 角色名称 */
29
31
  roleName?: string;
30
32
  /** 工作空间路径 */
31
33
  workspacePath?: string;
32
- /** 注册 IP(优先用于生成 runtimeBridgeBaseUrl) */
34
+ /**
35
+ * 注册地址(推荐)
36
+ * - 支持 `host:port`、纯 `host`(自动补 AWS_RUNTIME_BRIDGE_PORT)、完整 URL(`http://...` / `https://...`,原样使用)
37
+ * - 优先级高于 registerIp / virtualIp
38
+ */
39
+ registerAddr?: string;
40
+ /**
41
+ * 注册 IP(已废弃,仅做向后兼容回退)
42
+ * - 仅接受纯 IP/host,端口由 AWS_RUNTIME_BRIDGE_PORT 决定
43
+ * - 推荐迁移到 registerAddr
44
+ */
33
45
  registerIp?: string;
34
46
  /** 虚拟 IP(EasyTier,兼容旧配置) */
35
47
  virtualIp?: string;
48
+ /**
49
+ * 是否启用隧道模式(三态):
50
+ * - true:显式启用隧道模式,bridge 经 WebSocket 反向连出到 server,
51
+ * server 经 /tunnel/{instanceId}/ 虚拟路径反向调用 bridge。
52
+ * - false:显式禁用隧道模式,即使未填 registerAddr 也走直连(用于 loopback 场景)。
53
+ * - undefined(默认):未填 registerAddr/registerIp/virtualIp 时自动判定为隧道模式(向后兼容)。
54
+ */
55
+ tunnel?: boolean;
36
56
  /** 是否优先选择与 serverUrl 同局域网的本机 IP */
37
57
  preferSameLanIp?: boolean;
38
58
  /** 注册重试次数 */
@@ -41,6 +61,8 @@ interface AutoRegisterConfig {
41
61
  retryInterval?: number;
42
62
  }
43
63
  export declare function getConfiguredConnectionKeys(): string[];
64
+ /** 停止所有后台注册重试(优雅关闭/测试清理用) */
65
+ export declare function cancelBackgroundRegisterRetries(): void;
44
66
  /**
45
67
  * 配置文件路径
46
68
  */
@@ -54,6 +76,8 @@ export declare function getAutoRegisterConfigFilePath(): string;
54
76
  */
55
77
  export declare function loadConfig(): AutoRegisterConfig;
56
78
  export declare function loadConfigs(): AutoRegisterConfig[];
79
+ export declare function isTunnelConfig(config?: AutoRegisterConfig): boolean;
80
+ export declare function loadPrimaryLifecycleConfig(): AutoRegisterConfig;
57
81
  /**
58
82
  * 自动注册主函数
59
83
  *
@@ -1 +1 @@
1
- {"version":3,"file":"auto-register.d.ts","sourceRoot":"","sources":["../../src/services/auto-register.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAmDH;;GAEG;AACH,UAAU,kBAAkB;IAC1B,eAAe;IACf,OAAO,EAAE,OAAO,CAAC;IACjB,oBAAoB;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,oCAAoC;IACpC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,mCAAmC;IACnC,OAAO,EAAE,MAAM,CAAC;IAChB,0BAA0B;IAC1B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,oBAAoB;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW;IACX,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW;IACX,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,aAAa;IACb,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,yCAAyC;IACzC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,4BAA4B;IAC5B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,mCAAmC;IACnC,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,aAAa;IACb,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,iBAAiB;IACjB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAuBD,wBAAgB,2BAA2B,IAAI,MAAM,EAAE,CAEtD;AAiED;;GAEG;AACH,wBAAgB,6BAA6B,IAAI,MAAM,CAGtD;AAyJD;;;;;;GAMG;AACH,wBAAgB,UAAU,IAAI,kBAAkB,CA2C/C;AAED,wBAAgB,WAAW,IAAI,kBAAkB,EAAE,CA0ClD;AA2PD;;;;;;;;;;GAUG;AACH,wBAAsB,YAAY,CAChC,YAAY,CAAC,EAAE,OAAO,CAAC,kBAAkB,CAAC,GACzC,OAAO,CAAC,OAAO,CAAC,CAalB;AAyHD;;GAEG;AACH,wBAAsB,gCAAgC,IAAI,OAAO,CAAC;IAChE,OAAO,EAAE,OAAO,CAAC;IACjB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC,CAoED;AAED,wBAAsB,yCAAyC,CAC7D,aAAa,EAAE,MAAM,GACpB,OAAO,CAAC;IACT,OAAO,EAAE,OAAO,CAAC;IACjB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC,CA0ED;AAED,wBAAsB,UAAU,IAAI,OAAO,CAAC,OAAO,CAAC,CAgCnD;AAED;;GAEG;AACH,wBAAgB,oBAAoB;gBAh6BtB,OAAO;iBACN,MAAM;mBACJ,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;kBACvB,IAAI;YACV,MAAM;EA85Bf;AAED;;GAEG;AACH,wBAAgB,YAAY,IAAI,OAAO,CAEtC;AAED;;GAEG;AACH,wBAAgB,aAAa,IAAI,MAAM,GAAG,SAAS,CAElD;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,oBAAoB,IAAI,OAAO,CAAC;IACpD,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC,CA0ED"}
1
+ {"version":3,"file":"auto-register.d.ts","sourceRoot":"","sources":["../../src/services/auto-register.ts"],"names":[],"mappings":"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"}