@fengye404/termpilot 0.2.1 → 0.2.3

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 (2) hide show
  1. package/dist/cli.js +54 -7
  2. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -652,8 +652,7 @@ function createDaemonFromEnv() {
652
652
  function isLocalRelayHost(hostname) {
653
653
  return hostname === "localhost" || hostname === "127.0.0.1" || hostname === "::1" || /^10\./.test(hostname) || /^192\.168\./.test(hostname) || /^172\.(1[6-9]|2\d|3[0-1])\./.test(hostname);
654
654
  }
655
- function getRelayBaseCandidates() {
656
- const relayUrl = process.env.TERMPILOT_RELAY_URL ?? "ws://127.0.0.1:8787/ws";
655
+ function getRelayBaseCandidates(relayUrl = process.env.TERMPILOT_RELAY_URL ?? "ws://127.0.0.1:8787/ws") {
657
656
  let url;
658
657
  try {
659
658
  url = new URL(relayUrl);
@@ -686,6 +685,32 @@ function getRelayBaseCandidates() {
686
685
  }
687
686
  return candidates;
688
687
  }
688
+ async function isRelayReachable(baseUrl) {
689
+ try {
690
+ const response = await fetch(new URL("/health", baseUrl), {
691
+ signal: AbortSignal.timeout(2e3)
692
+ });
693
+ return response.ok;
694
+ } catch {
695
+ return false;
696
+ }
697
+ }
698
+ async function resolvePreferredRelayUrl(relayUrl) {
699
+ const candidates = getRelayBaseCandidates(relayUrl);
700
+ if (candidates.length === 1) {
701
+ return candidates[0].relayUrl;
702
+ }
703
+ const primary = candidates[0];
704
+ if (await isRelayReachable(primary.baseUrl)) {
705
+ return primary.relayUrl;
706
+ }
707
+ for (const candidate of candidates.slice(1)) {
708
+ if (await isRelayReachable(candidate.baseUrl)) {
709
+ return candidate.relayUrl;
710
+ }
711
+ }
712
+ return primary.relayUrl;
713
+ }
689
714
  function getAgentToken() {
690
715
  return process.env.TERMPILOT_AGENT_TOKEN ?? DEFAULT_AGENT_TOKEN;
691
716
  }
@@ -712,11 +737,10 @@ async function fetchJson(input, init, message) {
712
737
  lastError = error;
713
738
  continue;
714
739
  }
715
- const payload = await readJsonOrThrow(response, message);
716
740
  if (process.env.TERMPILOT_RELAY_URL !== candidate.relayUrl) {
717
741
  process.env.TERMPILOT_RELAY_URL = candidate.relayUrl;
718
742
  }
719
- return payload;
743
+ return readJsonOrThrow(response, message);
720
744
  }
721
745
  const detail = lastError instanceof Error ? lastError.message : "\u672A\u77E5\u7F51\u7EDC\u9519\u8BEF";
722
746
  throw new Error(`${message}: \u65E0\u6CD5\u8FDE\u63A5 relay (${lastOrigin})\uFF0C${detail}`);
@@ -996,8 +1020,9 @@ function applyAgentConfig(config) {
996
1020
  function persistMigratedRelayUrl(deviceId) {
997
1021
  const migratedRelayUrl = process.env.TERMPILOT_RELAY_URL?.trim();
998
1022
  if (!migratedRelayUrl) {
999
- return;
1023
+ return false;
1000
1024
  }
1025
+ let changed = false;
1001
1026
  const saved = loadAgentConfig();
1002
1027
  if (saved && saved.deviceId === deviceId && saved.relayUrl !== migratedRelayUrl) {
1003
1028
  saveAgentConfig({
@@ -1005,6 +1030,7 @@ function persistMigratedRelayUrl(deviceId) {
1005
1030
  deviceId
1006
1031
  });
1007
1032
  console.log(`\u5DF2\u81EA\u52A8\u66F4\u65B0 relay \u5730\u5740\u4E3A: ${migratedRelayUrl}`);
1033
+ changed = true;
1008
1034
  }
1009
1035
  const runtime = loadAgentRuntime();
1010
1036
  if (runtime && runtime.deviceId === deviceId && runtime.relayUrl !== migratedRelayUrl) {
@@ -1012,7 +1038,9 @@ function persistMigratedRelayUrl(deviceId) {
1012
1038
  ...runtime,
1013
1039
  relayUrl: migratedRelayUrl
1014
1040
  });
1041
+ changed = true;
1015
1042
  }
1043
+ return changed;
1016
1044
  }
1017
1045
  function printRuntimeStatus(runtime = readRuntimeStatus().runtime) {
1018
1046
  if (!runtime) {
@@ -1061,6 +1089,7 @@ async function waitForPairingCode(deviceId) {
1061
1089
  return payload;
1062
1090
  } catch (error) {
1063
1091
  lastError = error;
1092
+ persistMigratedRelayUrl(deviceId);
1064
1093
  await delay2(500);
1065
1094
  }
1066
1095
  }
@@ -1072,9 +1101,19 @@ async function waitForPairingCode(deviceId) {
1072
1101
  async function runStart(argv) {
1073
1102
  const args = parseArgs(argv);
1074
1103
  const shouldPair = Boolean(args.pair);
1075
- const { config, source } = await ensureConfigured(argv);
1104
+ const resolved = await ensureConfigured(argv);
1105
+ let { config } = resolved;
1106
+ const { source } = resolved;
1107
+ const preferredRelayUrl = await resolvePreferredRelayUrl(config.relayUrl);
1108
+ if (preferredRelayUrl !== config.relayUrl) {
1109
+ config = {
1110
+ ...config,
1111
+ relayUrl: preferredRelayUrl
1112
+ };
1113
+ console.log(`\u5DF2\u81EA\u52A8\u4FEE\u6B63 relay \u5730\u5740\u4E3A: ${preferredRelayUrl}`);
1114
+ }
1076
1115
  applyAgentConfig(config);
1077
- if (source === "cli" || source === "prompt") {
1116
+ if (source === "cli" || source === "prompt" || source === "saved") {
1078
1117
  saveAgentConfig(config);
1079
1118
  }
1080
1119
  if (args.foreground) {
@@ -1096,6 +1135,14 @@ async function runStart(argv) {
1096
1135
  if (pairing) {
1097
1136
  console.log(`\u914D\u5BF9\u7801: ${pairing.pairingCode}`);
1098
1137
  console.log(`\u6709\u6548\u671F\u81F3: ${pairing.expiresAt}`);
1138
+ } else {
1139
+ const migrated = loadAgentConfig();
1140
+ if (migrated && migrated.deviceId === deviceId && migrated.relayUrl !== existing.runtime.relayUrl) {
1141
+ console.log("\u68C0\u6D4B\u5230\u540E\u53F0 agent \u4ECD\u5728\u4F7F\u7528\u65E7 relay \u5730\u5740\uFF0C\u6B63\u5728\u81EA\u52A8\u91CD\u542F\u540E\u91CD\u8BD5\u3002");
1142
+ await runStop();
1143
+ await runStart(argv);
1144
+ return;
1145
+ }
1099
1146
  }
1100
1147
  } else {
1101
1148
  console.log("\u5982\u9700\u91CD\u65B0\u7ED9\u624B\u673A\u914D\u5BF9\uFF0C\u8BF7\u6267\u884C\uFF1Atermpilot agent --pair");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fengye404/termpilot",
3
- "version": "0.2.1",
3
+ "version": "0.2.3",
4
4
  "type": "module",
5
5
  "packageManager": "pnpm@10.31.0",
6
6
  "description": "一个基于 tmux 的终端会话跨端查看与控制原型。",