@liberseek/boft-cli-win32-arm64 0.7.1 → 0.7.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.
@@ -4283,7 +4283,7 @@ async function runDelegationCli(input) {
4283
4283
 
4284
4284
  // packages/host-runtime/src/run-host-runtime.ts
4285
4285
  import { randomBytes as randomBytes2 } from "node:crypto";
4286
- import path23 from "node:path";
4286
+ import path24 from "node:path";
4287
4287
  import { homedir as homedir2 } from "node:os";
4288
4288
  import { fileURLToPath as fileURLToPath2 } from "node:url";
4289
4289
 
@@ -5978,10 +5978,10 @@ function mergeDefs(...defs) {
5978
5978
  function cloneDef(schema) {
5979
5979
  return mergeDefs(schema._zod.def);
5980
5980
  }
5981
- function getElementAtPath(obj, path28) {
5982
- if (!path28)
5981
+ function getElementAtPath(obj, path29) {
5982
+ if (!path29)
5983
5983
  return obj;
5984
- return path28.reduce((acc, key) => acc?.[key], obj);
5984
+ return path29.reduce((acc, key) => acc?.[key], obj);
5985
5985
  }
5986
5986
  function promiseAllObject(promisesObj) {
5987
5987
  const keys = Object.keys(promisesObj);
@@ -6390,11 +6390,11 @@ function explicitlyAborted(x, startIndex = 0) {
6390
6390
  }
6391
6391
  return false;
6392
6392
  }
6393
- function prefixIssues(path28, issues) {
6393
+ function prefixIssues(path29, issues) {
6394
6394
  return issues.map((iss) => {
6395
6395
  var _a3;
6396
6396
  (_a3 = iss).path ?? (_a3.path = []);
6397
- iss.path.unshift(path28);
6397
+ iss.path.unshift(path29);
6398
6398
  return iss;
6399
6399
  });
6400
6400
  }
@@ -6541,16 +6541,16 @@ function flattenError(error51, mapper = (issue2) => issue2.message) {
6541
6541
  }
6542
6542
  function formatError(error51, mapper = (issue2) => issue2.message) {
6543
6543
  const fieldErrors = { _errors: [] };
6544
- const processError = (error52, path28 = []) => {
6544
+ const processError = (error52, path29 = []) => {
6545
6545
  for (const issue2 of error52.issues) {
6546
6546
  if (issue2.code === "invalid_union" && issue2.errors.length) {
6547
- issue2.errors.map((issues) => processError({ issues }, [...path28, ...issue2.path]));
6547
+ issue2.errors.map((issues) => processError({ issues }, [...path29, ...issue2.path]));
6548
6548
  } else if (issue2.code === "invalid_key") {
6549
- processError({ issues: issue2.issues }, [...path28, ...issue2.path]);
6549
+ processError({ issues: issue2.issues }, [...path29, ...issue2.path]);
6550
6550
  } else if (issue2.code === "invalid_element") {
6551
- processError({ issues: issue2.issues }, [...path28, ...issue2.path]);
6551
+ processError({ issues: issue2.issues }, [...path29, ...issue2.path]);
6552
6552
  } else {
6553
- const fullpath = [...path28, ...issue2.path];
6553
+ const fullpath = [...path29, ...issue2.path];
6554
6554
  if (fullpath.length === 0) {
6555
6555
  fieldErrors._errors.push(mapper(issue2));
6556
6556
  } else {
@@ -6577,17 +6577,17 @@ function formatError(error51, mapper = (issue2) => issue2.message) {
6577
6577
  }
6578
6578
  function treeifyError(error51, mapper = (issue2) => issue2.message) {
6579
6579
  const result = { errors: [] };
6580
- const processError = (error52, path28 = []) => {
6580
+ const processError = (error52, path29 = []) => {
6581
6581
  var _a3, _b;
6582
6582
  for (const issue2 of error52.issues) {
6583
6583
  if (issue2.code === "invalid_union" && issue2.errors.length) {
6584
- issue2.errors.map((issues) => processError({ issues }, [...path28, ...issue2.path]));
6584
+ issue2.errors.map((issues) => processError({ issues }, [...path29, ...issue2.path]));
6585
6585
  } else if (issue2.code === "invalid_key") {
6586
- processError({ issues: issue2.issues }, [...path28, ...issue2.path]);
6586
+ processError({ issues: issue2.issues }, [...path29, ...issue2.path]);
6587
6587
  } else if (issue2.code === "invalid_element") {
6588
- processError({ issues: issue2.issues }, [...path28, ...issue2.path]);
6588
+ processError({ issues: issue2.issues }, [...path29, ...issue2.path]);
6589
6589
  } else {
6590
- const fullpath = [...path28, ...issue2.path];
6590
+ const fullpath = [...path29, ...issue2.path];
6591
6591
  if (fullpath.length === 0) {
6592
6592
  result.errors.push(mapper(issue2));
6593
6593
  continue;
@@ -6619,8 +6619,8 @@ function treeifyError(error51, mapper = (issue2) => issue2.message) {
6619
6619
  }
6620
6620
  function toDotPath(_path) {
6621
6621
  const segs = [];
6622
- const path28 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
6623
- for (const seg of path28) {
6622
+ const path29 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
6623
+ for (const seg of path29) {
6624
6624
  if (typeof seg === "number")
6625
6625
  segs.push(`[${seg}]`);
6626
6626
  else if (typeof seg === "symbol")
@@ -19312,13 +19312,13 @@ function resolveRef(ref, ctx) {
19312
19312
  if (!ref.startsWith("#")) {
19313
19313
  throw new Error("External $ref is not supported, only local refs (#/...) are allowed");
19314
19314
  }
19315
- const path28 = ref.slice(1).split("/").filter(Boolean);
19316
- if (path28.length === 0) {
19315
+ const path29 = ref.slice(1).split("/").filter(Boolean);
19316
+ if (path29.length === 0) {
19317
19317
  return ctx.rootSchema;
19318
19318
  }
19319
19319
  const defsKey = ctx.version === "draft-2020-12" ? "$defs" : "definitions";
19320
- if (path28[0] === defsKey) {
19321
- const key = path28[1];
19320
+ if (path29[0] === defsKey) {
19321
+ const key = path29[1];
19322
19322
  if (!key || !ctx.defs[key]) {
19323
19323
  throw new Error(`Reference not found: ${ref}`);
19324
19324
  }
@@ -20546,10 +20546,21 @@ var harnessCommandDescriptorSchema = external_exports.object({
20546
20546
  invocation: commandInvocationSchema,
20547
20547
  label: commandLabelSchema,
20548
20548
  description: commandDescriptionSchema.optional(),
20549
- argumentMode: external_exports.enum(["none", "text"])
20549
+ argumentMode: external_exports.enum(["none", "text"]),
20550
+ /**
20551
+ * Native distinction reported by the Harness. Omitted when the Harness does
20552
+ * not tell skills and commands apart; consumers treat that as "command".
20553
+ */
20554
+ kind: external_exports.enum(["command", "skill"]).optional()
20550
20555
  }).strict();
20551
20556
  var harnessCommandCatalogSchema = external_exports.object({
20552
- commands: external_exports.array(harnessCommandDescriptorSchema)
20557
+ commands: external_exports.array(harnessCommandDescriptorSchema),
20558
+ /**
20559
+ * `live` when the catalog includes what a native Session reports for its
20560
+ * workspace (custom commands, skills); `static` for Adapter built-ins only.
20561
+ * Omitted by Adapters; set by the Host on inspection results.
20562
+ */
20563
+ source: external_exports.enum(["live", "static"]).optional()
20553
20564
  }).strict().superRefine((catalog, context) => {
20554
20565
  const ids = /* @__PURE__ */ new Set();
20555
20566
  for (const [index, command] of catalog.commands.entries()) {
@@ -20563,7 +20574,11 @@ var harnessCommandCatalogSchema = external_exports.object({
20563
20574
  ids.add(command.id);
20564
20575
  }
20565
20576
  });
20566
- var harnessCommandsInspectParamsSchema = external_exports.object({ harnessId: harnessIdSchema }).strict();
20577
+ var harnessCommandsInspectParamsSchema = external_exports.object({
20578
+ harnessId: harnessIdSchema,
20579
+ /** Workspace of a draft without a Thread, for its live catalog when known. */
20580
+ cwd: external_exports.string().min(1).optional()
20581
+ }).strict();
20567
20582
  var threadCommandsInspectParamsSchema = external_exports.object({
20568
20583
  threadId: hostThreadIdSchema
20569
20584
  }).strict();
@@ -20707,6 +20722,41 @@ var updateStatusResultSchema = external_exports.strictObject({
20707
20722
  status: updateStatusSchema.nullable()
20708
20723
  });
20709
20724
 
20725
+ // packages/shared-contracts/dist/delegation-mention.js
20726
+ var DELEGATION_MENTION_PATH_PREFIX = "subagent://codexhost.";
20727
+ var MENTION_LINK_PATTERN = /\[@([^\]\n]+)\]\(<?subagent:\/\/codexhost\.([a-z0-9][a-z0-9-]*)>?\)/gu;
20728
+ function stripDelegationMentions(text2) {
20729
+ const mentions = [];
20730
+ const seen = /* @__PURE__ */ new Set();
20731
+ const rewritten = text2.replace(MENTION_LINK_PATTERN, (_match, label, harnessId) => {
20732
+ const trimmed = label.trim();
20733
+ if (!seen.has(harnessId)) {
20734
+ seen.add(harnessId);
20735
+ mentions.push({ harnessId, label: trimmed });
20736
+ }
20737
+ return `@${trimmed}`;
20738
+ });
20739
+ return { text: rewritten, mentions };
20740
+ }
20741
+ var COMMAND_LINK_PATTERN = /([ \t]*)\[@([^\]\n]+)\]\(<?subagent:\/\/codexhost-command\.([^)\s>]+)>?\)([ \t]*)/gu;
20742
+ function restoreHarnessCommandMentions(text2) {
20743
+ let invocation = null;
20744
+ const rest = text2.replace(COMMAND_LINK_PATTERN, (match, before, _label, encoded, after) => {
20745
+ if (invocation === null) {
20746
+ try {
20747
+ invocation = `/${decodeURIComponent(encoded)}`;
20748
+ } catch {
20749
+ return match;
20750
+ }
20751
+ }
20752
+ return before || after ? " " : "";
20753
+ });
20754
+ if (invocation === null)
20755
+ return text2;
20756
+ const argumentsText = rest.trim();
20757
+ return argumentsText ? `${invocation} ${argumentsText}` : invocation;
20758
+ }
20759
+
20710
20760
  // packages/shared-contracts/dist/index.js
20711
20761
  var workspaceContractVersionSchema = external_exports.literal(WORKSPACE_CONTRACT_VERSION);
20712
20762
 
@@ -20801,6 +20851,232 @@ async function listOthers(adapter) {
20801
20851
  }
20802
20852
  }
20803
20853
 
20854
+ // packages/host-runtime/src/delegation-skill.ts
20855
+ import { createHash as createHash3, randomUUID as randomUUID2 } from "node:crypto";
20856
+ import { mkdir as mkdir3, open as open3, readFile as readFile5, rename as rename2, rm as rm3, stat } from "node:fs/promises";
20857
+ import os2 from "node:os";
20858
+ import path6 from "node:path";
20859
+ var SKILL_VERSION = 7;
20860
+ var DELEGATION_SKILL_NAME = "codexhost-delegation";
20861
+ var SKILL_RELATIVE_PATH = path6.join("skills", DELEGATION_SKILL_NAME, "SKILL.md");
20862
+ var PREVIOUS_MANAGED_DIGESTS = [
20863
+ "9d2f491850fb0b4084a31ba9b5e4a550b5e833747af322090d8ed0ff80b88c30",
20864
+ "2bb0aebb9b06febbc6c0c0bcdb0b32506c7cdbf8dc3b734cc6b2a86621270e4e",
20865
+ "aff258622dc8ff321f32b15620d081e578cb9c9ed1134d6a57f35ca8e7762c0a",
20866
+ "ba509f57e5448e796b3dfdd5031dcb08672eded50b61c0a54de84cfa02c49dd3",
20867
+ "d3ddf6db9bc5c5df825479c885bbbf0ca08da66f7057a12e02e1fdf57525149e",
20868
+ "15eb63519ff867e1536c97188a0c43738d7a49d38d4d6adeb7a1036726e7246d",
20869
+ "09acc3cc0a598e546ce35fccb9d856d9fe06c01ab055dfce1914dab92479c9a2"
20870
+ ];
20871
+ var CODEXHOST_DELEGATION_SKILL = `---
20872
+ name: codexhost-delegation
20873
+ version: ${SKILL_VERSION}
20874
+ description: >
20875
+ Delegate tasks to other coding agents, or read and follow up on existing
20876
+ external agent sessions. Use when the user asks another agent (including
20877
+ @agent) to independently perform a task, or asks to view a specified external
20878
+ session's content, progress, or results, send follow-up messages, wait, or
20879
+ cancel a task. Not for recapping the current conversation, discussing or
20880
+ configuring agents, or role-playing.
20881
+ ---
20882
+
20883
+ # Execute the task
20884
+
20885
+ Before acting, run:
20886
+
20887
+ \`boft delegate --help\`
20888
+
20889
+ Use CLI help as the authoritative source for commands and behavior. Consult
20890
+ command-specific help for options and the Harness listing command when the
20891
+ target is unknown. Prefer compact output when supported, and use its task links
20892
+ directly for subsequent commands.
20893
+
20894
+ Use the Harness native defaults. Inspect the target when a Model or Thinking
20895
+ selection is needed or the default is unavailable.
20896
+
20897
+ For a new delegation, create an independent child session and submit the
20898
+ requested task. For an existing external session, resolve the target from the
20899
+ user-provided session link, identifier, or context and operate on that Thread
20900
+ directly; it need not have been created by the current assistant. If the target
20901
+ is ambiguous, ask the user to identify it. Keep requests to view or summarize a
20902
+ session read-only.
20903
+
20904
+ For a new or existing task, choose the appropriate next action based on the
20905
+ user’s request and the task:
20906
+
20907
+ - send a follow-up message to the same Thread;
20908
+ - cancel its current Turn;
20909
+ - read its current state immediately;
20910
+ - wait for a bounded period;
20911
+ - check it again later;
20912
+ - leave it running in the background.
20913
+
20914
+ Report the result returned by read or a completed wait, together with the target
20915
+ agent, status, and a labeled task link. Keep internal tracking IDs in tool calls.
20916
+ `;
20917
+ var CURRENT_DIGEST = createHash3("sha256").update(CODEXHOST_DELEGATION_SKILL).digest("hex");
20918
+ function digest(value2) {
20919
+ return createHash3("sha256").update(value2).digest("hex");
20920
+ }
20921
+ function managedVersion(value2) {
20922
+ const match = /^version:\s*(\d+)\s*$/mu.exec(value2);
20923
+ return match ? Number(match[1]) : null;
20924
+ }
20925
+ async function readOptional(filePath) {
20926
+ try {
20927
+ return await readFile5(filePath, "utf8");
20928
+ } catch (error51) {
20929
+ if (error51.code === "ENOENT") return null;
20930
+ throw error51;
20931
+ }
20932
+ }
20933
+ async function atomicWrite(filePath, content) {
20934
+ await mkdir3(path6.dirname(filePath), { recursive: true, mode: 448 });
20935
+ const temporaryPath = path6.join(path6.dirname(filePath), `.SKILL.md.${randomUUID2()}.tmp`);
20936
+ const handle = await open3(temporaryPath, "wx", 384);
20937
+ try {
20938
+ await handle.writeFile(content, "utf8");
20939
+ await handle.sync();
20940
+ } finally {
20941
+ await handle.close();
20942
+ }
20943
+ try {
20944
+ await rename2(temporaryPath, filePath);
20945
+ } finally {
20946
+ await rm3(temporaryPath, { force: true });
20947
+ }
20948
+ }
20949
+ async function installDelegationSkills(input = {}) {
20950
+ const home = input.homeDirectory ?? os2.homedir();
20951
+ const destinations = [
20952
+ path6.join(home, ".agents", SKILL_RELATIVE_PATH),
20953
+ path6.join(home, ".claude", SKILL_RELATIVE_PATH)
20954
+ ];
20955
+ const knownDigests = /* @__PURE__ */ new Set([
20956
+ CURRENT_DIGEST,
20957
+ ...PREVIOUS_MANAGED_DIGESTS,
20958
+ ...input.previousManagedDigests ?? []
20959
+ ]);
20960
+ const results = [];
20961
+ for (const destination of destinations) {
20962
+ const current = await readOptional(destination);
20963
+ if (current === CODEXHOST_DELEGATION_SKILL) {
20964
+ results.push({
20965
+ path: destination,
20966
+ status: "current",
20967
+ version: SKILL_VERSION,
20968
+ digest: CURRENT_DIGEST
20969
+ });
20970
+ continue;
20971
+ }
20972
+ if (current !== null) {
20973
+ const currentDigest = digest(current);
20974
+ const version2 = managedVersion(current);
20975
+ if (!knownDigests.has(currentDigest)) {
20976
+ results.push({ path: destination, status: "conflict", version: version2, digest: currentDigest });
20977
+ continue;
20978
+ }
20979
+ await atomicWrite(destination, CODEXHOST_DELEGATION_SKILL);
20980
+ results.push({
20981
+ path: destination,
20982
+ status: "updated",
20983
+ version: SKILL_VERSION,
20984
+ digest: CURRENT_DIGEST
20985
+ });
20986
+ continue;
20987
+ }
20988
+ await atomicWrite(destination, CODEXHOST_DELEGATION_SKILL);
20989
+ results.push({
20990
+ path: destination,
20991
+ status: "installed",
20992
+ version: SKILL_VERSION,
20993
+ digest: CURRENT_DIGEST
20994
+ });
20995
+ }
20996
+ for (const result of results) {
20997
+ if (result.status === "conflict") continue;
20998
+ const source = await readFile5(result.path, "utf8");
20999
+ const metadata = await stat(result.path);
21000
+ if (!metadata.isFile() || source !== CODEXHOST_DELEGATION_SKILL) {
21001
+ throw new Error(`Delegation Skill verification failed: ${result.path}`);
21002
+ }
21003
+ }
21004
+ const managed = results.filter((result) => result.status !== "conflict");
21005
+ if (managed.some((result) => result.digest !== CURRENT_DIGEST)) {
21006
+ throw new Error("Delegation Skill copies are inconsistent");
21007
+ }
21008
+ if (results.every((result) => result.status !== "conflict")) {
21009
+ const copies = await Promise.all(results.map((result) => readFile5(result.path, "utf8")));
21010
+ if (copies.some((copy) => copy !== copies[0])) {
21011
+ throw new Error("Delegation Skill copies are inconsistent");
21012
+ }
21013
+ }
21014
+ return results;
21015
+ }
21016
+ async function managedDelegationSkillReference(input = {}) {
21017
+ const filePath = path6.join(input.homeDirectory ?? os2.homedir(), ".agents", SKILL_RELATIVE_PATH);
21018
+ try {
21019
+ return await readOptional(filePath) === CODEXHOST_DELEGATION_SKILL ? { name: DELEGATION_SKILL_NAME, path: filePath } : null;
21020
+ } catch {
21021
+ return null;
21022
+ }
21023
+ }
21024
+
21025
+ // packages/host-runtime/src/delegation-mention-rewrite.ts
21026
+ function describeTargets(mentions) {
21027
+ return mentions.map(({ harnessId, label }) => `@${label} (Harness \`${harnessId}\`)`).join(", ");
21028
+ }
21029
+ function delegationMentionInstruction(mentions) {
21030
+ const plural = mentions.length > 1;
21031
+ return [
21032
+ `[codexhost delegation] The user mentioned ${describeTargets(mentions)}.`,
21033
+ `Use the ${DELEGATION_SKILL_NAME} skill to delegate this request to ${plural ? "each mentioned Harness" : "that Harness"}`,
21034
+ "with `codexhost delegate start --harness <id>`, instead of doing the task yourself."
21035
+ ].join(" ");
21036
+ }
21037
+ function appendInstruction(text2, mentions) {
21038
+ const instruction = delegationMentionInstruction(mentions);
21039
+ return text2.trim().length === 0 ? instruction : `${text2}
21040
+
21041
+ ${instruction}`;
21042
+ }
21043
+ function rewriteDelegationMentionText(text2) {
21044
+ const { text: stripped, mentions } = stripDelegationMentions(text2);
21045
+ return mentions.length === 0 ? text2 : appendInstruction(stripped, mentions);
21046
+ }
21047
+ function isRecord(value2) {
21048
+ return typeof value2 === "object" && value2 !== null && !Array.isArray(value2);
21049
+ }
21050
+ function rewriteDelegationMentionInput(input, skill) {
21051
+ const mentions = [];
21052
+ const seen = /* @__PURE__ */ new Set();
21053
+ let lastTextIndex = -1;
21054
+ const rewritten = input.map((item, index) => {
21055
+ if (!isRecord(item) || item.type !== "text" || typeof item.text !== "string") return item;
21056
+ lastTextIndex = index;
21057
+ const result = stripDelegationMentions(item.text);
21058
+ for (const mention of result.mentions) {
21059
+ if (seen.has(mention.harnessId)) continue;
21060
+ seen.add(mention.harnessId);
21061
+ mentions.push(mention);
21062
+ }
21063
+ return result.mentions.length === 0 ? item : { ...item, text: result.text };
21064
+ });
21065
+ if (mentions.length === 0) return null;
21066
+ const target = rewritten[lastTextIndex];
21067
+ if (isRecord(target) && typeof target.text === "string") {
21068
+ rewritten[lastTextIndex] = {
21069
+ ...target,
21070
+ text: appendInstruction(target.text, mentions)
21071
+ };
21072
+ }
21073
+ const hasSkill = rewritten.some(
21074
+ (item) => isRecord(item) && item.type === "skill" && item.name === skill?.name
21075
+ );
21076
+ if (skill && !hasSkill) rewritten.push({ type: "skill", name: skill.name, path: skill.path });
21077
+ return rewritten;
21078
+ }
21079
+
20804
21080
  // packages/harness-adapter/dist/output-channel.js
20805
21081
  var HarnessOutputChannel = class {
20806
21082
  outputs;
@@ -20879,11 +21155,11 @@ var usageFields = /* @__PURE__ */ new Set([
20879
21155
  "totalCredits",
20880
21156
  "contextUsagePercent"
20881
21157
  ]);
20882
- function isRecord(value2) {
21158
+ function isRecord2(value2) {
20883
21159
  return typeof value2 === "object" && value2 !== null && !Array.isArray(value2);
20884
21160
  }
20885
21161
  function parseHostUsage(value2) {
20886
- if (!isRecord(value2))
21162
+ if (!isRecord2(value2))
20887
21163
  throw new Error("Harness Usage must be an object");
20888
21164
  const keys = Object.keys(value2);
20889
21165
  if (keys.length === 0)
@@ -20946,6 +21222,82 @@ function parseHostUsage(value2) {
20946
21222
  return { ...value2 };
20947
21223
  }
20948
21224
 
21225
+ // packages/harness-adapter/dist/live-command-catalog.js
21226
+ var COMMON_EXCLUDED_LIVE_COMMANDS = /* @__PURE__ */ new Set([
21227
+ // Session lifecycle
21228
+ "branch",
21229
+ "clear",
21230
+ "exit",
21231
+ "fork",
21232
+ "fresh",
21233
+ "new",
21234
+ "quit",
21235
+ "rename",
21236
+ "rename-chat",
21237
+ "reset",
21238
+ "resume",
21239
+ "rewind",
21240
+ "session",
21241
+ "sessions",
21242
+ // Desktop-owned configuration
21243
+ "autocompact",
21244
+ "color",
21245
+ "config",
21246
+ "effort",
21247
+ "fast",
21248
+ "keybindings",
21249
+ "model",
21250
+ "models",
21251
+ "output-style",
21252
+ "permissions",
21253
+ "settings",
21254
+ "statusline",
21255
+ "terminal-setup",
21256
+ "theme",
21257
+ "vim",
21258
+ // Trust and approval policy
21259
+ "always-approve",
21260
+ "auto-mode-setup",
21261
+ // Native login
21262
+ "login",
21263
+ "logout",
21264
+ // Work outliving the Turn
21265
+ "autopilot",
21266
+ "background",
21267
+ "bg",
21268
+ "goal",
21269
+ "jobs",
21270
+ "loop",
21271
+ "multitask",
21272
+ "queue",
21273
+ "remote-control",
21274
+ "schedule",
21275
+ "steer",
21276
+ // Native terminal UI
21277
+ "copy",
21278
+ "debug",
21279
+ "feedback",
21280
+ "heapdump",
21281
+ "share",
21282
+ "shell",
21283
+ // Plugin and MCP management
21284
+ "marketplace",
21285
+ "mcp",
21286
+ "plugins",
21287
+ "reload-plugins"
21288
+ ]);
21289
+ var COMMON_EXCLUDED_LIVE_COMMAND_PREFIXES = ["__", "hooks-"];
21290
+ function isExcludedLiveCommand(name, kind, extra = {}) {
21291
+ const normalized = name.trim().replace(/^\//u, "");
21292
+ if (new Set(extra.names ?? []).has(normalized))
21293
+ return true;
21294
+ if (extra.prefixes?.some((prefix) => normalized.startsWith(prefix)))
21295
+ return true;
21296
+ if (kind === "skill")
21297
+ return false;
21298
+ return COMMON_EXCLUDED_LIVE_COMMANDS.has(normalized) || COMMON_EXCLUDED_LIVE_COMMAND_PREFIXES.some((prefix) => normalized.startsWith(prefix));
21299
+ }
21300
+
20949
21301
  // packages/harness-adapter/dist/index.js
20950
21302
  var packageMetadata = {
20951
21303
  name: "@codexhost/harness-adapter",
@@ -20954,10 +21306,10 @@ var packageMetadata = {
20954
21306
 
20955
21307
  // packages/mapping-store/dist/mapping-store.js
20956
21308
  import { execFileSync } from "node:child_process";
20957
- import { randomUUID as randomUUID2 } from "node:crypto";
21309
+ import { randomUUID as randomUUID3 } from "node:crypto";
20958
21310
  import { constants } from "node:fs";
20959
- import { copyFile as copyFile2, mkdir as mkdir3, open as open3, readFile as readFile5, readdir as readdir2, rename as rename2, rm as rm3, stat } from "node:fs/promises";
20960
- import path6 from "node:path";
21311
+ import { copyFile as copyFile2, mkdir as mkdir4, open as open4, readFile as readFile6, readdir as readdir2, rename as rename3, rm as rm4, stat as stat2 } from "node:fs/promises";
21312
+ import path7 from "node:path";
20961
21313
 
20962
21314
  // packages/mapping-store/dist/records.js
20963
21315
  var nonBlankTextSchema6 = external_exports.string().refine((value2) => value2.trim().length > 0, {
@@ -21110,7 +21462,7 @@ function systemErrorCode2(error51) {
21110
21462
  }
21111
21463
  async function exists(file2) {
21112
21464
  try {
21113
- await stat(file2);
21465
+ await stat2(file2);
21114
21466
  return true;
21115
21467
  } catch (error51) {
21116
21468
  if (systemErrorCode2(error51) === "ENOENT")
@@ -21220,13 +21572,13 @@ var MappingStore = class {
21220
21572
  #initialized = false;
21221
21573
  #lockHandle = null;
21222
21574
  constructor(options2) {
21223
- this.#directory = path6.resolve(options2.directory);
21224
- this.#threadsDirectory = path6.join(this.#directory, "threads");
21225
- this.#delegationsDirectory = path6.join(this.#directory, "delegations");
21226
- this.#backupsDirectory = path6.join(this.#directory, "backups");
21227
- this.#quarantineDirectory = path6.join(this.#directory, "quarantine");
21228
- this.#lockPath = path6.join(this.#directory, "store.lock");
21229
- this.#instanceId = options2.instanceId ?? randomUUID2();
21575
+ this.#directory = path7.resolve(options2.directory);
21576
+ this.#threadsDirectory = path7.join(this.#directory, "threads");
21577
+ this.#delegationsDirectory = path7.join(this.#directory, "delegations");
21578
+ this.#backupsDirectory = path7.join(this.#directory, "backups");
21579
+ this.#quarantineDirectory = path7.join(this.#directory, "quarantine");
21580
+ this.#lockPath = path7.join(this.#directory, "store.lock");
21581
+ this.#instanceId = options2.instanceId ?? randomUUID3();
21230
21582
  this.#now = options2.now ?? (() => /* @__PURE__ */ new Date());
21231
21583
  this.#beforeReplace = options2.beforeReplace;
21232
21584
  }
@@ -21234,18 +21586,18 @@ var MappingStore = class {
21234
21586
  if (this.#initialized)
21235
21587
  return;
21236
21588
  await Promise.all([
21237
- mkdir3(this.#threadsDirectory, { recursive: true }),
21238
- mkdir3(this.#delegationsDirectory, { recursive: true }),
21239
- mkdir3(this.#backupsDirectory, { recursive: true }),
21240
- mkdir3(this.#quarantineDirectory, { recursive: true })
21589
+ mkdir4(this.#threadsDirectory, { recursive: true }),
21590
+ mkdir4(this.#delegationsDirectory, { recursive: true }),
21591
+ mkdir4(this.#backupsDirectory, { recursive: true }),
21592
+ mkdir4(this.#quarantineDirectory, { recursive: true })
21241
21593
  ]);
21242
21594
  await this.#acquireLock();
21243
21595
  try {
21244
21596
  await this.#cleanupResidue();
21245
21597
  const names = (await readdir2(this.#threadsDirectory)).filter((name) => name.endsWith(".json"));
21246
21598
  for (const name of names) {
21247
- const primary = path6.join(this.#threadsDirectory, name);
21248
- const backup = path6.join(this.#backupsDirectory, name);
21599
+ const primary = path7.join(this.#threadsDirectory, name);
21600
+ const backup = path7.join(this.#backupsDirectory, name);
21249
21601
  let record3 = null;
21250
21602
  try {
21251
21603
  record3 = await this.#readRecord(primary, name);
@@ -21254,31 +21606,31 @@ var MappingStore = class {
21254
21606
  record3 = await this.#readRecord(backup, name);
21255
21607
  await this.#replaceFile(primary, record3, false);
21256
21608
  } catch (backupError) {
21257
- const quarantine = path6.join(this.#quarantineDirectory, `${name}.${this.#now().getTime()}.invalid`);
21258
- await rename2(primary, quarantine).catch(() => void 0);
21609
+ const quarantine = path7.join(this.#quarantineDirectory, `${name}.${this.#now().getTime()}.invalid`);
21610
+ await rename3(primary, quarantine).catch(() => void 0);
21259
21611
  void primaryError;
21260
21612
  void backupError;
21261
21613
  continue;
21262
21614
  }
21263
21615
  }
21264
21616
  if (record3.state === "creating" && !record3.nativeSessionRef) {
21265
- await rm3(primary, { force: true });
21266
- await rm3(backup, { force: true });
21617
+ await rm4(primary, { force: true });
21618
+ await rm4(backup, { force: true });
21267
21619
  continue;
21268
21620
  }
21269
21621
  this.#records.set(record3.hostThreadId, record3);
21270
21622
  }
21271
21623
  const delegationNames = (await readdir2(this.#delegationsDirectory)).filter((name) => name.endsWith(".json"));
21272
21624
  for (const name of delegationNames) {
21273
- const file2 = path6.join(this.#delegationsDirectory, name);
21625
+ const file2 = path7.join(this.#delegationsDirectory, name);
21274
21626
  try {
21275
- const parsed = storedDelegationRecordV1Schema.parse(JSON.parse(await readFile5(file2, "utf8")));
21627
+ const parsed = storedDelegationRecordV1Schema.parse(JSON.parse(await readFile6(file2, "utf8")));
21276
21628
  if (`${parsed.delegationId}.json` !== name)
21277
21629
  throw new Error("filename mismatch");
21278
21630
  this.#delegations.set(parsed.delegationId, parsed);
21279
21631
  } catch {
21280
- const quarantine = path6.join(this.#quarantineDirectory, `${name}.${this.#now().getTime()}.invalid-delegation`);
21281
- await rename2(file2, quarantine).catch(() => void 0);
21632
+ const quarantine = path7.join(this.#quarantineDirectory, `${name}.${this.#now().getTime()}.invalid-delegation`);
21633
+ await rename3(file2, quarantine).catch(() => void 0);
21282
21634
  }
21283
21635
  }
21284
21636
  this.#rebuildIndexes();
@@ -21376,7 +21728,7 @@ var MappingStore = class {
21376
21728
  }
21377
21729
  async removeDelegation(delegationId) {
21378
21730
  this.#requireInitialized();
21379
- await rm3(this.#delegationPath(delegationId), { force: true });
21731
+ await rm4(this.#delegationPath(delegationId), { force: true });
21380
21732
  this.#delegations.delete(delegationId);
21381
21733
  this.#rebuildIndexes();
21382
21734
  }
@@ -21557,8 +21909,8 @@ var MappingStore = class {
21557
21909
  if (!this.#records.has(hostThreadId))
21558
21910
  return;
21559
21911
  await Promise.all([
21560
- rm3(this.#recordPath(hostThreadId), { force: true }),
21561
- rm3(this.#backupPath(hostThreadId), { force: true })
21912
+ rm4(this.#recordPath(hostThreadId), { force: true }),
21913
+ rm4(this.#backupPath(hostThreadId), { force: true })
21562
21914
  ]);
21563
21915
  this.#records.delete(hostThreadId);
21564
21916
  this.#rebuildIndexes();
@@ -21571,9 +21923,9 @@ var MappingStore = class {
21571
21923
  if (handle)
21572
21924
  await handle.close().catch(() => void 0);
21573
21925
  try {
21574
- const current = JSON.parse(await readFile5(this.#lockPath, "utf8"));
21926
+ const current = JSON.parse(await readFile6(this.#lockPath, "utf8"));
21575
21927
  if (current.instanceId === this.#instanceId)
21576
- await rm3(this.#lockPath, { force: true });
21928
+ await rm4(this.#lockPath, { force: true });
21577
21929
  } catch {
21578
21930
  }
21579
21931
  }
@@ -21640,11 +21992,11 @@ var MappingStore = class {
21640
21992
  this.#rebuildIndexes();
21641
21993
  }
21642
21994
  async #replaceFile(target, record3, preserveBackup) {
21643
- const temp = `${target}.tmp-${randomUUID2()}`;
21995
+ const temp = `${target}.tmp-${randomUUID3()}`;
21644
21996
  let handle = null;
21645
21997
  try {
21646
21998
  await this.#beforeReplace?.(cloneRecord(record3));
21647
- handle = await open3(temp, "wx", constants.S_IRUSR | constants.S_IWUSR);
21999
+ handle = await open4(temp, "wx", constants.S_IRUSR | constants.S_IWUSR);
21648
22000
  await handle.writeFile(`${JSON.stringify(record3, null, 2)}
21649
22001
  `, "utf8");
21650
22002
  await handle.sync();
@@ -21653,10 +22005,10 @@ var MappingStore = class {
21653
22005
  if (preserveBackup && await exists(target)) {
21654
22006
  await copyFile2(target, this.#backupPath(record3.hostThreadId));
21655
22007
  }
21656
- await rename2(temp, target);
22008
+ await rename3(temp, target);
21657
22009
  } catch (error51) {
21658
22010
  await handle?.close().catch(() => void 0);
21659
- await rm3(temp, { force: true }).catch(() => void 0);
22011
+ await rm4(temp, { force: true }).catch(() => void 0);
21660
22012
  if (error51 instanceof MappingStoreError)
21661
22013
  throw error51;
21662
22014
  throw new MappingStoreError("IO_ERROR", "Mapping Store atomic replacement failed", {
@@ -21666,19 +22018,19 @@ var MappingStore = class {
21666
22018
  }
21667
22019
  async #replaceDelegationFile(record3) {
21668
22020
  const target = this.#delegationPath(record3.delegationId);
21669
- const temp = `${target}.tmp-${randomUUID2()}`;
22021
+ const temp = `${target}.tmp-${randomUUID3()}`;
21670
22022
  let handle = null;
21671
22023
  try {
21672
- handle = await open3(temp, "wx", constants.S_IRUSR | constants.S_IWUSR);
22024
+ handle = await open4(temp, "wx", constants.S_IRUSR | constants.S_IWUSR);
21673
22025
  await handle.writeFile(`${JSON.stringify(record3, null, 2)}
21674
22026
  `, "utf8");
21675
22027
  await handle.sync();
21676
22028
  await handle.close();
21677
22029
  handle = null;
21678
- await rename2(temp, target);
22030
+ await rename3(temp, target);
21679
22031
  } catch (error51) {
21680
22032
  await handle?.close().catch(() => void 0);
21681
- await rm3(temp, { force: true }).catch(() => void 0);
22033
+ await rm4(temp, { force: true }).catch(() => void 0);
21682
22034
  if (error51 instanceof MappingStoreError)
21683
22035
  throw error51;
21684
22036
  throw new MappingStoreError("IO_ERROR", "Delegation atomic replacement failed", {
@@ -21687,7 +22039,7 @@ var MappingStore = class {
21687
22039
  }
21688
22040
  }
21689
22041
  async #readRecord(file2, expectedName) {
21690
- const parsed = storedThreadRecordV1Schema.safeParse(JSON.parse(await readFile5(file2, "utf8")));
22042
+ const parsed = storedThreadRecordV1Schema.safeParse(JSON.parse(await readFile6(file2, "utf8")));
21691
22043
  if (!parsed.success) {
21692
22044
  throw new MappingStoreError("INVALID_RECORD", "Mapping Store record is invalid", {
21693
22045
  cause: parsed.error
@@ -21705,15 +22057,15 @@ var MappingStore = class {
21705
22057
  readdir2(this.#directory)
21706
22058
  ]);
21707
22059
  await Promise.all([
21708
- ...threadNames.filter((name) => name.includes(".tmp-")).map((name) => rm3(path6.join(this.#threadsDirectory, name), { force: true })),
21709
- ...delegationNames.filter((name) => name.includes(".tmp-")).map((name) => rm3(path6.join(this.#delegationsDirectory, name), { force: true })),
22060
+ ...threadNames.filter((name) => name.includes(".tmp-")).map((name) => rm4(path7.join(this.#threadsDirectory, name), { force: true })),
22061
+ ...delegationNames.filter((name) => name.includes(".tmp-")).map((name) => rm4(path7.join(this.#delegationsDirectory, name), { force: true })),
21710
22062
  // Renamed aside by #acquireLock; nothing reads them back, and they accumulate one per run.
21711
- ...rootNames.filter((name) => name.startsWith(`${path6.basename(this.#lockPath)}.stale-`)).map((name) => rm3(path6.join(this.#directory, name), { force: true }))
22063
+ ...rootNames.filter((name) => name.startsWith(`${path7.basename(this.#lockPath)}.stale-`)).map((name) => rm4(path7.join(this.#directory, name), { force: true }))
21712
22064
  ]);
21713
22065
  }
21714
22066
  async #acquireLock() {
21715
22067
  const attempt = async () => {
21716
- const handle = await open3(this.#lockPath, "wx", constants.S_IRUSR | constants.S_IWUSR);
22068
+ const handle = await open4(this.#lockPath, "wx", constants.S_IRUSR | constants.S_IWUSR);
21717
22069
  const lock = {
21718
22070
  pid: process.pid,
21719
22071
  instanceId: this.#instanceId,
@@ -21735,13 +22087,13 @@ var MappingStore = class {
21735
22087
  }
21736
22088
  let existing = {};
21737
22089
  try {
21738
- existing = JSON.parse(await readFile5(this.#lockPath, "utf8"));
22090
+ existing = JSON.parse(await readFile6(this.#lockPath, "utf8"));
21739
22091
  } catch {
21740
22092
  }
21741
22093
  if (typeof existing.pid === "number" && lockOwnerIsLive(existing)) {
21742
22094
  throw new MappingStoreError("STORE_LOCKED", "Another BOFT CLI process owns Mapping Store");
21743
22095
  }
21744
- await rename2(this.#lockPath, `${this.#lockPath}.stale-${this.#now().getTime()}`).catch(() => void 0);
22096
+ await rename3(this.#lockPath, `${this.#lockPath}.stale-${this.#now().getTime()}`).catch(() => void 0);
21745
22097
  try {
21746
22098
  this.#lockHandle = await attempt();
21747
22099
  } catch (error51) {
@@ -21809,13 +22161,13 @@ var MappingStore = class {
21809
22161
  await next;
21810
22162
  }
21811
22163
  #recordPath(hostThreadId) {
21812
- return path6.join(this.#threadsDirectory, `${hostThreadId}.json`);
22164
+ return path7.join(this.#threadsDirectory, `${hostThreadId}.json`);
21813
22165
  }
21814
22166
  #delegationPath(delegationId) {
21815
- return path6.join(this.#delegationsDirectory, `${delegationId}.json`);
22167
+ return path7.join(this.#delegationsDirectory, `${delegationId}.json`);
21816
22168
  }
21817
22169
  #backupPath(hostThreadId) {
21818
- return path6.join(this.#backupsDirectory, `${hostThreadId}.json`);
22170
+ return path7.join(this.#backupsDirectory, `${hostThreadId}.json`);
21819
22171
  }
21820
22172
  #requireInitialized() {
21821
22173
  if (!this.#initialized) {
@@ -21835,7 +22187,7 @@ var TITLE_MAX_LENGTH = 150;
21835
22187
  var DESCRIPTION_MAX_LENGTH = 500;
21836
22188
  var SERVER_NAME_MAX_LENGTH = 80;
21837
22189
  var ELLIPSIS = "…";
21838
- function isRecord2(value2) {
22190
+ function isRecord3(value2) {
21839
22191
  return typeof value2 === "object" && value2 !== null && !Array.isArray(value2);
21840
22192
  }
21841
22193
  function boundedText(value2, field, maxLength) {
@@ -21889,7 +22241,7 @@ function responseError(message) {
21889
22241
  function responsePersist(value2) {
21890
22242
  if (value2 === void 0 || value2 === null)
21891
22243
  return null;
21892
- if (!isRecord2(value2) || Object.keys(value2).length !== 1 || value2.persist !== "session" && value2.persist !== "always") {
22244
+ if (!isRecord3(value2) || Object.keys(value2).length !== 1 || value2.persist !== "session" && value2.persist !== "always") {
21893
22245
  throw responseError("contains malformed persist metadata");
21894
22246
  }
21895
22247
  return value2.persist;
@@ -21939,7 +22291,7 @@ function projectCodexApprovalRequest(input) {
21939
22291
  },
21940
22292
  denyResponse,
21941
22293
  parseResponse(result) {
21942
- if (!isRecord2(result) || typeof result.action !== "string") {
22294
+ if (!isRecord3(result) || typeof result.action !== "string") {
21943
22295
  throw responseError("missing action");
21944
22296
  }
21945
22297
  if (Object.keys(result).some((key) => key !== "action" && key !== "content" && key !== "_meta")) {
@@ -21947,7 +22299,7 @@ function projectCodexApprovalRequest(input) {
21947
22299
  }
21948
22300
  const selectedPersist = responsePersist(result._meta);
21949
22301
  if (result.action === "accept") {
21950
- if ("content" in result && (!isRecord2(result.content) || Object.keys(result.content).length !== 0)) {
22302
+ if ("content" in result && (!isRecord3(result.content) || Object.keys(result.content).length !== 0)) {
21951
22303
  throw responseError("contains non-empty accepted content");
21952
22304
  }
21953
22305
  if (selectedPersist === "session") {
@@ -22007,7 +22359,7 @@ function projectApprovalChoices(input) {
22007
22359
  },
22008
22360
  denyResponse,
22009
22361
  parseResponse(result) {
22010
- if (!isRecord2(result) || typeof result.action !== "string")
22362
+ if (!isRecord3(result) || typeof result.action !== "string")
22011
22363
  throw responseError("missing action");
22012
22364
  if (Object.keys(result).some((key) => !["action", "content", "_meta"].includes(key))) {
22013
22365
  throw responseError("contains unreviewed fields");
@@ -22022,7 +22374,7 @@ function projectApprovalChoices(input) {
22022
22374
  return denyResponse;
22023
22375
  }
22024
22376
  const content = result.content;
22025
- if (result.action !== "accept" || !isRecord2(content) || Object.keys(content).length !== 1 || !interaction.actions.some(({ id: id2 }) => id2 === content.actionId)) {
22377
+ if (result.action !== "accept" || !isRecord3(content) || Object.keys(content).length !== 1 || !interaction.actions.some(({ id: id2 }) => id2 === content.actionId)) {
22026
22378
  throw responseError("contains an undeclared approval choice");
22027
22379
  }
22028
22380
  return { type: "approval", actionId: content.actionId };
@@ -22031,7 +22383,7 @@ function projectApprovalChoices(input) {
22031
22383
  }
22032
22384
 
22033
22385
  // packages/protocol-core/dist/codex-question.js
22034
- function isRecord3(value2) {
22386
+ function isRecord4(value2) {
22035
22387
  return typeof value2 === "object" && value2 !== null && !Array.isArray(value2);
22036
22388
  }
22037
22389
  function responseError2(message) {
@@ -22100,7 +22452,7 @@ function projectCodexQuestionRequest(input) {
22100
22452
  }
22101
22453
  },
22102
22454
  parseResponse(result) {
22103
- if (!isRecord3(result) || !isRecord3(result.answers)) {
22455
+ if (!isRecord4(result) || !isRecord4(result.answers)) {
22104
22456
  throw responseError2("missing answers object");
22105
22457
  }
22106
22458
  const rawAnswers = result.answers;
@@ -22113,7 +22465,7 @@ function projectCodexQuestionRequest(input) {
22113
22465
  const question = interaction.questions.find(({ id: id2 }) => id2 === questionId);
22114
22466
  if (!question)
22115
22467
  throw responseError2("contains an unknown Question ID");
22116
- if (!isRecord3(answerValue) || !Array.isArray(answerValue.answers)) {
22468
+ if (!isRecord4(answerValue) || !Array.isArray(answerValue.answers)) {
22117
22469
  throw responseError2("answer entry has no answers array");
22118
22470
  }
22119
22471
  const values = answerValue.answers;
@@ -22200,7 +22552,7 @@ function projectCodexThreadUsage(input) {
22200
22552
  }
22201
22553
 
22202
22554
  // packages/protocol-core/dist/codex-native-usage.js
22203
- function isRecord4(value2) {
22555
+ function isRecord5(value2) {
22204
22556
  return typeof value2 === "object" && value2 !== null && !Array.isArray(value2);
22205
22557
  }
22206
22558
  function nonNegativeSafeInteger(value2) {
@@ -22230,20 +22582,20 @@ function addBreakdown(target, source) {
22230
22582
  }
22231
22583
  }
22232
22584
  function observeCodexTokenUsage(value2) {
22233
- if (!isRecord4(value2) || value2.method !== "thread/tokenUsage/updated")
22585
+ if (!isRecord5(value2) || value2.method !== "thread/tokenUsage/updated")
22234
22586
  return null;
22235
22587
  const params = value2.params;
22236
- if (!isRecord4(params))
22588
+ if (!isRecord5(params))
22237
22589
  return null;
22238
22590
  const threadId2 = hostThreadIdSchema.safeParse(params.threadId);
22239
22591
  const turnId = hostTurnIdSchema.safeParse(params.turnId);
22240
22592
  if (!threadId2.success || !turnId.success)
22241
22593
  return null;
22242
22594
  const tokenUsage = params.tokenUsage;
22243
- if (!isRecord4(tokenUsage))
22595
+ if (!isRecord5(tokenUsage))
22244
22596
  return null;
22245
- const total = isRecord4(tokenUsage.total) ? tokenUsage.total : void 0;
22246
- const last = isRecord4(tokenUsage.last) ? tokenUsage.last : void 0;
22597
+ const total = isRecord5(tokenUsage.total) ? tokenUsage.total : void 0;
22598
+ const last = isRecord5(tokenUsage.last) ? tokenUsage.last : void 0;
22247
22599
  const usage = {};
22248
22600
  addBreakdown(usage, total);
22249
22601
  const contextUsedTokens = nonNegativeSafeInteger(last?.totalTokens);
@@ -22268,7 +22620,7 @@ function observeCodexTokenUsage(value2) {
22268
22620
  }
22269
22621
  }
22270
22622
  function parseRateLimitWindow(value2) {
22271
- if (!isRecord4(value2))
22623
+ if (!isRecord5(value2))
22272
22624
  return null;
22273
22625
  const usedPercent = finitePercent(value2.usedPercent);
22274
22626
  const windowDurationMins = nonNegativeSafeInteger(value2.windowDurationMins);
@@ -22279,7 +22631,7 @@ function parseRateLimitWindow(value2) {
22279
22631
  return { usedPercent, windowDurationMins, ...resetsAt !== void 0 ? { resetsAt } : {} };
22280
22632
  }
22281
22633
  function parseRateLimitCandidate(value2, options2 = {}) {
22282
- if (!isRecord4(value2))
22634
+ if (!isRecord5(value2))
22283
22635
  return null;
22284
22636
  if (options2.genericOnly && value2.limitId !== void 0 && value2.limitId !== null && value2.limitId !== "codex") {
22285
22637
  return null;
@@ -22289,16 +22641,16 @@ function parseRateLimitCandidate(value2, options2 = {}) {
22289
22641
  return primary || secondary ? { primary, secondary } : null;
22290
22642
  }
22291
22643
  function rateLimitCandidates(value2) {
22292
- if (!isRecord4(value2))
22644
+ if (!isRecord5(value2))
22293
22645
  return [];
22294
- const result = isRecord4(value2.result) ? value2.result : value2;
22295
- if (!isRecord4(result))
22646
+ const result = isRecord5(value2.result) ? value2.result : value2;
22647
+ if (!isRecord5(result))
22296
22648
  return [];
22297
22649
  const candidates = [];
22298
22650
  const base = parseRateLimitCandidate(result.rateLimits, { genericOnly: true });
22299
22651
  if (base)
22300
22652
  candidates.push(base);
22301
- const notificationParams = isRecord4(value2.params) ? value2.params : void 0;
22653
+ const notificationParams = isRecord5(value2.params) ? value2.params : void 0;
22302
22654
  const notificationSnapshot = parseRateLimitCandidate(notificationParams?.rateLimits, {
22303
22655
  genericOnly: true
22304
22656
  });
@@ -22342,14 +22694,14 @@ function parseAvailableCount(value2) {
22342
22694
  return void 0;
22343
22695
  }
22344
22696
  function rateLimitResetCreditsSummary(value2) {
22345
- if (!isRecord4(value2))
22697
+ if (!isRecord5(value2))
22346
22698
  return null;
22347
- const result = isRecord4(value2.result) ? value2.result : value2;
22348
- const fromResult = isRecord4(result) && isRecord4(result.rateLimitResetCredits) ? result.rateLimitResetCredits : null;
22699
+ const result = isRecord5(value2.result) ? value2.result : value2;
22700
+ const fromResult = isRecord5(result) && isRecord5(result.rateLimitResetCredits) ? result.rateLimitResetCredits : null;
22349
22701
  if (fromResult)
22350
22702
  return fromResult;
22351
- const params = isRecord4(value2.params) ? value2.params : void 0;
22352
- return isRecord4(params?.rateLimitResetCredits) ? params.rateLimitResetCredits : null;
22703
+ const params = isRecord5(value2.params) ? value2.params : void 0;
22704
+ return isRecord5(params?.rateLimitResetCredits) ? params.rateLimitResetCredits : null;
22353
22705
  }
22354
22706
  function observeCodexRateLimitResetCredits(value2) {
22355
22707
  const summary = rateLimitResetCreditsSummary(value2);
@@ -22361,7 +22713,7 @@ function observeCodexRateLimitResetCredits(value2) {
22361
22713
  const expiresAtUnix = [];
22362
22714
  if (Array.isArray(summary.credits)) {
22363
22715
  for (const credit of summary.credits) {
22364
- if (!isRecord4(credit))
22716
+ if (!isRecord5(credit))
22365
22717
  continue;
22366
22718
  if (credit.status !== void 0 && credit.status !== "available")
22367
22719
  continue;
@@ -22512,16 +22864,16 @@ var Diff = class {
22512
22864
  }
22513
22865
  }
22514
22866
  }
22515
- addToPath(path28, added, removed, oldPosInc, options2) {
22516
- const last = path28.lastComponent;
22867
+ addToPath(path29, added, removed, oldPosInc, options2) {
22868
+ const last = path29.lastComponent;
22517
22869
  if (last && !options2.oneChangePerToken && last.added === added && last.removed === removed) {
22518
22870
  return {
22519
- oldPos: path28.oldPos + oldPosInc,
22871
+ oldPos: path29.oldPos + oldPosInc,
22520
22872
  lastComponent: { count: last.count + 1, added, removed, previousComponent: last.previousComponent }
22521
22873
  };
22522
22874
  } else {
22523
22875
  return {
22524
- oldPos: path28.oldPos + oldPosInc,
22876
+ oldPos: path29.oldPos + oldPosInc,
22525
22877
  lastComponent: { count: 1, added, removed, previousComponent: last }
22526
22878
  };
22527
22879
  }
@@ -22950,10 +23302,10 @@ function splitLines(text2) {
22950
23302
  }
22951
23303
 
22952
23304
  // packages/protocol-core/dist/file-change-summary.js
22953
- import path7 from "node:path";
23305
+ import path8 from "node:path";
22954
23306
  function filePathKey(file2, cwd) {
22955
23307
  const windows = /^[a-z]:[/\\]/i.test(cwd) || /^[a-z]:[/\\]/i.test(file2);
22956
- const paths = windows ? path7.win32 : path7.posix;
23308
+ const paths = windows ? path8.win32 : path8.posix;
22957
23309
  const resolved = paths.resolve(cwd, file2).replaceAll("\\", "/");
22958
23310
  return windows ? resolved.toLowerCase() : resolved;
22959
23311
  }
@@ -23105,11 +23457,11 @@ function itemStatus(outcome) {
23105
23457
  return "inProgress";
23106
23458
  return outcome.status === "succeeded" ? "completed" : "failed";
23107
23459
  }
23108
- function isRecord5(value2) {
23460
+ function isRecord6(value2) {
23109
23461
  return typeof value2 === "object" && value2 !== null && !Array.isArray(value2);
23110
23462
  }
23111
23463
  function nestedString(value2, keys, preserveText = false) {
23112
- if (!isRecord5(value2))
23464
+ if (!isRecord6(value2))
23113
23465
  return void 0;
23114
23466
  for (const key of keys) {
23115
23467
  const field = value2[key];
@@ -23223,8 +23575,8 @@ function projectFileChangeKind(kind) {
23223
23575
  return { type: kind };
23224
23576
  }
23225
23577
  function projectFileChanges(changes) {
23226
- return changes.map(({ path: path28, kind, unifiedDiff }) => ({
23227
- path: path28,
23578
+ return changes.map(({ path: path29, kind, unifiedDiff }) => ({
23579
+ path: path29,
23228
23580
  kind: projectFileChangeKind(kind),
23229
23581
  diff: unifiedDiff
23230
23582
  }));
@@ -23264,7 +23616,7 @@ function planFromTodoValue(value2) {
23264
23616
  const record3 = unwrapToolRecord(value2);
23265
23617
  if (!record3)
23266
23618
  return planFromChecklistText(typeof value2 === "string" ? value2 : null);
23267
- if (isRecord5(record3.TodosUpdated)) {
23619
+ if (isRecord6(record3.TodosUpdated)) {
23268
23620
  const nested = planFromTodoValue(record3.TodosUpdated);
23269
23621
  if (nested)
23270
23622
  return nested;
@@ -23279,7 +23631,7 @@ function planFromTodoValue(value2) {
23279
23631
  plan.push({ step: entry.trim(), status: "pending" });
23280
23632
  continue;
23281
23633
  }
23282
- if (!isRecord5(entry))
23634
+ if (!isRecord6(entry))
23283
23635
  continue;
23284
23636
  const step = nestedString(entry, ["content", "step", "text", "title", "description", "task"]);
23285
23637
  if (!step)
@@ -23334,7 +23686,7 @@ function unwrapToolRecord(value2) {
23334
23686
  }
23335
23687
  if (Array.isArray(value2))
23336
23688
  return { todos: value2 };
23337
- if (!isRecord5(value2))
23689
+ if (!isRecord6(value2))
23338
23690
  return null;
23339
23691
  for (const wrapper of ["input", "arguments", "params"]) {
23340
23692
  if (value2[wrapper] === void 0)
@@ -24133,7 +24485,7 @@ var CodexTurnProjector = class {
24133
24485
  };
24134
24486
 
24135
24487
  // packages/protocol-core/dist/thread-fork.js
24136
- function isRecord6(value2) {
24488
+ function isRecord7(value2) {
24137
24489
  return typeof value2 === "object" && value2 !== null && !Array.isArray(value2);
24138
24490
  }
24139
24491
  function optionalText(params, name, options2 = {}) {
@@ -24156,7 +24508,7 @@ function optionalBoolean(params, name) {
24156
24508
  function decodeThreadForkRequest(request) {
24157
24509
  if (request.method !== "thread/fork")
24158
24510
  return null;
24159
- if (!isRecord6(request.params))
24511
+ if (!isRecord7(request.params))
24160
24512
  throw new Error("thread/fork params must be an object");
24161
24513
  const params = request.params;
24162
24514
  const threadId2 = optionalText(params, "threadId");
@@ -24171,13 +24523,13 @@ function decodeThreadForkRequest(request) {
24171
24523
  if (runtimeWorkspaceRoots !== void 0 && runtimeWorkspaceRoots !== null && (!Array.isArray(runtimeWorkspaceRoots) || runtimeWorkspaceRoots.some((root) => typeof root !== "string" || root.length === 0))) {
24172
24524
  throw new Error("thread/fork params.runtimeWorkspaceRoots must be text paths or null");
24173
24525
  }
24174
- const path28 = optionalText(params, "path", { allowEmpty: true });
24526
+ const path29 = optionalText(params, "path", { allowEmpty: true });
24175
24527
  const ephemeral = optionalBoolean(params, "ephemeral");
24176
24528
  return {
24177
24529
  threadId: threadId2,
24178
24530
  ...lastTurnText ? { lastTurnId: hostTurnIdSchema.parse(lastTurnText) } : {},
24179
24531
  ...beforeTurnText ? { beforeTurnId: hostTurnIdSchema.parse(beforeTurnText) } : {},
24180
- ...path28 ? { path: path28 } : {},
24532
+ ...path29 ? { path: path29 } : {},
24181
24533
  ...optionalField(params, "model"),
24182
24534
  ...optionalField(params, "modelProvider"),
24183
24535
  ...optionalField(params, "cwd"),
@@ -24192,7 +24544,7 @@ function decodeThreadForkRequest(request) {
24192
24544
  function decodeThreadRevertRequest(request) {
24193
24545
  if (request.method !== "thread/revert")
24194
24546
  return null;
24195
- if (!isRecord6(request.params))
24547
+ if (!isRecord7(request.params))
24196
24548
  throw new Error("thread/revert params must be an object");
24197
24549
  const { threadId: threadId2, beforeTurnId } = request.params;
24198
24550
  if (typeof threadId2 !== "string" || threadId2.length === 0) {
@@ -24206,7 +24558,7 @@ function decodeThreadRevertRequest(request) {
24206
24558
  function decodeThreadRollbackRequest(request) {
24207
24559
  if (request.method !== "thread/rollback")
24208
24560
  return null;
24209
- if (!isRecord6(request.params))
24561
+ if (!isRecord7(request.params))
24210
24562
  throw new Error("thread/rollback params must be an object");
24211
24563
  const { threadId: threadId2, numTurns } = request.params;
24212
24564
  if (typeof threadId2 !== "string" || threadId2.length === 0) {
@@ -24270,7 +24622,7 @@ function threadForkResult(thread, input) {
24270
24622
  }
24271
24623
 
24272
24624
  // packages/protocol-core/dist/thread-management.js
24273
- import { createHash as createHash3 } from "node:crypto";
24625
+ import { createHash as createHash4 } from "node:crypto";
24274
24626
  var HOST_CURSOR_PREFIX = "codexhost:thread-list:v1:";
24275
24627
  var MAX_CURSOR_LENGTH = 65536;
24276
24628
  var DEFAULT_PAGE_SIZE = 25;
@@ -24303,13 +24655,13 @@ var THREAD_SOURCE_KINDS = /* @__PURE__ */ new Set([
24303
24655
  "subAgentOther",
24304
24656
  "unknown"
24305
24657
  ]);
24306
- function isRecord7(value2) {
24658
+ function isRecord8(value2) {
24307
24659
  return typeof value2 === "object" && value2 !== null && !Array.isArray(value2);
24308
24660
  }
24309
24661
  function paramsObject(request, method) {
24310
24662
  if (request.params === void 0 && method === "thread/list")
24311
24663
  return {};
24312
- if (!isRecord7(request.params))
24664
+ if (!isRecord8(request.params))
24313
24665
  throw new Error(`${method} params must be an object`);
24314
24666
  return request.params;
24315
24667
  }
@@ -24367,7 +24719,7 @@ function decodeSortKey(value2) {
24367
24719
  return value2;
24368
24720
  }
24369
24721
  function queryFingerprint(value2) {
24370
- return createHash3("sha256").update(JSON.stringify(value2)).digest("hex");
24722
+ return createHash4("sha256").update(JSON.stringify(value2)).digest("hex");
24371
24723
  }
24372
24724
  function cursorPayload(value2) {
24373
24725
  return {
@@ -24381,7 +24733,7 @@ function cursorPayload(value2) {
24381
24733
  };
24382
24734
  }
24383
24735
  function parseCursorPayload(value2) {
24384
- if (!isRecord7(value2) || value2.formatVersion !== 1)
24736
+ if (!isRecord8(value2) || value2.formatVersion !== 1)
24385
24737
  throw new Error("Host cursor is invalid");
24386
24738
  const { queryFingerprint: fingerprint, sortDirection: sortDirection2, officialCursor, officialDone } = value2;
24387
24739
  const { externalAnchor: externalAnchor2, externalDone } = value2;
@@ -24390,7 +24742,7 @@ function parseCursorPayload(value2) {
24390
24742
  }
24391
24743
  let anchor = null;
24392
24744
  if (externalAnchor2 !== null) {
24393
- if (!isRecord7(externalAnchor2) || !Number.isSafeInteger(externalAnchor2.timestamp) || typeof externalAnchor2.threadId !== "string" || externalAnchor2.threadId.length === 0) {
24745
+ if (!isRecord8(externalAnchor2) || !Number.isSafeInteger(externalAnchor2.timestamp) || typeof externalAnchor2.threadId !== "string" || externalAnchor2.threadId.length === 0) {
24394
24746
  throw new Error("Host cursor is invalid");
24395
24747
  }
24396
24748
  anchor = {
@@ -24513,7 +24865,7 @@ function decodeThreadMetadataUpdateRequest(request) {
24513
24865
  if (params.gitInfo === null) {
24514
24866
  gitInfo = null;
24515
24867
  } else if (params.gitInfo !== void 0) {
24516
- if (!isRecord7(params.gitInfo)) {
24868
+ if (!isRecord8(params.gitInfo)) {
24517
24869
  throw new Error("thread/metadata/update params.gitInfo must be an object or null");
24518
24870
  }
24519
24871
  gitInfo = {};
@@ -24541,7 +24893,7 @@ function optionalCursor(value2, name) {
24541
24893
  return value2;
24542
24894
  }
24543
24895
  function decodeOfficialThreadListPage(value2) {
24544
- if (!isRecord7(value2) || !Array.isArray(value2.data) || value2.data.some((row) => !isRecord7(row))) {
24896
+ if (!isRecord8(value2) || !Array.isArray(value2.data) || value2.data.some((row) => !isRecord8(row))) {
24545
24897
  throw new Error("Official thread/list response is invalid");
24546
24898
  }
24547
24899
  return {
@@ -25353,22 +25705,22 @@ var HarnessAccountInspectionCache = class {
25353
25705
  };
25354
25706
 
25355
25707
  // packages/host-runtime/src/app-server-host.ts
25356
- import { createHash as createHash7, randomUUID as randomUUID9 } from "node:crypto";
25357
- import os4 from "node:os";
25358
- import path14 from "node:path";
25708
+ import { createHash as createHash8, randomUUID as randomUUID10 } from "node:crypto";
25709
+ import os5 from "node:os";
25710
+ import path16 from "node:path";
25359
25711
 
25360
25712
  // packages/host-runtime/src/external-thread-fork.ts
25361
25713
  import nodePath from "node:path";
25362
25714
 
25363
25715
  // packages/host-runtime/src/external-thread-repository.ts
25364
- import { randomUUID as randomUUID4 } from "node:crypto";
25365
- import os2 from "node:os";
25366
- import path8 from "node:path";
25716
+ import { randomUUID as randomUUID5 } from "node:crypto";
25717
+ import os3 from "node:os";
25718
+ import path9 from "node:path";
25367
25719
 
25368
25720
  // packages/host-runtime/src/external-subagent-threads.ts
25369
- import { createHash as createHash4, randomUUID as randomUUID3 } from "node:crypto";
25721
+ import { createHash as createHash5, randomUUID as randomUUID4 } from "node:crypto";
25370
25722
  function childCreateRequest(parent, nativeRef, id2) {
25371
- const key = createHash4("sha256").update(JSON.stringify([parent.hostThreadId, parent.harnessId, nativeRef.nativeSessionId, id2])).digest("hex");
25723
+ const key = createHash5("sha256").update(JSON.stringify([parent.hostThreadId, parent.harnessId, nativeRef.nativeSessionId, id2])).digest("hex");
25372
25724
  return `subagent:${key}`;
25373
25725
  }
25374
25726
  function subagentMaterializer(store, parent, previousParent) {
@@ -25441,7 +25793,7 @@ function subagentMaterializer(store, parent, previousParent) {
25441
25793
  return rebind(existing, parent);
25442
25794
  }
25443
25795
  const provisional = existing ?? await store.createProvisional({
25444
- hostThreadId: hostThreadIdSchema.parse(randomUUID3()),
25796
+ hostThreadId: hostThreadIdSchema.parse(randomUUID4()),
25445
25797
  createRequestId,
25446
25798
  harnessId: parent.harnessId,
25447
25799
  cwd: parent.cwd,
@@ -25503,8 +25855,8 @@ function sameMapping(left, right) {
25503
25855
  }
25504
25856
  function defaultMappingStoreDirectory(environment) {
25505
25857
  const dataDirectory = environment.CODEXHOST_DATA_DIR;
25506
- return path8.join(
25507
- dataDirectory ? path8.resolve(dataDirectory) : path8.join(os2.homedir(), ".codexhost"),
25858
+ return path9.join(
25859
+ dataDirectory ? path9.resolve(dataDirectory) : path9.join(os3.homedir(), ".codexhost"),
25508
25860
  "mapping-store"
25509
25861
  );
25510
25862
  }
@@ -25608,7 +25960,7 @@ var ExternalThreadRepository = class {
25608
25960
  throw new Error("Derived Snapshot identity does not belong to its Native Session");
25609
25961
  }
25610
25962
  return {
25611
- hostTurnId: hostTurnIdSchema.parse(randomUUID4()),
25963
+ hostTurnId: hostTurnIdSchema.parse(randomUUID5()),
25612
25964
  nativeTurnRef: turn.nativeTurnRef,
25613
25965
  ...turn.checkpoint ? { nativeCheckpointRef: turn.checkpoint } : {}
25614
25966
  };
@@ -25728,7 +26080,7 @@ var ExternalThreadRepository = class {
25728
26080
  const aligned = snapshot.turns.map((turn) => {
25729
26081
  const existing = mappingsByNative.get(nativeTurnKey2(turn.nativeTurnRef));
25730
26082
  const mapping = existing ?? {
25731
- hostTurnId: hostTurnIdSchema.parse(randomUUID4()),
26083
+ hostTurnId: hostTurnIdSchema.parse(randomUUID5()),
25732
26084
  nativeTurnRef: turn.nativeTurnRef,
25733
26085
  ...turn.checkpoint ? { nativeCheckpointRef: turn.checkpoint } : {}
25734
26086
  };
@@ -25755,8 +26107,8 @@ var ExternalThreadRepository = class {
25755
26107
  };
25756
26108
  function createExternalThreadRecordInput(input) {
25757
26109
  return {
25758
- hostThreadId: input.hostThreadId ?? hostThreadIdSchema.parse(randomUUID4()),
25759
- createRequestId: input.createRequestId ?? randomUUID4(),
26110
+ hostThreadId: input.hostThreadId ?? hostThreadIdSchema.parse(randomUUID5()),
26111
+ createRequestId: input.createRequestId ?? randomUUID5(),
25760
26112
  harnessId: input.harnessId,
25761
26113
  cwd: input.cwd,
25762
26114
  ...input.title ? { title: input.title } : {},
@@ -25931,6 +26283,7 @@ async function executeExternalThreadFork(input) {
25931
26283
  return { ok: false, error: mapExternalThreadHarnessError(opened.error, "fork") };
25932
26284
  }
25933
26285
  const session = opened.value;
26286
+ const inheritedPermissionModeId = await inheritSourcePermissionMode(source, session);
25934
26287
  try {
25935
26288
  const derivedNativeRef = session.initialState.nativeRef;
25936
26289
  if (!derivedNativeRef || derivedNativeRef.nativeSessionId === nativeSessionRef.nativeSessionId) {
@@ -25958,7 +26311,8 @@ async function executeExternalThreadFork(input) {
25958
26311
  sessionId: source.sessionId,
25959
26312
  thread,
25960
26313
  turns: aligned.turns,
25961
- ...snapshot.value.state ? { restoredState: snapshot.value.state } : {}
26314
+ ...snapshot.value.state ? { restoredState: snapshot.value.state } : {},
26315
+ ...inheritedPermissionModeId ? { requestedPermissionModeId: inheritedPermissionModeId } : {}
25962
26316
  });
25963
26317
  return {
25964
26318
  ok: true,
@@ -25976,6 +26330,23 @@ async function executeExternalThreadFork(input) {
25976
26330
  };
25977
26331
  }
25978
26332
  }
26333
+ async function inheritSourcePermissionMode(source, session) {
26334
+ const sourceModeId = source.stateObserver.state.effectivePermissionModeId ?? source.requestedPermissionModeId;
26335
+ if (!sourceModeId) return void 0;
26336
+ const configuration = session.capabilities.configuration;
26337
+ if (!configuration.selectPermissionMode || permissionModeFixedAtCreate(configuration)) {
26338
+ return void 0;
26339
+ }
26340
+ try {
26341
+ const selected = await session.execute({
26342
+ type: "permissionMode.select",
26343
+ permissionModeId: sourceModeId
26344
+ });
26345
+ return selected.ok ? sourceModeId : void 0;
26346
+ } catch {
26347
+ return void 0;
26348
+ }
26349
+ }
25979
26350
 
25980
26351
  // packages/host-runtime/src/harness-session-import.ts
25981
26352
  function fixedError(code, message) {
@@ -27557,9 +27928,12 @@ var ExternalTurnSteering = class {
27557
27928
  if (!cancelled.ok) throw new ExternalSteerError(-32074, cancelled.error.message);
27558
27929
  const outcome = await Promise.race([terminal2.promise, failure.promise]);
27559
27930
  clearTimeout(timeout);
27560
- if (failureReason) throw failureReason;
27561
- if (this.#closed)
27562
- throw new ExternalSteerError(-32074, "External steering connection is closed");
27931
+ const assertActive = () => {
27932
+ if (failureReason) throw failureReason;
27933
+ if (this.#closed)
27934
+ throw new ExternalSteerError(-32074, "External steering connection is closed");
27935
+ };
27936
+ assertActive();
27563
27937
  if (outcome.status === "failed") throw new ExternalSteerError(-32074, outcome.error.message);
27564
27938
  if (thread.persistenceError)
27565
27939
  throw new ExternalSteerError(
@@ -27569,7 +27943,7 @@ var ExternalTurnSteering = class {
27569
27943
  if (thread.running || thread.activeTurnId) {
27570
27944
  throw new ExternalSteerError(-32072, "Another External Turn started before replacement");
27571
27945
  }
27572
- return await start(input.text);
27946
+ return await start(input.text, assertActive);
27573
27947
  } finally {
27574
27948
  clearTimeout(timeout);
27575
27949
  if (this.#pending.get(thread.id) === pending) this.#pending.delete(thread.id);
@@ -27577,16 +27951,98 @@ var ExternalTurnSteering = class {
27577
27951
  }
27578
27952
  };
27579
27953
 
27954
+ // packages/host-runtime/src/external-command-routing.ts
27955
+ var ExternalCommandError = class extends Error {
27956
+ constructor(code, message) {
27957
+ super(message);
27958
+ this.code = code;
27959
+ }
27960
+ code;
27961
+ };
27962
+ function isExternalCommandCandidate(text2) {
27963
+ return /^\/[^\s/]+(?:\s|$)/u.test(text2.trimStart());
27964
+ }
27965
+ async function inspectLiveCommandCatalog(commands, timeoutMs = 1e3) {
27966
+ let timeout;
27967
+ try {
27968
+ const result = await Promise.race([
27969
+ commands.list(),
27970
+ new Promise((resolve) => {
27971
+ timeout = setTimeout(() => resolve(null), timeoutMs);
27972
+ })
27973
+ ]);
27974
+ return result?.ok ? harnessCommandCatalogSchema.parse(result.value) : null;
27975
+ } catch {
27976
+ return null;
27977
+ } finally {
27978
+ if (timeout !== void 0) clearTimeout(timeout);
27979
+ }
27980
+ }
27981
+ async function resolveExternalCommand(commands, text2, options2 = {}) {
27982
+ const catalog = await commands.list();
27983
+ if (!catalog.ok) throw new ExternalCommandError(-32073, catalog.error.message);
27984
+ const commandText = text2.trim();
27985
+ const matched = catalog.value.commands.toSorted((left, right) => right.invocation.length - left.invocation.length).find((command) => {
27986
+ if (commandText === command.invocation) return true;
27987
+ return command.argumentMode === "text" && commandText.startsWith(`${command.invocation} `);
27988
+ });
27989
+ if (!matched) {
27990
+ const name = /^\/(\S+)/u.exec(commandText)?.[1] ?? "";
27991
+ if (name && !isExcludedLiveCommand(name, "command") && options2.liveCatalogPending?.(catalog.value)) {
27992
+ return null;
27993
+ }
27994
+ throw new ExternalCommandError(
27995
+ -32078,
27996
+ "External Harness does not expose the requested command"
27997
+ );
27998
+ }
27999
+ const argumentText = commandText.slice(matched.invocation.length).trimStart();
28000
+ return {
28001
+ commandId: matched.id,
28002
+ ...argumentText.length > 0 ? { arguments: { text: argumentText } } : {}
28003
+ };
28004
+ }
28005
+
28006
+ // packages/host-runtime/src/live-command-catalog-cache.ts
28007
+ import path10 from "node:path";
28008
+ var MAX_ENTRIES = 64;
28009
+ function isLiveCommandCatalog(catalog, staticCatalog) {
28010
+ const staticIds = new Set(staticCatalog.commands.map(({ id: id2 }) => id2));
28011
+ return catalog.commands.some(({ id: id2 }) => !staticIds.has(id2));
28012
+ }
28013
+ var LiveCommandCatalogCache = class {
28014
+ #entries = /* @__PURE__ */ new Map();
28015
+ #key(harnessId, cwd) {
28016
+ return `${harnessId}\0${path10.resolve(cwd)}`;
28017
+ }
28018
+ remember(harnessId, cwd, catalog) {
28019
+ const key = this.#key(harnessId, cwd);
28020
+ this.#entries.delete(key);
28021
+ this.#entries.set(key, catalog);
28022
+ while (this.#entries.size > MAX_ENTRIES) {
28023
+ const oldest = this.#entries.keys().next().value;
28024
+ if (oldest === void 0) break;
28025
+ this.#entries.delete(oldest);
28026
+ }
28027
+ }
28028
+ lookup(harnessId, cwd) {
28029
+ return this.#entries.get(this.#key(harnessId, cwd));
28030
+ }
28031
+ };
28032
+ function sameWorkspace(left, right) {
28033
+ return path10.resolve(left) === path10.resolve(right);
28034
+ }
28035
+
27580
28036
  // packages/host-runtime/src/harness-delegation-coordinator.ts
27581
- import { createHash as createHash6, randomUUID as randomUUID5 } from "node:crypto";
27582
- import path9 from "node:path";
28037
+ import { createHash as createHash7, randomUUID as randomUUID6 } from "node:crypto";
28038
+ import path11 from "node:path";
27583
28039
 
27584
28040
  // packages/host-runtime/src/delegation-snapshot.ts
27585
- import { createHash as createHash5 } from "node:crypto";
28041
+ import { createHash as createHash6 } from "node:crypto";
27586
28042
  var CURSOR_PREFIX = "codexhost:thread-messages:v1:";
27587
28043
  var DEFAULT_MESSAGE_LIMIT = 25;
27588
28044
  var MAX_MESSAGE_LIMIT = 100;
27589
- function isRecord8(value2) {
28045
+ function isRecord9(value2) {
27590
28046
  return typeof value2 === "object" && value2 !== null && !Array.isArray(value2);
27591
28047
  }
27592
28048
  function stringValue(value2) {
@@ -27595,12 +28051,12 @@ function stringValue(value2) {
27595
28051
  function textFromUserItem(item) {
27596
28052
  if (!Array.isArray(item.content)) return "";
27597
28053
  return item.content.flatMap(
27598
- (part) => isRecord8(part) && part.type === "text" && typeof part.text === "string" ? [part.text] : []
28054
+ (part) => isRecord9(part) && part.type === "text" && typeof part.text === "string" ? [part.text] : []
27599
28055
  ).join("\n");
27600
28056
  }
27601
28057
  function threadStatus(value2, running) {
27602
28058
  if (running) return "running";
27603
- if (isRecord8(value2)) {
28059
+ if (isRecord9(value2)) {
27604
28060
  if (value2.type === "active") return "running";
27605
28061
  }
27606
28062
  return "completed";
@@ -27617,10 +28073,10 @@ function allVisibleMessages(turns) {
27617
28073
  const turnId = stringValue(turn.id);
27618
28074
  if (!turnId || !Array.isArray(turn.items)) continue;
27619
28075
  const agentItems = turn.items.filter(
27620
- (item) => isRecord8(item) && item.type === "agentMessage"
28076
+ (item) => isRecord9(item) && item.type === "agentMessage"
27621
28077
  );
27622
28078
  for (const item of turn.items) {
27623
- if (!isRecord8(item)) continue;
28079
+ if (!isRecord9(item)) continue;
27624
28080
  const id2 = stringValue(item.id);
27625
28081
  if (!id2) continue;
27626
28082
  if (item.type === "userMessage") {
@@ -27636,7 +28092,7 @@ function allVisibleMessages(turns) {
27636
28092
  return messages;
27637
28093
  }
27638
28094
  function cursorFingerprint(threadId2) {
27639
- return createHash5("sha256").update(threadId2).digest("hex");
28095
+ return createHash6("sha256").update(threadId2).digest("hex");
27640
28096
  }
27641
28097
  function encodeCursor(threadId2, offset) {
27642
28098
  const payload = JSON.stringify({ version: 1, fingerprint: cursorFingerprint(threadId2), offset });
@@ -27695,7 +28151,7 @@ function projectDelegationThreadSnapshot(input) {
27695
28151
  const progress = latestTurnMessages.filter((message) => message.phase !== "final" && message.text.trim()).map(({ id: id2, turnId, text: text2 }) => ({ id: id2, turnId, text: text2 }));
27696
28152
  const result = input.running ? { availability: "pending" } : final ? { availability: "available", text: final.text } : {
27697
28153
  availability: "unavailable",
27698
- ...isRecord8(latestTurn?.error) && typeof latestTurn.error.message === "string" ? { message: latestTurn.error.message } : {}
28154
+ ...isRecord9(latestTurn?.error) && typeof latestTurn.error.message === "string" ? { message: latestTurn.error.message } : {}
27699
28155
  };
27700
28156
  const offset = options2.view === "messages" ? decodeCursor(input.threadId, options2.cursor) : visible.length;
27701
28157
  const page = options2.view === "messages" ? [] : void 0;
@@ -27747,10 +28203,10 @@ function terminal(status) {
27747
28203
  return status === "completed" || status === "failed" || status === "interrupted";
27748
28204
  }
27749
28205
  function taskDigest(input) {
27750
- return createHash6("sha256").update(
28206
+ return createHash7("sha256").update(
27751
28207
  JSON.stringify({
27752
28208
  task: input.task,
27753
- cwd: path9.resolve(input.cwd),
28209
+ cwd: path11.resolve(input.cwd),
27754
28210
  modelId: input.model?.id ?? null,
27755
28211
  thinkingOptionId: input.thinkingOptionId ?? null
27756
28212
  })
@@ -27821,7 +28277,7 @@ var HarnessDelegationCoordinator = class {
27821
28277
  return {
27822
28278
  harnessId: input.harnessId,
27823
28279
  inspection: await adapter.inspect({
27824
- ...input.cwd ? { cwd: path9.resolve(input.cwd) } : {},
28280
+ ...input.cwd ? { cwd: path11.resolve(input.cwd) } : {},
27825
28281
  ...input.refresh !== void 0 ? { refresh: input.refresh } : {}
27826
28282
  })
27827
28283
  };
@@ -27835,7 +28291,7 @@ var HarnessDelegationCoordinator = class {
27835
28291
  const result = await this.#startOfficial({ ...input, parentThreadId, cwd: selectedCwd });
27836
28292
  return { ...result, parentThreadId, cwd: result.cwd ?? selectedCwd };
27837
28293
  }
27838
- const startInput = { ...input, parentThreadId, cwd: path9.resolve(selectedCwd) };
28294
+ const startInput = { ...input, parentThreadId, cwd: path11.resolve(selectedCwd) };
27839
28295
  if (!this.#adapters.has(input.harnessId)) {
27840
28296
  throw new DelegationControlError(
27841
28297
  "HARNESS_NOT_FOUND",
@@ -27875,10 +28331,10 @@ var HarnessDelegationCoordinator = class {
27875
28331
  });
27876
28332
  this.#validateConfiguration(inspected.inspection, input.model, input.thinkingOptionId);
27877
28333
  }
27878
- const delegationId = hostThreadIdSchema.parse(randomUUID5());
27879
- const childThreadId = hostThreadIdSchema.parse(randomUUID5());
27880
- const turnId = hostTurnIdSchema.parse(randomUUID5());
27881
- const createRequestId = input.requestId ? `delegation:${input.requestId}` : randomUUID5();
28334
+ const delegationId = hostThreadIdSchema.parse(randomUUID6());
28335
+ const childThreadId = hostThreadIdSchema.parse(randomUUID6());
28336
+ const turnId = hostTurnIdSchema.parse(randomUUID6());
28337
+ const createRequestId = input.requestId ? `delegation:${input.requestId}` : randomUUID6();
27882
28338
  let record3 = await this.#repository.createProvisional(
27883
28339
  createExternalThreadRecordInput({
27884
28340
  hostThreadId: childThreadId,
@@ -28010,7 +28466,7 @@ var HarnessDelegationCoordinator = class {
28010
28466
  if (thread.running || thread.activeTurnId) {
28011
28467
  throw new DelegationControlError("THREAD_BUSY", "Thread already has an active Turn");
28012
28468
  }
28013
- const turnId = hostTurnIdSchema.parse(randomUUID5());
28469
+ const turnId = hostTurnIdSchema.parse(randomUUID6());
28014
28470
  try {
28015
28471
  await this.#startExternalTurn(thread, input.message, turnId);
28016
28472
  } catch (error51) {
@@ -28264,7 +28720,7 @@ var HarnessDelegationCoordinator = class {
28264
28720
 
28265
28721
  // packages/host-runtime/src/harness-plugin-loader.ts
28266
28722
  import { readdir as readdir3, realpath as realpath2 } from "node:fs/promises";
28267
- import path11 from "node:path";
28723
+ import path13 from "node:path";
28268
28724
  import { pathToFileURL } from "node:url";
28269
28725
 
28270
28726
  // packages/host-runtime/src/harness-plugin-registry.ts
@@ -28301,25 +28757,25 @@ var HarnessPluginRegistry = class {
28301
28757
  };
28302
28758
 
28303
28759
  // packages/host-runtime/src/plugin-files.ts
28304
- import { open as open4, realpath, stat as stat2 } from "node:fs/promises";
28305
- import path10 from "node:path";
28760
+ import { open as open5, realpath, stat as stat3 } from "node:fs/promises";
28761
+ import path12 from "node:path";
28306
28762
  function inside(root, candidate) {
28307
- const relative = path10.relative(root, candidate);
28308
- return relative !== "" && !path10.isAbsolute(relative) && relative !== ".." && !relative.startsWith(`..${path10.sep}`);
28763
+ const relative = path12.relative(root, candidate);
28764
+ return relative !== "" && !path12.isAbsolute(relative) && relative !== ".." && !relative.startsWith(`..${path12.sep}`);
28309
28765
  }
28310
28766
  async function pluginResourcePath(root, relative) {
28311
- if (path10.isAbsolute(relative) || !inside(root, path10.resolve(root, relative))) {
28767
+ if (path12.isAbsolute(relative) || !inside(root, path12.resolve(root, relative))) {
28312
28768
  throw new Error("Plugin resource escapes its root");
28313
28769
  }
28314
- const resolved = await realpath(path10.resolve(root, relative));
28315
- if (!inside(root, resolved) || !(await stat2(resolved)).isFile()) {
28770
+ const resolved = await realpath(path12.resolve(root, relative));
28771
+ if (!inside(root, resolved) || !(await stat3(resolved)).isFile()) {
28316
28772
  throw new Error("Plugin resource must be a regular file inside its root");
28317
28773
  }
28318
28774
  return resolved;
28319
28775
  }
28320
28776
  async function readPluginFile(file2, maximum) {
28321
- if (!(await stat2(file2)).isFile()) throw new Error("Plugin resource is not a regular file");
28322
- const handle = await open4(file2, "r");
28777
+ if (!(await stat3(file2)).isFile()) throw new Error("Plugin resource is not a regular file");
28778
+ const handle = await open5(file2, "r");
28323
28779
  try {
28324
28780
  const info = await handle.stat();
28325
28781
  if (!info.isFile() || info.size > maximum) throw new Error("Plugin resource exceeds its limit");
@@ -28473,7 +28929,7 @@ async function loadHarnessPlugins(options2) {
28473
28929
  const enabledIds = /* @__PURE__ */ new Set();
28474
28930
  const roots = /* @__PURE__ */ new Set();
28475
28931
  for (const configuredRoot of options2.roots) {
28476
- if (!path11.isAbsolute(configuredRoot)) {
28932
+ if (!path13.isAbsolute(configuredRoot)) {
28477
28933
  diagnose({ code: "invalidRoot" });
28478
28934
  continue;
28479
28935
  }
@@ -28503,7 +28959,7 @@ async function loadHarnessPlugins(options2) {
28503
28959
  for (const directory of directories) {
28504
28960
  try {
28505
28961
  const file2 = await pluginResourcePath(root, `${directory.name}/manifest.json`);
28506
- const pluginRoot = await realpath2(path11.join(root, directory.name));
28962
+ const pluginRoot = await realpath2(path13.join(root, directory.name));
28507
28963
  await pluginResourcePath(pluginRoot, "manifest.json");
28508
28964
  const manifest = harnessPluginManifestSchema.parse(
28509
28965
  JSON.parse(
@@ -28598,28 +29054,28 @@ async function loadHarnessPlugins(options2) {
28598
29054
  }
28599
29055
 
28600
29056
  // packages/host-runtime/src/harness-launch-settings.ts
28601
- import { randomUUID as randomUUID6 } from "node:crypto";
28602
- import { mkdir as mkdir4, readFile as readFile6, rename as rename3, rm as rm4, stat as stat3, writeFile as writeFile3 } from "node:fs/promises";
28603
- import os3 from "node:os";
28604
- import path12 from "node:path";
29057
+ import { randomUUID as randomUUID7 } from "node:crypto";
29058
+ import { mkdir as mkdir5, readFile as readFile7, rename as rename4, rm as rm5, stat as stat4, writeFile as writeFile3 } from "node:fs/promises";
29059
+ import os4 from "node:os";
29060
+ import path14 from "node:path";
28605
29061
  var HarnessLaunchSettingsStore = class {
28606
29062
  #directory;
28607
29063
  #initial = /* @__PURE__ */ new Map();
28608
29064
  constructor(environment) {
28609
- this.#directory = path12.join(
28610
- environment.CODEXHOST_DATA_DIR ? path12.resolve(environment.CODEXHOST_DATA_DIR) : path12.join(os3.homedir(), ".codexhost"),
29065
+ this.#directory = path14.join(
29066
+ environment.CODEXHOST_DATA_DIR ? path14.resolve(environment.CODEXHOST_DATA_DIR) : path14.join(os4.homedir(), ".codexhost"),
28611
29067
  "harness-launch-settings"
28612
29068
  );
28613
29069
  }
28614
29070
  #file(id2) {
28615
- return path12.join(this.#directory, `${harnessPluginIdSchema.parse(id2)}.json`);
29071
+ return path14.join(this.#directory, `${harnessPluginIdSchema.parse(id2)}.json`);
28616
29072
  }
28617
29073
  async #read(id2) {
28618
29074
  try {
28619
29075
  const value2 = harnessLaunchPathSchema.parse(
28620
- JSON.parse(await readFile6(this.#file(id2), "utf8"))
29076
+ JSON.parse(await readFile7(this.#file(id2), "utf8"))
28621
29077
  );
28622
- if (!path12.isAbsolute(value2)) throw new Error("Expected an absolute entrypoint path");
29078
+ if (!path14.isAbsolute(value2)) throw new Error("Expected an absolute entrypoint path");
28623
29079
  return value2;
28624
29080
  } catch (error51) {
28625
29081
  if (error51 && typeof error51 === "object" && "code" in error51 && error51.code === "ENOENT")
@@ -28645,22 +29101,22 @@ var HarnessLaunchSettingsStore = class {
28645
29101
  const initial = await this.initialCommand(id2) ?? null;
28646
29102
  const file2 = this.#file(id2);
28647
29103
  if (value2 === null) {
28648
- await rm4(file2, { force: true });
29104
+ await rm5(file2, { force: true });
28649
29105
  } else {
28650
29106
  value2 = harnessLaunchPathSchema.parse(value2);
28651
- if (!path12.isAbsolute(value2))
29107
+ if (!path14.isAbsolute(value2))
28652
29108
  throw new Error("Use an absolute entrypoint path without arguments");
28653
- const metadata = await stat3(value2).catch(() => void 0);
29109
+ const metadata = await stat4(value2).catch(() => void 0);
28654
29110
  if (!metadata?.isDirectory() && !metadata?.isFile())
28655
29111
  throw new Error("The installation path must be an existing directory on this Host");
28656
- await mkdir4(this.#directory, { recursive: true, mode: 448 });
28657
- const temporary = `${file2}.${randomUUID6()}.tmp`;
29112
+ await mkdir5(this.#directory, { recursive: true, mode: 448 });
29113
+ const temporary = `${file2}.${randomUUID7()}.tmp`;
28658
29114
  try {
28659
29115
  await writeFile3(temporary, `${JSON.stringify(value2)}
28660
29116
  `, { mode: 384, flag: "wx" });
28661
- await rename3(temporary, file2);
29117
+ await rename4(temporary, file2);
28662
29118
  } finally {
28663
- await rm4(temporary, { force: true });
29119
+ await rm5(temporary, { force: true });
28664
29120
  }
28665
29121
  }
28666
29122
  return { path: value2, restartRequired: value2 !== initial };
@@ -28823,11 +29279,11 @@ function spawnOfficialAppServerConnection(input) {
28823
29279
  }
28824
29280
 
28825
29281
  // packages/host-runtime/src/account/codex-account-control.ts
28826
- function isRecord9(value2) {
29282
+ function isRecord10(value2) {
28827
29283
  return typeof value2 === "object" && value2 !== null && !Array.isArray(value2);
28828
29284
  }
28829
29285
  function currentCodexAccountFromOfficialRead(result) {
28830
- if (!isRecord9(result) || !isRecord9(result.account) || result.account.type !== "chatgpt") {
29286
+ if (!isRecord10(result) || !isRecord10(result.account) || result.account.type !== "chatgpt") {
28831
29287
  return null;
28832
29288
  }
28833
29289
  const email3 = external_exports.string().email().max(320).safeParse(result.account.email);
@@ -28857,8 +29313,8 @@ var SingleNativeCodexAccount = class {
28857
29313
  };
28858
29314
 
28859
29315
  // packages/host-runtime/src/account/codex-home-auth.ts
28860
- import { readFile as readFile7 } from "node:fs/promises";
28861
- import path13 from "node:path";
29316
+ import { readFile as readFile8 } from "node:fs/promises";
29317
+ import path15 from "node:path";
28862
29318
  var CODEX_API_AUTH_IDENTITY_FALLBACK = "BANK OF TOKEN";
28863
29319
  function tomlUnquote(value2) {
28864
29320
  const trimmed = value2.trim();
@@ -28979,7 +29435,7 @@ function inspectCodexAuthDocuments(input) {
28979
29435
  }
28980
29436
  async function readOptionalUtf8(file2) {
28981
29437
  try {
28982
- return await readFile7(file2, "utf8");
29438
+ return await readFile8(file2, "utf8");
28983
29439
  } catch (error51) {
28984
29440
  if (error51.code === "ENOENT") return void 0;
28985
29441
  throw error51;
@@ -29004,10 +29460,10 @@ function inspectCodexApiUsageSource(input) {
29004
29460
  return { baseUrl, apiKey };
29005
29461
  }
29006
29462
  async function inspectCodexHomeAuth(codexHome) {
29007
- const root = path13.resolve(codexHome);
29463
+ const root = path15.resolve(codexHome);
29008
29464
  const [configToml, authJson] = await Promise.all([
29009
- readOptionalUtf8(path13.join(root, "config.toml")),
29010
- readOptionalUtf8(path13.join(root, "auth.json"))
29465
+ readOptionalUtf8(path15.join(root, "config.toml")),
29466
+ readOptionalUtf8(path15.join(root, "auth.json"))
29011
29467
  ]);
29012
29468
  return inspectCodexAuthDocuments({
29013
29469
  ...configToml ? { configToml } : {},
@@ -29015,10 +29471,10 @@ async function inspectCodexHomeAuth(codexHome) {
29015
29471
  });
29016
29472
  }
29017
29473
  async function inspectCodexHomeApiUsageSource(codexHome, env = process.env) {
29018
- const root = path13.resolve(codexHome);
29474
+ const root = path15.resolve(codexHome);
29019
29475
  const [configToml, authJson] = await Promise.all([
29020
- readOptionalUtf8(path13.join(root, "config.toml")),
29021
- readOptionalUtf8(path13.join(root, "auth.json"))
29476
+ readOptionalUtf8(path15.join(root, "config.toml")),
29477
+ readOptionalUtf8(path15.join(root, "auth.json"))
29022
29478
  ]);
29023
29479
  return inspectCodexApiUsageSource({
29024
29480
  ...configToml ? { configToml } : {},
@@ -29029,7 +29485,7 @@ async function inspectCodexHomeApiUsageSource(codexHome, env = process.env) {
29029
29485
 
29030
29486
  // packages/host-runtime/src/account/codex-api-usage.ts
29031
29487
  var REQUEST_TIMEOUT_MS = 15e3;
29032
- function isRecord10(value2) {
29488
+ function isRecord11(value2) {
29033
29489
  return typeof value2 === "object" && value2 !== null && !Array.isArray(value2);
29034
29490
  }
29035
29491
  function finiteNumber(value2) {
@@ -29057,8 +29513,8 @@ function codexApiUsageUrl(baseUrl) {
29057
29513
  return parsed.toString();
29058
29514
  }
29059
29515
  function extractCodexApiUsage(response) {
29060
- if (!isRecord10(response)) return null;
29061
- const quota = isRecord10(response.quota) ? response.quota : void 0;
29516
+ if (!isRecord11(response)) return null;
29517
+ const quota = isRecord11(response.quota) ? response.quota : void 0;
29062
29518
  const remaining = finiteNumber(response.remaining) ?? finiteNumber(quota?.remaining) ?? finiteNumber(response.balance);
29063
29519
  if (remaining === void 0) return null;
29064
29520
  const isValid = boolean4(response.is_active) ?? boolean4(response.isValid) ?? true;
@@ -29134,13 +29590,13 @@ function projectCodexAccountAuth(snapshot, homeAuth) {
29134
29590
  }
29135
29591
 
29136
29592
  // packages/host-runtime/src/codex-runtime/official-runtime-owner.ts
29137
- import { randomUUID as randomUUID8 } from "node:crypto";
29593
+ import { randomUUID as randomUUID9 } from "node:crypto";
29138
29594
 
29139
29595
  // packages/host-runtime/src/official-request-broker.ts
29140
- import { randomUUID as randomUUID7 } from "node:crypto";
29596
+ import { randomUUID as randomUUID8 } from "node:crypto";
29141
29597
  var INTERNAL_REQUEST_PREFIX = "codexhost:official:";
29142
29598
  var MAX_RETIRED_IDS = 1024;
29143
- function isRecord11(value2) {
29599
+ function isRecord12(value2) {
29144
29600
  return typeof value2 === "object" && value2 !== null && !Array.isArray(value2);
29145
29601
  }
29146
29602
  var OfficialRequestBroker = class {
@@ -29153,7 +29609,7 @@ var OfficialRequestBroker = class {
29153
29609
  constructor(input) {
29154
29610
  this.#send = input.send;
29155
29611
  this.#timeoutMs = input.timeoutMs ?? 3e4;
29156
- this.#nextId = input.nextId ?? (() => `${INTERNAL_REQUEST_PREFIX}${randomUUID7()}`);
29612
+ this.#nextId = input.nextId ?? (() => `${INTERNAL_REQUEST_PREFIX}${randomUUID8()}`);
29157
29613
  }
29158
29614
  get pendingCount() {
29159
29615
  return this.#pending.size;
@@ -29183,7 +29639,7 @@ var OfficialRequestBroker = class {
29183
29639
  });
29184
29640
  }
29185
29641
  handle(value2) {
29186
- if (!isRecord11(value2) || typeof value2.id !== "string") return false;
29642
+ if (!isRecord12(value2) || typeof value2.id !== "string") return false;
29187
29643
  const pending = this.#pending.get(value2.id);
29188
29644
  if (!pending) return this.#retired.has(value2.id);
29189
29645
  clearTimeout(pending.timeout);
@@ -29507,7 +29963,7 @@ var OfficialRuntimeOwner = class {
29507
29963
  }
29508
29964
  #attach(role, output, onBackendStopped) {
29509
29965
  const client = {
29510
- id: randomUUID8(),
29966
+ id: randomUUID9(),
29511
29967
  role,
29512
29968
  output,
29513
29969
  ...onBackendStopped ? { onBackendStopped } : {},
@@ -29665,7 +30121,7 @@ var OfficialRuntimeOwner = class {
29665
30121
  if (!object4(value2)) return client.output(event);
29666
30122
  if (typeof value2.id === "string" || typeof value2.id === "number") {
29667
30123
  if (typeof value2.method === "string") {
29668
- const id2 = `codexhost:server:${client.id}:${event.generation}:${randomUUID8()}`;
30124
+ const id2 = `codexhost:server:${client.id}:${event.generation}:${randomUUID9()}`;
29669
30125
  client.serverRequests.set(id2, value2.id);
29670
30126
  const projected = { ...value2, id: id2 };
29671
30127
  return client.output({
@@ -29903,11 +30359,11 @@ function createOwnedConnectionBackend(factory) {
29903
30359
  }
29904
30360
 
29905
30361
  // packages/host-runtime/src/route-observation.ts
29906
- function isRecord12(value2) {
30362
+ function isRecord13(value2) {
29907
30363
  return typeof value2 === "object" && value2 !== null && !Array.isArray(value2);
29908
30364
  }
29909
30365
  function classifyThreadPurpose(request) {
29910
- return isRecord12(request.params) && request.params.ephemeral === true ? "ephemeral" : "conversation";
30366
+ return isRecord13(request.params) && request.params.ephemeral === true ? "ephemeral" : "conversation";
29911
30367
  }
29912
30368
  var RequestRouteObservationTracker = class {
29913
30369
  #nextCreateOrdinal = 0;
@@ -29932,13 +30388,13 @@ var RequestRouteObservationTracker = class {
29932
30388
  this.#createByThreadId.set(threadId2, tracked);
29933
30389
  }
29934
30390
  bindOfficialResponse(response) {
29935
- if (!isRecord12(response) || !("id" in response)) return;
30391
+ if (!isRecord13(response) || !("id" in response)) return;
29936
30392
  const tracked = this.#pendingByRequestId.get(response.id);
29937
30393
  if (!tracked) return;
29938
30394
  this.#pendingByRequestId.delete(response.id);
29939
30395
  const result = response.result;
29940
- const thread = isRecord12(result) ? result.thread : null;
29941
- if (isRecord12(thread) && typeof thread.id === "string") {
30396
+ const thread = isRecord13(result) ? result.thread : null;
30397
+ if (isRecord13(thread) && typeof thread.id === "string") {
29942
30398
  this.#createByThreadId.set(thread.id, tracked);
29943
30399
  }
29944
30400
  }
@@ -30060,25 +30516,25 @@ function resolveExternalSessionTreeIds(records) {
30060
30516
  const resolve = (start) => {
30061
30517
  const cached2 = resolved.get(start.hostThreadId);
30062
30518
  if (cached2) return cached2;
30063
- const path28 = [];
30519
+ const path29 = [];
30064
30520
  const visited = /* @__PURE__ */ new Set();
30065
30521
  let current = start;
30066
30522
  while (true) {
30067
30523
  const known = resolved.get(current.hostThreadId);
30068
30524
  if (known) {
30069
- for (const record3 of path28) resolved.set(record3.hostThreadId, known);
30525
+ for (const record3 of path29) resolved.set(record3.hostThreadId, known);
30070
30526
  return known;
30071
30527
  }
30072
30528
  if (visited.has(current.hostThreadId)) {
30073
30529
  throw new Error("External Thread Fork tree contains a cycle");
30074
30530
  }
30075
30531
  visited.add(current.hostThreadId);
30076
- path28.push(current);
30532
+ path29.push(current);
30077
30533
  const sourceId = current.subagent?.parentHostThreadId ?? current.forkSource?.hostThreadId;
30078
30534
  const source = sourceId ? byId.get(sourceId) : void 0;
30079
30535
  if (!source) {
30080
30536
  const root = current.hostThreadId;
30081
- for (const record3 of path28) resolved.set(record3.hostThreadId, root);
30537
+ for (const record3 of path29) resolved.set(record3.hostThreadId, root);
30082
30538
  return root;
30083
30539
  }
30084
30540
  current = source;
@@ -30132,11 +30588,11 @@ var OfficialThreadListError = class extends Error {
30132
30588
  }
30133
30589
  rpcError;
30134
30590
  };
30135
- function isRecord13(value2) {
30591
+ function isRecord14(value2) {
30136
30592
  return typeof value2 === "object" && value2 !== null && !Array.isArray(value2);
30137
30593
  }
30138
30594
  function officialThreadListPageFromResponse(response) {
30139
- if (isRecord13(response.error)) {
30595
+ if (isRecord14(response.error)) {
30140
30596
  if (!Number.isSafeInteger(response.error.code) || typeof response.error.message !== "string") {
30141
30597
  throw new Error("Official thread/list error response is invalid");
30142
30598
  }
@@ -30308,14 +30764,14 @@ var THREAD_USAGE_UPDATED_METHOD = "codexhost/thread/usage/updated";
30308
30764
  function delay3(milliseconds) {
30309
30765
  return new Promise((resolve) => setTimeout(resolve, milliseconds));
30310
30766
  }
30311
- function isRecord14(value2) {
30767
+ function isRecord15(value2) {
30312
30768
  return typeof value2 === "object" && value2 !== null && !Array.isArray(value2);
30313
30769
  }
30314
30770
  function isCreditsAdapter(adapter) {
30315
30771
  return typeof adapter.credits === "function";
30316
30772
  }
30317
30773
  function projectAccountCredits(value2) {
30318
- if (!isRecord14(value2)) return null;
30774
+ if (!isRecord15(value2)) return null;
30319
30775
  const rest = { ...value2 };
30320
30776
  delete rest.fetchedAt;
30321
30777
  const parsed = accountCreditsSnapshotSchema.safeParse(rest);
@@ -30441,12 +30897,12 @@ function classifyCreateRequestRoute(request, defaultAgent) {
30441
30897
  };
30442
30898
  }
30443
30899
  function requestObject(request) {
30444
- if (!isRecord14(request.params)) throw new Error(`${request.method} params must be an object`);
30900
+ if (!isRecord15(request.params)) throw new Error(`${request.method} params must be an object`);
30445
30901
  return request.params;
30446
30902
  }
30447
30903
  function requestText(params) {
30448
30904
  if (!Array.isArray(params.input)) throw new Error("turn/start input must be an array");
30449
- const text2 = params.input.filter((item) => isRecord14(item) && item.type === "text").map((item) => item.text).filter((value2) => typeof value2 === "string").join("\n");
30905
+ const text2 = params.input.filter((item) => isRecord15(item) && item.type === "text").map((item) => item.text).filter((value2) => typeof value2 === "string").join("\n");
30450
30906
  if (!text2) throw new Error("turn/start must contain text input");
30451
30907
  return text2;
30452
30908
  }
@@ -30501,6 +30957,7 @@ var AppServerHost = class {
30501
30957
  #accountInspections = new HarnessAccountInspectionCache();
30502
30958
  #externalRuntime;
30503
30959
  #externalSteering = new ExternalTurnSteering();
30960
+ #liveCommandCache = new LiveCommandCatalogCache();
30504
30961
  #repository;
30505
30962
  #pendingDesktopApprovals = /* @__PURE__ */ new Map();
30506
30963
  #pendingDesktopQuestions = /* @__PURE__ */ new Map();
@@ -30542,7 +30999,7 @@ var AppServerHost = class {
30542
30999
  this.#launchSettings = new HarnessLaunchSettingsStore(
30543
31000
  this.#options.pluginContext?.environment ?? environment
30544
31001
  );
30545
- const permanentHome = path14.resolve(environment.CODEX_HOME ?? path14.join(os4.homedir(), ".codex"));
31002
+ const permanentHome = path16.resolve(environment.CODEX_HOME ?? path16.join(os5.homedir(), ".codex"));
30546
31003
  this.#ownsOfficialRuntimeScope = options2.officialRuntimeScope === void 0;
30547
31004
  this.#officialRuntimeScope = options2.officialRuntimeScope ?? new OfficialRuntimeScope({
30548
31005
  diagnosticOutput: this.#options.diagnosticOutput,
@@ -30810,12 +31267,12 @@ var AppServerHost = class {
30810
31267
  for (const resolve of waiters) resolve();
30811
31268
  }
30812
31269
  #observeOfficialTurnStartResponse(value2) {
30813
- if (!isRecord14(value2) || !("id" in value2)) return;
31270
+ if (!isRecord15(value2) || !("id" in value2)) return;
30814
31271
  const threadId2 = this.#pendingOfficialTurnStarts.get(value2.id);
30815
31272
  if (!threadId2) return;
30816
31273
  this.#pendingOfficialTurnStarts.delete(value2.id);
30817
- const result = isRecord14(value2.result) ? value2.result : null;
30818
- const turn = result && isRecord14(result.turn) ? result.turn : null;
31274
+ const result = isRecord15(value2.result) ? value2.result : null;
31275
+ const turn = result && isRecord15(result.turn) ? result.turn : null;
30819
31276
  if (turn && typeof turn.id === "string") {
30820
31277
  this.#activeOfficialTurns.set(threadId2, turn.id);
30821
31278
  }
@@ -30829,7 +31286,7 @@ var AppServerHost = class {
30829
31286
  async #forwardDesktop() {
30830
31287
  for await (const frame of readLfFrames(this.#options.desktopInput)) {
30831
31288
  const parsed = parseJsonFrame(frame);
30832
- if (isRecord14(parsed) && parsed.method === "initialized" && !("id" in parsed)) {
31289
+ if (isRecord15(parsed) && parsed.method === "initialized" && !("id" in parsed)) {
30833
31290
  continue;
30834
31291
  }
30835
31292
  if (await this.#handleDesktopApprovalResponse(parsed)) continue;
@@ -30853,7 +31310,7 @@ var AppServerHost = class {
30853
31310
  }
30854
31311
  continue;
30855
31312
  }
30856
- const threadId2 = isRecord14(request.params) && typeof request.params.threadId === "string" ? request.params.threadId : void 0;
31313
+ const threadId2 = isRecord15(request.params) && typeof request.params.threadId === "string" ? request.params.threadId : void 0;
30857
31314
  this.#dispatchDesktopRequest(
30858
31315
  () => this.#desktopRequests.run(
30859
31316
  threadId2,
@@ -31081,7 +31538,7 @@ var AppServerHost = class {
31081
31538
  rpcError(request, -32602, "Invalid Harness command inspection params")
31082
31539
  );
31083
31540
  } else {
31084
- await this.#writeHarnessCommandCatalog(request, params.data.harnessId);
31541
+ await this.#writeHarnessCommandCatalog(request, params.data.harnessId, params.data.cwd);
31085
31542
  }
31086
31543
  return;
31087
31544
  }
@@ -31185,7 +31642,7 @@ var AppServerHost = class {
31185
31642
  return;
31186
31643
  }
31187
31644
  if (request.method === "thread/fork") {
31188
- const params = isRecord14(request.params) ? request.params : {};
31645
+ const params = isRecord15(request.params) ? request.params : {};
31189
31646
  const resolution = typeof params.threadId === "string" ? await this.#resolveExternalThread(params.threadId) : { kind: "official" };
31190
31647
  if (resolution.kind === "error") {
31191
31648
  await this.#writer.json(rpcError(request, resolution.error.code, resolution.error.message));
@@ -31206,7 +31663,7 @@ var AppServerHost = class {
31206
31663
  }
31207
31664
  }
31208
31665
  if (request.method === "thread/revert") {
31209
- const params = isRecord14(request.params) ? request.params : {};
31666
+ const params = isRecord15(request.params) ? request.params : {};
31210
31667
  const resolution = typeof params.threadId === "string" ? await this.#resolveExternalThread(params.threadId) : { kind: "official" };
31211
31668
  if (resolution.kind === "error") {
31212
31669
  await this.#writer.json(rpcError(request, resolution.error.code, resolution.error.message));
@@ -31227,7 +31684,7 @@ var AppServerHost = class {
31227
31684
  }
31228
31685
  }
31229
31686
  if (request.method === "thread/rollback") {
31230
- const params = isRecord14(request.params) ? request.params : {};
31687
+ const params = isRecord15(request.params) ? request.params : {};
31231
31688
  const resolution = typeof params.threadId === "string" ? await this.#resolveExternalThread(params.threadId) : { kind: "official" };
31232
31689
  if (resolution.kind === "error") {
31233
31690
  await this.#writer.json(rpcError(request, resolution.error.code, resolution.error.message));
@@ -31383,7 +31840,7 @@ var AppServerHost = class {
31383
31840
  return;
31384
31841
  }
31385
31842
  }
31386
- if (request.method.startsWith("thread/") && !EXPLICIT_EXTERNAL_THREAD_METHODS.has(request.method) && isRecord14(request.params) && typeof request.params.threadId === "string") {
31843
+ if (request.method.startsWith("thread/") && !EXPLICIT_EXTERNAL_THREAD_METHODS.has(request.method) && isRecord15(request.params) && typeof request.params.threadId === "string") {
31387
31844
  const location = await this.#locateExternalThread(request.params.threadId);
31388
31845
  if (await this.#writeResolutionError(request, location)) return;
31389
31846
  if (location.kind === "external") {
@@ -31393,10 +31850,30 @@ var AppServerHost = class {
31393
31850
  return;
31394
31851
  }
31395
31852
  }
31396
- await this.#forwardOfficialRequest(request, frame);
31853
+ await this.#forwardOfficialRequest(
31854
+ request,
31855
+ await this.#rewriteOfficialDelegationMentions(request, frame)
31856
+ );
31857
+ }
31858
+ /** Native Codex Turns: turn `#` delegation chips into an explicit Skill-backed request. */
31859
+ async #rewriteOfficialDelegationMentions(request, frame) {
31860
+ if (request.method !== "turn/start" && request.method !== "turn/steer") return frame;
31861
+ if (!isRecord15(request.params) || !Array.isArray(request.params.input)) return frame;
31862
+ const input = request.params.input;
31863
+ if (!input.some(
31864
+ (item) => isRecord15(item) && typeof item.text === "string" && item.text.includes(DELEGATION_MENTION_PATH_PREFIX)
31865
+ )) {
31866
+ return frame;
31867
+ }
31868
+ const rewritten = rewriteDelegationMentionInput(input, await managedDelegationSkillReference());
31869
+ if (!rewritten) return frame;
31870
+ return encodeJsonFrame({
31871
+ ...request,
31872
+ params: { ...request.params, input: rewritten }
31873
+ });
31397
31874
  }
31398
31875
  async #forwardOfficialNonRequest(value2, frame) {
31399
- const response = isRecord14(value2) ? value2 : null;
31876
+ const response = isRecord15(value2) ? value2 : null;
31400
31877
  const request = response && (typeof response.id === "string" || typeof response.id === "number") ? this.#officialServerRequests.get(response.id) : null;
31401
31878
  if (request !== void 0 && response) {
31402
31879
  this.#officialServerRequests.delete(response.id);
@@ -31425,7 +31902,7 @@ var AppServerHost = class {
31425
31902
  const parsed = input.value;
31426
31903
  this.#observeOfficialTurnStartResponse(parsed);
31427
31904
  let forwarded = parsed;
31428
- if (isRecord14(parsed) && typeof parsed.method === "string" && "id" in parsed) {
31905
+ if (isRecord15(parsed) && typeof parsed.method === "string" && "id" in parsed) {
31429
31906
  const originalId = parsed.id;
31430
31907
  if (typeof originalId === "string" || typeof originalId === "number") {
31431
31908
  const forwardedId = `codexhost:official:${++this.#nextOfficialServerRequestId}`;
@@ -31433,7 +31910,7 @@ var AppServerHost = class {
31433
31910
  forwarded = { ...parsed, id: forwardedId };
31434
31911
  }
31435
31912
  }
31436
- const accountScopedNotification = isRecord14(parsed) && typeof parsed.method === "string" && (parsed.method === "account/updated" || parsed.method.startsWith("account/rateLimits/"));
31913
+ const accountScopedNotification = isRecord15(parsed) && typeof parsed.method === "string" && (parsed.method === "account/updated" || parsed.method.startsWith("account/rateLimits/"));
31437
31914
  if (accountScopedNotification) {
31438
31915
  if (parsed.method === "account/updated") this.#officialRateLimits.reset(input.accountId);
31439
31916
  }
@@ -31534,10 +32011,10 @@ var AppServerHost = class {
31534
32011
  }
31535
32012
  }
31536
32013
  async #observeOfficialTurnLifecycle(value2) {
31537
- if (!isRecord14(value2) || !isRecord14(value2.params)) return;
32014
+ if (!isRecord15(value2) || !isRecord15(value2.params)) return;
31538
32015
  const params = value2.params;
31539
32016
  if (value2.method === "turn/started" && typeof params.threadId === "string") {
31540
- const turn = isRecord14(params.turn) ? params.turn : null;
32017
+ const turn = isRecord15(params.turn) ? params.turn : null;
31541
32018
  if (turn && typeof turn.id === "string") {
31542
32019
  this.#forgetPendingOfficialTurnStarts(params.threadId);
31543
32020
  this.#activeOfficialTurns.set(params.threadId, turn.id);
@@ -31550,7 +32027,7 @@ var AppServerHost = class {
31550
32027
  const delegation = await this.#repository.getDelegationByChild(
31551
32028
  hostThreadIdSchema.parse(params.threadId)
31552
32029
  );
31553
- const turn = isRecord14(params.turn) ? params.turn : null;
32030
+ const turn = isRecord15(params.turn) ? params.turn : null;
31554
32031
  const status = turn?.status === "failed" ? "failed" : turn?.status === "interrupted" || turn?.status === "cancelled" ? "interrupted" : "completed";
31555
32032
  if (this.#pendingOfficialDelegationThreads.has(params.threadId)) {
31556
32033
  this.#pendingOfficialTerminalStatuses.set(params.threadId, status);
@@ -31580,28 +32057,28 @@ var AppServerHost = class {
31580
32057
  }
31581
32058
  async #readOfficialThreadCwd(threadId2) {
31582
32059
  const response = await this.#requestOfficial("thread/read", { threadId: threadId2 });
31583
- if (isRecord14(response.error)) return void 0;
31584
- const result = isRecord14(response.result) ? response.result : null;
31585
- const thread = result && isRecord14(result.thread) ? result.thread : null;
32060
+ if (isRecord15(response.error)) return void 0;
32061
+ const result = isRecord15(response.result) ? response.result : null;
32062
+ const thread = result && isRecord15(result.thread) ? result.thread : null;
31586
32063
  return thread && typeof thread.cwd === "string" && thread.cwd.trim() ? thread.cwd : void 0;
31587
32064
  }
31588
32065
  async #inspectOfficialDelegationTarget(input) {
31589
32066
  const response = await this.#requestOfficial("model/list", {});
31590
- if (isRecord14(response.error)) {
32067
+ if (isRecord15(response.error)) {
31591
32068
  throw new DelegationControlError(
31592
32069
  "DELEGATION_FAILED",
31593
32070
  typeof response.error.message === "string" ? response.error.message : "Official Model catalog could not be read"
31594
32071
  );
31595
32072
  }
31596
- const result = isRecord14(response.result) ? response.result : null;
32073
+ const result = isRecord15(response.result) ? response.result : null;
31597
32074
  const data = result && Array.isArray(result.data) ? result.data : [];
31598
32075
  const thinkingById = /* @__PURE__ */ new Map();
31599
32076
  const models = data.flatMap((candidate) => {
31600
- if (!isRecord14(candidate) || typeof candidate.model !== "string" || !candidate.model.trim()) {
32077
+ if (!isRecord15(candidate) || typeof candidate.model !== "string" || !candidate.model.trim()) {
31601
32078
  return [];
31602
32079
  }
31603
32080
  const supportedThinkingOptionIds = Array.isArray(candidate.supportedReasoningEfforts) ? candidate.supportedReasoningEfforts.flatMap((option) => {
31604
- if (!isRecord14(option) || typeof option.reasoningEffort !== "string" || !option.reasoningEffort.trim()) {
32081
+ if (!isRecord15(option) || typeof option.reasoningEffort !== "string" || !option.reasoningEffort.trim()) {
31605
32082
  return [];
31606
32083
  }
31607
32084
  const id2 = harnessThinkingOptionIdSchema.safeParse(option.reasoningEffort);
@@ -31621,9 +32098,9 @@ var AppServerHost = class {
31621
32098
  ];
31622
32099
  });
31623
32100
  const defaultEntry = data.find(
31624
- (candidate) => isRecord14(candidate) && candidate.isDefault === true
32101
+ (candidate) => isRecord15(candidate) && candidate.isDefault === true
31625
32102
  );
31626
- const defaultModel = isRecord14(defaultEntry) && typeof defaultEntry.model === "string" ? encodeOfficialCodexModelRef(defaultEntry.model) : void 0;
32103
+ const defaultModel = isRecord15(defaultEntry) && typeof defaultEntry.model === "string" ? encodeOfficialCodexModelRef(defaultEntry.model) : void 0;
31627
32104
  return {
31628
32105
  harnessId: input.harnessId,
31629
32106
  inspection: {
@@ -31653,7 +32130,7 @@ var AppServerHost = class {
31653
32130
  throw new DelegationControlError("INVALID_ARGUMENT", "Official Model Ref is invalid");
31654
32131
  }
31655
32132
  const nativeModelId = requestedModel ? decodeOfficialCodexModelRef(requestedModel) : void 0;
31656
- const digest2 = createHash7("sha256").update(
32133
+ const digest2 = createHash8("sha256").update(
31657
32134
  JSON.stringify({
31658
32135
  task: input.task,
31659
32136
  cwd: input.cwd,
@@ -31729,8 +32206,8 @@ var AppServerHost = class {
31729
32206
  ephemeral: false,
31730
32207
  historyMode: "paginated"
31731
32208
  });
31732
- const startedResult = isRecord14(started.result) ? started.result : null;
31733
- const thread = startedResult && isRecord14(startedResult.thread) ? startedResult.thread : null;
32209
+ const startedResult = isRecord15(started.result) ? started.result : null;
32210
+ const thread = startedResult && isRecord15(startedResult.thread) ? startedResult.thread : null;
31734
32211
  const threadId2 = thread && typeof thread.id === "string" ? thread.id : null;
31735
32212
  if (!threadId2) throw new Error("Official thread/start returned no Thread identity");
31736
32213
  this.#pendingOfficialDelegationThreads.add(threadId2);
@@ -31742,8 +32219,8 @@ var AppServerHost = class {
31742
32219
  ...nativeModelId ? { model: nativeModelId } : {},
31743
32220
  ...input.thinkingOptionId ? { effort: input.thinkingOptionId } : {}
31744
32221
  });
31745
- const turnResult = isRecord14(turn.result) ? turn.result : null;
31746
- const turnValue = turnResult && isRecord14(turnResult.turn) ? turnResult.turn : null;
32222
+ const turnResult = isRecord15(turn.result) ? turn.result : null;
32223
+ const turnValue = turnResult && isRecord15(turnResult.turn) ? turnResult.turn : null;
31747
32224
  const parsedTurnId = turnValue && typeof turnValue.id === "string" ? turnValue.id : null;
31748
32225
  if (!parsedTurnId) throw new Error("Official turn/start returned no Turn identity");
31749
32226
  turnId = parsedTurnId;
@@ -31754,7 +32231,7 @@ var AppServerHost = class {
31754
32231
  throw error51;
31755
32232
  }
31756
32233
  this.#activeOfficialTurns.set(threadId2, turnId);
31757
- const delegationId = hostThreadIdSchema.parse(randomUUID9());
32234
+ const delegationId = hostThreadIdSchema.parse(randomUUID10());
31758
32235
  try {
31759
32236
  const source = await this.#repository.find(input.parentThreadId);
31760
32237
  const pendingTerminal = this.#pendingOfficialTerminalStatuses.get(threadId2);
@@ -31813,27 +32290,27 @@ var AppServerHost = class {
31813
32290
  threadId: input.threadId,
31814
32291
  includeTurns: true
31815
32292
  });
31816
- if (isRecord14(current.error) || !isRecord14(current.result)) {
32293
+ if (isRecord15(current.error) || !isRecord15(current.result)) {
31817
32294
  throw new DelegationControlError("THREAD_NOT_FOUND", "Official Thread was not found");
31818
32295
  }
31819
- const currentThread = isRecord14(current.result.thread) ? current.result.thread : null;
32296
+ const currentThread = isRecord15(current.result.thread) ? current.result.thread : null;
31820
32297
  const currentTurns = currentThread && Array.isArray(currentThread.turns) ? currentThread.turns : [];
31821
32298
  const latestTurn = currentTurns.at(-1);
31822
- if (currentThread && isRecord14(currentThread.status) && currentThread.status.type === "active" || isRecord14(latestTurn) && (latestTurn.status === "inProgress" || latestTurn.status === "running")) {
32299
+ if (currentThread && isRecord15(currentThread.status) && currentThread.status.type === "active" || isRecord15(latestTurn) && (latestTurn.status === "inProgress" || latestTurn.status === "running")) {
31823
32300
  throw new DelegationControlError("THREAD_BUSY", "Thread already has an active Turn");
31824
32301
  }
31825
32302
  const response = await this.#requestOfficial("turn/start", {
31826
32303
  threadId: input.threadId,
31827
32304
  input: [{ type: "text", text: input.message }]
31828
32305
  });
31829
- if (isRecord14(response.error)) {
32306
+ if (isRecord15(response.error)) {
31830
32307
  throw new DelegationControlError(
31831
32308
  "DELEGATION_FAILED",
31832
32309
  typeof response.error.message === "string" ? response.error.message : "Turn start failed"
31833
32310
  );
31834
32311
  }
31835
- const result = isRecord14(response.result) ? response.result : null;
31836
- const turn = result && isRecord14(result.turn) ? result.turn : null;
32312
+ const result = isRecord15(response.result) ? response.result : null;
32313
+ const turn = result && isRecord15(result.turn) ? result.turn : null;
31837
32314
  const turnId = turn && typeof turn.id === "string" ? turn.id : null;
31838
32315
  if (!turnId) throw new Error("Official turn/start returned no Turn identity");
31839
32316
  this.#activeOfficialTurns.set(input.threadId, turnId);
@@ -31855,13 +32332,13 @@ var AppServerHost = class {
31855
32332
  threadId: input.threadId,
31856
32333
  includeTurns: true
31857
32334
  });
31858
- if (isRecord14(current.error) || !isRecord14(current.result)) {
32335
+ if (isRecord15(current.error) || !isRecord15(current.result)) {
31859
32336
  throw new DelegationControlError("THREAD_NOT_FOUND", "Official Thread was not found");
31860
32337
  }
31861
- const currentThread = isRecord14(current.result.thread) ? current.result.thread : null;
32338
+ const currentThread = isRecord15(current.result.thread) ? current.result.thread : null;
31862
32339
  const currentTurns = currentThread && Array.isArray(currentThread.turns) ? currentThread.turns : [];
31863
32340
  const latestTurn = currentTurns.at(-1);
31864
- if (isRecord14(latestTurn) && typeof latestTurn.id === "string" && (latestTurn.status === "inProgress" || latestTurn.status === "running")) {
32341
+ if (isRecord15(latestTurn) && typeof latestTurn.id === "string" && (latestTurn.status === "inProgress" || latestTurn.status === "running")) {
31865
32342
  turnId = latestTurn.id;
31866
32343
  this.#activeOfficialTurns.set(input.threadId, turnId);
31867
32344
  } else {
@@ -31872,7 +32349,7 @@ var AppServerHost = class {
31872
32349
  threadId: input.threadId,
31873
32350
  turnId
31874
32351
  });
31875
- if (isRecord14(response.error)) {
32352
+ if (isRecord15(response.error)) {
31876
32353
  throw new DelegationControlError(
31877
32354
  "DELEGATION_FAILED",
31878
32355
  typeof response.error.message === "string" ? response.error.message : "Turn cancel failed"
@@ -31885,18 +32362,18 @@ var AppServerHost = class {
31885
32362
  threadId: input.threadId,
31886
32363
  includeTurns: true
31887
32364
  });
31888
- if (isRecord14(response.error)) {
32365
+ if (isRecord15(response.error)) {
31889
32366
  throw new DelegationControlError(
31890
32367
  "THREAD_NOT_FOUND",
31891
32368
  typeof response.error.message === "string" ? response.error.message : "Official Thread was not found"
31892
32369
  );
31893
32370
  }
31894
- const result = isRecord14(response.result) ? response.result : null;
31895
- const thread = result && isRecord14(result.thread) ? result.thread : null;
32371
+ const result = isRecord15(response.result) ? response.result : null;
32372
+ const thread = result && isRecord15(result.thread) ? result.thread : null;
31896
32373
  if (!thread)
31897
32374
  throw new DelegationControlError("THREAD_NOT_FOUND", "Official Thread was not found");
31898
- const turns = Array.isArray(thread.turns) ? thread.turns.filter((turn) => isRecord14(turn)) : [];
31899
- const running = this.#activeOfficialTurns.has(input.threadId) || isRecord14(thread.status) && thread.status.type === "active";
32375
+ const turns = Array.isArray(thread.turns) ? thread.turns.filter((turn) => isRecord15(turn)) : [];
32376
+ const running = this.#activeOfficialTurns.has(input.threadId) || isRecord15(thread.status) && thread.status.type === "active";
31900
32377
  const snapshot = projectDelegationThreadSnapshot({
31901
32378
  threadId: input.threadId,
31902
32379
  harnessId: "codex",
@@ -31918,7 +32395,7 @@ var AppServerHost = class {
31918
32395
  async #listDelegationThreads(input) {
31919
32396
  const [sortKey, sortDirection2] = input.sort.split("-");
31920
32397
  const request = {
31921
- id: `codexhost:delegation-list:${randomUUID9()}`,
32398
+ id: `codexhost:delegation-list:${randomUUID10()}`,
31922
32399
  method: "thread/list",
31923
32400
  params: {
31924
32401
  cwd: input.cwd ? [input.cwd] : null,
@@ -31946,7 +32423,7 @@ var AppServerHost = class {
31946
32423
  threads: result.data.flatMap((entry) => {
31947
32424
  if (typeof entry.id !== "string") return [];
31948
32425
  const record3 = records.find((candidate) => candidate.hostThreadId === entry.id);
31949
- const status = isRecord14(entry.status) && entry.status.type === "active" ? "running" : "completed";
32426
+ const status = isRecord15(entry.status) && entry.status.type === "active" ? "running" : "completed";
31950
32427
  return [
31951
32428
  {
31952
32429
  threadId: entry.id,
@@ -32304,21 +32781,67 @@ var AppServerHost = class {
32304
32781
  await this.#writer.json(rpcEnvelope(request, { result: { commands: [] } }));
32305
32782
  return;
32306
32783
  }
32307
- await this.#writeHarnessCommandCatalog(request, location.record.harnessId);
32784
+ const loaded = this.#externalRuntime.get(params.data.threadId);
32785
+ if (loaded) {
32786
+ const catalog = await this.#inspectLoadedCommands(loaded);
32787
+ if (catalog) {
32788
+ await this.#writer.json(rpcEnvelope(request, { result: jsonValueSchema.parse(catalog) }));
32789
+ return;
32790
+ }
32791
+ }
32792
+ await this.#writeHarnessCommandCatalog(
32793
+ request,
32794
+ location.record.harnessId,
32795
+ loaded?.cwd ?? location.record.cwd,
32796
+ params.data.threadId
32797
+ );
32308
32798
  }
32309
- async #writeHarnessCommandCatalog(request, harnessId) {
32799
+ /**
32800
+ * Catalog of a loaded Session, marked live or static. A live catalog is
32801
+ * remembered for its Harness and workspace so later drafts there can show it.
32802
+ */
32803
+ async #inspectLoadedCommands(thread) {
32804
+ if (!thread.session.commands) return null;
32805
+ const catalog = await inspectLiveCommandCatalog(thread.session.commands);
32806
+ if (!catalog) return null;
32807
+ const staticCatalog = this.#externalAdapters.get(thread.harnessId)?.commandCatalog;
32808
+ if (staticCatalog && !isLiveCommandCatalog(catalog, staticCatalog)) return null;
32809
+ const live = { ...catalog, source: "live" };
32810
+ this.#liveCommandCache.remember(thread.harnessId, thread.cwd, live);
32811
+ return live;
32812
+ }
32813
+ async #writeHarnessCommandCatalog(request, harnessId, cwd, inspectedThreadId) {
32310
32814
  await this.#waitForPlugins();
32311
32815
  const adapter = this.#externalAdapters.get(harnessId);
32312
32816
  if (!adapter) {
32313
32817
  await this.#writer.json(rpcError(request, -32077, `Harness '${harnessId}' is unavailable`));
32314
32818
  return;
32315
32819
  }
32820
+ let catalog;
32316
32821
  try {
32317
- const catalog = harnessCommandCatalogSchema.parse(adapter.commandCatalog ?? { commands: [] });
32318
- await this.#writer.json(rpcEnvelope(request, { result: jsonValueSchema.parse(catalog) }));
32822
+ catalog = harnessCommandCatalogSchema.parse({
32823
+ ...adapter.commandCatalog ?? { commands: [] },
32824
+ ...adapter.liveCommandCatalog ? { source: "static" } : {}
32825
+ });
32319
32826
  } catch {
32320
32827
  await this.#writer.json(rpcError(request, -32078, "Harness command catalog is invalid"));
32828
+ return;
32321
32829
  }
32830
+ if (cwd && adapter.liveCommandCatalog) {
32831
+ for (const thread of this.#externalRuntime.values()) {
32832
+ if (thread.id === inspectedThreadId) continue;
32833
+ if (thread.harnessId !== harnessId || !sameWorkspace(thread.cwd, cwd)) continue;
32834
+ const live = await this.#inspectLoadedCommands(thread);
32835
+ if (live) {
32836
+ catalog = live;
32837
+ break;
32838
+ }
32839
+ }
32840
+ if (catalog.source === "static") {
32841
+ catalog = this.#liveCommandCache.lookup(harnessId, cwd) ?? catalog;
32842
+ }
32843
+ }
32844
+ await this.#writer.json(rpcEnvelope(request, { result: jsonValueSchema.parse(catalog) }));
32322
32845
  }
32323
32846
  async #executeThreadCommand(request) {
32324
32847
  const params = threadCommandExecuteParamsSchema.safeParse(request.params);
@@ -32370,39 +32893,43 @@ var AppServerHost = class {
32370
32893
  return;
32371
32894
  }
32372
32895
  try {
32373
- await this.#startExternalCommand(
32374
- request,
32896
+ const started = await this.#beginExternalCommand(
32375
32897
  thread,
32376
32898
  params.commandId,
32377
32899
  params.arguments,
32378
- params.turnId,
32379
- "command"
32900
+ params.turnId
32380
32901
  );
32902
+ try {
32903
+ const result = threadCommandExecuteResultSchema.parse({
32904
+ accepted: true,
32905
+ turnId: started.turnId
32906
+ });
32907
+ await this.#writer.json(rpcEnvelope(request, { result: jsonValueSchema.parse(result) }));
32908
+ } finally {
32909
+ started.gate.resolve();
32910
+ }
32381
32911
  } catch (error51) {
32382
32912
  this.#diagnose(error51);
32383
32913
  await this.#writer.json(
32384
- rpcError(request, -32073, `External Harness command failed: ${errorMessage3(error51)}`)
32914
+ error51 instanceof ExternalCommandError ? rpcError(request, error51.code, error51.message) : rpcError(request, -32073, `External Harness command failed: ${errorMessage3(error51)}`)
32385
32915
  );
32386
32916
  }
32387
32917
  } finally {
32388
32918
  this.#pendingExternalCommandRequests.delete(thread.id);
32389
32919
  }
32390
32920
  }
32391
- async #startExternalCommand(request, thread, commandId, arguments_2, requestedTurnId, responseKind) {
32921
+ async #beginExternalCommand(thread, commandId, arguments_2, requestedTurnId) {
32392
32922
  const commands = thread.session.commands;
32393
32923
  if (!commands) {
32394
- await this.#writer.json(
32395
- rpcError(request, -32078, "External Harness does not expose commands")
32396
- );
32397
- return;
32924
+ throw new ExternalCommandError(-32078, "External Harness does not expose commands");
32398
32925
  }
32399
- if (thread.running || this.#externalSteering.hasPending(thread.id)) {
32400
- await this.#writer.json(
32401
- rpcError(request, -32072, "External Thread already has an active operation")
32402
- );
32403
- return;
32926
+ if (this.#closeRequested || this.#externalRuntime.get(thread.id) !== thread) {
32927
+ throw new ExternalCommandError(-32073, "External Thread is no longer available");
32928
+ }
32929
+ if (thread.running || thread.activeTurnId) {
32930
+ throw new ExternalCommandError(-32072, "External Thread already has an active operation");
32404
32931
  }
32405
- const turnId = requestedTurnId ?? hostTurnIdSchema.parse(randomUUID9());
32932
+ const turnId = requestedTurnId ?? hostTurnIdSchema.parse(randomUUID10());
32406
32933
  const projection = {
32407
32934
  projector: new CodexTurnProjector({
32408
32935
  threadId: thread.id,
@@ -32417,13 +32944,14 @@ var AppServerHost = class {
32417
32944
  thread.projectedTurns.set(turnId, projection);
32418
32945
  thread.responseGates.set(turnId, gate);
32419
32946
  thread.ephemeralTurnIds.add(turnId);
32420
- let result;
32421
32947
  try {
32422
- result = await commands.execute({
32948
+ const result = await commands.execute({
32423
32949
  turnId,
32424
32950
  commandId,
32425
32951
  ...arguments_2 ? { arguments: arguments_2 } : {}
32426
32952
  });
32953
+ if (!result.ok) throw new ExternalCommandError(-32073, result.error.message);
32954
+ return { turnId: result.value.turnId, turn: projection.projector.pendingTurn(), gate };
32427
32955
  } catch (error51) {
32428
32956
  thread.running = false;
32429
32957
  thread.activeTurnId = null;
@@ -32434,28 +32962,6 @@ var AppServerHost = class {
32434
32962
  this.#signalActiveWorkChanged();
32435
32963
  throw error51;
32436
32964
  }
32437
- if (!result.ok) {
32438
- thread.running = false;
32439
- thread.activeTurnId = null;
32440
- thread.projectedTurns.delete(turnId);
32441
- thread.responseGates.delete(turnId);
32442
- thread.ephemeralTurnIds.delete(turnId);
32443
- gate.resolve();
32444
- this.#signalActiveWorkChanged();
32445
- await this.#writer.json(rpcError(request, -32073, result.error.message));
32446
- return;
32447
- }
32448
- try {
32449
- const response = responseKind === "command" ? jsonValueSchema.parse(
32450
- threadCommandExecuteResultSchema.parse({
32451
- accepted: true,
32452
- turnId: result.value.turnId
32453
- })
32454
- ) : { turn: projection.projector.pendingTurn() };
32455
- await this.#writer.json(rpcEnvelope(request, { result: response }));
32456
- } finally {
32457
- gate.resolve();
32458
- }
32459
32965
  }
32460
32966
  async #selectThreadModel(request) {
32461
32967
  const params = threadModelSelectParamsSchema.safeParse(request.params);
@@ -33078,10 +33584,10 @@ var AppServerHost = class {
33078
33584
  ...typeof params.serviceTier === "string" ? { serviceTier: params.serviceTier } : {}
33079
33585
  });
33080
33586
  try {
33081
- if (params.initialTurnsPage !== void 0 && params.initialTurnsPage !== null && !isRecord14(params.initialTurnsPage)) {
33587
+ if (params.initialTurnsPage !== void 0 && params.initialTurnsPage !== null && !isRecord15(params.initialTurnsPage)) {
33082
33588
  throw new ExternalHistoryRequestError("initialTurnsPage must be an object");
33083
33589
  }
33084
- const initialPageParams = isRecord14(params.initialTurnsPage) ? params.initialTurnsPage : null;
33590
+ const initialPageParams = isRecord15(params.initialTurnsPage) ? params.initialTurnsPage : null;
33085
33591
  const initialTurnsPage = initialPageParams ? listExternalTurns(turns, initialPageParams) : null;
33086
33592
  const paginated = thread.record.historyMode === "paginated";
33087
33593
  const turnsBackwardsCursor = paginated ? listExternalTurns(turns, { limit: 1, itemsView: "notLoaded" }).backwardsCursor : null;
@@ -33176,53 +33682,8 @@ var AppServerHost = class {
33176
33682
  await this.#writer.json(rpcError(request, -32602, errorMessage3(error51)));
33177
33683
  return;
33178
33684
  }
33179
- const commandCandidate = text2.trimStart();
33180
- if (thread.session.commands && /^\/[^\s/]+(?:\s|$)/u.test(commandCandidate)) {
33181
- const commandText = commandCandidate.trimEnd();
33182
- this.#pendingExternalCommandRequests.add(thread.id);
33183
- try {
33184
- const catalog = await thread.session.commands.list();
33185
- if (!catalog.ok) {
33186
- await this.#writer.json(rpcError(request, -32073, catalog.error.message));
33187
- return;
33188
- }
33189
- const matched = catalog.value.commands.toSorted((left, right) => right.invocation.length - left.invocation.length).find((command) => {
33190
- if (commandText === command.invocation) return true;
33191
- return command.argumentMode === "text" && commandText.startsWith(`${command.invocation} `);
33192
- });
33193
- if (matched) {
33194
- const argumentText = commandText.slice(matched.invocation.length).trimStart();
33195
- try {
33196
- await this.#startExternalCommand(
33197
- request,
33198
- thread,
33199
- matched.id,
33200
- argumentText.length > 0 ? { text: argumentText } : void 0,
33201
- void 0,
33202
- "turn"
33203
- );
33204
- } catch (error51) {
33205
- this.#diagnose(error51);
33206
- await this.#writer.json(
33207
- rpcError(request, -32073, `External Harness command failed: ${errorMessage3(error51)}`)
33208
- );
33209
- }
33210
- return;
33211
- }
33212
- await this.#writer.json(
33213
- rpcError(request, -32078, "External Harness does not expose the requested command")
33214
- );
33215
- return;
33216
- } finally {
33217
- this.#pendingExternalCommandRequests.delete(thread.id);
33218
- }
33219
- }
33220
- if (this.#externalSteering.hasPending(thread.id)) {
33221
- await this.#writer.json(rpcError(request, -32072, "External Thread is changing direction"));
33222
- return;
33223
- }
33224
33685
  try {
33225
- const started = await this.#beginExternalTurn(thread, text2);
33686
+ const started = await this.#beginExternalInputTurn(thread, text2);
33226
33687
  try {
33227
33688
  await this.#writer.json(rpcEnvelope(request, { result: { turn: started.turn } }));
33228
33689
  } finally {
@@ -33232,7 +33693,7 @@ var AppServerHost = class {
33232
33693
  await this.#writer.json(
33233
33694
  rpcError(
33234
33695
  request,
33235
- error51 instanceof ExternalSteerError ? error51.code : -32073,
33696
+ error51 instanceof ExternalSteerError || error51 instanceof ExternalCommandError ? error51.code : -32073,
33236
33697
  errorMessage3(error51)
33237
33698
  )
33238
33699
  );
@@ -33243,7 +33704,7 @@ var AppServerHost = class {
33243
33704
  const started = await this.#externalSteering.run(
33244
33705
  thread,
33245
33706
  requestObject(request),
33246
- (text2) => this.#beginExternalTurn(thread, text2)
33707
+ (text2, assertActive) => this.#beginExternalInputTurn(thread, text2, assertActive)
33247
33708
  );
33248
33709
  try {
33249
33710
  await this.#writer.json(rpcEnvelope(request, { result: { turnId: started.turnId } }));
@@ -33254,7 +33715,7 @@ var AppServerHost = class {
33254
33715
  await this.#writer.json(
33255
33716
  rpcError(
33256
33717
  request,
33257
- error51 instanceof ExternalSteerError ? error51.code : -32074,
33718
+ error51 instanceof ExternalSteerError || error51 instanceof ExternalCommandError ? error51.code : -32074,
33258
33719
  errorMessage3(error51)
33259
33720
  )
33260
33721
  );
@@ -33262,6 +33723,37 @@ var AppServerHost = class {
33262
33723
  this.#signalActiveWorkChanged();
33263
33724
  }
33264
33725
  }
33726
+ /** Keep command restoration and dispatch identical for start and steer submissions. */
33727
+ async #beginExternalInputTurn(thread, inputText, assertActive) {
33728
+ const text2 = restoreHarnessCommandMentions(inputText);
33729
+ const commands = thread.session.commands;
33730
+ if (!commands || !isExternalCommandCandidate(text2)) {
33731
+ assertActive?.();
33732
+ return this.#beginExternalTurn(thread, text2);
33733
+ }
33734
+ this.#pendingExternalCommandRequests.add(thread.id);
33735
+ try {
33736
+ const adapter = this.#externalAdapters.get(thread.harnessId);
33737
+ const command = await resolveExternalCommand(commands, text2, {
33738
+ liveCatalogPending: (catalog) => adapter?.liveCommandCatalog === true && !isLiveCommandCatalog(catalog, adapter.commandCatalog ?? { commands: [] })
33739
+ });
33740
+ assertActive?.();
33741
+ if (!command) {
33742
+ this.#pendingExternalCommandRequests.delete(thread.id);
33743
+ return await this.#beginExternalTurn(thread, text2);
33744
+ }
33745
+ return await this.#beginExternalCommand(thread, command.commandId, command.arguments);
33746
+ } catch (error51) {
33747
+ if (error51 instanceof ExternalCommandError || error51 instanceof ExternalSteerError) throw error51;
33748
+ this.#diagnose(error51);
33749
+ throw new ExternalCommandError(
33750
+ -32073,
33751
+ `External Harness command failed: ${errorMessage3(error51)}`
33752
+ );
33753
+ } finally {
33754
+ this.#pendingExternalCommandRequests.delete(thread.id);
33755
+ }
33756
+ }
33265
33757
  async #beginExternalTurn(thread, text2) {
33266
33758
  if (this.#closeRequested || this.#externalRuntime.get(thread.id) !== thread) {
33267
33759
  throw new ExternalSteerError(-32073, "External Thread is no longer available");
@@ -33269,7 +33761,7 @@ var AppServerHost = class {
33269
33761
  if (thread.running || thread.activeTurnId || this.#pendingExternalCommandRequests.has(thread.id)) {
33270
33762
  throw new ExternalSteerError(-32072, "External Thread already has an active Turn");
33271
33763
  }
33272
- const turnId = hostTurnIdSchema.parse(randomUUID9());
33764
+ const turnId = hostTurnIdSchema.parse(randomUUID10());
33273
33765
  const startedAtMs = Date.now();
33274
33766
  const projection = {
33275
33767
  projector: new CodexTurnProjector({
@@ -33288,7 +33780,7 @@ var AppServerHost = class {
33288
33780
  const result = await thread.session.execute({
33289
33781
  type: "turn.start",
33290
33782
  turnId,
33291
- input: [{ type: "text", text: text2 }]
33783
+ input: [{ type: "text", text: rewriteDelegationMentionText(text2) }]
33292
33784
  });
33293
33785
  if (!result.ok) throw new ExternalSteerError(-32073, result.error.message);
33294
33786
  return { turnId, turn: projection.projector.pendingTurn(), gate };
@@ -33670,7 +34162,7 @@ var AppServerHost = class {
33670
34162
  const previousItems = new Map(
33671
34163
  child.turns.flatMap(
33672
34164
  (turn) => Array.isArray(turn.items) ? turn.items.flatMap(
33673
- (item) => isRecord14(item) && typeof item.id === "string" ? [[item.id, JSON.stringify(item)]] : []
34165
+ (item) => isRecord15(item) && typeof item.id === "string" ? [[item.id, JSON.stringify(item)]] : []
33674
34166
  ) : []
33675
34167
  )
33676
34168
  );
@@ -33683,7 +34175,7 @@ var AppServerHost = class {
33683
34175
  for (const turn of child.turns) {
33684
34176
  if (typeof turn.id !== "string" || !Array.isArray(turn.items)) continue;
33685
34177
  const changedItems = turn.items.filter(
33686
- (item) => isRecord14(item) && typeof item.id === "string" && previousItems.get(item.id) !== JSON.stringify(item)
34178
+ (item) => isRecord15(item) && typeof item.id === "string" && previousItems.get(item.id) !== JSON.stringify(item)
33687
34179
  );
33688
34180
  if (changedItems.length > 0) {
33689
34181
  await this.#writer.json({
@@ -33815,7 +34307,7 @@ var AppServerHost = class {
33815
34307
  }
33816
34308
  }
33817
34309
  async #handleDesktopApprovalResponse(value2) {
33818
- if (!isRecord14(value2) || !isHostApprovalRequestId(value2.id)) return false;
34310
+ if (!isRecord15(value2) || !isHostApprovalRequestId(value2.id)) return false;
33819
34311
  const requestId = value2.id;
33820
34312
  const pending = this.#pendingDesktopApprovals.get(requestId);
33821
34313
  if (!pending) return true;
@@ -33897,7 +34389,7 @@ var AppServerHost = class {
33897
34389
  try {
33898
34390
  result = projection.projector.projectQuestion(
33899
34391
  interaction,
33900
- hostItemIdSchema.parse(randomUUID9())
34392
+ hostItemIdSchema.parse(randomUUID10())
33901
34393
  );
33902
34394
  } catch (error51) {
33903
34395
  this.#diagnose(error51);
@@ -33942,7 +34434,7 @@ var AppServerHost = class {
33942
34434
  }
33943
34435
  }
33944
34436
  async #handleDesktopQuestionResponse(value2) {
33945
- if (!isRecord14(value2) || !isHostQuestionRequestId(value2.id)) return false;
34437
+ if (!isRecord15(value2) || !isHostQuestionRequestId(value2.id)) return false;
33946
34438
  const requestId = value2.id;
33947
34439
  const pending = this.#pendingDesktopQuestions.get(requestId);
33948
34440
  if (!pending) return true;
@@ -34063,19 +34555,19 @@ var AppServerHost = class {
34063
34555
  };
34064
34556
 
34065
34557
  // packages/host-runtime/src/native-account-host.ts
34066
- import { mkdir as mkdir7, realpath as realpath3 } from "node:fs/promises";
34558
+ import { mkdir as mkdir8, realpath as realpath3 } from "node:fs/promises";
34067
34559
  import { homedir } from "node:os";
34068
- import path18 from "node:path";
34560
+ import path20 from "node:path";
34069
34561
 
34070
34562
  // packages/host-runtime/src/codex-runtime/owned-official-backends.ts
34071
- import { createHash as createHash8, randomBytes } from "node:crypto";
34563
+ import { createHash as createHash9, randomBytes } from "node:crypto";
34072
34564
  import { Writable as Writable2 } from "node:stream";
34073
34565
 
34074
34566
  // packages/host-runtime/src/remote-app-server.ts
34075
34567
  import { createServer } from "node:http";
34076
34568
  import net from "node:net";
34077
- import { chmod as chmod3, lstat as lstat6, mkdir as mkdir6, rm as rm6 } from "node:fs/promises";
34078
- import path16 from "node:path";
34569
+ import { chmod as chmod3, lstat as lstat6, mkdir as mkdir7, rm as rm7 } from "node:fs/promises";
34570
+ import path18 from "node:path";
34079
34571
  import { PassThrough } from "node:stream";
34080
34572
 
34081
34573
  // node_modules/ws/wrapper.mjs
@@ -34090,10 +34582,10 @@ var import_websocket_server = __toESM(require_websocket_server(), 1);
34090
34582
  var wrapper_default = import_websocket.default;
34091
34583
 
34092
34584
  // packages/host-runtime/src/remote-socket-lock.ts
34093
- import { randomUUID as randomUUID10 } from "node:crypto";
34094
- import { chmod as chmod2, lstat as lstat5, mkdir as mkdir5, open as open5, readFile as readFile8, readdir as readdir4, rename as rename4, rm as rm5 } from "node:fs/promises";
34585
+ import { randomUUID as randomUUID11 } from "node:crypto";
34586
+ import { chmod as chmod2, lstat as lstat5, mkdir as mkdir6, open as open6, readFile as readFile9, readdir as readdir4, rename as rename5, rm as rm6 } from "node:fs/promises";
34095
34587
  import { uptime } from "node:os";
34096
- import path15 from "node:path";
34588
+ import path17 from "node:path";
34097
34589
  import { setTimeout as delay4 } from "node:timers/promises";
34098
34590
  var LOCK_RETRY_COUNT = 200;
34099
34591
  var LOCK_RETRY_DELAY_MS = 25;
@@ -34156,7 +34648,7 @@ async function readLockEntrySnapshot(filePath) {
34156
34648
  throw error51;
34157
34649
  });
34158
34650
  if (metadata === null || !metadata.isFile()) return null;
34159
- const source = await readFile8(filePath, "utf8").catch((error51) => {
34651
+ const source = await readFile9(filePath, "utf8").catch((error51) => {
34160
34652
  if (error51.code === "ENOENT") return null;
34161
34653
  throw error51;
34162
34654
  });
@@ -34167,7 +34659,7 @@ async function readLockEntrySnapshot(filePath) {
34167
34659
  source,
34168
34660
  identity: { dev: metadata.dev, ino: metadata.ino },
34169
34661
  mtimeMs: metadata.mtimeMs,
34170
- record: record3 && path15.basename(filePath) === lockEntryName(record3.ownerToken) ? record3 : null
34662
+ record: record3 && path17.basename(filePath) === lockEntryName(record3.ownerToken) ? record3 : null
34171
34663
  };
34172
34664
  }
34173
34665
  function lockEntryIsAbandoned(snapshot) {
@@ -34179,7 +34671,7 @@ async function removeAbandonedLockEntry(snapshot) {
34179
34671
  if (current === null || current.source !== snapshot.source || !sameUnixFileIdentity(current.identity, snapshot.identity) || !lockEntryIsAbandoned(current)) {
34180
34672
  return false;
34181
34673
  }
34182
- await rm5(snapshot.filePath, { force: true });
34674
+ await rm6(snapshot.filePath, { force: true });
34183
34675
  return true;
34184
34676
  }
34185
34677
  async function readLockEntryCatalog(lockDirectory) {
@@ -34188,7 +34680,7 @@ async function readLockEntryCatalog(lockDirectory) {
34188
34680
  let unsettled = false;
34189
34681
  for (const name of names) {
34190
34682
  if (!name.startsWith(LOCK_ENTRY_PREFIX) || !name.endsWith(LOCK_ENTRY_SUFFIX)) continue;
34191
- const snapshot = await readLockEntrySnapshot(path15.join(lockDirectory, name));
34683
+ const snapshot = await readLockEntrySnapshot(path17.join(lockDirectory, name));
34192
34684
  if (snapshot === null) continue;
34193
34685
  if (lockEntryIsAbandoned(snapshot)) {
34194
34686
  if (!await removeAbandonedLockEntry(snapshot)) unsettled = true;
@@ -34203,7 +34695,7 @@ async function readLockEntryCatalog(lockDirectory) {
34203
34695
  return { entries, unsettled };
34204
34696
  }
34205
34697
  async function preparePrivateLockDirectory(lockDirectory) {
34206
- await mkdir5(lockDirectory, { mode: 448 }).catch((error51) => {
34698
+ await mkdir6(lockDirectory, { mode: 448 }).catch((error51) => {
34207
34699
  if (error51.code !== "EEXIST") throw error51;
34208
34700
  });
34209
34701
  const metadata = await lstat5(lockDirectory);
@@ -34216,8 +34708,8 @@ async function preparePrivateLockDirectory(lockDirectory) {
34216
34708
  await chmod2(lockDirectory, 448);
34217
34709
  }
34218
34710
  async function writeLockRecordAtomic(lockDirectory, entryPath, record3) {
34219
- const temporary = path15.join(lockDirectory, `.tmp-${record3.ownerToken}-${randomUUID10()}`);
34220
- const handle = await open5(temporary, "wx", 384);
34711
+ const temporary = path17.join(lockDirectory, `.tmp-${record3.ownerToken}-${randomUUID11()}`);
34712
+ const handle = await open6(temporary, "wx", 384);
34221
34713
  try {
34222
34714
  await handle.writeFile(`${JSON.stringify(record3)}
34223
34715
  `, "utf8");
@@ -34226,15 +34718,15 @@ async function writeLockRecordAtomic(lockDirectory, entryPath, record3) {
34226
34718
  await handle.close();
34227
34719
  }
34228
34720
  try {
34229
- await rename4(temporary, entryPath);
34721
+ await rename5(temporary, entryPath);
34230
34722
  } finally {
34231
- await rm5(temporary, { force: true });
34723
+ await rm6(temporary, { force: true });
34232
34724
  }
34233
34725
  }
34234
34726
  async function removeOwnedLockEntry(entryPath, ownerToken) {
34235
34727
  const snapshot = await readLockEntrySnapshot(entryPath);
34236
34728
  if (snapshot?.record?.ownerToken !== ownerToken) return;
34237
- await rm5(entryPath, { force: true });
34729
+ await rm6(entryPath, { force: true });
34238
34730
  }
34239
34731
  async function legacyLockState(legacyPath) {
34240
34732
  const metadata = await lstat5(legacyPath).catch((error51) => {
@@ -34243,7 +34735,7 @@ async function legacyLockState(legacyPath) {
34243
34735
  });
34244
34736
  if (metadata === null) return "absent";
34245
34737
  if (!metadata.isFile()) return "blocking";
34246
- const source = await readFile8(legacyPath, "utf8").catch((error51) => {
34738
+ const source = await readFile9(legacyPath, "utf8").catch((error51) => {
34247
34739
  if (error51.code === "ENOENT") return null;
34248
34740
  throw error51;
34249
34741
  });
@@ -34254,7 +34746,7 @@ async function legacyLockState(legacyPath) {
34254
34746
  return ownerIsAbandoned(record3, metadata.mtimeMs) ? "abandoned" : "blocking";
34255
34747
  }
34256
34748
  async function tryAcquireLegacyCompatibilityGuard(legacyPath, record3) {
34257
- const handle = await open5(legacyPath, "wx", 384).catch((error51) => {
34749
+ const handle = await open6(legacyPath, "wx", 384).catch((error51) => {
34258
34750
  if (error51.code === "EEXIST") return null;
34259
34751
  throw error51;
34260
34752
  });
@@ -34280,7 +34772,7 @@ async function releaseLegacyCompatibilityGuard(legacyPath, guard) {
34280
34772
  throw error51;
34281
34773
  });
34282
34774
  if (metadata?.isFile() && sameUnixFileIdentity({ dev: metadata.dev, ino: metadata.ino }, guard.identity)) {
34283
- await rm5(legacyPath, { force: true });
34775
+ await rm6(legacyPath, { force: true });
34284
34776
  }
34285
34777
  }
34286
34778
  }
@@ -34291,8 +34783,8 @@ async function withRemoteAppServerSocketInitializationLock(socketPath, action) {
34291
34783
  const legacyPath = `${socketPath}.initializing`;
34292
34784
  const lockDirectory = `${socketPath}.initializers`;
34293
34785
  await preparePrivateLockDirectory(lockDirectory);
34294
- const ownerToken = randomUUID10();
34295
- const entryPath = path15.join(lockDirectory, lockEntryName(ownerToken));
34786
+ const ownerToken = randomUUID11();
34787
+ const entryPath = path17.join(lockDirectory, lockEntryName(ownerToken));
34296
34788
  const baseRecord = {
34297
34789
  version: 2,
34298
34790
  ownerToken,
@@ -34466,14 +34958,14 @@ function remoteAppServerSocketPath(environment, listenUrl = "unix://") {
34466
34958
  throw new Error("Remote app-server listener must use a Unix URL");
34467
34959
  }
34468
34960
  const explicit = listenUrl.slice("unix://".length);
34469
- if (explicit.length > 0) return path16.posix.resolve(decodeURIComponent(explicit));
34470
- const codexHome = environment.CODEX_HOME ?? (environment.HOME ? path16.posix.join(environment.HOME, ".codex") : void 0);
34961
+ if (explicit.length > 0) return path18.posix.resolve(decodeURIComponent(explicit));
34962
+ const codexHome = environment.CODEX_HOME ?? (environment.HOME ? path18.posix.join(environment.HOME, ".codex") : void 0);
34471
34963
  if (!codexHome)
34472
34964
  throw new Error("CODEX_HOME or HOME is required for the remote app-server socket");
34473
- return path16.posix.join(codexHome, "app-server-control", "app-server-control.sock");
34965
+ return path18.posix.join(codexHome, "app-server-control", "app-server-control.sock");
34474
34966
  }
34475
34967
  function officialListenerArgumentsForRemoteListener(arguments_2, socketPath) {
34476
- if (!path16.posix.isAbsolute(socketPath)) {
34968
+ if (!path18.posix.isAbsolute(socketPath)) {
34477
34969
  throw new Error("Shared official app-server socket path must be absolute");
34478
34970
  }
34479
34971
  if (remoteUnixListenerUrl(arguments_2) === null) {
@@ -34581,10 +35073,10 @@ async function removeStaleSocket(socketPath) {
34581
35073
  });
34582
35074
  });
34583
35075
  if (active) throw new Error(`Remote app-server socket is already in use at ${socketPath}`);
34584
- await rm6(socketPath, { force: true });
35076
+ await rm7(socketPath, { force: true });
34585
35077
  }
34586
35078
  async function prepareRemoteAppServerSocketDirectory(socketPath) {
34587
- const socketDirectory = path16.dirname(socketPath);
35079
+ const socketDirectory = path18.dirname(socketPath);
34588
35080
  const existing = await lstat6(socketDirectory).catch((error51) => {
34589
35081
  if (error51.code === "ENOENT") return null;
34590
35082
  throw error51;
@@ -34598,7 +35090,7 @@ async function prepareRemoteAppServerSocketDirectory(socketPath) {
34598
35090
  );
34599
35091
  }
34600
35092
  }
34601
- await mkdir6(socketDirectory, { recursive: true, mode: 448 });
35093
+ await mkdir7(socketDirectory, { recursive: true, mode: 448 });
34602
35094
  await chmod3(socketDirectory, 448);
34603
35095
  }
34604
35096
  function sendOutputFrames(socket, output) {
@@ -34771,7 +35263,7 @@ function createRemoteAppServerWebSocketListener(input) {
34771
35263
  if (ownedSocketIdentity) {
34772
35264
  const current = await unixSocketIdentity(input.socketPath);
34773
35265
  if (current && sameUnixFileIdentity2(current, ownedSocketIdentity)) {
34774
- await rm6(input.socketPath, { force: true });
35266
+ await rm7(input.socketPath, { force: true });
34775
35267
  }
34776
35268
  ownedSocketIdentity = null;
34777
35269
  }
@@ -34789,39 +35281,57 @@ function createRemoteAppServerWebSocketListener(input) {
34789
35281
 
34790
35282
  // packages/host-runtime/src/remote-official-app-server.ts
34791
35283
  import { spawn as spawn3 } from "node:child_process";
34792
- import { randomUUID as randomUUID11 } from "node:crypto";
34793
- import { lstat as lstat7, rm as rm7 } from "node:fs/promises";
34794
- import path17 from "node:path";
35284
+ import { randomUUID as randomUUID12 } from "node:crypto";
35285
+ import { lstat as lstat7, rm as rm8, stat as stat5 } from "node:fs/promises";
35286
+ import path19 from "node:path";
34795
35287
  var DEFAULT_CLOSE_TIMEOUT_MS = 2e3;
34796
35288
  var DEFAULT_LISTEN_TIMEOUT_MS = 1e4;
34797
- function remoteOfficialAppServerSocketPath(desktopControlSocketPath, token = randomUUID11()) {
34798
- if (!path17.posix.isAbsolute(desktopControlSocketPath)) {
35289
+ function remoteOfficialAppServerSocketPath(desktopControlSocketPath, token = randomUUID12()) {
35290
+ if (!path19.posix.isAbsolute(desktopControlSocketPath)) {
34799
35291
  throw new Error("Desktop control socket path must be absolute");
34800
35292
  }
34801
35293
  if (!/^[A-Za-z0-9-]+$/u.test(token) || !/[A-Za-z0-9]/u.test(token)) {
34802
35294
  throw new Error("Shared official app-server socket token is invalid");
34803
35295
  }
34804
35296
  const compactToken = token.replaceAll("-", "").slice(0, 15);
34805
- return path17.posix.join(path17.posix.dirname(desktopControlSocketPath), `.c-${compactToken}.sock`);
35297
+ return path19.posix.join(path19.posix.dirname(desktopControlSocketPath), `.c-${compactToken}.sock`);
34806
35298
  }
34807
35299
  function errorMessage4(error51) {
34808
35300
  return error51 instanceof Error ? error51.message : String(error51);
34809
35301
  }
34810
- async function socketIdentity(socketPath) {
35302
+ async function inspectSocket(socketPath) {
34811
35303
  const metadata = await lstat7(socketPath).catch((error51) => {
34812
35304
  if (error51.code === "ENOENT") return null;
34813
35305
  throw error51;
34814
35306
  });
34815
35307
  if (metadata === null) return null;
34816
- if (!metadata.isSocket()) {
35308
+ const identity = { dev: metadata.dev, ino: metadata.ino };
35309
+ if (metadata.isSymbolicLink()) {
35310
+ const uid = process.getuid?.();
35311
+ if (uid === void 0 || metadata.uid !== uid) {
35312
+ throw new Error(
35313
+ `Shared official app-server link must belong to the current user: ${socketPath}`
35314
+ );
35315
+ }
35316
+ const target = await stat5(socketPath).catch((error51) => {
35317
+ if (error51.code === "ENOENT") return null;
35318
+ throw error51;
35319
+ });
35320
+ if (target === null) return { identity, ready: false };
35321
+ if (target.uid !== uid || !target.isSocket() || (target.mode & 63) !== 0) {
35322
+ throw new Error(
35323
+ `Shared official app-server link must target a current-user private socket: ${socketPath}`
35324
+ );
35325
+ }
35326
+ } else if (!metadata.isSocket()) {
34817
35327
  throw new Error(`Shared official app-server path is not a socket: ${socketPath}`);
34818
35328
  }
34819
- return { dev: metadata.dev, ino: metadata.ino };
35329
+ return { identity, ready: true };
34820
35330
  }
34821
35331
  function sameUnixFileIdentity3(left, right) {
34822
35332
  return left.dev === right.dev && left.ino === right.ino;
34823
35333
  }
34824
- async function waitForOfficialSocket(socketPath, closed) {
35334
+ async function waitForOfficialSocket(socketPath, closed, onIdentity) {
34825
35335
  const deadline = Date.now() + 1e4;
34826
35336
  const state = { exit: null };
34827
35337
  void closed.then((value2) => {
@@ -34834,14 +35344,20 @@ async function waitForOfficialSocket(socketPath, closed) {
34834
35344
  exit.error ? `Shared official app-server failed: ${exit.error.message}` : `Shared official app-server exited before its socket was ready (code=${String(exit.code)}, signal=${String(exit.signal)})`
34835
35345
  );
34836
35346
  }
34837
- if (await socketIdentity(socketPath) !== null) return;
35347
+ const socket = await inspectSocket(socketPath);
35348
+ if (socket !== null) {
35349
+ onIdentity(socket.identity);
35350
+ if (socket.ready) return;
35351
+ }
34838
35352
  await new Promise((resolve) => setTimeout(resolve, 25));
34839
35353
  }
34840
35354
  throw new Error(`Shared official app-server socket was not ready after 10000ms: ${socketPath}`);
34841
35355
  }
34842
35356
  function createRemoteOfficialAppServerListener(input) {
34843
35357
  const spawnOfficial = input.spawnOfficial ?? spawn3;
34844
- const waitUntilReady = input.waitUntilReady ?? waitForOfficialSocket;
35358
+ const waitUntilReady = input.waitUntilReady ?? ((socketPath, closed2) => waitForOfficialSocket(socketPath, closed2, (identity) => {
35359
+ ownedSocketIdentity ??= identity;
35360
+ }));
34845
35361
  const closeTimeoutMs = input.closeTimeoutMs ?? DEFAULT_CLOSE_TIMEOUT_MS;
34846
35362
  const closed = Promise.withResolvers();
34847
35363
  let child = null;
@@ -34872,9 +35388,9 @@ function createRemoteOfficialAppServerListener(input) {
34872
35388
  };
34873
35389
  const removeOwnedSocket = async () => {
34874
35390
  if (ownedSocketIdentity === null) return;
34875
- const current = await socketIdentity(input.socketPath).catch(() => null);
35391
+ const current = await lstat7(input.socketPath).catch(() => null);
34876
35392
  if (current && sameUnixFileIdentity3(current, ownedSocketIdentity)) {
34877
- await rm7(input.socketPath, { force: true });
35393
+ await rm8(input.socketPath, { force: true });
34878
35394
  }
34879
35395
  ownedSocketIdentity = null;
34880
35396
  };
@@ -34898,7 +35414,7 @@ function createRemoteOfficialAppServerListener(input) {
34898
35414
  spawned.stderr?.pipe(input.diagnosticOutput, { end: false });
34899
35415
  try {
34900
35416
  await waitUntilReady(input.socketPath, closed.promise);
34901
- ownedSocketIdentity = await socketIdentity(input.socketPath).catch(() => null);
35417
+ ownedSocketIdentity ??= (await inspectSocket(input.socketPath).catch(() => null))?.identity ?? null;
34902
35418
  } catch (error51) {
34903
35419
  let stopFailed = false;
34904
35420
  try {
@@ -34906,7 +35422,7 @@ function createRemoteOfficialAppServerListener(input) {
34906
35422
  } catch {
34907
35423
  stopFailed = true;
34908
35424
  }
34909
- ownedSocketIdentity ??= await socketIdentity(input.socketPath).catch(() => null);
35425
+ ownedSocketIdentity ??= (await inspectSocket(input.socketPath).catch(() => null))?.identity ?? null;
34910
35426
  if (!stopFailed) await removeOwnedSocket();
34911
35427
  throw new Error(`Shared official app-server startup failed: ${errorMessage4(error51)}`);
34912
35428
  }
@@ -35235,7 +35751,7 @@ function createOwnedLoopbackBackend(input) {
35235
35751
  "--ws-auth",
35236
35752
  "capability-token",
35237
35753
  "--ws-token-sha256",
35238
- createHash8("sha256").update(capabilityToken).digest("hex")
35754
+ createHash9("sha256").update(capabilityToken).digest("hex")
35239
35755
  ],
35240
35756
  // Managed stderr may carry credential-bearing errors. Never forward raw bytes.
35241
35757
  diagnosticOutput: new Writable2({
@@ -35288,21 +35804,21 @@ function createOwnedUnixBackend(input) {
35288
35804
 
35289
35805
  // packages/host-runtime/src/native-account-host.ts
35290
35806
  async function canonicalCodexHome(home) {
35291
- const absolute = path18.resolve(home);
35807
+ const absolute = path20.resolve(home);
35292
35808
  try {
35293
35809
  return await realpath3(absolute);
35294
35810
  } catch (error51) {
35295
35811
  if (!(error51 instanceof Error && "code" in error51 && error51.code === "ENOENT")) throw error51;
35296
- const parent = path18.dirname(absolute);
35812
+ const parent = path20.dirname(absolute);
35297
35813
  if (parent === absolute) throw error51;
35298
- return path18.join(await canonicalCodexHome(parent), path18.basename(absolute));
35814
+ return path20.join(await canonicalCodexHome(parent), path20.basename(absolute));
35299
35815
  }
35300
35816
  }
35301
35817
  async function prepareLocalCodex(input) {
35302
35818
  const home = await canonicalCodexHome(
35303
- input.environment.CODEX_HOME ?? path18.join(homedir(), ".codex")
35819
+ input.environment.CODEX_HOME ?? path20.join(homedir(), ".codex")
35304
35820
  );
35305
- await mkdir7(home, { recursive: true });
35821
+ await mkdir8(home, { recursive: true });
35306
35822
  const scope = new OfficialRuntimeScope({
35307
35823
  permanentHome: home,
35308
35824
  diagnosticOutput: input.diagnosticOutput,
@@ -35466,18 +35982,18 @@ var DelegationControlRegistry = class {
35466
35982
  };
35467
35983
 
35468
35984
  // packages/host-runtime/src/installed-harness-plugins.ts
35469
- import os5 from "node:os";
35470
- import path20 from "node:path";
35985
+ import os6 from "node:os";
35986
+ import path22 from "node:path";
35471
35987
  import { fileURLToPath } from "node:url";
35472
35988
 
35473
35989
  // packages/host-runtime/src/launcher-url-opener.ts
35474
35990
  import { spawn as spawn4 } from "node:child_process";
35475
- import path19 from "node:path";
35991
+ import path21 from "node:path";
35476
35992
  var LOOPBACK_HOSTS = /* @__PURE__ */ new Set(["127.0.0.1", "localhost", "[::1]"]);
35477
35993
  var OPEN_TIMEOUT_MS = 1e4;
35478
35994
  function createLauncherUrlOpener(environment, spawnLauncher = (command, arguments_2, options2) => spawn4(command, arguments_2, options2)) {
35479
35995
  const launcher = environment.CODEXHOST_LAUNCHER_EXECUTABLE;
35480
- if (!launcher || !path19.isAbsolute(launcher)) return void 0;
35996
+ if (!launcher || !path21.isAbsolute(launcher)) return void 0;
35481
35997
  const launcherEnvironment = Object.fromEntries(
35482
35998
  Object.entries(environment).filter(([name]) => {
35483
35999
  const normalized = name.toUpperCase();
@@ -35535,9 +36051,9 @@ function installedHarnessPluginOptions(environment, managedRemoteHost = false, h
35535
36051
  const opener = managedRemoteHost ? void 0 : createLauncherUrlOpener(environment);
35536
36052
  return {
35537
36053
  pluginRoots: [
35538
- path20.join(path20.dirname(fileURLToPath(hostRuntimeUrl)), "plugins"),
35539
- environment[HARNESS_PLUGIN_DIRECTORY_ENV] ?? path20.join(
35540
- environment.CODEXHOST_DATA_DIR ? path20.resolve(environment.CODEXHOST_DATA_DIR) : path20.join(os5.homedir(), ".codexhost"),
36054
+ path22.join(path22.dirname(fileURLToPath(hostRuntimeUrl)), "plugins"),
36055
+ environment[HARNESS_PLUGIN_DIRECTORY_ENV] ?? path22.join(
36056
+ environment.CODEXHOST_DATA_DIR ? path22.resolve(environment.CODEXHOST_DATA_DIR) : path22.join(os6.homedir(), ".codexhost"),
35541
36057
  "plugins"
35542
36058
  )
35543
36059
  ],
@@ -35661,172 +36177,10 @@ async function startDelegationControlServer(input) {
35661
36177
  };
35662
36178
  }
35663
36179
 
35664
- // packages/host-runtime/src/delegation-skill.ts
35665
- import { createHash as createHash9, randomUUID as randomUUID12 } from "node:crypto";
35666
- import { mkdir as mkdir8, open as open6, readFile as readFile9, rename as rename5, rm as rm8, stat as stat4 } from "node:fs/promises";
35667
- import os6 from "node:os";
35668
- import path21 from "node:path";
35669
- var SKILL_VERSION = 7;
35670
- var SKILL_RELATIVE_PATH = path21.join("skills", "codexhost-delegation", "SKILL.md");
35671
- var PREVIOUS_MANAGED_DIGESTS = [
35672
- "9d2f491850fb0b4084a31ba9b5e4a550b5e833747af322090d8ed0ff80b88c30",
35673
- "2bb0aebb9b06febbc6c0c0bcdb0b32506c7cdbf8dc3b734cc6b2a86621270e4e",
35674
- "aff258622dc8ff321f32b15620d081e578cb9c9ed1134d6a57f35ca8e7762c0a",
35675
- "ba509f57e5448e796b3dfdd5031dcb08672eded50b61c0a54de84cfa02c49dd3",
35676
- "d3ddf6db9bc5c5df825479c885bbbf0ca08da66f7057a12e02e1fdf57525149e",
35677
- "15eb63519ff867e1536c97188a0c43738d7a49d38d4d6adeb7a1036726e7246d",
35678
- "09acc3cc0a598e546ce35fccb9d856d9fe06c01ab055dfce1914dab92479c9a2"
35679
- ];
35680
- var CODEXHOST_DELEGATION_SKILL = `---
35681
- name: codexhost-delegation
35682
- version: ${SKILL_VERSION}
35683
- description: >
35684
- Delegate tasks to other coding agents, or read and follow up on existing
35685
- external agent sessions. Use when the user asks another agent (including
35686
- @agent) to independently perform a task, or asks to view a specified external
35687
- session's content, progress, or results, send follow-up messages, wait, or
35688
- cancel a task. Not for recapping the current conversation, discussing or
35689
- configuring agents, or role-playing.
35690
- ---
35691
-
35692
- # Execute the task
35693
-
35694
- Before acting, run:
35695
-
35696
- \`boft delegate --help\`
35697
-
35698
- Use CLI help as the authoritative source for commands and behavior. Consult
35699
- command-specific help for options and the Harness listing command when the
35700
- target is unknown. Prefer compact output when supported, and use its task links
35701
- directly for subsequent commands.
35702
-
35703
- Use the Harness native defaults. Inspect the target when a Model or Thinking
35704
- selection is needed or the default is unavailable.
35705
-
35706
- For a new delegation, create an independent child session and submit the
35707
- requested task. For an existing external session, resolve the target from the
35708
- user-provided session link, identifier, or context and operate on that Thread
35709
- directly; it need not have been created by the current assistant. If the target
35710
- is ambiguous, ask the user to identify it. Keep requests to view or summarize a
35711
- session read-only.
35712
-
35713
- For a new or existing task, choose the appropriate next action based on the
35714
- user’s request and the task:
35715
-
35716
- - send a follow-up message to the same Thread;
35717
- - cancel its current Turn;
35718
- - read its current state immediately;
35719
- - wait for a bounded period;
35720
- - check it again later;
35721
- - leave it running in the background.
35722
-
35723
- Report the result returned by read or a completed wait, together with the target
35724
- agent, status, and a labeled task link. Keep internal tracking IDs in tool calls.
35725
- `;
35726
- var CURRENT_DIGEST = createHash9("sha256").update(CODEXHOST_DELEGATION_SKILL).digest("hex");
35727
- function digest(value2) {
35728
- return createHash9("sha256").update(value2).digest("hex");
35729
- }
35730
- function managedVersion(value2) {
35731
- const match = /^version:\s*(\d+)\s*$/mu.exec(value2);
35732
- return match ? Number(match[1]) : null;
35733
- }
35734
- async function readOptional(filePath) {
35735
- try {
35736
- return await readFile9(filePath, "utf8");
35737
- } catch (error51) {
35738
- if (error51.code === "ENOENT") return null;
35739
- throw error51;
35740
- }
35741
- }
35742
- async function atomicWrite(filePath, content) {
35743
- await mkdir8(path21.dirname(filePath), { recursive: true, mode: 448 });
35744
- const temporaryPath = path21.join(path21.dirname(filePath), `.SKILL.md.${randomUUID12()}.tmp`);
35745
- const handle = await open6(temporaryPath, "wx", 384);
35746
- try {
35747
- await handle.writeFile(content, "utf8");
35748
- await handle.sync();
35749
- } finally {
35750
- await handle.close();
35751
- }
35752
- try {
35753
- await rename5(temporaryPath, filePath);
35754
- } finally {
35755
- await rm8(temporaryPath, { force: true });
35756
- }
35757
- }
35758
- async function installDelegationSkills(input = {}) {
35759
- const home = input.homeDirectory ?? os6.homedir();
35760
- const destinations = [
35761
- path21.join(home, ".agents", SKILL_RELATIVE_PATH),
35762
- path21.join(home, ".claude", SKILL_RELATIVE_PATH)
35763
- ];
35764
- const knownDigests = /* @__PURE__ */ new Set([
35765
- CURRENT_DIGEST,
35766
- ...PREVIOUS_MANAGED_DIGESTS,
35767
- ...input.previousManagedDigests ?? []
35768
- ]);
35769
- const results = [];
35770
- for (const destination of destinations) {
35771
- const current = await readOptional(destination);
35772
- if (current === CODEXHOST_DELEGATION_SKILL) {
35773
- results.push({
35774
- path: destination,
35775
- status: "current",
35776
- version: SKILL_VERSION,
35777
- digest: CURRENT_DIGEST
35778
- });
35779
- continue;
35780
- }
35781
- if (current !== null) {
35782
- const currentDigest = digest(current);
35783
- const version2 = managedVersion(current);
35784
- if (!knownDigests.has(currentDigest)) {
35785
- results.push({ path: destination, status: "conflict", version: version2, digest: currentDigest });
35786
- continue;
35787
- }
35788
- await atomicWrite(destination, CODEXHOST_DELEGATION_SKILL);
35789
- results.push({
35790
- path: destination,
35791
- status: "updated",
35792
- version: SKILL_VERSION,
35793
- digest: CURRENT_DIGEST
35794
- });
35795
- continue;
35796
- }
35797
- await atomicWrite(destination, CODEXHOST_DELEGATION_SKILL);
35798
- results.push({
35799
- path: destination,
35800
- status: "installed",
35801
- version: SKILL_VERSION,
35802
- digest: CURRENT_DIGEST
35803
- });
35804
- }
35805
- for (const result of results) {
35806
- if (result.status === "conflict") continue;
35807
- const source = await readFile9(result.path, "utf8");
35808
- const metadata = await stat4(result.path);
35809
- if (!metadata.isFile() || source !== CODEXHOST_DELEGATION_SKILL) {
35810
- throw new Error(`Delegation Skill verification failed: ${result.path}`);
35811
- }
35812
- }
35813
- const managed = results.filter((result) => result.status !== "conflict");
35814
- if (managed.some((result) => result.digest !== CURRENT_DIGEST)) {
35815
- throw new Error("Delegation Skill copies are inconsistent");
35816
- }
35817
- if (results.every((result) => result.status !== "conflict")) {
35818
- const copies = await Promise.all(results.map((result) => readFile9(result.path, "utf8")));
35819
- if (copies.some((copy) => copy !== copies[0])) {
35820
- throw new Error("Delegation Skill copies are inconsistent");
35821
- }
35822
- }
35823
- return results;
35824
- }
35825
-
35826
36180
  // packages/host-runtime/src/remote-control-app-server.ts
35827
36181
  import { randomUUID as randomUUID13 } from "node:crypto";
35828
36182
  import { mkdir as mkdir9, open as open7, rename as rename6, rm as rm9 } from "node:fs/promises";
35829
- import path22 from "node:path";
36183
+ import path23 from "node:path";
35830
36184
  var REMOTE_CONTROL_BRIDGE_PIPE_ENV = "CODEXHOST_REMOTE_CONTROL_BRIDGE_PIPE";
35831
36185
  var REMOTE_CONTROL_BRIDGE_NODE_ENV = "CODEXHOST_REMOTE_CONTROL_BRIDGE_NODE_PATH";
35832
36186
  var REMOTE_CONTROL_BRIDGE_RUNTIME_ENV = "CODEXHOST_REMOTE_CONTROL_BRIDGE_RUNTIME_PATH";
@@ -35837,8 +36191,8 @@ var BRIDGE_READY_METHOD = "codexhost/remote-control-bridge/ready";
35837
36191
  function absoluteEnvironmentPath2(environment, name, fallback, platform = process.platform) {
35838
36192
  const value2 = environment[name] ?? fallback;
35839
36193
  if (!value2) return null;
35840
- if (path22.isAbsolute(value2)) return path22.normalize(value2);
35841
- return platform === "win32" && path22.win32.isAbsolute(value2) ? path22.win32.normalize(value2) : null;
36194
+ if (path23.isAbsolute(value2)) return path23.normalize(value2);
36195
+ return platform === "win32" && path23.win32.isAbsolute(value2) ? path23.win32.normalize(value2) : null;
35842
36196
  }
35843
36197
  function nodeCompatibleWindowsPath(value2) {
35844
36198
  if (value2.startsWith("\\\\?\\UNC\\")) return `\\\\${value2.slice(8)}`;
@@ -35852,13 +36206,13 @@ function remoteControlBridgePipePath(processId = process.pid, instanceId = rando
35852
36206
  }
35853
36207
  function remoteControlBridgeDescriptorPath(environment) {
35854
36208
  const root = environment.LOCALAPPDATA;
35855
- if (!root || !path22.isAbsolute(root)) return null;
35856
- return path22.join(path22.normalize(root), "codexhost", REMOTE_CONTROL_BRIDGE_DESCRIPTOR_FILE);
36209
+ if (!root || !path23.isAbsolute(root)) return null;
36210
+ return path23.join(path23.normalize(root), "codexhost", REMOTE_CONTROL_BRIDGE_DESCRIPTOR_FILE);
35857
36211
  }
35858
36212
  async function publishRemoteControlAppServerDescriptor(plan) {
35859
- const directory = path22.dirname(plan.descriptorPath);
36213
+ const directory = path23.dirname(plan.descriptorPath);
35860
36214
  await mkdir9(directory, { recursive: true, mode: 448 });
35861
- const temporaryPath = path22.join(
36215
+ const temporaryPath = path23.join(
35862
36216
  directory,
35863
36217
  `.${REMOTE_CONTROL_BRIDGE_DESCRIPTOR_FILE}.${plan.descriptor.ownerPid}.${randomUUID13()}.tmp`
35864
36218
  );
@@ -36159,9 +36513,9 @@ function hasLauncherManagedUpdateRuntime(environment, hostRuntimePath) {
36159
36513
  if (!environment[UPDATE_RUNTIME_ENV.launcherPid]) return false;
36160
36514
  const npmPackageRoot = environment[UPDATE_RUNTIME_ENV.npmPackageRoot];
36161
36515
  if (!npmPackageRoot || !hostRuntimePath) return true;
36162
- if (!path23.isAbsolute(npmPackageRoot) || !path23.isAbsolute(hostRuntimePath)) return false;
36163
- const runtimePackageRoot = path23.dirname(path23.dirname(path23.normalize(hostRuntimePath)));
36164
- return path23.relative(path23.normalize(npmPackageRoot), runtimePackageRoot) === "";
36516
+ if (!path24.isAbsolute(npmPackageRoot) || !path24.isAbsolute(hostRuntimePath)) return false;
36517
+ const runtimePackageRoot = path24.dirname(path24.dirname(path24.normalize(hostRuntimePath)));
36518
+ return path24.relative(path24.normalize(npmPackageRoot), runtimePackageRoot) === "";
36165
36519
  }
36166
36520
  function requiredRuntimeConfiguration(environment) {
36167
36521
  const stockCodexPath = environment[STOCK_CODEX_PATH_ENV];
@@ -36307,8 +36661,8 @@ async function runHostRuntime(input) {
36307
36661
  const socketPath = remoteAppServerSocketPath(delegationEnvironment, listenUrl);
36308
36662
  const officialPlan = createRemoteOfficialAppServerPlan(input.arguments, socketPath);
36309
36663
  const officialRuntimeScope = new OfficialRuntimeScope({
36310
- permanentHome: path23.resolve(
36311
- delegationEnvironment.CODEX_HOME ?? path23.join(homedir2(), ".codex")
36664
+ permanentHome: path24.resolve(
36665
+ delegationEnvironment.CODEX_HOME ?? path24.join(homedir2(), ".codex")
36312
36666
  ),
36313
36667
  diagnosticOutput: process.stderr,
36314
36668
  createBackend: () => createOwnedUnixBackend({
@@ -36401,10 +36755,10 @@ import {
36401
36755
  rename as rename7,
36402
36756
  rm as rm10,
36403
36757
  rmdir,
36404
- stat as stat5,
36758
+ stat as stat6,
36405
36759
  writeFile as writeFile4
36406
36760
  } from "node:fs/promises";
36407
- import path24 from "node:path";
36761
+ import path25 from "node:path";
36408
36762
  var MANIFEST_FORMAT = 1;
36409
36763
  var WRAPPER_MARKER = "# codexhost remote SSH wrapper v1";
36410
36764
  var PROFILE_START = "# >>> codexhost remote SSH >>>";
@@ -36415,25 +36769,25 @@ function resolvePaths(options2) {
36415
36769
  if (!configuredHome) {
36416
36770
  throw new Error("A non-root HOME is required for remote Host installation");
36417
36771
  }
36418
- const home = path24.resolve(configuredHome);
36419
- if (!home || home === path24.parse(home).root) {
36772
+ const home = path25.resolve(configuredHome);
36773
+ if (!home || home === path25.parse(home).root) {
36420
36774
  throw new Error("A non-root HOME is required for remote Host installation");
36421
36775
  }
36422
- const installRoot = path24.resolve(options2.installRoot ?? path24.join(home, ".codexhost", "remote"));
36423
- const profilePath = path24.resolve(
36424
- options2.profilePath ?? path24.join(
36776
+ const installRoot = path25.resolve(options2.installRoot ?? path25.join(home, ".codexhost", "remote"));
36777
+ const profilePath = path25.resolve(
36778
+ options2.profilePath ?? path25.join(
36425
36779
  home,
36426
- path24.basename(environment.SHELL ?? "") === "zsh" ? ".zshenv" : path24.basename(environment.SHELL ?? "") === "bash" ? ".bashrc" : ".profile"
36780
+ path25.basename(environment.SHELL ?? "") === "zsh" ? ".zshenv" : path25.basename(environment.SHELL ?? "") === "bash" ? ".bashrc" : ".profile"
36427
36781
  )
36428
36782
  );
36429
- const binDirectory = path24.join(installRoot, "bin");
36783
+ const binDirectory = path25.join(installRoot, "bin");
36430
36784
  return {
36431
36785
  home,
36432
36786
  installRoot,
36433
36787
  binDirectory,
36434
- wrapperPath: path24.join(binDirectory, "codex"),
36435
- manifestPath: path24.join(installRoot, "manifest.json"),
36436
- dataDirectory: path24.join(installRoot, "data"),
36788
+ wrapperPath: path25.join(binDirectory, "codex"),
36789
+ manifestPath: path25.join(installRoot, "manifest.json"),
36790
+ dataDirectory: path25.join(installRoot, "data"),
36437
36791
  profilePath
36438
36792
  };
36439
36793
  }
@@ -36452,9 +36806,9 @@ async function fileSha256(filePath) {
36452
36806
  return createHash10("sha256").update(await readFile10(filePath)).digest("hex");
36453
36807
  }
36454
36808
  async function executable(filePath, label) {
36455
- const absolute = path24.resolve(filePath);
36809
+ const absolute = path25.resolve(filePath);
36456
36810
  try {
36457
- if (!(await stat5(absolute)).isFile()) throw new Error("not a regular file");
36811
+ if (!(await stat6(absolute)).isFile()) throw new Error("not a regular file");
36458
36812
  await access(absolute, fsConstants.X_OK);
36459
36813
  } catch {
36460
36814
  throw new Error(`${label} is not an executable file: ${absolute}`);
@@ -36462,9 +36816,9 @@ async function executable(filePath, label) {
36462
36816
  return absolute;
36463
36817
  }
36464
36818
  async function existingFile(filePath, label) {
36465
- const absolute = path24.resolve(filePath);
36819
+ const absolute = path25.resolve(filePath);
36466
36820
  try {
36467
- const metadata = await stat5(absolute);
36821
+ const metadata = await stat6(absolute);
36468
36822
  if (!metadata.isFile()) throw new Error("not a regular file");
36469
36823
  } catch {
36470
36824
  throw new Error(`${label} is not a regular file: ${absolute}`);
@@ -36472,9 +36826,9 @@ async function existingFile(filePath, label) {
36472
36826
  return absolute;
36473
36827
  }
36474
36828
  async function discoverExecutable(name, environment) {
36475
- for (const directory of (environment.PATH ?? "").split(path24.delimiter)) {
36829
+ for (const directory of (environment.PATH ?? "").split(path25.delimiter)) {
36476
36830
  if (!directory) continue;
36477
- const candidate = path24.resolve(directory, name);
36831
+ const candidate = path25.resolve(directory, name);
36478
36832
  try {
36479
36833
  await access(candidate, fsConstants.X_OK);
36480
36834
  return candidate;
@@ -36485,10 +36839,10 @@ async function discoverExecutable(name, environment) {
36485
36839
  return null;
36486
36840
  }
36487
36841
  async function writeAtomic(filePath, contents, mode) {
36488
- await mkdir10(path24.dirname(filePath), { recursive: true, mode: 448 });
36489
- const temporary = path24.join(
36490
- path24.dirname(filePath),
36491
- `.${path24.basename(filePath)}.${process.pid}.${randomUUID14()}.tmp`
36842
+ await mkdir10(path25.dirname(filePath), { recursive: true, mode: 448 });
36843
+ const temporary = path25.join(
36844
+ path25.dirname(filePath),
36845
+ `.${path25.basename(filePath)}.${process.pid}.${randomUUID14()}.tmp`
36492
36846
  );
36493
36847
  try {
36494
36848
  if (typeof contents === "string") {
@@ -36509,10 +36863,10 @@ async function writeAtomic(filePath, contents, mode) {
36509
36863
  }
36510
36864
  }
36511
36865
  async function writeAtomicExecutable(filePath, sourcePath) {
36512
- await mkdir10(path24.dirname(filePath), { recursive: true, mode: 448 });
36513
- const temporary = path24.join(
36514
- path24.dirname(filePath),
36515
- `.${path24.basename(filePath)}.${process.pid}.${randomUUID14()}.tmp`
36866
+ await mkdir10(path25.dirname(filePath), { recursive: true, mode: 448 });
36867
+ const temporary = path25.join(
36868
+ path25.dirname(filePath),
36869
+ `.${path25.basename(filePath)}.${process.pid}.${randomUUID14()}.tmp`
36516
36870
  );
36517
36871
  try {
36518
36872
  await copyFile3(sourcePath, temporary);
@@ -36553,8 +36907,8 @@ function removeManagedProfileBlock(contents) {
36553
36907
  function installManagedProfileBlock(contents, manifest) {
36554
36908
  const base = removeManagedProfileBlock(contents);
36555
36909
  const environment = [
36556
- `export CODEX_INSTALL_DIR=${shellQuote(path24.dirname(manifest.wrapperPath))}`,
36557
- `export PATH=${shellQuote(path24.dirname(manifest.wrapperPath))}:${shellQuote(path24.dirname(manifest.nodePath))}:${shellQuote(path24.dirname(manifest.stockCodexPath))}:"\${PATH:-/usr/local/bin:/usr/bin:/bin}"`,
36910
+ `export CODEX_INSTALL_DIR=${shellQuote(path25.dirname(manifest.wrapperPath))}`,
36911
+ `export PATH=${shellQuote(path25.dirname(manifest.wrapperPath))}:${shellQuote(path25.dirname(manifest.nodePath))}:${shellQuote(path25.dirname(manifest.stockCodexPath))}:"\${PATH:-/usr/local/bin:/usr/bin:/bin}"`,
36558
36912
  `export CODEXHOST_STOCK_CODEX_PATH=${shellQuote(manifest.stockCodexPath)}`,
36559
36913
  `export CODEXHOST_HOST_NODE_PATH=${shellQuote(manifest.nodePath)}`,
36560
36914
  `export CODEXHOST_HOST_RUNTIME_PATH=${shellQuote(manifest.hostRuntimePath)}`,
@@ -36570,7 +36924,7 @@ function installManagedProfileBlock(contents, manifest) {
36570
36924
  PROFILE_END,
36571
36925
  ""
36572
36926
  ].join("\n");
36573
- if (path24.basename(manifest.profilePath) === ".bashrc") return `${block}${base}`;
36927
+ if (path25.basename(manifest.profilePath) === ".bashrc") return `${block}${base}`;
36574
36928
  const separator = base.length > 0 && !base.endsWith("\n") ? "\n" : "";
36575
36929
  return `${base}${separator}${block}`;
36576
36930
  }
@@ -36636,9 +36990,9 @@ async function readManifest(filePath) {
36636
36990
  ];
36637
36991
  const optionalPaths = ["claudeCommand", "profileBackupPath"];
36638
36992
  if (manifest.format !== MANIFEST_FORMAT || Object.keys(manifest).some((key) => !allowed.has(key)) || requiredPaths.some(
36639
- (key) => typeof manifest[key] !== "string" || !path24.isAbsolute(manifest[key])
36993
+ (key) => typeof manifest[key] !== "string" || !path25.isAbsolute(manifest[key])
36640
36994
  ) || optionalPaths.some(
36641
- (key) => manifest[key] !== void 0 && (typeof manifest[key] !== "string" || !path24.isAbsolute(manifest[key]))
36995
+ (key) => manifest[key] !== void 0 && (typeof manifest[key] !== "string" || !path25.isAbsolute(manifest[key]))
36642
36996
  ) || manifest.entrypointSha256 !== void 0 && (typeof manifest.entrypointSha256 !== "string" || !/^[a-f0-9]{64}$/u.test(manifest.entrypointSha256))) {
36643
36997
  throw new Error("Remote Host manifest has an unsupported format");
36644
36998
  }
@@ -36647,7 +37001,7 @@ async function readManifest(filePath) {
36647
37001
  async function backupProfile(profilePath, contents, action) {
36648
37002
  const timestamp = (/* @__PURE__ */ new Date()).toISOString().replaceAll(/[-:.TZ]/gu, "");
36649
37003
  const backupPath = `${profilePath}.codexhost-${action}-${timestamp}.bak`;
36650
- const metadata = await stat5(profilePath).catch(() => null);
37004
+ const metadata = await stat6(profilePath).catch(() => null);
36651
37005
  await writeAtomic(backupPath, contents, metadata?.mode ?? 384);
36652
37006
  return backupPath;
36653
37007
  }
@@ -36661,7 +37015,7 @@ async function installRemoteHost(options2) {
36661
37015
  const previousManifest = await readManifest(paths.manifestPath);
36662
37016
  const previousManifestFile = previousManifest ? {
36663
37017
  contents: await readFile10(paths.manifestPath),
36664
- mode: (await stat5(paths.manifestPath)).mode & 511
37018
+ mode: (await stat6(paths.manifestPath)).mode & 511
36665
37019
  } : null;
36666
37020
  const existingEntrypoint = await lstat8(paths.wrapperPath).catch(
36667
37021
  (error51) => {
@@ -36717,7 +37071,7 @@ async function installRemoteHost(options2) {
36717
37071
  const existingProfile = existingProfileSource ?? "";
36718
37072
  const nextProfile = installManagedProfileBlock(existingProfile, manifest);
36719
37073
  const profileChanged = nextProfile !== existingProfile;
36720
- const profileMetadata = await stat5(profilePath).catch(() => null);
37074
+ const profileMetadata = await stat6(profilePath).catch(() => null);
36721
37075
  try {
36722
37076
  if (profileChanged) {
36723
37077
  const profileBackupPath = await backupProfile(profilePath, existingProfile, "install");
@@ -36808,7 +37162,7 @@ async function inspectRemoteHostInstallation(options2) {
36808
37162
  if (!profileMatches && profileIssue === null)
36809
37163
  profileIssue = "shell profile does not configure the managed native entrypoint";
36810
37164
  if (profileIssue !== null) issues.push(profileIssue);
36811
- const dataDirectory = await stat5(manifest.dataDirectory).catch(() => null);
37165
+ const dataDirectory = await stat6(manifest.dataDirectory).catch(() => null);
36812
37166
  if (!dataDirectory?.isDirectory()) issues.push("remote Host data directory is unavailable");
36813
37167
  for (const [label, filePath, requiresExecutable] of [
36814
37168
  ["stock Codex", manifest.stockCodexPath, true],
@@ -36818,7 +37172,7 @@ async function inspectRemoteHostInstallation(options2) {
36818
37172
  ]) {
36819
37173
  try {
36820
37174
  if (requiresExecutable) await executable(filePath, label);
36821
- else if (!(await stat5(filePath)).isFile()) throw new Error("not a regular file");
37175
+ else if (!(await stat6(filePath)).isFile()) throw new Error("not a regular file");
36822
37176
  } catch {
36823
37177
  issues.push(`${label} is unavailable`);
36824
37178
  }
@@ -36847,7 +37201,7 @@ async function uninstallRemoteHost(options2) {
36847
37201
  const nextProfile = removeManagedProfileBlock(profile);
36848
37202
  if (nextProfile !== profile) {
36849
37203
  await backupProfile(manifest.profilePath, profile, "uninstall");
36850
- const metadata = await stat5(manifest.profilePath).catch(() => null);
37204
+ const metadata = await stat6(manifest.profilePath).catch(() => null);
36851
37205
  await writeAtomic(manifest.profilePath, nextProfile, metadata?.mode ?? 384);
36852
37206
  }
36853
37207
  await rm10(manifest.wrapperPath, { force: true });
@@ -36862,9 +37216,9 @@ async function uninstallRemoteHost(options2) {
36862
37216
 
36863
37217
  // packages/host-runtime/src/remote-host-lifecycle.ts
36864
37218
  import { spawn as spawn5 } from "node:child_process";
36865
- import { stat as stat6 } from "node:fs/promises";
37219
+ import { stat as stat7 } from "node:fs/promises";
36866
37220
  import net3 from "node:net";
36867
- import path25 from "node:path";
37221
+ import path26 from "node:path";
36868
37222
  import { Duplex } from "node:stream";
36869
37223
 
36870
37224
  // packages/host-runtime/src/app-server-websocket-options.ts
@@ -36891,12 +37245,12 @@ function classifyRemoteHostProbeResponse(response, socketPath) {
36891
37245
  }
36892
37246
  var lifecycleDependencyOverrides = {};
36893
37247
  function socketPathFor(environment) {
36894
- const codexHome = environment.CODEX_HOME ?? (environment.HOME ? path25.join(environment.HOME, ".codex") : void 0);
37248
+ const codexHome = environment.CODEX_HOME ?? (environment.HOME ? path26.join(environment.HOME, ".codex") : void 0);
36895
37249
  if (!codexHome) throw new Error("CODEX_HOME or HOME is required for remote Host lifecycle");
36896
- return path25.join(codexHome, "app-server-control", "app-server-control.sock");
37250
+ return path26.join(codexHome, "app-server-control", "app-server-control.sock");
36897
37251
  }
36898
37252
  async function defaultSocketExists(socketPath) {
36899
- const metadata = await stat6(socketPath).catch((error51) => {
37253
+ const metadata = await stat7(socketPath).catch((error51) => {
36900
37254
  if (error51.code === "ENOENT") return null;
36901
37255
  throw error51;
36902
37256
  });
@@ -37023,14 +37377,14 @@ function installedManifest(status) {
37023
37377
  function managedEnvironment(manifest, environment) {
37024
37378
  return {
37025
37379
  ...environment,
37026
- CODEX_INSTALL_DIR: path25.dirname(manifest.wrapperPath),
37380
+ CODEX_INSTALL_DIR: path26.dirname(manifest.wrapperPath),
37027
37381
  CODEXHOST_STOCK_CODEX_PATH: manifest.stockCodexPath,
37028
37382
  CODEXHOST_HOST_NODE_PATH: manifest.nodePath,
37029
37383
  CODEXHOST_HOST_RUNTIME_PATH: manifest.hostRuntimePath,
37030
37384
  CODEXHOST_DATA_DIR: manifest.dataDirectory,
37031
37385
  CODEXHOST_DEFAULT_AGENT: "codex",
37032
37386
  CODEXHOST_REMOTE_SSH_MANAGED: "1",
37033
- PATH: `${path25.dirname(manifest.wrapperPath)}${path25.delimiter}${path25.dirname(manifest.stockCodexPath)}${path25.delimiter}${environment.PATH ?? "/usr/bin:/bin"}`
37387
+ PATH: `${path26.dirname(manifest.wrapperPath)}${path26.delimiter}${path26.dirname(manifest.stockCodexPath)}${path26.delimiter}${environment.PATH ?? "/usr/bin:/bin"}`
37034
37388
  };
37035
37389
  }
37036
37390
  async function defaultRunTerminator(manifest, socketPath, role, environment) {
@@ -37369,25 +37723,25 @@ function consumeBrokerFrames(socket, onFrame, onError) {
37369
37723
 
37370
37724
  // packages/harness-broker/dist/paths.js
37371
37725
  import os7 from "node:os";
37372
- import path26 from "node:path";
37726
+ import path27 from "node:path";
37373
37727
  var HARNESS_BROKER_DESCRIPTOR_ENV = "CODEXHOST_CLAUDE_BROKER_DESCRIPTOR";
37374
37728
  var HARNESS_BROKER_DESCRIPTOR_FILE = "claude-code-broker-v1.json";
37375
37729
  var HARNESS_BROKER_SOCKET_FILE = "claude-code-broker-v1.sock";
37376
37730
  function defaultHarnessBrokerDirectory(environment = process.env) {
37377
37731
  const home = environment.HOME || os7.homedir();
37378
- return path26.join(home, ".codexhost", "harness-broker");
37732
+ return path27.join(home, ".codexhost", "harness-broker");
37379
37733
  }
37380
37734
  function defaultHarnessBrokerDescriptorPath(environment = process.env, harnessId = "claude-code") {
37381
37735
  harnessPluginIdSchema.parse(harnessId);
37382
37736
  if (harnessId !== "claude-code")
37383
- return path26.join(defaultHarnessBrokerDirectory(environment), `${harnessId}-broker-v1.json`);
37384
- return environment[HARNESS_BROKER_DESCRIPTOR_ENV] ?? path26.join(defaultHarnessBrokerDirectory(environment), HARNESS_BROKER_DESCRIPTOR_FILE);
37737
+ return path27.join(defaultHarnessBrokerDirectory(environment), `${harnessId}-broker-v1.json`);
37738
+ return environment[HARNESS_BROKER_DESCRIPTOR_ENV] ?? path27.join(defaultHarnessBrokerDirectory(environment), HARNESS_BROKER_DESCRIPTOR_FILE);
37385
37739
  }
37386
37740
  function defaultHarnessBrokerSocketPath(environment = process.env, harnessId = "claude-code") {
37387
37741
  harnessPluginIdSchema.parse(harnessId);
37388
37742
  if (harnessId !== "claude-code")
37389
- return path26.join(defaultHarnessBrokerDirectory(environment), `${harnessId}-broker-v1.sock`);
37390
- return path26.join(defaultHarnessBrokerDirectory(environment), HARNESS_BROKER_SOCKET_FILE);
37743
+ return path27.join(defaultHarnessBrokerDirectory(environment), `${harnessId}-broker-v1.sock`);
37744
+ return path27.join(defaultHarnessBrokerDirectory(environment), HARNESS_BROKER_SOCKET_FILE);
37391
37745
  }
37392
37746
 
37393
37747
  // packages/harness-broker/dist/validation.js
@@ -37624,7 +37978,7 @@ var harnessOutputSchema = external_exports.custom((value2) => {
37624
37978
  import { randomBytes as randomBytes3, randomUUID as randomUUID15 } from "node:crypto";
37625
37979
  import { chmod as chmod5, lstat as lstat9, mkdir as mkdir11, open as open8, readFile as readFile11, rename as rename8, rm as rm11 } from "node:fs/promises";
37626
37980
  import net4, {} from "node:net";
37627
- import path27 from "node:path";
37981
+ import path28 from "node:path";
37628
37982
  function harnessError(message, retryable = true) {
37629
37983
  return { code: "unavailable", message, retryable, stage: "harnessBroker" };
37630
37984
  }
@@ -37747,13 +38101,13 @@ async function prepareUnixSocketPath(socketPath) {
37747
38101
  }
37748
38102
  async function startHarnessBrokerServer(input) {
37749
38103
  harnessPluginIdSchema.parse(input.adapter.harnessId);
37750
- if (process.platform !== "win32" && path27.dirname(input.descriptorPath) !== path27.dirname(input.socketPath)) {
38104
+ if (process.platform !== "win32" && path28.dirname(input.descriptorPath) !== path28.dirname(input.socketPath)) {
37751
38105
  throw new Error("Harness broker descriptor and socket must share one private directory");
37752
38106
  }
37753
38107
  if (process.platform === "darwin" && Buffer.byteLength(input.socketPath) > 103) {
37754
38108
  throw new Error("Harness broker Unix socket path is too long for macOS");
37755
38109
  }
37756
- await privateDirectory(path27.dirname(input.descriptorPath));
38110
+ await privateDirectory(path28.dirname(input.descriptorPath));
37757
38111
  await assertNoLiveDescriptor(input.descriptorPath);
37758
38112
  if (process.platform !== "win32")
37759
38113
  await prepareUnixSocketPath(input.socketPath);