@codexhost/cli-win32-arm64 0.1.2 → 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -7,7 +7,7 @@ Run Pi and Claude Code as first-class external harnesses inside Codex Desktop.
7
7
  ## Install
8
8
 
9
9
  ```bash
10
- npm install -g @codexhost/cli@0.1.2
10
+ npm install -g @codexhost/cli@0.1.3
11
11
  ```
12
12
 
13
13
  Do not install this package directly. npm selects it through the optional dependencies of `@codexhost/cli`.
@@ -1 +1 @@
1
- {"schemaVersion":1,"version":"0.1.2","distribution":"npm","target":"windows-arm64"}
1
+ {"schemaVersion":1,"version":"0.1.3","distribution":"npm","target":"windows-arm64"}
@@ -1344,12 +1344,15 @@ function isTransientElectronInstallError(error) {
1344
1344
  }
1345
1345
  return false;
1346
1346
  }
1347
+ function shouldRetryInstallError(error) {
1348
+ return !(error instanceof RendererCompatibilityError) || isTransientElectronInstallError(error);
1349
+ }
1347
1350
  async function installProductionSession(options, dependencies) {
1348
1351
  for (let attempt = 1; attempt <= TRANSIENT_INSTALL_ATTEMPTS; attempt += 1) {
1349
1352
  try {
1350
1353
  return await dependencies.install(options);
1351
1354
  } catch (error) {
1352
- if (attempt === TRANSIENT_INSTALL_ATTEMPTS || !isTransientElectronInstallError(error)) {
1355
+ if (attempt === TRANSIENT_INSTALL_ATTEMPTS || !shouldRetryInstallError(error)) {
1353
1356
  throw error;
1354
1357
  }
1355
1358
  await dependencies.sleep(TRANSIENT_INSTALL_RETRY_MS);
@@ -52789,13 +52789,25 @@ async function acquireUpdateOperationLock(stateDirectory) {
52789
52789
  }
52790
52790
  };
52791
52791
  }
52792
+ function processIsAlive(processId) {
52793
+ if (!Number.isSafeInteger(processId) || processId <= 0)
52794
+ return false;
52795
+ try {
52796
+ process.kill(processId, 0);
52797
+ return true;
52798
+ } catch (error52) {
52799
+ return error52.code === "EPERM";
52800
+ }
52801
+ }
52792
52802
  async function recoverUpdateOperationLock(stateDirectory) {
52793
52803
  const lockPath = path9.join(stateDirectory, LOCK_FILE);
52794
52804
  if (!await regularFile(lockPath))
52795
52805
  return;
52806
+ let ownerPid;
52796
52807
  let statusPath;
52797
52808
  try {
52798
52809
  const value = JSON.parse(await readFile3(lockPath, "utf8"));
52810
+ ownerPid = value.ownerPid;
52799
52811
  statusPath = value.statusPath;
52800
52812
  } catch {
52801
52813
  return;
@@ -52804,8 +52816,9 @@ async function recoverUpdateOperationLock(stateDirectory) {
52804
52816
  return;
52805
52817
  try {
52806
52818
  const status = parseUpdateStatus(JSON.parse(await readFile3(statusPath, "utf8")));
52807
- if (TERMINAL_PHASES.has(status.phase))
52819
+ if (TERMINAL_PHASES.has(status.phase) || typeof ownerPid !== "number" || !processIsAlive(ownerPid)) {
52808
52820
  await rm3(lockPath, { force: true });
52821
+ }
52809
52822
  } catch {
52810
52823
  }
52811
52824
  }
@@ -53149,6 +53162,8 @@ function createBackgroundUpdateManager(dependencies = {}) {
53149
53162
  // packages/host-runtime/src/update-coordinator.ts
53150
53163
  var ERROR_MAX_LENGTH = 500;
53151
53164
  var CONTROLLER_TIMEOUT_MS = 5e3;
53165
+ var UPDATER_READY_TIMEOUT_MS = 1e4;
53166
+ var UPDATER_READY_POLL_MS = 20;
53152
53167
  async function startCompatibilityUpdate(coordinator) {
53153
53168
  try {
53154
53169
  const check2 = await coordinator.check();
@@ -53167,6 +53182,30 @@ function boundedError(error52) {
53167
53182
  const message3 = error52 instanceof Error ? error52.message : String(error52);
53168
53183
  return message3.slice(0, ERROR_MAX_LENGTH) || "Update operation failed";
53169
53184
  }
53185
+ function delay4(milliseconds) {
53186
+ return new Promise((resolve2) => setTimeout(resolve2, milliseconds));
53187
+ }
53188
+ async function waitForUpdaterReady(manager, statusPath) {
53189
+ const deadline = Date.now() + UPDATER_READY_TIMEOUT_MS;
53190
+ while (Date.now() < deadline) {
53191
+ const status = await manager.readStatus(statusPath);
53192
+ switch (status?.phase) {
53193
+ case "waiting-for-exit":
53194
+ case "installing":
53195
+ case "restarting":
53196
+ case "succeeded":
53197
+ return;
53198
+ case "failed":
53199
+ throw new Error(status.error ?? "Background Updater failed before Desktop shutdown");
53200
+ case "prepared":
53201
+ break;
53202
+ default:
53203
+ throw new Error("Background Updater reported an unexpected startup phase");
53204
+ }
53205
+ await delay4(UPDATER_READY_POLL_MS);
53206
+ }
53207
+ throw new Error("Background Updater did not become ready before Desktop shutdown");
53208
+ }
53170
53209
  function publicStatus(status) {
53171
53210
  return {
53172
53211
  version: status.version,
@@ -53207,7 +53246,8 @@ function requestControllerShutdown(controller) {
53207
53246
  });
53208
53247
  }
53209
53248
  function createHostUpdateCoordinator(options) {
53210
- const manager = options.manager ?? createBackgroundUpdateManager(options.platform ? { platform: options.platform } : {});
53249
+ const platform = options.platform ?? process.platform;
53250
+ const manager = options.manager ?? createBackgroundUpdateManager({ platform });
53211
53251
  const contextPromise = resolveInstalledUpdateContext({
53212
53252
  hostRuntimePath: options.hostRuntimePath,
53213
53253
  ...options.environment ? { environment: options.environment } : {},
@@ -53350,7 +53390,8 @@ function createHostUpdateCoordinator(options) {
53350
53390
  onPrepared
53351
53391
  });
53352
53392
  }
53353
- manager.start(prepared2);
53393
+ if (platform !== "darwin") manager.start(prepared2);
53394
+ await waitForUpdaterReady(manager, prepared2.statusPath);
53354
53395
  shutdownPending = context.controller;
53355
53396
  scheduleShutdown();
53356
53397
  } catch (error52) {
@@ -18130,7 +18130,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
18130
18130
  updateSucceeded: "Update installed successfully.",
18131
18131
  updateFailed: "Update failed.",
18132
18132
  updateRetry: "Retry",
18133
- updateViewRelease: "View release notes",
18133
+ updateDownloadFromReleases: "Download from GitHub Releases",
18134
18134
  pageLabels: Object.freeze({
18135
18135
  connections: "Connections",
18136
18136
  "model-pool": "Model Pool",
@@ -18175,7 +18175,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
18175
18175
  updateSucceeded: "\u66F4\u65B0\u5B89\u88C5\u6210\u529F\u3002",
18176
18176
  updateFailed: "\u66F4\u65B0\u5931\u8D25\u3002",
18177
18177
  updateRetry: "\u91CD\u8BD5",
18178
- updateViewRelease: "\u67E5\u770B\u66F4\u65B0\u65E5\u5FD7",
18178
+ updateDownloadFromReleases: "\u524D\u5F80 GitHub Releases \u4E0B\u8F7D",
18179
18179
  pageLabels: Object.freeze({
18180
18180
  connections: "\u8FDE\u63A5",
18181
18181
  "model-pool": "\u6A21\u578B\u6C60",
@@ -18521,6 +18521,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
18521
18521
  }
18522
18522
 
18523
18523
  // src/settings/pages.ts
18524
+ var CODEXHOST_RELEASES_LATEST_URL = "https://github.com/BytePioneer-AI/codex-host/releases/latest";
18524
18525
  var DEFAULT_RENDERER_SETTINGS_PAGE_IDS = [
18525
18526
  "connections",
18526
18527
  "model-pool",
@@ -18625,7 +18626,19 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
18625
18626
  const panel = document2.createElement("section");
18626
18627
  panel.className = "settings-update-panel";
18627
18628
  panel.setAttribute("aria-live", "polite");
18628
- context.content.append(heading, metadata, panel);
18629
+ const actions = document2.createElement("div");
18630
+ actions.className = "settings-update-actions";
18631
+ const releaseLink = document2.createElement("a");
18632
+ releaseLink.className = "settings-update-link";
18633
+ releaseLink.href = CODEXHOST_RELEASES_LATEST_URL;
18634
+ releaseLink.target = "_blank";
18635
+ releaseLink.rel = "noopener noreferrer";
18636
+ releaseLink.append(
18637
+ messages.updateDownloadFromReleases,
18638
+ createRendererSettingsIcon("external-link", 14)
18639
+ );
18640
+ actions.append(releaseLink);
18641
+ context.content.append(heading, metadata, panel, actions);
18629
18642
  let pollTimer;
18630
18643
  let pollAttempts = 0;
18631
18644
  let pending = false;
@@ -18730,6 +18743,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
18730
18743
  const renderCheck = (result, client) => {
18731
18744
  currentVersionValue.textContent = `v${result.currentVersion}`;
18732
18745
  installationValue.textContent = installationLabel(result.installation, messages);
18746
+ if (result.releaseNotesUrl) releaseLink.href = result.releaseNotesUrl;
18733
18747
  const operationMessage = statusMessage(result.status, messages);
18734
18748
  if (isPendingStatus(result.status)) {
18735
18749
  renderPendingStatus(result.status, operationMessage ?? messages.updatePreparing);
@@ -18765,15 +18779,6 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
18765
18779
  update.addEventListener("click", () => start(client));
18766
18780
  panel.append(update);
18767
18781
  }
18768
- if (result.releaseNotesUrl) {
18769
- const notes = document2.createElement("a");
18770
- notes.className = "settings-update-link";
18771
- notes.href = result.releaseNotesUrl;
18772
- notes.target = "_blank";
18773
- notes.rel = "noopener noreferrer";
18774
- notes.append(messages.updateViewRelease, createRendererSettingsIcon("external-link", 14));
18775
- panel.append(notes);
18776
- }
18777
18782
  if (result.error) {
18778
18783
  const error51 = document2.createElement("p");
18779
18784
  error51.className = "settings-update-error";
@@ -18829,7 +18834,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
18829
18834
  }
18830
18835
 
18831
18836
  // src/settings/shell.css
18832
- var shell_default = ':host {\n --settings-bg: #181818;\n --settings-sidebar: #1c1c1c;\n --settings-panel: transparent;\n --settings-text: #f5f5f5;\n --settings-muted: #a1a1a1;\n --settings-border: rgb(255 255 255 / 10%);\n --settings-divider: rgb(255 255 255 / 10%);\n --settings-hover: rgb(255 255 255 / 6%);\n --settings-active: rgb(51 156 255 / 12%);\n --settings-focus: #339cff;\n color: var(--settings-text);\n color-scheme: dark;\n font:\n 14px/1.5 system-ui,\n -apple-system,\n BlinkMacSystemFont,\n "Segoe UI",\n sans-serif;\n letter-spacing: 0;\n}\n\n*,\n*::before,\n*::after {\n box-sizing: border-box;\n letter-spacing: 0;\n}\n\nbutton,\ninput,\nselect {\n font: inherit;\n}\n\nbutton {\n color: inherit;\n}\n\n[hidden] {\n display: none !important;\n}\n\n.codexhost-settings-dialog {\n width: min(1120px, calc(100vw - 32px));\n height: min(780px, calc(100vh - 32px));\n max-width: none;\n max-height: none;\n margin: auto;\n padding: 0;\n overflow: hidden;\n color: var(--settings-text);\n background: var(--settings-bg);\n border: 1px solid var(--settings-border);\n border-radius: 12px;\n box-shadow: 0 24px 64px rgb(0 0 0 / 38%);\n}\n\n.codexhost-settings-dialog::backdrop {\n background: rgb(0 0 0 / 52%);\n}\n\n.settings-frame,\n.settings-layout {\n width: 100%;\n height: 100%;\n min-width: 0;\n min-height: 0;\n}\n\n.settings-frame {\n display: flex;\n flex-direction: column;\n}\n\n.settings-layout {\n flex: 1;\n display: grid;\n grid-template-columns: 240px minmax(0, 1fr);\n background: var(--settings-bg);\n}\n\n.settings-sidebar {\n display: flex;\n min-width: 0;\n min-height: 0;\n flex-direction: column;\n overflow: hidden;\n background: var(--settings-sidebar);\n border-right: 1px solid var(--settings-border);\n padding-top: 28px;\n}\n\n.settings-header {\n display: flex;\n align-items: center;\n min-width: 0;\n height: 64px;\n flex: none;\n padding: 0 16px;\n border-bottom: 1px solid var(--settings-border);\n}\n\n.settings-brand {\n display: flex;\n align-items: center;\n min-width: 0;\n gap: 8px;\n}\n\n.settings-brand__mark {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 36px;\n height: 36px;\n flex: none;\n color: var(--settings-text);\n}\n\n.settings-brand__mark .codexhost-settings-icon {\n width: 32px;\n height: 32px;\n object-fit: contain;\n}\n\n.settings-brand__copy {\n display: flex;\n min-width: 0;\n align-items: baseline;\n gap: 0;\n line-height: 20px;\n}\n\n.settings-brand__name {\n overflow: hidden;\n color: var(--settings-text);\n font-size: 14px;\n font-weight: 500;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.settings-brand__title {\n margin-left: 14px;\n padding-left: 14px;\n color: var(--settings-muted);\n font-size: 14px;\n font-weight: 400;\n border-left: 1px solid var(--settings-border);\n}\n\n.settings-nav {\n display: flex;\n min-width: 0;\n min-height: 0;\n flex: 1;\n flex-direction: column;\n gap: 4px;\n padding: 0 12px 16px;\n overflow-y: auto;\n}\n\n.settings-nav-button {\n display: grid;\n grid-template-columns: 16px minmax(0, 1fr);\n align-items: center;\n width: 100%;\n position: relative;\n min-height: 40px;\n flex: none;\n gap: 12px;\n padding: 8px 12px;\n color: var(--settings-text);\n font-size: 14px;\n line-height: 21px;\n text-align: left;\n background: transparent;\n border: 0;\n border-radius: 10px;\n cursor: pointer;\n}\n\n.settings-nav-button .codexhost-settings-icon {\n width: 18px;\n height: 18px;\n opacity: 0.9;\n}\n\n.settings-nav-button:hover {\n background: var(--settings-hover);\n}\n\n.settings-nav-button[aria-current="page"] {\n background: var(--settings-active);\n color: var(--settings-focus);\n}\n\n.settings-nav-button[aria-current="page"]::before {\n position: absolute;\n left: 0;\n width: 3px;\n height: 22px;\n content: "";\n background: var(--settings-focus);\n border-radius: 0 3px 3px 0;\n}\n\n.settings-nav-button span {\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.settings-icon-button {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 28px;\n height: 28px;\n flex: none;\n padding: 0;\n color: var(--settings-muted);\n background: transparent;\n border: 0;\n border-radius: 8px;\n cursor: pointer;\n}\n\n.settings-icon-button:hover {\n color: var(--settings-text);\n background: var(--settings-hover);\n}\n\n.settings-icon-button:focus-visible,\n.settings-nav-button:focus-visible {\n outline: 2px solid var(--settings-focus);\n outline-offset: 1px;\n}\n\n.settings-page {\n display: block;\n position: relative;\n min-width: 0;\n min-height: 0;\n overflow-y: auto;\n background: var(--settings-bg);\n scrollbar-gutter: stable;\n}\n\n.settings-page__content {\n width: min(930px, calc(100% - 80px));\n margin-inline: auto;\n}\n\n.settings-page__content {\n min-width: 0;\n padding: 44px 0 56px;\n}\n\n.settings-section-label {\n min-height: auto;\n padding: 0 0 28px;\n color: var(--settings-text);\n font-size: 24px;\n font-weight: 600;\n line-height: 30px;\n}\n\n.settings-status-list,\n.settings-empty {\n overflow: hidden;\n background: var(--settings-panel);\n}\n\n.settings-status-row {\n display: grid;\n grid-template-columns: minmax(170px, 1fr) auto minmax(280px, 1.45fr);\n position: relative;\n align-items: center;\n min-height: 88px;\n gap: 28px;\n padding: 16px 0;\n}\n\n.settings-status-row:not(:last-child)::after {\n content: "";\n position: absolute;\n right: 0;\n bottom: 0;\n left: 0;\n height: 1px;\n background: var(--settings-divider);\n}\n\n.settings-status-row__identity {\n display: inline-flex;\n align-items: center;\n min-width: 0;\n color: var(--settings-text);\n gap: 14px;\n font-size: 15px;\n font-weight: 500;\n line-height: 22px;\n}\n\n.settings-status-row__icon {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 44px;\n height: 44px;\n flex: none;\n color: var(--settings-muted);\n background: rgb(255 255 255 / 7%);\n border-radius: 50%;\n}\n\n.settings-status-badge {\n flex: none;\n padding: 5px 12px;\n color: var(--settings-muted);\n font-size: 13px;\n font-weight: 500;\n line-height: 18px;\n background: rgb(255 255 255 / 9%);\n border: 1px solid rgb(255 255 255 / 6%);\n border-radius: 6px;\n}\n\n.settings-status-row__detail {\n min-width: 0;\n color: var(--settings-muted);\n font-size: 13px;\n line-height: 20px;\n}\n\n.settings-empty {\n display: flex;\n align-items: center;\n min-height: 72px;\n padding: 12px 16px;\n}\n\n.settings-empty > div {\n display: grid;\n min-width: 0;\n gap: 2px;\n}\n\n.settings-empty strong {\n color: var(--settings-text);\n font-size: 13px;\n font-weight: 500;\n line-height: 19px;\n}\n\n.settings-empty span {\n color: var(--settings-muted);\n font-size: 13px;\n line-height: 19px;\n}\n\n.settings-page-error {\n padding: 16px;\n color: var(--settings-text);\n font-size: 13px;\n background: var(--settings-panel);\n border: 1px solid var(--settings-border);\n border-radius: 20px;\n}\n\n.settings-update-metadata {\n display: grid;\n grid-template-columns: repeat(2, minmax(0, 1fr));\n gap: 24px;\n margin-bottom: 24px;\n padding: 0 4px 20px;\n border-bottom: 1px solid var(--settings-divider);\n}\n\n.settings-update-metadata__item {\n display: grid;\n min-width: 0;\n gap: 4px;\n}\n\n.settings-update-metadata__item span {\n color: var(--settings-muted);\n font-size: 12px;\n line-height: 18px;\n}\n\n.settings-update-metadata__item strong {\n min-width: 0;\n overflow-wrap: anywhere;\n color: var(--settings-text);\n font-size: 15px;\n font-weight: 500;\n line-height: 22px;\n}\n\n.settings-update-panel {\n display: grid;\n gap: 16px;\n min-height: 128px;\n padding: 20px;\n color: var(--settings-text);\n background: var(--settings-panel);\n border: 1px solid var(--settings-border);\n border-radius: 8px;\n}\n\n.settings-update-panel > strong,\n.settings-update-panel > span,\n.settings-update-summary,\n.settings-update-error {\n margin: 0;\n overflow-wrap: anywhere;\n font-size: 13px;\n line-height: 20px;\n}\n\n.settings-update-panel > span,\n.settings-update-summary {\n color: var(--settings-muted);\n}\n\n.settings-update-error {\n color: #ef4444;\n}\n\n.settings-update-progress {\n width: 100%;\n height: 8px;\n accent-color: #238be8;\n}\n\n.settings-update-progress-detail {\n color: var(--settings-muted);\n font-size: 12px;\n line-height: 18px;\n}\n\n.settings-update-notes {\n max-height: 240px;\n padding: 14px;\n overflow: auto;\n color: var(--settings-muted);\n font-size: 13px;\n line-height: 20px;\n white-space: pre-wrap;\n overflow-wrap: anywhere;\n background: rgb(255 255 255 / 4%);\n border: 1px solid var(--settings-divider);\n border-radius: 6px;\n}\n\n.settings-update-version-row {\n display: grid;\n grid-template-columns: minmax(0, 1fr) auto;\n align-items: center;\n gap: 20px;\n min-height: 32px;\n color: var(--settings-muted);\n font-size: 13px;\n}\n\n.settings-update-version-row strong {\n color: var(--settings-text);\n font-size: 15px;\n}\n\n.settings-command-button,\n.settings-update-link {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: fit-content;\n min-height: 36px;\n gap: 8px;\n padding: 8px 12px;\n color: white;\n font: inherit;\n font-size: 13px;\n text-decoration: none;\n background: #1677d2;\n border: 1px solid #238be8;\n border-radius: 6px;\n cursor: pointer;\n}\n\n.settings-command-button--secondary,\n.settings-update-link {\n color: var(--settings-text);\n background: transparent;\n border-color: var(--settings-border);\n}\n\n.settings-command-button:hover,\n.settings-update-link:hover {\n filter: brightness(1.08);\n}\n\n.settings-command-button:focus-visible,\n.settings-update-link:focus-visible {\n outline: 2px solid var(--settings-focus);\n outline-offset: 2px;\n}\n\n.codexhost-settings-icon {\n display: block;\n flex: none;\n stroke: currentColor;\n}\n\n@media (max-width: 720px) {\n .codexhost-settings-dialog {\n width: calc(100vw - 16px);\n height: calc(100vh - 16px);\n border-radius: 10px;\n }\n\n .settings-layout {\n grid-template-columns: minmax(0, 1fr);\n grid-template-rows: auto minmax(0, 1fr);\n }\n\n .settings-sidebar {\n border-right: 0;\n border-bottom: 1px solid var(--settings-border);\n }\n\n .settings-header {\n height: 56px;\n padding-inline: 14px;\n }\n\n .settings-sidebar {\n padding-top: 20px;\n }\n\n .settings-nav {\n flex: none;\n flex-direction: row;\n gap: 4px;\n padding: 7px 8px 8px;\n overflow-x: auto;\n overflow-y: hidden;\n }\n\n .settings-nav-button {\n width: auto;\n min-width: max-content;\n min-height: 34px;\n grid-template-columns: 16px auto;\n border-radius: 10px;\n }\n\n .settings-page__content {\n width: calc(100% - 40px);\n }\n\n .settings-page__content {\n padding-top: 32px;\n padding-bottom: 32px;\n }\n\n .settings-section-label {\n padding-bottom: 20px;\n font-size: 20px;\n line-height: 26px;\n }\n\n .settings-status-row {\n grid-template-columns: minmax(0, 1fr) auto;\n gap: 16px;\n }\n\n .settings-status-row__detail {\n grid-column: 1 / -1;\n margin: -8px 0 0 58px;\n }\n}\n\n@media (forced-colors: active) {\n :host,\n :host([data-theme="dark"]) {\n --settings-bg: Canvas;\n --settings-sidebar: Canvas;\n --settings-panel: Canvas;\n --settings-text: CanvasText;\n --settings-muted: GrayText;\n --settings-border: ButtonBorder;\n --settings-divider: ButtonBorder;\n --settings-hover: Highlight;\n --settings-active: Highlight;\n --settings-focus: Highlight;\n }\n}\n\n@media (prefers-reduced-motion: reduce) {\n *,\n *::before,\n *::after {\n scroll-behavior: auto !important;\n }\n}\n';
18837
+ var shell_default = ':host {\n --settings-bg: #181818;\n --settings-sidebar: #1c1c1c;\n --settings-panel: transparent;\n --settings-text: #f5f5f5;\n --settings-muted: #a1a1a1;\n --settings-border: rgb(255 255 255 / 10%);\n --settings-divider: rgb(255 255 255 / 10%);\n --settings-hover: rgb(255 255 255 / 6%);\n --settings-active: rgb(51 156 255 / 12%);\n --settings-focus: #339cff;\n color: var(--settings-text);\n color-scheme: dark;\n font:\n 14px/1.5 system-ui,\n -apple-system,\n BlinkMacSystemFont,\n "Segoe UI",\n sans-serif;\n letter-spacing: 0;\n}\n\n*,\n*::before,\n*::after {\n box-sizing: border-box;\n letter-spacing: 0;\n}\n\nbutton,\ninput,\nselect {\n font: inherit;\n}\n\nbutton {\n color: inherit;\n}\n\n[hidden] {\n display: none !important;\n}\n\n.codexhost-settings-dialog {\n width: min(1120px, calc(100vw - 32px));\n height: min(780px, calc(100vh - 32px));\n max-width: none;\n max-height: none;\n margin: auto;\n padding: 0;\n overflow: hidden;\n color: var(--settings-text);\n background: var(--settings-bg);\n border: 1px solid var(--settings-border);\n border-radius: 12px;\n box-shadow: 0 24px 64px rgb(0 0 0 / 38%);\n}\n\n.codexhost-settings-dialog::backdrop {\n background: rgb(0 0 0 / 52%);\n}\n\n.settings-frame,\n.settings-layout {\n width: 100%;\n height: 100%;\n min-width: 0;\n min-height: 0;\n}\n\n.settings-frame {\n display: flex;\n flex-direction: column;\n}\n\n.settings-layout {\n flex: 1;\n display: grid;\n grid-template-columns: 240px minmax(0, 1fr);\n background: var(--settings-bg);\n}\n\n.settings-sidebar {\n display: flex;\n min-width: 0;\n min-height: 0;\n flex-direction: column;\n overflow: hidden;\n background: var(--settings-sidebar);\n border-right: 1px solid var(--settings-border);\n padding-top: 28px;\n}\n\n.settings-header {\n display: flex;\n align-items: center;\n min-width: 0;\n height: 64px;\n flex: none;\n padding: 0 16px;\n border-bottom: 1px solid var(--settings-border);\n}\n\n.settings-brand {\n display: flex;\n align-items: center;\n min-width: 0;\n gap: 8px;\n}\n\n.settings-brand__mark {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 36px;\n height: 36px;\n flex: none;\n color: var(--settings-text);\n}\n\n.settings-brand__mark .codexhost-settings-icon {\n width: 32px;\n height: 32px;\n object-fit: contain;\n}\n\n.settings-brand__copy {\n display: flex;\n min-width: 0;\n align-items: baseline;\n gap: 0;\n line-height: 20px;\n}\n\n.settings-brand__name {\n overflow: hidden;\n color: var(--settings-text);\n font-size: 14px;\n font-weight: 500;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.settings-brand__title {\n margin-left: 14px;\n padding-left: 14px;\n color: var(--settings-muted);\n font-size: 14px;\n font-weight: 400;\n border-left: 1px solid var(--settings-border);\n}\n\n.settings-nav {\n display: flex;\n min-width: 0;\n min-height: 0;\n flex: 1;\n flex-direction: column;\n gap: 4px;\n padding: 0 12px 16px;\n overflow-y: auto;\n}\n\n.settings-nav-button {\n display: grid;\n grid-template-columns: 16px minmax(0, 1fr);\n align-items: center;\n width: 100%;\n position: relative;\n min-height: 40px;\n flex: none;\n gap: 12px;\n padding: 8px 12px;\n color: var(--settings-text);\n font-size: 14px;\n line-height: 21px;\n text-align: left;\n background: transparent;\n border: 0;\n border-radius: 10px;\n cursor: pointer;\n}\n\n.settings-nav-button .codexhost-settings-icon {\n width: 18px;\n height: 18px;\n opacity: 0.9;\n}\n\n.settings-nav-button:hover {\n background: var(--settings-hover);\n}\n\n.settings-nav-button[aria-current="page"] {\n background: var(--settings-active);\n color: var(--settings-focus);\n}\n\n.settings-nav-button[aria-current="page"]::before {\n position: absolute;\n left: 0;\n width: 3px;\n height: 22px;\n content: "";\n background: var(--settings-focus);\n border-radius: 0 3px 3px 0;\n}\n\n.settings-nav-button span {\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.settings-icon-button {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 28px;\n height: 28px;\n flex: none;\n padding: 0;\n color: var(--settings-muted);\n background: transparent;\n border: 0;\n border-radius: 8px;\n cursor: pointer;\n}\n\n.settings-icon-button:hover {\n color: var(--settings-text);\n background: var(--settings-hover);\n}\n\n.settings-icon-button:focus-visible,\n.settings-nav-button:focus-visible {\n outline: 2px solid var(--settings-focus);\n outline-offset: 1px;\n}\n\n.settings-page {\n display: block;\n position: relative;\n min-width: 0;\n min-height: 0;\n overflow-y: auto;\n background: var(--settings-bg);\n scrollbar-gutter: stable;\n}\n\n.settings-page__content {\n width: min(930px, calc(100% - 80px));\n margin-inline: auto;\n}\n\n.settings-page__content {\n min-width: 0;\n padding: 44px 0 56px;\n}\n\n.settings-section-label {\n min-height: auto;\n padding: 0 0 28px;\n color: var(--settings-text);\n font-size: 24px;\n font-weight: 600;\n line-height: 30px;\n}\n\n.settings-status-list,\n.settings-empty {\n overflow: hidden;\n background: var(--settings-panel);\n}\n\n.settings-status-row {\n display: grid;\n grid-template-columns: minmax(170px, 1fr) auto minmax(280px, 1.45fr);\n position: relative;\n align-items: center;\n min-height: 88px;\n gap: 28px;\n padding: 16px 0;\n}\n\n.settings-status-row:not(:last-child)::after {\n content: "";\n position: absolute;\n right: 0;\n bottom: 0;\n left: 0;\n height: 1px;\n background: var(--settings-divider);\n}\n\n.settings-status-row__identity {\n display: inline-flex;\n align-items: center;\n min-width: 0;\n color: var(--settings-text);\n gap: 14px;\n font-size: 15px;\n font-weight: 500;\n line-height: 22px;\n}\n\n.settings-status-row__icon {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 44px;\n height: 44px;\n flex: none;\n color: var(--settings-muted);\n background: rgb(255 255 255 / 7%);\n border-radius: 50%;\n}\n\n.settings-status-badge {\n flex: none;\n padding: 5px 12px;\n color: var(--settings-muted);\n font-size: 13px;\n font-weight: 500;\n line-height: 18px;\n background: rgb(255 255 255 / 9%);\n border: 1px solid rgb(255 255 255 / 6%);\n border-radius: 6px;\n}\n\n.settings-status-row__detail {\n min-width: 0;\n color: var(--settings-muted);\n font-size: 13px;\n line-height: 20px;\n}\n\n.settings-empty {\n display: flex;\n align-items: center;\n min-height: 72px;\n padding: 12px 16px;\n}\n\n.settings-empty > div {\n display: grid;\n min-width: 0;\n gap: 2px;\n}\n\n.settings-empty strong {\n color: var(--settings-text);\n font-size: 13px;\n font-weight: 500;\n line-height: 19px;\n}\n\n.settings-empty span {\n color: var(--settings-muted);\n font-size: 13px;\n line-height: 19px;\n}\n\n.settings-page-error {\n padding: 16px;\n color: var(--settings-text);\n font-size: 13px;\n background: var(--settings-panel);\n border: 1px solid var(--settings-border);\n border-radius: 20px;\n}\n\n.settings-update-metadata {\n display: grid;\n grid-template-columns: repeat(2, minmax(0, 1fr));\n gap: 24px;\n margin-bottom: 24px;\n padding: 0 4px 20px;\n border-bottom: 1px solid var(--settings-divider);\n}\n\n.settings-update-metadata__item {\n display: grid;\n min-width: 0;\n gap: 4px;\n}\n\n.settings-update-metadata__item span {\n color: var(--settings-muted);\n font-size: 12px;\n line-height: 18px;\n}\n\n.settings-update-metadata__item strong {\n min-width: 0;\n overflow-wrap: anywhere;\n color: var(--settings-text);\n font-size: 15px;\n font-weight: 500;\n line-height: 22px;\n}\n\n.settings-update-panel {\n display: grid;\n gap: 16px;\n min-height: 128px;\n padding: 20px;\n color: var(--settings-text);\n background: var(--settings-panel);\n border: 1px solid var(--settings-border);\n border-radius: 8px;\n}\n\n.settings-update-panel > strong,\n.settings-update-panel > span,\n.settings-update-summary,\n.settings-update-error {\n margin: 0;\n overflow-wrap: anywhere;\n font-size: 13px;\n line-height: 20px;\n}\n\n.settings-update-panel > span,\n.settings-update-summary {\n color: var(--settings-muted);\n}\n\n.settings-update-error {\n color: #ef4444;\n}\n\n.settings-update-progress {\n width: 100%;\n height: 8px;\n accent-color: #238be8;\n}\n\n.settings-update-progress-detail {\n color: var(--settings-muted);\n font-size: 12px;\n line-height: 18px;\n}\n\n.settings-update-notes {\n max-height: 240px;\n padding: 14px;\n overflow: auto;\n color: var(--settings-muted);\n font-size: 13px;\n line-height: 20px;\n white-space: pre-wrap;\n overflow-wrap: anywhere;\n background: rgb(255 255 255 / 4%);\n border: 1px solid var(--settings-divider);\n border-radius: 6px;\n}\n\n.settings-update-version-row {\n display: grid;\n grid-template-columns: minmax(0, 1fr) auto;\n align-items: center;\n gap: 20px;\n min-height: 32px;\n color: var(--settings-muted);\n font-size: 13px;\n}\n\n.settings-update-version-row strong {\n color: var(--settings-text);\n font-size: 15px;\n}\n\n.settings-update-actions {\n display: flex;\n min-width: 0;\n margin-top: 16px;\n}\n\n.settings-command-button,\n.settings-update-link {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: fit-content;\n min-height: 36px;\n gap: 8px;\n padding: 8px 12px;\n color: white;\n font: inherit;\n font-size: 13px;\n text-decoration: none;\n background: #1677d2;\n border: 1px solid #238be8;\n border-radius: 6px;\n cursor: pointer;\n}\n\n.settings-command-button--secondary,\n.settings-update-link {\n color: var(--settings-text);\n background: transparent;\n border-color: var(--settings-border);\n}\n\n.settings-command-button:hover,\n.settings-update-link:hover {\n filter: brightness(1.08);\n}\n\n.settings-command-button:focus-visible,\n.settings-update-link:focus-visible {\n outline: 2px solid var(--settings-focus);\n outline-offset: 2px;\n}\n\n.codexhost-settings-icon {\n display: block;\n flex: none;\n stroke: currentColor;\n}\n\n@media (max-width: 720px) {\n .codexhost-settings-dialog {\n width: calc(100vw - 16px);\n height: calc(100vh - 16px);\n border-radius: 10px;\n }\n\n .settings-layout {\n grid-template-columns: minmax(0, 1fr);\n grid-template-rows: auto minmax(0, 1fr);\n }\n\n .settings-sidebar {\n border-right: 0;\n border-bottom: 1px solid var(--settings-border);\n }\n\n .settings-header {\n height: 56px;\n padding-inline: 14px;\n }\n\n .settings-sidebar {\n padding-top: 20px;\n }\n\n .settings-nav {\n flex: none;\n flex-direction: row;\n gap: 4px;\n padding: 7px 8px 8px;\n overflow-x: auto;\n overflow-y: hidden;\n }\n\n .settings-nav-button {\n width: auto;\n min-width: max-content;\n min-height: 34px;\n grid-template-columns: 16px auto;\n border-radius: 10px;\n }\n\n .settings-page__content {\n width: calc(100% - 40px);\n }\n\n .settings-page__content {\n padding-top: 32px;\n padding-bottom: 32px;\n }\n\n .settings-section-label {\n padding-bottom: 20px;\n font-size: 20px;\n line-height: 26px;\n }\n\n .settings-status-row {\n grid-template-columns: minmax(0, 1fr) auto;\n gap: 16px;\n }\n\n .settings-status-row__detail {\n grid-column: 1 / -1;\n margin: -8px 0 0 58px;\n }\n}\n\n@media (forced-colors: active) {\n :host,\n :host([data-theme="dark"]) {\n --settings-bg: Canvas;\n --settings-sidebar: Canvas;\n --settings-panel: Canvas;\n --settings-text: CanvasText;\n --settings-muted: GrayText;\n --settings-border: ButtonBorder;\n --settings-divider: ButtonBorder;\n --settings-hover: Highlight;\n --settings-active: Highlight;\n --settings-focus: Highlight;\n }\n}\n\n@media (prefers-reduced-motion: reduce) {\n *,\n *::before,\n *::after {\n scroll-behavior: auto !important;\n }\n}\n';
18833
18838
 
18834
18839
  // src/settings/shell.ts
18835
18840
  var SETTINGS_SHELL_ATTRIBUTE = "data-codexhost-settings-shell";
@@ -19265,6 +19270,8 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
19265
19270
  }
19266
19271
 
19267
19272
  // src/renderer-settings-lifecycle.ts
19273
+ var UPDATE_CHECK_TIMEOUT_MS = 5e3;
19274
+ var UPDATE_RETRY_DELAYS_MS = [1e3, 3e3, 1e4, 3e4];
19268
19275
  function installRendererSettingsLifecycle(ownerWindow = window, options = {}) {
19269
19276
  const lifecycleController = new AbortController();
19270
19277
  let locale = resolveRendererSettingsLocale(ownerWindow.navigator.languages);
@@ -19272,6 +19279,9 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
19272
19279
  let trigger = null;
19273
19280
  let localeRequest = null;
19274
19281
  let checkedUpdateClient = null;
19282
+ let retryUpdateClient = null;
19283
+ let updateRetryTimer = null;
19284
+ let updateRetryAttempt = 0;
19275
19285
  let updateCheckGeneration = 0;
19276
19286
  let updateAvailable = false;
19277
19287
  let openGeneration = 0;
@@ -19334,16 +19344,65 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
19334
19344
  localeRequest = request;
19335
19345
  return request;
19336
19346
  };
19347
+ const clearUpdateRetry = () => {
19348
+ if (updateRetryTimer === null) return;
19349
+ ownerWindow.clearTimeout(updateRetryTimer);
19350
+ updateRetryTimer = null;
19351
+ };
19352
+ const scheduleUpdateRetry = (client) => {
19353
+ if (disposed || updateRetryTimer !== null) return;
19354
+ const delay = UPDATE_RETRY_DELAYS_MS[updateRetryAttempt];
19355
+ if (delay === void 0) return;
19356
+ updateRetryAttempt += 1;
19357
+ updateRetryTimer = ownerWindow.setTimeout(() => {
19358
+ updateRetryTimer = null;
19359
+ if (disposed || options.getUpdateClient?.() !== client) return;
19360
+ refreshUpdateIndicator();
19361
+ }, delay);
19362
+ };
19363
+ const checkUpdateWithTimeout = (client) => new Promise((resolve, reject) => {
19364
+ const timeout = ownerWindow.setTimeout(
19365
+ () => reject(new Error("Update indicator check timed out")),
19366
+ UPDATE_CHECK_TIMEOUT_MS
19367
+ );
19368
+ void client.checkUpdate().then(
19369
+ (result) => {
19370
+ ownerWindow.clearTimeout(timeout);
19371
+ resolve(result);
19372
+ },
19373
+ (error51) => {
19374
+ ownerWindow.clearTimeout(timeout);
19375
+ reject(error51);
19376
+ }
19377
+ );
19378
+ });
19337
19379
  const refreshUpdateIndicator = () => {
19338
19380
  const client = options.getUpdateClient?.() ?? null;
19339
19381
  if (!client || checkedUpdateClient === client) return;
19382
+ if (retryUpdateClient !== client) {
19383
+ clearUpdateRetry();
19384
+ retryUpdateClient = client;
19385
+ updateRetryAttempt = 0;
19386
+ }
19340
19387
  checkedUpdateClient = client;
19341
19388
  const generation = ++updateCheckGeneration;
19342
- void client.checkUpdate().then((result) => {
19389
+ void checkUpdateWithTimeout(client).then((result) => {
19343
19390
  if (disposed || generation !== updateCheckGeneration) return;
19344
19391
  updateAvailable = result.updateAvailable;
19345
19392
  trigger?.setUpdateAvailable(updateAvailable);
19393
+ if (result.error === null) {
19394
+ updateRetryAttempt = 0;
19395
+ clearUpdateRetry();
19396
+ return;
19397
+ }
19398
+ checkedUpdateClient = null;
19399
+ scheduleUpdateRetry(client);
19346
19400
  }).catch(() => {
19401
+ if (disposed || generation !== updateCheckGeneration || checkedUpdateClient !== client) {
19402
+ return;
19403
+ }
19404
+ checkedUpdateClient = null;
19405
+ scheduleUpdateRetry(client);
19347
19406
  });
19348
19407
  };
19349
19408
  mount();
@@ -19364,6 +19423,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
19364
19423
  openGeneration += 1;
19365
19424
  updateCheckGeneration += 1;
19366
19425
  lifecycleController.abort();
19426
+ clearUpdateRetry();
19367
19427
  trigger?.dispose();
19368
19428
  shell?.dispose();
19369
19429
  trigger = null;
@@ -20627,6 +20687,14 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
20627
20687
  applyAdapterAgent = applyAgent ?? null;
20628
20688
  modelControl = nextModelControl ?? null;
20629
20689
  adapterStatus = status;
20690
+ const installedModelControl = modelControl;
20691
+ queueMicrotask(() => {
20692
+ if (disposed || modelControl !== installedModelControl) return;
20693
+ try {
20694
+ settingsLifecycle.refresh();
20695
+ } catch {
20696
+ }
20697
+ });
20630
20698
  sidebarAgentIcons.refresh();
20631
20699
  void refreshHarnessAvailability();
20632
20700
  const connected = connectedComposers();
package/bin/codexhost.exe CHANGED
Binary file
Binary file
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@codexhost/cli-win32-arm64",
3
- "version": "0.1.2",
3
+ "version": "0.1.3",
4
4
  "description": "Run Pi and Claude Code as first-class external harnesses inside Codex Desktop.",
5
5
  "type": "module",
6
6
  "files": [