@codexhost/cli-darwin-x64 0.9.2 → 0.10.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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 path22 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, path27) {
5982
- if (!path27)
5981
+ function getElementAtPath(obj, path29) {
5982
+ if (!path29)
5983
5983
  return obj;
5984
- return path27.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(path27, 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(path27);
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, path27 = []) => {
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 }, [...path27, ...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 }, [...path27, ...issue2.path]);
6549
+ processError({ issues: issue2.issues }, [...path29, ...issue2.path]);
6550
6550
  } else if (issue2.code === "invalid_element") {
6551
- processError({ issues: issue2.issues }, [...path27, ...issue2.path]);
6551
+ processError({ issues: issue2.issues }, [...path29, ...issue2.path]);
6552
6552
  } else {
6553
- const fullpath = [...path27, ...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, path27 = []) => {
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 }, [...path27, ...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 }, [...path27, ...issue2.path]);
6586
+ processError({ issues: issue2.issues }, [...path29, ...issue2.path]);
6587
6587
  } else if (issue2.code === "invalid_element") {
6588
- processError({ issues: issue2.issues }, [...path27, ...issue2.path]);
6588
+ processError({ issues: issue2.issues }, [...path29, ...issue2.path]);
6589
6589
  } else {
6590
- const fullpath = [...path27, ...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 path27 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
6623
- for (const seg of path27) {
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 path27 = ref.slice(1).split("/").filter(Boolean);
19316
- if (path27.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 (path27[0] === defsKey) {
19321
- const key = path27[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
  }
@@ -20522,10 +20522,21 @@ var harnessCommandDescriptorSchema = external_exports.object({
20522
20522
  invocation: commandInvocationSchema,
20523
20523
  label: commandLabelSchema,
20524
20524
  description: commandDescriptionSchema.optional(),
20525
- argumentMode: external_exports.enum(["none", "text"])
20525
+ argumentMode: external_exports.enum(["none", "text"]),
20526
+ /**
20527
+ * Native distinction reported by the Harness. Omitted when the Harness does
20528
+ * not tell skills and commands apart; consumers treat that as "command".
20529
+ */
20530
+ kind: external_exports.enum(["command", "skill"]).optional()
20526
20531
  }).strict();
20527
20532
  var harnessCommandCatalogSchema = external_exports.object({
20528
- commands: external_exports.array(harnessCommandDescriptorSchema)
20533
+ commands: external_exports.array(harnessCommandDescriptorSchema),
20534
+ /**
20535
+ * `live` when the catalog includes what a native Session reports for its
20536
+ * workspace (custom commands, skills); `static` for Adapter built-ins only.
20537
+ * Omitted by Adapters; set by the Host on inspection results.
20538
+ */
20539
+ source: external_exports.enum(["live", "static"]).optional()
20529
20540
  }).strict().superRefine((catalog, context) => {
20530
20541
  const ids = /* @__PURE__ */ new Set();
20531
20542
  for (const [index, command] of catalog.commands.entries()) {
@@ -20539,7 +20550,11 @@ var harnessCommandCatalogSchema = external_exports.object({
20539
20550
  ids.add(command.id);
20540
20551
  }
20541
20552
  });
20542
- var harnessCommandsInspectParamsSchema = external_exports.object({ harnessId: harnessIdSchema }).strict();
20553
+ var harnessCommandsInspectParamsSchema = external_exports.object({
20554
+ harnessId: harnessIdSchema,
20555
+ /** Workspace of a draft without a Thread, for its live catalog when known. */
20556
+ cwd: external_exports.string().min(1).optional()
20557
+ }).strict();
20543
20558
  var threadCommandsInspectParamsSchema = external_exports.object({
20544
20559
  threadId: hostThreadIdSchema
20545
20560
  }).strict();
@@ -20683,6 +20698,41 @@ var updateStatusResultSchema = external_exports.strictObject({
20683
20698
  status: updateStatusSchema.nullable()
20684
20699
  });
20685
20700
 
20701
+ // packages/shared-contracts/dist/delegation-mention.js
20702
+ var DELEGATION_MENTION_PATH_PREFIX = "subagent://codexhost.";
20703
+ var MENTION_LINK_PATTERN = /\[@([^\]\n]+)\]\(<?subagent:\/\/codexhost\.([a-z0-9][a-z0-9-]*)>?\)/gu;
20704
+ function stripDelegationMentions(text) {
20705
+ const mentions = [];
20706
+ const seen = /* @__PURE__ */ new Set();
20707
+ const rewritten = text.replace(MENTION_LINK_PATTERN, (_match, label, harnessId) => {
20708
+ const trimmed = label.trim();
20709
+ if (!seen.has(harnessId)) {
20710
+ seen.add(harnessId);
20711
+ mentions.push({ harnessId, label: trimmed });
20712
+ }
20713
+ return `@${trimmed}`;
20714
+ });
20715
+ return { text: rewritten, mentions };
20716
+ }
20717
+ var COMMAND_LINK_PATTERN = /([ \t]*)\[@([^\]\n]+)\]\(<?subagent:\/\/codexhost-command\.([^)\s>]+)>?\)([ \t]*)/gu;
20718
+ function restoreHarnessCommandMentions(text) {
20719
+ let invocation = null;
20720
+ const rest = text.replace(COMMAND_LINK_PATTERN, (match, before, _label, encoded, after) => {
20721
+ if (invocation === null) {
20722
+ try {
20723
+ invocation = `/${decodeURIComponent(encoded)}`;
20724
+ } catch {
20725
+ return match;
20726
+ }
20727
+ }
20728
+ return before || after ? " " : "";
20729
+ });
20730
+ if (invocation === null)
20731
+ return text;
20732
+ const argumentsText = rest.trim();
20733
+ return argumentsText ? `${invocation} ${argumentsText}` : invocation;
20734
+ }
20735
+
20686
20736
  // packages/shared-contracts/dist/index.js
20687
20737
  var workspaceContractVersionSchema = external_exports.literal(WORKSPACE_CONTRACT_VERSION);
20688
20738
 
@@ -20777,6 +20827,231 @@ async function listOthers(adapter) {
20777
20827
  }
20778
20828
  }
20779
20829
 
20830
+ // packages/host-runtime/src/delegation-skill.ts
20831
+ import { createHash as createHash3, randomUUID as randomUUID2 } from "node:crypto";
20832
+ import { mkdir as mkdir3, open as open3, readFile as readFile5, rename as rename2, rm as rm3, stat } from "node:fs/promises";
20833
+ import os2 from "node:os";
20834
+ import path6 from "node:path";
20835
+ var SKILL_VERSION = 7;
20836
+ var DELEGATION_SKILL_NAME = "codexhost-delegation";
20837
+ var SKILL_RELATIVE_PATH = path6.join("skills", DELEGATION_SKILL_NAME, "SKILL.md");
20838
+ var PREVIOUS_MANAGED_DIGESTS = [
20839
+ "9d2f491850fb0b4084a31ba9b5e4a550b5e833747af322090d8ed0ff80b88c30",
20840
+ "2bb0aebb9b06febbc6c0c0bcdb0b32506c7cdbf8dc3b734cc6b2a86621270e4e",
20841
+ "aff258622dc8ff321f32b15620d081e578cb9c9ed1134d6a57f35ca8e7762c0a",
20842
+ "ba509f57e5448e796b3dfdd5031dcb08672eded50b61c0a54de84cfa02c49dd3",
20843
+ "d3ddf6db9bc5c5df825479c885bbbf0ca08da66f7057a12e02e1fdf57525149e",
20844
+ "15eb63519ff867e1536c97188a0c43738d7a49d38d4d6adeb7a1036726e7246d"
20845
+ ];
20846
+ var CODEXHOST_DELEGATION_SKILL = `---
20847
+ name: codexhost-delegation
20848
+ version: ${SKILL_VERSION}
20849
+ description: >
20850
+ Delegate tasks to other coding agents, or read and follow up on existing
20851
+ external agent sessions. Use when the user asks another agent (including
20852
+ @agent) to independently perform a task, or asks to view a specified external
20853
+ session's content, progress, or results, send follow-up messages, wait, or
20854
+ cancel a task. Not for recapping the current conversation, discussing or
20855
+ configuring agents, or role-playing.
20856
+ ---
20857
+
20858
+ # Execute the task
20859
+
20860
+ Before acting, run:
20861
+
20862
+ \`codexhost delegate --help\`
20863
+
20864
+ Use CLI help as the authoritative source for commands and behavior. Consult
20865
+ command-specific help for options and the Harness listing command when the
20866
+ target is unknown. Prefer compact output when supported, and use its task links
20867
+ directly for subsequent commands.
20868
+
20869
+ Use the Harness native defaults. Inspect the target when a Model or Thinking
20870
+ selection is needed or the default is unavailable.
20871
+
20872
+ For a new delegation, create an independent child session and submit the
20873
+ requested task. For an existing external session, resolve the target from the
20874
+ user-provided session link, identifier, or context and operate on that Thread
20875
+ directly; it need not have been created by the current assistant. If the target
20876
+ is ambiguous, ask the user to identify it. Keep requests to view or summarize a
20877
+ session read-only.
20878
+
20879
+ For a new or existing task, choose the appropriate next action based on the
20880
+ user’s request and the task:
20881
+
20882
+ - send a follow-up message to the same Thread;
20883
+ - cancel its current Turn;
20884
+ - read its current state immediately;
20885
+ - wait for a bounded period;
20886
+ - check it again later;
20887
+ - leave it running in the background.
20888
+
20889
+ Report the result returned by read or a completed wait, together with the target
20890
+ agent, status, and a labeled task link. Keep internal tracking IDs in tool calls.
20891
+ `;
20892
+ var CURRENT_DIGEST = createHash3("sha256").update(CODEXHOST_DELEGATION_SKILL).digest("hex");
20893
+ function digest(value2) {
20894
+ return createHash3("sha256").update(value2).digest("hex");
20895
+ }
20896
+ function managedVersion(value2) {
20897
+ const match = /^version:\s*(\d+)\s*$/mu.exec(value2);
20898
+ return match ? Number(match[1]) : null;
20899
+ }
20900
+ async function readOptional(filePath) {
20901
+ try {
20902
+ return await readFile5(filePath, "utf8");
20903
+ } catch (error51) {
20904
+ if (error51.code === "ENOENT") return null;
20905
+ throw error51;
20906
+ }
20907
+ }
20908
+ async function atomicWrite(filePath, content) {
20909
+ await mkdir3(path6.dirname(filePath), { recursive: true, mode: 448 });
20910
+ const temporaryPath = path6.join(path6.dirname(filePath), `.SKILL.md.${randomUUID2()}.tmp`);
20911
+ const handle = await open3(temporaryPath, "wx", 384);
20912
+ try {
20913
+ await handle.writeFile(content, "utf8");
20914
+ await handle.sync();
20915
+ } finally {
20916
+ await handle.close();
20917
+ }
20918
+ try {
20919
+ await rename2(temporaryPath, filePath);
20920
+ } finally {
20921
+ await rm3(temporaryPath, { force: true });
20922
+ }
20923
+ }
20924
+ async function installDelegationSkills(input = {}) {
20925
+ const home = input.homeDirectory ?? os2.homedir();
20926
+ const destinations = [
20927
+ path6.join(home, ".agents", SKILL_RELATIVE_PATH),
20928
+ path6.join(home, ".claude", SKILL_RELATIVE_PATH)
20929
+ ];
20930
+ const knownDigests = /* @__PURE__ */ new Set([
20931
+ CURRENT_DIGEST,
20932
+ ...PREVIOUS_MANAGED_DIGESTS,
20933
+ ...input.previousManagedDigests ?? []
20934
+ ]);
20935
+ const results = [];
20936
+ for (const destination of destinations) {
20937
+ const current = await readOptional(destination);
20938
+ if (current === CODEXHOST_DELEGATION_SKILL) {
20939
+ results.push({
20940
+ path: destination,
20941
+ status: "current",
20942
+ version: SKILL_VERSION,
20943
+ digest: CURRENT_DIGEST
20944
+ });
20945
+ continue;
20946
+ }
20947
+ if (current !== null) {
20948
+ const currentDigest = digest(current);
20949
+ const version2 = managedVersion(current);
20950
+ if (!knownDigests.has(currentDigest)) {
20951
+ results.push({ path: destination, status: "conflict", version: version2, digest: currentDigest });
20952
+ continue;
20953
+ }
20954
+ await atomicWrite(destination, CODEXHOST_DELEGATION_SKILL);
20955
+ results.push({
20956
+ path: destination,
20957
+ status: "updated",
20958
+ version: SKILL_VERSION,
20959
+ digest: CURRENT_DIGEST
20960
+ });
20961
+ continue;
20962
+ }
20963
+ await atomicWrite(destination, CODEXHOST_DELEGATION_SKILL);
20964
+ results.push({
20965
+ path: destination,
20966
+ status: "installed",
20967
+ version: SKILL_VERSION,
20968
+ digest: CURRENT_DIGEST
20969
+ });
20970
+ }
20971
+ for (const result of results) {
20972
+ if (result.status === "conflict") continue;
20973
+ const source = await readFile5(result.path, "utf8");
20974
+ const metadata = await stat(result.path);
20975
+ if (!metadata.isFile() || source !== CODEXHOST_DELEGATION_SKILL) {
20976
+ throw new Error(`Delegation Skill verification failed: ${result.path}`);
20977
+ }
20978
+ }
20979
+ const managed = results.filter((result) => result.status !== "conflict");
20980
+ if (managed.some((result) => result.digest !== CURRENT_DIGEST)) {
20981
+ throw new Error("Delegation Skill copies are inconsistent");
20982
+ }
20983
+ if (results.every((result) => result.status !== "conflict")) {
20984
+ const copies = await Promise.all(results.map((result) => readFile5(result.path, "utf8")));
20985
+ if (copies.some((copy) => copy !== copies[0])) {
20986
+ throw new Error("Delegation Skill copies are inconsistent");
20987
+ }
20988
+ }
20989
+ return results;
20990
+ }
20991
+ async function managedDelegationSkillReference(input = {}) {
20992
+ const filePath = path6.join(input.homeDirectory ?? os2.homedir(), ".agents", SKILL_RELATIVE_PATH);
20993
+ try {
20994
+ return await readOptional(filePath) === CODEXHOST_DELEGATION_SKILL ? { name: DELEGATION_SKILL_NAME, path: filePath } : null;
20995
+ } catch {
20996
+ return null;
20997
+ }
20998
+ }
20999
+
21000
+ // packages/host-runtime/src/delegation-mention-rewrite.ts
21001
+ function describeTargets(mentions) {
21002
+ return mentions.map(({ harnessId, label }) => `@${label} (Harness \`${harnessId}\`)`).join(", ");
21003
+ }
21004
+ function delegationMentionInstruction(mentions) {
21005
+ const plural = mentions.length > 1;
21006
+ return [
21007
+ `[codexhost delegation] The user mentioned ${describeTargets(mentions)}.`,
21008
+ `Use the ${DELEGATION_SKILL_NAME} skill to delegate this request to ${plural ? "each mentioned Harness" : "that Harness"}`,
21009
+ "with `codexhost delegate start --harness <id>`, instead of doing the task yourself."
21010
+ ].join(" ");
21011
+ }
21012
+ function appendInstruction(text, mentions) {
21013
+ const instruction = delegationMentionInstruction(mentions);
21014
+ return text.trim().length === 0 ? instruction : `${text}
21015
+
21016
+ ${instruction}`;
21017
+ }
21018
+ function rewriteDelegationMentionText(text) {
21019
+ const { text: stripped, mentions } = stripDelegationMentions(text);
21020
+ return mentions.length === 0 ? text : appendInstruction(stripped, mentions);
21021
+ }
21022
+ function isRecord(value2) {
21023
+ return typeof value2 === "object" && value2 !== null && !Array.isArray(value2);
21024
+ }
21025
+ function rewriteDelegationMentionInput(input, skill) {
21026
+ const mentions = [];
21027
+ const seen = /* @__PURE__ */ new Set();
21028
+ let lastTextIndex = -1;
21029
+ const rewritten = input.map((item, index) => {
21030
+ if (!isRecord(item) || item.type !== "text" || typeof item.text !== "string") return item;
21031
+ lastTextIndex = index;
21032
+ const result = stripDelegationMentions(item.text);
21033
+ for (const mention of result.mentions) {
21034
+ if (seen.has(mention.harnessId)) continue;
21035
+ seen.add(mention.harnessId);
21036
+ mentions.push(mention);
21037
+ }
21038
+ return result.mentions.length === 0 ? item : { ...item, text: result.text };
21039
+ });
21040
+ if (mentions.length === 0) return null;
21041
+ const target = rewritten[lastTextIndex];
21042
+ if (isRecord(target) && typeof target.text === "string") {
21043
+ rewritten[lastTextIndex] = {
21044
+ ...target,
21045
+ text: appendInstruction(target.text, mentions)
21046
+ };
21047
+ }
21048
+ const hasSkill = rewritten.some(
21049
+ (item) => isRecord(item) && item.type === "skill" && item.name === skill?.name
21050
+ );
21051
+ if (skill && !hasSkill) rewritten.push({ type: "skill", name: skill.name, path: skill.path });
21052
+ return rewritten;
21053
+ }
21054
+
20780
21055
  // packages/harness-adapter/dist/output-channel.js
20781
21056
  var HarnessOutputChannel = class {
20782
21057
  outputs;
@@ -20855,11 +21130,11 @@ var usageFields = /* @__PURE__ */ new Set([
20855
21130
  "totalCredits",
20856
21131
  "contextUsagePercent"
20857
21132
  ]);
20858
- function isRecord(value2) {
21133
+ function isRecord2(value2) {
20859
21134
  return typeof value2 === "object" && value2 !== null && !Array.isArray(value2);
20860
21135
  }
20861
21136
  function parseHostUsage(value2) {
20862
- if (!isRecord(value2))
21137
+ if (!isRecord2(value2))
20863
21138
  throw new Error("Harness Usage must be an object");
20864
21139
  const keys = Object.keys(value2);
20865
21140
  if (keys.length === 0)
@@ -20916,6 +21191,82 @@ function parseHostUsage(value2) {
20916
21191
  return { ...value2 };
20917
21192
  }
20918
21193
 
21194
+ // packages/harness-adapter/dist/live-command-catalog.js
21195
+ var COMMON_EXCLUDED_LIVE_COMMANDS = /* @__PURE__ */ new Set([
21196
+ // Session lifecycle
21197
+ "branch",
21198
+ "clear",
21199
+ "exit",
21200
+ "fork",
21201
+ "fresh",
21202
+ "new",
21203
+ "quit",
21204
+ "rename",
21205
+ "rename-chat",
21206
+ "reset",
21207
+ "resume",
21208
+ "rewind",
21209
+ "session",
21210
+ "sessions",
21211
+ // Desktop-owned configuration
21212
+ "autocompact",
21213
+ "color",
21214
+ "config",
21215
+ "effort",
21216
+ "fast",
21217
+ "keybindings",
21218
+ "model",
21219
+ "models",
21220
+ "output-style",
21221
+ "permissions",
21222
+ "settings",
21223
+ "statusline",
21224
+ "terminal-setup",
21225
+ "theme",
21226
+ "vim",
21227
+ // Trust and approval policy
21228
+ "always-approve",
21229
+ "auto-mode-setup",
21230
+ // Native login
21231
+ "login",
21232
+ "logout",
21233
+ // Work outliving the Turn
21234
+ "autopilot",
21235
+ "background",
21236
+ "bg",
21237
+ "goal",
21238
+ "jobs",
21239
+ "loop",
21240
+ "multitask",
21241
+ "queue",
21242
+ "remote-control",
21243
+ "schedule",
21244
+ "steer",
21245
+ // Native terminal UI
21246
+ "copy",
21247
+ "debug",
21248
+ "feedback",
21249
+ "heapdump",
21250
+ "share",
21251
+ "shell",
21252
+ // Plugin and MCP management
21253
+ "marketplace",
21254
+ "mcp",
21255
+ "plugins",
21256
+ "reload-plugins"
21257
+ ]);
21258
+ var COMMON_EXCLUDED_LIVE_COMMAND_PREFIXES = ["__", "hooks-"];
21259
+ function isExcludedLiveCommand(name, kind, extra = {}) {
21260
+ const normalized = name.trim().replace(/^\//u, "");
21261
+ if (new Set(extra.names ?? []).has(normalized))
21262
+ return true;
21263
+ if (extra.prefixes?.some((prefix) => normalized.startsWith(prefix)))
21264
+ return true;
21265
+ if (kind === "skill")
21266
+ return false;
21267
+ return COMMON_EXCLUDED_LIVE_COMMANDS.has(normalized) || COMMON_EXCLUDED_LIVE_COMMAND_PREFIXES.some((prefix) => normalized.startsWith(prefix));
21268
+ }
21269
+
20919
21270
  // packages/harness-adapter/dist/index.js
20920
21271
  var packageMetadata = {
20921
21272
  name: "@codexhost/harness-adapter",
@@ -20924,10 +21275,10 @@ var packageMetadata = {
20924
21275
 
20925
21276
  // packages/mapping-store/dist/mapping-store.js
20926
21277
  import { execFileSync } from "node:child_process";
20927
- import { randomUUID as randomUUID2 } from "node:crypto";
21278
+ import { randomUUID as randomUUID3 } from "node:crypto";
20928
21279
  import { constants } from "node:fs";
20929
- 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";
20930
- import path6 from "node:path";
21280
+ 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";
21281
+ import path7 from "node:path";
20931
21282
 
20932
21283
  // packages/mapping-store/dist/records.js
20933
21284
  var nonBlankTextSchema6 = external_exports.string().refine((value2) => value2.trim().length > 0, {
@@ -21078,7 +21429,7 @@ function systemErrorCode2(error51) {
21078
21429
  }
21079
21430
  async function exists(file2) {
21080
21431
  try {
21081
- await stat(file2);
21432
+ await stat2(file2);
21082
21433
  return true;
21083
21434
  } catch (error51) {
21084
21435
  if (systemErrorCode2(error51) === "ENOENT")
@@ -21188,13 +21539,13 @@ var MappingStore = class {
21188
21539
  #initialized = false;
21189
21540
  #lockHandle = null;
21190
21541
  constructor(options2) {
21191
- this.#directory = path6.resolve(options2.directory);
21192
- this.#threadsDirectory = path6.join(this.#directory, "threads");
21193
- this.#delegationsDirectory = path6.join(this.#directory, "delegations");
21194
- this.#backupsDirectory = path6.join(this.#directory, "backups");
21195
- this.#quarantineDirectory = path6.join(this.#directory, "quarantine");
21196
- this.#lockPath = path6.join(this.#directory, "store.lock");
21197
- this.#instanceId = options2.instanceId ?? randomUUID2();
21542
+ this.#directory = path7.resolve(options2.directory);
21543
+ this.#threadsDirectory = path7.join(this.#directory, "threads");
21544
+ this.#delegationsDirectory = path7.join(this.#directory, "delegations");
21545
+ this.#backupsDirectory = path7.join(this.#directory, "backups");
21546
+ this.#quarantineDirectory = path7.join(this.#directory, "quarantine");
21547
+ this.#lockPath = path7.join(this.#directory, "store.lock");
21548
+ this.#instanceId = options2.instanceId ?? randomUUID3();
21198
21549
  this.#now = options2.now ?? (() => /* @__PURE__ */ new Date());
21199
21550
  this.#beforeReplace = options2.beforeReplace;
21200
21551
  }
@@ -21202,18 +21553,18 @@ var MappingStore = class {
21202
21553
  if (this.#initialized)
21203
21554
  return;
21204
21555
  await Promise.all([
21205
- mkdir3(this.#threadsDirectory, { recursive: true }),
21206
- mkdir3(this.#delegationsDirectory, { recursive: true }),
21207
- mkdir3(this.#backupsDirectory, { recursive: true }),
21208
- mkdir3(this.#quarantineDirectory, { recursive: true })
21556
+ mkdir4(this.#threadsDirectory, { recursive: true }),
21557
+ mkdir4(this.#delegationsDirectory, { recursive: true }),
21558
+ mkdir4(this.#backupsDirectory, { recursive: true }),
21559
+ mkdir4(this.#quarantineDirectory, { recursive: true })
21209
21560
  ]);
21210
21561
  await this.#acquireLock();
21211
21562
  try {
21212
21563
  await this.#cleanupResidue();
21213
21564
  const names = (await readdir2(this.#threadsDirectory)).filter((name) => name.endsWith(".json"));
21214
21565
  for (const name of names) {
21215
- const primary = path6.join(this.#threadsDirectory, name);
21216
- const backup = path6.join(this.#backupsDirectory, name);
21566
+ const primary = path7.join(this.#threadsDirectory, name);
21567
+ const backup = path7.join(this.#backupsDirectory, name);
21217
21568
  let record3 = null;
21218
21569
  try {
21219
21570
  record3 = await this.#readRecord(primary, name);
@@ -21222,31 +21573,31 @@ var MappingStore = class {
21222
21573
  record3 = await this.#readRecord(backup, name);
21223
21574
  await this.#replaceFile(primary, record3, false);
21224
21575
  } catch (backupError) {
21225
- const quarantine = path6.join(this.#quarantineDirectory, `${name}.${this.#now().getTime()}.invalid`);
21226
- await rename2(primary, quarantine).catch(() => void 0);
21576
+ const quarantine = path7.join(this.#quarantineDirectory, `${name}.${this.#now().getTime()}.invalid`);
21577
+ await rename3(primary, quarantine).catch(() => void 0);
21227
21578
  void primaryError;
21228
21579
  void backupError;
21229
21580
  continue;
21230
21581
  }
21231
21582
  }
21232
21583
  if (record3.state === "creating" && !record3.nativeSessionRef) {
21233
- await rm3(primary, { force: true });
21234
- await rm3(backup, { force: true });
21584
+ await rm4(primary, { force: true });
21585
+ await rm4(backup, { force: true });
21235
21586
  continue;
21236
21587
  }
21237
21588
  this.#records.set(record3.hostThreadId, record3);
21238
21589
  }
21239
21590
  const delegationNames = (await readdir2(this.#delegationsDirectory)).filter((name) => name.endsWith(".json"));
21240
21591
  for (const name of delegationNames) {
21241
- const file2 = path6.join(this.#delegationsDirectory, name);
21592
+ const file2 = path7.join(this.#delegationsDirectory, name);
21242
21593
  try {
21243
- const parsed = storedDelegationRecordV1Schema.parse(JSON.parse(await readFile5(file2, "utf8")));
21594
+ const parsed = storedDelegationRecordV1Schema.parse(JSON.parse(await readFile6(file2, "utf8")));
21244
21595
  if (`${parsed.delegationId}.json` !== name)
21245
21596
  throw new Error("filename mismatch");
21246
21597
  this.#delegations.set(parsed.delegationId, parsed);
21247
21598
  } catch {
21248
- const quarantine = path6.join(this.#quarantineDirectory, `${name}.${this.#now().getTime()}.invalid-delegation`);
21249
- await rename2(file2, quarantine).catch(() => void 0);
21599
+ const quarantine = path7.join(this.#quarantineDirectory, `${name}.${this.#now().getTime()}.invalid-delegation`);
21600
+ await rename3(file2, quarantine).catch(() => void 0);
21250
21601
  }
21251
21602
  }
21252
21603
  this.#rebuildIndexes();
@@ -21344,7 +21695,7 @@ var MappingStore = class {
21344
21695
  }
21345
21696
  async removeDelegation(delegationId) {
21346
21697
  this.#requireInitialized();
21347
- await rm3(this.#delegationPath(delegationId), { force: true });
21698
+ await rm4(this.#delegationPath(delegationId), { force: true });
21348
21699
  this.#delegations.delete(delegationId);
21349
21700
  this.#rebuildIndexes();
21350
21701
  }
@@ -21517,8 +21868,8 @@ var MappingStore = class {
21517
21868
  if (!this.#records.has(hostThreadId))
21518
21869
  return;
21519
21870
  await Promise.all([
21520
- rm3(this.#recordPath(hostThreadId), { force: true }),
21521
- rm3(this.#backupPath(hostThreadId), { force: true })
21871
+ rm4(this.#recordPath(hostThreadId), { force: true }),
21872
+ rm4(this.#backupPath(hostThreadId), { force: true })
21522
21873
  ]);
21523
21874
  this.#records.delete(hostThreadId);
21524
21875
  this.#rebuildIndexes();
@@ -21531,9 +21882,9 @@ var MappingStore = class {
21531
21882
  if (handle)
21532
21883
  await handle.close().catch(() => void 0);
21533
21884
  try {
21534
- const current = JSON.parse(await readFile5(this.#lockPath, "utf8"));
21885
+ const current = JSON.parse(await readFile6(this.#lockPath, "utf8"));
21535
21886
  if (current.instanceId === this.#instanceId)
21536
- await rm3(this.#lockPath, { force: true });
21887
+ await rm4(this.#lockPath, { force: true });
21537
21888
  } catch {
21538
21889
  }
21539
21890
  }
@@ -21600,11 +21951,11 @@ var MappingStore = class {
21600
21951
  this.#rebuildIndexes();
21601
21952
  }
21602
21953
  async #replaceFile(target, record3, preserveBackup) {
21603
- const temp = `${target}.tmp-${randomUUID2()}`;
21954
+ const temp = `${target}.tmp-${randomUUID3()}`;
21604
21955
  let handle = null;
21605
21956
  try {
21606
21957
  await this.#beforeReplace?.(cloneRecord(record3));
21607
- handle = await open3(temp, "wx", constants.S_IRUSR | constants.S_IWUSR);
21958
+ handle = await open4(temp, "wx", constants.S_IRUSR | constants.S_IWUSR);
21608
21959
  await handle.writeFile(`${JSON.stringify(record3, null, 2)}
21609
21960
  `, "utf8");
21610
21961
  await handle.sync();
@@ -21613,10 +21964,10 @@ var MappingStore = class {
21613
21964
  if (preserveBackup && await exists(target)) {
21614
21965
  await copyFile2(target, this.#backupPath(record3.hostThreadId));
21615
21966
  }
21616
- await rename2(temp, target);
21967
+ await rename3(temp, target);
21617
21968
  } catch (error51) {
21618
21969
  await handle?.close().catch(() => void 0);
21619
- await rm3(temp, { force: true }).catch(() => void 0);
21970
+ await rm4(temp, { force: true }).catch(() => void 0);
21620
21971
  if (error51 instanceof MappingStoreError)
21621
21972
  throw error51;
21622
21973
  throw new MappingStoreError("IO_ERROR", "Mapping Store atomic replacement failed", {
@@ -21626,19 +21977,19 @@ var MappingStore = class {
21626
21977
  }
21627
21978
  async #replaceDelegationFile(record3) {
21628
21979
  const target = this.#delegationPath(record3.delegationId);
21629
- const temp = `${target}.tmp-${randomUUID2()}`;
21980
+ const temp = `${target}.tmp-${randomUUID3()}`;
21630
21981
  let handle = null;
21631
21982
  try {
21632
- handle = await open3(temp, "wx", constants.S_IRUSR | constants.S_IWUSR);
21983
+ handle = await open4(temp, "wx", constants.S_IRUSR | constants.S_IWUSR);
21633
21984
  await handle.writeFile(`${JSON.stringify(record3, null, 2)}
21634
21985
  `, "utf8");
21635
21986
  await handle.sync();
21636
21987
  await handle.close();
21637
21988
  handle = null;
21638
- await rename2(temp, target);
21989
+ await rename3(temp, target);
21639
21990
  } catch (error51) {
21640
21991
  await handle?.close().catch(() => void 0);
21641
- await rm3(temp, { force: true }).catch(() => void 0);
21992
+ await rm4(temp, { force: true }).catch(() => void 0);
21642
21993
  if (error51 instanceof MappingStoreError)
21643
21994
  throw error51;
21644
21995
  throw new MappingStoreError("IO_ERROR", "Delegation atomic replacement failed", {
@@ -21647,7 +21998,7 @@ var MappingStore = class {
21647
21998
  }
21648
21999
  }
21649
22000
  async #readRecord(file2, expectedName) {
21650
- const parsed = storedThreadRecordV1Schema.safeParse(JSON.parse(await readFile5(file2, "utf8")));
22001
+ const parsed = storedThreadRecordV1Schema.safeParse(JSON.parse(await readFile6(file2, "utf8")));
21651
22002
  if (!parsed.success) {
21652
22003
  throw new MappingStoreError("INVALID_RECORD", "Mapping Store record is invalid", {
21653
22004
  cause: parsed.error
@@ -21665,15 +22016,15 @@ var MappingStore = class {
21665
22016
  readdir2(this.#directory)
21666
22017
  ]);
21667
22018
  await Promise.all([
21668
- ...threadNames.filter((name) => name.includes(".tmp-")).map((name) => rm3(path6.join(this.#threadsDirectory, name), { force: true })),
21669
- ...delegationNames.filter((name) => name.includes(".tmp-")).map((name) => rm3(path6.join(this.#delegationsDirectory, name), { force: true })),
22019
+ ...threadNames.filter((name) => name.includes(".tmp-")).map((name) => rm4(path7.join(this.#threadsDirectory, name), { force: true })),
22020
+ ...delegationNames.filter((name) => name.includes(".tmp-")).map((name) => rm4(path7.join(this.#delegationsDirectory, name), { force: true })),
21670
22021
  // Renamed aside by #acquireLock; nothing reads them back, and they accumulate one per run.
21671
- ...rootNames.filter((name) => name.startsWith(`${path6.basename(this.#lockPath)}.stale-`)).map((name) => rm3(path6.join(this.#directory, name), { force: true }))
22022
+ ...rootNames.filter((name) => name.startsWith(`${path7.basename(this.#lockPath)}.stale-`)).map((name) => rm4(path7.join(this.#directory, name), { force: true }))
21672
22023
  ]);
21673
22024
  }
21674
22025
  async #acquireLock() {
21675
22026
  const attempt = async () => {
21676
- const handle = await open3(this.#lockPath, "wx", constants.S_IRUSR | constants.S_IWUSR);
22027
+ const handle = await open4(this.#lockPath, "wx", constants.S_IRUSR | constants.S_IWUSR);
21677
22028
  const lock = {
21678
22029
  pid: process.pid,
21679
22030
  instanceId: this.#instanceId,
@@ -21695,13 +22046,13 @@ var MappingStore = class {
21695
22046
  }
21696
22047
  let existing = {};
21697
22048
  try {
21698
- existing = JSON.parse(await readFile5(this.#lockPath, "utf8"));
22049
+ existing = JSON.parse(await readFile6(this.#lockPath, "utf8"));
21699
22050
  } catch {
21700
22051
  }
21701
22052
  if (typeof existing.pid === "number" && lockOwnerIsLive(existing)) {
21702
22053
  throw new MappingStoreError("STORE_LOCKED", "Another codexhost process owns Mapping Store");
21703
22054
  }
21704
- await rename2(this.#lockPath, `${this.#lockPath}.stale-${this.#now().getTime()}`).catch(() => void 0);
22055
+ await rename3(this.#lockPath, `${this.#lockPath}.stale-${this.#now().getTime()}`).catch(() => void 0);
21705
22056
  try {
21706
22057
  this.#lockHandle = await attempt();
21707
22058
  } catch (error51) {
@@ -21769,13 +22120,13 @@ var MappingStore = class {
21769
22120
  await next;
21770
22121
  }
21771
22122
  #recordPath(hostThreadId) {
21772
- return path6.join(this.#threadsDirectory, `${hostThreadId}.json`);
22123
+ return path7.join(this.#threadsDirectory, `${hostThreadId}.json`);
21773
22124
  }
21774
22125
  #delegationPath(delegationId) {
21775
- return path6.join(this.#delegationsDirectory, `${delegationId}.json`);
22126
+ return path7.join(this.#delegationsDirectory, `${delegationId}.json`);
21776
22127
  }
21777
22128
  #backupPath(hostThreadId) {
21778
- return path6.join(this.#backupsDirectory, `${hostThreadId}.json`);
22129
+ return path7.join(this.#backupsDirectory, `${hostThreadId}.json`);
21779
22130
  }
21780
22131
  #requireInitialized() {
21781
22132
  if (!this.#initialized) {
@@ -21795,7 +22146,7 @@ var TITLE_MAX_LENGTH = 150;
21795
22146
  var DESCRIPTION_MAX_LENGTH = 500;
21796
22147
  var SERVER_NAME_MAX_LENGTH = 80;
21797
22148
  var ELLIPSIS = "…";
21798
- function isRecord2(value2) {
22149
+ function isRecord3(value2) {
21799
22150
  return typeof value2 === "object" && value2 !== null && !Array.isArray(value2);
21800
22151
  }
21801
22152
  function boundedText(value2, field, maxLength) {
@@ -21849,7 +22200,7 @@ function responseError(message) {
21849
22200
  function responsePersist(value2) {
21850
22201
  if (value2 === void 0 || value2 === null)
21851
22202
  return null;
21852
- if (!isRecord2(value2) || Object.keys(value2).length !== 1 || value2.persist !== "session" && value2.persist !== "always") {
22203
+ if (!isRecord3(value2) || Object.keys(value2).length !== 1 || value2.persist !== "session" && value2.persist !== "always") {
21853
22204
  throw responseError("contains malformed persist metadata");
21854
22205
  }
21855
22206
  return value2.persist;
@@ -21895,7 +22246,7 @@ function projectCodexApprovalRequest(input) {
21895
22246
  },
21896
22247
  denyResponse,
21897
22248
  parseResponse(result) {
21898
- if (!isRecord2(result) || typeof result.action !== "string") {
22249
+ if (!isRecord3(result) || typeof result.action !== "string") {
21899
22250
  throw responseError("missing action");
21900
22251
  }
21901
22252
  if (Object.keys(result).some((key) => key !== "action" && key !== "content" && key !== "_meta")) {
@@ -21903,7 +22254,7 @@ function projectCodexApprovalRequest(input) {
21903
22254
  }
21904
22255
  const selectedPersist = responsePersist(result._meta);
21905
22256
  if (result.action === "accept") {
21906
- if ("content" in result && (!isRecord2(result.content) || Object.keys(result.content).length !== 0)) {
22257
+ if ("content" in result && (!isRecord3(result.content) || Object.keys(result.content).length !== 0)) {
21907
22258
  throw responseError("contains non-empty accepted content");
21908
22259
  }
21909
22260
  if (selectedPersist === "session") {
@@ -21963,7 +22314,7 @@ function projectApprovalChoices(input) {
21963
22314
  },
21964
22315
  denyResponse,
21965
22316
  parseResponse(result) {
21966
- if (!isRecord2(result) || typeof result.action !== "string")
22317
+ if (!isRecord3(result) || typeof result.action !== "string")
21967
22318
  throw responseError("missing action");
21968
22319
  if (Object.keys(result).some((key) => !["action", "content", "_meta"].includes(key))) {
21969
22320
  throw responseError("contains unreviewed fields");
@@ -21978,7 +22329,7 @@ function projectApprovalChoices(input) {
21978
22329
  return denyResponse;
21979
22330
  }
21980
22331
  const content = result.content;
21981
- if (result.action !== "accept" || !isRecord2(content) || Object.keys(content).length !== 1 || !interaction.actions.some(({ id: id2 }) => id2 === content.actionId)) {
22332
+ if (result.action !== "accept" || !isRecord3(content) || Object.keys(content).length !== 1 || !interaction.actions.some(({ id: id2 }) => id2 === content.actionId)) {
21982
22333
  throw responseError("contains an undeclared approval choice");
21983
22334
  }
21984
22335
  return { type: "approval", actionId: content.actionId };
@@ -21987,7 +22338,7 @@ function projectApprovalChoices(input) {
21987
22338
  }
21988
22339
 
21989
22340
  // packages/protocol-core/dist/codex-question.js
21990
- function isRecord3(value2) {
22341
+ function isRecord4(value2) {
21991
22342
  return typeof value2 === "object" && value2 !== null && !Array.isArray(value2);
21992
22343
  }
21993
22344
  function responseError2(message) {
@@ -22056,7 +22407,7 @@ function projectCodexQuestionRequest(input) {
22056
22407
  }
22057
22408
  },
22058
22409
  parseResponse(result) {
22059
- if (!isRecord3(result) || !isRecord3(result.answers)) {
22410
+ if (!isRecord4(result) || !isRecord4(result.answers)) {
22060
22411
  throw responseError2("missing answers object");
22061
22412
  }
22062
22413
  const rawAnswers = result.answers;
@@ -22069,7 +22420,7 @@ function projectCodexQuestionRequest(input) {
22069
22420
  const question = interaction.questions.find(({ id: id2 }) => id2 === questionId);
22070
22421
  if (!question)
22071
22422
  throw responseError2("contains an unknown Question ID");
22072
- if (!isRecord3(answerValue) || !Array.isArray(answerValue.answers)) {
22423
+ if (!isRecord4(answerValue) || !Array.isArray(answerValue.answers)) {
22073
22424
  throw responseError2("answer entry has no answers array");
22074
22425
  }
22075
22426
  const values = answerValue.answers;
@@ -22151,7 +22502,7 @@ function projectCodexThreadUsage(input) {
22151
22502
  }
22152
22503
 
22153
22504
  // packages/protocol-core/dist/codex-native-usage.js
22154
- function isRecord4(value2) {
22505
+ function isRecord5(value2) {
22155
22506
  return typeof value2 === "object" && value2 !== null && !Array.isArray(value2);
22156
22507
  }
22157
22508
  function nonNegativeSafeInteger(value2) {
@@ -22181,20 +22532,20 @@ function addBreakdown(target, source) {
22181
22532
  }
22182
22533
  }
22183
22534
  function observeCodexTokenUsage(value2) {
22184
- if (!isRecord4(value2) || value2.method !== "thread/tokenUsage/updated")
22535
+ if (!isRecord5(value2) || value2.method !== "thread/tokenUsage/updated")
22185
22536
  return null;
22186
22537
  const params = value2.params;
22187
- if (!isRecord4(params))
22538
+ if (!isRecord5(params))
22188
22539
  return null;
22189
22540
  const threadId2 = hostThreadIdSchema.safeParse(params.threadId);
22190
22541
  const turnId = hostTurnIdSchema.safeParse(params.turnId);
22191
22542
  if (!threadId2.success || !turnId.success)
22192
22543
  return null;
22193
22544
  const tokenUsage = params.tokenUsage;
22194
- if (!isRecord4(tokenUsage))
22545
+ if (!isRecord5(tokenUsage))
22195
22546
  return null;
22196
- const total = isRecord4(tokenUsage.total) ? tokenUsage.total : void 0;
22197
- const last = isRecord4(tokenUsage.last) ? tokenUsage.last : void 0;
22547
+ const total = isRecord5(tokenUsage.total) ? tokenUsage.total : void 0;
22548
+ const last = isRecord5(tokenUsage.last) ? tokenUsage.last : void 0;
22198
22549
  const usage = {};
22199
22550
  addBreakdown(usage, total);
22200
22551
  const contextUsedTokens = nonNegativeSafeInteger(last?.totalTokens);
@@ -22219,7 +22570,7 @@ function observeCodexTokenUsage(value2) {
22219
22570
  }
22220
22571
  }
22221
22572
  function parseRateLimitWindow(value2) {
22222
- if (!isRecord4(value2))
22573
+ if (!isRecord5(value2))
22223
22574
  return null;
22224
22575
  const usedPercent = finitePercent(value2.usedPercent);
22225
22576
  const windowDurationMins = nonNegativeSafeInteger(value2.windowDurationMins);
@@ -22230,7 +22581,7 @@ function parseRateLimitWindow(value2) {
22230
22581
  return { usedPercent, windowDurationMins, ...resetsAt !== void 0 ? { resetsAt } : {} };
22231
22582
  }
22232
22583
  function parseRateLimitCandidate(value2, options2 = {}) {
22233
- if (!isRecord4(value2))
22584
+ if (!isRecord5(value2))
22234
22585
  return null;
22235
22586
  if (options2.genericOnly && value2.limitId !== void 0 && value2.limitId !== null && value2.limitId !== "codex") {
22236
22587
  return null;
@@ -22240,16 +22591,16 @@ function parseRateLimitCandidate(value2, options2 = {}) {
22240
22591
  return primary || secondary ? { primary, secondary } : null;
22241
22592
  }
22242
22593
  function rateLimitCandidates(value2) {
22243
- if (!isRecord4(value2))
22594
+ if (!isRecord5(value2))
22244
22595
  return [];
22245
- const result = isRecord4(value2.result) ? value2.result : value2;
22246
- if (!isRecord4(result))
22596
+ const result = isRecord5(value2.result) ? value2.result : value2;
22597
+ if (!isRecord5(result))
22247
22598
  return [];
22248
22599
  const candidates = [];
22249
22600
  const base = parseRateLimitCandidate(result.rateLimits, { genericOnly: true });
22250
22601
  if (base)
22251
22602
  candidates.push(base);
22252
- const notificationParams = isRecord4(value2.params) ? value2.params : void 0;
22603
+ const notificationParams = isRecord5(value2.params) ? value2.params : void 0;
22253
22604
  const notificationSnapshot = parseRateLimitCandidate(notificationParams?.rateLimits, {
22254
22605
  genericOnly: true
22255
22606
  });
@@ -22293,14 +22644,14 @@ function parseAvailableCount(value2) {
22293
22644
  return void 0;
22294
22645
  }
22295
22646
  function rateLimitResetCreditsSummary(value2) {
22296
- if (!isRecord4(value2))
22647
+ if (!isRecord5(value2))
22297
22648
  return null;
22298
- const result = isRecord4(value2.result) ? value2.result : value2;
22299
- const fromResult = isRecord4(result) && isRecord4(result.rateLimitResetCredits) ? result.rateLimitResetCredits : null;
22649
+ const result = isRecord5(value2.result) ? value2.result : value2;
22650
+ const fromResult = isRecord5(result) && isRecord5(result.rateLimitResetCredits) ? result.rateLimitResetCredits : null;
22300
22651
  if (fromResult)
22301
22652
  return fromResult;
22302
- const params = isRecord4(value2.params) ? value2.params : void 0;
22303
- return isRecord4(params?.rateLimitResetCredits) ? params.rateLimitResetCredits : null;
22653
+ const params = isRecord5(value2.params) ? value2.params : void 0;
22654
+ return isRecord5(params?.rateLimitResetCredits) ? params.rateLimitResetCredits : null;
22304
22655
  }
22305
22656
  function observeCodexRateLimitResetCredits(value2) {
22306
22657
  const summary = rateLimitResetCreditsSummary(value2);
@@ -22312,7 +22663,7 @@ function observeCodexRateLimitResetCredits(value2) {
22312
22663
  const expiresAtUnix = [];
22313
22664
  if (Array.isArray(summary.credits)) {
22314
22665
  for (const credit of summary.credits) {
22315
- if (!isRecord4(credit))
22666
+ if (!isRecord5(credit))
22316
22667
  continue;
22317
22668
  if (credit.status !== void 0 && credit.status !== "available")
22318
22669
  continue;
@@ -22463,16 +22814,16 @@ var Diff = class {
22463
22814
  }
22464
22815
  }
22465
22816
  }
22466
- addToPath(path27, added, removed, oldPosInc, options2) {
22467
- const last = path27.lastComponent;
22817
+ addToPath(path29, added, removed, oldPosInc, options2) {
22818
+ const last = path29.lastComponent;
22468
22819
  if (last && !options2.oneChangePerToken && last.added === added && last.removed === removed) {
22469
22820
  return {
22470
- oldPos: path27.oldPos + oldPosInc,
22821
+ oldPos: path29.oldPos + oldPosInc,
22471
22822
  lastComponent: { count: last.count + 1, added, removed, previousComponent: last.previousComponent }
22472
22823
  };
22473
22824
  } else {
22474
22825
  return {
22475
- oldPos: path27.oldPos + oldPosInc,
22826
+ oldPos: path29.oldPos + oldPosInc,
22476
22827
  lastComponent: { count: 1, added, removed, previousComponent: last }
22477
22828
  };
22478
22829
  }
@@ -22900,11 +23251,14 @@ function splitLines(text) {
22900
23251
  return result;
22901
23252
  }
22902
23253
 
23254
+ // packages/protocol-core/dist/codex-ui-projector.js
23255
+ import path9 from "node:path";
23256
+
22903
23257
  // packages/protocol-core/dist/file-change-summary.js
22904
- import path7 from "node:path";
23258
+ import path8 from "node:path";
22905
23259
  function filePathKey(file2, cwd) {
22906
23260
  const windows = /^[a-z]:[/\\]/i.test(cwd) || /^[a-z]:[/\\]/i.test(file2);
22907
- const paths = windows ? path7.win32 : path7.posix;
23261
+ const paths = windows ? path8.win32 : path8.posix;
22908
23262
  const resolved = paths.resolve(cwd, file2).replaceAll("\\", "/");
22909
23263
  return windows ? resolved.toLowerCase() : resolved;
22910
23264
  }
@@ -23055,11 +23409,11 @@ function itemStatus(outcome) {
23055
23409
  return "inProgress";
23056
23410
  return outcome.status === "succeeded" ? "completed" : "failed";
23057
23411
  }
23058
- function isRecord5(value2) {
23412
+ function isRecord6(value2) {
23059
23413
  return typeof value2 === "object" && value2 !== null && !Array.isArray(value2);
23060
23414
  }
23061
23415
  function nestedString(value2, keys, preserveText = false) {
23062
- if (!isRecord5(value2))
23416
+ if (!isRecord6(value2))
23063
23417
  return void 0;
23064
23418
  for (const key of keys) {
23065
23419
  const field = value2[key];
@@ -23073,6 +23427,14 @@ function nestedString(value2, keys, preserveText = false) {
23073
23427
  }
23074
23428
  return void 0;
23075
23429
  }
23430
+ function toolWorkingDirectory(args, defaultCwd) {
23431
+ const workdir = nestedString(args, ["workdir"]);
23432
+ if (workdir === void 0)
23433
+ return defaultCwd;
23434
+ const windows = /^(?:[a-z]:[/\\]|\\\\)/iu;
23435
+ const paths = windows.test(defaultCwd) || windows.test(workdir) ? path9.win32 : path9.posix;
23436
+ return paths.resolve(defaultCwd, workdir);
23437
+ }
23076
23438
  function toolOutputText(item) {
23077
23439
  if (!item.output)
23078
23440
  return null;
@@ -23082,7 +23444,7 @@ function toolOutputText(item) {
23082
23444
  function toolCommandLine(toolName, args) {
23083
23445
  const lower = toolName.toLowerCase().replaceAll(/[_-]/g, "");
23084
23446
  const command = nestedString(args, ["command", "cmd", "script", "commandLine", "command_line"]);
23085
- if (command && ["bash", "exec", "terminal", "run", "shell", "powershell", "command"].includes(lower)) {
23447
+ if (command && ["bash", "exec", "terminal", "run", "shell", "powershell", "pwsh", "command"].includes(lower)) {
23086
23448
  return command;
23087
23449
  }
23088
23450
  const filePath = nestedString(args, [
@@ -23173,8 +23535,8 @@ function projectFileChangeKind(kind) {
23173
23535
  return { type: kind };
23174
23536
  }
23175
23537
  function projectFileChanges(changes) {
23176
- return changes.map(({ path: path27, kind, unifiedDiff }) => ({
23177
- path: path27,
23538
+ return changes.map(({ path: path29, kind, unifiedDiff }) => ({
23539
+ path: path29,
23178
23540
  kind: projectFileChangeKind(kind),
23179
23541
  diff: unifiedDiff
23180
23542
  }));
@@ -23214,7 +23576,7 @@ function planFromTodoValue(value2) {
23214
23576
  const record3 = unwrapToolRecord(value2);
23215
23577
  if (!record3)
23216
23578
  return planFromChecklistText(typeof value2 === "string" ? value2 : null);
23217
- if (isRecord5(record3.TodosUpdated)) {
23579
+ if (isRecord6(record3.TodosUpdated)) {
23218
23580
  const nested = planFromTodoValue(record3.TodosUpdated);
23219
23581
  if (nested)
23220
23582
  return nested;
@@ -23229,7 +23591,7 @@ function planFromTodoValue(value2) {
23229
23591
  plan.push({ step: entry.trim(), status: "pending" });
23230
23592
  continue;
23231
23593
  }
23232
- if (!isRecord5(entry))
23594
+ if (!isRecord6(entry))
23233
23595
  continue;
23234
23596
  const step = nestedString(entry, ["content", "step", "text", "title", "description", "task"]);
23235
23597
  if (!step)
@@ -23284,7 +23646,7 @@ function unwrapToolRecord(value2) {
23284
23646
  }
23285
23647
  if (Array.isArray(value2))
23286
23648
  return { todos: value2 };
23287
- if (!isRecord5(value2))
23649
+ if (!isRecord6(value2))
23288
23650
  return null;
23289
23651
  for (const wrapper of ["input", "arguments", "params"]) {
23290
23652
  if (value2[wrapper] === void 0)
@@ -23339,13 +23701,15 @@ function projectItem(item, outcome, defaultCwd, includeCommandOutput = true, sen
23339
23701
  phase: item.phase ?? null,
23340
23702
  memoryCitation: null
23341
23703
  };
23342
- case "reasoning":
23704
+ case "reasoning": {
23705
+ const text = reasoningDisplayText(item.text);
23343
23706
  return {
23344
23707
  id: reasoningPreviewItemId(item.itemId),
23345
23708
  type: "reasoning",
23346
- summary: item.text.length > 0 ? [item.text] : [],
23709
+ summary: text ? [text] : [],
23347
23710
  content: []
23348
23711
  };
23712
+ }
23349
23713
  case "contextCompaction":
23350
23714
  return { id: item.itemId, type: "contextCompaction" };
23351
23715
  case "commandExecution":
@@ -23369,13 +23733,13 @@ function projectItem(item, outcome, defaultCwd, includeCommandOutput = true, sen
23369
23733
  id: item.itemId,
23370
23734
  type: "commandExecution",
23371
23735
  command,
23372
- cwd: defaultCwd,
23736
+ cwd: toolWorkingDirectory(item.arguments, defaultCwd),
23373
23737
  processId: null,
23374
23738
  source: "agent",
23375
23739
  status: itemStatus(outcome),
23376
23740
  commandActions: [],
23377
23741
  aggregatedOutput: includeCommandOutput ? toolOutputText(item) : null,
23378
- exitCode: outcome ? outcome.status === "succeeded" ? 0 : 1 : null,
23742
+ exitCode: null,
23379
23743
  durationMs: item.durationMs ?? null
23380
23744
  };
23381
23745
  }
@@ -23423,6 +23787,9 @@ function projectItem(item, outcome, defaultCwd, includeCommandOutput = true, sen
23423
23787
  function reasoningPreviewItemId(itemId) {
23424
23788
  return `${itemId}-summary`;
23425
23789
  }
23790
+ function reasoningDisplayText(text) {
23791
+ return text.replace(/[\r\n]+$/u, "");
23792
+ }
23426
23793
  function projectReasoningTranscriptItem(item, outcome, defaultCwd, durationMs = null) {
23427
23794
  return {
23428
23795
  id: item.itemId,
@@ -23433,7 +23800,7 @@ function projectReasoningTranscriptItem(item, outcome, defaultCwd, durationMs =
23433
23800
  source: "agent",
23434
23801
  status: itemStatus(outcome),
23435
23802
  commandActions: [],
23436
- aggregatedOutput: item.text.length > 0 ? item.text : null,
23803
+ aggregatedOutput: reasoningDisplayText(item.text) || null,
23437
23804
  exitCode: outcome ? 0 : null,
23438
23805
  durationMs
23439
23806
  };
@@ -23490,6 +23857,8 @@ function projectHistoricalTurn(input) {
23490
23857
  if (isFileMutatingTool(item.toolName))
23491
23858
  return [];
23492
23859
  }
23860
+ if (item.type === "reasoning" && !reasoningDisplayText(item.text))
23861
+ return [];
23493
23862
  return item.type === "reasoning" ? [
23494
23863
  projectItem(item, outcome, cwd, true, input.threadId ?? ""),
23495
23864
  projectReasoningTranscriptItem(item, outcome, cwd)
@@ -23679,7 +24048,7 @@ var CodexTurnProjector = class {
23679
24048
  startedAtMs
23680
24049
  };
23681
24050
  this.#items.set(event.item.itemId, projected);
23682
- if ((event.item.type === "agentMessage" || event.item.type === "reasoning") && event.item.text.length === 0) {
24051
+ if ((event.item.type === "agentMessage" || event.item.type === "reasoning") && (event.item.type === "reasoning" ? reasoningDisplayText(event.item.text).length === 0 : event.item.text.length === 0)) {
23683
24052
  return { messages: [] };
23684
24053
  }
23685
24054
  if (event.item.type === "toolExecution") {
@@ -23699,7 +24068,8 @@ var CodexTurnProjector = class {
23699
24068
  const startedItem = event.item.type === "reasoning" ? { ...event.item, text: "" } : event.item;
23700
24069
  const messages = [this.#startWireItem(projected, startedItem, startedAtMs)];
23701
24070
  if (event.item.type === "reasoning") {
23702
- messages.push(this.#startReasoningTranscript(event.item, startedAtMs), this.#reasoningOutputDelta(event.item.itemId, event.item.text, startedAtMs), ...this.#reasoningDelta(projected, event.item.text, startedAtMs));
24071
+ const text = reasoningDisplayText(event.item.text);
24072
+ messages.push(this.#startReasoningTranscript(event.item, startedAtMs), this.#reasoningOutputDelta(event.item.itemId, text, startedAtMs), ...this.#reasoningDelta(projected, text, startedAtMs));
23703
24073
  }
23704
24074
  return { messages };
23705
24075
  }
@@ -23727,10 +24097,14 @@ var CodexTurnProjector = class {
23727
24097
  }
23728
24098
  });
23729
24099
  } else if (next.type === "reasoning") {
24100
+ const previousText = previous.type === "reasoning" ? reasoningDisplayText(previous.text) : "";
24101
+ const delta = reasoningDisplayText(next.text).slice(previousText.length);
24102
+ if (!delta)
24103
+ return { messages };
23730
24104
  if (!projected.wireStarted) {
23731
24105
  messages.push(this.#startWireItem(projected, { ...next, text: "" }, emittedAtMs), this.#startReasoningTranscript({ ...next, text: "" }, emittedAtMs));
23732
24106
  }
23733
- messages.push(this.#reasoningOutputDelta(event.itemId, event.update.text, emittedAtMs), ...this.#reasoningDelta(projected, event.update.text, emittedAtMs));
24107
+ messages.push(this.#reasoningOutputDelta(event.itemId, delta, emittedAtMs), ...this.#reasoningDelta(projected, delta, emittedAtMs));
23734
24108
  }
23735
24109
  } else if (event.update.type === "output.append") {
23736
24110
  projected.streamedCommandOutput = true;
@@ -24074,7 +24448,7 @@ var CodexTurnProjector = class {
24074
24448
  };
24075
24449
 
24076
24450
  // packages/protocol-core/dist/thread-fork.js
24077
- function isRecord6(value2) {
24451
+ function isRecord7(value2) {
24078
24452
  return typeof value2 === "object" && value2 !== null && !Array.isArray(value2);
24079
24453
  }
24080
24454
  function optionalText(params, name, options2 = {}) {
@@ -24097,7 +24471,7 @@ function optionalBoolean(params, name) {
24097
24471
  function decodeThreadForkRequest(request) {
24098
24472
  if (request.method !== "thread/fork")
24099
24473
  return null;
24100
- if (!isRecord6(request.params))
24474
+ if (!isRecord7(request.params))
24101
24475
  throw new Error("thread/fork params must be an object");
24102
24476
  const params = request.params;
24103
24477
  const threadId2 = optionalText(params, "threadId");
@@ -24112,13 +24486,13 @@ function decodeThreadForkRequest(request) {
24112
24486
  if (runtimeWorkspaceRoots !== void 0 && runtimeWorkspaceRoots !== null && (!Array.isArray(runtimeWorkspaceRoots) || runtimeWorkspaceRoots.some((root) => typeof root !== "string" || root.length === 0))) {
24113
24487
  throw new Error("thread/fork params.runtimeWorkspaceRoots must be text paths or null");
24114
24488
  }
24115
- const path27 = optionalText(params, "path", { allowEmpty: true });
24489
+ const path29 = optionalText(params, "path", { allowEmpty: true });
24116
24490
  const ephemeral = optionalBoolean(params, "ephemeral");
24117
24491
  return {
24118
24492
  threadId: threadId2,
24119
24493
  ...lastTurnText ? { lastTurnId: hostTurnIdSchema.parse(lastTurnText) } : {},
24120
24494
  ...beforeTurnText ? { beforeTurnId: hostTurnIdSchema.parse(beforeTurnText) } : {},
24121
- ...path27 ? { path: path27 } : {},
24495
+ ...path29 ? { path: path29 } : {},
24122
24496
  ...optionalField(params, "model"),
24123
24497
  ...optionalField(params, "modelProvider"),
24124
24498
  ...optionalField(params, "cwd"),
@@ -24133,7 +24507,7 @@ function decodeThreadForkRequest(request) {
24133
24507
  function decodeThreadRevertRequest(request) {
24134
24508
  if (request.method !== "thread/revert")
24135
24509
  return null;
24136
- if (!isRecord6(request.params))
24510
+ if (!isRecord7(request.params))
24137
24511
  throw new Error("thread/revert params must be an object");
24138
24512
  const { threadId: threadId2, beforeTurnId } = request.params;
24139
24513
  if (typeof threadId2 !== "string" || threadId2.length === 0) {
@@ -24147,7 +24521,7 @@ function decodeThreadRevertRequest(request) {
24147
24521
  function decodeThreadRollbackRequest(request) {
24148
24522
  if (request.method !== "thread/rollback")
24149
24523
  return null;
24150
- if (!isRecord6(request.params))
24524
+ if (!isRecord7(request.params))
24151
24525
  throw new Error("thread/rollback params must be an object");
24152
24526
  const { threadId: threadId2, numTurns } = request.params;
24153
24527
  if (typeof threadId2 !== "string" || threadId2.length === 0) {
@@ -24211,7 +24585,7 @@ function threadForkResult(thread, input) {
24211
24585
  }
24212
24586
 
24213
24587
  // packages/protocol-core/dist/thread-management.js
24214
- import { createHash as createHash3 } from "node:crypto";
24588
+ import { createHash as createHash4 } from "node:crypto";
24215
24589
  var HOST_CURSOR_PREFIX = "codexhost:thread-list:v1:";
24216
24590
  var MAX_CURSOR_LENGTH = 65536;
24217
24591
  var DEFAULT_PAGE_SIZE = 25;
@@ -24244,13 +24618,13 @@ var THREAD_SOURCE_KINDS = /* @__PURE__ */ new Set([
24244
24618
  "subAgentOther",
24245
24619
  "unknown"
24246
24620
  ]);
24247
- function isRecord7(value2) {
24621
+ function isRecord8(value2) {
24248
24622
  return typeof value2 === "object" && value2 !== null && !Array.isArray(value2);
24249
24623
  }
24250
24624
  function paramsObject(request, method) {
24251
24625
  if (request.params === void 0 && method === "thread/list")
24252
24626
  return {};
24253
- if (!isRecord7(request.params))
24627
+ if (!isRecord8(request.params))
24254
24628
  throw new Error(`${method} params must be an object`);
24255
24629
  return request.params;
24256
24630
  }
@@ -24308,7 +24682,7 @@ function decodeSortKey(value2) {
24308
24682
  return value2;
24309
24683
  }
24310
24684
  function queryFingerprint(value2) {
24311
- return createHash3("sha256").update(JSON.stringify(value2)).digest("hex");
24685
+ return createHash4("sha256").update(JSON.stringify(value2)).digest("hex");
24312
24686
  }
24313
24687
  function cursorPayload(value2) {
24314
24688
  return {
@@ -24322,7 +24696,7 @@ function cursorPayload(value2) {
24322
24696
  };
24323
24697
  }
24324
24698
  function parseCursorPayload(value2) {
24325
- if (!isRecord7(value2) || value2.formatVersion !== 1)
24699
+ if (!isRecord8(value2) || value2.formatVersion !== 1)
24326
24700
  throw new Error("Host cursor is invalid");
24327
24701
  const { queryFingerprint: fingerprint, sortDirection: sortDirection2, officialCursor, officialDone } = value2;
24328
24702
  const { externalAnchor: externalAnchor2, externalDone } = value2;
@@ -24331,7 +24705,7 @@ function parseCursorPayload(value2) {
24331
24705
  }
24332
24706
  let anchor = null;
24333
24707
  if (externalAnchor2 !== null) {
24334
- if (!isRecord7(externalAnchor2) || !Number.isSafeInteger(externalAnchor2.timestamp) || typeof externalAnchor2.threadId !== "string" || externalAnchor2.threadId.length === 0) {
24708
+ if (!isRecord8(externalAnchor2) || !Number.isSafeInteger(externalAnchor2.timestamp) || typeof externalAnchor2.threadId !== "string" || externalAnchor2.threadId.length === 0) {
24335
24709
  throw new Error("Host cursor is invalid");
24336
24710
  }
24337
24711
  anchor = {
@@ -24454,7 +24828,7 @@ function decodeThreadMetadataUpdateRequest(request) {
24454
24828
  if (params.gitInfo === null) {
24455
24829
  gitInfo = null;
24456
24830
  } else if (params.gitInfo !== void 0) {
24457
- if (!isRecord7(params.gitInfo)) {
24831
+ if (!isRecord8(params.gitInfo)) {
24458
24832
  throw new Error("thread/metadata/update params.gitInfo must be an object or null");
24459
24833
  }
24460
24834
  gitInfo = {};
@@ -24482,7 +24856,7 @@ function optionalCursor(value2, name) {
24482
24856
  return value2;
24483
24857
  }
24484
24858
  function decodeOfficialThreadListPage(value2) {
24485
- if (!isRecord7(value2) || !Array.isArray(value2.data) || value2.data.some((row) => !isRecord7(row))) {
24859
+ if (!isRecord8(value2) || !Array.isArray(value2.data) || value2.data.some((row) => !isRecord8(row))) {
24486
24860
  throw new Error("Official thread/list response is invalid");
24487
24861
  }
24488
24862
  return {
@@ -25294,22 +25668,22 @@ var HarnessAccountInspectionCache = class {
25294
25668
  };
25295
25669
 
25296
25670
  // packages/host-runtime/src/app-server-host.ts
25297
- import { createHash as createHash7, randomUUID as randomUUID9 } from "node:crypto";
25298
- import os4 from "node:os";
25299
- import path13 from "node:path";
25671
+ import { createHash as createHash8, randomUUID as randomUUID10 } from "node:crypto";
25672
+ import os5 from "node:os";
25673
+ import path16 from "node:path";
25300
25674
 
25301
25675
  // packages/host-runtime/src/external-thread-fork.ts
25302
25676
  import nodePath from "node:path";
25303
25677
 
25304
25678
  // packages/host-runtime/src/external-thread-repository.ts
25305
- import { randomUUID as randomUUID4 } from "node:crypto";
25306
- import os2 from "node:os";
25307
- import path8 from "node:path";
25679
+ import { randomUUID as randomUUID5 } from "node:crypto";
25680
+ import os3 from "node:os";
25681
+ import path10 from "node:path";
25308
25682
 
25309
25683
  // packages/host-runtime/src/external-subagent-threads.ts
25310
- import { createHash as createHash4, randomUUID as randomUUID3 } from "node:crypto";
25684
+ import { createHash as createHash5, randomUUID as randomUUID4 } from "node:crypto";
25311
25685
  function childCreateRequest(parent, nativeRef, id2) {
25312
- const key = createHash4("sha256").update(JSON.stringify([parent.hostThreadId, parent.harnessId, nativeRef.nativeSessionId, id2])).digest("hex");
25686
+ const key = createHash5("sha256").update(JSON.stringify([parent.hostThreadId, parent.harnessId, nativeRef.nativeSessionId, id2])).digest("hex");
25313
25687
  return `subagent:${key}`;
25314
25688
  }
25315
25689
  function subagentMaterializer(store, parent, previousParent) {
@@ -25382,7 +25756,7 @@ function subagentMaterializer(store, parent, previousParent) {
25382
25756
  return rebind(existing, parent);
25383
25757
  }
25384
25758
  const provisional = existing ?? await store.createProvisional({
25385
- hostThreadId: hostThreadIdSchema.parse(randomUUID3()),
25759
+ hostThreadId: hostThreadIdSchema.parse(randomUUID4()),
25386
25760
  createRequestId,
25387
25761
  harnessId: parent.harnessId,
25388
25762
  cwd: parent.cwd,
@@ -25444,8 +25818,8 @@ function sameMapping(left, right) {
25444
25818
  }
25445
25819
  function defaultMappingStoreDirectory(environment) {
25446
25820
  const dataDirectory = environment.CODEXHOST_DATA_DIR;
25447
- return path8.join(
25448
- dataDirectory ? path8.resolve(dataDirectory) : path8.join(os2.homedir(), ".codexhost"),
25821
+ return path10.join(
25822
+ dataDirectory ? path10.resolve(dataDirectory) : path10.join(os3.homedir(), ".codexhost"),
25449
25823
  "mapping-store"
25450
25824
  );
25451
25825
  }
@@ -25542,7 +25916,7 @@ var ExternalThreadRepository = class {
25542
25916
  throw new Error("Derived Snapshot identity does not belong to its Native Session");
25543
25917
  }
25544
25918
  return {
25545
- hostTurnId: hostTurnIdSchema.parse(randomUUID4()),
25919
+ hostTurnId: hostTurnIdSchema.parse(randomUUID5()),
25546
25920
  nativeTurnRef: turn.nativeTurnRef,
25547
25921
  ...turn.checkpoint ? { nativeCheckpointRef: turn.checkpoint } : {}
25548
25922
  };
@@ -25662,7 +26036,7 @@ var ExternalThreadRepository = class {
25662
26036
  const aligned = snapshot.turns.map((turn) => {
25663
26037
  const existing = mappingsByNative.get(nativeTurnKey2(turn.nativeTurnRef));
25664
26038
  const mapping = existing ?? {
25665
- hostTurnId: hostTurnIdSchema.parse(randomUUID4()),
26039
+ hostTurnId: hostTurnIdSchema.parse(randomUUID5()),
25666
26040
  nativeTurnRef: turn.nativeTurnRef,
25667
26041
  ...turn.checkpoint ? { nativeCheckpointRef: turn.checkpoint } : {}
25668
26042
  };
@@ -25689,8 +26063,8 @@ var ExternalThreadRepository = class {
25689
26063
  };
25690
26064
  function createExternalThreadRecordInput(input) {
25691
26065
  return {
25692
- hostThreadId: input.hostThreadId ?? hostThreadIdSchema.parse(randomUUID4()),
25693
- createRequestId: input.createRequestId ?? randomUUID4(),
26066
+ hostThreadId: input.hostThreadId ?? hostThreadIdSchema.parse(randomUUID5()),
26067
+ createRequestId: input.createRequestId ?? randomUUID5(),
25694
26068
  harnessId: input.harnessId,
25695
26069
  cwd: input.cwd,
25696
26070
  ...input.title ? { title: input.title } : {},
@@ -25851,6 +26225,7 @@ async function executeExternalThreadFork(input) {
25851
26225
  return { ok: false, error: mapExternalThreadHarnessError(opened.error, "fork") };
25852
26226
  }
25853
26227
  const session = opened.value;
26228
+ const inheritedPermissionModeId = await inheritSourcePermissionMode(source, session);
25854
26229
  try {
25855
26230
  const derivedNativeRef = session.initialState.nativeRef;
25856
26231
  if (!derivedNativeRef || derivedNativeRef.nativeSessionId === nativeSessionRef.nativeSessionId) {
@@ -25878,7 +26253,8 @@ async function executeExternalThreadFork(input) {
25878
26253
  sessionId: source.sessionId,
25879
26254
  thread,
25880
26255
  turns: aligned.turns,
25881
- ...snapshot.value.state ? { restoredState: snapshot.value.state } : {}
26256
+ ...snapshot.value.state ? { restoredState: snapshot.value.state } : {},
26257
+ ...inheritedPermissionModeId ? { requestedPermissionModeId: inheritedPermissionModeId } : {}
25882
26258
  });
25883
26259
  return {
25884
26260
  ok: true,
@@ -25896,6 +26272,23 @@ async function executeExternalThreadFork(input) {
25896
26272
  };
25897
26273
  }
25898
26274
  }
26275
+ async function inheritSourcePermissionMode(source, session) {
26276
+ const sourceModeId = source.stateObserver.state.effectivePermissionModeId ?? source.requestedPermissionModeId;
26277
+ if (!sourceModeId) return void 0;
26278
+ const configuration = session.capabilities.configuration;
26279
+ if (!configuration.selectPermissionMode || permissionModeFixedAtCreate(configuration)) {
26280
+ return void 0;
26281
+ }
26282
+ try {
26283
+ const selected = await session.execute({
26284
+ type: "permissionMode.select",
26285
+ permissionModeId: sourceModeId
26286
+ });
26287
+ return selected.ok ? sourceModeId : void 0;
26288
+ } catch {
26289
+ return void 0;
26290
+ }
26291
+ }
25899
26292
 
25900
26293
  // packages/host-runtime/src/harness-session-import.ts
25901
26294
  function fixedError(code, message) {
@@ -27460,9 +27853,12 @@ var ExternalTurnSteering = class {
27460
27853
  if (!cancelled.ok) throw new ExternalSteerError(-32074, cancelled.error.message);
27461
27854
  const outcome = await Promise.race([terminal2.promise, failure.promise]);
27462
27855
  clearTimeout(timeout);
27463
- if (failureReason) throw failureReason;
27464
- if (this.#closed)
27465
- throw new ExternalSteerError(-32074, "External steering connection is closed");
27856
+ const assertActive = () => {
27857
+ if (failureReason) throw failureReason;
27858
+ if (this.#closed)
27859
+ throw new ExternalSteerError(-32074, "External steering connection is closed");
27860
+ };
27861
+ assertActive();
27466
27862
  if (outcome.status === "failed") throw new ExternalSteerError(-32074, outcome.error.message);
27467
27863
  if (thread.persistenceError)
27468
27864
  throw new ExternalSteerError(
@@ -27472,7 +27868,7 @@ var ExternalTurnSteering = class {
27472
27868
  if (thread.running || thread.activeTurnId) {
27473
27869
  throw new ExternalSteerError(-32072, "Another External Turn started before replacement");
27474
27870
  }
27475
- return await start(input.text);
27871
+ return await start(input.text, assertActive);
27476
27872
  } finally {
27477
27873
  clearTimeout(timeout);
27478
27874
  if (this.#pending.get(thread.id) === pending) this.#pending.delete(thread.id);
@@ -27480,16 +27876,98 @@ var ExternalTurnSteering = class {
27480
27876
  }
27481
27877
  };
27482
27878
 
27483
- // packages/host-runtime/src/harness-delegation-coordinator.ts
27484
- import { createHash as createHash6, randomUUID as randomUUID5 } from "node:crypto";
27485
- import path9 from "node:path";
27486
-
27487
- // packages/host-runtime/src/delegation-snapshot.ts
27488
- import { createHash as createHash5 } from "node:crypto";
27489
- var CURSOR_PREFIX = "codexhost:thread-messages:v1:";
27490
- var DEFAULT_MESSAGE_LIMIT = 25;
27491
- var MAX_MESSAGE_LIMIT = 100;
27492
- function isRecord8(value2) {
27879
+ // packages/host-runtime/src/external-command-routing.ts
27880
+ var ExternalCommandError = class extends Error {
27881
+ constructor(code, message) {
27882
+ super(message);
27883
+ this.code = code;
27884
+ }
27885
+ code;
27886
+ };
27887
+ function isExternalCommandCandidate(text) {
27888
+ return /^\/[^\s/]+(?:\s|$)/u.test(text.trimStart());
27889
+ }
27890
+ async function inspectLiveCommandCatalog(commands, timeoutMs = 1e3) {
27891
+ let timeout;
27892
+ try {
27893
+ const result = await Promise.race([
27894
+ commands.list(),
27895
+ new Promise((resolve) => {
27896
+ timeout = setTimeout(() => resolve(null), timeoutMs);
27897
+ })
27898
+ ]);
27899
+ return result?.ok ? harnessCommandCatalogSchema.parse(result.value) : null;
27900
+ } catch {
27901
+ return null;
27902
+ } finally {
27903
+ if (timeout !== void 0) clearTimeout(timeout);
27904
+ }
27905
+ }
27906
+ async function resolveExternalCommand(commands, text, options2 = {}) {
27907
+ const catalog = await commands.list();
27908
+ if (!catalog.ok) throw new ExternalCommandError(-32073, catalog.error.message);
27909
+ const commandText = text.trim();
27910
+ const matched = catalog.value.commands.toSorted((left, right) => right.invocation.length - left.invocation.length).find((command) => {
27911
+ if (commandText === command.invocation) return true;
27912
+ return command.argumentMode === "text" && commandText.startsWith(`${command.invocation} `);
27913
+ });
27914
+ if (!matched) {
27915
+ const name = /^\/(\S+)/u.exec(commandText)?.[1] ?? "";
27916
+ if (name && !isExcludedLiveCommand(name, "command") && options2.liveCatalogPending?.(catalog.value)) {
27917
+ return null;
27918
+ }
27919
+ throw new ExternalCommandError(
27920
+ -32078,
27921
+ "External Harness does not expose the requested command"
27922
+ );
27923
+ }
27924
+ const argumentText = commandText.slice(matched.invocation.length).trimStart();
27925
+ return {
27926
+ commandId: matched.id,
27927
+ ...argumentText.length > 0 ? { arguments: { text: argumentText } } : {}
27928
+ };
27929
+ }
27930
+
27931
+ // packages/host-runtime/src/live-command-catalog-cache.ts
27932
+ import path11 from "node:path";
27933
+ var MAX_ENTRIES = 64;
27934
+ function isLiveCommandCatalog(catalog, staticCatalog) {
27935
+ const staticIds = new Set(staticCatalog.commands.map(({ id: id2 }) => id2));
27936
+ return catalog.commands.some(({ id: id2 }) => !staticIds.has(id2));
27937
+ }
27938
+ var LiveCommandCatalogCache = class {
27939
+ #entries = /* @__PURE__ */ new Map();
27940
+ #key(harnessId, cwd) {
27941
+ return `${harnessId}\0${path11.resolve(cwd)}`;
27942
+ }
27943
+ remember(harnessId, cwd, catalog) {
27944
+ const key = this.#key(harnessId, cwd);
27945
+ this.#entries.delete(key);
27946
+ this.#entries.set(key, catalog);
27947
+ while (this.#entries.size > MAX_ENTRIES) {
27948
+ const oldest = this.#entries.keys().next().value;
27949
+ if (oldest === void 0) break;
27950
+ this.#entries.delete(oldest);
27951
+ }
27952
+ }
27953
+ lookup(harnessId, cwd) {
27954
+ return this.#entries.get(this.#key(harnessId, cwd));
27955
+ }
27956
+ };
27957
+ function sameWorkspace(left, right) {
27958
+ return path11.resolve(left) === path11.resolve(right);
27959
+ }
27960
+
27961
+ // packages/host-runtime/src/harness-delegation-coordinator.ts
27962
+ import { createHash as createHash7, randomUUID as randomUUID6 } from "node:crypto";
27963
+ import path12 from "node:path";
27964
+
27965
+ // packages/host-runtime/src/delegation-snapshot.ts
27966
+ import { createHash as createHash6 } from "node:crypto";
27967
+ var CURSOR_PREFIX = "codexhost:thread-messages:v1:";
27968
+ var DEFAULT_MESSAGE_LIMIT = 25;
27969
+ var MAX_MESSAGE_LIMIT = 100;
27970
+ function isRecord9(value2) {
27493
27971
  return typeof value2 === "object" && value2 !== null && !Array.isArray(value2);
27494
27972
  }
27495
27973
  function stringValue(value2) {
@@ -27498,12 +27976,12 @@ function stringValue(value2) {
27498
27976
  function textFromUserItem(item) {
27499
27977
  if (!Array.isArray(item.content)) return "";
27500
27978
  return item.content.flatMap(
27501
- (part) => isRecord8(part) && part.type === "text" && typeof part.text === "string" ? [part.text] : []
27979
+ (part) => isRecord9(part) && part.type === "text" && typeof part.text === "string" ? [part.text] : []
27502
27980
  ).join("\n");
27503
27981
  }
27504
27982
  function threadStatus(value2, running) {
27505
27983
  if (running) return "running";
27506
- if (isRecord8(value2)) {
27984
+ if (isRecord9(value2)) {
27507
27985
  if (value2.type === "active") return "running";
27508
27986
  }
27509
27987
  return "completed";
@@ -27520,10 +27998,10 @@ function allVisibleMessages(turns) {
27520
27998
  const turnId = stringValue(turn.id);
27521
27999
  if (!turnId || !Array.isArray(turn.items)) continue;
27522
28000
  const agentItems = turn.items.filter(
27523
- (item) => isRecord8(item) && item.type === "agentMessage"
28001
+ (item) => isRecord9(item) && item.type === "agentMessage"
27524
28002
  );
27525
28003
  for (const item of turn.items) {
27526
- if (!isRecord8(item)) continue;
28004
+ if (!isRecord9(item)) continue;
27527
28005
  const id2 = stringValue(item.id);
27528
28006
  if (!id2) continue;
27529
28007
  if (item.type === "userMessage") {
@@ -27539,7 +28017,7 @@ function allVisibleMessages(turns) {
27539
28017
  return messages;
27540
28018
  }
27541
28019
  function cursorFingerprint(threadId2) {
27542
- return createHash5("sha256").update(threadId2).digest("hex");
28020
+ return createHash6("sha256").update(threadId2).digest("hex");
27543
28021
  }
27544
28022
  function encodeCursor(threadId2, offset) {
27545
28023
  const payload = JSON.stringify({ version: 1, fingerprint: cursorFingerprint(threadId2), offset });
@@ -27598,7 +28076,7 @@ function projectDelegationThreadSnapshot(input) {
27598
28076
  const progress = latestTurnMessages.filter((message) => message.phase !== "final" && message.text.trim()).map(({ id: id2, turnId, text }) => ({ id: id2, turnId, text }));
27599
28077
  const result = input.running ? { availability: "pending" } : final ? { availability: "available", text: final.text } : {
27600
28078
  availability: "unavailable",
27601
- ...isRecord8(latestTurn?.error) && typeof latestTurn.error.message === "string" ? { message: latestTurn.error.message } : {}
28079
+ ...isRecord9(latestTurn?.error) && typeof latestTurn.error.message === "string" ? { message: latestTurn.error.message } : {}
27602
28080
  };
27603
28081
  const offset = options2.view === "messages" ? decodeCursor(input.threadId, options2.cursor) : visible.length;
27604
28082
  const page = options2.view === "messages" ? [] : void 0;
@@ -27634,10 +28112,10 @@ function terminal(status) {
27634
28112
  return status === "completed" || status === "failed" || status === "interrupted";
27635
28113
  }
27636
28114
  function taskDigest(input) {
27637
- return createHash6("sha256").update(
28115
+ return createHash7("sha256").update(
27638
28116
  JSON.stringify({
27639
28117
  task: input.task,
27640
- cwd: path9.resolve(input.cwd),
28118
+ cwd: path12.resolve(input.cwd),
27641
28119
  modelId: input.model?.id ?? null,
27642
28120
  thinkingOptionId: input.thinkingOptionId ?? null
27643
28121
  })
@@ -27708,7 +28186,7 @@ var HarnessDelegationCoordinator = class {
27708
28186
  return {
27709
28187
  harnessId: input.harnessId,
27710
28188
  inspection: await adapter.inspect({
27711
- ...input.cwd ? { cwd: path9.resolve(input.cwd) } : {},
28189
+ ...input.cwd ? { cwd: path12.resolve(input.cwd) } : {},
27712
28190
  ...input.refresh !== void 0 ? { refresh: input.refresh } : {}
27713
28191
  })
27714
28192
  };
@@ -27722,7 +28200,7 @@ var HarnessDelegationCoordinator = class {
27722
28200
  const result = await this.#startOfficial({ ...input, parentThreadId, cwd: selectedCwd });
27723
28201
  return { ...result, parentThreadId, cwd: result.cwd ?? selectedCwd };
27724
28202
  }
27725
- const startInput = { ...input, parentThreadId, cwd: path9.resolve(selectedCwd) };
28203
+ const startInput = { ...input, parentThreadId, cwd: path12.resolve(selectedCwd) };
27726
28204
  if (!this.#adapters.has(input.harnessId)) {
27727
28205
  throw new DelegationControlError(
27728
28206
  "HARNESS_NOT_FOUND",
@@ -27762,10 +28240,10 @@ var HarnessDelegationCoordinator = class {
27762
28240
  });
27763
28241
  this.#validateConfiguration(inspected.inspection, input.model, input.thinkingOptionId);
27764
28242
  }
27765
- const delegationId = hostThreadIdSchema.parse(randomUUID5());
27766
- const childThreadId = hostThreadIdSchema.parse(randomUUID5());
27767
- const turnId = hostTurnIdSchema.parse(randomUUID5());
27768
- const createRequestId = input.requestId ? `delegation:${input.requestId}` : randomUUID5();
28243
+ const delegationId = hostThreadIdSchema.parse(randomUUID6());
28244
+ const childThreadId = hostThreadIdSchema.parse(randomUUID6());
28245
+ const turnId = hostTurnIdSchema.parse(randomUUID6());
28246
+ const createRequestId = input.requestId ? `delegation:${input.requestId}` : randomUUID6();
27769
28247
  let record3 = await this.#repository.createProvisional(
27770
28248
  createExternalThreadRecordInput({
27771
28249
  hostThreadId: childThreadId,
@@ -27897,7 +28375,7 @@ var HarnessDelegationCoordinator = class {
27897
28375
  if (thread.running || thread.activeTurnId) {
27898
28376
  throw new DelegationControlError("THREAD_BUSY", "Thread already has an active Turn");
27899
28377
  }
27900
- const turnId = hostTurnIdSchema.parse(randomUUID5());
28378
+ const turnId = hostTurnIdSchema.parse(randomUUID6());
27901
28379
  try {
27902
28380
  await this.#startExternalTurn(thread, input.message, turnId);
27903
28381
  } catch (error51) {
@@ -28151,7 +28629,7 @@ var HarnessDelegationCoordinator = class {
28151
28629
 
28152
28630
  // packages/host-runtime/src/harness-plugin-loader.ts
28153
28631
  import { readdir as readdir3, realpath as realpath2 } from "node:fs/promises";
28154
- import path11 from "node:path";
28632
+ import path14 from "node:path";
28155
28633
  import { pathToFileURL } from "node:url";
28156
28634
 
28157
28635
  // packages/host-runtime/src/harness-plugin-registry.ts
@@ -28188,25 +28666,25 @@ var HarnessPluginRegistry = class {
28188
28666
  };
28189
28667
 
28190
28668
  // packages/host-runtime/src/plugin-files.ts
28191
- import { open as open4, realpath, stat as stat2 } from "node:fs/promises";
28192
- import path10 from "node:path";
28669
+ import { open as open5, realpath, stat as stat3 } from "node:fs/promises";
28670
+ import path13 from "node:path";
28193
28671
  function inside(root, candidate) {
28194
- const relative = path10.relative(root, candidate);
28195
- return relative !== "" && !path10.isAbsolute(relative) && relative !== ".." && !relative.startsWith(`..${path10.sep}`);
28672
+ const relative = path13.relative(root, candidate);
28673
+ return relative !== "" && !path13.isAbsolute(relative) && relative !== ".." && !relative.startsWith(`..${path13.sep}`);
28196
28674
  }
28197
28675
  async function pluginResourcePath(root, relative) {
28198
- if (path10.isAbsolute(relative) || !inside(root, path10.resolve(root, relative))) {
28676
+ if (path13.isAbsolute(relative) || !inside(root, path13.resolve(root, relative))) {
28199
28677
  throw new Error("Plugin resource escapes its root");
28200
28678
  }
28201
- const resolved = await realpath(path10.resolve(root, relative));
28202
- if (!inside(root, resolved) || !(await stat2(resolved)).isFile()) {
28679
+ const resolved = await realpath(path13.resolve(root, relative));
28680
+ if (!inside(root, resolved) || !(await stat3(resolved)).isFile()) {
28203
28681
  throw new Error("Plugin resource must be a regular file inside its root");
28204
28682
  }
28205
28683
  return resolved;
28206
28684
  }
28207
28685
  async function readPluginFile(file2, maximum) {
28208
- if (!(await stat2(file2)).isFile()) throw new Error("Plugin resource is not a regular file");
28209
- const handle = await open4(file2, "r");
28686
+ if (!(await stat3(file2)).isFile()) throw new Error("Plugin resource is not a regular file");
28687
+ const handle = await open5(file2, "r");
28210
28688
  try {
28211
28689
  const info = await handle.stat();
28212
28690
  if (!info.isFile() || info.size > maximum) throw new Error("Plugin resource exceeds its limit");
@@ -28360,7 +28838,7 @@ async function loadHarnessPlugins(options2) {
28360
28838
  const enabledIds = /* @__PURE__ */ new Set();
28361
28839
  const roots = /* @__PURE__ */ new Set();
28362
28840
  for (const configuredRoot of options2.roots) {
28363
- if (!path11.isAbsolute(configuredRoot)) {
28841
+ if (!path14.isAbsolute(configuredRoot)) {
28364
28842
  diagnose({ code: "invalidRoot" });
28365
28843
  continue;
28366
28844
  }
@@ -28390,7 +28868,7 @@ async function loadHarnessPlugins(options2) {
28390
28868
  for (const directory of directories) {
28391
28869
  try {
28392
28870
  const file2 = await pluginResourcePath(root, `${directory.name}/manifest.json`);
28393
- const pluginRoot = await realpath2(path11.join(root, directory.name));
28871
+ const pluginRoot = await realpath2(path14.join(root, directory.name));
28394
28872
  await pluginResourcePath(pluginRoot, "manifest.json");
28395
28873
  const manifest = harnessPluginManifestSchema.parse(
28396
28874
  JSON.parse(
@@ -28485,28 +28963,28 @@ async function loadHarnessPlugins(options2) {
28485
28963
  }
28486
28964
 
28487
28965
  // packages/host-runtime/src/harness-launch-settings.ts
28488
- import { randomUUID as randomUUID6 } from "node:crypto";
28489
- import { mkdir as mkdir4, readFile as readFile6, rename as rename3, rm as rm4, stat as stat3, writeFile as writeFile3 } from "node:fs/promises";
28490
- import os3 from "node:os";
28491
- import path12 from "node:path";
28966
+ import { randomUUID as randomUUID7 } from "node:crypto";
28967
+ import { mkdir as mkdir5, readFile as readFile7, rename as rename4, rm as rm5, stat as stat4, writeFile as writeFile3 } from "node:fs/promises";
28968
+ import os4 from "node:os";
28969
+ import path15 from "node:path";
28492
28970
  var HarnessLaunchSettingsStore = class {
28493
28971
  #directory;
28494
28972
  #initial = /* @__PURE__ */ new Map();
28495
28973
  constructor(environment) {
28496
- this.#directory = path12.join(
28497
- environment.CODEXHOST_DATA_DIR ? path12.resolve(environment.CODEXHOST_DATA_DIR) : path12.join(os3.homedir(), ".codexhost"),
28974
+ this.#directory = path15.join(
28975
+ environment.CODEXHOST_DATA_DIR ? path15.resolve(environment.CODEXHOST_DATA_DIR) : path15.join(os4.homedir(), ".codexhost"),
28498
28976
  "harness-launch-settings"
28499
28977
  );
28500
28978
  }
28501
28979
  #file(id2) {
28502
- return path12.join(this.#directory, `${harnessPluginIdSchema.parse(id2)}.json`);
28980
+ return path15.join(this.#directory, `${harnessPluginIdSchema.parse(id2)}.json`);
28503
28981
  }
28504
28982
  async #read(id2) {
28505
28983
  try {
28506
28984
  const value2 = harnessLaunchPathSchema.parse(
28507
- JSON.parse(await readFile6(this.#file(id2), "utf8"))
28985
+ JSON.parse(await readFile7(this.#file(id2), "utf8"))
28508
28986
  );
28509
- if (!path12.isAbsolute(value2)) throw new Error("Expected an absolute entrypoint path");
28987
+ if (!path15.isAbsolute(value2)) throw new Error("Expected an absolute entrypoint path");
28510
28988
  return value2;
28511
28989
  } catch (error51) {
28512
28990
  if (error51 && typeof error51 === "object" && "code" in error51 && error51.code === "ENOENT")
@@ -28532,22 +29010,22 @@ var HarnessLaunchSettingsStore = class {
28532
29010
  const initial = await this.initialCommand(id2) ?? null;
28533
29011
  const file2 = this.#file(id2);
28534
29012
  if (value2 === null) {
28535
- await rm4(file2, { force: true });
29013
+ await rm5(file2, { force: true });
28536
29014
  } else {
28537
29015
  value2 = harnessLaunchPathSchema.parse(value2);
28538
- if (!path12.isAbsolute(value2))
29016
+ if (!path15.isAbsolute(value2))
28539
29017
  throw new Error("Use an absolute entrypoint path without arguments");
28540
- const metadata = await stat3(value2).catch(() => void 0);
29018
+ const metadata = await stat4(value2).catch(() => void 0);
28541
29019
  if (!metadata?.isDirectory() && !metadata?.isFile())
28542
29020
  throw new Error("The installation path must be an existing directory on this Host");
28543
- await mkdir4(this.#directory, { recursive: true, mode: 448 });
28544
- const temporary = `${file2}.${randomUUID6()}.tmp`;
29021
+ await mkdir5(this.#directory, { recursive: true, mode: 448 });
29022
+ const temporary = `${file2}.${randomUUID7()}.tmp`;
28545
29023
  try {
28546
29024
  await writeFile3(temporary, `${JSON.stringify(value2)}
28547
29025
  `, { mode: 384, flag: "wx" });
28548
- await rename3(temporary, file2);
29026
+ await rename4(temporary, file2);
28549
29027
  } finally {
28550
- await rm4(temporary, { force: true });
29028
+ await rm5(temporary, { force: true });
28551
29029
  }
28552
29030
  }
28553
29031
  return { path: value2, restartRequired: value2 !== initial };
@@ -28710,11 +29188,11 @@ function spawnOfficialAppServerConnection(input) {
28710
29188
  }
28711
29189
 
28712
29190
  // packages/host-runtime/src/account/codex-account-control.ts
28713
- function isRecord9(value2) {
29191
+ function isRecord10(value2) {
28714
29192
  return typeof value2 === "object" && value2 !== null && !Array.isArray(value2);
28715
29193
  }
28716
29194
  function currentCodexAccountFromOfficialRead(result) {
28717
- if (!isRecord9(result) || !isRecord9(result.account) || result.account.type !== "chatgpt") {
29195
+ if (!isRecord10(result) || !isRecord10(result.account) || result.account.type !== "chatgpt") {
28718
29196
  return null;
28719
29197
  }
28720
29198
  const email3 = external_exports.string().email().max(320).safeParse(result.account.email);
@@ -28744,13 +29222,13 @@ var SingleNativeCodexAccount = class {
28744
29222
  };
28745
29223
 
28746
29224
  // packages/host-runtime/src/codex-runtime/official-runtime-owner.ts
28747
- import { randomUUID as randomUUID8 } from "node:crypto";
29225
+ import { randomUUID as randomUUID9 } from "node:crypto";
28748
29226
 
28749
29227
  // packages/host-runtime/src/official-request-broker.ts
28750
- import { randomUUID as randomUUID7 } from "node:crypto";
29228
+ import { randomUUID as randomUUID8 } from "node:crypto";
28751
29229
  var INTERNAL_REQUEST_PREFIX = "codexhost:official:";
28752
29230
  var MAX_RETIRED_IDS = 1024;
28753
- function isRecord10(value2) {
29231
+ function isRecord11(value2) {
28754
29232
  return typeof value2 === "object" && value2 !== null && !Array.isArray(value2);
28755
29233
  }
28756
29234
  var OfficialRequestBroker = class {
@@ -28763,7 +29241,7 @@ var OfficialRequestBroker = class {
28763
29241
  constructor(input) {
28764
29242
  this.#send = input.send;
28765
29243
  this.#timeoutMs = input.timeoutMs ?? 3e4;
28766
- this.#nextId = input.nextId ?? (() => `${INTERNAL_REQUEST_PREFIX}${randomUUID7()}`);
29244
+ this.#nextId = input.nextId ?? (() => `${INTERNAL_REQUEST_PREFIX}${randomUUID8()}`);
28767
29245
  }
28768
29246
  get pendingCount() {
28769
29247
  return this.#pending.size;
@@ -28793,7 +29271,7 @@ var OfficialRequestBroker = class {
28793
29271
  });
28794
29272
  }
28795
29273
  handle(value2) {
28796
- if (!isRecord10(value2) || typeof value2.id !== "string") return false;
29274
+ if (!isRecord11(value2) || typeof value2.id !== "string") return false;
28797
29275
  const pending = this.#pending.get(value2.id);
28798
29276
  if (!pending) return this.#retired.has(value2.id);
28799
29277
  clearTimeout(pending.timeout);
@@ -29117,7 +29595,7 @@ var OfficialRuntimeOwner = class {
29117
29595
  }
29118
29596
  #attach(role, output, onBackendStopped) {
29119
29597
  const client = {
29120
- id: randomUUID8(),
29598
+ id: randomUUID9(),
29121
29599
  role,
29122
29600
  output,
29123
29601
  ...onBackendStopped ? { onBackendStopped } : {},
@@ -29275,7 +29753,7 @@ var OfficialRuntimeOwner = class {
29275
29753
  if (!object4(value2)) return client.output(event);
29276
29754
  if (typeof value2.id === "string" || typeof value2.id === "number") {
29277
29755
  if (typeof value2.method === "string") {
29278
- const id2 = `codexhost:server:${client.id}:${event.generation}:${randomUUID8()}`;
29756
+ const id2 = `codexhost:server:${client.id}:${event.generation}:${randomUUID9()}`;
29279
29757
  client.serverRequests.set(id2, value2.id);
29280
29758
  const projected = { ...value2, id: id2 };
29281
29759
  return client.output({
@@ -29513,11 +29991,11 @@ function createOwnedConnectionBackend(factory) {
29513
29991
  }
29514
29992
 
29515
29993
  // packages/host-runtime/src/route-observation.ts
29516
- function isRecord11(value2) {
29994
+ function isRecord12(value2) {
29517
29995
  return typeof value2 === "object" && value2 !== null && !Array.isArray(value2);
29518
29996
  }
29519
29997
  function classifyThreadPurpose(request) {
29520
- return isRecord11(request.params) && request.params.ephemeral === true ? "ephemeral" : "conversation";
29998
+ return isRecord12(request.params) && request.params.ephemeral === true ? "ephemeral" : "conversation";
29521
29999
  }
29522
30000
  var RequestRouteObservationTracker = class {
29523
30001
  #nextCreateOrdinal = 0;
@@ -29542,13 +30020,13 @@ var RequestRouteObservationTracker = class {
29542
30020
  this.#createByThreadId.set(threadId2, tracked);
29543
30021
  }
29544
30022
  bindOfficialResponse(response) {
29545
- if (!isRecord11(response) || !("id" in response)) return;
30023
+ if (!isRecord12(response) || !("id" in response)) return;
29546
30024
  const tracked = this.#pendingByRequestId.get(response.id);
29547
30025
  if (!tracked) return;
29548
30026
  this.#pendingByRequestId.delete(response.id);
29549
30027
  const result = response.result;
29550
- const thread = isRecord11(result) ? result.thread : null;
29551
- if (isRecord11(thread) && typeof thread.id === "string") {
30028
+ const thread = isRecord12(result) ? result.thread : null;
30029
+ if (isRecord12(thread) && typeof thread.id === "string") {
29552
30030
  this.#createByThreadId.set(thread.id, tracked);
29553
30031
  }
29554
30032
  }
@@ -29670,25 +30148,25 @@ function resolveExternalSessionTreeIds(records) {
29670
30148
  const resolve = (start) => {
29671
30149
  const cached2 = resolved.get(start.hostThreadId);
29672
30150
  if (cached2) return cached2;
29673
- const path27 = [];
30151
+ const path29 = [];
29674
30152
  const visited = /* @__PURE__ */ new Set();
29675
30153
  let current = start;
29676
30154
  while (true) {
29677
30155
  const known = resolved.get(current.hostThreadId);
29678
30156
  if (known) {
29679
- for (const record3 of path27) resolved.set(record3.hostThreadId, known);
30157
+ for (const record3 of path29) resolved.set(record3.hostThreadId, known);
29680
30158
  return known;
29681
30159
  }
29682
30160
  if (visited.has(current.hostThreadId)) {
29683
30161
  throw new Error("External Thread Fork tree contains a cycle");
29684
30162
  }
29685
30163
  visited.add(current.hostThreadId);
29686
- path27.push(current);
30164
+ path29.push(current);
29687
30165
  const sourceId = current.subagent?.parentHostThreadId ?? current.forkSource?.hostThreadId;
29688
30166
  const source = sourceId ? byId.get(sourceId) : void 0;
29689
30167
  if (!source) {
29690
30168
  const root = current.hostThreadId;
29691
- for (const record3 of path27) resolved.set(record3.hostThreadId, root);
30169
+ for (const record3 of path29) resolved.set(record3.hostThreadId, root);
29692
30170
  return root;
29693
30171
  }
29694
30172
  current = source;
@@ -29742,11 +30220,11 @@ var OfficialThreadListError = class extends Error {
29742
30220
  }
29743
30221
  rpcError;
29744
30222
  };
29745
- function isRecord12(value2) {
30223
+ function isRecord13(value2) {
29746
30224
  return typeof value2 === "object" && value2 !== null && !Array.isArray(value2);
29747
30225
  }
29748
30226
  function officialThreadListPageFromResponse(response) {
29749
- if (isRecord12(response.error)) {
30227
+ if (isRecord13(response.error)) {
29750
30228
  if (!Number.isSafeInteger(response.error.code) || typeof response.error.message !== "string") {
29751
30229
  throw new Error("Official thread/list error response is invalid");
29752
30230
  }
@@ -29914,14 +30392,14 @@ var THREAD_USAGE_UPDATED_METHOD = "codexhost/thread/usage/updated";
29914
30392
  function delay3(milliseconds) {
29915
30393
  return new Promise((resolve) => setTimeout(resolve, milliseconds));
29916
30394
  }
29917
- function isRecord13(value2) {
30395
+ function isRecord14(value2) {
29918
30396
  return typeof value2 === "object" && value2 !== null && !Array.isArray(value2);
29919
30397
  }
29920
30398
  function isCreditsAdapter(adapter) {
29921
30399
  return typeof adapter.credits === "function";
29922
30400
  }
29923
30401
  function projectAccountCredits(value2) {
29924
- if (!isRecord13(value2)) return null;
30402
+ if (!isRecord14(value2)) return null;
29925
30403
  const rest = { ...value2 };
29926
30404
  delete rest.fetchedAt;
29927
30405
  const parsed = accountCreditsSnapshotSchema.safeParse(rest);
@@ -30044,12 +30522,12 @@ function classifyCreateRequestRoute(request, defaultAgent) {
30044
30522
  };
30045
30523
  }
30046
30524
  function requestObject(request) {
30047
- if (!isRecord13(request.params)) throw new Error(`${request.method} params must be an object`);
30525
+ if (!isRecord14(request.params)) throw new Error(`${request.method} params must be an object`);
30048
30526
  return request.params;
30049
30527
  }
30050
30528
  function requestText(params) {
30051
30529
  if (!Array.isArray(params.input)) throw new Error("turn/start input must be an array");
30052
- const text = params.input.filter((item) => isRecord13(item) && item.type === "text").map((item) => item.text).filter((value2) => typeof value2 === "string").join("\n");
30530
+ const text = params.input.filter((item) => isRecord14(item) && item.type === "text").map((item) => item.text).filter((value2) => typeof value2 === "string").join("\n");
30053
30531
  if (!text) throw new Error("turn/start must contain text input");
30054
30532
  return text;
30055
30533
  }
@@ -30103,6 +30581,7 @@ var AppServerHost = class {
30103
30581
  #accountInspections = new HarnessAccountInspectionCache();
30104
30582
  #externalRuntime;
30105
30583
  #externalSteering = new ExternalTurnSteering();
30584
+ #liveCommandCache = new LiveCommandCatalogCache();
30106
30585
  #repository;
30107
30586
  #pendingDesktopApprovals = /* @__PURE__ */ new Map();
30108
30587
  #pendingDesktopQuestions = /* @__PURE__ */ new Map();
@@ -30144,7 +30623,7 @@ var AppServerHost = class {
30144
30623
  this.#launchSettings = new HarnessLaunchSettingsStore(
30145
30624
  this.#options.pluginContext?.environment ?? environment
30146
30625
  );
30147
- const permanentHome = path13.resolve(environment.CODEX_HOME ?? path13.join(os4.homedir(), ".codex"));
30626
+ const permanentHome = path16.resolve(environment.CODEX_HOME ?? path16.join(os5.homedir(), ".codex"));
30148
30627
  this.#ownsOfficialRuntimeScope = options2.officialRuntimeScope === void 0;
30149
30628
  this.#officialRuntimeScope = options2.officialRuntimeScope ?? new OfficialRuntimeScope({
30150
30629
  diagnosticOutput: this.#options.diagnosticOutput,
@@ -30406,12 +30885,12 @@ var AppServerHost = class {
30406
30885
  for (const resolve of waiters) resolve();
30407
30886
  }
30408
30887
  #observeOfficialTurnStartResponse(value2) {
30409
- if (!isRecord13(value2) || !("id" in value2)) return;
30888
+ if (!isRecord14(value2) || !("id" in value2)) return;
30410
30889
  const threadId2 = this.#pendingOfficialTurnStarts.get(value2.id);
30411
30890
  if (!threadId2) return;
30412
30891
  this.#pendingOfficialTurnStarts.delete(value2.id);
30413
- const result = isRecord13(value2.result) ? value2.result : null;
30414
- const turn = result && isRecord13(result.turn) ? result.turn : null;
30892
+ const result = isRecord14(value2.result) ? value2.result : null;
30893
+ const turn = result && isRecord14(result.turn) ? result.turn : null;
30415
30894
  if (turn && typeof turn.id === "string") {
30416
30895
  this.#activeOfficialTurns.set(threadId2, turn.id);
30417
30896
  }
@@ -30425,7 +30904,7 @@ var AppServerHost = class {
30425
30904
  async #forwardDesktop() {
30426
30905
  for await (const frame of readLfFrames(this.#options.desktopInput)) {
30427
30906
  const parsed = parseJsonFrame(frame);
30428
- if (isRecord13(parsed) && parsed.method === "initialized" && !("id" in parsed)) {
30907
+ if (isRecord14(parsed) && parsed.method === "initialized" && !("id" in parsed)) {
30429
30908
  continue;
30430
30909
  }
30431
30910
  if (await this.#handleDesktopApprovalResponse(parsed)) continue;
@@ -30449,7 +30928,7 @@ var AppServerHost = class {
30449
30928
  }
30450
30929
  continue;
30451
30930
  }
30452
- const threadId2 = isRecord13(request.params) && typeof request.params.threadId === "string" ? request.params.threadId : void 0;
30931
+ const threadId2 = isRecord14(request.params) && typeof request.params.threadId === "string" ? request.params.threadId : void 0;
30453
30932
  this.#dispatchDesktopRequest(
30454
30933
  () => this.#desktopRequests.run(
30455
30934
  threadId2,
@@ -30677,7 +31156,7 @@ var AppServerHost = class {
30677
31156
  rpcError(request, -32602, "Invalid Harness command inspection params")
30678
31157
  );
30679
31158
  } else {
30680
- await this.#writeHarnessCommandCatalog(request, params.data.harnessId);
31159
+ await this.#writeHarnessCommandCatalog(request, params.data.harnessId, params.data.cwd);
30681
31160
  }
30682
31161
  return;
30683
31162
  }
@@ -30774,7 +31253,7 @@ var AppServerHost = class {
30774
31253
  return;
30775
31254
  }
30776
31255
  if (request.method === "thread/fork") {
30777
- const params = isRecord13(request.params) ? request.params : {};
31256
+ const params = isRecord14(request.params) ? request.params : {};
30778
31257
  const resolution = typeof params.threadId === "string" ? await this.#resolveExternalThread(params.threadId) : { kind: "official" };
30779
31258
  if (resolution.kind === "error") {
30780
31259
  await this.#writer.json(rpcError(request, resolution.error.code, resolution.error.message));
@@ -30795,7 +31274,7 @@ var AppServerHost = class {
30795
31274
  }
30796
31275
  }
30797
31276
  if (request.method === "thread/revert") {
30798
- const params = isRecord13(request.params) ? request.params : {};
31277
+ const params = isRecord14(request.params) ? request.params : {};
30799
31278
  const resolution = typeof params.threadId === "string" ? await this.#resolveExternalThread(params.threadId) : { kind: "official" };
30800
31279
  if (resolution.kind === "error") {
30801
31280
  await this.#writer.json(rpcError(request, resolution.error.code, resolution.error.message));
@@ -30816,7 +31295,7 @@ var AppServerHost = class {
30816
31295
  }
30817
31296
  }
30818
31297
  if (request.method === "thread/rollback") {
30819
- const params = isRecord13(request.params) ? request.params : {};
31298
+ const params = isRecord14(request.params) ? request.params : {};
30820
31299
  const resolution = typeof params.threadId === "string" ? await this.#resolveExternalThread(params.threadId) : { kind: "official" };
30821
31300
  if (resolution.kind === "error") {
30822
31301
  await this.#writer.json(rpcError(request, resolution.error.code, resolution.error.message));
@@ -30972,7 +31451,7 @@ var AppServerHost = class {
30972
31451
  return;
30973
31452
  }
30974
31453
  }
30975
- if (request.method.startsWith("thread/") && !EXPLICIT_EXTERNAL_THREAD_METHODS.has(request.method) && isRecord13(request.params) && typeof request.params.threadId === "string") {
31454
+ if (request.method.startsWith("thread/") && !EXPLICIT_EXTERNAL_THREAD_METHODS.has(request.method) && isRecord14(request.params) && typeof request.params.threadId === "string") {
30976
31455
  const location = await this.#locateExternalThread(request.params.threadId);
30977
31456
  if (await this.#writeResolutionError(request, location)) return;
30978
31457
  if (location.kind === "external") {
@@ -30982,10 +31461,30 @@ var AppServerHost = class {
30982
31461
  return;
30983
31462
  }
30984
31463
  }
30985
- await this.#forwardOfficialRequest(request, frame);
31464
+ await this.#forwardOfficialRequest(
31465
+ request,
31466
+ await this.#rewriteOfficialDelegationMentions(request, frame)
31467
+ );
31468
+ }
31469
+ /** Native Codex Turns: turn `#` delegation chips into an explicit Skill-backed request. */
31470
+ async #rewriteOfficialDelegationMentions(request, frame) {
31471
+ if (request.method !== "turn/start" && request.method !== "turn/steer") return frame;
31472
+ if (!isRecord14(request.params) || !Array.isArray(request.params.input)) return frame;
31473
+ const input = request.params.input;
31474
+ if (!input.some(
31475
+ (item) => isRecord14(item) && typeof item.text === "string" && item.text.includes(DELEGATION_MENTION_PATH_PREFIX)
31476
+ )) {
31477
+ return frame;
31478
+ }
31479
+ const rewritten = rewriteDelegationMentionInput(input, await managedDelegationSkillReference());
31480
+ if (!rewritten) return frame;
31481
+ return encodeJsonFrame({
31482
+ ...request,
31483
+ params: { ...request.params, input: rewritten }
31484
+ });
30986
31485
  }
30987
31486
  async #forwardOfficialNonRequest(value2, frame) {
30988
- const response = isRecord13(value2) ? value2 : null;
31487
+ const response = isRecord14(value2) ? value2 : null;
30989
31488
  const request = response && (typeof response.id === "string" || typeof response.id === "number") ? this.#officialServerRequests.get(response.id) : null;
30990
31489
  if (request !== void 0 && response) {
30991
31490
  this.#officialServerRequests.delete(response.id);
@@ -31014,7 +31513,7 @@ var AppServerHost = class {
31014
31513
  const parsed = input.value;
31015
31514
  this.#observeOfficialTurnStartResponse(parsed);
31016
31515
  let forwarded = parsed;
31017
- if (isRecord13(parsed) && typeof parsed.method === "string" && "id" in parsed) {
31516
+ if (isRecord14(parsed) && typeof parsed.method === "string" && "id" in parsed) {
31018
31517
  const originalId = parsed.id;
31019
31518
  if (typeof originalId === "string" || typeof originalId === "number") {
31020
31519
  const forwardedId = `codexhost:official:${++this.#nextOfficialServerRequestId}`;
@@ -31022,7 +31521,7 @@ var AppServerHost = class {
31022
31521
  forwarded = { ...parsed, id: forwardedId };
31023
31522
  }
31024
31523
  }
31025
- const accountScopedNotification = isRecord13(parsed) && typeof parsed.method === "string" && (parsed.method === "account/updated" || parsed.method.startsWith("account/rateLimits/"));
31524
+ const accountScopedNotification = isRecord14(parsed) && typeof parsed.method === "string" && (parsed.method === "account/updated" || parsed.method.startsWith("account/rateLimits/"));
31026
31525
  if (accountScopedNotification) {
31027
31526
  if (parsed.method === "account/updated") this.#officialRateLimits.reset(input.accountId);
31028
31527
  }
@@ -31091,10 +31590,10 @@ var AppServerHost = class {
31091
31590
  }
31092
31591
  }
31093
31592
  async #observeOfficialTurnLifecycle(value2) {
31094
- if (!isRecord13(value2) || !isRecord13(value2.params)) return;
31593
+ if (!isRecord14(value2) || !isRecord14(value2.params)) return;
31095
31594
  const params = value2.params;
31096
31595
  if (value2.method === "turn/started" && typeof params.threadId === "string") {
31097
- const turn = isRecord13(params.turn) ? params.turn : null;
31596
+ const turn = isRecord14(params.turn) ? params.turn : null;
31098
31597
  if (turn && typeof turn.id === "string") {
31099
31598
  this.#forgetPendingOfficialTurnStarts(params.threadId);
31100
31599
  this.#activeOfficialTurns.set(params.threadId, turn.id);
@@ -31107,7 +31606,7 @@ var AppServerHost = class {
31107
31606
  const delegation = await this.#repository.getDelegationByChild(
31108
31607
  hostThreadIdSchema.parse(params.threadId)
31109
31608
  );
31110
- const turn = isRecord13(params.turn) ? params.turn : null;
31609
+ const turn = isRecord14(params.turn) ? params.turn : null;
31111
31610
  const status = turn?.status === "failed" ? "failed" : turn?.status === "interrupted" || turn?.status === "cancelled" ? "interrupted" : "completed";
31112
31611
  if (this.#pendingOfficialDelegationThreads.has(params.threadId)) {
31113
31612
  this.#pendingOfficialTerminalStatuses.set(params.threadId, status);
@@ -31137,28 +31636,28 @@ var AppServerHost = class {
31137
31636
  }
31138
31637
  async #readOfficialThreadCwd(threadId2) {
31139
31638
  const response = await this.#requestOfficial("thread/read", { threadId: threadId2 });
31140
- if (isRecord13(response.error)) return void 0;
31141
- const result = isRecord13(response.result) ? response.result : null;
31142
- const thread = result && isRecord13(result.thread) ? result.thread : null;
31639
+ if (isRecord14(response.error)) return void 0;
31640
+ const result = isRecord14(response.result) ? response.result : null;
31641
+ const thread = result && isRecord14(result.thread) ? result.thread : null;
31143
31642
  return thread && typeof thread.cwd === "string" && thread.cwd.trim() ? thread.cwd : void 0;
31144
31643
  }
31145
31644
  async #inspectOfficialDelegationTarget(input) {
31146
31645
  const response = await this.#requestOfficial("model/list", {});
31147
- if (isRecord13(response.error)) {
31646
+ if (isRecord14(response.error)) {
31148
31647
  throw new DelegationControlError(
31149
31648
  "DELEGATION_FAILED",
31150
31649
  typeof response.error.message === "string" ? response.error.message : "Official Model catalog could not be read"
31151
31650
  );
31152
31651
  }
31153
- const result = isRecord13(response.result) ? response.result : null;
31652
+ const result = isRecord14(response.result) ? response.result : null;
31154
31653
  const data = result && Array.isArray(result.data) ? result.data : [];
31155
31654
  const thinkingById = /* @__PURE__ */ new Map();
31156
31655
  const models = data.flatMap((candidate) => {
31157
- if (!isRecord13(candidate) || typeof candidate.model !== "string" || !candidate.model.trim()) {
31656
+ if (!isRecord14(candidate) || typeof candidate.model !== "string" || !candidate.model.trim()) {
31158
31657
  return [];
31159
31658
  }
31160
31659
  const supportedThinkingOptionIds = Array.isArray(candidate.supportedReasoningEfforts) ? candidate.supportedReasoningEfforts.flatMap((option) => {
31161
- if (!isRecord13(option) || typeof option.reasoningEffort !== "string" || !option.reasoningEffort.trim()) {
31660
+ if (!isRecord14(option) || typeof option.reasoningEffort !== "string" || !option.reasoningEffort.trim()) {
31162
31661
  return [];
31163
31662
  }
31164
31663
  const id2 = harnessThinkingOptionIdSchema.safeParse(option.reasoningEffort);
@@ -31178,9 +31677,9 @@ var AppServerHost = class {
31178
31677
  ];
31179
31678
  });
31180
31679
  const defaultEntry = data.find(
31181
- (candidate) => isRecord13(candidate) && candidate.isDefault === true
31680
+ (candidate) => isRecord14(candidate) && candidate.isDefault === true
31182
31681
  );
31183
- const defaultModel = isRecord13(defaultEntry) && typeof defaultEntry.model === "string" ? encodeOfficialCodexModelRef(defaultEntry.model) : void 0;
31682
+ const defaultModel = isRecord14(defaultEntry) && typeof defaultEntry.model === "string" ? encodeOfficialCodexModelRef(defaultEntry.model) : void 0;
31184
31683
  return {
31185
31684
  harnessId: input.harnessId,
31186
31685
  inspection: {
@@ -31210,7 +31709,7 @@ var AppServerHost = class {
31210
31709
  throw new DelegationControlError("INVALID_ARGUMENT", "Official Model Ref is invalid");
31211
31710
  }
31212
31711
  const nativeModelId = requestedModel ? decodeOfficialCodexModelRef(requestedModel) : void 0;
31213
- const digest2 = createHash7("sha256").update(
31712
+ const digest2 = createHash8("sha256").update(
31214
31713
  JSON.stringify({
31215
31714
  task: input.task,
31216
31715
  cwd: input.cwd,
@@ -31286,8 +31785,8 @@ var AppServerHost = class {
31286
31785
  ephemeral: false,
31287
31786
  historyMode: "paginated"
31288
31787
  });
31289
- const startedResult = isRecord13(started.result) ? started.result : null;
31290
- const thread = startedResult && isRecord13(startedResult.thread) ? startedResult.thread : null;
31788
+ const startedResult = isRecord14(started.result) ? started.result : null;
31789
+ const thread = startedResult && isRecord14(startedResult.thread) ? startedResult.thread : null;
31291
31790
  const threadId2 = thread && typeof thread.id === "string" ? thread.id : null;
31292
31791
  if (!threadId2) throw new Error("Official thread/start returned no Thread identity");
31293
31792
  this.#pendingOfficialDelegationThreads.add(threadId2);
@@ -31299,8 +31798,8 @@ var AppServerHost = class {
31299
31798
  ...nativeModelId ? { model: nativeModelId } : {},
31300
31799
  ...input.thinkingOptionId ? { effort: input.thinkingOptionId } : {}
31301
31800
  });
31302
- const turnResult = isRecord13(turn.result) ? turn.result : null;
31303
- const turnValue = turnResult && isRecord13(turnResult.turn) ? turnResult.turn : null;
31801
+ const turnResult = isRecord14(turn.result) ? turn.result : null;
31802
+ const turnValue = turnResult && isRecord14(turnResult.turn) ? turnResult.turn : null;
31304
31803
  const parsedTurnId = turnValue && typeof turnValue.id === "string" ? turnValue.id : null;
31305
31804
  if (!parsedTurnId) throw new Error("Official turn/start returned no Turn identity");
31306
31805
  turnId = parsedTurnId;
@@ -31311,7 +31810,7 @@ var AppServerHost = class {
31311
31810
  throw error51;
31312
31811
  }
31313
31812
  this.#activeOfficialTurns.set(threadId2, turnId);
31314
- const delegationId = hostThreadIdSchema.parse(randomUUID9());
31813
+ const delegationId = hostThreadIdSchema.parse(randomUUID10());
31315
31814
  try {
31316
31815
  const source = await this.#repository.find(input.parentThreadId);
31317
31816
  const pendingTerminal = this.#pendingOfficialTerminalStatuses.get(threadId2);
@@ -31370,27 +31869,27 @@ var AppServerHost = class {
31370
31869
  threadId: input.threadId,
31371
31870
  includeTurns: true
31372
31871
  });
31373
- if (isRecord13(current.error) || !isRecord13(current.result)) {
31872
+ if (isRecord14(current.error) || !isRecord14(current.result)) {
31374
31873
  throw new DelegationControlError("THREAD_NOT_FOUND", "Official Thread was not found");
31375
31874
  }
31376
- const currentThread = isRecord13(current.result.thread) ? current.result.thread : null;
31875
+ const currentThread = isRecord14(current.result.thread) ? current.result.thread : null;
31377
31876
  const currentTurns = currentThread && Array.isArray(currentThread.turns) ? currentThread.turns : [];
31378
31877
  const latestTurn = currentTurns.at(-1);
31379
- if (currentThread && isRecord13(currentThread.status) && currentThread.status.type === "active" || isRecord13(latestTurn) && (latestTurn.status === "inProgress" || latestTurn.status === "running")) {
31878
+ if (currentThread && isRecord14(currentThread.status) && currentThread.status.type === "active" || isRecord14(latestTurn) && (latestTurn.status === "inProgress" || latestTurn.status === "running")) {
31380
31879
  throw new DelegationControlError("THREAD_BUSY", "Thread already has an active Turn");
31381
31880
  }
31382
31881
  const response = await this.#requestOfficial("turn/start", {
31383
31882
  threadId: input.threadId,
31384
31883
  input: [{ type: "text", text: input.message }]
31385
31884
  });
31386
- if (isRecord13(response.error)) {
31885
+ if (isRecord14(response.error)) {
31387
31886
  throw new DelegationControlError(
31388
31887
  "DELEGATION_FAILED",
31389
31888
  typeof response.error.message === "string" ? response.error.message : "Turn start failed"
31390
31889
  );
31391
31890
  }
31392
- const result = isRecord13(response.result) ? response.result : null;
31393
- const turn = result && isRecord13(result.turn) ? result.turn : null;
31891
+ const result = isRecord14(response.result) ? response.result : null;
31892
+ const turn = result && isRecord14(result.turn) ? result.turn : null;
31394
31893
  const turnId = turn && typeof turn.id === "string" ? turn.id : null;
31395
31894
  if (!turnId) throw new Error("Official turn/start returned no Turn identity");
31396
31895
  this.#activeOfficialTurns.set(input.threadId, turnId);
@@ -31412,13 +31911,13 @@ var AppServerHost = class {
31412
31911
  threadId: input.threadId,
31413
31912
  includeTurns: true
31414
31913
  });
31415
- if (isRecord13(current.error) || !isRecord13(current.result)) {
31914
+ if (isRecord14(current.error) || !isRecord14(current.result)) {
31416
31915
  throw new DelegationControlError("THREAD_NOT_FOUND", "Official Thread was not found");
31417
31916
  }
31418
- const currentThread = isRecord13(current.result.thread) ? current.result.thread : null;
31917
+ const currentThread = isRecord14(current.result.thread) ? current.result.thread : null;
31419
31918
  const currentTurns = currentThread && Array.isArray(currentThread.turns) ? currentThread.turns : [];
31420
31919
  const latestTurn = currentTurns.at(-1);
31421
- if (isRecord13(latestTurn) && typeof latestTurn.id === "string" && (latestTurn.status === "inProgress" || latestTurn.status === "running")) {
31920
+ if (isRecord14(latestTurn) && typeof latestTurn.id === "string" && (latestTurn.status === "inProgress" || latestTurn.status === "running")) {
31422
31921
  turnId = latestTurn.id;
31423
31922
  this.#activeOfficialTurns.set(input.threadId, turnId);
31424
31923
  } else {
@@ -31429,7 +31928,7 @@ var AppServerHost = class {
31429
31928
  threadId: input.threadId,
31430
31929
  turnId
31431
31930
  });
31432
- if (isRecord13(response.error)) {
31931
+ if (isRecord14(response.error)) {
31433
31932
  throw new DelegationControlError(
31434
31933
  "DELEGATION_FAILED",
31435
31934
  typeof response.error.message === "string" ? response.error.message : "Turn cancel failed"
@@ -31442,18 +31941,18 @@ var AppServerHost = class {
31442
31941
  threadId: input.threadId,
31443
31942
  includeTurns: true
31444
31943
  });
31445
- if (isRecord13(response.error)) {
31944
+ if (isRecord14(response.error)) {
31446
31945
  throw new DelegationControlError(
31447
31946
  "THREAD_NOT_FOUND",
31448
31947
  typeof response.error.message === "string" ? response.error.message : "Official Thread was not found"
31449
31948
  );
31450
31949
  }
31451
- const result = isRecord13(response.result) ? response.result : null;
31452
- const thread = result && isRecord13(result.thread) ? result.thread : null;
31950
+ const result = isRecord14(response.result) ? response.result : null;
31951
+ const thread = result && isRecord14(result.thread) ? result.thread : null;
31453
31952
  if (!thread)
31454
31953
  throw new DelegationControlError("THREAD_NOT_FOUND", "Official Thread was not found");
31455
- const turns = Array.isArray(thread.turns) ? thread.turns.filter((turn) => isRecord13(turn)) : [];
31456
- const running = this.#activeOfficialTurns.has(input.threadId) || isRecord13(thread.status) && thread.status.type === "active";
31954
+ const turns = Array.isArray(thread.turns) ? thread.turns.filter((turn) => isRecord14(turn)) : [];
31955
+ const running = this.#activeOfficialTurns.has(input.threadId) || isRecord14(thread.status) && thread.status.type === "active";
31457
31956
  const snapshot = projectDelegationThreadSnapshot({
31458
31957
  threadId: input.threadId,
31459
31958
  harnessId: "codex",
@@ -31475,7 +31974,7 @@ var AppServerHost = class {
31475
31974
  async #listDelegationThreads(input) {
31476
31975
  const [sortKey, sortDirection2] = input.sort.split("-");
31477
31976
  const request = {
31478
- id: `codexhost:delegation-list:${randomUUID9()}`,
31977
+ id: `codexhost:delegation-list:${randomUUID10()}`,
31479
31978
  method: "thread/list",
31480
31979
  params: {
31481
31980
  cwd: input.cwd ? [input.cwd] : null,
@@ -31503,7 +32002,7 @@ var AppServerHost = class {
31503
32002
  threads: result.data.flatMap((entry) => {
31504
32003
  if (typeof entry.id !== "string") return [];
31505
32004
  const record3 = records.find((candidate) => candidate.hostThreadId === entry.id);
31506
- const status = isRecord13(entry.status) && entry.status.type === "active" ? "running" : "completed";
32005
+ const status = isRecord14(entry.status) && entry.status.type === "active" ? "running" : "completed";
31507
32006
  return [
31508
32007
  {
31509
32008
  threadId: entry.id,
@@ -31823,21 +32322,67 @@ var AppServerHost = class {
31823
32322
  await this.#writer.json(rpcEnvelope(request, { result: { commands: [] } }));
31824
32323
  return;
31825
32324
  }
31826
- await this.#writeHarnessCommandCatalog(request, location.record.harnessId);
32325
+ const loaded = this.#externalRuntime.get(params.data.threadId);
32326
+ if (loaded) {
32327
+ const catalog = await this.#inspectLoadedCommands(loaded);
32328
+ if (catalog) {
32329
+ await this.#writer.json(rpcEnvelope(request, { result: jsonValueSchema.parse(catalog) }));
32330
+ return;
32331
+ }
32332
+ }
32333
+ await this.#writeHarnessCommandCatalog(
32334
+ request,
32335
+ location.record.harnessId,
32336
+ loaded?.cwd ?? location.record.cwd,
32337
+ params.data.threadId
32338
+ );
31827
32339
  }
31828
- async #writeHarnessCommandCatalog(request, harnessId) {
32340
+ /**
32341
+ * Catalog of a loaded Session, marked live or static. A live catalog is
32342
+ * remembered for its Harness and workspace so later drafts there can show it.
32343
+ */
32344
+ async #inspectLoadedCommands(thread) {
32345
+ if (!thread.session.commands) return null;
32346
+ const catalog = await inspectLiveCommandCatalog(thread.session.commands);
32347
+ if (!catalog) return null;
32348
+ const staticCatalog = this.#externalAdapters.get(thread.harnessId)?.commandCatalog;
32349
+ if (staticCatalog && !isLiveCommandCatalog(catalog, staticCatalog)) return null;
32350
+ const live = { ...catalog, source: "live" };
32351
+ this.#liveCommandCache.remember(thread.harnessId, thread.cwd, live);
32352
+ return live;
32353
+ }
32354
+ async #writeHarnessCommandCatalog(request, harnessId, cwd, inspectedThreadId) {
31829
32355
  await this.#waitForPlugins();
31830
32356
  const adapter = this.#externalAdapters.get(harnessId);
31831
32357
  if (!adapter) {
31832
32358
  await this.#writer.json(rpcError(request, -32077, `Harness '${harnessId}' is unavailable`));
31833
32359
  return;
31834
32360
  }
32361
+ let catalog;
31835
32362
  try {
31836
- const catalog = harnessCommandCatalogSchema.parse(adapter.commandCatalog ?? { commands: [] });
31837
- await this.#writer.json(rpcEnvelope(request, { result: jsonValueSchema.parse(catalog) }));
32363
+ catalog = harnessCommandCatalogSchema.parse({
32364
+ ...adapter.commandCatalog ?? { commands: [] },
32365
+ ...adapter.liveCommandCatalog ? { source: "static" } : {}
32366
+ });
31838
32367
  } catch {
31839
32368
  await this.#writer.json(rpcError(request, -32078, "Harness command catalog is invalid"));
32369
+ return;
32370
+ }
32371
+ if (cwd && adapter.liveCommandCatalog) {
32372
+ for (const thread of this.#externalRuntime.values()) {
32373
+ if (thread.id === inspectedThreadId) continue;
32374
+ if (thread.harnessId !== harnessId || !sameWorkspace(thread.cwd, cwd)) continue;
32375
+ const live = await this.#inspectLoadedCommands(thread);
32376
+ if (live) {
32377
+ catalog = live;
32378
+ break;
32379
+ }
32380
+ }
32381
+ if (catalog.source === "static") {
32382
+ catalog = this.#liveCommandCache.lookup(harnessId, cwd) ?? catalog;
32383
+ }
31840
32384
  }
32385
+ await this.#writer.json(rpcEnvelope(request, { result: jsonValueSchema.parse(catalog) }));
31841
32386
  }
31842
32387
  async #executeThreadCommand(request) {
31843
32388
  const params = threadCommandExecuteParamsSchema.safeParse(request.params);
@@ -31889,39 +32434,43 @@ var AppServerHost = class {
31889
32434
  return;
31890
32435
  }
31891
32436
  try {
31892
- await this.#startExternalCommand(
31893
- request,
32437
+ const started = await this.#beginExternalCommand(
31894
32438
  thread,
31895
32439
  params.commandId,
31896
32440
  params.arguments,
31897
- params.turnId,
31898
- "command"
32441
+ params.turnId
31899
32442
  );
32443
+ try {
32444
+ const result = threadCommandExecuteResultSchema.parse({
32445
+ accepted: true,
32446
+ turnId: started.turnId
32447
+ });
32448
+ await this.#writer.json(rpcEnvelope(request, { result: jsonValueSchema.parse(result) }));
32449
+ } finally {
32450
+ started.gate.resolve();
32451
+ }
31900
32452
  } catch (error51) {
31901
32453
  this.#diagnose(error51);
31902
32454
  await this.#writer.json(
31903
- rpcError(request, -32073, `External Harness command failed: ${errorMessage3(error51)}`)
32455
+ error51 instanceof ExternalCommandError ? rpcError(request, error51.code, error51.message) : rpcError(request, -32073, `External Harness command failed: ${errorMessage3(error51)}`)
31904
32456
  );
31905
32457
  }
31906
32458
  } finally {
31907
32459
  this.#pendingExternalCommandRequests.delete(thread.id);
31908
32460
  }
31909
32461
  }
31910
- async #startExternalCommand(request, thread, commandId, arguments_2, requestedTurnId, responseKind) {
32462
+ async #beginExternalCommand(thread, commandId, arguments_2, requestedTurnId) {
31911
32463
  const commands = thread.session.commands;
31912
32464
  if (!commands) {
31913
- await this.#writer.json(
31914
- rpcError(request, -32078, "External Harness does not expose commands")
31915
- );
31916
- return;
32465
+ throw new ExternalCommandError(-32078, "External Harness does not expose commands");
31917
32466
  }
31918
- if (thread.running || this.#externalSteering.hasPending(thread.id)) {
31919
- await this.#writer.json(
31920
- rpcError(request, -32072, "External Thread already has an active operation")
31921
- );
31922
- return;
32467
+ if (this.#closeRequested || this.#externalRuntime.get(thread.id) !== thread) {
32468
+ throw new ExternalCommandError(-32073, "External Thread is no longer available");
32469
+ }
32470
+ if (thread.running || thread.activeTurnId) {
32471
+ throw new ExternalCommandError(-32072, "External Thread already has an active operation");
31923
32472
  }
31924
- const turnId = requestedTurnId ?? hostTurnIdSchema.parse(randomUUID9());
32473
+ const turnId = requestedTurnId ?? hostTurnIdSchema.parse(randomUUID10());
31925
32474
  const projection = {
31926
32475
  projector: new CodexTurnProjector({
31927
32476
  threadId: thread.id,
@@ -31936,13 +32485,14 @@ var AppServerHost = class {
31936
32485
  thread.projectedTurns.set(turnId, projection);
31937
32486
  thread.responseGates.set(turnId, gate);
31938
32487
  thread.ephemeralTurnIds.add(turnId);
31939
- let result;
31940
32488
  try {
31941
- result = await commands.execute({
32489
+ const result = await commands.execute({
31942
32490
  turnId,
31943
32491
  commandId,
31944
32492
  ...arguments_2 ? { arguments: arguments_2 } : {}
31945
32493
  });
32494
+ if (!result.ok) throw new ExternalCommandError(-32073, result.error.message);
32495
+ return { turnId: result.value.turnId, turn: projection.projector.pendingTurn(), gate };
31946
32496
  } catch (error51) {
31947
32497
  thread.running = false;
31948
32498
  thread.activeTurnId = null;
@@ -31953,28 +32503,6 @@ var AppServerHost = class {
31953
32503
  this.#signalActiveWorkChanged();
31954
32504
  throw error51;
31955
32505
  }
31956
- if (!result.ok) {
31957
- thread.running = false;
31958
- thread.activeTurnId = null;
31959
- thread.projectedTurns.delete(turnId);
31960
- thread.responseGates.delete(turnId);
31961
- thread.ephemeralTurnIds.delete(turnId);
31962
- gate.resolve();
31963
- this.#signalActiveWorkChanged();
31964
- await this.#writer.json(rpcError(request, -32073, result.error.message));
31965
- return;
31966
- }
31967
- try {
31968
- const response = responseKind === "command" ? jsonValueSchema.parse(
31969
- threadCommandExecuteResultSchema.parse({
31970
- accepted: true,
31971
- turnId: result.value.turnId
31972
- })
31973
- ) : { turn: projection.projector.pendingTurn() };
31974
- await this.#writer.json(rpcEnvelope(request, { result: response }));
31975
- } finally {
31976
- gate.resolve();
31977
- }
31978
32506
  }
31979
32507
  async #selectThreadModel(request) {
31980
32508
  const params = threadModelSelectParamsSchema.safeParse(request.params);
@@ -32597,10 +33125,10 @@ var AppServerHost = class {
32597
33125
  ...typeof params.serviceTier === "string" ? { serviceTier: params.serviceTier } : {}
32598
33126
  });
32599
33127
  try {
32600
- if (params.initialTurnsPage !== void 0 && params.initialTurnsPage !== null && !isRecord13(params.initialTurnsPage)) {
33128
+ if (params.initialTurnsPage !== void 0 && params.initialTurnsPage !== null && !isRecord14(params.initialTurnsPage)) {
32601
33129
  throw new ExternalHistoryRequestError("initialTurnsPage must be an object");
32602
33130
  }
32603
- const initialPageParams = isRecord13(params.initialTurnsPage) ? params.initialTurnsPage : null;
33131
+ const initialPageParams = isRecord14(params.initialTurnsPage) ? params.initialTurnsPage : null;
32604
33132
  const initialTurnsPage = initialPageParams ? listExternalTurns(turns, initialPageParams) : null;
32605
33133
  const paginated = thread.record.historyMode === "paginated";
32606
33134
  const turnsBackwardsCursor = paginated ? listExternalTurns(turns, { limit: 1, itemsView: "notLoaded" }).backwardsCursor : null;
@@ -32695,53 +33223,8 @@ var AppServerHost = class {
32695
33223
  await this.#writer.json(rpcError(request, -32602, errorMessage3(error51)));
32696
33224
  return;
32697
33225
  }
32698
- const commandCandidate = text.trimStart();
32699
- if (thread.session.commands && /^\/[^\s/]+(?:\s|$)/u.test(commandCandidate)) {
32700
- const commandText = commandCandidate.trimEnd();
32701
- this.#pendingExternalCommandRequests.add(thread.id);
32702
- try {
32703
- const catalog = await thread.session.commands.list();
32704
- if (!catalog.ok) {
32705
- await this.#writer.json(rpcError(request, -32073, catalog.error.message));
32706
- return;
32707
- }
32708
- const matched = catalog.value.commands.toSorted((left, right) => right.invocation.length - left.invocation.length).find((command) => {
32709
- if (commandText === command.invocation) return true;
32710
- return command.argumentMode === "text" && commandText.startsWith(`${command.invocation} `);
32711
- });
32712
- if (matched) {
32713
- const argumentText = commandText.slice(matched.invocation.length).trimStart();
32714
- try {
32715
- await this.#startExternalCommand(
32716
- request,
32717
- thread,
32718
- matched.id,
32719
- argumentText.length > 0 ? { text: argumentText } : void 0,
32720
- void 0,
32721
- "turn"
32722
- );
32723
- } catch (error51) {
32724
- this.#diagnose(error51);
32725
- await this.#writer.json(
32726
- rpcError(request, -32073, `External Harness command failed: ${errorMessage3(error51)}`)
32727
- );
32728
- }
32729
- return;
32730
- }
32731
- await this.#writer.json(
32732
- rpcError(request, -32078, "External Harness does not expose the requested command")
32733
- );
32734
- return;
32735
- } finally {
32736
- this.#pendingExternalCommandRequests.delete(thread.id);
32737
- }
32738
- }
32739
- if (this.#externalSteering.hasPending(thread.id)) {
32740
- await this.#writer.json(rpcError(request, -32072, "External Thread is changing direction"));
32741
- return;
32742
- }
32743
33226
  try {
32744
- const started = await this.#beginExternalTurn(thread, text);
33227
+ const started = await this.#beginExternalInputTurn(thread, text);
32745
33228
  try {
32746
33229
  await this.#writer.json(rpcEnvelope(request, { result: { turn: started.turn } }));
32747
33230
  } finally {
@@ -32751,7 +33234,7 @@ var AppServerHost = class {
32751
33234
  await this.#writer.json(
32752
33235
  rpcError(
32753
33236
  request,
32754
- error51 instanceof ExternalSteerError ? error51.code : -32073,
33237
+ error51 instanceof ExternalSteerError || error51 instanceof ExternalCommandError ? error51.code : -32073,
32755
33238
  errorMessage3(error51)
32756
33239
  )
32757
33240
  );
@@ -32762,7 +33245,7 @@ var AppServerHost = class {
32762
33245
  const started = await this.#externalSteering.run(
32763
33246
  thread,
32764
33247
  requestObject(request),
32765
- (text) => this.#beginExternalTurn(thread, text)
33248
+ (text, assertActive) => this.#beginExternalInputTurn(thread, text, assertActive)
32766
33249
  );
32767
33250
  try {
32768
33251
  await this.#writer.json(rpcEnvelope(request, { result: { turnId: started.turnId } }));
@@ -32773,7 +33256,7 @@ var AppServerHost = class {
32773
33256
  await this.#writer.json(
32774
33257
  rpcError(
32775
33258
  request,
32776
- error51 instanceof ExternalSteerError ? error51.code : -32074,
33259
+ error51 instanceof ExternalSteerError || error51 instanceof ExternalCommandError ? error51.code : -32074,
32777
33260
  errorMessage3(error51)
32778
33261
  )
32779
33262
  );
@@ -32781,6 +33264,37 @@ var AppServerHost = class {
32781
33264
  this.#signalActiveWorkChanged();
32782
33265
  }
32783
33266
  }
33267
+ /** Keep command restoration and dispatch identical for start and steer submissions. */
33268
+ async #beginExternalInputTurn(thread, inputText, assertActive) {
33269
+ const text = restoreHarnessCommandMentions(inputText);
33270
+ const commands = thread.session.commands;
33271
+ if (!commands || !isExternalCommandCandidate(text)) {
33272
+ assertActive?.();
33273
+ return this.#beginExternalTurn(thread, text);
33274
+ }
33275
+ this.#pendingExternalCommandRequests.add(thread.id);
33276
+ try {
33277
+ const adapter = this.#externalAdapters.get(thread.harnessId);
33278
+ const command = await resolveExternalCommand(commands, text, {
33279
+ liveCatalogPending: (catalog) => adapter?.liveCommandCatalog === true && !isLiveCommandCatalog(catalog, adapter.commandCatalog ?? { commands: [] })
33280
+ });
33281
+ assertActive?.();
33282
+ if (!command) {
33283
+ this.#pendingExternalCommandRequests.delete(thread.id);
33284
+ return await this.#beginExternalTurn(thread, text);
33285
+ }
33286
+ return await this.#beginExternalCommand(thread, command.commandId, command.arguments);
33287
+ } catch (error51) {
33288
+ if (error51 instanceof ExternalCommandError || error51 instanceof ExternalSteerError) throw error51;
33289
+ this.#diagnose(error51);
33290
+ throw new ExternalCommandError(
33291
+ -32073,
33292
+ `External Harness command failed: ${errorMessage3(error51)}`
33293
+ );
33294
+ } finally {
33295
+ this.#pendingExternalCommandRequests.delete(thread.id);
33296
+ }
33297
+ }
32784
33298
  async #beginExternalTurn(thread, text) {
32785
33299
  if (this.#closeRequested || this.#externalRuntime.get(thread.id) !== thread) {
32786
33300
  throw new ExternalSteerError(-32073, "External Thread is no longer available");
@@ -32788,7 +33302,7 @@ var AppServerHost = class {
32788
33302
  if (thread.running || thread.activeTurnId || this.#pendingExternalCommandRequests.has(thread.id)) {
32789
33303
  throw new ExternalSteerError(-32072, "External Thread already has an active Turn");
32790
33304
  }
32791
- const turnId = hostTurnIdSchema.parse(randomUUID9());
33305
+ const turnId = hostTurnIdSchema.parse(randomUUID10());
32792
33306
  const startedAtMs = Date.now();
32793
33307
  const projection = {
32794
33308
  projector: new CodexTurnProjector({
@@ -32807,7 +33321,7 @@ var AppServerHost = class {
32807
33321
  const result = await thread.session.execute({
32808
33322
  type: "turn.start",
32809
33323
  turnId,
32810
- input: [{ type: "text", text }]
33324
+ input: [{ type: "text", text: rewriteDelegationMentionText(text) }]
32811
33325
  });
32812
33326
  if (!result.ok) throw new ExternalSteerError(-32073, result.error.message);
32813
33327
  return { turnId, turn: projection.projector.pendingTurn(), gate };
@@ -33109,7 +33623,7 @@ var AppServerHost = class {
33109
33623
  const previousItems = new Map(
33110
33624
  child.turns.flatMap(
33111
33625
  (turn) => Array.isArray(turn.items) ? turn.items.flatMap(
33112
- (item) => isRecord13(item) && typeof item.id === "string" ? [[item.id, JSON.stringify(item)]] : []
33626
+ (item) => isRecord14(item) && typeof item.id === "string" ? [[item.id, JSON.stringify(item)]] : []
33113
33627
  ) : []
33114
33628
  )
33115
33629
  );
@@ -33122,7 +33636,7 @@ var AppServerHost = class {
33122
33636
  for (const turn of child.turns) {
33123
33637
  if (typeof turn.id !== "string" || !Array.isArray(turn.items)) continue;
33124
33638
  const changedItems = turn.items.filter(
33125
- (item) => isRecord13(item) && typeof item.id === "string" && previousItems.get(item.id) !== JSON.stringify(item)
33639
+ (item) => isRecord14(item) && typeof item.id === "string" && previousItems.get(item.id) !== JSON.stringify(item)
33126
33640
  );
33127
33641
  if (changedItems.length > 0) {
33128
33642
  await this.#writer.json({
@@ -33254,7 +33768,7 @@ var AppServerHost = class {
33254
33768
  }
33255
33769
  }
33256
33770
  async #handleDesktopApprovalResponse(value2) {
33257
- if (!isRecord13(value2) || !isHostApprovalRequestId(value2.id)) return false;
33771
+ if (!isRecord14(value2) || !isHostApprovalRequestId(value2.id)) return false;
33258
33772
  const requestId = value2.id;
33259
33773
  const pending = this.#pendingDesktopApprovals.get(requestId);
33260
33774
  if (!pending) return true;
@@ -33336,7 +33850,7 @@ var AppServerHost = class {
33336
33850
  try {
33337
33851
  result = projection.projector.projectQuestion(
33338
33852
  interaction,
33339
- hostItemIdSchema.parse(randomUUID9())
33853
+ hostItemIdSchema.parse(randomUUID10())
33340
33854
  );
33341
33855
  } catch (error51) {
33342
33856
  this.#diagnose(error51);
@@ -33381,7 +33895,7 @@ var AppServerHost = class {
33381
33895
  }
33382
33896
  }
33383
33897
  async #handleDesktopQuestionResponse(value2) {
33384
- if (!isRecord13(value2) || !isHostQuestionRequestId(value2.id)) return false;
33898
+ if (!isRecord14(value2) || !isHostQuestionRequestId(value2.id)) return false;
33385
33899
  const requestId = value2.id;
33386
33900
  const pending = this.#pendingDesktopQuestions.get(requestId);
33387
33901
  if (!pending) return true;
@@ -33502,19 +34016,19 @@ var AppServerHost = class {
33502
34016
  };
33503
34017
 
33504
34018
  // packages/host-runtime/src/native-account-host.ts
33505
- import { mkdir as mkdir7, realpath as realpath3 } from "node:fs/promises";
34019
+ import { mkdir as mkdir8, realpath as realpath3 } from "node:fs/promises";
33506
34020
  import { homedir } from "node:os";
33507
- import path17 from "node:path";
34021
+ import path20 from "node:path";
33508
34022
 
33509
34023
  // packages/host-runtime/src/codex-runtime/owned-official-backends.ts
33510
- import { createHash as createHash8, randomBytes } from "node:crypto";
34024
+ import { createHash as createHash9, randomBytes } from "node:crypto";
33511
34025
  import { Writable as Writable2 } from "node:stream";
33512
34026
 
33513
34027
  // packages/host-runtime/src/remote-app-server.ts
33514
34028
  import { createServer } from "node:http";
33515
34029
  import net from "node:net";
33516
- import { chmod as chmod3, lstat as lstat6, mkdir as mkdir6, rm as rm6 } from "node:fs/promises";
33517
- import path15 from "node:path";
34030
+ import { chmod as chmod3, lstat as lstat6, mkdir as mkdir7, rm as rm7 } from "node:fs/promises";
34031
+ import path18 from "node:path";
33518
34032
  import { PassThrough } from "node:stream";
33519
34033
 
33520
34034
  // node_modules/ws/wrapper.mjs
@@ -33529,10 +34043,10 @@ var import_websocket_server = __toESM(require_websocket_server(), 1);
33529
34043
  var wrapper_default = import_websocket.default;
33530
34044
 
33531
34045
  // packages/host-runtime/src/remote-socket-lock.ts
33532
- import { randomUUID as randomUUID10 } from "node:crypto";
33533
- import { chmod as chmod2, lstat as lstat5, mkdir as mkdir5, open as open5, readFile as readFile7, readdir as readdir4, rename as rename4, rm as rm5 } from "node:fs/promises";
34046
+ import { randomUUID as randomUUID11 } from "node:crypto";
34047
+ import { chmod as chmod2, lstat as lstat5, mkdir as mkdir6, open as open6, readFile as readFile8, readdir as readdir4, rename as rename5, rm as rm6 } from "node:fs/promises";
33534
34048
  import { uptime } from "node:os";
33535
- import path14 from "node:path";
34049
+ import path17 from "node:path";
33536
34050
  import { setTimeout as delay4 } from "node:timers/promises";
33537
34051
  var LOCK_RETRY_COUNT = 200;
33538
34052
  var LOCK_RETRY_DELAY_MS = 25;
@@ -33595,7 +34109,7 @@ async function readLockEntrySnapshot(filePath) {
33595
34109
  throw error51;
33596
34110
  });
33597
34111
  if (metadata === null || !metadata.isFile()) return null;
33598
- const source = await readFile7(filePath, "utf8").catch((error51) => {
34112
+ const source = await readFile8(filePath, "utf8").catch((error51) => {
33599
34113
  if (error51.code === "ENOENT") return null;
33600
34114
  throw error51;
33601
34115
  });
@@ -33606,7 +34120,7 @@ async function readLockEntrySnapshot(filePath) {
33606
34120
  source,
33607
34121
  identity: { dev: metadata.dev, ino: metadata.ino },
33608
34122
  mtimeMs: metadata.mtimeMs,
33609
- record: record3 && path14.basename(filePath) === lockEntryName(record3.ownerToken) ? record3 : null
34123
+ record: record3 && path17.basename(filePath) === lockEntryName(record3.ownerToken) ? record3 : null
33610
34124
  };
33611
34125
  }
33612
34126
  function lockEntryIsAbandoned(snapshot) {
@@ -33618,7 +34132,7 @@ async function removeAbandonedLockEntry(snapshot) {
33618
34132
  if (current === null || current.source !== snapshot.source || !sameUnixFileIdentity(current.identity, snapshot.identity) || !lockEntryIsAbandoned(current)) {
33619
34133
  return false;
33620
34134
  }
33621
- await rm5(snapshot.filePath, { force: true });
34135
+ await rm6(snapshot.filePath, { force: true });
33622
34136
  return true;
33623
34137
  }
33624
34138
  async function readLockEntryCatalog(lockDirectory) {
@@ -33627,7 +34141,7 @@ async function readLockEntryCatalog(lockDirectory) {
33627
34141
  let unsettled = false;
33628
34142
  for (const name of names) {
33629
34143
  if (!name.startsWith(LOCK_ENTRY_PREFIX) || !name.endsWith(LOCK_ENTRY_SUFFIX)) continue;
33630
- const snapshot = await readLockEntrySnapshot(path14.join(lockDirectory, name));
34144
+ const snapshot = await readLockEntrySnapshot(path17.join(lockDirectory, name));
33631
34145
  if (snapshot === null) continue;
33632
34146
  if (lockEntryIsAbandoned(snapshot)) {
33633
34147
  if (!await removeAbandonedLockEntry(snapshot)) unsettled = true;
@@ -33642,7 +34156,7 @@ async function readLockEntryCatalog(lockDirectory) {
33642
34156
  return { entries, unsettled };
33643
34157
  }
33644
34158
  async function preparePrivateLockDirectory(lockDirectory) {
33645
- await mkdir5(lockDirectory, { mode: 448 }).catch((error51) => {
34159
+ await mkdir6(lockDirectory, { mode: 448 }).catch((error51) => {
33646
34160
  if (error51.code !== "EEXIST") throw error51;
33647
34161
  });
33648
34162
  const metadata = await lstat5(lockDirectory);
@@ -33655,8 +34169,8 @@ async function preparePrivateLockDirectory(lockDirectory) {
33655
34169
  await chmod2(lockDirectory, 448);
33656
34170
  }
33657
34171
  async function writeLockRecordAtomic(lockDirectory, entryPath, record3) {
33658
- const temporary = path14.join(lockDirectory, `.tmp-${record3.ownerToken}-${randomUUID10()}`);
33659
- const handle = await open5(temporary, "wx", 384);
34172
+ const temporary = path17.join(lockDirectory, `.tmp-${record3.ownerToken}-${randomUUID11()}`);
34173
+ const handle = await open6(temporary, "wx", 384);
33660
34174
  try {
33661
34175
  await handle.writeFile(`${JSON.stringify(record3)}
33662
34176
  `, "utf8");
@@ -33665,15 +34179,15 @@ async function writeLockRecordAtomic(lockDirectory, entryPath, record3) {
33665
34179
  await handle.close();
33666
34180
  }
33667
34181
  try {
33668
- await rename4(temporary, entryPath);
34182
+ await rename5(temporary, entryPath);
33669
34183
  } finally {
33670
- await rm5(temporary, { force: true });
34184
+ await rm6(temporary, { force: true });
33671
34185
  }
33672
34186
  }
33673
34187
  async function removeOwnedLockEntry(entryPath, ownerToken) {
33674
34188
  const snapshot = await readLockEntrySnapshot(entryPath);
33675
34189
  if (snapshot?.record?.ownerToken !== ownerToken) return;
33676
- await rm5(entryPath, { force: true });
34190
+ await rm6(entryPath, { force: true });
33677
34191
  }
33678
34192
  async function legacyLockState(legacyPath) {
33679
34193
  const metadata = await lstat5(legacyPath).catch((error51) => {
@@ -33682,7 +34196,7 @@ async function legacyLockState(legacyPath) {
33682
34196
  });
33683
34197
  if (metadata === null) return "absent";
33684
34198
  if (!metadata.isFile()) return "blocking";
33685
- const source = await readFile7(legacyPath, "utf8").catch((error51) => {
34199
+ const source = await readFile8(legacyPath, "utf8").catch((error51) => {
33686
34200
  if (error51.code === "ENOENT") return null;
33687
34201
  throw error51;
33688
34202
  });
@@ -33693,7 +34207,7 @@ async function legacyLockState(legacyPath) {
33693
34207
  return ownerIsAbandoned(record3, metadata.mtimeMs) ? "abandoned" : "blocking";
33694
34208
  }
33695
34209
  async function tryAcquireLegacyCompatibilityGuard(legacyPath, record3) {
33696
- const handle = await open5(legacyPath, "wx", 384).catch((error51) => {
34210
+ const handle = await open6(legacyPath, "wx", 384).catch((error51) => {
33697
34211
  if (error51.code === "EEXIST") return null;
33698
34212
  throw error51;
33699
34213
  });
@@ -33719,7 +34233,7 @@ async function releaseLegacyCompatibilityGuard(legacyPath, guard) {
33719
34233
  throw error51;
33720
34234
  });
33721
34235
  if (metadata?.isFile() && sameUnixFileIdentity({ dev: metadata.dev, ino: metadata.ino }, guard.identity)) {
33722
- await rm5(legacyPath, { force: true });
34236
+ await rm6(legacyPath, { force: true });
33723
34237
  }
33724
34238
  }
33725
34239
  }
@@ -33730,8 +34244,8 @@ async function withRemoteAppServerSocketInitializationLock(socketPath, action) {
33730
34244
  const legacyPath = `${socketPath}.initializing`;
33731
34245
  const lockDirectory = `${socketPath}.initializers`;
33732
34246
  await preparePrivateLockDirectory(lockDirectory);
33733
- const ownerToken = randomUUID10();
33734
- const entryPath = path14.join(lockDirectory, lockEntryName(ownerToken));
34247
+ const ownerToken = randomUUID11();
34248
+ const entryPath = path17.join(lockDirectory, lockEntryName(ownerToken));
33735
34249
  const baseRecord = {
33736
34250
  version: 2,
33737
34251
  ownerToken,
@@ -33905,14 +34419,14 @@ function remoteAppServerSocketPath(environment, listenUrl = "unix://") {
33905
34419
  throw new Error("Remote app-server listener must use a Unix URL");
33906
34420
  }
33907
34421
  const explicit = listenUrl.slice("unix://".length);
33908
- if (explicit.length > 0) return path15.posix.resolve(decodeURIComponent(explicit));
33909
- const codexHome = environment.CODEX_HOME ?? (environment.HOME ? path15.posix.join(environment.HOME, ".codex") : void 0);
34422
+ if (explicit.length > 0) return path18.posix.resolve(decodeURIComponent(explicit));
34423
+ const codexHome = environment.CODEX_HOME ?? (environment.HOME ? path18.posix.join(environment.HOME, ".codex") : void 0);
33910
34424
  if (!codexHome)
33911
34425
  throw new Error("CODEX_HOME or HOME is required for the remote app-server socket");
33912
- return path15.posix.join(codexHome, "app-server-control", "app-server-control.sock");
34426
+ return path18.posix.join(codexHome, "app-server-control", "app-server-control.sock");
33913
34427
  }
33914
34428
  function officialListenerArgumentsForRemoteListener(arguments_2, socketPath) {
33915
- if (!path15.posix.isAbsolute(socketPath)) {
34429
+ if (!path18.posix.isAbsolute(socketPath)) {
33916
34430
  throw new Error("Shared official app-server socket path must be absolute");
33917
34431
  }
33918
34432
  if (remoteUnixListenerUrl(arguments_2) === null) {
@@ -34020,10 +34534,10 @@ async function removeStaleSocket(socketPath) {
34020
34534
  });
34021
34535
  });
34022
34536
  if (active) throw new Error(`Remote app-server socket is already in use at ${socketPath}`);
34023
- await rm6(socketPath, { force: true });
34537
+ await rm7(socketPath, { force: true });
34024
34538
  }
34025
34539
  async function prepareRemoteAppServerSocketDirectory(socketPath) {
34026
- const socketDirectory = path15.dirname(socketPath);
34540
+ const socketDirectory = path18.dirname(socketPath);
34027
34541
  const existing = await lstat6(socketDirectory).catch((error51) => {
34028
34542
  if (error51.code === "ENOENT") return null;
34029
34543
  throw error51;
@@ -34037,7 +34551,7 @@ async function prepareRemoteAppServerSocketDirectory(socketPath) {
34037
34551
  );
34038
34552
  }
34039
34553
  }
34040
- await mkdir6(socketDirectory, { recursive: true, mode: 448 });
34554
+ await mkdir7(socketDirectory, { recursive: true, mode: 448 });
34041
34555
  await chmod3(socketDirectory, 448);
34042
34556
  }
34043
34557
  function sendOutputFrames(socket, output) {
@@ -34210,7 +34724,7 @@ function createRemoteAppServerWebSocketListener(input) {
34210
34724
  if (ownedSocketIdentity) {
34211
34725
  const current = await unixSocketIdentity(input.socketPath);
34212
34726
  if (current && sameUnixFileIdentity2(current, ownedSocketIdentity)) {
34213
- await rm6(input.socketPath, { force: true });
34727
+ await rm7(input.socketPath, { force: true });
34214
34728
  }
34215
34729
  ownedSocketIdentity = null;
34216
34730
  }
@@ -34228,39 +34742,57 @@ function createRemoteAppServerWebSocketListener(input) {
34228
34742
 
34229
34743
  // packages/host-runtime/src/remote-official-app-server.ts
34230
34744
  import { spawn as spawn3 } from "node:child_process";
34231
- import { randomUUID as randomUUID11 } from "node:crypto";
34232
- import { lstat as lstat7, rm as rm7 } from "node:fs/promises";
34233
- import path16 from "node:path";
34745
+ import { randomUUID as randomUUID12 } from "node:crypto";
34746
+ import { lstat as lstat7, rm as rm8, stat as stat5 } from "node:fs/promises";
34747
+ import path19 from "node:path";
34234
34748
  var DEFAULT_CLOSE_TIMEOUT_MS = 2e3;
34235
34749
  var DEFAULT_LISTEN_TIMEOUT_MS = 1e4;
34236
- function remoteOfficialAppServerSocketPath(desktopControlSocketPath, token = randomUUID11()) {
34237
- if (!path16.posix.isAbsolute(desktopControlSocketPath)) {
34750
+ function remoteOfficialAppServerSocketPath(desktopControlSocketPath, token = randomUUID12()) {
34751
+ if (!path19.posix.isAbsolute(desktopControlSocketPath)) {
34238
34752
  throw new Error("Desktop control socket path must be absolute");
34239
34753
  }
34240
34754
  if (!/^[A-Za-z0-9-]+$/u.test(token) || !/[A-Za-z0-9]/u.test(token)) {
34241
34755
  throw new Error("Shared official app-server socket token is invalid");
34242
34756
  }
34243
34757
  const compactToken = token.replaceAll("-", "").slice(0, 15);
34244
- return path16.posix.join(path16.posix.dirname(desktopControlSocketPath), `.c-${compactToken}.sock`);
34758
+ return path19.posix.join(path19.posix.dirname(desktopControlSocketPath), `.c-${compactToken}.sock`);
34245
34759
  }
34246
34760
  function errorMessage4(error51) {
34247
34761
  return error51 instanceof Error ? error51.message : String(error51);
34248
34762
  }
34249
- async function socketIdentity(socketPath) {
34763
+ async function inspectSocket(socketPath) {
34250
34764
  const metadata = await lstat7(socketPath).catch((error51) => {
34251
34765
  if (error51.code === "ENOENT") return null;
34252
34766
  throw error51;
34253
34767
  });
34254
34768
  if (metadata === null) return null;
34255
- if (!metadata.isSocket()) {
34769
+ const identity = { dev: metadata.dev, ino: metadata.ino };
34770
+ if (metadata.isSymbolicLink()) {
34771
+ const uid = process.getuid?.();
34772
+ if (uid === void 0 || metadata.uid !== uid) {
34773
+ throw new Error(
34774
+ `Shared official app-server link must belong to the current user: ${socketPath}`
34775
+ );
34776
+ }
34777
+ const target = await stat5(socketPath).catch((error51) => {
34778
+ if (error51.code === "ENOENT") return null;
34779
+ throw error51;
34780
+ });
34781
+ if (target === null) return { identity, ready: false };
34782
+ if (target.uid !== uid || !target.isSocket() || (target.mode & 63) !== 0) {
34783
+ throw new Error(
34784
+ `Shared official app-server link must target a current-user private socket: ${socketPath}`
34785
+ );
34786
+ }
34787
+ } else if (!metadata.isSocket()) {
34256
34788
  throw new Error(`Shared official app-server path is not a socket: ${socketPath}`);
34257
34789
  }
34258
- return { dev: metadata.dev, ino: metadata.ino };
34790
+ return { identity, ready: true };
34259
34791
  }
34260
34792
  function sameUnixFileIdentity3(left, right) {
34261
34793
  return left.dev === right.dev && left.ino === right.ino;
34262
34794
  }
34263
- async function waitForOfficialSocket(socketPath, closed) {
34795
+ async function waitForOfficialSocket(socketPath, closed, onIdentity) {
34264
34796
  const deadline = Date.now() + 1e4;
34265
34797
  const state = { exit: null };
34266
34798
  void closed.then((value2) => {
@@ -34273,14 +34805,20 @@ async function waitForOfficialSocket(socketPath, closed) {
34273
34805
  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)})`
34274
34806
  );
34275
34807
  }
34276
- if (await socketIdentity(socketPath) !== null) return;
34808
+ const socket = await inspectSocket(socketPath);
34809
+ if (socket !== null) {
34810
+ onIdentity(socket.identity);
34811
+ if (socket.ready) return;
34812
+ }
34277
34813
  await new Promise((resolve) => setTimeout(resolve, 25));
34278
34814
  }
34279
34815
  throw new Error(`Shared official app-server socket was not ready after 10000ms: ${socketPath}`);
34280
34816
  }
34281
34817
  function createRemoteOfficialAppServerListener(input) {
34282
34818
  const spawnOfficial = input.spawnOfficial ?? spawn3;
34283
- const waitUntilReady = input.waitUntilReady ?? waitForOfficialSocket;
34819
+ const waitUntilReady = input.waitUntilReady ?? ((socketPath, closed2) => waitForOfficialSocket(socketPath, closed2, (identity) => {
34820
+ ownedSocketIdentity ??= identity;
34821
+ }));
34284
34822
  const closeTimeoutMs = input.closeTimeoutMs ?? DEFAULT_CLOSE_TIMEOUT_MS;
34285
34823
  const closed = Promise.withResolvers();
34286
34824
  let child = null;
@@ -34311,9 +34849,9 @@ function createRemoteOfficialAppServerListener(input) {
34311
34849
  };
34312
34850
  const removeOwnedSocket = async () => {
34313
34851
  if (ownedSocketIdentity === null) return;
34314
- const current = await socketIdentity(input.socketPath).catch(() => null);
34852
+ const current = await lstat7(input.socketPath).catch(() => null);
34315
34853
  if (current && sameUnixFileIdentity3(current, ownedSocketIdentity)) {
34316
- await rm7(input.socketPath, { force: true });
34854
+ await rm8(input.socketPath, { force: true });
34317
34855
  }
34318
34856
  ownedSocketIdentity = null;
34319
34857
  };
@@ -34337,7 +34875,7 @@ function createRemoteOfficialAppServerListener(input) {
34337
34875
  spawned.stderr?.pipe(input.diagnosticOutput, { end: false });
34338
34876
  try {
34339
34877
  await waitUntilReady(input.socketPath, closed.promise);
34340
- ownedSocketIdentity = await socketIdentity(input.socketPath).catch(() => null);
34878
+ ownedSocketIdentity ??= (await inspectSocket(input.socketPath).catch(() => null))?.identity ?? null;
34341
34879
  } catch (error51) {
34342
34880
  let stopFailed = false;
34343
34881
  try {
@@ -34345,7 +34883,7 @@ function createRemoteOfficialAppServerListener(input) {
34345
34883
  } catch {
34346
34884
  stopFailed = true;
34347
34885
  }
34348
- ownedSocketIdentity ??= await socketIdentity(input.socketPath).catch(() => null);
34886
+ ownedSocketIdentity ??= (await inspectSocket(input.socketPath).catch(() => null))?.identity ?? null;
34349
34887
  if (!stopFailed) await removeOwnedSocket();
34350
34888
  throw new Error(`Shared official app-server startup failed: ${errorMessage4(error51)}`);
34351
34889
  }
@@ -34674,7 +35212,7 @@ function createOwnedLoopbackBackend(input) {
34674
35212
  "--ws-auth",
34675
35213
  "capability-token",
34676
35214
  "--ws-token-sha256",
34677
- createHash8("sha256").update(capabilityToken).digest("hex")
35215
+ createHash9("sha256").update(capabilityToken).digest("hex")
34678
35216
  ],
34679
35217
  // Managed stderr may carry credential-bearing errors. Never forward raw bytes.
34680
35218
  diagnosticOutput: new Writable2({
@@ -34727,21 +35265,21 @@ function createOwnedUnixBackend(input) {
34727
35265
 
34728
35266
  // packages/host-runtime/src/native-account-host.ts
34729
35267
  async function canonicalCodexHome(home) {
34730
- const absolute = path17.resolve(home);
35268
+ const absolute = path20.resolve(home);
34731
35269
  try {
34732
35270
  return await realpath3(absolute);
34733
35271
  } catch (error51) {
34734
35272
  if (!(error51 instanceof Error && "code" in error51 && error51.code === "ENOENT")) throw error51;
34735
- const parent = path17.dirname(absolute);
35273
+ const parent = path20.dirname(absolute);
34736
35274
  if (parent === absolute) throw error51;
34737
- return path17.join(await canonicalCodexHome(parent), path17.basename(absolute));
35275
+ return path20.join(await canonicalCodexHome(parent), path20.basename(absolute));
34738
35276
  }
34739
35277
  }
34740
35278
  async function prepareLocalCodex(input) {
34741
35279
  const home = await canonicalCodexHome(
34742
- input.environment.CODEX_HOME ?? path17.join(homedir(), ".codex")
35280
+ input.environment.CODEX_HOME ?? path20.join(homedir(), ".codex")
34743
35281
  );
34744
- await mkdir7(home, { recursive: true });
35282
+ await mkdir8(home, { recursive: true });
34745
35283
  const scope = new OfficialRuntimeScope({
34746
35284
  permanentHome: home,
34747
35285
  diagnosticOutput: input.diagnosticOutput,
@@ -34905,18 +35443,18 @@ var DelegationControlRegistry = class {
34905
35443
  };
34906
35444
 
34907
35445
  // packages/host-runtime/src/installed-harness-plugins.ts
34908
- import os5 from "node:os";
34909
- import path19 from "node:path";
35446
+ import os6 from "node:os";
35447
+ import path22 from "node:path";
34910
35448
  import { fileURLToPath } from "node:url";
34911
35449
 
34912
35450
  // packages/host-runtime/src/launcher-url-opener.ts
34913
35451
  import { spawn as spawn4 } from "node:child_process";
34914
- import path18 from "node:path";
35452
+ import path21 from "node:path";
34915
35453
  var LOOPBACK_HOSTS = /* @__PURE__ */ new Set(["127.0.0.1", "localhost", "[::1]"]);
34916
35454
  var OPEN_TIMEOUT_MS = 1e4;
34917
35455
  function createLauncherUrlOpener(environment, spawnLauncher = (command, arguments_2, options2) => spawn4(command, arguments_2, options2)) {
34918
35456
  const launcher = environment.CODEXHOST_LAUNCHER_EXECUTABLE;
34919
- if (!launcher || !path18.isAbsolute(launcher)) return void 0;
35457
+ if (!launcher || !path21.isAbsolute(launcher)) return void 0;
34920
35458
  const launcherEnvironment = Object.fromEntries(
34921
35459
  Object.entries(environment).filter(([name]) => {
34922
35460
  const normalized = name.toUpperCase();
@@ -34974,9 +35512,9 @@ function installedHarnessPluginOptions(environment, managedRemoteHost = false, h
34974
35512
  const opener = managedRemoteHost ? void 0 : createLauncherUrlOpener(environment);
34975
35513
  return {
34976
35514
  pluginRoots: [
34977
- path19.join(path19.dirname(fileURLToPath(hostRuntimeUrl)), "plugins"),
34978
- environment[HARNESS_PLUGIN_DIRECTORY_ENV] ?? path19.join(
34979
- environment.CODEXHOST_DATA_DIR ? path19.resolve(environment.CODEXHOST_DATA_DIR) : path19.join(os5.homedir(), ".codexhost"),
35515
+ path22.join(path22.dirname(fileURLToPath(hostRuntimeUrl)), "plugins"),
35516
+ environment[HARNESS_PLUGIN_DIRECTORY_ENV] ?? path22.join(
35517
+ environment.CODEXHOST_DATA_DIR ? path22.resolve(environment.CODEXHOST_DATA_DIR) : path22.join(os6.homedir(), ".codexhost"),
34980
35518
  "plugins"
34981
35519
  )
34982
35520
  ],
@@ -35100,171 +35638,10 @@ async function startDelegationControlServer(input) {
35100
35638
  };
35101
35639
  }
35102
35640
 
35103
- // packages/host-runtime/src/delegation-skill.ts
35104
- import { createHash as createHash9, randomUUID as randomUUID12 } from "node:crypto";
35105
- import { mkdir as mkdir8, open as open6, readFile as readFile8, rename as rename5, rm as rm8, stat as stat4 } from "node:fs/promises";
35106
- import os6 from "node:os";
35107
- import path20 from "node:path";
35108
- var SKILL_VERSION = 7;
35109
- var SKILL_RELATIVE_PATH = path20.join("skills", "codexhost-delegation", "SKILL.md");
35110
- var PREVIOUS_MANAGED_DIGESTS = [
35111
- "9d2f491850fb0b4084a31ba9b5e4a550b5e833747af322090d8ed0ff80b88c30",
35112
- "2bb0aebb9b06febbc6c0c0bcdb0b32506c7cdbf8dc3b734cc6b2a86621270e4e",
35113
- "aff258622dc8ff321f32b15620d081e578cb9c9ed1134d6a57f35ca8e7762c0a",
35114
- "ba509f57e5448e796b3dfdd5031dcb08672eded50b61c0a54de84cfa02c49dd3",
35115
- "d3ddf6db9bc5c5df825479c885bbbf0ca08da66f7057a12e02e1fdf57525149e",
35116
- "15eb63519ff867e1536c97188a0c43738d7a49d38d4d6adeb7a1036726e7246d"
35117
- ];
35118
- var CODEXHOST_DELEGATION_SKILL = `---
35119
- name: codexhost-delegation
35120
- version: ${SKILL_VERSION}
35121
- description: >
35122
- Delegate tasks to other coding agents, or read and follow up on existing
35123
- external agent sessions. Use when the user asks another agent (including
35124
- @agent) to independently perform a task, or asks to view a specified external
35125
- session's content, progress, or results, send follow-up messages, wait, or
35126
- cancel a task. Not for recapping the current conversation, discussing or
35127
- configuring agents, or role-playing.
35128
- ---
35129
-
35130
- # Execute the task
35131
-
35132
- Before acting, run:
35133
-
35134
- \`codexhost delegate --help\`
35135
-
35136
- Use CLI help as the authoritative source for commands and behavior. Consult
35137
- command-specific help for options and the Harness listing command when the
35138
- target is unknown. Prefer compact output when supported, and use its task links
35139
- directly for subsequent commands.
35140
-
35141
- Use the Harness native defaults. Inspect the target when a Model or Thinking
35142
- selection is needed or the default is unavailable.
35143
-
35144
- For a new delegation, create an independent child session and submit the
35145
- requested task. For an existing external session, resolve the target from the
35146
- user-provided session link, identifier, or context and operate on that Thread
35147
- directly; it need not have been created by the current assistant. If the target
35148
- is ambiguous, ask the user to identify it. Keep requests to view or summarize a
35149
- session read-only.
35150
-
35151
- For a new or existing task, choose the appropriate next action based on the
35152
- user’s request and the task:
35153
-
35154
- - send a follow-up message to the same Thread;
35155
- - cancel its current Turn;
35156
- - read its current state immediately;
35157
- - wait for a bounded period;
35158
- - check it again later;
35159
- - leave it running in the background.
35160
-
35161
- Report the result returned by read or a completed wait, together with the target
35162
- agent, status, and a labeled task link. Keep internal tracking IDs in tool calls.
35163
- `;
35164
- var CURRENT_DIGEST = createHash9("sha256").update(CODEXHOST_DELEGATION_SKILL).digest("hex");
35165
- function digest(value2) {
35166
- return createHash9("sha256").update(value2).digest("hex");
35167
- }
35168
- function managedVersion(value2) {
35169
- const match = /^version:\s*(\d+)\s*$/mu.exec(value2);
35170
- return match ? Number(match[1]) : null;
35171
- }
35172
- async function readOptional(filePath) {
35173
- try {
35174
- return await readFile8(filePath, "utf8");
35175
- } catch (error51) {
35176
- if (error51.code === "ENOENT") return null;
35177
- throw error51;
35178
- }
35179
- }
35180
- async function atomicWrite(filePath, content) {
35181
- await mkdir8(path20.dirname(filePath), { recursive: true, mode: 448 });
35182
- const temporaryPath = path20.join(path20.dirname(filePath), `.SKILL.md.${randomUUID12()}.tmp`);
35183
- const handle = await open6(temporaryPath, "wx", 384);
35184
- try {
35185
- await handle.writeFile(content, "utf8");
35186
- await handle.sync();
35187
- } finally {
35188
- await handle.close();
35189
- }
35190
- try {
35191
- await rename5(temporaryPath, filePath);
35192
- } finally {
35193
- await rm8(temporaryPath, { force: true });
35194
- }
35195
- }
35196
- async function installDelegationSkills(input = {}) {
35197
- const home = input.homeDirectory ?? os6.homedir();
35198
- const destinations = [
35199
- path20.join(home, ".agents", SKILL_RELATIVE_PATH),
35200
- path20.join(home, ".claude", SKILL_RELATIVE_PATH)
35201
- ];
35202
- const knownDigests = /* @__PURE__ */ new Set([
35203
- CURRENT_DIGEST,
35204
- ...PREVIOUS_MANAGED_DIGESTS,
35205
- ...input.previousManagedDigests ?? []
35206
- ]);
35207
- const results = [];
35208
- for (const destination of destinations) {
35209
- const current = await readOptional(destination);
35210
- if (current === CODEXHOST_DELEGATION_SKILL) {
35211
- results.push({
35212
- path: destination,
35213
- status: "current",
35214
- version: SKILL_VERSION,
35215
- digest: CURRENT_DIGEST
35216
- });
35217
- continue;
35218
- }
35219
- if (current !== null) {
35220
- const currentDigest = digest(current);
35221
- const version2 = managedVersion(current);
35222
- if (!knownDigests.has(currentDigest)) {
35223
- results.push({ path: destination, status: "conflict", version: version2, digest: currentDigest });
35224
- continue;
35225
- }
35226
- await atomicWrite(destination, CODEXHOST_DELEGATION_SKILL);
35227
- results.push({
35228
- path: destination,
35229
- status: "updated",
35230
- version: SKILL_VERSION,
35231
- digest: CURRENT_DIGEST
35232
- });
35233
- continue;
35234
- }
35235
- await atomicWrite(destination, CODEXHOST_DELEGATION_SKILL);
35236
- results.push({
35237
- path: destination,
35238
- status: "installed",
35239
- version: SKILL_VERSION,
35240
- digest: CURRENT_DIGEST
35241
- });
35242
- }
35243
- for (const result of results) {
35244
- if (result.status === "conflict") continue;
35245
- const source = await readFile8(result.path, "utf8");
35246
- const metadata = await stat4(result.path);
35247
- if (!metadata.isFile() || source !== CODEXHOST_DELEGATION_SKILL) {
35248
- throw new Error(`Delegation Skill verification failed: ${result.path}`);
35249
- }
35250
- }
35251
- const managed = results.filter((result) => result.status !== "conflict");
35252
- if (managed.some((result) => result.digest !== CURRENT_DIGEST)) {
35253
- throw new Error("Delegation Skill copies are inconsistent");
35254
- }
35255
- if (results.every((result) => result.status !== "conflict")) {
35256
- const copies = await Promise.all(results.map((result) => readFile8(result.path, "utf8")));
35257
- if (copies.some((copy) => copy !== copies[0])) {
35258
- throw new Error("Delegation Skill copies are inconsistent");
35259
- }
35260
- }
35261
- return results;
35262
- }
35263
-
35264
35641
  // packages/host-runtime/src/remote-control-app-server.ts
35265
35642
  import { randomUUID as randomUUID13 } from "node:crypto";
35266
35643
  import { mkdir as mkdir9, open as open7, rename as rename6, rm as rm9 } from "node:fs/promises";
35267
- import path21 from "node:path";
35644
+ import path23 from "node:path";
35268
35645
  var REMOTE_CONTROL_BRIDGE_PIPE_ENV = "CODEXHOST_REMOTE_CONTROL_BRIDGE_PIPE";
35269
35646
  var REMOTE_CONTROL_BRIDGE_NODE_ENV = "CODEXHOST_REMOTE_CONTROL_BRIDGE_NODE_PATH";
35270
35647
  var REMOTE_CONTROL_BRIDGE_RUNTIME_ENV = "CODEXHOST_REMOTE_CONTROL_BRIDGE_RUNTIME_PATH";
@@ -35275,8 +35652,8 @@ var BRIDGE_READY_METHOD = "codexhost/remote-control-bridge/ready";
35275
35652
  function absoluteEnvironmentPath2(environment, name, fallback, platform = process.platform) {
35276
35653
  const value2 = environment[name] ?? fallback;
35277
35654
  if (!value2) return null;
35278
- if (path21.isAbsolute(value2)) return path21.normalize(value2);
35279
- return platform === "win32" && path21.win32.isAbsolute(value2) ? path21.win32.normalize(value2) : null;
35655
+ if (path23.isAbsolute(value2)) return path23.normalize(value2);
35656
+ return platform === "win32" && path23.win32.isAbsolute(value2) ? path23.win32.normalize(value2) : null;
35280
35657
  }
35281
35658
  function nodeCompatibleWindowsPath(value2) {
35282
35659
  if (value2.startsWith("\\\\?\\UNC\\")) return `\\\\${value2.slice(8)}`;
@@ -35290,13 +35667,13 @@ function remoteControlBridgePipePath(processId = process.pid, instanceId = rando
35290
35667
  }
35291
35668
  function remoteControlBridgeDescriptorPath(environment) {
35292
35669
  const root = environment.LOCALAPPDATA;
35293
- if (!root || !path21.isAbsolute(root)) return null;
35294
- return path21.join(path21.normalize(root), "codexhost", REMOTE_CONTROL_BRIDGE_DESCRIPTOR_FILE);
35670
+ if (!root || !path23.isAbsolute(root)) return null;
35671
+ return path23.join(path23.normalize(root), "codexhost", REMOTE_CONTROL_BRIDGE_DESCRIPTOR_FILE);
35295
35672
  }
35296
35673
  async function publishRemoteControlAppServerDescriptor(plan) {
35297
- const directory = path21.dirname(plan.descriptorPath);
35674
+ const directory = path23.dirname(plan.descriptorPath);
35298
35675
  await mkdir9(directory, { recursive: true, mode: 448 });
35299
- const temporaryPath = path21.join(
35676
+ const temporaryPath = path23.join(
35300
35677
  directory,
35301
35678
  `.${REMOTE_CONTROL_BRIDGE_DESCRIPTOR_FILE}.${plan.descriptor.ownerPid}.${randomUUID13()}.tmp`
35302
35679
  );
@@ -35597,9 +35974,9 @@ function hasLauncherManagedUpdateRuntime(environment, hostRuntimePath) {
35597
35974
  if (!environment[UPDATE_RUNTIME_ENV.launcherPid]) return false;
35598
35975
  const npmPackageRoot = environment[UPDATE_RUNTIME_ENV.npmPackageRoot];
35599
35976
  if (!npmPackageRoot || !hostRuntimePath) return true;
35600
- if (!path22.isAbsolute(npmPackageRoot) || !path22.isAbsolute(hostRuntimePath)) return false;
35601
- const runtimePackageRoot = path22.dirname(path22.dirname(path22.normalize(hostRuntimePath)));
35602
- return path22.relative(path22.normalize(npmPackageRoot), runtimePackageRoot) === "";
35977
+ if (!path24.isAbsolute(npmPackageRoot) || !path24.isAbsolute(hostRuntimePath)) return false;
35978
+ const runtimePackageRoot = path24.dirname(path24.dirname(path24.normalize(hostRuntimePath)));
35979
+ return path24.relative(path24.normalize(npmPackageRoot), runtimePackageRoot) === "";
35603
35980
  }
35604
35981
  function requiredRuntimeConfiguration(environment) {
35605
35982
  const stockCodexPath = environment[STOCK_CODEX_PATH_ENV];
@@ -35745,8 +36122,8 @@ async function runHostRuntime(input) {
35745
36122
  const socketPath = remoteAppServerSocketPath(delegationEnvironment, listenUrl);
35746
36123
  const officialPlan = createRemoteOfficialAppServerPlan(input.arguments, socketPath);
35747
36124
  const officialRuntimeScope = new OfficialRuntimeScope({
35748
- permanentHome: path22.resolve(
35749
- delegationEnvironment.CODEX_HOME ?? path22.join(homedir2(), ".codex")
36125
+ permanentHome: path24.resolve(
36126
+ delegationEnvironment.CODEX_HOME ?? path24.join(homedir2(), ".codex")
35750
36127
  ),
35751
36128
  diagnosticOutput: process.stderr,
35752
36129
  createBackend: () => createOwnedUnixBackend({
@@ -35839,10 +36216,10 @@ import {
35839
36216
  rename as rename7,
35840
36217
  rm as rm10,
35841
36218
  rmdir,
35842
- stat as stat5,
36219
+ stat as stat6,
35843
36220
  writeFile as writeFile4
35844
36221
  } from "node:fs/promises";
35845
- import path23 from "node:path";
36222
+ import path25 from "node:path";
35846
36223
  var MANIFEST_FORMAT = 1;
35847
36224
  var WRAPPER_MARKER = "# codexhost remote SSH wrapper v1";
35848
36225
  var PROFILE_START = "# >>> codexhost remote SSH >>>";
@@ -35853,25 +36230,25 @@ function resolvePaths(options2) {
35853
36230
  if (!configuredHome) {
35854
36231
  throw new Error("A non-root HOME is required for remote Host installation");
35855
36232
  }
35856
- const home = path23.resolve(configuredHome);
35857
- if (!home || home === path23.parse(home).root) {
36233
+ const home = path25.resolve(configuredHome);
36234
+ if (!home || home === path25.parse(home).root) {
35858
36235
  throw new Error("A non-root HOME is required for remote Host installation");
35859
36236
  }
35860
- const installRoot = path23.resolve(options2.installRoot ?? path23.join(home, ".codexhost", "remote"));
35861
- const profilePath = path23.resolve(
35862
- options2.profilePath ?? path23.join(
36237
+ const installRoot = path25.resolve(options2.installRoot ?? path25.join(home, ".codexhost", "remote"));
36238
+ const profilePath = path25.resolve(
36239
+ options2.profilePath ?? path25.join(
35863
36240
  home,
35864
- path23.basename(environment.SHELL ?? "") === "zsh" ? ".zshenv" : path23.basename(environment.SHELL ?? "") === "bash" ? ".bashrc" : ".profile"
36241
+ path25.basename(environment.SHELL ?? "") === "zsh" ? ".zshenv" : path25.basename(environment.SHELL ?? "") === "bash" ? ".bashrc" : ".profile"
35865
36242
  )
35866
36243
  );
35867
- const binDirectory = path23.join(installRoot, "bin");
36244
+ const binDirectory = path25.join(installRoot, "bin");
35868
36245
  return {
35869
36246
  home,
35870
36247
  installRoot,
35871
36248
  binDirectory,
35872
- wrapperPath: path23.join(binDirectory, "codex"),
35873
- manifestPath: path23.join(installRoot, "manifest.json"),
35874
- dataDirectory: path23.join(installRoot, "data"),
36249
+ wrapperPath: path25.join(binDirectory, "codex"),
36250
+ manifestPath: path25.join(installRoot, "manifest.json"),
36251
+ dataDirectory: path25.join(installRoot, "data"),
35875
36252
  profilePath
35876
36253
  };
35877
36254
  }
@@ -35890,9 +36267,9 @@ async function fileSha256(filePath) {
35890
36267
  return createHash10("sha256").update(await readFile9(filePath)).digest("hex");
35891
36268
  }
35892
36269
  async function executable(filePath, label) {
35893
- const absolute = path23.resolve(filePath);
36270
+ const absolute = path25.resolve(filePath);
35894
36271
  try {
35895
- if (!(await stat5(absolute)).isFile()) throw new Error("not a regular file");
36272
+ if (!(await stat6(absolute)).isFile()) throw new Error("not a regular file");
35896
36273
  await access(absolute, fsConstants.X_OK);
35897
36274
  } catch {
35898
36275
  throw new Error(`${label} is not an executable file: ${absolute}`);
@@ -35900,9 +36277,9 @@ async function executable(filePath, label) {
35900
36277
  return absolute;
35901
36278
  }
35902
36279
  async function existingFile(filePath, label) {
35903
- const absolute = path23.resolve(filePath);
36280
+ const absolute = path25.resolve(filePath);
35904
36281
  try {
35905
- const metadata = await stat5(absolute);
36282
+ const metadata = await stat6(absolute);
35906
36283
  if (!metadata.isFile()) throw new Error("not a regular file");
35907
36284
  } catch {
35908
36285
  throw new Error(`${label} is not a regular file: ${absolute}`);
@@ -35910,9 +36287,9 @@ async function existingFile(filePath, label) {
35910
36287
  return absolute;
35911
36288
  }
35912
36289
  async function discoverExecutable(name, environment) {
35913
- for (const directory of (environment.PATH ?? "").split(path23.delimiter)) {
36290
+ for (const directory of (environment.PATH ?? "").split(path25.delimiter)) {
35914
36291
  if (!directory) continue;
35915
- const candidate = path23.resolve(directory, name);
36292
+ const candidate = path25.resolve(directory, name);
35916
36293
  try {
35917
36294
  await access(candidate, fsConstants.X_OK);
35918
36295
  return candidate;
@@ -35923,10 +36300,10 @@ async function discoverExecutable(name, environment) {
35923
36300
  return null;
35924
36301
  }
35925
36302
  async function writeAtomic(filePath, contents, mode) {
35926
- await mkdir10(path23.dirname(filePath), { recursive: true, mode: 448 });
35927
- const temporary = path23.join(
35928
- path23.dirname(filePath),
35929
- `.${path23.basename(filePath)}.${process.pid}.${randomUUID14()}.tmp`
36303
+ await mkdir10(path25.dirname(filePath), { recursive: true, mode: 448 });
36304
+ const temporary = path25.join(
36305
+ path25.dirname(filePath),
36306
+ `.${path25.basename(filePath)}.${process.pid}.${randomUUID14()}.tmp`
35930
36307
  );
35931
36308
  try {
35932
36309
  if (typeof contents === "string") {
@@ -35947,10 +36324,10 @@ async function writeAtomic(filePath, contents, mode) {
35947
36324
  }
35948
36325
  }
35949
36326
  async function writeAtomicExecutable(filePath, sourcePath) {
35950
- await mkdir10(path23.dirname(filePath), { recursive: true, mode: 448 });
35951
- const temporary = path23.join(
35952
- path23.dirname(filePath),
35953
- `.${path23.basename(filePath)}.${process.pid}.${randomUUID14()}.tmp`
36327
+ await mkdir10(path25.dirname(filePath), { recursive: true, mode: 448 });
36328
+ const temporary = path25.join(
36329
+ path25.dirname(filePath),
36330
+ `.${path25.basename(filePath)}.${process.pid}.${randomUUID14()}.tmp`
35954
36331
  );
35955
36332
  try {
35956
36333
  await copyFile3(sourcePath, temporary);
@@ -35991,8 +36368,8 @@ function removeManagedProfileBlock(contents) {
35991
36368
  function installManagedProfileBlock(contents, manifest) {
35992
36369
  const base = removeManagedProfileBlock(contents);
35993
36370
  const environment = [
35994
- `export CODEX_INSTALL_DIR=${shellQuote(path23.dirname(manifest.wrapperPath))}`,
35995
- `export PATH=${shellQuote(path23.dirname(manifest.wrapperPath))}:${shellQuote(path23.dirname(manifest.nodePath))}:${shellQuote(path23.dirname(manifest.stockCodexPath))}:"\${PATH:-/usr/local/bin:/usr/bin:/bin}"`,
36371
+ `export CODEX_INSTALL_DIR=${shellQuote(path25.dirname(manifest.wrapperPath))}`,
36372
+ `export PATH=${shellQuote(path25.dirname(manifest.wrapperPath))}:${shellQuote(path25.dirname(manifest.nodePath))}:${shellQuote(path25.dirname(manifest.stockCodexPath))}:"\${PATH:-/usr/local/bin:/usr/bin:/bin}"`,
35996
36373
  `export CODEXHOST_STOCK_CODEX_PATH=${shellQuote(manifest.stockCodexPath)}`,
35997
36374
  `export CODEXHOST_HOST_NODE_PATH=${shellQuote(manifest.nodePath)}`,
35998
36375
  `export CODEXHOST_HOST_RUNTIME_PATH=${shellQuote(manifest.hostRuntimePath)}`,
@@ -36008,7 +36385,7 @@ function installManagedProfileBlock(contents, manifest) {
36008
36385
  PROFILE_END,
36009
36386
  ""
36010
36387
  ].join("\n");
36011
- if (path23.basename(manifest.profilePath) === ".bashrc") return `${block}${base}`;
36388
+ if (path25.basename(manifest.profilePath) === ".bashrc") return `${block}${base}`;
36012
36389
  const separator = base.length > 0 && !base.endsWith("\n") ? "\n" : "";
36013
36390
  return `${base}${separator}${block}`;
36014
36391
  }
@@ -36074,9 +36451,9 @@ async function readManifest(filePath) {
36074
36451
  ];
36075
36452
  const optionalPaths = ["claudeCommand", "profileBackupPath"];
36076
36453
  if (manifest.format !== MANIFEST_FORMAT || Object.keys(manifest).some((key) => !allowed.has(key)) || requiredPaths.some(
36077
- (key) => typeof manifest[key] !== "string" || !path23.isAbsolute(manifest[key])
36454
+ (key) => typeof manifest[key] !== "string" || !path25.isAbsolute(manifest[key])
36078
36455
  ) || optionalPaths.some(
36079
- (key) => manifest[key] !== void 0 && (typeof manifest[key] !== "string" || !path23.isAbsolute(manifest[key]))
36456
+ (key) => manifest[key] !== void 0 && (typeof manifest[key] !== "string" || !path25.isAbsolute(manifest[key]))
36080
36457
  ) || manifest.entrypointSha256 !== void 0 && (typeof manifest.entrypointSha256 !== "string" || !/^[a-f0-9]{64}$/u.test(manifest.entrypointSha256))) {
36081
36458
  throw new Error("Remote Host manifest has an unsupported format");
36082
36459
  }
@@ -36085,7 +36462,7 @@ async function readManifest(filePath) {
36085
36462
  async function backupProfile(profilePath, contents, action) {
36086
36463
  const timestamp = (/* @__PURE__ */ new Date()).toISOString().replaceAll(/[-:.TZ]/gu, "");
36087
36464
  const backupPath = `${profilePath}.codexhost-${action}-${timestamp}.bak`;
36088
- const metadata = await stat5(profilePath).catch(() => null);
36465
+ const metadata = await stat6(profilePath).catch(() => null);
36089
36466
  await writeAtomic(backupPath, contents, metadata?.mode ?? 384);
36090
36467
  return backupPath;
36091
36468
  }
@@ -36099,7 +36476,7 @@ async function installRemoteHost(options2) {
36099
36476
  const previousManifest = await readManifest(paths.manifestPath);
36100
36477
  const previousManifestFile = previousManifest ? {
36101
36478
  contents: await readFile9(paths.manifestPath),
36102
- mode: (await stat5(paths.manifestPath)).mode & 511
36479
+ mode: (await stat6(paths.manifestPath)).mode & 511
36103
36480
  } : null;
36104
36481
  const existingEntrypoint = await lstat8(paths.wrapperPath).catch(
36105
36482
  (error51) => {
@@ -36155,7 +36532,7 @@ async function installRemoteHost(options2) {
36155
36532
  const existingProfile = existingProfileSource ?? "";
36156
36533
  const nextProfile = installManagedProfileBlock(existingProfile, manifest);
36157
36534
  const profileChanged = nextProfile !== existingProfile;
36158
- const profileMetadata = await stat5(profilePath).catch(() => null);
36535
+ const profileMetadata = await stat6(profilePath).catch(() => null);
36159
36536
  try {
36160
36537
  if (profileChanged) {
36161
36538
  const profileBackupPath = await backupProfile(profilePath, existingProfile, "install");
@@ -36246,7 +36623,7 @@ async function inspectRemoteHostInstallation(options2) {
36246
36623
  if (!profileMatches && profileIssue === null)
36247
36624
  profileIssue = "shell profile does not configure the managed native entrypoint";
36248
36625
  if (profileIssue !== null) issues.push(profileIssue);
36249
- const dataDirectory = await stat5(manifest.dataDirectory).catch(() => null);
36626
+ const dataDirectory = await stat6(manifest.dataDirectory).catch(() => null);
36250
36627
  if (!dataDirectory?.isDirectory()) issues.push("remote Host data directory is unavailable");
36251
36628
  for (const [label, filePath, requiresExecutable] of [
36252
36629
  ["stock Codex", manifest.stockCodexPath, true],
@@ -36256,7 +36633,7 @@ async function inspectRemoteHostInstallation(options2) {
36256
36633
  ]) {
36257
36634
  try {
36258
36635
  if (requiresExecutable) await executable(filePath, label);
36259
- else if (!(await stat5(filePath)).isFile()) throw new Error("not a regular file");
36636
+ else if (!(await stat6(filePath)).isFile()) throw new Error("not a regular file");
36260
36637
  } catch {
36261
36638
  issues.push(`${label} is unavailable`);
36262
36639
  }
@@ -36285,7 +36662,7 @@ async function uninstallRemoteHost(options2) {
36285
36662
  const nextProfile = removeManagedProfileBlock(profile);
36286
36663
  if (nextProfile !== profile) {
36287
36664
  await backupProfile(manifest.profilePath, profile, "uninstall");
36288
- const metadata = await stat5(manifest.profilePath).catch(() => null);
36665
+ const metadata = await stat6(manifest.profilePath).catch(() => null);
36289
36666
  await writeAtomic(manifest.profilePath, nextProfile, metadata?.mode ?? 384);
36290
36667
  }
36291
36668
  await rm10(manifest.wrapperPath, { force: true });
@@ -36300,9 +36677,9 @@ async function uninstallRemoteHost(options2) {
36300
36677
 
36301
36678
  // packages/host-runtime/src/remote-host-lifecycle.ts
36302
36679
  import { spawn as spawn5 } from "node:child_process";
36303
- import { stat as stat6 } from "node:fs/promises";
36680
+ import { stat as stat7 } from "node:fs/promises";
36304
36681
  import net3 from "node:net";
36305
- import path24 from "node:path";
36682
+ import path26 from "node:path";
36306
36683
  import { Duplex } from "node:stream";
36307
36684
  var CODEXHOST_STATUS_METHOD = "codexhost/update/status";
36308
36685
  var DIRECT_PROBE_TIMEOUT_MS = 5e3;
@@ -36321,12 +36698,12 @@ function classifyRemoteHostProbeResponse(response, socketPath) {
36321
36698
  }
36322
36699
  var lifecycleDependencyOverrides = {};
36323
36700
  function socketPathFor(environment) {
36324
- const codexHome = environment.CODEX_HOME ?? (environment.HOME ? path24.join(environment.HOME, ".codex") : void 0);
36701
+ const codexHome = environment.CODEX_HOME ?? (environment.HOME ? path26.join(environment.HOME, ".codex") : void 0);
36325
36702
  if (!codexHome) throw new Error("CODEX_HOME or HOME is required for remote Host lifecycle");
36326
- return path24.join(codexHome, "app-server-control", "app-server-control.sock");
36703
+ return path26.join(codexHome, "app-server-control", "app-server-control.sock");
36327
36704
  }
36328
36705
  async function defaultSocketExists(socketPath) {
36329
- const metadata = await stat6(socketPath).catch((error51) => {
36706
+ const metadata = await stat7(socketPath).catch((error51) => {
36330
36707
  if (error51.code === "ENOENT") return null;
36331
36708
  throw error51;
36332
36709
  });
@@ -36450,14 +36827,14 @@ function installedManifest(status) {
36450
36827
  function managedEnvironment(manifest, environment) {
36451
36828
  return {
36452
36829
  ...environment,
36453
- CODEX_INSTALL_DIR: path24.dirname(manifest.wrapperPath),
36830
+ CODEX_INSTALL_DIR: path26.dirname(manifest.wrapperPath),
36454
36831
  CODEXHOST_STOCK_CODEX_PATH: manifest.stockCodexPath,
36455
36832
  CODEXHOST_HOST_NODE_PATH: manifest.nodePath,
36456
36833
  CODEXHOST_HOST_RUNTIME_PATH: manifest.hostRuntimePath,
36457
36834
  CODEXHOST_DATA_DIR: manifest.dataDirectory,
36458
36835
  CODEXHOST_DEFAULT_AGENT: "codex",
36459
36836
  CODEXHOST_REMOTE_SSH_MANAGED: "1",
36460
- PATH: `${path24.dirname(manifest.wrapperPath)}${path24.delimiter}${path24.dirname(manifest.stockCodexPath)}${path24.delimiter}${environment.PATH ?? "/usr/bin:/bin"}`
36837
+ PATH: `${path26.dirname(manifest.wrapperPath)}${path26.delimiter}${path26.dirname(manifest.stockCodexPath)}${path26.delimiter}${environment.PATH ?? "/usr/bin:/bin"}`
36461
36838
  };
36462
36839
  }
36463
36840
  async function defaultRunTerminator(manifest, socketPath, role, environment) {
@@ -36793,25 +37170,25 @@ function consumeBrokerFrames(socket, onFrame, onError) {
36793
37170
 
36794
37171
  // packages/harness-broker/dist/paths.js
36795
37172
  import os7 from "node:os";
36796
- import path25 from "node:path";
37173
+ import path27 from "node:path";
36797
37174
  var HARNESS_BROKER_DESCRIPTOR_ENV = "CODEXHOST_CLAUDE_BROKER_DESCRIPTOR";
36798
37175
  var HARNESS_BROKER_DESCRIPTOR_FILE = "claude-code-broker-v1.json";
36799
37176
  var HARNESS_BROKER_SOCKET_FILE = "claude-code-broker-v1.sock";
36800
37177
  function defaultHarnessBrokerDirectory(environment = process.env) {
36801
37178
  const home = environment.HOME || os7.homedir();
36802
- return path25.join(home, ".codexhost", "harness-broker");
37179
+ return path27.join(home, ".codexhost", "harness-broker");
36803
37180
  }
36804
37181
  function defaultHarnessBrokerDescriptorPath(environment = process.env, harnessId = "claude-code") {
36805
37182
  harnessPluginIdSchema.parse(harnessId);
36806
37183
  if (harnessId !== "claude-code")
36807
- return path25.join(defaultHarnessBrokerDirectory(environment), `${harnessId}-broker-v1.json`);
36808
- return environment[HARNESS_BROKER_DESCRIPTOR_ENV] ?? path25.join(defaultHarnessBrokerDirectory(environment), HARNESS_BROKER_DESCRIPTOR_FILE);
37184
+ return path27.join(defaultHarnessBrokerDirectory(environment), `${harnessId}-broker-v1.json`);
37185
+ return environment[HARNESS_BROKER_DESCRIPTOR_ENV] ?? path27.join(defaultHarnessBrokerDirectory(environment), HARNESS_BROKER_DESCRIPTOR_FILE);
36809
37186
  }
36810
37187
  function defaultHarnessBrokerSocketPath(environment = process.env, harnessId = "claude-code") {
36811
37188
  harnessPluginIdSchema.parse(harnessId);
36812
37189
  if (harnessId !== "claude-code")
36813
- return path25.join(defaultHarnessBrokerDirectory(environment), `${harnessId}-broker-v1.sock`);
36814
- return path25.join(defaultHarnessBrokerDirectory(environment), HARNESS_BROKER_SOCKET_FILE);
37190
+ return path27.join(defaultHarnessBrokerDirectory(environment), `${harnessId}-broker-v1.sock`);
37191
+ return path27.join(defaultHarnessBrokerDirectory(environment), HARNESS_BROKER_SOCKET_FILE);
36815
37192
  }
36816
37193
 
36817
37194
  // packages/harness-broker/dist/validation.js
@@ -37027,7 +37404,7 @@ var harnessOutputSchema = external_exports.custom((value2) => {
37027
37404
  import { randomBytes as randomBytes3, randomUUID as randomUUID15 } from "node:crypto";
37028
37405
  import { chmod as chmod5, lstat as lstat9, mkdir as mkdir11, open as open8, readFile as readFile10, rename as rename8, rm as rm11 } from "node:fs/promises";
37029
37406
  import net4, {} from "node:net";
37030
- import path26 from "node:path";
37407
+ import path28 from "node:path";
37031
37408
  function harnessError(message, retryable = true) {
37032
37409
  return { code: "unavailable", message, retryable, stage: "harnessBroker" };
37033
37410
  }
@@ -37150,13 +37527,13 @@ async function prepareUnixSocketPath(socketPath) {
37150
37527
  }
37151
37528
  async function startHarnessBrokerServer(input) {
37152
37529
  harnessPluginIdSchema.parse(input.adapter.harnessId);
37153
- if (process.platform !== "win32" && path26.dirname(input.descriptorPath) !== path26.dirname(input.socketPath)) {
37530
+ if (process.platform !== "win32" && path28.dirname(input.descriptorPath) !== path28.dirname(input.socketPath)) {
37154
37531
  throw new Error("Harness broker descriptor and socket must share one private directory");
37155
37532
  }
37156
37533
  if (process.platform === "darwin" && Buffer.byteLength(input.socketPath) > 103) {
37157
37534
  throw new Error("Harness broker Unix socket path is too long for macOS");
37158
37535
  }
37159
- await privateDirectory(path26.dirname(input.descriptorPath));
37536
+ await privateDirectory(path28.dirname(input.descriptorPath));
37160
37537
  await assertNoLiveDescriptor(input.descriptorPath);
37161
37538
  if (process.platform !== "win32")
37162
37539
  await prepareUnixSocketPath(input.socketPath);