@karlorz/codexhost-cli-win32-arm64 0.13.3-0 → 0.13.3-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.
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 @karlorz/codexhost-cli@0.13.3-0
10
+ npm install -g @karlorz/codexhost-cli@0.13.3-1
11
11
  ```
12
12
 
13
13
  Do not install this package directly. npm selects it through the optional dependencies of `@karlorz/codexhost-cli`.
@@ -1 +1 @@
1
- {"schemaVersion":1,"version":"0.13.3-0","distribution":"npm","target":"windows-arm64"}
1
+ {"schemaVersion":1,"version":"0.13.3-1","distribution":"npm","target":"windows-arm64"}
@@ -18856,6 +18856,7 @@ th[aria-sort] .console-usage-sort__mark {
18856
18856
  "Codex Desktop installation discovered": "findDesktop",
18857
18857
  "acquiring Launcher ownership": "ownership",
18858
18858
  "Launcher ownership acquired": "ownership",
18859
+ "recovering leftover Desktop Controller": "ownership",
18859
18860
  "attached to existing controlled Desktop": "ownership",
18860
18861
  "launching Codex Desktop": "launchDesktop",
18861
18862
  "Codex Desktop launched": "launchDesktop",
@@ -3227,7 +3227,7 @@ var require_stream = __commonJS({
3227
3227
  };
3228
3228
  duplex._final = function(callback) {
3229
3229
  if (ws.readyState === ws.CONNECTING) {
3230
- ws.once("open", function open13() {
3230
+ ws.once("open", function open12() {
3231
3231
  duplex._final(callback);
3232
3232
  });
3233
3233
  return;
@@ -3248,7 +3248,7 @@ var require_stream = __commonJS({
3248
3248
  };
3249
3249
  duplex._write = function(chunk, encoding, callback) {
3250
3250
  if (ws.readyState === ws.CONNECTING) {
3251
- ws.once("open", function open13() {
3251
+ ws.once("open", function open12() {
3252
3252
  duplex._write(chunk, encoding, callback);
3253
3253
  });
3254
3254
  return;
@@ -21781,7 +21781,7 @@ function isLocalPageUrl(value2) {
21781
21781
  return false;
21782
21782
  }
21783
21783
  }
21784
- async function serveLocalPage(socket, url2, open13) {
21784
+ async function serveLocalPage(socket, url2, open12) {
21785
21785
  let page;
21786
21786
  let buffer = "";
21787
21787
  let operation = Promise.resolve();
@@ -21815,7 +21815,7 @@ async function serveLocalPage(socket, url2, open13) {
21815
21815
  }
21816
21816
  };
21817
21817
  try {
21818
- page = await open13(url2);
21818
+ page = await open12(url2);
21819
21819
  if (socket.destroyed)
21820
21820
  return;
21821
21821
  socket.on("data", receive);
@@ -26022,7 +26022,7 @@ async function atomicWrite(filePath, content) {
26022
26022
  }
26023
26023
  async function installDelegationSkills(input = {}) {
26024
26024
  const home = input.homeDirectory ?? os6.homedir();
26025
- const destinations = [
26025
+ const destinations2 = [
26026
26026
  path17.join(home, ".agents", SKILL_RELATIVE_PATH),
26027
26027
  path17.join(home, ".claude", SKILL_RELATIVE_PATH)
26028
26028
  ];
@@ -26032,7 +26032,7 @@ async function installDelegationSkills(input = {}) {
26032
26032
  ...input.previousManagedDigests ?? []
26033
26033
  ]);
26034
26034
  const results = [];
26035
- for (const destination of destinations) {
26035
+ for (const destination of destinations2) {
26036
26036
  const current = await readOptional(destination);
26037
26037
  if (current === CODEXHOST_DELEGATION_SKILL) {
26038
26038
  results.push({
@@ -42448,9 +42448,9 @@ var AppServerHost = class {
42448
42448
  */
42449
42449
  #withOpenBackgroundCommands(thread, turns) {
42450
42450
  return turns.map((turn) => {
42451
- const open13 = thread.projectedTurns.get(turn.id)?.projector.openDetachedWireItems();
42452
- if (!open13 || open13.size === 0) return turn;
42453
- const remaining = new Map(open13);
42451
+ const open12 = thread.projectedTurns.get(turn.id)?.projector.openDetachedWireItems();
42452
+ if (!open12 || open12.size === 0) return turn;
42453
+ const remaining = new Map(open12);
42454
42454
  const items = turn.items.map((item) => {
42455
42455
  const id2 = item.id;
42456
42456
  const live = remaining.get(id2);
@@ -45430,62 +45430,24 @@ async function startDelegationControlServer(input) {
45430
45430
  }
45431
45431
 
45432
45432
  // packages/host-runtime/src/codexhost-desktop-rule.ts
45433
- import { createHash as createHash11, randomUUID as randomUUID18 } from "node:crypto";
45434
- import { mkdir as mkdir15, open as open10, readFile as readFile18, rename as rename12, rm as rm14, stat as stat8 } from "node:fs/promises";
45433
+ import { createHash as createHash11 } from "node:crypto";
45434
+ import { readFile as readFile18, rm as rm14 } from "node:fs/promises";
45435
45435
  import os10 from "node:os";
45436
45436
  import path33 from "node:path";
45437
- var RULE_VERSION = 3;
45438
45437
  var RULE_FILE = "codexhost-desktop.md";
45439
- var PREVIOUS_MANAGED_DIGESTS2 = [
45438
+ var MANAGED_DIGESTS = [
45440
45439
  "5add2d2c7ea03ecbb3552b94e47da7a755909e63f30714878a5609a4e272526f",
45441
- "9d8d2762b5f90e6f10a6571651b3461dec882bd45b40f0f0debc432f4833301b"
45440
+ "9d8d2762b5f90e6f10a6571651b3461dec882bd45b40f0f0debc432f4833301b",
45441
+ "4658e68f312686e2134cd282abd9ce434d2583b0a1d23c7c3eb8bd7ec9b76cf3"
45442
45442
  ];
45443
- var CODEXHOST_DESKTOP_RULE = `<!-- codexhost-desktop-rule: ${RULE_VERSION} -->
45444
- # Codex Desktop / CodexHost
45445
-
45446
- CodexHost installs this file into Grok home rules. Orca and Grok TUI sessions may also load it.
45447
-
45448
- At the first user turn, if you have a shell, run this once and print only \`set\` or \`unset\`:
45449
-
45450
- \`\`\`sh
45451
- if test -n "\${CODEXHOST_THREAD_ID-}"; then echo set; else echo unset; fi
45452
- \`\`\`
45453
-
45454
- - \`set\`: this is a CodexHost external Thread, including Codex Desktop. Apply the session rules even when cwd is a real repository such as \`codex-host\` or the wiki.
45455
- - Working directory is a Playground folder named \`realtime-voice-chat\` or \`realtime-voice-chat-*\`: apply the session rules and ask the user to start a new Thread in the real repo.
45456
- - \`unset\` and not a Playground voice cwd: leave the session rules inactive.
45457
-
45458
- Never print \`CODEXHOST_THREAD_ID\`, \`CODEXHOST_RUNTIME_TOKEN\`, \`CODEXHOST_RUNTIME_ENDPOINT\`, or other runtime descriptors. Do not invent other host signals.
45459
-
45460
- ## Session rules
45461
-
45462
- 1. **Model.** The Desktop composer Model is this Harness's Model. Pick that Harness's real Model before starting voice. For Grok, that is grok-4.6 or grok-4.7. \`flash-max\` is a Gemini Flash Model.
45463
-
45464
- 2. **Working directory.** Start the chat in the real repository (\`codex-host\` or the wiki). A Playground \`realtime-voice-chat*\` folder is a scratch cwd. Ask the user to start a new Thread in the real repo.
45465
-
45466
- 3. **Voice vs tools.** Desktop voice is gpt-live speech plus delegated Harness tasks on this same Thread. Do wiki, MCP, and file-heavy work as text in this Thread.
45467
-
45468
- 4. **Harness-owned tools.** This session's MCP servers and skills belong to this Harness. SkillWiki on Grok is Grok's config, not Claude, Pi, or Codex.
45469
-
45470
- 5. **Desktop chrome.** The window is Codex Desktop. Markdown View preview is a Codex file tab (View preview vs View source). \`file://\` browser tabs stay raw.
45471
-
45472
- 6. **Voice routes.** Official Codex live voice (New API/CPA) is a separate route from Host-owned external \`thread/realtime/*\`. This external Thread uses the Host-owned route.
45473
-
45474
- Keep Grok Build tools, MCP, and rules inside the native session. An \`AGENT_TOOLS_AND_RULES.md\` dump in the cwd is unnecessary.
45475
- `;
45476
- var CURRENT_DIGEST2 = createHash11("sha256").update(CODEXHOST_DESKTOP_RULE).digest("hex");
45477
45443
  function digest2(value2) {
45478
45444
  return createHash11("sha256").update(value2).digest("hex");
45479
45445
  }
