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
@@ -7,6 +7,7 @@
7
7
  * 1. 环境变量
8
8
  * 2. 用户目录下的 .aws-bridge/config.json 文件
9
9
  */
10
+ import { v4 as uuidv4 } from "uuid";
10
11
  import axios from "axios";
11
12
  import os from "node:os";
12
13
  import path from "node:path";
@@ -29,6 +30,56 @@ let cachedConfiguredConnectionKeys = [];
29
30
  export function getConfiguredConnectionKeys() {
30
31
  return [...cachedConfiguredConnectionKeys];
31
32
  }
33
+ /** 注册失败后的后台重试默认间隔(毫秒),可用 AWS_REGISTER_BACKGROUND_RETRY_INTERVAL 覆盖 */
34
+ const DEFAULT_BACKGROUND_RETRY_INTERVAL_MS = 30_000;
35
+ function getBackgroundRetryIntervalMs() {
36
+ const raw = Number(process.env.AWS_REGISTER_BACKGROUND_RETRY_INTERVAL);
37
+ return Number.isFinite(raw) && raw > 0 ? raw : DEFAULT_BACKGROUND_RETRY_INTERVAL_MS;
38
+ }
39
+ /** 后台重试定时器:key = 归一化 serverUrl,保证同一 target 只有一个重试循环 */
40
+ const backgroundRetryTimers = new Map();
41
+ /**
42
+ * 调度后台注册重试。
43
+ * bridge 先于 server 启动(或 server 临时不可用)时,前台重试耗尽后转入后台
44
+ * 持续重试,直到与调度中心建立连接为止。
45
+ */
46
+ function scheduleBackgroundRegisterRetry(config) {
47
+ const rawServerUrl = config.serverUrl || schedulerBaseUrl;
48
+ const key = normalizeSchedulerBaseUrl(rawServerUrl) || rawServerUrl;
49
+ if (backgroundRetryTimers.has(key)) {
50
+ return;
51
+ }
52
+ const timer = setTimeout(() => {
53
+ backgroundRetryTimers.delete(key);
54
+ void retryRegisterInBackground(config, key);
55
+ }, getBackgroundRetryIntervalMs());
56
+ // unref:后台重试不应阻止进程退出(优雅关闭/测试进程)
57
+ timer.unref?.();
58
+ backgroundRetryTimers.set(key, timer);
59
+ }
60
+ /**
61
+ * 后台重试注册:每次触发时重新从 config.json 读取该 target 的最新配置
62
+ *(运行期间修改配置可生效)。失败由 autoRegisterSingle 末尾自动调度下一次;
63
+ * 配置被禁用/删除(enabled=false 或无 userKey)时自然终止重试循环。
64
+ */
65
+ async function retryRegisterInBackground(config, key) {
66
+ try {
67
+ const fresh = loadConfigs().find((item) => (normalizeSchedulerBaseUrl(item.serverUrl || schedulerBaseUrl) ||
68
+ (item.serverUrl || schedulerBaseUrl)) === key) || config;
69
+ await autoRegisterSingle(fresh, { backgroundRetry: true });
70
+ }
71
+ catch (error) {
72
+ logger.warn(`[AutoRegister] 后台重试注册异常: ${error.message}`);
73
+ scheduleBackgroundRegisterRetry(config);
74
+ }
75
+ }
76
+ /** 停止所有后台注册重试(优雅关闭/测试清理用) */
77
+ export function cancelBackgroundRegisterRetries() {
78
+ for (const timer of backgroundRetryTimers.values()) {
79
+ clearTimeout(timer);
80
+ }
81
+ backgroundRetryTimers.clear();
82
+ }
32
83
  function normalizeOptionalString(value) {
33
84
  if (value == null) {
34
85
  return undefined;
@@ -73,11 +124,14 @@ function normalizeTargetConfig(source) {
73
124
  userKey: normalizeOptionalString(source.userKey),
74
125
  connectionKey,
75
126
  instanceName: normalizeOptionalString(source.instanceName),
127
+ instanceId: normalizeOptionalString(source.instanceId),
76
128
  projectName: normalizeOptionalString(source.projectName),
77
129
  roleName: normalizeOptionalString(source.roleName),
78
130
  workspacePath: normalizeOptionalString(source.workspacePath),
131
+ registerAddr: normalizeOptionalString(source.registerAddr),
79
132
  registerIp: normalizeOptionalString(source.registerIp),
80
133
  virtualIp: normalizeOptionalString(source.virtualIp),
134
+ tunnel: normalizeOptionalBoolean(source.tunnel),
81
135
  preferSameLanIp: normalizeOptionalBoolean(source.preferSameLanIp),
82
136
  maxRetries: normalizeOptionalNumber(source.maxRetries),
83
137
  retryInterval: normalizeOptionalNumber(source.retryInterval),
@@ -103,7 +157,7 @@ export function getAutoRegisterConfigFilePath() {
103
157
  * "serverUrl": "http://scheduler-host:7380", // 必填,要主动注册的 server 地址
104
158
  * "userKey": "aws_live_xxx", // 必填,用户 API Key
105
159
  * "instanceName": "my-bridge", // 必填/可选,默认主机名
106
- * "registerIp": "192.168.1.25", // 可选,优先作为注册 IP
160
+ * "registerAddr": "192.168.1.25:18081", // 可选,注册地址(推荐,支持 host:port / 纯 host / 完整 URL)
107
161
  * "connectionKey": "bridge-password" // 可选,不填则使用顶层 connectionKey
108
162
  * }
109
163
  * ],
@@ -115,7 +169,8 @@ export function getAutoRegisterConfigFilePath() {
115
169
  * "projectName": "default", // 可选
116
170
  * "roleName": "Bridge", // 可选
117
171
  * "workspacePath": "/path/to/workspace", // 可选
118
- * "registerIp": "192.168.1.25", // 可选,优先作为注册 IP
172
+ * "registerAddr": "192.168.1.25:18081", // 可选,注册地址(推荐)
173
+ * "registerIp": "192.168.1.25", // 可选,已废弃(仅纯 IP,端口由 AWS_RUNTIME_BRIDGE_PORT 决定)
119
174
  * "virtualIp": "10.144.144.1", // 可选,兼容 EasyTier 虚拟 IP
120
175
  * "maxRetries": 5, // 可选
121
176
  * "retryInterval": 5000 // 可选
@@ -203,6 +258,9 @@ function loadConfigFromEnv() {
203
258
  if (process.env.AWS_WORKSPACE_PATH) {
204
259
  envConfig.workspacePath = process.env.AWS_WORKSPACE_PATH;
205
260
  }
261
+ if (process.env.AWS_REGISTER_ADDR) {
262
+ envConfig.registerAddr = process.env.AWS_REGISTER_ADDR;
263
+ }
206
264
  if (process.env.AWS_REGISTER_IP) {
207
265
  envConfig.registerIp = process.env.AWS_REGISTER_IP;
208
266
  }
@@ -258,11 +316,15 @@ export function loadConfig() {
258
316
  userKey: merged.userKey || "",
259
317
  connectionKey: merged.connectionKey,
260
318
  instanceName,
319
+ instanceId: merged.instanceId,
261
320
  projectName: merged.projectName,
262
321
  roleName: merged.roleName,
263
322
  workspacePath: merged.workspacePath,
323
+ registerAddr: merged.registerAddr,
264
324
  registerIp: merged.registerIp,
265
325
  virtualIp: merged.virtualIp,
326
+ // 保留三态(true/false/undefined):isTunnelConfig 依赖 undefined 走向后兼容判定
327
+ tunnel: typeof merged.tunnel === "boolean" ? merged.tunnel : undefined,
266
328
  preferSameLanIp: merged.preferSameLanIp !== false,
267
329
  maxRetries: merged.maxRetries,
268
330
  retryInterval: merged.retryInterval,
@@ -292,11 +354,15 @@ export function loadConfigs() {
292
354
  userKey: merged.userKey || "",
293
355
  connectionKey: merged.connectionKey,
294
356
  instanceName: merged.instanceName || os.hostname(),
357
+ instanceId: merged.instanceId,
295
358
  projectName: merged.projectName,
296
359
  roleName: merged.roleName,
297
360
  workspacePath: merged.workspacePath,
361
+ registerAddr: merged.registerAddr,
298
362
  registerIp: merged.registerIp,
299
363
  virtualIp: merged.virtualIp,
364
+ // 保留三态(true/false/undefined):isTunnelConfig 依赖 undefined 走向后兼容判定
365
+ tunnel: typeof merged.tunnel === "boolean" ? merged.tunnel : undefined,
300
366
  preferSameLanIp: merged.preferSameLanIp !== false,
301
367
  maxRetries: merged.maxRetries,
302
368
  retryInterval: merged.retryInterval,
@@ -414,14 +480,62 @@ function getPreferredIpAddress(schedulerUrl) {
414
480
  function getLocalIpAddress(targetServerUrl = schedulerBaseUrl) {
415
481
  return getPreferredIpAddress(targetServerUrl);
416
482
  }
483
+ export function isTunnelConfig(config) {
484
+ const check = config || loadConfig();
485
+ if (!check.enabled || !check.userKey) {
486
+ return false;
487
+ }
488
+ // 显式 tunnel=true → 隧道模式
489
+ if (check.tunnel === true) {
490
+ return true;
491
+ }
492
+ // 显式 tunnel=false → 直连模式(用于 loopback 等不需要隧道的场景)
493
+ if (check.tunnel === false) {
494
+ return false;
495
+ }
496
+ // 未显式设置 tunnel:保持向后兼容——无 registerAddr/registerIp/virtualIp 即为隧道模式。
497
+ // 隧道模式下 bridge 位于 NAT/内网,没有可直接访问的地址,由 server 反向代理。
498
+ return !check.registerAddr && !check.registerIp && !check.virtualIp;
499
+ }
417
500
  function resolveRuntimeBridgeBaseUrl(config) {
418
501
  const port = process.env.AWS_RUNTIME_BRIDGE_PORT || 18081;
502
+ // 隧道模式:bridge 位于 NAT/内网,通过 WebSocket 反向连出到 server,
503
+ // server 经 /tunnel/<instanceId>/ 虚拟路径反向调用 bridge。
504
+ // 触发条件见 isTunnelConfig():显式 tunnel=true,或未填地址且未显式 tunnel=false。
505
+ // 此时 config.instanceId 必须已由 autoRegisterSingle 预声明(见 callers)。
506
+ if (isTunnelConfig(config)) {
507
+ const targetServerUrl = config.serverUrl || schedulerBaseUrl;
508
+ try {
509
+ const url = new URL(targetServerUrl);
510
+ // 隧道模式下 instanceId 必须已设,否则视为配置错误,降级到 localIp
511
+ if (!config.instanceId) {
512
+ logger.warn("[AutoRegister] 隧道模式但缺少 instanceId,降级为直连模式");
513
+ }
514
+ else {
515
+ return `${url.protocol}//${url.host}/tunnel/${config.instanceId}`;
516
+ }
517
+ }
518
+ catch {
519
+ logger.warn("[AutoRegister] serverUrl 解析失败,降级为直连模式");
520
+ }
521
+ }
419
522
  const localIp = config.preferSameLanIp === false
420
523
  ? "127.0.0.1"
421
524
  : getLocalIpAddress(config.serverUrl || schedulerBaseUrl);
422
- return `http://${config.registerIp || config.virtualIp || localIp}:${port}`;
525
+ // 优先级:registerAddr(推荐) > registerIp(已废弃,仅纯 host) > virtualIp > localIp
526
+ const raw = config.registerAddr || config.registerIp || config.virtualIp || localIp;
527
+ if (!raw) {
528
+ return `http://127.0.0.1:${port}`;
529
+ }
530
+ // 已带协议前缀(http:// / https://)→ 原样使用,支持反代/TLS/自定义端口场景
531
+ if (/^https?:\/\//i.test(raw)) {
532
+ return raw;
533
+ }
534
+ // 未带协议:统一补 http://;末尾无 :port 时补默认端口
535
+ const hasTrailingPort = /:[0-9]+$/.test(raw);
536
+ return hasTrailingPort ? `http://${raw}` : `http://${raw}:${port}`;
423
537
  }
424
- function loadPrimaryLifecycleConfig() {
538
+ export function loadPrimaryLifecycleConfig() {
425
539
  return loadConfigs()[0] || loadConfig();
426
540
  }
427
541
  function resolveRegisteredSchedulerBaseUrl(instanceId) {
@@ -458,9 +572,10 @@ async function doRegister(config) {
458
572
  const request = {
459
573
  tenantId: config.tenantId,
460
574
  userKey: config.userKey,
575
+ instanceId: config.instanceId,
461
576
  instanceName,
462
577
  hostname: os.hostname(),
463
- virtualIp: config.registerIp || config.virtualIp,
578
+ virtualIp: config.registerAddr || config.registerIp || config.virtualIp,
464
579
  runtimeBridgeBaseUrl: resolveRuntimeBridgeBaseUrl(config),
465
580
  connectionKey: config.connectionKey,
466
581
  workspacePath: config.workspacePath,
@@ -479,13 +594,61 @@ async function doRegister(config) {
479
594
  });
480
595
  return response.data;
481
596
  }
597
+ /** 串行化 config.json 回写,避免并行注册时并发写入冲突 */
598
+ let configWriteBackChain = Promise.resolve();
599
+ /**
600
+ * 将 server 返回的 instanceId 回写到 config.json 对应 target。
601
+ * 回写策略:读 → 找到 serverUrl 匹配的 target → 更新 instanceId → 写回。
602
+ * 仅在值变化时写入,避免不必要的文件 I/O。多 target 并行注册时通过 Promise 链串行化。
603
+ */
604
+ function writeBackInstanceInfoToConfig(targetServerUrl, instanceId) {
605
+ const task = configWriteBackChain.then(() => {
606
+ const configPath = getAutoRegisterConfigFilePath();
607
+ if (!fs.existsSync(configPath)) {
608
+ return;
609
+ }
610
+ const raw = fs.readFileSync(configPath, "utf-8");
611
+ const config = JSON.parse(raw);
612
+ const normalizedTargetUrl = normalizeSchedulerBaseUrl(targetServerUrl);
613
+ if (!normalizedTargetUrl) {
614
+ return;
615
+ }
616
+ let changed = false;
617
+ const updateTarget = (target) => {
618
+ const url = normalizeSchedulerBaseUrl(String(target.serverUrl || target.schedulerBaseUrl || ""));
619
+ if (url !== normalizedTargetUrl) {
620
+ return;
621
+ }
622
+ if (instanceId && target.instanceId !== instanceId) {
623
+ target.instanceId = instanceId;
624
+ changed = true;
625
+ }
626
+ };
627
+ if (Array.isArray(config.autoRegisterTargets)) {
628
+ for (const target of config.autoRegisterTargets) {
629
+ if (target && typeof target === "object" && !Array.isArray(target)) {
630
+ updateTarget(target);
631
+ }
632
+ }
633
+ }
634
+ else {
635
+ updateTarget(config);
636
+ }
637
+ if (changed) {
638
+ fs.writeFileSync(configPath, JSON.stringify(config, null, 2), "utf-8");
639
+ logger.info(`[AutoRegister] 已回写 instanceId 到 config.json (serverUrl=${targetServerUrl})`);
640
+ }
641
+ });
642
+ configWriteBackChain = task.catch(() => { });
643
+ return task;
644
+ }
482
645
  /**
483
646
  * 执行注销请求
484
647
  */
485
648
  async function doUnregister(instanceId) {
486
649
  const targetServerUrl = resolveLifecycleSchedulerBaseUrl(loadPrimaryLifecycleConfig(), instanceId);
487
650
  const binding = loadRuntimeBinding();
488
- const runtimeAccessToken = getRuntimeAccessToken(binding.userId, targetServerUrl);
651
+ const runtimeAccessToken = getRuntimeAccessToken(targetServerUrl);
489
652
  if (!runtimeAccessToken) {
490
653
  throw new Error("runtimeAccessToken is required to unregister bridge instance");
491
654
  }
@@ -519,7 +682,7 @@ export async function autoRegister(customConfig) {
519
682
  }
520
683
  return autoRegisterSingle(configs[0] || loadConfig());
521
684
  }
522
- async function autoRegisterSingle(config) {
685
+ async function autoRegisterSingle(config, options) {
523
686
  // 检查是否启用
524
687
  if (!config.enabled) {
525
688
  logger.info("[AutoRegister] 自动注册未启用");
@@ -531,8 +694,16 @@ async function autoRegisterSingle(config) {
531
694
  logger.error("[AutoRegister] 缺少用户 Key(在配置文件中设置 userKey 或设置环境变量 AWS_USER_KEY)");
532
695
  return false;
533
696
  }
697
+ // ★ 隧道模式:在注册前预声明 instanceId,确保 URL 与注册 request 中的 instanceId 一致
698
+ const isTunnel = isTunnelConfig(config);
699
+ if (isTunnel && !config.instanceId) {
700
+ // 用 uuid 前 12 位确保唯一可读
701
+ config = { ...config, instanceId: `bridge-${uuidv4().replace(/-/g, "").slice(0, 12)}` };
702
+ logger.info(`[AutoRegister] 隧道模式:已预声明 instanceId=${config.instanceId}`);
703
+ }
534
704
  // tenantId 现在是可选的,如果没有提供,后端会根据 userKey 自动推导
535
- const maxRetries = config.maxRetries ?? 3;
705
+ // 后台重试每轮只尝试 1 次,避免每个间隔内刷出一串重试日志
706
+ const maxRetries = options?.backgroundRetry ? 1 : (config.maxRetries ?? 3);
536
707
  const retryInterval = config.retryInterval ?? 2000;
537
708
  // 重试循环
538
709
  for (let attempt = 1; attempt <= maxRetries; attempt++) {
@@ -560,6 +731,12 @@ async function autoRegisterSingle(config) {
560
731
  schedulerBaseUrl: response.serverUrl || config.serverUrl || schedulerBaseUrl,
561
732
  });
562
733
  logger.info("[AutoRegister] 已保存调度中心下发的 runtime access token");
734
+ // 回写 instanceId 到 config.json,供后续 instanceId 匹配使用
735
+ if (response.instanceId) {
736
+ writeBackInstanceInfoToConfig(config.serverUrl || schedulerBaseUrl, response.instanceId).catch((error) => {
737
+ logger.warn(`[AutoRegister] 回写 instanceId 到 config.json 失败: ${error.message}`);
738
+ });
739
+ }
563
740
  }
564
741
  catch (error) {
565
742
  const err = error;
@@ -571,6 +748,15 @@ async function autoRegisterSingle(config) {
571
748
  else {
572
749
  logger.warn("[AutoRegister] 注册响应未包含 runtime access token,MCP 将无法访问调度中心,请检查 server 的 bridge 实例 token 颁发逻辑");
573
750
  }
751
+ // ★ 隧道模式:注册成功且拿到 runtimeAccessToken 后,使用 server 返回的真实 instanceId 启动隧道客户端。
752
+ // 没有 runtimeAccessToken 时隧道鉴权必然失败,跳过启动以免反复重连刷日志。
753
+ // 多 target 场景:传入本次注册的 serverUrl,隧道客户端按 server 维度多实例并存。
754
+ if (isTunnel && response.instanceId && response.runtimeAccessToken) {
755
+ const { startTunnelClient } = await import("./tunnel-client.js");
756
+ const tunnelServerUrl = config.serverUrl || schedulerBaseUrl;
757
+ startTunnelClient(tunnelServerUrl, response.instanceId);
758
+ logger.info(`[AutoRegister] 隧道客户端已启动: server=${tunnelServerUrl}, instanceId=${response.instanceId}`);
759
+ }
574
760
  return true;
575
761
  }
576
762
  else {
@@ -592,17 +778,26 @@ async function autoRegisterSingle(config) {
592
778
  await new Promise((resolve) => setTimeout(resolve, retryInterval));
593
779
  }
594
780
  }
595
- logger.error(`[AutoRegister] ✗ 注册失败,已达最大重试次数`);
596
- logger.error(`[AutoRegister] ========================================`);
597
- logger.error(`[AutoRegister] 自动注册已启用但注册失败,实例无法正常工作`);
598
- logger.error(`[AutoRegister] 请检查以下配置:`);
599
- logger.error(`[AutoRegister] - 用户 Key (userKey): ${config.userKey ? "****" + config.userKey.slice(-4) : "(未设置)"}`);
600
- logger.error(`[AutoRegister] - 租户 ID (tenantId): ${config.tenantId || "(可选,将自动推导)"}`);
601
- logger.error(`[AutoRegister] - 实例名 (instanceName): ${config.instanceName || "(使用主机名)"}`);
602
- logger.error(`[AutoRegister] - 调度中心地址: ${config.serverUrl || schedulerBaseUrl}`);
603
- logger.error(`[AutoRegister] - 最后错误: ${registrationState.error || "未知"}`);
604
- logger.error(`[AutoRegister] ========================================`);
605
- logger.error(`[AutoRegister] 配置来源:~/.aws-bridge/config.json 或环境变量`);
781
+ if (options?.backgroundRetry) {
782
+ // 后台重试轮:单行日志,避免每个间隔刷一大段错误块
783
+ logger.warn(`[AutoRegister] 后台重试注册仍未成功 (server=${config.serverUrl || schedulerBaseUrl}): ${registrationState.error || "未知"}`);
784
+ }
785
+ else {
786
+ logger.error(`[AutoRegister] 注册失败,已达最大重试次数`);
787
+ logger.error(`[AutoRegister] ========================================`);
788
+ logger.error(`[AutoRegister] 自动注册已启用但注册失败,实例暂时无法正常工作`);
789
+ logger.error(`[AutoRegister] 请检查以下配置:`);
790
+ logger.error(`[AutoRegister] - 用户 Key (userKey): ${config.userKey ? "****" + config.userKey.slice(-4) : "(未设置)"}`);
791
+ logger.error(`[AutoRegister] - 租户 ID (tenantId): ${config.tenantId || "(可选,将自动推导)"}`);
792
+ logger.error(`[AutoRegister] - 实例名 (instanceName): ${config.instanceName || "(使用主机名)"}`);
793
+ logger.error(`[AutoRegister] - 调度中心地址: ${config.serverUrl || schedulerBaseUrl}`);
794
+ logger.error(`[AutoRegister] - 最后错误: ${registrationState.error || "未知"}`);
795
+ logger.error(`[AutoRegister] ========================================`);
796
+ logger.error(`[AutoRegister] 配置来源:~/.aws-bridge/config.json 或环境变量`);
797
+ logger.warn(`[AutoRegister] 将在后台持续重试注册(每 ${Math.round(getBackgroundRetryIntervalMs() / 1000)} 秒),直到与调度中心建立连接`);
798
+ }
799
+ // 未与 server 建立连接前持续后台重试;成功/配置失效(禁用、缺 userKey)时自动停止
800
+ scheduleBackgroundRegisterRetry(config);
606
801
  return false;
607
802
  }
608
803
  /**
@@ -618,9 +813,7 @@ export async function requestRuntimeAccessTokenRefresh() {
618
813
  }
619
814
  const state = getRuntimeBindingPublicState();
620
815
  const targetServerUrl = resolveLifecycleSchedulerBaseUrl(config);
621
- const localIp = getLocalIpAddress(targetServerUrl);
622
- const runtimeBridgePort = process.env.AWS_RUNTIME_BRIDGE_PORT || 18081;
623
- const runtimeBridgeBaseUrl = `http://${config.registerIp || config.virtualIp || localIp}:${runtimeBridgePort}`;
816
+ const runtimeBridgeBaseUrl = resolveRuntimeBridgeBaseUrl(config);
624
817
  try {
625
818
  const response = await axios.post(`${targetServerUrl}/api/instances/runtime-tokens/refresh`, {
626
819
  tenantId: config.tenantId,
@@ -676,9 +869,7 @@ export async function requestRuntimeAccessTokenRefreshForServer(serverBaseUrl) {
676
869
  };
677
870
  }
678
871
  const state = getRuntimeBindingPublicState();
679
- const localIp = getLocalIpAddress(targetServerUrl);
680
- const runtimeBridgePort = process.env.AWS_RUNTIME_BRIDGE_PORT || 18081;
681
- const runtimeBridgeBaseUrl = `http://${config.registerIp || config.virtualIp || localIp}:${runtimeBridgePort}`;
872
+ const runtimeBridgeBaseUrl = resolveRuntimeBridgeBaseUrl(config);
682
873
  try {
683
874
  const response = await axios.post(`${targetServerUrl}/api/instances/runtime-tokens/refresh`, {
684
875
  tenantId: config.tenantId,
@@ -699,11 +890,9 @@ export async function requestRuntimeAccessTokenRefreshForServer(serverBaseUrl) {
699
890
  "scheduler did not return runtimeAccessToken",
700
891
  };
701
892
  }
702
- const userId = response.data.userId || config.userKey;
703
- const previousToken = getRuntimeAccessToken(userId, targetServerUrl);
893
+ const previousToken = getRuntimeAccessToken(targetServerUrl);
704
894
  const updated = previousToken !== response.data.runtimeAccessToken;
705
895
  saveScopedRuntimeAccessToken({
706
- userId,
707
896
  serverBaseUrl: targetServerUrl,
708
897
  accessToken: response.data.runtimeAccessToken,
709
898
  });
@@ -732,8 +921,8 @@ export async function unregister() {
732
921
  logger.info(`[AutoRegister] ✓ 注销成功: ${registrationState.instanceId}`);
733
922
  const targetServerUrl = resolveLifecycleSchedulerBaseUrl(loadPrimaryLifecycleConfig(), registrationState.instanceId);
734
923
  const binding = loadRuntimeBinding();
735
- if (binding.userId) {
736
- clearScopedRuntimeAccessToken(binding.userId, targetServerUrl);
924
+ if (binding.schedulerBaseUrl) {
925
+ clearScopedRuntimeAccessToken(targetServerUrl);
737
926
  }
738
927
  clearRuntimeBinding();
739
928
  registrationState.registered = false;
@@ -792,9 +981,7 @@ export async function bridgeRestartCleanup() {
792
981
  }
793
982
  // 如果有配置,也传入 runtimeBridgeBaseUrl
794
983
  if (config.enabled) {
795
- const localIp = getLocalIpAddress(targetServerUrl);
796
- const port = process.env.AWS_RUNTIME_BRIDGE_PORT || 18081;
797
- requestBody.runtimeBridgeBaseUrl = `http://${config.registerIp || config.virtualIp || localIp}:${port}`;
984
+ requestBody.runtimeBridgeBaseUrl = resolveRuntimeBridgeBaseUrl(config);
798
985
  }
799
986
  if (!requestBody.instanceId && !requestBody.runtimeBridgeBaseUrl) {
800
987
  logger.info("[AutoRegister] Bridge 重启清理:没有 instanceId 或 runtimeBridgeBaseUrl,跳过清理");
@@ -1 +1 @@
1
- {"version":3,"file":"cli-commands.d.ts","sourceRoot":"","sources":["../../src/services/cli-commands.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,4BAA4B,CAAC;AAM5E,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,KAAK,CAAC,EAAE,KAAK,CAAC;CACf;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,gBAAgB,CAAC;IACnE,SAAS,CAAC,EAAE,MAAM,OAAO,CAAC,yBAAyB,CAAC,CAAC;IACrD,QAAQ,CAAC,EAAE,MAAM,CAAC,QAAQ,CAAC;IAC3B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAYD,wBAAgB,kBAAkB,CAAC,WAAW,SAA0B,GAAG,MAAM,CAMhF;AAgCD;;GAEG;AACH,wBAAgB,wBAAwB,CAAC,cAAc,EAAE,MAAM,GAAG,MAAM,CAsBvE;AAwOD,wBAAsB,gBAAgB,CACpC,OAAO,GAAE,iBAAsB,GAC9B,OAAO,CAAC,gBAAgB,CAAC,CA+C3B"}
1
+ {"version":3,"file":"cli-commands.d.ts","sourceRoot":"","sources":["../../src/services/cli-commands.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,4BAA4B,CAAC;AAM5E,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,KAAK,CAAC,EAAE,KAAK,CAAC;CACf;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,gBAAgB,CAAC;IACnE,SAAS,CAAC,EAAE,MAAM,OAAO,CAAC,yBAAyB,CAAC,CAAC;IACrD,QAAQ,CAAC,EAAE,MAAM,CAAC,QAAQ,CAAC;IAC3B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAYD,wBAAgB,kBAAkB,CAAC,WAAW,SAA0B,GAAG,MAAM,CAMhF;AAgCD;;GAEG;AACH,wBAAgB,wBAAwB,CAAC,cAAc,EAAE,MAAM,GAAG,MAAM,CAsBvE;AAwOD,wBAAsB,gBAAgB,CACpC,OAAO,GAAE,iBAAsB,GAC9B,OAAO,CAAC,gBAAgB,CAAC,CAgD3B"}
@@ -241,6 +241,7 @@ export async function handleCliCommand(options = {}) {
241
241
  "install",
242
242
  "-g",
243
243
  "aws-runtime-bridge@latest",
244
+ "--omit=optional",
244
245
  ]);
245
246
  if (result.error) {
246
247
  stderr(`[runtime-bridge] 更新失败: ${result.error.message}`);
@@ -12,7 +12,7 @@ const pushStates = new Map();
12
12
  function runtimeAuthHeaders(authOptions, callbackBaseUrl) {
13
13
  const resolvedBaseUrl = callbackBaseUrl ?? resolveSchedulerBaseUrlFrom(authOptions?.schedulerBaseUrl).url;
14
14
  const token = authOptions?.runtimeAccessToken ||
15
- getRuntimeAccessToken(undefined, resolvedBaseUrl) ||
15
+ getRuntimeAccessToken(resolvedBaseUrl) ||
16
16
  getRuntimeAccessToken();
17
17
  return token ? { "X-Runtime-Token": token } : undefined;
18
18
  }
@@ -66,7 +66,7 @@ async function sendLifecycleNotification(operation) {
66
66
  const schedulerBaseUrl = normalizeSchedulerBaseUrl(operation.schedulerBaseUrl) ||
67
67
  normalizeSchedulerBaseUrl(loadRuntimeBinding().schedulerBaseUrl) ||
68
68
  resolveSchedulerBaseUrlFrom(undefined).url;
69
- const token = getRuntimeAccessToken(operation.requestedByUserId, schedulerBaseUrl);
69
+ const token = getRuntimeAccessToken(schedulerBaseUrl);
70
70
  if (!token) {
71
71
  throw new Error("runtime access token is missing");
72
72
  }
@@ -126,7 +126,7 @@ export function claimMcpLaunchBinding(request) {
126
126
  const runtimeState = loadRuntimeBinding();
127
127
  const userId = binding.userId || runtimeState.userId;
128
128
  const schedulerBaseUrl = binding.schedulerBaseUrl || runtimeState.schedulerBaseUrl;
129
- const runtimeAccessToken = binding.runtimeAccessToken || getRuntimeAccessToken(userId, schedulerBaseUrl);
129
+ const runtimeAccessToken = binding.runtimeAccessToken || getRuntimeAccessToken(schedulerBaseUrl);
130
130
  return {
131
131
  ...binding,
132
132
  runtimeAccessToken,
@@ -54,6 +54,11 @@ export declare class OrphanMonitor {
54
54
  * 清理已死亡的会话记录
55
55
  */
56
56
  private cleanupDeadSessions;
57
+ /**
58
+ * 向 server 查询 agent 是否仍然存在。
59
+ * 返回 true=存在, false=已删除, null=无法确认(网络错误/认证失败等)。
60
+ */
61
+ private checkAgentExistsOnServer;
57
62
  /**
58
63
  * 上报事件到调度中心
59
64
  */
@@ -1 +1 @@
1
- {"version":3,"file":"orphan-monitor.d.ts","sourceRoot":"","sources":["../../src/services/orphan-monitor.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AA0BH;;GAEG;AACH,MAAM,MAAM,eAAe,GACvB,iBAAiB,GACjB,gBAAgB,GAChB,sBAAsB,GACtB,kBAAkB,GAClB,qBAAqB,GACrB,cAAc,CAAC;AAEnB;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,eAAe,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,IAAI,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACnC;AAED;;GAEG;AACH,qBAAa,aAAa;IACxB,OAAO,CAAC,UAAU,CAA+B;IACjD,OAAO,CAAC,YAAY,CAAqB;IACzC,OAAO,CAAC,cAAc,CAA2C;IACjE,OAAO,CAAC,OAAO,CAAkB;IAEjC;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAoB5B;;OAEG;IACH,IAAI,IAAI,IAAI;IASZ;;OAEG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IA0E3B;;OAEG;YACW,oBAAoB;IAoClC;;OAEG;YACW,iBAAiB;IAwC/B;;OAEG;YACW,eAAe;IA0B7B;;OAEG;YACW,mBAAmB;IAsBjC;;OAEG;YACW,iBAAiB;IA8C/B;;OAEG;IACH,OAAO,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,WAAW,KAAK,IAAI,GAAG,IAAI;IAIrD;;OAEG;IACH,QAAQ,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,WAAW,KAAK,IAAI,GAAG,IAAI;IAOtD;;OAEG;IACH,OAAO,CAAC,IAAI;IAUZ;;OAEG;IACH,SAAS,IAAI;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,YAAY,EAAE,IAAI,GAAG,IAAI,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE;CAO3E;AAKD;;GAEG;AACH,wBAAgB,gBAAgB,IAAI,aAAa,CAKhD;AAED;;GAEG;AACH,wBAAsB,kBAAkB,IAAI,OAAO,CAAC,IAAI,CAAC,CAGxD;AAED;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,IAAI,CAGxC"}
1
+ {"version":3,"file":"orphan-monitor.d.ts","sourceRoot":"","sources":["../../src/services/orphan-monitor.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AA0BH;;GAEG;AACH,MAAM,MAAM,eAAe,GACvB,iBAAiB,GACjB,gBAAgB,GAChB,sBAAsB,GACtB,kBAAkB,GAClB,qBAAqB,GACrB,cAAc,CAAC;AAEnB;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,eAAe,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,IAAI,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACnC;AAED;;GAEG;AACH,qBAAa,aAAa;IACxB,OAAO,CAAC,UAAU,CAA+B;IACjD,OAAO,CAAC,YAAY,CAAqB;IACzC,OAAO,CAAC,cAAc,CAA2C;IACjE,OAAO,CAAC,OAAO,CAAkB;IAEjC;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAoB5B;;OAEG;IACH,IAAI,IAAI,IAAI;IASZ;;OAEG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IA0E3B;;OAEG;YACW,oBAAoB;IA8ClC;;OAEG;YACW,iBAAiB;IAwC/B;;OAEG;YACW,eAAe;IA0B7B;;OAEG;YACW,mBAAmB;IAsBjC;;;OAGG;YACW,wBAAwB;IAmCtC;;OAEG;YACW,iBAAiB;IA8C/B;;OAEG;IACH,OAAO,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,WAAW,KAAK,IAAI,GAAG,IAAI;IAIrD;;OAEG;IACH,QAAQ,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,WAAW,KAAK,IAAI,GAAG,IAAI;IAOtD;;OAEG;IACH,OAAO,CAAC,IAAI;IAUZ;;OAEG;IACH,SAAS,IAAI;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,YAAY,EAAE,IAAI,GAAG,IAAI,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE;CAO3E;AAKD;;GAEG;AACH,wBAAgB,gBAAgB,IAAI,aAAa,CAKhD;AAED;;GAEG;AACH,wBAAsB,kBAAkB,IAAI,OAAO,CAAC,IAAI,CAAC,CAGxD;AAED;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,IAAI,CAGxC"}
@@ -127,7 +127,16 @@ export class OrphanMonitor {
127
127
  };
128
128
  this.emit(event);
129
129
  logger.warn(`检测到孤儿进程: agentId=${agentId}, pid=${pid}`);
130
- // 根据模式处理。auto 模式也必须经过显式清理开关,避免重启恢复时误杀保留会话。
130
+ // 优先向 server 确认 agent 是否已被删除。如果已删除,直接自动终止残留进程,
131
+ // 绕过 ORPHAN_AUTO_CLEAN_MODE 和双重开关保护——因为 agent 已明确不存在,
132
+ // 残留进程不可能再被恢复,继续运行只会浪费资源。
133
+ const agentExists = await this.checkAgentExistsOnServer(agentId);
134
+ if (agentExists === false) {
135
+ logger.info(`agent ${agentId} 已从服务端删除,自动终止残留进程 pid=${pid}`);
136
+ await this.autoCleanOrphan(agentId, pid);
137
+ return;
138
+ }
139
+ // agent 仍存在或无法确认时,按原有模式处理
131
140
  switch (ORPHAN_AUTO_CLEAN_MODE) {
132
141
  case 'auto':
133
142
  if (shouldAutoCleanOrphanProcesses()) {
@@ -229,6 +238,41 @@ export class OrphanMonitor {
229
238
  await savePersistedSessions(aliveSessions);
230
239
  }
231
240
  }
241
+ /**
242
+ * 向 server 查询 agent 是否仍然存在。
243
+ * 返回 true=存在, false=已删除, null=无法确认(网络错误/认证失败等)。
244
+ */
245
+ async checkAgentExistsOnServer(agentId) {
246
+ if (this.stopped) {
247
+ return null;
248
+ }
249
+ try {
250
+ const runtimeAccessToken = getRuntimeAccessToken(schedulerBaseUrl) || getRuntimeAccessToken();
251
+ if (!runtimeAccessToken) {
252
+ logger.debug('缺少 runtimeAccessToken,无法查询 agent 存在性');
253
+ return null;
254
+ }
255
+ const response = await fetch(`${schedulerBaseUrl}/api/runtime/callback/agent-exists`, {
256
+ method: 'POST',
257
+ headers: {
258
+ 'Content-Type': 'application/json',
259
+ 'X-Runtime-Token': runtimeAccessToken,
260
+ },
261
+ body: JSON.stringify({ agentId }),
262
+ signal: AbortSignal.timeout(5000),
263
+ });
264
+ if (!response.ok) {
265
+ logger.debug(`查询 agent 存在性失败: ${response.status}`);
266
+ return null;
267
+ }
268
+ const data = await response.json();
269
+ return data.exists === true;
270
+ }
271
+ catch (error) {
272
+ logger.debug('查询 agent 存在性异常:', error);
273
+ return null;
274
+ }
275
+ }
232
276
  /**
233
277
  * 上报事件到调度中心
234
278
  */
@@ -239,16 +283,16 @@ export class OrphanMonitor {
239
283
  return;
240
284
  }
241
285
  try {
242
- const runtimeAccessToken = getRuntimeAccessToken(undefined, schedulerBaseUrl) || getRuntimeAccessToken();
286
+ const runtimeAccessToken = getRuntimeAccessToken(schedulerBaseUrl) || getRuntimeAccessToken();
243
287
  if (!runtimeAccessToken) {
244
288
  logger.debug(`缺少 runtimeAccessToken,跳过上报: ${eventType}`);
245
289
  return;
246
290
  }
247
- const response = await fetch(`${schedulerBaseUrl}/api/runtime/orphan-event`, {
291
+ const response = await fetch(`${schedulerBaseUrl}/api/runtime/callback/orphan-event`, {
248
292
  method: 'POST',
249
293
  headers: {
250
294
  'Content-Type': 'application/json',
251
- 'Authorization': `Bearer ${runtimeAccessToken}`,
295
+ 'X-Runtime-Token': runtimeAccessToken,
252
296
  },
253
297
  body: JSON.stringify({
254
298
  agentId,
@@ -18,21 +18,20 @@ export declare function normalizeSchedulerBaseUrl(value: unknown): string | unde
18
18
  export declare function getRuntimePairingCode(): string;
19
19
  export declare function getRuntimeBindingFilePath(): string;
20
20
  export declare function getRuntimeTokenStoreFilePath(): string;
21
- export declare function buildRuntimeTokenKey(userId: unknown, serverBaseUrl: unknown): string;
21
+ export declare function buildRuntimeTokenKey(serverBaseUrl: unknown): string;
22
22
  export declare function saveScopedRuntimeAccessToken(input: {
23
- userId: string;
24
23
  serverBaseUrl: string;
25
24
  accessToken: string;
26
25
  }): string;
27
- export declare function getScopedRuntimeAccessToken(userId: unknown, serverBaseUrl: unknown): string | undefined;
28
- export declare function clearScopedRuntimeAccessToken(userId: unknown, serverBaseUrl: unknown): boolean;
26
+ export declare function getScopedRuntimeAccessToken(serverBaseUrl: unknown): string | undefined;
27
+ export declare function clearScopedRuntimeAccessToken(serverBaseUrl: unknown): boolean;
29
28
  export declare function loadRuntimeBinding(): RuntimeBindingState;
30
29
  export declare function getRuntimeBindingPublicState(): Omit<RuntimeBindingState, "tokenHash" | "accessToken"> & {
31
30
  paired: boolean;
32
31
  };
33
32
  export declare function hasRuntimeBinding(): boolean;
34
33
  export declare function validateRuntimeBindingToken(token: unknown): boolean;
35
- export declare function getRuntimeAccessToken(userId?: unknown, serverBaseUrl?: unknown): string | undefined;
34
+ export declare function getRuntimeAccessToken(serverBaseUrl?: unknown): string | undefined;
36
35
  export declare function validateRuntimePairingCode(code: unknown): boolean;
37
36
  export declare function saveRuntimeBinding(input: {
38
37
  accessToken: string;
@@ -1 +1 @@
1
- {"version":3,"file":"runtime-binding.d.ts","sourceRoot":"","sources":["../../src/services/runtime-binding.ts"],"names":[],"mappings":"AASA,MAAM,MAAM,mBAAmB,GAAG;IAChC,MAAM,EAAE,UAAU,GAAG,QAAQ,CAAC;IAC9B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B;;;;OAIG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAmEF,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAqB5E;AAED,wBAAgB,qBAAqB,IAAI,MAAM,CAE9C;AAED,wBAAgB,yBAAyB,IAAI,MAAM,CAElD;AAED,wBAAgB,4BAA4B,IAAI,MAAM,CAErD;AAiCD,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,OAAO,EACf,aAAa,EAAE,OAAO,GACrB,MAAM,CAYR;AAsCD,wBAAgB,4BAA4B,CAAC,KAAK,EAAE;IAClD,MAAM,EAAE,MAAM,CAAC;IACf,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,MAAM,CAAC;CACrB,GAAG,MAAM,CAWT;AAED,wBAAgB,2BAA2B,CACzC,MAAM,EAAE,OAAO,EACf,aAAa,EAAE,OAAO,GACrB,MAAM,GAAG,SAAS,CAUpB;AAED,wBAAgB,6BAA6B,CAC3C,MAAM,EAAE,OAAO,EACf,aAAa,EAAE,OAAO,GACrB,OAAO,CAeT;AAcD,wBAAgB,kBAAkB,IAAI,mBAAmB,CAgBxD;AAED,wBAAgB,4BAA4B,IAAI,IAAI,CAClD,mBAAmB,EACnB,WAAW,GAAG,aAAa,CAC5B,GAAG;IAAE,MAAM,EAAE,OAAO,CAAA;CAAE,CAWtB;AAED,wBAAgB,iBAAiB,IAAI,OAAO,CAG3C;AAED,wBAAgB,2BAA2B,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAcnE;AAED,wBAAgB,qBAAqB,CACnC,MAAM,CAAC,EAAE,OAAO,EAChB,aAAa,CAAC,EAAE,OAAO,GACtB,MAAM,GAAG,SAAS,CAyBpB;AAED,wBAAgB,0BAA0B,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAEjE;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE;IACxC,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B,GAAG,mBAAmB,CAwCtB;AAED,wBAAgB,mBAAmB,IAAI,IAAI,CAkB1C;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,IAAI,IAAI,CA0B3C"}
1
+ {"version":3,"file":"runtime-binding.d.ts","sourceRoot":"","sources":["../../src/services/runtime-binding.ts"],"names":[],"mappings":"AASA,MAAM,MAAM,mBAAmB,GAAG;IAChC,MAAM,EAAE,UAAU,GAAG,QAAQ,CAAC;IAC9B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B;;;;OAIG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAmEF,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAqB5E;AAED,wBAAgB,qBAAqB,IAAI,MAAM,CAE9C;AAED,wBAAgB,yBAAyB,IAAI,MAAM,CAElD;AAED,wBAAgB,4BAA4B,IAAI,MAAM,CAErD;AAiCD,wBAAgB,oBAAoB,CAClC,aAAa,EAAE,OAAO,GACrB,MAAM,CAWR;AAsCD,wBAAgB,4BAA4B,CAAC,KAAK,EAAE;IAClD,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,MAAM,CAAC;CACrB,GAAG,MAAM,CAWT;AAED,wBAAgB,2BAA2B,CACzC,aAAa,EAAE,OAAO,GACrB,MAAM,GAAG,SAAS,CAUpB;AAED,wBAAgB,6BAA6B,CAC3C,aAAa,EAAE,OAAO,GACrB,OAAO,CAeT;AAcD,wBAAgB,kBAAkB,IAAI,mBAAmB,CAgBxD;AAED,wBAAgB,4BAA4B,IAAI,IAAI,CAClD,mBAAmB,EACnB,WAAW,GAAG,aAAa,CAC5B,GAAG;IAAE,MAAM,EAAE,OAAO,CAAA;CAAE,CAWtB;AAED,wBAAgB,iBAAiB,IAAI,OAAO,CAG3C;AAED,wBAAgB,2BAA2B,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAcnE;AAED,wBAAgB,qBAAqB,CACnC,aAAa,CAAC,EAAE,OAAO,GACtB,MAAM,GAAG,SAAS,CAyBpB;AAED,wBAAgB,0BAA0B,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAEjE;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE;IACxC,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B,GAAG,mBAAmB,CAuCtB;AAED,wBAAgB,mBAAmB,IAAI,IAAI,CAkB1C;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,IAAI,IAAI,CA0B3C"}