@codexhost/cli-darwin-x64 0.12.0 → 0.12.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.
@@ -41,12 +41,13 @@
41
41
  }
42
42
  return payload;
43
43
  }
44
- async function consolePost(path, body = {}) {
44
+ async function consolePost(path, body = {}, signal) {
45
45
  const response = await fetch(path, {
46
46
  method: "POST",
47
47
  credentials: "same-origin",
48
48
  headers: { "content-type": "application/json", [CONSOLE_REQUEST_HEADER]: "1" },
49
- body: JSON.stringify(body)
49
+ body: JSON.stringify(body),
50
+ ...signal ? { signal } : {}
50
51
  });
51
52
  const payload = await response.json().catch(() => null);
52
53
  if (!response.ok) {
@@ -57,8 +58,9 @@
57
58
  }
58
59
  function hostRequestManager() {
59
60
  return {
60
- async sendRequest(method, params) {
61
- const reply = await consolePost("/api/host/request", { method, params });
61
+ async sendRequest(method, params, options) {
62
+ const signal = options instanceof AbortSignal ? options : void 0;
63
+ const reply = await consolePost("/api/host/request", { method, params }, signal);
62
64
  if (reply.error) {
63
65
  throw Object.assign(new Error(reply.error.message), { code: reply.error.code });
64
66
  }
@@ -14661,6 +14663,20 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
14661
14663
  initializeOnly: external_exports.boolean().optional()
14662
14664
  });
14663
14665
 
14666
+ // ../shared-contracts/dist/ids.js
14667
+ var opaqueIdSchema = external_exports.string().refine((value) => value.trim().length > 0, {
14668
+ message: "Identifier must not be empty or whitespace"
14669
+ });
14670
+ var harnessIdSchema = opaqueIdSchema.brand();
14671
+ var hostThreadIdSchema = opaqueIdSchema.brand();
14672
+ var hostTurnIdSchema = opaqueIdSchema.brand();
14673
+ var hostItemIdSchema = opaqueIdSchema.brand();
14674
+ var hostInteractionIdSchema = opaqueIdSchema.brand();
14675
+
14676
+ // ../shared-contracts/dist/thread-prewarm.js
14677
+ var threadPrewarmDiscardParamsSchema = external_exports.object({ threadId: hostThreadIdSchema });
14678
+ var threadPrewarmDiscardResultSchema = external_exports.object({ discarded: external_exports.boolean() });
14679
+
14664
14680
  // ../shared-contracts/dist/console.js
14665
14681
  var consoleAnnouncementSchema = external_exports.strictObject({
14666
14682
  title: external_exports.string().trim().min(1).max(200),
@@ -14674,6 +14690,9 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
14674
14690
  url: external_exports.string().max(2048).regex(/^http:\/\/(?:127\.0\.0\.1|localhost):\d{1,5}\/(?:\?.*)?$/u)
14675
14691
  });
14676
14692
  var CONSOLE_HOST_METHODS = Object.freeze([
14693
+ "codexhost/console/remote-connections",
14694
+ "codexhost/runtime/status",
14695
+ "codexhost/remote/ssh-setup",
14677
14696
  "codexhost/harness/plugins/list",
14678
14697
  "codexhost/harness/display-settings/get",
14679
14698
  "codexhost/harness/display-settings/set",
@@ -14742,16 +14761,6 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
14742
14761
  inactiveMs: external_exports.number().nonnegative()
14743
14762
  }));
14744
14763
 
14745
- // ../shared-contracts/dist/ids.js
14746
- var opaqueIdSchema = external_exports.string().refine((value) => value.trim().length > 0, {
14747
- message: "Identifier must not be empty or whitespace"
14748
- });
14749
- var harnessIdSchema = opaqueIdSchema.brand();
14750
- var hostThreadIdSchema = opaqueIdSchema.brand();
14751
- var hostTurnIdSchema = opaqueIdSchema.brand();
14752
- var hostItemIdSchema = opaqueIdSchema.brand();
14753
- var hostInteractionIdSchema = opaqueIdSchema.brand();
14754
-
14755
14764
  // ../shared-contracts/dist/manual-compaction.js
14756
14765
  var threadManualCompactionStartedSchema = external_exports.strictObject({
14757
14766
  threadId: hostThreadIdSchema,
@@ -15670,11 +15679,54 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
15670
15679
  hostname: external_exports.string().min(1).max(1024).refine((value) => !value.startsWith("-") && !/\s/u.test(value)),
15671
15680
  port: external_exports.number().int().min(1).max(65535).nullable(),
15672
15681
  identity: external_exports.string().max(4096).nullable(),
15673
- action: external_exports.enum(["inspect", "install", "update", "repair"]),
15682
+ action: external_exports.enum(["inspect", "install", "update", "repair", "uninstall"]),
15683
+ uninstallPackage: external_exports.boolean().optional(),
15674
15684
  version: external_exports.string().regex(/^\d+\.\d+\.\d+$/u).nullable()
15675
15685
  }).strict();
15676
15686
  var remoteSshSetupResultSchema = external_exports.object({ state: external_exports.enum(["installed", "not-installed"]) }).strict();
15677
15687
 
15688
+ // ../shared-contracts/dist/remote-connections.js
15689
+ var CONSOLE_REMOTE_CONNECTIONS_METHOD = "codexhost/console/remote-connections";
15690
+ var hostId = external_exports.string().min(1).max(1024);
15691
+ var codexSshConnectionSchema = external_exports.object({
15692
+ hostId,
15693
+ displayName: external_exports.string().min(1).max(1024),
15694
+ source: external_exports.enum(["codex-managed", "discovered"]),
15695
+ sshAlias: external_exports.string().max(1024).nullable(),
15696
+ sshHost: external_exports.string().min(1).max(1024),
15697
+ sshPort: external_exports.number().int().min(1).max(65535).nullable(),
15698
+ identity: external_exports.string().max(4096).nullable(),
15699
+ autoConnect: external_exports.boolean(),
15700
+ connectionAnalyticsId: external_exports.string().max(1024).optional()
15701
+ });
15702
+ var codexSshDraftSchema = external_exports.strictObject({
15703
+ displayName: external_exports.string().min(1).max(1024),
15704
+ hostname: external_exports.string().min(1).max(1024),
15705
+ sshPort: external_exports.number().int().min(1).max(65535).nullable(),
15706
+ identity: external_exports.string().max(4096).nullable()
15707
+ });
15708
+ var remoteConnectionsRequestSchema = external_exports.discriminatedUnion("action", [
15709
+ external_exports.strictObject({ action: external_exports.literal("list") }),
15710
+ external_exports.strictObject({
15711
+ action: external_exports.literal("save"),
15712
+ draft: codexSshDraftSchema,
15713
+ previous: codexSshConnectionSchema.nullable()
15714
+ }),
15715
+ external_exports.strictObject({ action: external_exports.literal("remove"), previous: codexSshConnectionSchema }),
15716
+ external_exports.strictObject({ action: external_exports.literal("connect"), hostId, enabled: external_exports.boolean() }),
15717
+ external_exports.strictObject({ action: external_exports.literal("state"), hostId }),
15718
+ external_exports.strictObject({ action: external_exports.literal("runtime"), hostId }),
15719
+ external_exports.strictObject({
15720
+ action: external_exports.literal("update"),
15721
+ hostId: hostId.refine((id) => id !== "local"),
15722
+ version: remoteUpdateParamsSchema.shape.version
15723
+ })
15724
+ ]);
15725
+ var remoteConnectionsReplySchema = external_exports.union([
15726
+ external_exports.strictObject({ result: jsonValueSchema }),
15727
+ external_exports.strictObject({ error: external_exports.strictObject({ code: external_exports.number().int(), message: external_exports.string() }) })
15728
+ ]);
15729
+
15678
15730
  // ../shared-contracts/dist/index.js
15679
15731
  var workspaceContractVersionSchema = external_exports.literal(WORKSPACE_CONTRACT_VERSION);
15680
15732
 
@@ -16585,8 +16637,8 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
16585
16637
  const installation = client.installation?.bind(client);
16586
16638
  return {
16587
16639
  ...installation ? {
16588
- installation: async (hostId, agent, action) => {
16589
- if (hostId !== "local") {
16640
+ installation: async (hostId2, agent, action) => {
16641
+ if (hostId2 !== "local") {
16590
16642
  throw new Error("Web console installation only supports the local Host");
16591
16643
  }
16592
16644
  return installation({ harnessId: harnessIdSchema.parse(agent), action });
@@ -17392,6 +17444,60 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
17392
17444
  }
17393
17445
  };
17394
17446
 
17447
+ // src/console/remote-connections.ts
17448
+ function createConsoleRemoteConnections(manager) {
17449
+ const request = (input, signal) => manager.sendRequest(
17450
+ CONSOLE_REMOTE_CONNECTIONS_METHOD,
17451
+ remoteConnectionsRequestSchema.parse(input),
17452
+ signal
17453
+ );
17454
+ return {
17455
+ ssh: {
17456
+ async list(signal) {
17457
+ return codexSshConnectionSchema.array().parse(await request({ action: "list" }, signal));
17458
+ },
17459
+ async save(draft, previous, signal) {
17460
+ await request({ action: "save", draft, previous }, signal);
17461
+ },
17462
+ async remove(previous, signal) {
17463
+ await request({ action: "remove", previous }, signal);
17464
+ },
17465
+ async connect(hostId2, enabled, signal) {
17466
+ await request({ action: "connect", hostId: hostId2, enabled }, signal);
17467
+ },
17468
+ async state(hostId2, signal) {
17469
+ const result = await request({ action: "state", hostId: hostId2 }, signal);
17470
+ if (!result || typeof result !== "object" || !("state" in result) || typeof result.state !== "string")
17471
+ throw new Error("Invalid Codex connection state");
17472
+ return {
17473
+ state: result.state,
17474
+ error: "error" in result && typeof result.error === "string" ? result.error : null
17475
+ };
17476
+ }
17477
+ },
17478
+ async setup(connection, action, version2, uninstallPackage) {
17479
+ return remoteSshSetupResultSchema.parse(
17480
+ await manager.sendRequest(REMOTE_SSH_SETUP_METHOD, {
17481
+ hostname: connection.sshAlias ?? connection.sshHost,
17482
+ port: connection.sshPort,
17483
+ identity: connection.identity,
17484
+ action,
17485
+ version: version2 ?? null,
17486
+ ...action === "uninstall" ? { uninstallPackage: uninstallPackage ?? false } : {}
17487
+ })
17488
+ );
17489
+ },
17490
+ async runtime(hostId2) {
17491
+ return runtimeStatusSchema.parse(
17492
+ await (hostId2 === "local" ? manager.sendRequest(RUNTIME_STATUS_METHOD, {}) : request({ action: "runtime", hostId: hostId2 }))
17493
+ );
17494
+ },
17495
+ async update(hostId2, version2) {
17496
+ return runtimeStatusSchema.parse(await request({ action: "update", hostId: hostId2, version: version2 }));
17497
+ }
17498
+ };
17499
+ }
17500
+
17395
17501
  // src/renderer-request-sender.ts
17396
17502
  var RendererMethodUnavailableError = class extends Error {
17397
17503
  constructor(method, cause) {
@@ -19273,6 +19379,9 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
19273
19379
 
19274
19380
  // src/settings/remote-failure-messages.ts
19275
19381
  var REMOTE_FAILURE_CHINESE = Object.freeze({
19382
+ "Remote connection management is unavailable. Restart Codex through codexhost": "\u8FDC\u7A0B\u8FDE\u63A5\u7BA1\u7406\u6682\u4E0D\u53EF\u7528\uFF0C\u8BF7\u901A\u8FC7 codexhost \u91CD\u65B0\u542F\u52A8 Codex",
19383
+ "Remote connection request timed out. Refresh before retrying": "\u8FDC\u7A0B\u8FDE\u63A5\u8BF7\u6C42\u8D85\u65F6\uFF0C\u8BF7\u5237\u65B0\u540E\u518D\u8BD5",
19384
+ "Invalid remote connection request": "\u8FDC\u7A0B\u8FDE\u63A5\u8BF7\u6C42\u65E0\u6548",
19276
19385
  // SSH helper: installing, updating and repairing over SSH.
19277
19386
  "Invalid SSH address or port": "SSH \u5730\u5740\u6216\u7AEF\u53E3\u65E0\u6548",
19278
19387
  "Install requires a published stable version": "\u53EA\u80FD\u5B89\u88C5\u5DF2\u53D1\u5E03\u7684\u6B63\u5F0F\u7248\u672C",
@@ -19282,7 +19391,13 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
19282
19391
  "This release is not published on npm, or the remote computer cannot reach the registry": "\u8BE5\u7248\u672C\u5C1A\u672A\u53D1\u5E03\u5230 npm\uFF0C\u6216\u8FDC\u7A0B\u7535\u8111\u65E0\u6CD5\u8BBF\u95EE npm \u4ED3\u5E93",
19283
19392
  "codexhost was installed but is not on the remote PATH. Update this remote manually": "codexhost \u5DF2\u5B89\u88C5\uFF0C\u4F46\u4E0D\u5728\u8FDC\u7A0B\u7535\u8111\u7684 PATH \u4E2D\uFF0C\u8BF7\u5728\u8FDC\u7A0B\u7535\u8111\u4E0A\u624B\u52A8\u66F4\u65B0",
19284
19393
  "Only Mac and Linux remote computers are supported": "\u53EA\u652F\u6301 Mac \u548C Linux \u8FDC\u7A0B\u7535\u8111",
19285
- "Node.js, npm or Codex CLI was not found over SSH. Install them on the remote computer and make sure non-interactive SSH sessions have them on PATH": "\u901A\u8FC7 SSH \u627E\u4E0D\u5230 Node.js\u3001npm \u6216 Codex CLI\u3002\u8BF7\u5728\u8FDC\u7A0B\u7535\u8111\u4E0A\u5B89\u88C5\u5B83\u4EEC\uFF0C\u5E76\u786E\u4FDD\u975E\u4EA4\u4E92\u5F0F SSH \u4F1A\u8BDD\u7684 PATH \u4E2D\u5305\u542B\u5B83\u4EEC",
19394
+ "Node.js was not detected over SSH. Install it on the remote computer or add it to the login shell PATH, then retry": "\u901A\u8FC7 SSH \u672A\u68C0\u6D4B\u5230 Node.js\u3002\u8BF7\u5728\u8FDC\u7A0B\u7535\u8111\u4E0A\u5B89\u88C5\uFF0C\u6216\u5C06\u5DF2\u5B89\u88C5\u7684 Node.js \u52A0\u5165\u767B\u5F55 shell \u7684 PATH \u540E\u91CD\u8BD5",
19395
+ "npm was not detected over SSH. Install it on the remote computer or add it to the login shell PATH, then retry": "\u901A\u8FC7 SSH \u672A\u68C0\u6D4B\u5230 npm\u3002\u8BF7\u5728\u8FDC\u7A0B\u7535\u8111\u4E0A\u5B89\u88C5\uFF0C\u6216\u5C06\u5DF2\u5B89\u88C5\u7684 npm \u52A0\u5165\u767B\u5F55 shell \u7684 PATH \u540E\u91CD\u8BD5",
19396
+ "Codex CLI was not detected over SSH. Install the command-line tool on the remote computer or add it to the login shell PATH, then retry. Codex Desktop is not required": "\u901A\u8FC7 SSH \u672A\u68C0\u6D4B\u5230 Codex CLI\uFF08\u547D\u4EE4\u884C\u5DE5\u5177\uFF09\u3002\u8BF7\u5728\u8FDC\u7A0B\u7535\u8111\u4E0A\u5B89\u88C5\uFF0C\u6216\u5C06\u5DF2\u5B89\u88C5\u7684 Codex CLI \u52A0\u5165\u767B\u5F55 shell \u7684 PATH \u540E\u91CD\u8BD5\u3002\u65E0\u9700\u5B89\u88C5 Codex \u684C\u9762\u7AEF",
19397
+ "codexhost was not detected over SSH. Install it on the remote computer or add it to the login shell PATH, then retry": "\u901A\u8FC7 SSH \u672A\u68C0\u6D4B\u5230 codexhost\u3002\u8BF7\u5728\u8FDC\u7A0B\u7535\u8111\u4E0A\u5B89\u88C5\uFF0C\u6216\u5C06\u5DF2\u5B89\u88C5\u7684 codexhost \u52A0\u5165\u767B\u5F55 shell \u7684 PATH \u540E\u91CD\u8BD5",
19398
+ "The active codexhost does not match the global npm installation. Uninstall only the remote service, or remove the package manually on the remote computer": "\u5F53\u524D codexhost \u4E0E npm \u5168\u5C40\u5B89\u88C5\u4F4D\u7F6E\u4E0D\u5339\u914D\u3002\u8BF7\u9009\u62E9\u4EC5\u5378\u8F7D\u8FDC\u7A0B\u670D\u52A1\uFF0C\u6216\u5728\u8FDC\u7A0B\u7535\u8111\u4E0A\u624B\u52A8\u5378\u8F7D\u8F6F\u4EF6\u5305",
19399
+ "The remote service was uninstalled, but removing the codexhost package failed. Check npm permissions on the remote computer and retry": "\u8FDC\u7A0B\u670D\u52A1\u5DF2\u5378\u8F7D\uFF0C\u4F46 codexhost \u8F6F\u4EF6\u5305\u5378\u8F7D\u5931\u8D25\u3002\u8BF7\u68C0\u67E5\u8FDC\u7A0B\u7535\u8111\u4E0A\u7684 npm \u6743\u9650\u540E\u91CD\u8BD5",
19400
+ "Remote Node.js is unsupported. Select Node.js 22.19 or later in the 22.x series, or Node.js 24.x": "\u8FDC\u7A0B Node.js \u7248\u672C\u4E0D\u53D7\u652F\u6301\uFF0C\u8BF7\u9009\u62E9 Node.js 22.19 \u53CA\u4EE5\u4E0A\u7684 22.x \u7248\u672C\uFF0C\u6216 Node.js 24.x",
19286
19401
  "npm installation failed. Check network access and global installation permissions": "npm \u5B89\u88C5\u5931\u8D25\uFF0C\u8BF7\u68C0\u67E5\u7F51\u7EDC\u548C\u5168\u5C40\u5B89\u88C5\u6743\u9650",
19287
19402
  "Remote service configuration failed. Check Codex CLI and the remote desktop login": "\u8FDC\u7A0B\u670D\u52A1\u914D\u7F6E\u5931\u8D25\uFF0C\u8BF7\u68C0\u67E5 Codex CLI \u4EE5\u53CA\u8FDC\u7A0B\u7535\u8111\u7684\u684C\u9762\u767B\u5F55\u72B6\u6001",
19288
19403
  "Remote service could not stop. Check the remote service before retrying": "\u8FDC\u7A0B\u670D\u52A1\u65E0\u6CD5\u505C\u6B62\uFF0C\u8BF7\u68C0\u67E5\u8FDC\u7A0B\u670D\u52A1\u540E\u91CD\u8BD5",
@@ -19580,6 +19695,9 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
19580
19695
  }
19581
19696
  const serviceActions = remoteElement(document2, "div", "settings-remote-card__actions");
19582
19697
  if (!row.probing) {
19698
+ if (row.installation === "installed" && !remoteBusy(remote)) {
19699
+ serviceActions.append(command("uninstall", t("\u5378\u8F7D\u8FDC\u7A0B\u670D\u52A1", "Uninstall remote service")));
19700
+ }
19583
19701
  const outdated = !remote && !!row.remoteIssue?.outdated && row.installation !== "not-installed";
19584
19702
  if (outdated) {
19585
19703
  const upgrade = command("upgrade", t("\u66F4\u65B0\u8FDC\u7A0B\u670D\u52A1", "Update remote service"), true);
@@ -19896,6 +20014,61 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
19896
20014
  });
19897
20015
  dialog.show(t("\u79FB\u9664", "Remove"), t("\u79FB\u9664\u4E2D\u2026", "Removing\u2026"), true);
19898
20016
  }
20017
+ function openRemoteServiceUninstall(options) {
20018
+ const { t, connection } = options;
20019
+ const dialog = createRemoteDialog(
20020
+ options,
20021
+ t(
20022
+ `\u5378\u8F7D\u201C${connection.displayName}\u201D\u7684\u8FDC\u7A0B\u670D\u52A1\uFF1F`,
20023
+ `Uninstall remote service on "${connection.displayName}"?`
20024
+ )
20025
+ );
20026
+ if (!dialog) return;
20027
+ const document2 = options.container.ownerDocument;
20028
+ dialog.body.append(
20029
+ remoteElement(
20030
+ document2,
20031
+ "p",
20032
+ "",
20033
+ t(
20034
+ "\u5378\u8F7D\u4F1A\u4E2D\u65AD codexhost \u542F\u52A8\u7684\u4F1A\u8BDD\u3002\u5982\u9700\u5728\u8BE5\u7535\u8111\u7EE7\u7EED\u4F7F\u7528\uFF0C\u8BF7\u624B\u52A8\u901A\u8FC7 codexhost \u91CD\u65B0\u542F\u52A8\u3002",
20035
+ "Uninstalling interrupts sessions started through codexhost. To keep using it on that computer, manually relaunch through codexhost."
20036
+ )
20037
+ )
20038
+ );
20039
+ const label = remoteElement(document2, "label", "settings-remote-dialog__package-option");
20040
+ const removePackage = remoteElement(document2, "input");
20041
+ removePackage.type = "checkbox";
20042
+ label.append(
20043
+ removePackage,
20044
+ t("\u540C\u65F6\u5378\u8F7D codexhost \u8F6F\u4EF6\u5305", "Also uninstall the codexhost package")
20045
+ );
20046
+ dialog.body.append(
20047
+ label,
20048
+ remoteElement(
20049
+ document2,
20050
+ "p",
20051
+ "",
20052
+ t(
20053
+ "\u52FE\u9009\u540E\uFF0C\u518D\u6B21\u4F7F\u7528\u524D\u9700\u91CD\u65B0\u5B89\u88C5 codexhost\u3002",
20054
+ "If selected, reinstall codexhost before using it again."
20055
+ )
20056
+ )
20057
+ );
20058
+ dialog.form.addEventListener("submit", (event) => {
20059
+ event.preventDefault();
20060
+ const selected = removePackage.checked;
20061
+ dialog.submit(async () => {
20062
+ removePackage.disabled = true;
20063
+ try {
20064
+ await options.uninstall(selected);
20065
+ } finally {
20066
+ removePackage.disabled = false;
20067
+ }
20068
+ });
20069
+ });
20070
+ dialog.show(t("\u5378\u8F7D", "Uninstall"), t("\u5378\u8F7D\u4E2D\u2026", "Uninstalling\u2026"), true);
20071
+ }
19899
20072
 
19900
20073
  // src/settings/remote-connections-page.ts
19901
20074
  var POLL_INTERVAL_MS = 5e3;
@@ -20024,17 +20197,17 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
20024
20197
  banner.hidden = !loadError;
20025
20198
  bannerText.textContent = loadError ? `${t("\u8BFB\u53D6\u8FDE\u63A5\u5931\u8D25", "Could not load connections")}: ${localizeRemoteFailure(loadError, t)}` : "";
20026
20199
  renderPlaceholder();
20027
- for (const [hostId, card] of cards) {
20028
- if (rows.has(hostId)) continue;
20200
+ for (const [hostId2, card] of cards) {
20201
+ if (rows.has(hostId2)) continue;
20029
20202
  card.element.remove();
20030
- cards.delete(hostId);
20203
+ cards.delete(hostId2);
20031
20204
  }
20032
20205
  const active = focusedElement();
20033
- order.forEach((hostId, index) => {
20034
- const row = rows.get(hostId);
20206
+ order.forEach((hostId2, index) => {
20207
+ const row = rows.get(hostId2);
20035
20208
  if (!row) return;
20036
20209
  const signature = JSON.stringify([row, local]);
20037
- let card = cards.get(hostId);
20210
+ let card = cards.get(hostId2);
20038
20211
  if (card?.signature !== signature) {
20039
20212
  const element = renderRemoteCard(
20040
20213
  document2,
@@ -20046,7 +20219,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
20046
20219
  const focusedAction = active && card?.element.contains(active) ? active.dataset.action : void 0;
20047
20220
  if (card) card.element.replaceWith(element);
20048
20221
  card = { element, signature };
20049
- cards.set(hostId, card);
20222
+ cards.set(hostId2, card);
20050
20223
  if (focusedAction) focusAction(element, focusedAction);
20051
20224
  }
20052
20225
  if (list.children[index] !== card.element)
@@ -20058,38 +20231,41 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
20058
20231
  target?.focus();
20059
20232
  }
20060
20233
  async function probe(row) {
20061
- const { hostId } = row.connection;
20062
- const token = (probeTokens.get(hostId) ?? 0) + 1;
20063
- probeTokens.set(hostId, token);
20064
- const state = await control.ssh.state(hostId, signal).catch((error51) => ({ state: "unknown", error: remoteErrorMessage(error51) }));
20234
+ const { hostId: hostId2 } = row.connection;
20235
+ const token = (probeTokens.get(hostId2) ?? 0) + 1;
20236
+ probeTokens.set(hostId2, token);
20237
+ const state = await control.ssh.state(hostId2, signal).catch((error51) => ({ state: "unknown", error: remoteErrorMessage(error51) }));
20065
20238
  let remote = null;
20066
20239
  let remoteIssue = null;
20067
20240
  if (state.state === "connected")
20068
- remote = await control.runtime(hostId).catch((error51) => {
20241
+ remote = await control.runtime(hostId2).catch((error51) => {
20069
20242
  remoteIssue = remoteVersionIssue(error51);
20070
20243
  return null;
20071
20244
  });
20245
+ if (signal.aborted || rows.get(hostId2) !== row || probeTokens.get(hostId2) !== token) return;
20072
20246
  let expectedGap = false;
20073
- if (remote && remoteBusy(remote)) restarting.set(hostId, Date.now() + RESTART_GRACE_MS);
20074
- else if (remote || (restarting.get(hostId) ?? 0) <= Date.now()) restarting.delete(hostId);
20247
+ if (remote && remoteBusy(remote)) restarting.set(hostId2, Date.now() + RESTART_GRACE_MS);
20248
+ else if (remote || (restarting.get(hostId2) ?? 0) <= Date.now()) restarting.delete(hostId2);
20075
20249
  else if (row.remote) {
20076
20250
  expectedGap = true;
20077
20251
  remote = { ...row.remote, update: { ...row.remote.update, phase: "restarting" } };
20078
20252
  remoteIssue = null;
20079
20253
  }
20080
- if (remote) installations.set(hostId, "installed");
20081
- else if (!installations.has(hostId) && Date.now() - (inspectFailures.get(hostId) ?? -INSPECT_RETRY_MS) >= INSPECT_RETRY_MS) {
20254
+ if (remote) installations.set(hostId2, "installed");
20255
+ else if (!installations.has(hostId2) && Date.now() - (inspectFailures.get(hostId2) ?? -INSPECT_RETRY_MS) >= INSPECT_RETRY_MS) {
20082
20256
  const inspected = await control.setup(row.connection, "inspect").catch(() => null);
20083
- if (inspected) installations.set(hostId, inspected.state);
20084
- else inspectFailures.set(hostId, Date.now());
20257
+ if (signal.aborted || rows.get(hostId2) !== row || probeTokens.get(hostId2) !== token)
20258
+ return;
20259
+ if (inspected) installations.set(hostId2, inspected.state);
20260
+ else inspectFailures.set(hostId2, Date.now());
20085
20261
  }
20086
- if (signal.aborted || rows.get(hostId) !== row || probeTokens.get(hostId) !== token) return;
20262
+ if (signal.aborted || rows.get(hostId2) !== row || probeTokens.get(hostId2) !== token) return;
20087
20263
  row.probing = false;
20088
20264
  row.state = expectedGap ? "connecting" : state.state;
20089
20265
  row.stateError = expectedGap ? null : state.error;
20090
20266
  row.remote = remote;
20091
20267
  row.remoteIssue = remoteIssue;
20092
- row.installation = installations.get(hostId) ?? "unknown";
20268
+ row.installation = installations.get(hostId2) ?? "unknown";
20093
20269
  render();
20094
20270
  }
20095
20271
  async function refresh(actingHostId, wait = "acting") {
@@ -20129,27 +20305,28 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
20129
20305
  notice: null
20130
20306
  });
20131
20307
  }
20132
- for (const hostId of [...rows.keys()]) {
20133
- if (order.includes(hostId)) continue;
20134
- rows.delete(hostId);
20135
- installations.delete(hostId);
20136
- probeTokens.delete(hostId);
20137
- inspectFailures.delete(hostId);
20138
- restarting.delete(hostId);
20308
+ for (const hostId2 of [...rows.keys()]) {
20309
+ if (order.includes(hostId2)) continue;
20310
+ rows.delete(hostId2);
20311
+ installations.delete(hostId2);
20312
+ probeTokens.delete(hostId2);
20313
+ inspectFailures.delete(hostId2);
20314
+ restarting.delete(hostId2);
20139
20315
  }
20140
20316
  render();
20141
20317
  const probes = [...rows.values()].filter((row) => !row.pending || row.connection.hostId === actingHostId).map((row) => ({ hostId: row.connection.hostId, done: probe(row) }));
20142
20318
  const awaited = wait === "all" ? probes : probes.filter((p) => p.hostId === actingHostId);
20143
20319
  await Promise.all([localTask, ...awaited.map((p) => p.done)]);
20144
20320
  }
20145
- async function act(row, action, label, operation) {
20146
- const { hostId } = row.connection;
20321
+ async function act(row, action, label, operation, rethrow = false) {
20322
+ const { hostId: hostId2 } = row.connection;
20323
+ probeTokens.set(hostId2, (probeTokens.get(hostId2) ?? 0) + 1);
20147
20324
  row.pending = label;
20148
20325
  row.notice = null;
20149
20326
  render();
20150
20327
  try {
20151
20328
  const done = await operation();
20152
- await refresh(hostId);
20329
+ await refresh(hostId2);
20153
20330
  if (typeof done === "string") {
20154
20331
  const notice = { tone: "success", text: done };
20155
20332
  row.notice = notice;
@@ -20161,14 +20338,15 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
20161
20338
  }
20162
20339
  } catch (error51) {
20163
20340
  row.notice = { tone: "danger", text: remoteErrorMessage(error51) };
20164
- installations.delete(hostId);
20165
- inspectFailures.delete(hostId);
20166
- void refresh(hostId);
20341
+ installations.delete(hostId2);
20342
+ inspectFailures.delete(hostId2);
20343
+ void refresh(hostId2);
20344
+ if (rethrow) throw error51;
20167
20345
  } finally {
20168
20346
  row.pending = null;
20169
20347
  if (!signal.aborted) {
20170
20348
  render();
20171
- const card = cards.get(hostId)?.element;
20349
+ const card = cards.get(hostId2)?.element;
20172
20350
  if (card && !focusedElement()) focusAction(card, action);
20173
20351
  }
20174
20352
  }
@@ -20193,9 +20371,9 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
20193
20371
  function handle(row, action) {
20194
20372
  if (row.pending) return;
20195
20373
  const { connection } = row;
20196
- const { hostId } = connection;
20374
+ const { hostId: hostId2 } = connection;
20197
20375
  const setConnected = async (enabled) => {
20198
- const request = control.ssh.connect(hostId, enabled, signal);
20376
+ const request = control.ssh.connect(hostId2, enabled, signal);
20199
20377
  request.catch(() => void 0);
20200
20378
  await Promise.race([
20201
20379
  request,
@@ -20203,8 +20381,8 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
20203
20381
  ]);
20204
20382
  };
20205
20383
  const reconnect = async () => {
20206
- installations.delete(hostId);
20207
- inspectFailures.delete(hostId);
20384
+ installations.delete(hostId2);
20385
+ inspectFailures.delete(hostId2);
20208
20386
  await setConnected(true);
20209
20387
  };
20210
20388
  switch (action) {
@@ -20239,8 +20417,8 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
20239
20417
  break;
20240
20418
  case "recheck":
20241
20419
  void act(row, action, t("\u6B63\u5728\u91CD\u65B0\u68C0\u6D4B\u2026", "Checking again\u2026"), async () => {
20242
- installations.delete(hostId);
20243
- inspectFailures.delete(hostId);
20420
+ installations.delete(hostId2);
20421
+ inspectFailures.delete(hostId2);
20244
20422
  });
20245
20423
  break;
20246
20424
  case "install": {
@@ -20285,6 +20463,47 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
20285
20463
  }
20286
20464
  );
20287
20465
  break;
20466
+ case "uninstall":
20467
+ if (row.installation !== "installed" || remoteBusy(row.remote)) break;
20468
+ openRemoteServiceUninstall({
20469
+ container: root,
20470
+ signal,
20471
+ t,
20472
+ connection,
20473
+ async uninstall(removePackage) {
20474
+ if (row.pending || remoteBusy(row.remote))
20475
+ throw new Error(
20476
+ t(
20477
+ "\u8FDC\u7A0B\u670D\u52A1\u6B63\u5728\u6267\u884C\u5176\u4ED6\u64CD\u4F5C\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5",
20478
+ "Another remote operation is active; retry shortly"
20479
+ )
20480
+ );
20481
+ await act(
20482
+ row,
20483
+ action,
20484
+ t("\u6B63\u5728\u5378\u8F7D\u8FDC\u7A0B\u670D\u52A1\u2026", "Uninstalling remote service\u2026"),
20485
+ async () => {
20486
+ await control.ssh.connect(hostId2, false, signal);
20487
+ await control.setup(connection, "uninstall", void 0, removePackage);
20488
+ installations.set(hostId2, "not-installed");
20489
+ inspectFailures.delete(hostId2);
20490
+ restarting.delete(hostId2);
20491
+ row.remote = null;
20492
+ row.remoteIssue = null;
20493
+ row.stateError = null;
20494
+ return removePackage ? t(
20495
+ "\u8FDC\u7A0B\u670D\u52A1\u548C codexhost \u8F6F\u4EF6\u5305\u5DF2\u5378\u8F7D",
20496
+ "Remote service and codexhost package uninstalled"
20497
+ ) : t(
20498
+ "\u8FDC\u7A0B\u670D\u52A1\u5DF2\u5378\u8F7D\uFF0Ccodexhost \u8F6F\u4EF6\u5305\u5DF2\u4FDD\u7559",
20499
+ "Remote service uninstalled; codexhost package kept"
20500
+ );
20501
+ },
20502
+ true
20503
+ );
20504
+ }
20505
+ });
20506
+ break;
20288
20507
  case "update": {
20289
20508
  const target = row.remote ? remoteMaintenanceTarget(local, row.remote) : null;
20290
20509
  if (!target) break;
@@ -20294,7 +20513,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
20294
20513
  action,
20295
20514
  restart ? t("\u6B63\u5728\u91CD\u542F\u8FDC\u7A0B\u670D\u52A1\u2026", "Restarting remote service\u2026") : t("\u6B63\u5728\u63D0\u4EA4\u66F4\u65B0\u2026", "Starting update\u2026"),
20296
20515
  async () => {
20297
- await control.update(hostId, target);
20516
+ await control.update(hostId2, target);
20298
20517
  await setConnected(true);
20299
20518
  }
20300
20519
  );
@@ -20766,7 +20985,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
20766
20985
  }
20767
20986
 
20768
20987
  // src/settings/harness-installation-panel.ts
20769
- function createHarnessInstallationPanel(document2, agent, hostId, messages, copy, installation) {
20988
+ function createHarnessInstallationPanel(document2, agent, hostId2, messages, copy, installation) {
20770
20989
  const zh = messages.locale === "zh-CN";
20771
20990
  const guide = harnessInstallationGuide(agent, messages.locale);
20772
20991
  const panel = document2.createElement("div");
@@ -20776,7 +20995,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
20776
20995
  p.textContent = text;
20777
20996
  panel.append(p);
20778
20997
  };
20779
- if (hostId !== "local") {
20998
+ if (hostId2 !== "local") {
20780
20999
  paragraph(zh ? "\u8BF7\u5728\u8FDC\u7A0B Host \u4E0A\u5B89\u88C5\u3002" : "Install on the remote Host.");
20781
21000
  }
20782
21001
  if (guide.before) paragraph(guide.before);
@@ -20996,11 +21215,11 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
20996
21215
  if (availability === "notInstalled") return "setup";
20997
21216
  return "failed";
20998
21217
  }
20999
- function diagnosticText(hostId, item) {
21218
+ function diagnosticText(hostId2, item) {
21000
21219
  const error51 = item.error;
21001
21220
  return [
21002
21221
  "codexhost connection diagnostics",
21003
- `host: ${hostId}`,
21222
+ `host: ${hostId2}`,
21004
21223
  `agent: ${item.name}`,
21005
21224
  `status: ${item.availability}`,
21006
21225
  ...error51 ? [
@@ -21035,10 +21254,10 @@ ${error51.stderrTail}`] : []
21035
21254
  () => showCopyButtonFeedback(button2, messages.connectionCopyFailed, restoreLabel)
21036
21255
  );
21037
21256
  }
21038
- function connectionHostName(hostId, messages) {
21039
- if (hostId === "local") return messages.connectionLocalHost;
21040
- const separator = hostId.lastIndexOf(":");
21041
- const encodedName = separator >= 0 ? hostId.slice(separator + 1) : hostId;
21257
+ function connectionHostName(hostId2, messages) {
21258
+ if (hostId2 === "local") return messages.connectionLocalHost;
21259
+ const separator = hostId2.lastIndexOf(":");
21260
+ const encodedName = separator >= 0 ? hostId2.slice(separator + 1) : hostId2;
21042
21261
  try {
21043
21262
  return decodeURIComponent(encodedName);
21044
21263
  } catch {
@@ -21233,7 +21452,7 @@ ${error51.stderrTail}`] : []
21233
21452
  header.append(identity, status);
21234
21453
  return header;
21235
21454
  }
21236
- function renderConnectionInspector(document2, inspector, item, hostId, messages, diagnostics, existingLaunchControls, refresh) {
21455
+ function renderConnectionInspector(document2, inspector, item, hostId2, messages, diagnostics, existingLaunchControls, refresh) {
21237
21456
  inspector.replaceChildren(createInspectorHeader(document2, item, messages));
21238
21457
  const body = document2.createElement("div");
21239
21458
  body.className = "settings-connection-inspector__body";
@@ -21263,7 +21482,7 @@ ${error51.stderrTail}`] : []
21263
21482
  createHarnessInstallationPanel(
21264
21483
  document2,
21265
21484
  item.agentSnapshot.agent,
21266
- hostId,
21485
+ hostId2,
21267
21486
  messages,
21268
21487
  (button2, command, label) => copyDiagnosticsToClipboard(document2, button2, command, messages, label),
21269
21488
  item.install ? {
@@ -21302,7 +21521,7 @@ ${error51.stderrTail}`] : []
21302
21521
  copy.type = "button";
21303
21522
  copy.className = "settings-command-button settings-command-button--secondary";
21304
21523
  setCopyButtonLabel(copy, messages.connectionCopyDetails);
21305
- const report = diagnosticText(hostId, item);
21524
+ const report = diagnosticText(hostId2, item);
21306
21525
  copy.addEventListener("click", () => {
21307
21526
  copyDiagnosticsToClipboard(document2, copy, report, messages, messages.connectionCopyDetails);
21308
21527
  });
@@ -21355,10 +21574,10 @@ ${error51.stderrTail}`] : []
21355
21574
  const agent = item.agentSnapshot?.agent;
21356
21575
  const getLaunchSettings = diagnostics?.getLaunchSettings?.bind(diagnostics);
21357
21576
  const setLaunchSettings = diagnostics?.setLaunchSettings?.bind(diagnostics);
21358
- if (hostId === "local" && (agent === "zcode" || agent === "workbuddy") && getLaunchSettings && setLaunchSettings) {
21577
+ if (hostId2 === "local" && (agent === "zcode" || agent === "workbuddy") && getLaunchSettings && setLaunchSettings) {
21359
21578
  launchControls = existingLaunchControls ?? createHarnessLaunchControls(document2, messages, agent, {
21360
- get: () => getLaunchSettings(hostId, agent),
21361
- set: (path) => setLaunchSettings(hostId, agent, path)
21579
+ get: () => getLaunchSettings(hostId2, agent),
21580
+ set: (path) => setLaunchSettings(hostId2, agent, path)
21362
21581
  });
21363
21582
  body.append(launchControls);
21364
21583
  }
@@ -21412,7 +21631,7 @@ ${error51.stderrTail}`] : []
21412
21631
  button2.addEventListener("click", onReset);
21413
21632
  return button2;
21414
21633
  }
21415
- function createConnectionsSettingsPage(messages, getDiagnostics, groupPreference = getSharedAgentGroupPreferenceStore()) {
21634
+ function createConnectionsSettingsPage(messages, getDiagnostics, groupPreference = getSharedAgentGroupPreferenceStore(), getRemoteConnections = () => null) {
21416
21635
  return Object.freeze({
21417
21636
  id: "connections",
21418
21637
  label: messages.pageLabels.connections,
@@ -21447,6 +21666,7 @@ ${error51.stderrTail}`] : []
21447
21666
  let launchControls = null;
21448
21667
  const versionPanels = /* @__PURE__ */ new Map();
21449
21668
  const updatingVersions = /* @__PURE__ */ new Set();
21669
+ const hostNames = /* @__PURE__ */ new Map();
21450
21670
  let latestSnapshot = null;
21451
21671
  let disposeHostScroller = () => void 0;
21452
21672
  const diagnostics = getDiagnostics();
@@ -21538,7 +21758,7 @@ ${error51.stderrTail}`] : []
21538
21758
  tab.setAttribute("aria-controls", panelId);
21539
21759
  tab.setAttribute("aria-selected", String(host.hostId === selectedHost.hostId));
21540
21760
  tab.tabIndex = host.hostId === selectedHost.hostId ? 0 : -1;
21541
- const hostName = connectionHostName(host.hostId, messages);
21761
+ const hostName = hostNames.get(host.hostId) || connectionHostName(host.hostId, messages);
21542
21762
  tab.textContent = hostName;
21543
21763
  tab.title = host.active ? `${hostName} \xB7 ${messages.connectionActiveHost}` : hostName;
21544
21764
  tab.addEventListener("click", () => {
@@ -21632,14 +21852,14 @@ ${error51.stderrTail}`] : []
21632
21852
  const key = JSON.stringify([selectedHost.hostId, agent]);
21633
21853
  let panel = versionPanels.get(key);
21634
21854
  if (!panel) {
21635
- const hostId = selectedHost.hostId;
21855
+ const hostId2 = selectedHost.hostId;
21636
21856
  panel = createHarnessVersionPanel(document2, messages, context.signal, agent, {
21637
21857
  async run(action) {
21638
- if (action !== "update") return installation(hostId, agent, action);
21858
+ if (action !== "update") return installation(hostId2, agent, action);
21639
21859
  updatingVersions.add(key);
21640
21860
  if (diagnostics) render(diagnostics.snapshot());
21641
21861
  try {
21642
- return await installation(hostId, agent, action);
21862
+ return await installation(hostId2, agent, action);
21643
21863
  } finally {
21644
21864
  updatingVersions.delete(key);
21645
21865
  if (!context.signal.aborted && diagnostics) render(diagnostics.snapshot());
@@ -21831,6 +22051,17 @@ ${error51.stderrTail}`] : []
21831
22051
  }
21832
22052
  };
21833
22053
  render(diagnostics?.snapshot() ?? null);
22054
+ void getRemoteConnections()?.ssh.list(context.signal).then(
22055
+ (connections) => {
22056
+ if (context.signal.aborted) return;
22057
+ for (const connection of connections) {
22058
+ hostNames.set(connection.hostId, connection.displayName.trim());
22059
+ }
22060
+ render(diagnostics?.snapshot() ?? null);
22061
+ },
22062
+ () => {
22063
+ }
22064
+ );
21834
22065
  const unsubscribeGroup = groupPreference.subscribe(
21835
22066
  () => render(diagnostics?.snapshot() ?? latestSnapshot)
21836
22067
  );
@@ -22415,7 +22646,7 @@ ${error51.stderrTail}`] : []
22415
22646
  void context.runLatest(
22416
22647
  async (signal) => {
22417
22648
  const missing = new Set(
22418
- getDiagnostics()?.snapshot().hosts.find(({ hostId }) => hostId === "local")?.agents.filter(({ availability }) => availability === "notInstalled").map(({ agent }) => agent)
22649
+ getDiagnostics()?.snapshot().hosts.find(({ hostId: hostId2 }) => hostId2 === "local")?.agents.filter(({ availability }) => availability === "notInstalled").map(({ agent }) => agent)
22419
22650
  );
22420
22651
  const harnesses = (await client.listSessionImportSources()).harnesses.filter(
22421
22652
  ({ harnessId }) => !missing.has(harnessId)
@@ -24834,7 +25065,7 @@ ${error51.stderrTail}`] : []
24834
25065
  }
24835
25066
  function createDefaultRendererSettingsPages(messages = DEFAULT_RENDERER_SETTINGS_MESSAGES, getUpdateClient = () => null, getDiagnostics = () => null, getAccountClient = () => null, getSessionImportClient = () => null, openImportedThread = () => Promise.reject(new Error("Imported Thread navigation is unavailable")), getLoadedSessionsClient = () => null, getRemoteConnections = () => null) {
24836
25067
  return Object.freeze([
24837
- createConnectionsSettingsPage(messages, getDiagnostics),
25068
+ createConnectionsSettingsPage(messages, getDiagnostics, void 0, getRemoteConnections),
24838
25069
  createRemoteConnectionsPage(messages, getRemoteConnections),
24839
25070
  createAccountsSettingsPage(messages, getAccountClient),
24840
25071
  createSessionImportSettingsPage(
@@ -27338,6 +27569,23 @@ ${error51.stderrTail}`] : []
27338
27569
  outline-offset: -1px;
27339
27570
  }
27340
27571
 
27572
+ .settings-remote-dialog__package-option {
27573
+ display: flex;
27574
+ align-items: center;
27575
+ gap: 8px;
27576
+ cursor: pointer;
27577
+ }
27578
+
27579
+ .settings-remote-dialog .settings-remote-dialog__package-option input {
27580
+ flex: none;
27581
+ width: 16px;
27582
+ height: 16px;
27583
+ min-height: 16px;
27584
+ margin: 0;
27585
+ padding: 0;
27586
+ accent-color: var(--settings-focus);
27587
+ }
27588
+
27341
27589
  @keyframes settings-remote-spin {
27342
27590
  to {
27343
27591
  transform: rotate(360deg);
@@ -27441,13 +27689,16 @@ ${error51.stderrTail}`] : []
27441
27689
  (method, params) => manager.sendRequest(method, params)
27442
27690
  );
27443
27691
  const updateClient = consoleUpdateClient();
27692
+ const remoteConnections = createConsoleRemoteConnections(manager);
27444
27693
  const settingsPages = createDefaultRendererSettingsPages(
27445
27694
  settingsMessages,
27446
27695
  () => updateClient,
27447
27696
  () => diagnostics,
27448
27697
  () => modelClient,
27449
27698
  () => sessionImportClient,
27450
- null
27699
+ null,
27700
+ () => null,
27701
+ () => remoteConnections
27451
27702
  );
27452
27703
  const navigate = (pageId) => {
27453
27704
  window.location.hash = pageId;
@@ -27470,6 +27721,7 @@ ${error51.stderrTail}`] : []
27470
27721
  () => state.overview?.inspect?.runtime.running ?? false
27471
27722
  )
27472
27723
  ),
27724
+ hostPage(required2(settingsPages, "remote-connections"), messages, state),
27473
27725
  hostPage(required2(settingsPages, "accounts"), messages, state),
27474
27726
  hostPage(required2(settingsPages, "session-import"), messages, state),
27475
27727
  required2(settingsPages, "updates")