45480
- function managedVersion2(value2) {
45481
- const match = /codexhost-desktop-rule:\s*(\d+)/u.exec(value2);
45482
- return match ? Number(match[1]) : null;
45483
- }
45484
- function grokDestination(home) {
45485
- return path33.join(home, ".grok", "rules", RULE_FILE);
45486
- }
45487
- function claudeDestination(home) {
45488
- return path33.join(home, ".claude", "rules", RULE_FILE);
45446
+ function destinations(home) {
45447
+ return [
45448
+ path33.join(home, ".grok", "rules", RULE_FILE),
45449
+ path33.join(home, ".claude", "rules", RULE_FILE)
45450
+ ];
45489
45451
  }
45490
45452
  async function readOptional2(filePath) {
45491
45453
  try {
@@ -45495,81 +45457,23 @@ async function readOptional2(filePath) {
45495
45457
  throw error51;
45496
45458
  }
45497
45459
  }
45498
- async function atomicWrite2(filePath, content) {
45499
- await mkdir15(path33.dirname(filePath), { recursive: true, mode: 448 });
45500
- const temporaryPath = path33.join(path33.dirname(filePath), `.${RULE_FILE}.${randomUUID18()}.tmp`);
45501
- const handle = await open10(temporaryPath, "wx", 384);
45502
- try {
45503
- await handle.writeFile(content, "utf8");
45504
- await handle.sync();
45505
- } finally {
45506
- await handle.close();
45507
- }
45508
- try {
45509
- await rename12(temporaryPath, filePath);
45510
- } finally {
45511
- await rm14(temporaryPath, { force: true });
45512
- }
45513
- }
45514
- async function installCodexhostDesktopRules(input = {}) {
45460
+ async function retireCodexhostDesktopRules(input = {}) {
45515
45461
  const home = input.homeDirectory ?? os10.homedir();
45516
- const knownDigests = /* @__PURE__ */ new Set([
45517
- CURRENT_DIGEST2,
45518
- ...PREVIOUS_MANAGED_DIGESTS2,
45519
- ...input.previousManagedDigests ?? []
45520
- ]);
45462
+ const knownDigests = /* @__PURE__ */ new Set([...MANAGED_DIGESTS, ...input.previousManagedDigests ?? []]);
45521
45463
  const results = [];
45522
- const destination = grokDestination(home);
45523
- const current = await readOptional2(destination);
45524
- if (current === CODEXHOST_DESKTOP_RULE) {
45525
- results.push({
45526
- path: destination,
45527
- status: "current",
45528
- version: RULE_VERSION,
45529
- digest: CURRENT_DIGEST2
45530
- });
45531
- } else if (current !== null) {
45464
+ for (const destination of destinations(home)) {
45465
+ const current = await readOptional2(destination);
45466
+ if (current === null) {
45467
+ results.push({ path: destination, status: "absent", digest: null });
45468
+ continue;
45469
+ }
45532
45470
  const currentDigest = digest2(current);
45533
- const version2 = managedVersion2(current);
45534
45471
  if (!knownDigests.has(currentDigest)) {
45535
- results.push({ path: destination, status: "conflict", version: version2, digest: currentDigest });
45536
- } else {
45537
- await atomicWrite2(destination, CODEXHOST_DESKTOP_RULE);
45538
- results.push({
45539
- path: destination,
45540
- status: "updated",
45541
- version: RULE_VERSION,
45542
- digest: CURRENT_DIGEST2
45543
- });
45544
- }
45545
- } else {
45546
- await atomicWrite2(destination, CODEXHOST_DESKTOP_RULE);
45547
- results.push({
45548
- path: destination,
45549
- status: "installed",
45550
- version: RULE_VERSION,
45551
- digest: CURRENT_DIGEST2
45552
- });
45553
- }
45554
- const claude = claudeDestination(home);
45555
- const claudeCurrent = await readOptional2(claude);
45556
- if (claudeCurrent !== null) {
45557
- const claudeDigest = digest2(claudeCurrent);
45558
- const version2 = managedVersion2(claudeCurrent);
45559
- if (knownDigests.has(claudeDigest) || claudeCurrent === CODEXHOST_DESKTOP_RULE) {
45560
- await rm14(claude, { force: true });
45561
- results.push({ path: claude, status: "removed", version: version2, digest: claudeDigest });
45562
- } else {
45563
- results.push({ path: claude, status: "conflict", version: version2, digest: claudeDigest });
45564
- }
45565
- }
45566
- for (const result of results) {
45567
- if (result.status === "conflict" || result.status === "removed") continue;
45568
- const source = await readFile18(result.path, "utf8");
45569
- const metadata = await stat8(result.path);
45570
- if (!metadata.isFile() || source !== CODEXHOST_DESKTOP_RULE) {
45571
- throw new Error(`Codex Desktop rule verification failed: ${result.path}`);
45472
+ results.push({ path: destination, status: "conflict", digest: currentDigest });
45473
+ continue;
45572
45474
  }
45475
+ await rm14(destination, { force: true });
45476
+ results.push({ path: destination, status: "removed", digest: currentDigest });
45573
45477
  }
45574
45478
  return results;
45575
45479
  }
@@ -45621,11 +45525,11 @@ async function readRemoteDelegationThread(environment, input) {
45621
45525
  }
45622
45526
 
45623
45527
  // packages/host-runtime/src/shared-thread-owner.ts
45624
- import { randomUUID as randomUUID20 } from "node:crypto";
45528
+ import { randomUUID as randomUUID19 } from "node:crypto";
45625
45529
  import { PassThrough as PassThrough3 } from "node:stream";
45626
45530
 
45627
45531
  // packages/host-runtime/src/shared-thread-peer.ts
45628
- import { randomUUID as randomUUID19 } from "node:crypto";
45532
+ import { randomUUID as randomUUID18 } from "node:crypto";
45629
45533
  function object7(value2) {
45630
45534
  return value2 !== null && typeof value2 === "object" && !Array.isArray(value2);
45631
45535
  }
@@ -45639,7 +45543,7 @@ var StreamThreadPeer = class {
45639
45543
  input;
45640
45544
  output;
45641
45545
  stop;
45642
- #prefix = `shared:${randomUUID19()}:`;
45546
+ #prefix = `shared:${randomUUID18()}:`;
45643
45547
  #pending = /* @__PURE__ */ new Map();
45644
45548
  #listeners = /* @__PURE__ */ new Set();
45645
45549
  #ended = Promise.withResolvers();
@@ -45717,7 +45621,7 @@ var SharedThreadOwner = class {
45717
45621
  input = new PassThrough3();
45718
45622
  output = new PassThrough3();
45719
45623
  #peer = new StreamThreadPeer(this.output, this.input, () => this.input.end());
45720
- #prefix = `shared-interaction:${randomUUID20()}:`;
45624
+ #prefix = `shared-interaction:${randomUUID19()}:`;
45721
45625
  #interactions = /* @__PURE__ */ new Map();
45722
45626
  #listeners = /* @__PURE__ */ new Set();
45723
45627
  #receipts = /* @__PURE__ */ new Map();
@@ -46027,8 +45931,8 @@ var SharedThreadBridge = class {
46027
45931
  };
46028
45932
 
46029
45933
  // packages/host-runtime/src/remote-control-app-server.ts
46030
- import { randomUUID as randomUUID21 } from "node:crypto";
46031
- import { mkdir as mkdir16, open as open11, rename as rename13, rm as rm15 } from "node:fs/promises";
45934
+ import { randomUUID as randomUUID20 } from "node:crypto";
45935
+ import { mkdir as mkdir15, open as open10, rename as rename12, rm as rm15 } from "node:fs/promises";
46032
45936
  import path35 from "node:path";
46033
45937
  var REMOTE_CONTROL_BRIDGE_PIPE_ENV = "CODEXHOST_REMOTE_CONTROL_BRIDGE_PIPE";
46034
45938
  var REMOTE_CONTROL_BRIDGE_NODE_ENV = "CODEXHOST_REMOTE_CONTROL_BRIDGE_NODE_PATH";
@@ -46048,7 +45952,7 @@ function nodeCompatibleWindowsPath(value2) {
46048
45952
  if (value2.startsWith("\\\\?\\")) return value2.slice(4);
46049
45953
  return value2;
46050
45954
  }
46051
- function remoteControlBridgePipePath(processId = process.pid, instanceId = randomUUID21()) {
45955
+ function remoteControlBridgePipePath(processId = process.pid, instanceId = randomUUID20()) {
46052
45956
  const safeInstance = instanceId.replaceAll(/[^a-zA-Z0-9-]/gu, "");
46053
45957
  if (!safeInstance) throw new Error("Remote Control bridge instance ID is invalid");
46054
45958
  return `\\\\.\\pipe\\codexhost-remote-control-${processId}-${safeInstance}`;
@@ -46060,12 +45964,12 @@ function remoteControlBridgeDescriptorPath(environment) {
46060
45964
  }
46061
45965
  async function publishRemoteControlAppServerDescriptor(plan) {
46062
45966
  const directory = path35.dirname(plan.descriptorPath);
46063
- await mkdir16(directory, { recursive: true, mode: 448 });
45967
+ await mkdir15(directory, { recursive: true, mode: 448 });
46064
45968
  const temporaryPath = path35.join(
46065
45969
  directory,
46066
- `.${REMOTE_CONTROL_BRIDGE_DESCRIPTOR_FILE}.${plan.descriptor.ownerPid}.${randomUUID21()}.tmp`
45970
+ `.${REMOTE_CONTROL_BRIDGE_DESCRIPTOR_FILE}.${plan.descriptor.ownerPid}.${randomUUID20()}.tmp`
46067
45971
  );
46068
- const handle = await open11(temporaryPath, "wx", 384);
45972
+ const handle = await open10(temporaryPath, "wx", 384);
46069
45973
  try {
46070
45974
  await handle.writeFile(`${JSON.stringify(plan.descriptor)}
46071
45975
  `, "utf8");
@@ -46074,7 +45978,7 @@ async function publishRemoteControlAppServerDescriptor(plan) {
46074
45978
  await handle.close();
46075
45979
  }
46076
45980
  try {
46077
- await rename13(temporaryPath, plan.descriptorPath);
45981
+ await rename12(temporaryPath, plan.descriptorPath);
46078
45982
  } finally {
46079
45983
  await rm15(temporaryPath, { force: true });
46080
45984
  }
@@ -46188,7 +46092,7 @@ function watchRemoteListenerSupervisor(options2) {
46188
46092
 
46189
46093
  // packages/host-runtime/src/console-control-server.ts
46190
46094
  import { randomBytes as randomBytes3, timingSafeEqual } from "node:crypto";
46191
- import { mkdir as mkdir17, rename as rename14, rm as rm16, writeFile as writeFile9 } from "node:fs/promises";
46095
+ import { mkdir as mkdir16, rename as rename13, rm as rm16, writeFile as writeFile9 } from "node:fs/promises";
46192
46096
  import { createServer as createServer4 } from "node:http";
46193
46097
  import os11 from "node:os";
46194
46098
  import path36 from "node:path";
@@ -46226,12 +46130,12 @@ function reply(response, status2, value2) {
46226
46130
  response.end(body);
46227
46131
  }
46228
46132
  async function writePrivateJson2(filePath, value2) {
46229
- await mkdir17(path36.dirname(filePath), { recursive: true, mode: 448 });
46133
+ await mkdir16(path36.dirname(filePath), { recursive: true, mode: 448 });
46230
46134
  const temporary = `${filePath}.${randomBytes3(6).toString("hex")}.tmp`;
46231
46135
  try {
46232
46136
  await writeFile9(temporary, `${JSON.stringify(value2)}
46233
46137
  `, { mode: 384, flag: "wx" });
46234
- await rename14(temporary, filePath);
46138
+ await rename13(temporary, filePath);
46235
46139
  } finally {
46236
46140
  await rm16(temporary, { force: true });
46237
46141
  }
@@ -46585,8 +46489,8 @@ function createHostUpdateCoordinator(options2) {
46585
46489
  }
46586
46490
 
46587
46491
  // packages/host-runtime/src/usage-statistics.ts
46588
- import { randomUUID as randomUUID22 } from "node:crypto";
46589
- import { mkdir as mkdir18, readFile as readFile19, readdir as readdir6, rename as rename15, rm as rm17, writeFile as writeFile10 } from "node:fs/promises";
46492
+ import { randomUUID as randomUUID21 } from "node:crypto";
46493
+ import { mkdir as mkdir17, readFile as readFile19, readdir as readdir6, rename as rename14, rm as rm17, writeFile as writeFile10 } from "node:fs/promises";
46590
46494
  import path38 from "node:path";
46591
46495
  import { setImmediate as yieldToEventLoop } from "node:timers/promises";
46592
46496
 
@@ -47028,16 +46932,16 @@ var UsageStatistics = class {
47028
46932
  async #persist(harness2, cache) {
47029
46933
  if (!cache.dirty || this.#now() - cache.persistedAtMs < PERSIST_INTERVAL_MS) return;
47030
46934
  const file2 = this.#file(harness2);
47031
- const temporary = `${file2}.${randomUUID22()}.tmp`;
46935
+ const temporary = `${file2}.${randomUUID21()}.tmp`;
47032
46936
  try {
47033
- await mkdir18(this.#directory, { recursive: true });
46937
+ await mkdir17(this.#directory, { recursive: true });
47034
46938
  const sources = [...cache.sources].map(([id2, source]) => [
47035
46939
  id2,
47036
46940
  source.fingerprint,
47037
46941
  source.entries.map(compact)
47038
46942
  ]);
47039
46943
  await writeFile10(temporary, JSON.stringify({ version: CACHE_VERSION, sources }));
47040
- await rename15(temporary, file2);
46944
+ await rename14(temporary, file2);
47041
46945
  cache.dirty = false;
47042
46946
  cache.persistedAtMs = this.#now();
47043
46947
  } catch (error51) {
@@ -47334,7 +47238,7 @@ async function prepareDelegationRuntime(input) {
47334
47238
  [DELEGATION_RUNTIME_TOKEN_ENV]: token
47335
47239
  };
47336
47240
  await installManagedHomeFiles(installDelegationSkills, "delegation Skill");
47337
- await installManagedHomeFiles(installCodexhostDesktopRules, "Desktop rule");
47241
+ await installManagedHomeFiles(retireCodexhostDesktopRules, "Desktop rule retirement");
47338
47242
  try {
47339
47243
  return await input.createHost(environment, (value2) => registry2.register(value2), registry2);
47340
47244
  } finally {
@@ -47649,19 +47553,19 @@ async function runHostRuntime(input) {
47649
47553
  }
47650
47554
 
47651
47555
  // packages/host-runtime/src/remote-host-install.ts
47652
- import { createHash as createHash12, randomUUID as randomUUID23 } from "node:crypto";
47556
+ import { createHash as createHash12, randomUUID as randomUUID22 } from "node:crypto";
47653
47557
  import { constants as fsConstants } from "node:fs";
47654
47558
  import {
47655
47559
  access as access3,
47656
47560
  chmod as chmod5,
47657
47561
  copyFile as copyFile4,
47658
47562
  lstat as lstat9,
47659
- mkdir as mkdir19,
47563
+ mkdir as mkdir18,
47660
47564
  readFile as readFile20,
47661
- rename as rename16,
47565
+ rename as rename15,
47662
47566
  rm as rm18,
47663
47567
  rmdir,
47664
- stat as stat9,
47568
+ stat as stat8,
47665
47569
  writeFile as writeFile11
47666
47570
  } from "node:fs/promises";
47667
47571
  import path40 from "node:path";
@@ -47714,7 +47618,7 @@ async function fileSha256(filePath) {
47714
47618
  async function executable(filePath, label) {
47715
47619
  const absolute = path40.resolve(filePath);
47716
47620
  try {
47717
- if (!(await stat9(absolute)).isFile()) throw new Error("not a regular file");
47621
+ if (!(await stat8(absolute)).isFile()) throw new Error("not a regular file");
47718
47622
  await access3(absolute, fsConstants.X_OK);
47719
47623
  } catch {
47720
47624
  throw new Error(`${label} is not an executable file: ${absolute}`);
@@ -47724,7 +47628,7 @@ async function executable(filePath, label) {
47724
47628
  async function existingFile(filePath, label) {
47725
47629
  const absolute = path40.resolve(filePath);
47726
47630
  try {
47727
- const metadata = await stat9(absolute);
47631
+ const metadata = await stat8(absolute);
47728
47632
  if (!metadata.isFile()) throw new Error("not a regular file");
47729
47633
  } catch {
47730
47634
  throw new Error(`${label} is not a regular file: ${absolute}`);
@@ -47745,10 +47649,10 @@ async function discoverExecutable(name, environment) {
47745
47649
  return null;
47746
47650
  }
47747
47651
  async function writeAtomic(filePath, contents, mode) {
47748
- await mkdir19(path40.dirname(filePath), { recursive: true, mode: 448 });
47652
+ await mkdir18(path40.dirname(filePath), { recursive: true, mode: 448 });
47749
47653
  const temporary = path40.join(
47750
47654
  path40.dirname(filePath),
47751
- `.${path40.basename(filePath)}.${process.pid}.${randomUUID23()}.tmp`
47655
+ `.${path40.basename(filePath)}.${process.pid}.${randomUUID22()}.tmp`
47752
47656
  );
47753
47657
  try {
47754
47658
  if (typeof contents === "string") {
@@ -47758,31 +47662,31 @@ async function writeAtomic(filePath, contents, mode) {
47758
47662
  }
47759
47663
  await chmod5(temporary, mode);
47760
47664
  try {
47761
- await rename16(temporary, filePath);
47665
+ await rename15(temporary, filePath);
47762
47666
  } catch (error51) {
47763
47667
  if (process.platform !== "win32") throw error51;
47764
47668
  await rm18(filePath, { force: true });
47765
- await rename16(temporary, filePath);
47669
+ await rename15(temporary, filePath);
47766
47670
  }
47767
47671
  } finally {
47768
47672
  await rm18(temporary, { force: true });
47769
47673
  }
47770
47674
  }
47771
47675
  async function writeAtomicExecutable(filePath, sourcePath) {
47772
- await mkdir19(path40.dirname(filePath), { recursive: true, mode: 448 });
47676
+ await mkdir18(path40.dirname(filePath), { recursive: true, mode: 448 });
47773
47677
  const temporary = path40.join(
47774
47678
  path40.dirname(filePath),
47775
- `.${path40.basename(filePath)}.${process.pid}.${randomUUID23()}.tmp`
47679
+ `.${path40.basename(filePath)}.${process.pid}.${randomUUID22()}.tmp`
47776
47680
  );
47777
47681
  try {
47778
47682
  await copyFile4(sourcePath, temporary);
47779
47683
  await chmod5(temporary, 448);
47780
47684
  try {
47781
- await rename16(temporary, filePath);
47685
+ await rename15(temporary, filePath);
47782
47686
  } catch (error51) {
47783
47687
  if (process.platform !== "win32") throw error51;
47784
47688
  await rm18(filePath, { force: true });
47785
- await rename16(temporary, filePath);
47689
+ await rename15(temporary, filePath);
47786
47690
  }
47787
47691
  } finally {
47788
47692
  await rm18(temporary, { force: true });
@@ -47906,7 +47810,7 @@ async function readManifest(filePath) {
47906
47810
  async function backupProfile(profilePath, contents, action) {
47907
47811
  const timestamp = (/* @__PURE__ */ new Date()).toISOString().replaceAll(/[-:.TZ]/gu, "");
47908
47812
  const backupPath = `${profilePath}.codexhost-${action}-${timestamp}.bak`;
47909
- const metadata = await stat9(profilePath).catch(() => null);
47813
+ const metadata = await stat8(profilePath).catch(() => null);
47910
47814
  await writeAtomic(backupPath, contents, metadata?.mode ?? 384);
47911
47815
  return backupPath;
47912
47816
  }
@@ -47920,7 +47824,7 @@ async function installRemoteHost(options2) {
47920
47824
  const previousManifest = await readManifest(paths.manifestPath);
47921
47825
  const previousManifestFile = previousManifest ? {
47922
47826
  contents: await readFile20(paths.manifestPath),
47923
- mode: (await stat9(paths.manifestPath)).mode & 511
47827
+ mode: (await stat8(paths.manifestPath)).mode & 511
47924
47828
  } : null;
47925
47829
  const existingEntrypoint = await lstat9(paths.wrapperPath).catch(
47926
47830
  (error51) => {
@@ -47976,14 +47880,14 @@ async function installRemoteHost(options2) {
47976
47880
  const existingProfile = existingProfileSource ?? "";
47977
47881
  const nextProfile = installManagedProfileBlock(existingProfile, manifest);
47978
47882
  const profileChanged = nextProfile !== existingProfile;
47979
- const profileMetadata = await stat9(profilePath).catch(() => null);
47883
+ const profileMetadata = await stat8(profilePath).catch(() => null);
47980
47884
  try {
47981
47885
  if (profileChanged) {
47982
47886
  const profileBackupPath = await backupProfile(profilePath, existingProfile, "install");
47983
47887
  manifest = { ...manifest, profileBackupPath };
47984
47888
  await writeAtomic(profilePath, nextProfile, profileMetadata?.mode ?? 384);
47985
47889
  }
47986
- await mkdir19(paths.dataDirectory, { recursive: true, mode: 448 });
47890
+ await mkdir18(paths.dataDirectory, { recursive: true, mode: 448 });
47987
47891
  await chmod5(paths.dataDirectory, 448);
47988
47892
  await writeAtomicExecutable(paths.wrapperPath, manifest.shimPath);
47989
47893
  manifest = { ...manifest, entrypointSha256: await fileSha256(paths.wrapperPath) };
@@ -48067,7 +47971,7 @@ async function inspectRemoteHostInstallation(options2) {
48067
47971
  if (!profileMatches && profileIssue === null)
48068
47972
  profileIssue = "shell profile does not configure the managed native entrypoint";
48069
47973
  if (profileIssue !== null) issues.push(profileIssue);
48070
- const dataDirectory = await stat9(manifest.dataDirectory).catch(() => null);
47974
+ const dataDirectory = await stat8(manifest.dataDirectory).catch(() => null);
48071
47975
  if (!dataDirectory?.isDirectory()) issues.push("remote Host data directory is unavailable");
48072
47976
  for (const [label, filePath, requiresExecutable] of [
48073
47977
  ["stock Codex", manifest.stockCodexPath, true],
@@ -48077,7 +47981,7 @@ async function inspectRemoteHostInstallation(options2) {
48077
47981
  ]) {
48078
47982
  try {
48079
47983
  if (requiresExecutable) await executable(filePath, label);
48080
- else if (!(await stat9(filePath)).isFile()) throw new Error("not a regular file");
47984
+ else if (!(await stat8(filePath)).isFile()) throw new Error("not a regular file");
48081
47985
  } catch {
48082
47986
  issues.push(`${label} is unavailable`);
48083
47987
  }
@@ -48106,7 +48010,7 @@ async function uninstallRemoteHost(options2) {
48106
48010
  const nextProfile = removeManagedProfileBlock(profile);
48107
48011
  if (nextProfile !== profile) {
48108
48012
  await backupProfile(manifest.profilePath, profile, "uninstall");
48109
- const metadata = await stat9(manifest.profilePath).catch(() => null);
48013
+ const metadata = await stat8(manifest.profilePath).catch(() => null);
48110
48014
  await writeAtomic(manifest.profilePath, nextProfile, metadata?.mode ?? 384);
48111
48015
  }
48112
48016
  await rm18(manifest.wrapperPath, { force: true });
@@ -48121,7 +48025,7 @@ async function uninstallRemoteHost(options2) {
48121
48025
 
48122
48026
  // packages/host-runtime/src/remote-host-lifecycle.ts
48123
48027
  import { spawn as spawn8 } from "node:child_process";
48124
- import { stat as stat10 } from "node:fs/promises";
48028
+ import { stat as stat9 } from "node:fs/promises";
48125
48029
  import net3 from "node:net";
48126
48030
  import path41 from "node:path";
48127
48031
  import { Duplex } from "node:stream";
@@ -48147,7 +48051,7 @@ function socketPathFor(environment) {
48147
48051
  return path41.join(codexHome, "app-server-control", "app-server-control.sock");
48148
48052
  }
48149
48053
  async function defaultSocketExists(socketPath) {
48150
- const metadata = await stat10(socketPath).catch((error51) => {
48054
+ const metadata = await stat9(socketPath).catch((error51) => {
48151
48055
  if (error51.code === "ENOENT") return null;
48152
48056
  throw error51;
48153
48057
  });
@@ -48854,8 +48758,8 @@ var harnessOutputSchema = external_exports.custom((value2) => {
48854
48758
  });
48855
48759
 
48856
48760
  // packages/harness-broker/dist/server.js
48857
- import { randomBytes as randomBytes5, randomUUID as randomUUID24 } from "node:crypto";
48858
- import { chmod as chmod6, lstat as lstat10, mkdir as mkdir20, open as open12, readFile as readFile21, rename as rename17, rm as rm19 } from "node:fs/promises";
48761
+ import { randomBytes as randomBytes5, randomUUID as randomUUID23 } from "node:crypto";
48762
+ import { chmod as chmod6, lstat as lstat10, mkdir as mkdir19, open as open11, readFile as readFile21, rename as rename16, rm as rm19 } from "node:fs/promises";
48859
48763
  import net4, {} from "node:net";
48860
48764
  import path43 from "node:path";
48861
48765
  function harnessError(message2, retryable = true) {
@@ -48868,7 +48772,7 @@ function nativeWriterKey(nativeSessionId) {
48868
48772
  return nativeSessionId;
48869
48773
  }
48870
48774
  async function privateDirectory(directory) {
48871
- await mkdir20(directory, { recursive: true, mode: 448 });
48775
+ await mkdir19(directory, { recursive: true, mode: 448 });
48872
48776
  if (process.platform === "win32")
48873
48777
  return;
48874
48778
  const metadata = await lstat10(directory);
@@ -48913,8 +48817,8 @@ async function assertNoLiveDescriptor(descriptorPath) {
48913
48817
  }
48914
48818
  }
48915
48819
  async function publishDescriptor(descriptorPath, descriptor) {
48916
- const temporary = `${descriptorPath}.${process.pid}.${randomUUID24()}.tmp`;
48917
- const handle = await open12(temporary, "wx", 384);
48820
+ const temporary = `${descriptorPath}.${process.pid}.${randomUUID23()}.tmp`;
48821
+ const handle = await open11(temporary, "wx", 384);
48918
48822
  try {
48919
48823
  await handle.writeFile(`${JSON.stringify(descriptor)}
48920
48824
  `, "utf8");
@@ -48922,7 +48826,7 @@ async function publishDescriptor(descriptorPath, descriptor) {
48922
48826
  } finally {
48923
48827
  await handle.close();
48924
48828
  }
48925
- await rename17(temporary, descriptorPath);
48829
+ await rename16(temporary, descriptorPath);
48926
48830
  if (process.platform !== "win32")
48927
48831
  await chmod6(descriptorPath, 384);
48928
48832
  }
@@ -48990,7 +48894,7 @@ async function startHarnessBrokerServer(input) {
48990
48894
  await assertNoLiveDescriptor(input.descriptorPath);
48991
48895
  if (process.platform !== "win32")
48992
48896
  await prepareUnixSocketPath(input.socketPath);
48993
- const generation = input.generation ?? randomUUID24();
48897
+ const generation = input.generation ?? randomUUID23();
48994
48898
  const token = input.token ?? randomBytes5(32).toString("hex");
48995
48899
  const descriptor = {
48996
48900
  schemaVersion: 1,
@@ -49031,7 +48935,7 @@ async function startHarnessBrokerServer(input) {
49031
48935
  };
49032
48936
  const server = net4.createServer((socket) => {
49033
48937
  const state = {
49034
- id: randomUUID24(),
48938
+ id: randomUUID23(),
49035
48939
  socket,
49036
48940
  authenticated: false,
49037
48941
  inputSequence: 0,
@@ -49269,7 +49173,7 @@ async function startHarnessBrokerServer(input) {
49269
49173
  }
49270
49174
  };
49271
49175
  }
49272
- const openReservation = randomUUID24();
49176
+ const openReservation = randomUUID23();
49273
49177
  if (sourceKey)
49274
49178
  nativeWriters.set(sourceKey, openReservation);
49275
49179
  const provisionalReservation = openInput.kind === "create" ? openReservation : void 0;
@@ -49570,7 +49474,7 @@ async function startHarnessBrokerServer(input) {
49570
49474
  }
49571
49475
  state.authenticated = true;
49572
49476
  state.inputSequence = 1;
49573
- await send({ kind: "response", id: randomUUID24(), ok: true, value: { ready: true } });
49477
+ await send({ kind: "response", id: randomUUID23(), ok: true, value: { ready: true } });
49574
49478
  return;
49575
49479
  }
49576
49480
  const parsed2 = harnessBrokerRequestSchema.safeParse(raw);
@@ -49826,7 +49730,7 @@ function installRuntimeLog(input) {
49826
49730
  let descriptor;
49827
49731
  let size = 0;
49828
49732
  let atLineStart = true;
49829
- const open13 = () => {
49733
+ const open12 = () => {
49830
49734
  descriptor = openSync(filePath, "a", 384);
49831
49735
  chmodSync(filePath, 384);
49832
49736
  size = fstatSync(descriptor).size;
@@ -49842,7 +49746,7 @@ function installRuntimeLog(input) {
49842
49746
  try {
49843
49747
  mkdirSync(logDirectory, { recursive: true, mode: 448 });
49844
49748
  chmodSync(logDirectory, 448);
49845
- open13();
49749
+ open12();
49846
49750
  try {
49847
49751
  chmodSync(`${filePath}.1`, 384);
49848
49752
  } catch (error51) {
@@ -49862,12 +49766,12 @@ function installRuntimeLog(input) {
49862
49766
  while (start < bytes.length && (bytes.readUInt8(start) & 192) === 128) start += 1;
49863
49767
  bytes = bytes.subarray(start);
49864
49768
  }
49865
- if (descriptor === void 0) open13();
49769
+ if (descriptor === void 0) open12();
49866
49770
  if (size > 0 && size + bytes.length > maxBytes) {
49867
49771
  close();
49868
49772
  rmSync(`${filePath}.1`, { force: true });
49869
49773
  renameSync(filePath, `${filePath}.1`);
49870
- open13();
49774
+ open12();
49871
49775
  prune();
49872
49776
  }
49873
49777
  if (descriptor === void 0) return;
@@ -23281,6 +23281,36 @@ function grokPermissionModeSessionMeta(permissionMode) {
23281
23281
  };
23282
23282
  }
23283
23283
 
23284
+ // dist/grok-codexhost-session-rules.js
23285
+ var GROK_CODEXHOST_SESSION_RULES = `# Codex Desktop / CodexHost
23286
+
23287
+ CodexHost started this Grok ACP session as an external Thread inside Codex Desktop.
23288
+
23289
+ Never print \`CODEXHOST_THREAD_ID\`, \`CODEXHOST_RUNTIME_TOKEN\`, \`CODEXHOST_RUNTIME_ENDPOINT\`, or other runtime descriptors.
23290
+
23291
+ ## Session rules
23292
+
23293
+ 1. **Model.** The Desktop composer Model is this Harness's Model. Pick that Harness's real Model before starting voice. For Grok, that is grok-4.6 or grok-4.7. \`flash-max\` is a Gemini Flash Model.
23294
+
23295
+ 2. **Working directory.** Start the chat in the real repository (\`codex-host\` or the wiki). A Playground \`realtime-voice-chat*\` folder is a scratch cwd. Ask the user to start a new Thread in the real repo.
23296
+
23297
+ 3. **Voice vs tools.** Desktop voice is gpt-live speech plus delegated Harness tasks on this same Thread. Do wiki, MCP, and file-heavy work as text in this Thread.
23298
+
23299
+ 4. **Harness-owned tools.** This session's MCP servers and skills belong to this Harness. SkillWiki on Grok is Grok's config, not Claude, Pi, or Codex.
23300
+
23301
+ 5. **Desktop chrome.** The window is Codex Desktop. Markdown View preview is a Codex file tab (View preview vs View source). \`file://\` browser tabs stay raw.
23302
+
23303
+ 6. **Voice routes.** Official Codex live voice (New API/CPA) is a separate route from Host-owned external \`thread/realtime/*\`. This external Thread uses the Host-owned route.
23304
+
23305
+ Keep Grok Build tools, MCP, and rules inside the native session. An \`AGENT_TOOLS_AND_RULES.md\` dump in the cwd is unnecessary.
23306
+ `;
23307
+ function grokCodexhostSessionMeta(permissionMode) {
23308
+ return {
23309
+ ...permissionMode ? grokPermissionModeSessionMeta(permissionMode) : {},
23310
+ rules: GROK_CODEXHOST_SESSION_RULES
23311
+ };
23312
+ }
23313
+
23284
23314
  // dist/acp-transport.js
23285
23315
  var GrokTransportError = class extends Error {
23286
23316
  kind;
@@ -23640,7 +23670,7 @@ var GrokAcpTransport = class {
23640
23670
  const created = await withTimeout(connection.newSession({
23641
23671
  cwd: this.#options.cwd,
23642
23672
  mcpServers: [],
23643
- _meta: grokPermissionModeSessionMeta(permissionMode)
23673
+ _meta: grokCodexhostSessionMeta(permissionMode)
23644
23674
  }), this.#options.commandTimeoutMs, "Grok Session creation");
23645
23675
  session = created;
23646
23676
  sessionId = created.sessionId;
@@ -23657,7 +23687,8 @@ var GrokAcpTransport = class {
23657
23687
  session = await withTimeout(connection.loadSession({
23658
23688
  cwd: this.#options.cwd,
23659
23689
  mcpServers: [],
23660
- sessionId: forked.newSessionId
23690
+ sessionId: forked.newSessionId,
23691
+ _meta: grokCodexhostSessionMeta()
23661
23692
  }), this.#options.commandTimeoutMs, "Grok Session load");
23662
23693
  } catch (error53) {
23663
23694
  throw new GrokTransportError("unavailable", `Grok Fork succeeded as ${forked.newSessionId} but session/load failed`, { cause: error53 });
@@ -23669,7 +23700,7 @@ var GrokAcpTransport = class {
23669
23700
  cwd: this.#options.cwd,
23670
23701
  mcpServers: [],
23671
23702
  sessionId: input.sessionId,
23672
- ...permissionMode ? { _meta: grokPermissionModeSessionMeta(permissionMode) } : {}
23703
+ _meta: grokCodexhostSessionMeta(permissionMode)
23673
23704
  }), this.#options.commandTimeoutMs, "Grok Session load");
23674
23705
  sessionId = input.sessionId;
23675
23706
  if (input.kind === "rewind") {
package/bin/codexhost.exe CHANGED
Binary file
Binary file
Binary file
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@karlorz/codexhost-cli-win32-arm64",
3
- "version": "0.13.3-0",
3
+ "version": "0.13.3-1",
4
4
  "description": "Run Pi and Claude Code as first-class external harnesses inside Codex Desktop.",
5
5
  "type": "module",
6
6
  "files": [