@codexhost/cli-darwin-x64 0.11.0 → 0.12.0

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.
@@ -14610,6 +14610,7 @@ var CONSOLE_HOST_METHODS = Object.freeze([
14610
14610
  "codexhost/harness/display-settings/get",
14611
14611
  "codexhost/harness/display-settings/set",
14612
14612
  "codexhost/harness/inspect",
14613
+ "codexhost/harness/installation",
14613
14614
  "codexhost/harness/launch-settings/get",
14614
14615
  "codexhost/harness/launch-settings/set",
14615
14616
  "codexhost/harness/web-ui/open",
@@ -15256,14 +15257,17 @@ var harnessLaunchSettingsSchema = external_exports.object({
15256
15257
  // ../../shared-contracts/dist/harness-installation.js
15257
15258
  var harnessInstallationParamsSchema = external_exports.object({
15258
15259
  harnessId: harnessIdSchema,
15259
- action: external_exports.enum(["check", "update"])
15260
+ action: external_exports.enum(["check", "update", "install"])
15260
15261
  }).strict();
15261
15262
  var harnessInstallationStateSchema = external_exports.object({
15262
15263
  currentVersion: external_exports.string().min(1).max(128),
15263
15264
  latestVersion: external_exports.string().min(1).max(128),
15264
15265
  updateAvailable: external_exports.boolean(),
15265
15266
  canUpdate: external_exports.boolean(),
15266
- message: external_exports.string().max(2048).optional()
15267
+ // Adapter-owned diagnostic text; UI uses messageCode rather than displaying it verbatim.
15268
+ message: external_exports.string().max(2048).optional(),
15269
+ messageCode: external_exports.string().min(1).max(128).optional(),
15270
+ latestVersionKind: external_exports.enum(["unknown", "tracking-branch"]).optional()
15267
15271
  }).strict();
15268
15272
 
15269
15273
  // ../../shared-contracts/dist/codex-accounts.js
@@ -15565,6 +15569,38 @@ var updateStatusResultSchema = external_exports.strictObject({
15565
15569
  status: updateStatusSchema.nullable()
15566
15570
  });
15567
15571
 
15572
+ // ../../shared-contracts/dist/remote-runtime.js
15573
+ var remoteUpdatePhaseSchema = external_exports.enum([
15574
+ "idle",
15575
+ "installing",
15576
+ "restarting",
15577
+ "succeeded",
15578
+ "failed"
15579
+ ]);
15580
+ var runtimeStatusSchema = external_exports.object({
15581
+ runningVersion: external_exports.string().nullable(),
15582
+ installedVersion: external_exports.string().nullable(),
15583
+ restartRequired: external_exports.boolean(),
15584
+ remote: external_exports.boolean(),
15585
+ updateSupported: external_exports.boolean(),
15586
+ update: external_exports.object({
15587
+ phase: remoteUpdatePhaseSchema,
15588
+ targetVersion: external_exports.string().nullable(),
15589
+ error: external_exports.string().nullable()
15590
+ })
15591
+ });
15592
+ var remoteUpdateParamsSchema = external_exports.object({
15593
+ version: external_exports.string().regex(/^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?$/u)
15594
+ }).strict();
15595
+ var remoteSshSetupParamsSchema = external_exports.object({
15596
+ hostname: external_exports.string().min(1).max(1024).refine((value) => !value.startsWith("-") && !/\s/u.test(value)),
15597
+ port: external_exports.number().int().min(1).max(65535).nullable(),
15598
+ identity: external_exports.string().max(4096).nullable(),
15599
+ action: external_exports.enum(["inspect", "install", "update", "repair"]),
15600
+ version: external_exports.string().regex(/^\d+\.\d+\.\d+$/u).nullable()
15601
+ }).strict();
15602
+ var remoteSshSetupResultSchema = external_exports.object({ state: external_exports.enum(["installed", "not-installed"]) }).strict();
15603
+
15568
15604
  // ../../shared-contracts/dist/index.js
15569
15605
  var workspaceContractVersionSchema = external_exports.literal(WORKSPACE_CONTRACT_VERSION);
15570
15606
 
@@ -42487,32 +42523,109 @@ import { opendir, realpath, stat } from "node:fs/promises";
42487
42523
  import os2 from "node:os";
42488
42524
  import path2 from "node:path";
42489
42525
  import { createInterface } from "node:readline";
42490
- var CLAUDE_SESSION_IMPORT_TITLE_MAX_LENGTH = 120;
42491
- var CLAUDE_INTERNAL_USER_TEXT = /^<(?:local-command-|command-)/u;
42492
- var ClaudeSessionChangedError = class extends Error {
42493
- constructor() {
42494
- super("Claude Code Session changed during discovery; refresh and retry");
42526
+
42527
+ // ../../harness-adapter/dist/session-import.js
42528
+ var SessionImportChangedError = class extends Error {
42529
+ constructor(message = "Native Session changed during discovery; refresh and retry") {
42530
+ super(message);
42531
+ this.name = "SessionImportChangedError";
42495
42532
  }
42496
42533
  };
42497
- function isRecord2(value) {
42498
- return typeof value === "object" && value !== null && !Array.isArray(value);
42499
- }
42500
- function missing(error52) {
42501
- return isRecord2(error52) && error52.code === "ENOENT";
42534
+ function isMissingFileError(error52) {
42535
+ return typeof error52 === "object" && error52 !== null && "code" in error52 && error52.code === "ENOENT";
42502
42536
  }
42503
- function sameFile(left, right) {
42504
- return left.size === right.size && left.mtimeMs === right.mtimeMs && left.ctimeMs === right.ctimeMs && left.ino === right.ino && left.dev === right.dev;
42537
+ function sameFileFingerprint(left, right) {
42538
+ return left === null || right === null ? left === right : left.dev === right.dev && left.ino === right.ino && left.size === right.size && left.mtimeMs === right.mtimeMs && left.ctimeMs === right.ctimeMs;
42505
42539
  }
42506
- function cleanText(value) {
42540
+ function sessionImportTitle(value, maxLength = HARNESS_SESSION_IMPORT_TITLE_MAX_LENGTH) {
42507
42541
  if (typeof value !== "string")
42508
42542
  return null;
42509
42543
  const normalized = value.replaceAll("\0", "").replaceAll(/\s+/gu, " ").trim();
42510
42544
  if (!normalized)
42511
42545
  return null;
42546
+ if (normalized.length <= maxLength)
42547
+ return normalized;
42512
42548
  const characters = [...normalized];
42513
- if (characters.length <= CLAUDE_SESSION_IMPORT_TITLE_MAX_LENGTH)
42549
+ if (characters.length <= maxLength)
42514
42550
  return normalized;
42515
- return `${characters.slice(0, CLAUDE_SESSION_IMPORT_TITLE_MAX_LENGTH - 1).join("").trimEnd()}…`;
42551
+ return `${characters.slice(0, maxLength - 1).join("").trimEnd()}…`;
42552
+ }
42553
+ function sessionImportCandidate(input) {
42554
+ const time3 = typeof input.updatedAt === "number" ? input.updatedAt : typeof input.updatedAt === "string" ? Date.parse(input.updatedAt) : Number.NaN;
42555
+ const parsed = harnessSessionImportCandidateSchema.safeParse({
42556
+ nativeSessionId: input.nativeSessionId,
42557
+ cwd: input.cwd,
42558
+ title: typeof input.title === "string" && input.title.trim().length > 0 ? input.title : null,
42559
+ updatedAt: Math.floor(time3),
42560
+ // Unknown must stay unknown; only an explicit boolean is a native statement.
42561
+ running: typeof input.running === "boolean" ? input.running : null
42562
+ });
42563
+ return parsed.success ? parsed.data : null;
42564
+ }
42565
+ var SessionImportScope = class {
42566
+ #abort = new AbortController();
42567
+ #options;
42568
+ #pending = /* @__PURE__ */ new Set();
42569
+ constructor(options) {
42570
+ this.#options = options;
42571
+ }
42572
+ #closed() {
42573
+ return {
42574
+ ok: false,
42575
+ error: { code: "invalidState", message: this.#options.closedMessage, retryable: false }
42576
+ };
42577
+ }
42578
+ read(operation) {
42579
+ const signal = this.#abort.signal;
42580
+ if (signal.aborted)
42581
+ return Promise.resolve(this.#closed());
42582
+ let started;
42583
+ try {
42584
+ started = operation(signal);
42585
+ } catch (error52) {
42586
+ started = Promise.reject(error52 instanceof Error ? error52 : new Error("Session read failed"));
42587
+ }
42588
+ const request = started.then((value) => signal.aborted ? this.#closed() : { ok: true, value }).catch(() => signal.aborted ? this.#closed() : {
42589
+ ok: false,
42590
+ error: {
42591
+ code: "unavailable",
42592
+ message: this.#options.unavailableMessage,
42593
+ retryable: true
42594
+ }
42595
+ }).finally(() => this.#pending.delete(request));
42596
+ this.#pending.add(request);
42597
+ return request;
42598
+ }
42599
+ /** `read` for `resolveCandidate`: a null source is the selected Session having disappeared. */
42600
+ async resolve(operation) {
42601
+ const result = await this.read(operation);
42602
+ if (!result.ok)
42603
+ return result;
42604
+ return result.value ? { ok: true, value: result.value } : {
42605
+ ok: false,
42606
+ error: {
42607
+ code: "sessionNotFound",
42608
+ message: this.#options.notFoundMessage,
42609
+ retryable: false
42610
+ }
42611
+ };
42612
+ }
42613
+ /** Idempotent. Resolves after every started read has settled. */
42614
+ async close() {
42615
+ this.#abort.abort();
42616
+ await Promise.allSettled(this.#pending);
42617
+ }
42618
+ };
42619
+
42620
+ // dist/claude-session-import.js
42621
+ var CLAUDE_SESSION_IMPORT_TITLE_MAX_LENGTH = 120;
42622
+ var CLAUDE_INTERNAL_USER_TEXT = /^<(?:local-command-|command-)/u;
42623
+ var CLAUDE_SESSION_CHANGED = "Claude Code Session changed during discovery; refresh and retry";
42624
+ function isRecord2(value) {
42625
+ return typeof value === "object" && value !== null && !Array.isArray(value);
42626
+ }
42627
+ function cleanText(value) {
42628
+ return sessionImportTitle(value, CLAUDE_SESSION_IMPORT_TITLE_MAX_LENGTH);
42516
42629
  }
42517
42630
  function userText(message) {
42518
42631
  if (!isRecord2(message) || message.role !== "user")
@@ -42528,7 +42641,7 @@ function claudeProjectsDirectory(environment) {
42528
42641
  async function sessionFiles(directory, signal) {
42529
42642
  signal.throwIfAborted();
42530
42643
  const projects = await opendir(directory).catch((error52) => {
42531
- if (missing(error52))
42644
+ if (isMissingFileError(error52))
42532
42645
  return null;
42533
42646
  throw error52;
42534
42647
  });
@@ -42540,7 +42653,7 @@ async function sessionFiles(directory, signal) {
42540
42653
  if (!project.isDirectory())
42541
42654
  continue;
42542
42655
  const entries = await opendir(path2.join(directory, project.name)).catch((error52) => {
42543
- if (missing(error52))
42656
+ if (isMissingFileError(error52))
42544
42657
  return null;
42545
42658
  throw error52;
42546
42659
  });
@@ -42607,24 +42720,23 @@ async function readCandidate(file2, signal) {
42607
42720
  if (!hasConversation || !cwd)
42608
42721
  return null;
42609
42722
  const after = await stat(file2);
42610
- if (!sameFile(before, after))
42611
- throw new ClaudeSessionChangedError();
42723
+ if (!sameFileFingerprint(before, after))
42724
+ throw new SessionImportChangedError(CLAUDE_SESSION_CHANGED);
42612
42725
  const resolvedCwd = await realpath(cwd);
42613
42726
  if (!(await stat(resolvedCwd)).isDirectory())
42614
42727
  return null;
42615
- const candidate = harnessSessionImportCandidateSchema.safeParse({
42728
+ const candidate = sessionImportCandidate({
42616
42729
  nativeSessionId,
42617
42730
  title: customTitle ?? generatedTitle ?? firstPrompt,
42618
- updatedAt: Math.floor(before.mtimeMs),
42619
- cwd: resolvedCwd,
42620
- running: null
42731
+ updatedAt: before.mtimeMs,
42732
+ cwd: resolvedCwd
42621
42733
  });
42622
42734
  const nativeRef = nativeSessionRefSchema.safeParse({
42623
42735
  harnessId: "claude-code",
42624
42736
  nativeSessionId,
42625
42737
  formatVersion: 1
42626
42738
  });
42627
- return candidate.success && nativeRef.success ? { candidate: candidate.data, nativeRef: nativeRef.data } : null;
42739
+ return candidate && nativeRef.success ? { candidate, nativeRef: nativeRef.data } : null;
42628
42740
  }
42629
42741
  var ClaudeSessionImportIndex = class {
42630
42742
  #directory;
@@ -42648,7 +42760,7 @@ var ClaudeSessionImportIndex = class {
42648
42760
  try {
42649
42761
  const fingerprint = await stat(file2);
42650
42762
  const cached2 = this.#cache.get(file2);
42651
- const source = cached2 && sameFile(cached2.fingerprint, fingerprint) ? cached2.source : await readCandidate(file2, signal);
42763
+ const source = cached2 && sameFileFingerprint(cached2.fingerprint, fingerprint) ? cached2.source : await readCandidate(file2, signal);
42652
42764
  if (!source)
42653
42765
  continue;
42654
42766
  if (!(await stat(source.candidate.cwd)).isDirectory())
@@ -42660,7 +42772,7 @@ var ClaudeSessionImportIndex = class {
42660
42772
  next.set(file2, { fingerprint, source });
42661
42773
  sources.push(source);
42662
42774
  } catch (error52) {
42663
- if (!missing(error52) && !(error52 instanceof ClaudeSessionChangedError))
42775
+ if (!isMissingFileError(error52) && !(error52 instanceof SessionImportChangedError))
42664
42776
  throw error52;
42665
42777
  }
42666
42778
  }
@@ -42685,7 +42797,7 @@ var ClaudeSessionImportIndex = class {
42685
42797
  const source = await readCandidate(selected, signal);
42686
42798
  return source?.candidate.nativeSessionId === nativeSessionId ? source : null;
42687
42799
  } catch (error52) {
42688
- if (missing(error52))
42800
+ if (isMissingFileError(error52))
42689
42801
  return null;
42690
42802
  throw error52;
42691
42803
  }
@@ -43123,6 +43235,60 @@ async function npmInstallation(command, packages, environment) {
43123
43235
  return null;
43124
43236
  }
43125
43237
 
43238
+ // ../../harness-discovery/dist/installer.js
43239
+ import { mkdtemp, rm as rm2, writeFile } from "node:fs/promises";
43240
+ import { tmpdir } from "node:os";
43241
+ import { join as join2 } from "node:path";
43242
+ function createHarnessInstaller(environment, source) {
43243
+ return async () => {
43244
+ if (!["darwin", "linux", "win32"].includes(process.platform))
43245
+ throw new Error("Unsupported installation platform");
43246
+ const env = withNodeRuntimeOnPath(environment);
43247
+ if ("npm" in source) {
43248
+ const npm = resolveHarnessExecutable({
43249
+ id: "npm",
43250
+ command: "npm",
43251
+ installRoots: {
43252
+ posix: [
43253
+ "~/.npm-global/bin",
43254
+ "~/.local/bin",
43255
+ VERSION_MANAGER_ROOTS,
43256
+ "/opt/homebrew/bin",
43257
+ "/usr/local/bin",
43258
+ "/usr/bin"
43259
+ ],
43260
+ windows: [
43261
+ "${APPDATA}/npm",
43262
+ VERSION_MANAGER_ROOTS,
43263
+ "${ProgramFiles}/nodejs",
43264
+ "${LOCALAPPDATA}/Programs/nodejs"
43265
+ ]
43266
+ }
43267
+ }, { environment: env });
43268
+ if (!npm)
43269
+ throw new Error("Install Node.js and npm first");
43270
+ await runInstallationCommand(npm.executable, ["install", "--global", source.npm], {
43271
+ ...env,
43272
+ ...source.allowScripts ? { npm_config_allow_scripts: source.allowScripts } : {}
43273
+ }, 6e5);
43274
+ return;
43275
+ }
43276
+ const windows = process.platform === "win32";
43277
+ const url2 = windows ? source.windows : source.posix;
43278
+ if (new URL(url2).protocol !== "https:")
43279
+ throw new Error("Installer requires HTTPS");
43280
+ const script = await fetchInstallationText(url2);
43281
+ const directory = await mkdtemp(join2(tmpdir(), "codexhost-installer-"));
43282
+ try {
43283
+ const file2 = join2(directory, windows ? "install.ps1" : "install.sh");
43284
+ await writeFile(file2, script, { mode: 384 });
43285
+ await runInstallationCommand(windows ? "powershell.exe" : source.shell ?? "bash", windows ? ["-NoProfile", "-NonInteractive", "-ExecutionPolicy", "Bypass", "-File", file2] : [file2], env, 6e5);
43286
+ } finally {
43287
+ await rm2(directory, { recursive: true, force: true });
43288
+ }
43289
+ };
43290
+ }
43291
+
43126
43292
  // dist/command.js
43127
43293
  var ClaudeCodeExecutableError = class extends Error {
43128
43294
  code = "CLAUDE_NOT_FOUND";
@@ -43174,7 +43340,7 @@ function resolveClaudeCodeExecutable(input = {}, dependencies = {}) {
43174
43340
 
43175
43341
  // dist/pending-session.js
43176
43342
  import { randomUUID as randomUUID2 } from "node:crypto";
43177
- import { mkdir, open, readFile as readFile3, rename, rm as rm2, stat as stat2, unlink } from "node:fs/promises";
43343
+ import { mkdir, open, readFile as readFile3, rename, rm as rm3, stat as stat2, unlink } from "node:fs/promises";
43178
43344
  import os4 from "node:os";
43179
43345
  import path8 from "node:path";
43180
43346
  var reservationSchema = external_exports.strictObject({
@@ -43222,7 +43388,7 @@ var ClaudePendingSessions = class {
43222
43388
  await file2.close();
43223
43389
  }
43224
43390
  } catch (error52) {
43225
- await rm2(directory, { recursive: true, force: true });
43391
+ await rm3(directory, { recursive: true, force: true });
43226
43392
  throw error52;
43227
43393
  }
43228
43394
  await this.#sync(directory);
@@ -43267,7 +43433,7 @@ var ClaudePendingSessions = class {
43267
43433
  await rename(temporary, path8.join(directory, "session.json"));
43268
43434
  await this.#sync(directory);
43269
43435
  } finally {
43270
- await rm2(temporary, { force: true });
43436
+ await rm3(temporary, { force: true });
43271
43437
  }
43272
43438
  }
43273
43439
  async #sync(directory) {
@@ -43296,7 +43462,7 @@ var ClaudePendingSessions = class {
43296
43462
  await this.#sync(this.#path(ref, cwd));
43297
43463
  }
43298
43464
  async discard(ref, cwd) {
43299
- await rm2(this.#path(ref, cwd), { recursive: true, force: true });
43465
+ await rm3(this.#path(ref, cwd), { recursive: true, force: true });
43300
43466
  }
43301
43467
  };
43302
43468
 
@@ -48749,22 +48915,10 @@ var ClaudeCodeAdapter = class {
48749
48915
  harnessId = claudeCodeHarnessId2;
48750
48916
  sessionImport = Object.freeze({
48751
48917
  listCandidates: async () => {
48752
- const result = await this.#readImport((signal) => this.#importIndex.list(signal));
48918
+ const result = await this.#importScope.read((signal) => this.#importIndex.list(signal));
48753
48919
  return result.ok ? { ok: true, value: result.value.map(({ candidate }) => candidate) } : result;
48754
48920
  },
48755
- resolveCandidate: async (nativeSessionId) => {
48756
- const result = await this.#readImport((signal) => this.#importIndex.resolve(nativeSessionId, signal));
48757
- if (!result.ok)
48758
- return result;
48759
- return result.value ? { ok: true, value: result.value } : {
48760
- ok: false,
48761
- error: {
48762
- code: "sessionNotFound",
48763
- message: "Claude Code Session is no longer importable",
48764
- retryable: false
48765
- }
48766
- };
48767
- }
48921
+ resolveCandidate: (nativeSessionId) => this.#importScope.resolve((signal) => this.#importIndex.resolve(nativeSessionId, signal))
48768
48922
  });
48769
48923
  subagents = {
48770
48924
  readSnapshot: async (input) => {
@@ -48809,9 +48963,12 @@ var ClaudeCodeAdapter = class {
48809
48963
  #cancelTimeoutMs;
48810
48964
  #closeTimeoutMs;
48811
48965
  #dependencies;
48812
- #importAbort = new AbortController();
48813
48966
  #importIndex;
48814
- #importRequests = /* @__PURE__ */ new Set();
48967
+ #importScope = new SessionImportScope({
48968
+ closedMessage: "Claude Code Adapter is closed",
48969
+ unavailableMessage: "Claude Code Session discovery failed; check storage access and duplicate Session identities, then retry after closing native clients",
48970
+ notFoundMessage: "Claude Code Session is no longer importable"
48971
+ });
48815
48972
  #pendingSessions;
48816
48973
  #toolOutputLimit;
48817
48974
  #continuationQuiescenceMs;
@@ -48880,24 +49037,6 @@ var ClaudeCodeAdapter = class {
48880
49037
  readSubagentMessages: ({ cwd, sessionId, nativeSubagentId: nativeSubagentId2 }) => jkt(sessionId, nativeSubagentId2, { dir: cwd })
48881
49038
  };
48882
49039
  }
48883
- #readImport(operation) {
48884
- if (this.#importAbort.signal.aborted) {
48885
- return Promise.resolve({
48886
- ok: false,
48887
- error: invalidState("Claude Code Adapter is closed")
48888
- });
48889
- }
48890
- const request = operation(this.#importAbort.signal).then((value) => ({ ok: true, value })).catch(() => ({
48891
- ok: false,
48892
- error: {
48893
- code: "unavailable",
48894
- message: "Claude Code Session discovery failed; check storage access and duplicate Session identities, then retry after closing native clients",
48895
- retryable: true
48896
- }
48897
- })).finally(() => this.#importRequests.delete(request));
48898
- this.#importRequests.add(request);
48899
- return request;
48900
- }
48901
49040
  async inspect(input = {}) {
48902
49041
  if (this.#closePromise) {
48903
49042
  return {
@@ -49213,10 +49352,9 @@ var ClaudeCodeAdapter = class {
49213
49352
  }
49214
49353
  close() {
49215
49354
  if (!this.#closePromise) {
49216
- this.#importAbort.abort();
49217
49355
  this.#inspectionCache.clear();
49218
49356
  this.#closePromise = Promise.all([
49219
- ...this.#importRequests,
49357
+ this.#importScope.close(),
49220
49358
  ...[...this.#inspectors].map((inspector) => inspector.close()),
49221
49359
  ...[...this.#sessions].map((session) => session.close()),
49222
49360
  ...this.#inspectionInFlight.values()
@@ -49281,6 +49419,7 @@ function createClaudeInstallation(environment, command) {
49281
49419
  updateAvailable: newerInstallationVersion(currentVersion, latestVersion),
49282
49420
  canUpdate,
49283
49421
  ...!canUpdate ? {
49422
+ messageCode: blocked ? "claude-policy-restricted" : "original-installer",
49284
49423
  message: blocked ? "Claude updates are restricted by the installation's settings or policy." : "Use the original installer or package manager for this Claude installation."
49285
49424
  } : {}
49286
49425
  };
@@ -49382,7 +49521,13 @@ async function createHarnessAdapter(context) {
49382
49521
  return Object.assign(new ClaudeCodeAdapter({
49383
49522
  ...environment[CLAUDE_CODE_COMMAND_ENV] ? { command: environment[CLAUDE_CODE_COMMAND_ENV] } : {},
49384
49523
  environment
49385
- }), { installation: createClaudeInstallation(environment, environment[CLAUDE_CODE_COMMAND_ENV]) });
49524
+ }), {
49525
+ installation: createClaudeInstallation(environment, environment[CLAUDE_CODE_COMMAND_ENV]),
49526
+ install: createHarnessInstaller(environment, {
49527
+ posix: "https://claude.ai/install.sh",
49528
+ windows: "https://claude.ai/install.ps1"
49529
+ })
49530
+ });
49386
49531
  }
49387
49532
  async function warmup(adapter) {
49388
49533
  try {