@codexhost/cli-darwin-x64 0.13.0 → 0.13.2

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.13.0
10
+ npm install -g @codexhost/cli@0.13.2
11
11
  ```
12
12
 
13
13
  Do not install this package directly. npm selects it through the optional dependencies of `@codexhost/cli`.
@@ -12,7 +12,7 @@ License text: licenses/Cosmokit-LICENSE.txt
12
12
  License: Apache-2.0
13
13
  License text: licenses/Agent-Client-Protocol-SDK-LICENSE.txt
14
14
 
15
- @anthropic-ai/claude-agent-sdk 0.3.220
15
+ @anthropic-ai/claude-agent-sdk 0.3.273
16
16
  License: SEE LICENSE IN README.md
17
17
  License text: licenses/Claude-Agent-SDK-LICENSE.md
18
18
 
@@ -1 +1 @@
1
- {"schemaVersion":1,"version":"0.13.0","distribution":"npm","target":"macos-x64"}
1
+ {"schemaVersion":1,"version":"0.13.2","distribution":"npm","target":"macos-x64"}
@@ -358,39 +358,25 @@ async function regularFile(filePath) {
358
358
  throw error51;
359
359
  }
360
360
  }
361
- async function isUpdateOperationActive(stateDirectory) {
361
+ async function discoverActiveUpdateStatus(stateDirectory) {
362
362
  if (!path4.isAbsolute(stateDirectory))
363
363
  throw new Error("update state directory must be absolute");
364
- return regularFile(path4.join(stateDirectory, LOCK_FILE));
365
- }
366
- async function discoverLatestUpdateStatus(stateDirectory) {
367
- if (!path4.isAbsolute(stateDirectory))
368
- throw new Error("update state directory must be absolute");
369
- let entries;
364
+ const lockPath = path4.join(stateDirectory, LOCK_FILE);
365
+ if (!await regularFile(lockPath))
366
+ return null;
370
367
  try {
371
- entries = await readdir(stateDirectory, { withFileTypes: true });
372
- } catch (error51) {
373
- if (error51.code === "ENOENT")
368
+ const lock = JSON.parse(await readFile2(lockPath, "utf8"));
369
+ if (typeof lock.statusPath !== "string" || !path4.isAbsolute(lock.statusPath))
374
370
  return null;
375
- throw error51;
376
- }
377
- const candidates = [];
378
- for (const entry of entries) {
379
- if (!entry.isDirectory() || entry.isSymbolicLink() || !entry.name.startsWith("update-"))
380
- continue;
381
- const statusPath = path4.join(stateDirectory, entry.name, STATUS_FILE);
382
- if (!await regularFile(statusPath))
383
- continue;
384
- try {
385
- candidates.push({
386
- statusPath,
387
- status: parseUpdateStatus(JSON.parse(await readFile2(statusPath, "utf8")))
388
- });
389
- } catch {
390
- }
371
+ if (!await regularFile(lock.statusPath))
372
+ return null;
373
+ const status = parseUpdateStatus(JSON.parse(await readFile2(lock.statusPath, "utf8")));
374
+ if (TERMINAL_PHASES.has(status.phase))
375
+ return null;
376
+ return { statusPath: lock.statusPath, status };
377
+ } catch {
378
+ return null;
391
379
  }
392
- candidates.sort((left, right) => right.status.updatedAt - left.status.updatedAt);
393
- return candidates[0] ?? null;
394
380
  }
395
381
  async function cleanupTerminalUpdateState(stateDirectory, options = {}) {
396
382
  const now = Math.floor((options.now ?? Date.now()) / 1e3);
@@ -588,6 +574,48 @@ async function verifyDownloadedArtifact(source, filePath, result) {
588
574
  }
589
575
  }
590
576
 
577
+ // packages/update-manager/dist/updater-ready.js
578
+ import { setTimeout as delay } from "node:timers/promises";
579
+ async function waitForUpdaterReady(child, readStatus, timeoutMs = 1e4) {
580
+ let failure;
581
+ const onError = (error51) => {
582
+ failure = error51;
583
+ };
584
+ const onExit = () => {
585
+ failure = new Error("Background Updater exited before completing handoff");
586
+ };
587
+ child.on("error", onError);
588
+ child.on("exit", onExit);
589
+ const deadline = performance.now() + timeoutMs;
590
+ try {
591
+ while (true) {
592
+ const status = await readStatus();
593
+ if (status?.phase === "failed")
594
+ throw new Error(status.error ?? "Background Updater failed");
595
+ if (failure)
596
+ throw failure;
597
+ if (child.exitCode != null || child.signalCode != null) {
598
+ throw new Error("Background Updater exited before completing handoff");
599
+ }
600
+ if (status?.phase === "waiting-for-exit")
601
+ return;
602
+ if (status && status.phase !== "prepared") {
603
+ throw new Error(`Unexpected Updater phase during handoff: ${status.phase}`);
604
+ }
605
+ if (performance.now() >= deadline) {
606
+ throw new Error("Background Updater did not confirm handoff before the startup timeout");
607
+ }
608
+ await delay(20);
609
+ }
610
+ } catch (error51) {
611
+ child.kill();
612
+ throw error51;
613
+ } finally {
614
+ child.removeListener("error", onError);
615
+ child.removeListener("exit", onExit);
616
+ }
617
+ }
618
+
591
619
  // packages/update-manager/dist/update-manager.js
592
620
  var REQUEST_SCHEMA_VERSION = 1;
593
621
  var WINDOWS_RENAME_RETRY_DELAYS_MS = [10, 30, 70, 150, 300];
@@ -597,7 +625,7 @@ function errorMessage(error51) {
597
625
  function systemErrorCode(error51) {
598
626
  return typeof error51 === "object" && error51 !== null && "code" in error51 ? String(error51.code) : null;
599
627
  }
600
- function delay(milliseconds) {
628
+ function delay2(milliseconds) {
601
629
  return new Promise((resolve) => setTimeout(resolve, milliseconds));
602
630
  }
603
631
  async function replaceStatusFile(temporaryPath, statusPath) {
@@ -613,7 +641,7 @@ async function replaceStatusFile(temporaryPath, statusPath) {
613
641
  throw error51;
614
642
  }
615
643
  retryIndex += 1;
616
- await delay(retryDelay);
644
+ await delay2(retryDelay);
617
645
  }
618
646
  }
619
647
  }
@@ -833,14 +861,20 @@ function createBackgroundUpdateManager(dependencies = {}) {
833
861
  app_path: appPath
834
862
  }, artifact.artifactPath);
835
863
  },
836
- start(prepared) {
864
+ async start(prepared) {
837
865
  if (!preparedRequests.delete(prepared.requestPath)) {
838
866
  throw new Error("background update was not prepared by this manager or was already started");
839
867
  }
840
- const child = spawnUpdater(prepared.helperPath, prepared.requestPath);
841
- if (child.pid === void 0)
842
- throw new Error("background Updater did not report a process ID");
843
- return Object.freeze({ ...prepared, updaterPid: child.pid });
868
+ try {
869
+ const child = spawnUpdater(prepared.helperPath, prepared.requestPath);
870
+ await waitForUpdaterReady(child, () => this.readStatus(prepared.statusPath));
871
+ if (child.pid === void 0)
872
+ throw new Error("background Updater did not report a process ID");
873
+ return Object.freeze({ ...prepared, updaterPid: child.pid });
874
+ } catch (error51) {
875
+ await writeFailedStatus(prepared.statusPath, prepared.version, prepared.installation, error51);
876
+ throw error51;
877
+ }
844
878
  },
845
879
  async readStatus(statusPathValue) {
846
880
  const statusPath = requireAbsolutePath(statusPathValue, "update status path");
@@ -15533,6 +15567,8 @@ var usageStatisticsSessionSchema = external_exports.strictObject({
15533
15567
  harness,
15534
15568
  sessionId: external_exports.string().min(1).max(512),
15535
15569
  project: project.nullable(),
15570
+ /** Persisted Desktop title for a mapped Session, otherwise its native name; may be absent. */
15571
+ title: external_exports.string().min(1).max(200).optional(),
15536
15572
  /** Models the session used, most requests first. */
15537
15573
  models: external_exports.array(model).max(16),
15538
15574
  firstAtMs: count,
@@ -15599,7 +15635,12 @@ var usageStatisticsResultSchema = external_exports.strictObject({
15599
15635
  * The sessions that spent the most, by cost and by tokens without cache, all filters applied;
15600
15636
  * requests without a native session are not listed here but count everywhere else.
15601
15637
  */
15602
- sessions: external_exports.array(usageStatisticsSessionSchema).max(100)
15638
+ sessions: external_exports.array(usageStatisticsSessionSchema).max(100),
15639
+ /**
15640
+ * The sessions last active in the range, newest first, all filters applied. Optional for older
15641
+ * Hosts; missing is treated as no list rather than no sessions.
15642
+ */
15643
+ recentSessions: external_exports.array(usageStatisticsSessionSchema).max(100).optional()
15603
15644
  });
15604
15645
 
15605
15646
  // packages/shared-contracts/dist/ids.js
@@ -17569,14 +17610,15 @@ function createConsoleUpdates(options) {
17569
17610
  });
17570
17611
  let candidate = null;
17571
17612
  let handedOff = false;
17613
+ let currentStatusPath = null;
17572
17614
  async function latestStatus() {
17573
- const directory = stateDirectory();
17574
- const discovered = await discoverLatestUpdateStatus(directory);
17575
- if (!discovered) return null;
17576
- if (discovered.status.phase !== "succeeded" && discovered.status.phase !== "failed" && !await isUpdateOperationActive(directory)) {
17577
- return null;
17615
+ if (!currentStatusPath) {
17616
+ const active = await discoverActiveUpdateStatus(stateDirectory());
17617
+ if (!active) return null;
17618
+ currentStatusPath = active.statusPath;
17578
17619
  }
17579
- return publicStatus(discovered.status);
17620
+ const status = await manager.readStatus(currentStatusPath);
17621
+ return status ? publicStatus(status) : null;
17580
17622
  }
17581
17623
  function installable(metadata, release) {
17582
17624
  const kind = installationKind(metadata);
@@ -17703,6 +17745,7 @@ function createConsoleUpdates(options) {
17703
17745
  if (existing) return { status: existing };
17704
17746
  throw new ConsoleUpdateError("busy", "Another update operation is already active");
17705
17747
  }
17748
+ currentStatusPath = null;
17706
17749
  try {
17707
17750
  const release = await fetchLatest();
17708
17751
  if (compareSemanticVersions(metadata.version, release.version) >= 0 || candidate && candidate.version !== release.version) {
@@ -17721,9 +17764,10 @@ function createConsoleUpdates(options) {
17721
17764
  try {
17722
17765
  const prepared = await prepare(metadata, target, release, async (info) => {
17723
17766
  await lock.setStatusPath(info.statusPath);
17767
+ currentStatusPath = info.statusPath;
17724
17768
  resolvePrepared(info.statusPath);
17725
17769
  });
17726
- manager.start(prepared);
17770
+ await manager.start(prepared);
17727
17771
  handedOff = true;
17728
17772
  options.onHandedOff();
17729
17773
  } catch (error51) {
@@ -18230,7 +18274,7 @@ async function runUpdateCommand(target, updates, write = console.log) {
18230
18274
  const { status } = await updates.start(target);
18231
18275
  if (status.phase === "failed") throw new Error(status.error ?? "Update failed");
18232
18276
  write(
18233
- `Update ${status.version}: ${status.phase}. The background updater will finish installation and restart codexhost.`
18277
+ `Update ${status.version}: ${status.phase}. The background updater has accepted the handoff; installation is not complete yet. It will install the update and restart codexhost.`
18234
18278
  );
18235
18279
  }
18236
18280
  async function updateFromCommand(appDirectory2, arguments_) {