@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.
@@ -581,11 +581,11 @@
581
581
  list,
582
582
  save: (draft, previous, signal) => mutate(previous, draft, signal),
583
583
  remove: (previous, signal) => mutate(previous, null, signal),
584
- async connect(hostId, enabled, signal) {
585
- await request("set-remote-connection-auto-connect", { hostId, autoConnect: enabled }, signal);
584
+ async connect(hostId2, enabled, signal) {
585
+ await request("set-remote-connection-auto-connect", { hostId: hostId2, autoConnect: enabled }, signal);
586
586
  },
587
- async state(hostId, signal) {
588
- const result = await request("app-server-connection-state", { hostId }, signal);
587
+ async state(hostId2, signal) {
588
+ const result = await request("app-server-connection-state", { hostId: hostId2 }, signal);
589
589
  if (!record(result) || typeof result.state !== "string")
590
590
  throw new Error("Invalid Codex connection state");
591
591
  return {
@@ -629,7 +629,7 @@
629
629
  }
630
630
  const control = {
631
631
  ssh: createCodexSshClient(ownerWindow),
632
- async setup(connection, action, version2) {
632
+ async setup(connection, action, version2, uninstallPackage) {
633
633
  const client = getClient("local");
634
634
  if (!client?.setupSsh)
635
635
  throw new Error("SSH installation is unavailable; update local codexhost and restart");
@@ -638,20 +638,21 @@
638
638
  port: connection.sshPort,
639
639
  identity: connection.identity,
640
640
  action,
641
- version: version2 ?? null
641
+ version: version2 ?? null,
642
+ ...action === "uninstall" ? { uninstallPackage: uninstallPackage ?? false } : {}
642
643
  });
643
644
  },
644
- async runtime(hostId) {
645
- const client = getClient(hostId);
645
+ async runtime(hostId2) {
646
+ const client = getClient(hostId2);
646
647
  if (!client?.runtimeStatus)
647
648
  throw new Error(
648
649
  "Version management is unavailable; update codexhost on this host and reconnect"
649
650
  );
650
651
  return bounded(client.runtimeStatus());
651
652
  },
652
- async update(hostId, version2) {
653
- if (hostId === "local") throw new Error("Choose a remote SSH connection");
654
- const client = getClient(hostId);
653
+ async update(hostId2, version2) {
654
+ if (hostId2 === "local") throw new Error("Choose a remote SSH connection");
655
+ const client = getClient(hostId2);
655
656
  if (!client?.updateRemote)
656
657
  throw new Error("Remote update is unavailable; update this remote once and reconnect");
657
658
  return bounded(client.updateRemote(version2));
@@ -15247,6 +15248,20 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
15247
15248
  initializeOnly: external_exports.boolean().optional()
15248
15249
  });
15249
15250
 
15251
+ // ../shared-contracts/dist/ids.js
15252
+ var opaqueIdSchema = external_exports.string().refine((value) => value.trim().length > 0, {
15253
+ message: "Identifier must not be empty or whitespace"
15254
+ });
15255
+ var harnessIdSchema = opaqueIdSchema.brand();
15256
+ var hostThreadIdSchema = opaqueIdSchema.brand();
15257
+ var hostTurnIdSchema = opaqueIdSchema.brand();
15258
+ var hostItemIdSchema = opaqueIdSchema.brand();
15259
+ var hostInteractionIdSchema = opaqueIdSchema.brand();
15260
+
15261
+ // ../shared-contracts/dist/thread-prewarm.js
15262
+ var threadPrewarmDiscardParamsSchema = external_exports.object({ threadId: hostThreadIdSchema });
15263
+ var threadPrewarmDiscardResultSchema = external_exports.object({ discarded: external_exports.boolean() });
15264
+
15250
15265
  // ../shared-contracts/dist/console.js
15251
15266
  var consoleAnnouncementSchema = external_exports.strictObject({
15252
15267
  title: external_exports.string().trim().min(1).max(200),
@@ -15260,6 +15275,9 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
15260
15275
  url: external_exports.string().max(2048).regex(/^http:\/\/(?:127\.0\.0\.1|localhost):\d{1,5}\/(?:\?.*)?$/u)
15261
15276
  });
15262
15277
  var CONSOLE_HOST_METHODS = Object.freeze([
15278
+ "codexhost/console/remote-connections",
15279
+ "codexhost/runtime/status",
15280
+ "codexhost/remote/ssh-setup",
15263
15281
  "codexhost/harness/plugins/list",
15264
15282
  "codexhost/harness/display-settings/get",
15265
15283
  "codexhost/harness/display-settings/set",
@@ -15328,16 +15346,6 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
15328
15346
  inactiveMs: external_exports.number().nonnegative()
15329
15347
  }));
15330
15348
 
15331
- // ../shared-contracts/dist/ids.js
15332
- var opaqueIdSchema = external_exports.string().refine((value) => value.trim().length > 0, {
15333
- message: "Identifier must not be empty or whitespace"
15334
- });
15335
- var harnessIdSchema = opaqueIdSchema.brand();
15336
- var hostThreadIdSchema = opaqueIdSchema.brand();
15337
- var hostTurnIdSchema = opaqueIdSchema.brand();
15338
- var hostItemIdSchema = opaqueIdSchema.brand();
15339
- var hostInteractionIdSchema = opaqueIdSchema.brand();
15340
-
15341
15349
  // ../shared-contracts/dist/manual-compaction.js
15342
15350
  var THREAD_MANUAL_COMPACTION_STARTED_METHOD = "codexhost/thread/manual-compaction/started";
15343
15351
  var threadManualCompactionStartedSchema = external_exports.strictObject({
@@ -15708,8 +15716,8 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
15708
15716
  message: "Cross-cwd Fork requires exact history Fork support"
15709
15717
  });
15710
15718
  var harnessPermissionModeScopeSchema = external_exports.enum(["live", "atCreate"]);
15711
- function permissionModeFixedAtCreate(configuration2) {
15712
- return configuration2.permissionModeScope === "atCreate";
15719
+ function permissionModeFixedAtCreate(configuration) {
15720
+ return configuration.permissionModeScope === "atCreate";
15713
15721
  }
15714
15722
  var harnessSessionCapabilitiesSchema = external_exports.object({
15715
15723
  configuration: external_exports.object({
@@ -16316,14 +16324,80 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
16316
16324
  hostname: external_exports.string().min(1).max(1024).refine((value) => !value.startsWith("-") && !/\s/u.test(value)),
16317
16325
  port: external_exports.number().int().min(1).max(65535).nullable(),
16318
16326
  identity: external_exports.string().max(4096).nullable(),
16319
- action: external_exports.enum(["inspect", "install", "update", "repair"]),
16327
+ action: external_exports.enum(["inspect", "install", "update", "repair", "uninstall"]),
16328
+ uninstallPackage: external_exports.boolean().optional(),
16320
16329
  version: external_exports.string().regex(/^\d+\.\d+\.\d+$/u).nullable()
16321
16330
  }).strict();
16322
16331
  var remoteSshSetupResultSchema = external_exports.object({ state: external_exports.enum(["installed", "not-installed"]) }).strict();
16323
16332
 
16333
+ // ../shared-contracts/dist/remote-connections.js
16334
+ var hostId = external_exports.string().min(1).max(1024);
16335
+ var codexSshConnectionSchema = external_exports.object({
16336
+ hostId,
16337
+ displayName: external_exports.string().min(1).max(1024),
16338
+ source: external_exports.enum(["codex-managed", "discovered"]),
16339
+ sshAlias: external_exports.string().max(1024).nullable(),
16340
+ sshHost: external_exports.string().min(1).max(1024),
16341
+ sshPort: external_exports.number().int().min(1).max(65535).nullable(),
16342
+ identity: external_exports.string().max(4096).nullable(),
16343
+ autoConnect: external_exports.boolean(),
16344
+ connectionAnalyticsId: external_exports.string().max(1024).optional()
16345
+ });
16346
+ var codexSshDraftSchema = external_exports.strictObject({
16347
+ displayName: external_exports.string().min(1).max(1024),
16348
+ hostname: external_exports.string().min(1).max(1024),
16349
+ sshPort: external_exports.number().int().min(1).max(65535).nullable(),
16350
+ identity: external_exports.string().max(4096).nullable()
16351
+ });
16352
+ var remoteConnectionsRequestSchema = external_exports.discriminatedUnion("action", [
16353
+ external_exports.strictObject({ action: external_exports.literal("list") }),
16354
+ external_exports.strictObject({
16355
+ action: external_exports.literal("save"),
16356
+ draft: codexSshDraftSchema,
16357
+ previous: codexSshConnectionSchema.nullable()
16358
+ }),
16359
+ external_exports.strictObject({ action: external_exports.literal("remove"), previous: codexSshConnectionSchema }),
16360
+ external_exports.strictObject({ action: external_exports.literal("connect"), hostId, enabled: external_exports.boolean() }),
16361
+ external_exports.strictObject({ action: external_exports.literal("state"), hostId }),
16362
+ external_exports.strictObject({ action: external_exports.literal("runtime"), hostId }),
16363
+ external_exports.strictObject({
16364
+ action: external_exports.literal("update"),
16365
+ hostId: hostId.refine((id) => id !== "local"),
16366
+ version: remoteUpdateParamsSchema.shape.version
16367
+ })
16368
+ ]);
16369
+ var remoteConnectionsReplySchema = external_exports.union([
16370
+ external_exports.strictObject({ result: jsonValueSchema }),
16371
+ external_exports.strictObject({ error: external_exports.strictObject({ code: external_exports.number().int(), message: external_exports.string() }) })
16372
+ ]);
16373
+
16324
16374
  // ../shared-contracts/dist/index.js
16325
16375
  var workspaceContractVersionSchema = external_exports.literal(WORKSPACE_CONTRACT_VERSION);
16326
16376
 
16377
+ // src/remote-connections-request.ts
16378
+ async function handleRemoteConnectionsRequest(control, input) {
16379
+ const request = remoteConnectionsRequestSchema.parse(input);
16380
+ switch (request.action) {
16381
+ case "list":
16382
+ return control.ssh.list();
16383
+ case "save":
16384
+ await control.ssh.save(request.draft, request.previous);
16385
+ return null;
16386
+ case "remove":
16387
+ await control.ssh.remove(request.previous);
16388
+ return null;
16389
+ case "connect":
16390
+ await control.ssh.connect(request.hostId, request.enabled);
16391
+ return null;
16392
+ case "state":
16393
+ return control.ssh.state(request.hostId);
16394
+ case "runtime":
16395
+ return control.runtime(request.hostId);
16396
+ case "update":
16397
+ return control.update(request.hostId, request.version);
16398
+ }
16399
+ }
16400
+
16327
16401
  // src/agent-group-preference.ts
16328
16402
  var AGENT_GROUP_PREFERENCE_STORAGE_KEY = "codexhost.agentGroupPreference.v1";
16329
16403
  var EXTERNAL_AGENTS = KNOWN_RENDERER_AGENTS.filter(
@@ -17349,7 +17423,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
17349
17423
  }
17350
17424
 
17351
17425
  // src/settings/harness-installation-panel.ts
17352
- function createHarnessInstallationPanel(document2, agent, hostId, messages, copy, installation) {
17426
+ function createHarnessInstallationPanel(document2, agent, hostId2, messages, copy, installation) {
17353
17427
  const zh = messages.locale === "zh-CN";
17354
17428
  const guide = harnessInstallationGuide(agent, messages.locale);
17355
17429
  const panel = document2.createElement("div");
@@ -17359,7 +17433,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
17359
17433
  p.textContent = text;
17360
17434
  panel.append(p);
17361
17435
  };
17362
- if (hostId !== "local") {
17436
+ if (hostId2 !== "local") {
17363
17437
  paragraph(zh ? "\u8BF7\u5728\u8FDC\u7A0B Host \u4E0A\u5B89\u88C5\u3002" : "Install on the remote Host.");
17364
17438
  }
17365
17439
  if (guide.before) paragraph(guide.before);
@@ -17627,11 +17701,11 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
17627
17701
  if (availability === "notInstalled") return "setup";
17628
17702
  return "failed";
17629
17703
  }
17630
- function diagnosticText(hostId, item) {
17704
+ function diagnosticText(hostId2, item) {
17631
17705
  const error51 = item.error;
17632
17706
  return [
17633
17707
  "codexhost connection diagnostics",
17634
- `host: ${hostId}`,
17708
+ `host: ${hostId2}`,
17635
17709
  `agent: ${item.name}`,
17636
17710
  `status: ${item.availability}`,
17637
17711
  ...error51 ? [
@@ -17666,10 +17740,10 @@ ${error51.stderrTail}`] : []
17666
17740
  () => showCopyButtonFeedback(button, messages.connectionCopyFailed, restoreLabel)
17667
17741
  );
17668
17742
  }
17669
- function connectionHostName(hostId, messages) {
17670
- if (hostId === "local") return messages.connectionLocalHost;
17671
- const separator = hostId.lastIndexOf(":");
17672
- const encodedName = separator >= 0 ? hostId.slice(separator + 1) : hostId;
17743
+ function connectionHostName(hostId2, messages) {
17744
+ if (hostId2 === "local") return messages.connectionLocalHost;
17745
+ const separator = hostId2.lastIndexOf(":");
17746
+ const encodedName = separator >= 0 ? hostId2.slice(separator + 1) : hostId2;
17673
17747
  try {
17674
17748
  return decodeURIComponent(encodedName);
17675
17749
  } catch {
@@ -17864,7 +17938,7 @@ ${error51.stderrTail}`] : []
17864
17938
  header.append(identity, status);
17865
17939
  return header;
17866
17940
  }
17867
- function renderConnectionInspector(document2, inspector, item, hostId, messages, diagnostics, existingLaunchControls, refresh) {
17941
+ function renderConnectionInspector(document2, inspector, item, hostId2, messages, diagnostics, existingLaunchControls, refresh) {
17868
17942
  inspector.replaceChildren(createInspectorHeader(document2, item, messages));
17869
17943
  const body = document2.createElement("div");
17870
17944
  body.className = "settings-connection-inspector__body";
@@ -17894,7 +17968,7 @@ ${error51.stderrTail}`] : []
17894
17968
  createHarnessInstallationPanel(
17895
17969
  document2,
17896
17970
  item.agentSnapshot.agent,
17897
- hostId,
17971
+ hostId2,
17898
17972
  messages,
17899
17973
  (button, command, label) => copyDiagnosticsToClipboard(document2, button, command, messages, label),
17900
17974
  item.install ? {
@@ -17933,7 +18007,7 @@ ${error51.stderrTail}`] : []
17933
18007
  copy.type = "button";
17934
18008
  copy.className = "settings-command-button settings-command-button--secondary";
17935
18009
  setCopyButtonLabel(copy, messages.connectionCopyDetails);
17936
- const report = diagnosticText(hostId, item);
18010
+ const report = diagnosticText(hostId2, item);
17937
18011
  copy.addEventListener("click", () => {
17938
18012
  copyDiagnosticsToClipboard(document2, copy, report, messages, messages.connectionCopyDetails);
17939
18013
  });
@@ -17986,10 +18060,10 @@ ${error51.stderrTail}`] : []
17986
18060
  const agent = item.agentSnapshot?.agent;
17987
18061
  const getLaunchSettings = diagnostics?.getLaunchSettings?.bind(diagnostics);
17988
18062
  const setLaunchSettings = diagnostics?.setLaunchSettings?.bind(diagnostics);
17989
- if (hostId === "local" && (agent === "zcode" || agent === "workbuddy") && getLaunchSettings && setLaunchSettings) {
18063
+ if (hostId2 === "local" && (agent === "zcode" || agent === "workbuddy") && getLaunchSettings && setLaunchSettings) {
17990
18064
  launchControls = existingLaunchControls ?? createHarnessLaunchControls(document2, messages, agent, {
17991
- get: () => getLaunchSettings(hostId, agent),
17992
- set: (path) => setLaunchSettings(hostId, agent, path)
18065
+ get: () => getLaunchSettings(hostId2, agent),
18066
+ set: (path) => setLaunchSettings(hostId2, agent, path)
17993
18067
  });
17994
18068
  body.append(launchControls);
17995
18069
  }
@@ -18046,7 +18120,7 @@ ${error51.stderrTail}`] : []
18046
18120
  button.addEventListener("click", onReset);
18047
18121
  return button;
18048
18122
  }
18049
- function createConnectionsSettingsPage(messages, getDiagnostics, groupPreference = getSharedAgentGroupPreferenceStore()) {
18123
+ function createConnectionsSettingsPage(messages, getDiagnostics, groupPreference = getSharedAgentGroupPreferenceStore(), getRemoteConnections = () => null) {
18050
18124
  return Object.freeze({
18051
18125
  id: "connections",
18052
18126
  label: messages.pageLabels.connections,
@@ -18081,6 +18155,7 @@ ${error51.stderrTail}`] : []
18081
18155
  let launchControls = null;
18082
18156
  const versionPanels = /* @__PURE__ */ new Map();
18083
18157
  const updatingVersions = /* @__PURE__ */ new Set();
18158
+ const hostNames = /* @__PURE__ */ new Map();
18084
18159
  let latestSnapshot = null;
18085
18160
  let disposeHostScroller = () => void 0;
18086
18161
  const diagnostics = getDiagnostics();
@@ -18172,7 +18247,7 @@ ${error51.stderrTail}`] : []
18172
18247
  tab.setAttribute("aria-controls", panelId);
18173
18248
  tab.setAttribute("aria-selected", String(host.hostId === selectedHost.hostId));
18174
18249
  tab.tabIndex = host.hostId === selectedHost.hostId ? 0 : -1;
18175
- const hostName = connectionHostName(host.hostId, messages);
18250
+ const hostName = hostNames.get(host.hostId) || connectionHostName(host.hostId, messages);
18176
18251
  tab.textContent = hostName;
18177
18252
  tab.title = host.active ? `${hostName} \xB7 ${messages.connectionActiveHost}` : hostName;
18178
18253
  tab.addEventListener("click", () => {
@@ -18266,14 +18341,14 @@ ${error51.stderrTail}`] : []
18266
18341
  const key = JSON.stringify([selectedHost.hostId, agent]);
18267
18342
  let panel = versionPanels.get(key);
18268
18343
  if (!panel) {
18269
- const hostId = selectedHost.hostId;
18344
+ const hostId2 = selectedHost.hostId;
18270
18345
  panel = createHarnessVersionPanel(document2, messages, context.signal, agent, {
18271
18346
  async run(action) {
18272
- if (action !== "update") return installation(hostId, agent, action);
18347
+ if (action !== "update") return installation(hostId2, agent, action);
18273
18348
  updatingVersions.add(key);
18274
18349
  if (diagnostics) render(diagnostics.snapshot());
18275
18350
  try {
18276
- return await installation(hostId, agent, action);
18351
+ return await installation(hostId2, agent, action);
18277
18352
  } finally {
18278
18353
  updatingVersions.delete(key);
18279
18354
  if (!context.signal.aborted && diagnostics) render(diagnostics.snapshot());
@@ -18465,6 +18540,17 @@ ${error51.stderrTail}`] : []
18465
18540
  }
18466
18541
  };
18467
18542
  render(diagnostics?.snapshot() ?? null);
18543
+ void getRemoteConnections()?.ssh.list(context.signal).then(
18544
+ (connections) => {
18545
+ if (context.signal.aborted) return;
18546
+ for (const connection of connections) {
18547
+ hostNames.set(connection.hostId, connection.displayName.trim());
18548
+ }
18549
+ render(diagnostics?.snapshot() ?? null);
18550
+ },
18551
+ () => {
18552
+ }
18553
+ );
18468
18554
  const unsubscribeGroup = groupPreference.subscribe(
18469
18555
  () => render(diagnostics?.snapshot() ?? latestSnapshot)
18470
18556
  );
@@ -23869,7 +23955,7 @@ Codex Fast mode prioritizes requests and may increase usage.`
23869
23955
  function isRecord7(value) {
23870
23956
  return value !== null && typeof value === "object" && !Array.isArray(value);
23871
23957
  }
23872
- function installRendererManualCompaction(target, hostId, messages) {
23958
+ function installRendererManualCompaction(target, hostId2, messages) {
23873
23959
  if (!messages || typeof messages.addEventListener !== "function" || typeof messages.removeEventListener !== "function" || !isRecord7(target) || typeof target.registerPendingManualContextCompaction !== "function" || typeof target.getConversation !== "function") {
23874
23960
  return null;
23875
23961
  }
@@ -23879,7 +23965,7 @@ Codex Fast mode prioritizes requests and may increase usage.`
23879
23965
  const listener = (event) => {
23880
23966
  if (event.source != null && event.source !== messages) return;
23881
23967
  const message = event.data;
23882
- if (!isRecord7(message) || message.type !== "mcp-notification" || message.hostId !== hostId || message.method !== THREAD_MANUAL_COMPACTION_STARTED_METHOD) {
23968
+ if (!isRecord7(message) || message.type !== "mcp-notification" || message.hostId !== hostId2 || message.method !== THREAD_MANUAL_COMPACTION_STARTED_METHOD) {
23883
23969
  return;
23884
23970
  }
23885
23971
  const params = threadManualCompactionStartedSchema.safeParse(message.params);
@@ -23903,9 +23989,9 @@ Codex Fast mode prioritizes requests and may increase usage.`
23903
23989
  function createRendererHostClients(readRouting, messages = null) {
23904
23990
  let disposed = false;
23905
23991
  const entries = /* @__PURE__ */ new Map();
23906
- const retire = (hostId) => {
23907
- const entry = entries.get(hostId);
23908
- entries.delete(hostId);
23992
+ const retire = (hostId2) => {
23993
+ const entry = entries.get(hostId2);
23994
+ entries.delete(hostId2);
23909
23995
  for (const cleanup of entry?.cleanups ?? []) {
23910
23996
  try {
23911
23997
  cleanup();
@@ -23955,16 +24041,16 @@ Codex Fast mode prioritizes requests and may increase usage.`
23955
24041
  };
23956
24042
  return {
23957
24043
  forRoute,
23958
- forHost(hostId) {
24044
+ forHost(hostId2) {
23959
24045
  if (disposed) return null;
23960
- const route = readRouting()?.forHost(hostId) ?? null;
23961
- if (!route) retire(hostId);
24046
+ const route = readRouting()?.forHost(hostId2) ?? null;
24047
+ if (!route) retire(hostId2);
23962
24048
  return forRoute(route);
23963
24049
  },
23964
24050
  dispose() {
23965
24051
  if (disposed) return;
23966
24052
  disposed = true;
23967
- for (const hostId of entries.keys()) retire(hostId);
24053
+ for (const hostId2 of entries.keys()) retire(hostId2);
23968
24054
  }
23969
24055
  };
23970
24056
  }
@@ -24073,10 +24159,10 @@ Codex Fast mode prioritizes requests and may increase usage.`
24073
24159
  }
24074
24160
  function sidebarThreadAttributes(element) {
24075
24161
  const taskKey = element.getAttribute(SIDEBAR_THREAD_ID_ATTRIBUTE);
24076
- const hostId = element.getAttribute(SIDEBAR_THREAD_HOST_ID_ATTRIBUTE);
24162
+ const hostId2 = element.getAttribute(SIDEBAR_THREAD_HOST_ID_ATTRIBUTE);
24077
24163
  const rowMarker = element.getAttribute(SIDEBAR_THREAD_ROW_ATTRIBUTE);
24078
- if (taskKey === null || hostId === null || rowMarker === null) return null;
24079
- return { taskKey, hostId, rowMarker };
24164
+ if (taskKey === null || hostId2 === null || rowMarker === null) return null;
24165
+ return { taskKey, hostId: hostId2, rowMarker };
24080
24166
  }
24081
24167
  function draftIdFromSidebarRowElement(element) {
24082
24168
  const attributes = sidebarThreadAttributes(element);
@@ -24088,7 +24174,7 @@ Codex Fast mode prioritizes requests and may increase usage.`
24088
24174
  function threadIdFromSidebarRowElement(element) {
24089
24175
  const attributes = sidebarThreadAttributes(element);
24090
24176
  if (!attributes) return null;
24091
- const { taskKey, hostId, rowMarker } = attributes;
24177
+ const { taskKey, hostId: hostId2, rowMarker } = attributes;
24092
24178
  const fiberNames = Object.getOwnPropertyNames(element).filter(
24093
24179
  (name) => name.startsWith("__reactFiber$")
24094
24180
  );
@@ -24103,7 +24189,7 @@ Codex Fast mode prioritizes requests and may increase usage.`
24103
24189
  if (isRecord8(props) && isRecord8(props.dataAttributes)) {
24104
24190
  const dataAttributes = props.dataAttributes;
24105
24191
  const threadId = hostThreadIdSchema.safeParse(props.conversationId);
24106
- if (threadId.success && dataAttributes[SIDEBAR_THREAD_ROW_ATTRIBUTE] === rowMarker && dataAttributes[SIDEBAR_THREAD_ID_ATTRIBUTE] === taskKey && dataAttributes[SIDEBAR_THREAD_HOST_ID_ATTRIBUTE] === hostId) {
24192
+ if (threadId.success && dataAttributes[SIDEBAR_THREAD_ROW_ATTRIBUTE] === rowMarker && dataAttributes[SIDEBAR_THREAD_ID_ATTRIBUTE] === taskKey && dataAttributes[SIDEBAR_THREAD_HOST_ID_ATTRIBUTE] === hostId2) {
24107
24193
  candidates.add(threadId.data);
24108
24194
  }
24109
24195
  }
@@ -24253,7 +24339,7 @@ Codex Fast mode prioritizes requests and may increase usage.`
24253
24339
  const ownershipRetryTimers = /* @__PURE__ */ new Map();
24254
24340
  let disposed = false;
24255
24341
  let scanScheduled = false;
24256
- const ownershipKey = (hostId, threadId) => JSON.stringify([hostId, threadId]);
24342
+ const ownershipKey = (hostId2, threadId) => JSON.stringify([hostId2, threadId]);
24257
24343
  const scheduleScan = () => {
24258
24344
  if (disposed || scanScheduled) return;
24259
24345
  scanScheduled = true;
@@ -24267,8 +24353,8 @@ Codex Fast mode prioritizes requests and may increase usage.`
24267
24353
  failed.delete(key);
24268
24354
  provisionalCodex.delete(key);
24269
24355
  };
24270
- const scheduleOwnershipRetry = (hostId, threadId) => {
24271
- const key = ownershipKey(hostId, threadId);
24356
+ const scheduleOwnershipRetry = (hostId2, threadId) => {
24357
+ const key = ownershipKey(hostId2, threadId);
24272
24358
  if (disposed || !failed.has(key) && !provisionalCodex.has(key) || pending.has(key) || ownershipRetryTimers.has(key)) {
24273
24359
  return;
24274
24360
  }
@@ -24285,19 +24371,19 @@ Codex Fast mode prioritizes requests and may increase usage.`
24285
24371
  }, delay);
24286
24372
  ownershipRetryTimers.set(key, timer);
24287
24373
  };
24288
- const requestOwnership = (hostId, threadIds, client) => {
24289
- for (const threadId of threadIds) pending.add(ownershipKey(hostId, threadId));
24374
+ const requestOwnership = (hostId2, threadIds, client) => {
24375
+ for (const threadId of threadIds) pending.add(ownershipKey(hostId2, threadId));
24290
24376
  let succeeded = false;
24291
24377
  let retryable = true;
24292
24378
  void Promise.resolve().then(() => client.listThreadOwnership({ threadIds })).then(({ threads }) => {
24293
24379
  if (disposed) return;
24294
24380
  for (const ownership of threads) {
24295
- const key = ownershipKey(hostId, ownership.threadId);
24381
+ const key = ownershipKey(hostId2, ownership.threadId);
24296
24382
  ownershipByThread.set(key, rendererAgentForThreadOwnership(ownership));
24297
24383
  failed.delete(key);
24298
24384
  if (ownership.owner === "codex") {
24299
24385
  provisionalCodex.add(key);
24300
- scheduleOwnershipRetry(hostId, ownership.threadId);
24386
+ scheduleOwnershipRetry(hostId2, ownership.threadId);
24301
24387
  } else {
24302
24388
  clearOwnershipRetry(key);
24303
24389
  }
@@ -24306,11 +24392,11 @@ Codex Fast mode prioritizes requests and may increase usage.`
24306
24392
  }).catch((error51) => {
24307
24393
  if (disposed) return;
24308
24394
  retryable = !(error51 instanceof RendererMethodUnavailableError);
24309
- for (const threadId of threadIds) failed.add(ownershipKey(hostId, threadId));
24395
+ for (const threadId of threadIds) failed.add(ownershipKey(hostId2, threadId));
24310
24396
  }).finally(() => {
24311
- for (const threadId of threadIds) pending.delete(ownershipKey(hostId, threadId));
24397
+ for (const threadId of threadIds) pending.delete(ownershipKey(hostId2, threadId));
24312
24398
  if (retryable) {
24313
- for (const threadId of threadIds) scheduleOwnershipRetry(hostId, threadId);
24399
+ for (const threadId of threadIds) scheduleOwnershipRetry(hostId2, threadId);
24314
24400
  }
24315
24401
  if (succeeded) scheduleScan();
24316
24402
  });
@@ -24324,20 +24410,20 @@ Codex Fast mode prioritizes requests and may increase usage.`
24324
24410
  row.clear();
24325
24411
  continue;
24326
24412
  }
24327
- const hostId = row.hostId();
24328
- if (!hostId) {
24413
+ const hostId2 = row.hostId();
24414
+ if (!hostId2) {
24329
24415
  row.clear();
24330
24416
  continue;
24331
24417
  }
24332
24418
  const threadId = hostThreadIdSchema.safeParse(row.threadId());
24333
24419
  const localAgent = options.getLocalAgent?.({
24334
- hostId,
24420
+ hostId: hostId2,
24335
24421
  threadId: threadId.success ? threadId.data : null,
24336
24422
  draftId: row.draftId()
24337
24423
  });
24338
24424
  if (localAgent !== null && localAgent !== void 0) {
24339
24425
  if (threadId.success) {
24340
- const key2 = ownershipKey(hostId, threadId.data);
24426
+ const key2 = ownershipKey(hostId2, threadId.data);
24341
24427
  ownershipByThread.set(key2, localAgent === "codex" ? null : localAgent);
24342
24428
  clearOwnershipRetry(key2);
24343
24429
  }
@@ -24349,7 +24435,7 @@ Codex Fast mode prioritizes requests and may increase usage.`
24349
24435
  row.clear();
24350
24436
  continue;
24351
24437
  }
24352
- const key = ownershipKey(hostId, threadId.data);
24438
+ const key = ownershipKey(hostId2, threadId.data);
24353
24439
  if (ownershipByThread.has(key)) {
24354
24440
  const agent = ownershipByThread.get(key);
24355
24441
  if (agent) row.render(agent);
@@ -24358,28 +24444,28 @@ Codex Fast mode prioritizes requests and may increase usage.`
24358
24444
  }
24359
24445
  row.clear();
24360
24446
  if (!pending.has(key) && !failed.has(key)) {
24361
- let unresolved = unresolvedByHost.get(hostId);
24447
+ let unresolved = unresolvedByHost.get(hostId2);
24362
24448
  if (!unresolved) {
24363
24449
  unresolved = /* @__PURE__ */ new Set();
24364
- unresolvedByHost.set(hostId, unresolved);
24450
+ unresolvedByHost.set(hostId2, unresolved);
24365
24451
  }
24366
24452
  unresolved.add(threadId.data);
24367
24453
  }
24368
24454
  }
24369
- for (const [hostId, unresolved] of unresolvedByHost) {
24370
- const client = options.getClient(hostId);
24455
+ for (const [hostId2, unresolved] of unresolvedByHost) {
24456
+ const client = options.getClient(hostId2);
24371
24457
  if (!client) {
24372
24458
  for (const threadId of unresolved) {
24373
- const key = ownershipKey(hostId, threadId);
24459
+ const key = ownershipKey(hostId2, threadId);
24374
24460
  failed.add(key);
24375
- scheduleOwnershipRetry(hostId, threadId);
24461
+ scheduleOwnershipRetry(hostId2, threadId);
24376
24462
  }
24377
24463
  continue;
24378
24464
  }
24379
24465
  const threadIds = [...unresolved];
24380
24466
  for (let index = 0; index < threadIds.length; index += THREAD_OWNERSHIP_LIST_MAX_LENGTH) {
24381
24467
  requestOwnership(
24382
- hostId,
24468
+ hostId2,
24383
24469
  threadIds.slice(index, index + THREAD_OWNERSHIP_LIST_MAX_LENGTH),
24384
24470
  client
24385
24471
  );
@@ -25064,7 +25150,7 @@ Codex Fast mode prioritizes requests and may increase usage.`
25064
25150
  const localClient = disposed ? null : route?.hostId === "local" ? client : clients.forHost("local");
25065
25151
  idleReleaseSync.connect(localClient);
25066
25152
  const connected = !disposed && (client !== null || localClient !== null || (window.__codexhostHostRoutingV1?.knownHostIds?.() ?? []).some(
25067
- (hostId) => window.__codexhostHostRoutingV1?.forHost(hostId) != null
25153
+ (hostId2) => window.__codexhostHostRoutingV1?.forHost(hostId2) != null
25068
25154
  ));
25069
25155
  updateStatus(
25070
25156
  connected ? "ready" : "installing",
@@ -25092,7 +25178,7 @@ Codex Fast mode prioritizes requests and may increase usage.`
25092
25178
  return disposed ? null : route?.hostId ?? window.__codexhostHostRoutingV1?.hostIdForComposer() ?? null;
25093
25179
  },
25094
25180
  knownHostIds: () => disposed ? [] : window.__codexhostHostRoutingV1?.knownHostIds?.() ?? [],
25095
- clientForHost: (hostId) => disposed ? null : clients.forHost(hostId),
25181
+ clientForHost: (hostId2) => disposed ? null : clients.forHost(hostId2),
25096
25182
  listHarnessPlugins: async () => {
25097
25183
  const client = settingsModelClient();
25098
25184
  if (!client.listHarnessPlugins) throw new Error("Harness plugin directory is unavailable");
@@ -25296,8 +25382,8 @@ Codex Fast mode prioritizes requests and may increase usage.`
25296
25382
  KNOWN_RENDERER_AGENTS.filter(
25297
25383
  (agent) => agent !== "codex"
25298
25384
  ).flatMap((agent) => {
25299
- const configuration2 = parseExternalConfiguration(externalByAgent[agent]);
25300
- return configuration2 ? [[agent, configuration2]] : [];
25385
+ const configuration = parseExternalConfiguration(externalByAgent[agent]);
25386
+ return configuration ? [[agent, configuration]] : [];
25301
25387
  })
25302
25388
  );
25303
25389
  return {
@@ -25596,6 +25682,9 @@ Codex Fast mode prioritizes requests and may increase usage.`
25596
25682
 
25597
25683
  // src/settings/remote-failure-messages.ts
25598
25684
  var REMOTE_FAILURE_CHINESE = Object.freeze({
25685
+ "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",
25686
+ "Remote connection request timed out. Refresh before retrying": "\u8FDC\u7A0B\u8FDE\u63A5\u8BF7\u6C42\u8D85\u65F6\uFF0C\u8BF7\u5237\u65B0\u540E\u518D\u8BD5",
25687
+ "Invalid remote connection request": "\u8FDC\u7A0B\u8FDE\u63A5\u8BF7\u6C42\u65E0\u6548",
25599
25688
  // SSH helper: installing, updating and repairing over SSH.
25600
25689
  "Invalid SSH address or port": "SSH \u5730\u5740\u6216\u7AEF\u53E3\u65E0\u6548",
25601
25690
  "Install requires a published stable version": "\u53EA\u80FD\u5B89\u88C5\u5DF2\u53D1\u5E03\u7684\u6B63\u5F0F\u7248\u672C",
@@ -25605,7 +25694,13 @@ Codex Fast mode prioritizes requests and may increase usage.`
25605
25694
  "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",
25606
25695
  "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",
25607
25696
  "Only Mac and Linux remote computers are supported": "\u53EA\u652F\u6301 Mac \u548C Linux \u8FDC\u7A0B\u7535\u8111",
25608
- "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",
25697
+ "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",
25698
+ "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",
25699
+ "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",
25700
+ "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",
25701
+ "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",
25702
+ "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",
25703
+ "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",
25609
25704
  "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",
25610
25705
  "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",
25611
25706
  "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",
@@ -25903,6 +25998,9 @@ Codex Fast mode prioritizes requests and may increase usage.`
25903
25998
  }
25904
25999
  const serviceActions = remoteElement(document2, "div", "settings-remote-card__actions");
25905
26000
  if (!row.probing) {
26001
+ if (row.installation === "installed" && !remoteBusy(remote)) {
26002
+ serviceActions.append(command("uninstall", t("\u5378\u8F7D\u8FDC\u7A0B\u670D\u52A1", "Uninstall remote service")));
26003
+ }
25906
26004
  const outdated = !remote && !!row.remoteIssue?.outdated && row.installation !== "not-installed";
25907
26005
  if (outdated) {
25908
26006
  const upgrade = command("upgrade", t("\u66F4\u65B0\u8FDC\u7A0B\u670D\u52A1", "Update remote service"), true);
@@ -26219,6 +26317,61 @@ Codex Fast mode prioritizes requests and may increase usage.`
26219
26317
  });
26220
26318
  dialog.show(t("\u79FB\u9664", "Remove"), t("\u79FB\u9664\u4E2D\u2026", "Removing\u2026"), true);
26221
26319
  }
26320
+ function openRemoteServiceUninstall(options) {
26321
+ const { t, connection } = options;
26322
+ const dialog = createRemoteDialog(
26323
+ options,
26324
+ t(
26325
+ `\u5378\u8F7D\u201C${connection.displayName}\u201D\u7684\u8FDC\u7A0B\u670D\u52A1\uFF1F`,
26326
+ `Uninstall remote service on "${connection.displayName}"?`
26327
+ )
26328
+ );
26329
+ if (!dialog) return;
26330
+ const document2 = options.container.ownerDocument;
26331
+ dialog.body.append(
26332
+ remoteElement(
26333
+ document2,
26334
+ "p",
26335
+ "",
26336
+ t(
26337
+ "\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",
26338
+ "Uninstalling interrupts sessions started through codexhost. To keep using it on that computer, manually relaunch through codexhost."
26339
+ )
26340
+ )
26341
+ );
26342
+ const label = remoteElement(document2, "label", "settings-remote-dialog__package-option");
26343
+ const removePackage = remoteElement(document2, "input");
26344
+ removePackage.type = "checkbox";
26345
+ label.append(
26346
+ removePackage,
26347
+ t("\u540C\u65F6\u5378\u8F7D codexhost \u8F6F\u4EF6\u5305", "Also uninstall the codexhost package")
26348
+ );
26349
+ dialog.body.append(
26350
+ label,
26351
+ remoteElement(
26352
+ document2,
26353
+ "p",
26354
+ "",
26355
+ t(
26356
+ "\u52FE\u9009\u540E\uFF0C\u518D\u6B21\u4F7F\u7528\u524D\u9700\u91CD\u65B0\u5B89\u88C5 codexhost\u3002",
26357
+ "If selected, reinstall codexhost before using it again."
26358
+ )
26359
+ )
26360
+ );
26361
+ dialog.form.addEventListener("submit", (event) => {
26362
+ event.preventDefault();
26363
+ const selected = removePackage.checked;
26364
+ dialog.submit(async () => {
26365
+ removePackage.disabled = true;
26366
+ try {
26367
+ await options.uninstall(selected);
26368
+ } finally {
26369
+ removePackage.disabled = false;
26370
+ }
26371
+ });
26372
+ });
26373
+ dialog.show(t("\u5378\u8F7D", "Uninstall"), t("\u5378\u8F7D\u4E2D\u2026", "Uninstalling\u2026"), true);
26374
+ }
26222
26375
 
26223
26376
  // src/settings/remote-connections-page.ts
26224
26377
  var POLL_INTERVAL_MS = 5e3;
@@ -26347,17 +26500,17 @@ Codex Fast mode prioritizes requests and may increase usage.`
26347
26500
  banner.hidden = !loadError;
26348
26501
  bannerText.textContent = loadError ? `${t("\u8BFB\u53D6\u8FDE\u63A5\u5931\u8D25", "Could not load connections")}: ${localizeRemoteFailure(loadError, t)}` : "";
26349
26502
  renderPlaceholder();
26350
- for (const [hostId, card] of cards) {
26351
- if (rows.has(hostId)) continue;
26503
+ for (const [hostId2, card] of cards) {
26504
+ if (rows.has(hostId2)) continue;
26352
26505
  card.element.remove();
26353
- cards.delete(hostId);
26506
+ cards.delete(hostId2);
26354
26507
  }
26355
26508
  const active = focusedElement();
26356
- order.forEach((hostId, index) => {
26357
- const row = rows.get(hostId);
26509
+ order.forEach((hostId2, index) => {
26510
+ const row = rows.get(hostId2);
26358
26511
  if (!row) return;
26359
26512
  const signature = JSON.stringify([row, local]);
26360
- let card = cards.get(hostId);
26513
+ let card = cards.get(hostId2);
26361
26514
  if (card?.signature !== signature) {
26362
26515
  const element = renderRemoteCard(
26363
26516
  document2,
@@ -26369,7 +26522,7 @@ Codex Fast mode prioritizes requests and may increase usage.`
26369
26522
  const focusedAction = active && card?.element.contains(active) ? active.dataset.action : void 0;
26370
26523
  if (card) card.element.replaceWith(element);
26371
26524
  card = { element, signature };
26372
- cards.set(hostId, card);
26525
+ cards.set(hostId2, card);
26373
26526
  if (focusedAction) focusAction(element, focusedAction);
26374
26527
  }
26375
26528
  if (list.children[index] !== card.element)
@@ -26381,38 +26534,41 @@ Codex Fast mode prioritizes requests and may increase usage.`
26381
26534
  target?.focus();
26382
26535
  }
26383
26536
  async function probe(row) {
26384
- const { hostId } = row.connection;
26385
- const token = (probeTokens.get(hostId) ?? 0) + 1;
26386
- probeTokens.set(hostId, token);
26387
- const state = await control.ssh.state(hostId, signal).catch((error51) => ({ state: "unknown", error: remoteErrorMessage(error51) }));
26537
+ const { hostId: hostId2 } = row.connection;
26538
+ const token = (probeTokens.get(hostId2) ?? 0) + 1;
26539
+ probeTokens.set(hostId2, token);
26540
+ const state = await control.ssh.state(hostId2, signal).catch((error51) => ({ state: "unknown", error: remoteErrorMessage(error51) }));
26388
26541
  let remote = null;
26389
26542
  let remoteIssue = null;
26390
26543
  if (state.state === "connected")
26391
- remote = await control.runtime(hostId).catch((error51) => {
26544
+ remote = await control.runtime(hostId2).catch((error51) => {
26392
26545
  remoteIssue = remoteVersionIssue(error51);
26393
26546
  return null;
26394
26547
  });
26548
+ if (signal.aborted || rows.get(hostId2) !== row || probeTokens.get(hostId2) !== token) return;
26395
26549
  let expectedGap = false;
26396
- if (remote && remoteBusy(remote)) restarting.set(hostId, Date.now() + RESTART_GRACE_MS);
26397
- else if (remote || (restarting.get(hostId) ?? 0) <= Date.now()) restarting.delete(hostId);
26550
+ if (remote && remoteBusy(remote)) restarting.set(hostId2, Date.now() + RESTART_GRACE_MS);
26551
+ else if (remote || (restarting.get(hostId2) ?? 0) <= Date.now()) restarting.delete(hostId2);
26398
26552
  else if (row.remote) {
26399
26553
  expectedGap = true;
26400
26554
  remote = { ...row.remote, update: { ...row.remote.update, phase: "restarting" } };
26401
26555
  remoteIssue = null;
26402
26556
  }
26403
- if (remote) installations.set(hostId, "installed");
26404
- else if (!installations.has(hostId) && Date.now() - (inspectFailures.get(hostId) ?? -INSPECT_RETRY_MS) >= INSPECT_RETRY_MS) {
26557
+ if (remote) installations.set(hostId2, "installed");
26558
+ else if (!installations.has(hostId2) && Date.now() - (inspectFailures.get(hostId2) ?? -INSPECT_RETRY_MS) >= INSPECT_RETRY_MS) {
26405
26559
  const inspected = await control.setup(row.connection, "inspect").catch(() => null);
26406
- if (inspected) installations.set(hostId, inspected.state);
26407
- else inspectFailures.set(hostId, Date.now());
26560
+ if (signal.aborted || rows.get(hostId2) !== row || probeTokens.get(hostId2) !== token)
26561
+ return;
26562
+ if (inspected) installations.set(hostId2, inspected.state);
26563
+ else inspectFailures.set(hostId2, Date.now());
26408
26564
  }
26409
- if (signal.aborted || rows.get(hostId) !== row || probeTokens.get(hostId) !== token) return;
26565
+ if (signal.aborted || rows.get(hostId2) !== row || probeTokens.get(hostId2) !== token) return;
26410
26566
  row.probing = false;
26411
26567
  row.state = expectedGap ? "connecting" : state.state;
26412
26568
  row.stateError = expectedGap ? null : state.error;
26413
26569
  row.remote = remote;
26414
26570
  row.remoteIssue = remoteIssue;
26415
- row.installation = installations.get(hostId) ?? "unknown";
26571
+ row.installation = installations.get(hostId2) ?? "unknown";
26416
26572
  render();
26417
26573
  }
26418
26574
  async function refresh(actingHostId, wait = "acting") {
@@ -26452,27 +26608,28 @@ Codex Fast mode prioritizes requests and may increase usage.`
26452
26608
  notice: null
26453
26609
  });
26454
26610
  }
26455
- for (const hostId of [...rows.keys()]) {
26456
- if (order.includes(hostId)) continue;
26457
- rows.delete(hostId);
26458
- installations.delete(hostId);
26459
- probeTokens.delete(hostId);
26460
- inspectFailures.delete(hostId);
26461
- restarting.delete(hostId);
26611
+ for (const hostId2 of [...rows.keys()]) {
26612
+ if (order.includes(hostId2)) continue;
26613
+ rows.delete(hostId2);
26614
+ installations.delete(hostId2);
26615
+ probeTokens.delete(hostId2);
26616
+ inspectFailures.delete(hostId2);
26617
+ restarting.delete(hostId2);
26462
26618
  }
26463
26619
  render();
26464
26620
  const probes = [...rows.values()].filter((row) => !row.pending || row.connection.hostId === actingHostId).map((row) => ({ hostId: row.connection.hostId, done: probe(row) }));
26465
26621
  const awaited = wait === "all" ? probes : probes.filter((p) => p.hostId === actingHostId);
26466
26622
  await Promise.all([localTask, ...awaited.map((p) => p.done)]);
26467
26623
  }
26468
- async function act(row, action, label, operation) {
26469
- const { hostId } = row.connection;
26624
+ async function act(row, action, label, operation, rethrow = false) {
26625
+ const { hostId: hostId2 } = row.connection;
26626
+ probeTokens.set(hostId2, (probeTokens.get(hostId2) ?? 0) + 1);
26470
26627
  row.pending = label;
26471
26628
  row.notice = null;
26472
26629
  render();
26473
26630
  try {
26474
26631
  const done = await operation();
26475
- await refresh(hostId);
26632
+ await refresh(hostId2);
26476
26633
  if (typeof done === "string") {
26477
26634
  const notice = { tone: "success", text: done };
26478
26635
  row.notice = notice;
@@ -26484,14 +26641,15 @@ Codex Fast mode prioritizes requests and may increase usage.`
26484
26641
  }
26485
26642
  } catch (error51) {
26486
26643
  row.notice = { tone: "danger", text: remoteErrorMessage(error51) };
26487
- installations.delete(hostId);
26488
- inspectFailures.delete(hostId);
26489
- void refresh(hostId);
26644
+ installations.delete(hostId2);
26645
+ inspectFailures.delete(hostId2);
26646
+ void refresh(hostId2);
26647
+ if (rethrow) throw error51;
26490
26648
  } finally {
26491
26649
  row.pending = null;
26492
26650
  if (!signal.aborted) {
26493
26651
  render();
26494
- const card = cards.get(hostId)?.element;
26652
+ const card = cards.get(hostId2)?.element;
26495
26653
  if (card && !focusedElement()) focusAction(card, action);
26496
26654
  }
26497
26655
  }
@@ -26516,9 +26674,9 @@ Codex Fast mode prioritizes requests and may increase usage.`
26516
26674
  function handle(row, action) {
26517
26675
  if (row.pending) return;
26518
26676
  const { connection } = row;
26519
- const { hostId } = connection;
26677
+ const { hostId: hostId2 } = connection;
26520
26678
  const setConnected = async (enabled) => {
26521
- const request = control.ssh.connect(hostId, enabled, signal);
26679
+ const request = control.ssh.connect(hostId2, enabled, signal);
26522
26680
  request.catch(() => void 0);
26523
26681
  await Promise.race([
26524
26682
  request,
@@ -26526,8 +26684,8 @@ Codex Fast mode prioritizes requests and may increase usage.`
26526
26684
  ]);
26527
26685
  };
26528
26686
  const reconnect = async () => {
26529
- installations.delete(hostId);
26530
- inspectFailures.delete(hostId);
26687
+ installations.delete(hostId2);
26688
+ inspectFailures.delete(hostId2);
26531
26689
  await setConnected(true);
26532
26690
  };
26533
26691
  switch (action) {
@@ -26562,8 +26720,8 @@ Codex Fast mode prioritizes requests and may increase usage.`
26562
26720
  break;
26563
26721
  case "recheck":
26564
26722
  void act(row, action, t("\u6B63\u5728\u91CD\u65B0\u68C0\u6D4B\u2026", "Checking again\u2026"), async () => {
26565
- installations.delete(hostId);
26566
- inspectFailures.delete(hostId);
26723
+ installations.delete(hostId2);
26724
+ inspectFailures.delete(hostId2);
26567
26725
  });
26568
26726
  break;
26569
26727
  case "install": {
@@ -26608,6 +26766,47 @@ Codex Fast mode prioritizes requests and may increase usage.`
26608
26766
  }
26609
26767
  );
26610
26768
  break;
26769
+ case "uninstall":
26770
+ if (row.installation !== "installed" || remoteBusy(row.remote)) break;
26771
+ openRemoteServiceUninstall({
26772
+ container: root,
26773
+ signal,
26774
+ t,
26775
+ connection,
26776
+ async uninstall(removePackage) {
26777
+ if (row.pending || remoteBusy(row.remote))
26778
+ throw new Error(
26779
+ t(
26780
+ "\u8FDC\u7A0B\u670D\u52A1\u6B63\u5728\u6267\u884C\u5176\u4ED6\u64CD\u4F5C\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5",
26781
+ "Another remote operation is active; retry shortly"
26782
+ )
26783
+ );
26784
+ await act(
26785
+ row,
26786
+ action,
26787
+ t("\u6B63\u5728\u5378\u8F7D\u8FDC\u7A0B\u670D\u52A1\u2026", "Uninstalling remote service\u2026"),
26788
+ async () => {
26789
+ await control.ssh.connect(hostId2, false, signal);
26790
+ await control.setup(connection, "uninstall", void 0, removePackage);
26791
+ installations.set(hostId2, "not-installed");
26792
+ inspectFailures.delete(hostId2);
26793
+ restarting.delete(hostId2);
26794
+ row.remote = null;
26795
+ row.remoteIssue = null;
26796
+ row.stateError = null;
26797
+ return removePackage ? t(
26798
+ "\u8FDC\u7A0B\u670D\u52A1\u548C codexhost \u8F6F\u4EF6\u5305\u5DF2\u5378\u8F7D",
26799
+ "Remote service and codexhost package uninstalled"
26800
+ ) : t(
26801
+ "\u8FDC\u7A0B\u670D\u52A1\u5DF2\u5378\u8F7D\uFF0Ccodexhost \u8F6F\u4EF6\u5305\u5DF2\u4FDD\u7559",
26802
+ "Remote service uninstalled; codexhost package kept"
26803
+ );
26804
+ },
26805
+ true
26806
+ );
26807
+ }
26808
+ });
26809
+ break;
26611
26810
  case "update": {
26612
26811
  const target = row.remote ? remoteMaintenanceTarget(local, row.remote) : null;
26613
26812
  if (!target) break;
@@ -26617,7 +26816,7 @@ Codex Fast mode prioritizes requests and may increase usage.`
26617
26816
  action,
26618
26817
  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"),
26619
26818
  async () => {
26620
- await control.update(hostId, target);
26819
+ await control.update(hostId2, target);
26621
26820
  await setConnected(true);
26622
26821
  }
26623
26822
  );
@@ -27313,7 +27512,7 @@ Codex Fast mode prioritizes requests and may increase usage.`
27313
27512
  void context.runLatest(
27314
27513
  async (signal) => {
27315
27514
  const missing = new Set(
27316
- getDiagnostics()?.snapshot().hosts.find(({ hostId }) => hostId === "local")?.agents.filter(({ availability }) => availability === "notInstalled").map(({ agent }) => agent)
27515
+ getDiagnostics()?.snapshot().hosts.find(({ hostId: hostId2 }) => hostId2 === "local")?.agents.filter(({ availability }) => availability === "notInstalled").map(({ agent }) => agent)
27317
27516
  );
27318
27517
  const harnesses = (await client.listSessionImportSources()).harnesses.filter(
27319
27518
  ({ harnessId }) => !missing.has(harnessId)
@@ -29786,7 +29985,7 @@ Codex Fast mode prioritizes requests and may increase usage.`
29786
29985
  }
29787
29986
  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) {
29788
29987
  return Object.freeze([
29789
- createConnectionsSettingsPage(messages, getDiagnostics),
29988
+ createConnectionsSettingsPage(messages, getDiagnostics, void 0, getRemoteConnections),
29790
29989
  createRemoteConnectionsPage(messages, getRemoteConnections),
29791
29990
  createAccountsSettingsPage(messages, getAccountClient),
29792
29991
  createSessionImportSettingsPage(
@@ -32302,6 +32501,23 @@ Codex Fast mode prioritizes requests and may increase usage.`
32302
32501
  outline-offset: -1px;
32303
32502
  }
32304
32503
 
32504
+ .settings-remote-dialog__package-option {
32505
+ display: flex;
32506
+ align-items: center;
32507
+ gap: 8px;
32508
+ cursor: pointer;
32509
+ }
32510
+
32511
+ .settings-remote-dialog .settings-remote-dialog__package-option input {
32512
+ flex: none;
32513
+ width: 16px;
32514
+ height: 16px;
32515
+ min-height: 16px;
32516
+ margin: 0;
32517
+ padding: 0;
32518
+ accent-color: var(--settings-focus);
32519
+ }
32520
+
32305
32521
  @keyframes settings-remote-spin {
32306
32522
  to {
32307
32523
  transform: rotate(360deg);
@@ -34421,9 +34637,9 @@ ${accounts_default}`;
34421
34637
  var rendererUsageRefreshDelays = [250, 500, 1e3, 2e3, 4e3, 8e3];
34422
34638
  function refreshConnectionHosts(hostIds, refreshHost, pendingHost) {
34423
34639
  return Promise.all(
34424
- [...hostIds].map(async (hostId) => {
34425
- if (pendingHost) await pendingHost(hostId)?.catch(() => void 0);
34426
- await refreshHost(hostId);
34640
+ [...hostIds].map(async (hostId2) => {
34641
+ if (pendingHost) await pendingHost(hostId2)?.catch(() => void 0);
34642
+ await refreshHost(hostId2);
34427
34643
  })
34428
34644
  ).then(() => void 0);
34429
34645
  }
@@ -34648,9 +34864,9 @@ ${accounts_default}`;
34648
34864
  if (!isLateConversationTarget(mountedTarget, currentTarget)) return "none";
34649
34865
  return mountedTarget?.[0] === "default" && (sourcePhase === "locked" || submissionPending) ? "transfer" : "inspect";
34650
34866
  }
34651
- function scopedComposerTarget(target, hostId) {
34652
- if (target?.[0] !== "conversation" || !hostId) return target;
34653
- return ["conversation", target[1], hostId];
34867
+ function scopedComposerTarget(target, hostId2) {
34868
+ if (target?.[0] !== "conversation" || !hostId2) return target;
34869
+ return ["conversation", target[1], hostId2];
34654
34870
  }
34655
34871
  function isComposerModelWriteAllowed(target) {
34656
34872
  return target?.[0] === "default";
@@ -34723,7 +34939,7 @@ ${accounts_default}`;
34723
34939
  if (!modelControl) return null;
34724
34940
  return modelControl.currentHostId ? modelControl.currentHostId(composer) : "local";
34725
34941
  };
34726
- const controllerTarget = (target, hostId) => scopedComposerTarget(target, hostId);
34942
+ const controllerTarget = (target, hostId2) => scopedComposerTarget(target, hostId2);
34727
34943
  const usageSubscriptions = /* @__PURE__ */ new Map();
34728
34944
  const usageNotificationDispose = () => {
34729
34945
  for (const subscription of usageSubscriptions.values()) subscription.dispose();
@@ -34742,7 +34958,7 @@ ${accounts_default}`;
34742
34958
  return null;
34743
34959
  };
34744
34960
  const sidebarAgentIcons = installRendererSidebarAgentIcons({
34745
- getClient: (hostId) => modelClientForHost(hostId),
34961
+ getClient: (hostId2) => modelClientForHost(hostId2),
34746
34962
  getLocalAgent: localAgentForSidebarThread
34747
34963
  });
34748
34964
  let connectionDiagnostics = null;
@@ -34808,27 +35024,27 @@ ${accounts_default}`;
34808
35024
  retryAttempt: 0
34809
35025
  });
34810
35026
  const harnessAvailabilityByHost = /* @__PURE__ */ new Map();
34811
- const hostHarnessAvailabilityState = (hostId) => {
34812
- let state = harnessAvailabilityByHost.get(hostId);
35027
+ const hostHarnessAvailabilityState = (hostId2) => {
35028
+ let state = harnessAvailabilityByHost.get(hostId2);
34813
35029
  if (!state) {
34814
35030
  state = createHostHarnessAvailabilityState();
34815
- harnessAvailabilityByHost.set(hostId, state);
35031
+ harnessAvailabilityByHost.set(hostId2, state);
34816
35032
  }
34817
35033
  return state;
34818
35034
  };
34819
- const codexAccountsForHost = (hostId) => {
34820
- if (!hostId) return null;
34821
- const client = modelClientForHost(hostId);
35035
+ const codexAccountsForHost = (hostId2) => {
35036
+ if (!hostId2) return null;
35037
+ const client = modelClientForHost(hostId2);
34822
35038
  if (!client) return null;
34823
- const state = hostHarnessAvailabilityState(hostId);
35039
+ const state = hostHarnessAvailabilityState(hostId2);
34824
35040
  if (state.codexAccounts?.client !== client) {
34825
35041
  state.codexAccounts?.dispose();
34826
35042
  state.codexAccounts = new RendererCodexAccountState(client, () => {
34827
35043
  queueMicrotask(() => {
34828
- if (disposed || hostHarnessAvailabilityState(hostId).codexAccounts?.client !== client)
35044
+ if (disposed || hostHarnessAvailabilityState(hostId2).codexAccounts?.client !== client)
34829
35045
  return;
34830
35046
  for (const mounted of mountedByComposer.values()) {
34831
- if (mounted.hostId !== hostId) continue;
35047
+ if (mounted.hostId !== hostId2) continue;
34832
35048
  renderMounted(mounted);
34833
35049
  void refreshDraftCodexUsage(mounted);
34834
35050
  }
@@ -34915,8 +35131,8 @@ ${accounts_default}`;
34915
35131
  {
34916
35132
  const published = Reflect.get(window, "__codexhostDraftWorkspacesV1");
34917
35133
  if (typeof published === "object" && published !== null) {
34918
- for (const [hostId, cwd] of Object.entries(published)) {
34919
- if (typeof cwd === "string" && cwd.length > 0) draftWorkspaces.set(hostId, cwd);
35134
+ for (const [hostId2, cwd] of Object.entries(published)) {
35135
+ if (typeof cwd === "string" && cwd.length > 0) draftWorkspaces.set(hostId2, cwd);
34920
35136
  }
34921
35137
  }
34922
35138
  }
@@ -34924,17 +35140,17 @@ ${accounts_default}`;
34924
35140
  const generation = ++mounted.commandRequestGeneration;
34925
35141
  const agent = controller.get(mounted.composer).agent;
34926
35142
  const threadId = threadIdFromComposerModelTarget(mounted.modelTarget);
34927
- const hostId = threadId ? mounted.hostId : activeModelHostId(mounted.composer);
35143
+ const hostId2 = threadId ? mounted.hostId : activeModelHostId(mounted.composer);
34928
35144
  const requestControl = modelControl;
34929
- const client = modelClientForHostFrom(requestControl, hostId);
35145
+ const client = modelClientForHostFrom(requestControl, hostId2);
34930
35146
  if (!keepCurrent || agent === "codex") mounted.control.harnessCommands.setCommands([]);
34931
35147
  if (agent === "codex" || !client) return;
34932
35148
  try {
34933
35149
  const catalog = threadId ? await client.inspectThreadCommands({ threadId }) : await client.inspectHarnessCommands({
34934
35150
  harnessId: externalHarnessIds[agent],
34935
- ...hostId && draftWorkspaces.has(hostId) ? { cwd: draftWorkspaces.get(hostId) } : {}
35151
+ ...hostId2 && draftWorkspaces.has(hostId2) ? { cwd: draftWorkspaces.get(hostId2) } : {}
34936
35152
  });
34937
- if (disposed || mountedByComposer.get(mounted.composer) !== mounted || mounted.commandRequestGeneration !== generation || requestControl !== modelControl || (threadIdFromComposerModelTarget(mounted.modelTarget) ? mounted.hostId : activeModelHostId(mounted.composer)) !== hostId || controller.get(mounted.composer).agent !== agent)
35153
+ if (disposed || mountedByComposer.get(mounted.composer) !== mounted || mounted.commandRequestGeneration !== generation || requestControl !== modelControl || (threadIdFromComposerModelTarget(mounted.modelTarget) ? mounted.hostId : activeModelHostId(mounted.composer)) !== hostId2 || controller.get(mounted.composer).agent !== agent)
34938
35154
  return;
34939
35155
  mounted.control.harnessCommands.setCommands(
34940
35156
  catalog.commands,
@@ -34974,9 +35190,9 @@ ${accounts_default}`;
34974
35190
  }
34975
35191
  console.error("codexhost Harness command could not claim the current Composer editor");
34976
35192
  };
34977
- const applyThreadUsageUpdate = (hostId, update) => {
35193
+ const applyThreadUsageUpdate = (hostId2, update) => {
34978
35194
  for (const mounted of mountedByComposer.values()) {
34979
- if (mounted.hostId !== hostId || threadIdFromComposerModelTarget(mounted.modelTarget) !== update.threadId)
35195
+ if (mounted.hostId !== hostId2 || threadIdFromComposerModelTarget(mounted.modelTarget) !== update.threadId)
34980
35196
  continue;
34981
35197
  mounted.usageRequestGeneration += 1;
34982
35198
  mounted.usage = update.usage;
@@ -34992,7 +35208,7 @@ ${accounts_default}`;
34992
35208
  const accounts = composerCodexAccounts(mounted.composer);
34993
35209
  const client = accounts?.client;
34994
35210
  const accountId = accounts?.readyAccountId;
34995
- const hostId = mounted.hostId;
35211
+ const hostId2 = mounted.hostId;
34996
35212
  const generation = ++mounted.usageRequestGeneration;
34997
35213
  mounted.usage = null;
34998
35214
  mounted.accountCredits = null;
@@ -35000,7 +35216,7 @@ ${accounts_default}`;
35000
35216
  if (!accountId || !client?.inspectCodexAccountUsage) return;
35001
35217
  try {
35002
35218
  const result = await client.inspectCodexAccountUsage({ accountId });
35003
- if (disposed || mounted.hostId !== hostId || composerCodexAccounts(mounted.composer) !== accounts || !mounted.composer.isConnected || mountedByComposer.get(mounted.composer) !== mounted || mounted.usageRequestGeneration !== generation || controller.get(mounted.composer).agent !== "codex" || controller.get(mounted.composer).phase !== "draft" || controller.isSubmissionPending(mounted.composer) || threadIdFromComposerModelTarget(mounted.modelTarget) || accounts.readyAccountId !== accountId || result.accountId !== accountId)
35219
+ if (disposed || mounted.hostId !== hostId2 || composerCodexAccounts(mounted.composer) !== accounts || !mounted.composer.isConnected || mountedByComposer.get(mounted.composer) !== mounted || mounted.usageRequestGeneration !== generation || controller.get(mounted.composer).agent !== "codex" || controller.get(mounted.composer).phase !== "draft" || controller.isSubmissionPending(mounted.composer) || threadIdFromComposerModelTarget(mounted.modelTarget) || accounts.readyAccountId !== accountId || result.accountId !== accountId)
35004
35220
  return;
35005
35221
  mounted.usage = result.usage;
35006
35222
  mounted.accountCredits = result.accountCredits ?? null;
@@ -35021,7 +35237,7 @@ ${accounts_default}`;
35021
35237
  renderMounted(mounted);
35022
35238
  return;
35023
35239
  }
35024
- const hostId = mounted.hostId;
35240
+ const hostId2 = mounted.hostId;
35025
35241
  const client = composerClient(mounted);
35026
35242
  if (!client) return;
35027
35243
  const generation = ++mounted.usageRequestGeneration;
@@ -35030,7 +35246,7 @@ ${accounts_default}`;
35030
35246
  threadId,
35031
35247
  ...refresh ? { refresh } : {}
35032
35248
  });
35033
- if (disposed || mountedByComposer.get(mounted.composer) !== mounted || !mounted.composer.isConnected || mounted.usageRequestGeneration !== generation || mounted.hostId !== hostId || composerClient(mounted) !== client || threadIdFromComposerModelTarget(mounted.modelTarget) !== threadId || result.threadId !== threadId) {
35249
+ if (disposed || mountedByComposer.get(mounted.composer) !== mounted || !mounted.composer.isConnected || mounted.usageRequestGeneration !== generation || mounted.hostId !== hostId2 || composerClient(mounted) !== client || threadIdFromComposerModelTarget(mounted.modelTarget) !== threadId || result.threadId !== threadId) {
35034
35250
  return;
35035
35251
  }
35036
35252
  mounted.usage = result.usage;
@@ -35836,13 +36052,13 @@ ${accounts_default}`;
35836
36052
  const loadCodexAccounts = async () => {
35837
36053
  const hostIds = new Set([...mountedByComposer.values()].map((mounted) => mounted.hostId));
35838
36054
  await Promise.all(
35839
- [...hostIds].map(async (hostId) => {
35840
- const accounts = codexAccountsForHost(hostId);
36055
+ [...hostIds].map(async (hostId2) => {
36056
+ const accounts = codexAccountsForHost(hostId2);
35841
36057
  if (!accounts) return;
35842
36058
  await accounts.refresh();
35843
- if (disposed || codexAccountsForHost(hostId) !== accounts) return;
36059
+ if (disposed || codexAccountsForHost(hostId2) !== accounts) return;
35844
36060
  for (const mounted of mountedByComposer.values()) {
35845
- if (mounted.hostId !== hostId) continue;
36061
+ if (mounted.hostId !== hostId2) continue;
35846
36062
  renderMounted(mounted);
35847
36063
  void refreshDraftCodexUsage(mounted);
35848
36064
  }
@@ -35853,16 +36069,16 @@ ${accounts_default}`;
35853
36069
  const url2 = RENDERER_AGENT_INSTALL_URLS[agent];
35854
36070
  window.open(url2, "_blank", "noopener,noreferrer");
35855
36071
  };
35856
- function resetHarnessAvailabilityRetry(hostId) {
35857
- const state = hostHarnessAvailabilityState(hostId);
36072
+ function resetHarnessAvailabilityRetry(hostId2) {
36073
+ const state = hostHarnessAvailabilityState(hostId2);
35858
36074
  if (state.retryTimer !== null) {
35859
36075
  window.clearTimeout(state.retryTimer);
35860
36076
  state.retryTimer = null;
35861
36077
  }
35862
36078
  state.retryAttempt = 0;
35863
36079
  }
35864
- function scheduleHarnessAvailabilityRetry(hostId) {
35865
- const state = hostHarnessAvailabilityState(hostId);
36080
+ function scheduleHarnessAvailabilityRetry(hostId2) {
36081
+ const state = hostHarnessAvailabilityState(hostId2);
35866
36082
  if (disposed || state.retryTimer !== null || state.retryAttempt >= availabilityRetryDelays.length) {
35867
36083
  return;
35868
36084
  }
@@ -35870,50 +36086,50 @@ ${accounts_default}`;
35870
36086
  state.retryAttempt += 1;
35871
36087
  state.retryTimer = window.setTimeout(() => {
35872
36088
  state.retryTimer = null;
35873
- void refreshHarnessAvailabilityForHost(hostId, true, true);
36089
+ void refreshHarnessAvailabilityForHost(hostId2, true, true);
35874
36090
  }, delay);
35875
36091
  }
35876
- function modelClientForHostFrom(control, hostId) {
35877
- if (!control || !hostId) return null;
35878
- if (control.clientForHost) return control.clientForHost(hostId);
35879
- if (!control.currentHostId) return hostId === "local" ? control : null;
35880
- return control.currentHostId() === hostId ? control : null;
36092
+ function modelClientForHostFrom(control, hostId2) {
36093
+ if (!control || !hostId2) return null;
36094
+ if (control.clientForHost) return control.clientForHost(hostId2);
36095
+ if (!control.currentHostId) return hostId2 === "local" ? control : null;
36096
+ return control.currentHostId() === hostId2 ? control : null;
35881
36097
  }
35882
- function modelClientForHost(hostId) {
35883
- return modelClientForHostFrom(modelControl, hostId);
36098
+ function modelClientForHost(hostId2) {
36099
+ return modelClientForHostFrom(modelControl, hostId2);
35884
36100
  }
35885
- function refreshHarnessAvailabilityForHost(hostId, refresh = false, retry = false, force = false) {
35886
- const state = hostHarnessAvailabilityState(hostId);
35887
- if (!retry) resetHarnessAvailabilityRetry(hostId);
35888
- const client = modelClientForHost(hostId);
36101
+ function refreshHarnessAvailabilityForHost(hostId2, refresh = false, retry = false, force = false) {
36102
+ const state = hostHarnessAvailabilityState(hostId2);
36103
+ if (!retry) resetHarnessAvailabilityRetry(hostId2);
36104
+ const client = modelClientForHost(hostId2);
35889
36105
  if (!client) {
35890
36106
  if (state.request) {
35891
36107
  state.requestGeneration += 1;
35892
36108
  state.request = null;
35893
36109
  }
35894
- if (force || [...mountedByComposer.values()].some((mounted) => mounted.hostId === hostId)) {
36110
+ if (force || [...mountedByComposer.values()].some((mounted) => mounted.hostId === hostId2)) {
35895
36111
  for (const agent of externalAgents) {
35896
36112
  state.availability[agent] = "error";
35897
36113
  state.errors[agent] = {
35898
36114
  code: "unavailable",
35899
- message: `Renderer connection is unavailable for Host ${hostId}`,
36115
+ message: `Renderer connection is unavailable for Host ${hostId2}`,
35900
36116
  retryable: true,
35901
36117
  stage: "request"
35902
36118
  };
35903
36119
  state.webUi[agent] = false;
35904
36120
  }
35905
36121
  publishConnectionStatus();
35906
- if (hostId === activeAvailabilityHostId) {
36122
+ if (hostId2 === activeAvailabilityHostId) {
35907
36123
  for (const mounted of mountedByComposer.values()) renderMounted(mounted);
35908
36124
  }
35909
36125
  }
35910
- scheduleHarnessAvailabilityRetry(hostId);
36126
+ scheduleHarnessAvailabilityRetry(hostId2);
35911
36127
  return Promise.resolve();
35912
36128
  }
35913
36129
  if (state.request?.client === client) return state.request.promise;
35914
36130
  const agentsToInspect = force ? externalAgents : passiveHarnessAvailabilityAgents(state.availability, state.errors);
35915
36131
  if (agentsToInspect.length === 0) {
35916
- resetHarnessAvailabilityRetry(hostId);
36132
+ resetHarnessAvailabilityRetry(hostId2);
35917
36133
  return Promise.resolve();
35918
36134
  }
35919
36135
  const nextAvailability = { ...state.availability };
@@ -35921,7 +36137,7 @@ ${accounts_default}`;
35921
36137
  nextAvailability[agent] = harnessAvailabilityDuringInspect(nextAvailability[agent]);
35922
36138
  }
35923
36139
  state.availability = nextAvailability;
35924
- if (hostId === activeAvailabilityHostId) {
36140
+ if (hostId2 === activeAvailabilityHostId) {
35925
36141
  publishConnectionStatus();
35926
36142
  for (const mounted of mountedByComposer.values()) renderMounted(mounted);
35927
36143
  }
@@ -35938,7 +36154,7 @@ ${accounts_default}`;
35938
36154
  { priority: "background" }
35939
36155
  );
35940
36156
  status = inspection.status === "ready" ? "ready" : inspection.status;
35941
- webUiAvailable = hostId === "local" && inspection.status === "ready" && inspection.webUi?.open === true;
36157
+ webUiAvailable = hostId2 === "local" && inspection.status === "ready" && inspection.webUi?.open === true;
35942
36158
  if (inspection.status !== "ready") {
35943
36159
  const error51 = inspection.error;
35944
36160
  nextError = {
@@ -35966,17 +36182,17 @@ ${accounts_default}`;
35966
36182
  state.availability = { ...state.availability, [agent]: status };
35967
36183
  state.webUi = { ...state.webUi, [agent]: webUiAvailable };
35968
36184
  for (const mounted of mountedByComposer.values()) {
35969
- if (mounted.hostId !== hostId) continue;
36185
+ if (mounted.hostId !== hostId2) continue;
35970
36186
  const composerState = controller.get(mounted.composer);
35971
36187
  if (composerAdapterState(mounted) === "ready" && composerState.phase === "draft" && composerState.agent === agent && status !== "ready") {
35972
36188
  await switchComposerAgent(mounted, "codex");
35973
36189
  }
35974
36190
  }
35975
36191
  for (const mounted of mountedByComposer.values()) {
35976
- if (mounted.hostId !== hostId) continue;
36192
+ if (mounted.hostId !== hostId2) continue;
35977
36193
  const composerState = controller.get(mounted.composer);
35978
36194
  const pendingCatalog = catalogRequests.get(mounted);
35979
- const loadingCurrentCatalog = pendingCatalog?.client === client && pendingCatalog.hostId === hostId && pendingCatalog.agent === agent && isCurrentModelRequest(mounted, pendingCatalog.generation);
36195
+ const loadingCurrentCatalog = pendingCatalog?.client === client && pendingCatalog.hostId === hostId2 && pendingCatalog.agent === agent && isCurrentModelRequest(mounted, pendingCatalog.generation);
35980
36196
  if (composerState.agent === agent && (status !== "ready" || !loadingCurrentCatalog || refresh && force) && shouldReloadExternalCatalogAfterAvailabilityRefresh(
35981
36197
  previousStatus,
35982
36198
  status,
@@ -35992,9 +36208,9 @@ ${accounts_default}`;
35992
36208
  );
35993
36209
  if (generation !== state.requestGeneration || disposed) return;
35994
36210
  if (retryableHarnessAvailabilityAgents(state.availability, state.errors).length === 0) {
35995
- resetHarnessAvailabilityRetry(hostId);
36211
+ resetHarnessAvailabilityRetry(hostId2);
35996
36212
  } else {
35997
- scheduleHarnessAvailabilityRetry(hostId);
36213
+ scheduleHarnessAvailabilityRetry(hostId2);
35998
36214
  }
35999
36215
  })();
36000
36216
  const request = { client, promise: promise2 };
@@ -36011,12 +36227,12 @@ ${accounts_default}`;
36011
36227
  }
36012
36228
  const reloadMountedOwnershipForHost = () => {
36013
36229
  for (const mounted of mountedByComposer.values()) {
36014
- const hostId = activeModelHostId(mounted.composer);
36015
- if (!hostId || mounted.hostId === hostId) continue;
36230
+ const hostId2 = activeModelHostId(mounted.composer);
36231
+ if (!hostId2 || mounted.hostId === hostId2) continue;
36016
36232
  if (!threadIdFromComposerModelTarget(mounted.modelTarget)) {
36017
36233
  controller.clearPendingSubmission(mounted.composer);
36018
36234
  controller.beginModelRequest(mounted.composer);
36019
- mounted.hostId = hostId;
36235
+ mounted.hostId = hostId2;
36020
36236
  mounted.modelView = { status: "idle" };
36021
36237
  mounted.permissionModeView = { status: "idle" };
36022
36238
  mounted.usage = null;
@@ -36029,13 +36245,13 @@ ${accounts_default}`;
36029
36245
  void loadExternalCatalog(mounted);
36030
36246
  continue;
36031
36247
  }
36032
- const target = controllerTarget(mounted.modelTarget, hostId);
36248
+ const target = controllerTarget(mounted.modelTarget, hostId2);
36033
36249
  if (controller.rebindConversation(mounted.composer, target) === null) {
36034
36250
  mounted.ownershipStatus = "error";
36035
36251
  renderMounted(mounted);
36036
36252
  continue;
36037
36253
  }
36038
- mounted.hostId = hostId;
36254
+ mounted.hostId = hostId2;
36039
36255
  mounted.composerId = controller.get(mounted.composer).composerId;
36040
36256
  mounted.modelView = { status: "idle" };
36041
36257
  mounted.permissionModeView = { status: "idle" };
@@ -36056,8 +36272,8 @@ ${accounts_default}`;
36056
36272
  sidebarAgentIcons.refresh();
36057
36273
  };
36058
36274
  function reconcileHarnessAvailabilityHost() {
36059
- for (const hostId2 of modelControl?.knownHostIds?.() ?? []) {
36060
- hostHarnessAvailabilityState(hostId2);
36275
+ for (const hostId3 of modelControl?.knownHostIds?.() ?? []) {
36276
+ hostHarnessAvailabilityState(hostId3);
36061
36277
  }
36062
36278
  reloadMountedOwnershipForHost();
36063
36279
  for (const target of new Set([...mountedByComposer.values()].map((m) => m.hostId))) {
@@ -36078,14 +36294,14 @@ ${accounts_default}`;
36078
36294
  } catch {
36079
36295
  }
36080
36296
  }
36081
- const hostId = activeModelHostId();
36082
- if (!hostId || hostId === activeAvailabilityHostId && [...mountedByComposer.values()].every((mounted) => mounted.hostId !== null))
36297
+ const hostId2 = activeModelHostId();
36298
+ if (!hostId2 || hostId2 === activeAvailabilityHostId && [...mountedByComposer.values()].every((mounted) => mounted.hostId !== null))
36083
36299
  return;
36084
- activeAvailabilityHostId = hostId;
36085
- hostHarnessAvailabilityState(hostId);
36300
+ activeAvailabilityHostId = hostId2;
36301
+ hostHarnessAvailabilityState(hostId2);
36086
36302
  publishConnectionStatus();
36087
36303
  for (const mounted of mountedByComposer.values()) renderMounted(mounted);
36088
- void refreshHarnessAvailabilityForHost(hostId);
36304
+ void refreshHarnessAvailabilityForHost(hostId2);
36089
36305
  }
36090
36306
  const refreshHarnessAvailability = async (refresh = false) => {
36091
36307
  reconcileHarnessAvailabilityHost();
@@ -36094,22 +36310,22 @@ ${accounts_default}`;
36094
36310
  if (mounted.hostId) hostIds.add(mounted.hostId);
36095
36311
  }
36096
36312
  await Promise.all(
36097
- [...hostIds].map((hostId) => refreshHarnessAvailabilityForHost(hostId, refresh))
36313
+ [...hostIds].map((hostId2) => refreshHarnessAvailabilityForHost(hostId2, refresh))
36098
36314
  );
36099
36315
  };
36100
36316
  connectionDiagnostics = {
36101
36317
  snapshot() {
36102
36318
  const hostIds = [
36103
36319
  "local",
36104
- ...[...harnessAvailabilityByHost.keys()].filter((hostId) => hostId !== "local").sort()
36320
+ ...[...harnessAvailabilityByHost.keys()].filter((hostId2) => hostId2 !== "local").sort()
36105
36321
  ];
36106
36322
  return {
36107
36323
  adapter: { ...adapterStatus },
36108
- hosts: hostIds.map((hostId) => {
36109
- const state = hostHarnessAvailabilityState(hostId);
36324
+ hosts: hostIds.map((hostId2) => {
36325
+ const state = hostHarnessAvailabilityState(hostId2);
36110
36326
  return {
36111
- hostId,
36112
- active: hostId === activeAvailabilityHostId,
36327
+ hostId: hostId2,
36328
+ active: hostId2 === activeAvailabilityHostId,
36113
36329
  agents: externalAgents.map((agent) => ({
36114
36330
  agent,
36115
36331
  availability: state.availability[agent] ?? "checking",
@@ -36120,10 +36336,10 @@ ${accounts_default}`;
36120
36336
  })
36121
36337
  };
36122
36338
  },
36123
- refresh(hostId) {
36124
- if (hostId !== void 0) {
36339
+ refresh(hostId2) {
36340
+ if (hostId2 !== void 0) {
36125
36341
  return refreshConnectionHosts(
36126
- [hostId],
36342
+ [hostId2],
36127
36343
  (target) => refreshHarnessAvailabilityForHost(target, true, false, true),
36128
36344
  (target) => hostHarnessAvailabilityState(target).request?.promise
36129
36345
  );
@@ -36134,25 +36350,25 @@ ${accounts_default}`;
36134
36350
  (target) => refreshHarnessAvailabilityForHost(target, true, false, true)
36135
36351
  );
36136
36352
  },
36137
- async installation(hostId, agent, action) {
36138
- const client = modelClientForHost(hostId);
36353
+ async installation(hostId2, agent, action) {
36354
+ const client = modelClientForHost(hostId2);
36139
36355
  if (!client?.installation)
36140
36356
  throw new Error("Harness version management is unavailable on this Host");
36141
36357
  return client.installation({ harnessId: externalHarnessIds[agent], action });
36142
36358
  },
36143
- async getLaunchSettings(hostId, agent) {
36144
- const client = hostId === "local" ? modelClientForHost(hostId) : null;
36359
+ async getLaunchSettings(hostId2, agent) {
36360
+ const client = hostId2 === "local" ? modelClientForHost(hostId2) : null;
36145
36361
  if (!client?.getHarnessLaunchSettings) throw new Error("Launch settings are unavailable");
36146
36362
  return client.getHarnessLaunchSettings({ harnessId: externalHarnessIds[agent] });
36147
36363
  },
36148
- async setLaunchSettings(hostId, agent, path) {
36149
- const client = hostId === "local" ? modelClientForHost(hostId) : null;
36364
+ async setLaunchSettings(hostId2, agent, path) {
36365
+ const client = hostId2 === "local" ? modelClientForHost(hostId2) : null;
36150
36366
  if (!client?.setHarnessLaunchSettings) throw new Error("Launch settings are unavailable");
36151
36367
  return client.setHarnessLaunchSettings({ harnessId: externalHarnessIds[agent], path });
36152
36368
  },
36153
- async openWebUi(hostId, agent) {
36154
- const state = hostHarnessAvailabilityState(hostId);
36155
- const client = hostId === "local" ? modelClientForHost(hostId) : null;
36369
+ async openWebUi(hostId2, agent) {
36370
+ const state = hostHarnessAvailabilityState(hostId2);
36371
+ const client = hostId2 === "local" ? modelClientForHost(hostId2) : null;
36156
36372
  if (state.availability[agent] !== "ready" || state.webUi[agent] !== true || !client?.openHarnessWebUi) {
36157
36373
  throw new Error("Harness Web UI is unavailable");
36158
36374
  }
@@ -36161,7 +36377,7 @@ ${accounts_default}`;
36161
36377
  } catch (error51) {
36162
36378
  state.webUi = { ...state.webUi, [agent]: false };
36163
36379
  publishConnectionStatus();
36164
- void refreshHarnessAvailabilityForHost(hostId, true, false, true).catch(() => void 0);
36380
+ void refreshHarnessAvailabilityForHost(hostId2, true, false, true).catch(() => void 0);
36165
36381
  throw error51;
36166
36382
  }
36167
36383
  },
@@ -36178,12 +36394,12 @@ ${accounts_default}`;
36178
36394
  const sendButton = sendButtonWithin(composer) ?? allButtons.at(-1) ?? null;
36179
36395
  if (!sendButton) return;
36180
36396
  const modelTarget = findComposerModelTarget(composer);
36181
- const hostId = activeModelHostId(composer);
36397
+ const hostId2 = activeModelHostId(composer);
36182
36398
  const editor = composer.querySelector(EDITOR_SELECTOR);
36183
36399
  if (!editor) return;
36184
36400
  const state = controller.mount(
36185
36401
  composer,
36186
- controllerTarget(modelTarget, hostId),
36402
+ controllerTarget(modelTarget, hostId2),
36187
36403
  modelTarget?.[0] === "default" ? readNewThreadAgentPreference(enabledAgentSet) : void 0
36188
36404
  );
36189
36405
  const inherited = pendingReplacements.get(composer)?.source;
@@ -36233,7 +36449,7 @@ ${accounts_default}`;
36233
36449
  threadConfiguration: inherited?.threadConfiguration,
36234
36450
  usage: inherited?.usage ?? null,
36235
36451
  accountCredits: inherited?.accountCredits ?? null,
36236
- hostId: inherited?.hostId ?? hostId,
36452
+ hostId: inherited?.hostId ?? hostId2,
36237
36453
  usageRequestGeneration: 0,
36238
36454
  commandRequestGeneration: 0
36239
36455
  };
@@ -36459,8 +36675,8 @@ ${accounts_default}`;
36459
36675
  });
36460
36676
  const onHostRouteChange = () => {
36461
36677
  for (const mounted of mountedByComposer.values()) {
36462
- const hostId = activeModelHostId(mounted.composer);
36463
- if (hostId && mounted.hostId === hostId && !threadIdFromComposerModelTarget(mounted.modelTarget) && controller.get(mounted.composer).agent !== "codex" && !controller.isSwitching(mounted.composer) && isExternalConfigurationStable(mounted.modelView, mounted.permissionModeView)) {
36678
+ const hostId2 = activeModelHostId(mounted.composer);
36679
+ if (hostId2 && mounted.hostId === hostId2 && !threadIdFromComposerModelTarget(mounted.modelTarget) && controller.get(mounted.composer).agent !== "codex" && !controller.isSwitching(mounted.composer) && isExternalConfigurationStable(mounted.modelView, mounted.permissionModeView)) {
36464
36680
  applyComposerAgent(mounted.composer);
36465
36681
  }
36466
36682
  }
@@ -36523,11 +36739,11 @@ ${accounts_default}`;
36523
36739
  const onDraftWorkspace = (event) => {
36524
36740
  const detail = event.detail;
36525
36741
  if (typeof detail !== "object" || detail === null) return;
36526
- const { hostId, cwd } = detail;
36527
- if (typeof hostId !== "string" || typeof cwd !== "string" || cwd.length === 0) return;
36528
- draftWorkspaces.set(hostId, cwd);
36742
+ const { hostId: hostId2, cwd } = detail;
36743
+ if (typeof hostId2 !== "string" || typeof cwd !== "string" || cwd.length === 0) return;
36744
+ draftWorkspaces.set(hostId2, cwd);
36529
36745
  for (const mounted of mountedByComposer.values()) {
36530
- if (!threadIdFromComposerModelTarget(mounted.modelTarget) && activeModelHostId(mounted.composer) === hostId && controller.get(mounted.composer).agent !== "codex") {
36746
+ if (!threadIdFromComposerModelTarget(mounted.modelTarget) && activeModelHostId(mounted.composer) === hostId2 && controller.get(mounted.composer).agent !== "codex") {
36531
36747
  void refreshCommands(mounted, { keepCurrent: true });
36532
36748
  }
36533
36749
  }
@@ -36583,6 +36799,7 @@ ${accounts_default}`;
36583
36799
  (mounted) => mounted.composer.isConnected && mounted.control.root.isConnected
36584
36800
  );
36585
36801
  const api = {
36802
+ remoteConnections: (request) => handleRemoteConnectionsRequest(remoteConnections, request),
36586
36803
  currentThreadId() {
36587
36804
  const mounted = connectedComposers();
36588
36805
  return mounted.length === 1 && mounted[0] ? threadIdFromComposerModelTarget(mounted[0].modelTarget) ?? null : null;
@@ -36717,9 +36934,9 @@ ${accounts_default}`;
36717
36934
  }
36718
36935
 
36719
36936
  // src/install-renderer-binding.ts
36720
- function installRendererBinding(enabledAgents = DEFAULT_RENDERER_AGENTS, defaultAgent = "codex") {
36937
+ function installRendererBinding(enabledAgents = DEFAULT_RENDERER_AGENTS) {
36721
36938
  window.__codexhostRendererBindingProbeV1?.dispose();
36722
- const binding = installRendererBindingProbe({ enabledAgents, defaultAgent });
36939
+ const binding = installRendererBindingProbe({ enabledAgents });
36723
36940
  try {
36724
36941
  const adapter = installCurrentRendererAdapter();
36725
36942
  binding.setAdapter(adapter.status, adapter.dispose, adapter.applyAgent, adapter.modelControl);
@@ -36739,10 +36956,8 @@ ${accounts_default}`;
36739
36956
  }
36740
36957
 
36741
36958
  // src/production-entry.ts
36742
- var configuration = window.__codexhostProductionConfigV1;
36743
- delete window.__codexhostProductionConfigV1;
36744
36959
  var install = () => {
36745
- installRendererBinding(DEFAULT_RENDERER_AGENTS, configuration?.defaultAgent ?? "codex");
36960
+ installRendererBinding(DEFAULT_RENDERER_AGENTS);
36746
36961
  };
36747
36962
  if (document.documentElement && document.body) {
36748
36963
  install();