@codexhost/cli-win32-arm64 0.9.2 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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 path23 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, path28) {
5982
+ if (!path28)
5983
5983
  return obj;
5984
- return path27.reduce((acc, key) => acc?.[key], obj);
5984
+ return path28.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(path28, 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(path28);
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, path28 = []) => {
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 }, [...path28, ...issue2.path]));
6548
6548
  } else if (issue2.code === "invalid_key") {
6549
- processError({ issues: issue2.issues }, [...path27, ...issue2.path]);
6549
+ processError({ issues: issue2.issues }, [...path28, ...issue2.path]);
6550
6550
  } else if (issue2.code === "invalid_element") {
6551
- processError({ issues: issue2.issues }, [...path27, ...issue2.path]);
6551
+ processError({ issues: issue2.issues }, [...path28, ...issue2.path]);
6552
6552
  } else {
6553
- const fullpath = [...path27, ...issue2.path];
6553
+ const fullpath = [...path28, ...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, path28 = []) => {
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 }, [...path28, ...issue2.path]));
6585
6585
  } else if (issue2.code === "invalid_key") {
6586
- processError({ issues: issue2.issues }, [...path27, ...issue2.path]);
6586
+ processError({ issues: issue2.issues }, [...path28, ...issue2.path]);
6587
6587
  } else if (issue2.code === "invalid_element") {
6588
- processError({ issues: issue2.issues }, [...path27, ...issue2.path]);
6588
+ processError({ issues: issue2.issues }, [...path28, ...issue2.path]);
6589
6589
  } else {
6590
- const fullpath = [...path27, ...issue2.path];
6590
+ const fullpath = [...path28, ...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 path28 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
6623
+ for (const seg of path28) {
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 path28 = ref.slice(1).split("/").filter(Boolean);
19316
+ if (path28.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 (path28[0] === defsKey) {
19321
+ const key = path28[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(path28, added, removed, oldPosInc, options2) {
22818
+ const last = path28.lastComponent;
22468
22819
  if (last && !options2.oneChangePerToken && last.added === added && last.removed === removed) {
22469
22820
  return {
22470
- oldPos: path27.oldPos + oldPosInc,
22821
+ oldPos: path28.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: path28.oldPos + oldPosInc,
22476
22827
  lastComponent: { count: 1, added, removed, previousComponent: last }
22477
22828
  };
22478
22829
  }
@@ -22901,10 +23252,10 @@ function splitLines(text) {
22901
23252
  }
22902
23253
 
22903
23254
  // packages/protocol-core/dist/file-change-summary.js
22904
- import path7 from "node:path";
23255
+ import path8 from "node:path";
22905
23256
  function filePathKey(file2, cwd) {
22906
23257
  const windows = /^[a-z]:[/\\]/i.test(cwd) || /^[a-z]:[/\\]/i.test(file2);
22907
- const paths = windows ? path7.win32 : path7.posix;
23258
+ const paths = windows ? path8.win32 : path8.posix;
22908
23259
  const resolved = paths.resolve(cwd, file2).replaceAll("\\", "/");
22909
23260
  return windows ? resolved.toLowerCase() : resolved;
22910
23261
  }
@@ -23055,11 +23406,11 @@ function itemStatus(outcome) {
23055
23406
  return "inProgress";
23056
23407
  return outcome.status === "succeeded" ? "completed" : "failed";
23057
23408
  }
23058
- function isRecord5(value2) {
23409
+ function isRecord6(value2) {
23059
23410
  return typeof value2 === "object" && value2 !== null && !Array.isArray(value2);
23060
23411
  }
23061
23412
  function nestedString(value2, keys, preserveText = false) {
23062
- if (!isRecord5(value2))
23413
+ if (!isRecord6(value2))
23063
23414
  return void 0;
23064
23415
  for (const key of keys) {
23065
23416
  const field = value2[key];
@@ -23173,8 +23524,8 @@ function projectFileChangeKind(kind) {
23173
23524
  return { type: kind };
23174
23525
  }
23175
23526
  function projectFileChanges(changes) {
23176
- return changes.map(({ path: path27, kind, unifiedDiff }) => ({
23177
- path: path27,
23527
+ return changes.map(({ path: path28, kind, unifiedDiff }) => ({
23528
+ path: path28,
23178
23529
  kind: projectFileChangeKind(kind),
23179
23530
  diff: unifiedDiff
23180
23531
  }));
@@ -23214,7 +23565,7 @@ function planFromTodoValue(value2) {
23214
23565
  const record3 = unwrapToolRecord(value2);
23215
23566
  if (!record3)
23216
23567
  return planFromChecklistText(typeof value2 === "string" ? value2 : null);
23217
- if (isRecord5(record3.TodosUpdated)) {
23568
+ if (isRecord6(record3.TodosUpdated)) {
23218
23569
  const nested = planFromTodoValue(record3.TodosUpdated);
23219
23570
  if (nested)
23220
23571
  return nested;
@@ -23229,7 +23580,7 @@ function planFromTodoValue(value2) {
23229
23580
  plan.push({ step: entry.trim(), status: "pending" });
23230
23581
  continue;
23231
23582
  }
23232
- if (!isRecord5(entry))
23583
+ if (!isRecord6(entry))
23233
23584
  continue;
23234
23585
  const step = nestedString(entry, ["content", "step", "text", "title", "description", "task"]);
23235
23586
  if (!step)
@@ -23284,7 +23635,7 @@ function unwrapToolRecord(value2) {
23284
23635
  }
23285
23636
  if (Array.isArray(value2))
23286
23637
  return { todos: value2 };
23287
- if (!isRecord5(value2))
23638
+ if (!isRecord6(value2))
23288
23639
  return null;
23289
23640
  for (const wrapper of ["input", "arguments", "params"]) {
23290
23641
  if (value2[wrapper] === void 0)
@@ -24074,7 +24425,7 @@ var CodexTurnProjector = class {
24074
24425
  };
24075
24426
 
24076
24427
  // packages/protocol-core/dist/thread-fork.js
24077
- function isRecord6(value2) {
24428
+ function isRecord7(value2) {
24078
24429
  return typeof value2 === "object" && value2 !== null && !Array.isArray(value2);
24079
24430
  }
24080
24431
  function optionalText(params, name, options2 = {}) {
@@ -24097,7 +24448,7 @@ function optionalBoolean(params, name) {
24097
24448
  function decodeThreadForkRequest(request) {
24098
24449
  if (request.method !== "thread/fork")
24099
24450
  return null;
24100
- if (!isRecord6(request.params))
24451
+ if (!isRecord7(request.params))
24101
24452
  throw new Error("thread/fork params must be an object");
24102
24453
  const params = request.params;
24103
24454
  const threadId2 = optionalText(params, "threadId");
@@ -24112,13 +24463,13 @@ function decodeThreadForkRequest(request) {
24112
24463
  if (runtimeWorkspaceRoots !== void 0 && runtimeWorkspaceRoots !== null && (!Array.isArray(runtimeWorkspaceRoots) || runtimeWorkspaceRoots.some((root) => typeof root !== "string" || root.length === 0))) {
24113
24464
  throw new Error("thread/fork params.runtimeWorkspaceRoots must be text paths or null");
24114
24465
  }
24115
- const path27 = optionalText(params, "path", { allowEmpty: true });
24466
+ const path28 = optionalText(params, "path", { allowEmpty: true });
24116
24467
  const ephemeral = optionalBoolean(params, "ephemeral");
24117
24468
  return {
24118
24469
  threadId: threadId2,
24119
24470
  ...lastTurnText ? { lastTurnId: hostTurnIdSchema.parse(lastTurnText) } : {},
24120
24471
  ...beforeTurnText ? { beforeTurnId: hostTurnIdSchema.parse(beforeTurnText) } : {},
24121
- ...path27 ? { path: path27 } : {},
24472
+ ...path28 ? { path: path28 } : {},
24122
24473
  ...optionalField(params, "model"),
24123
24474
  ...optionalField(params, "modelProvider"),
24124
24475
  ...optionalField(params, "cwd"),
@@ -24133,7 +24484,7 @@ function decodeThreadForkRequest(request) {
24133
24484
  function decodeThreadRevertRequest(request) {
24134
24485
  if (request.method !== "thread/revert")
24135
24486
  return null;
24136
- if (!isRecord6(request.params))
24487
+ if (!isRecord7(request.params))
24137
24488
  throw new Error("thread/revert params must be an object");
24138
24489
  const { threadId: threadId2, beforeTurnId } = request.params;
24139
24490
  if (typeof threadId2 !== "string" || threadId2.length === 0) {
@@ -24147,7 +24498,7 @@ function decodeThreadRevertRequest(request) {
24147
24498
  function decodeThreadRollbackRequest(request) {
24148
24499
  if (request.method !== "thread/rollback")
24149
24500
  return null;
24150
- if (!isRecord6(request.params))
24501
+ if (!isRecord7(request.params))
24151
24502
  throw new Error("thread/rollback params must be an object");
24152
24503
  const { threadId: threadId2, numTurns } = request.params;
24153
24504
  if (typeof threadId2 !== "string" || threadId2.length === 0) {
@@ -24211,7 +24562,7 @@ function threadForkResult(thread, input) {
24211
24562
  }
24212
24563
 
24213
24564
  // packages/protocol-core/dist/thread-management.js
24214
- import { createHash as createHash3 } from "node:crypto";
24565
+ import { createHash as createHash4 } from "node:crypto";
24215
24566
  var HOST_CURSOR_PREFIX = "codexhost:thread-list:v1:";
24216
24567
  var MAX_CURSOR_LENGTH = 65536;
24217
24568
  var DEFAULT_PAGE_SIZE = 25;
@@ -24244,13 +24595,13 @@ var THREAD_SOURCE_KINDS = /* @__PURE__ */ new Set([
24244
24595
  "subAgentOther",
24245
24596
  "unknown"
24246
24597
  ]);
24247
- function isRecord7(value2) {
24598
+ function isRecord8(value2) {
24248
24599
  return typeof value2 === "object" && value2 !== null && !Array.isArray(value2);
24249
24600
  }
24250
24601
  function paramsObject(request, method) {
24251
24602
  if (request.params === void 0 && method === "thread/list")
24252
24603
  return {};
24253
- if (!isRecord7(request.params))
24604
+ if (!isRecord8(request.params))
24254
24605
  throw new Error(`${method} params must be an object`);
24255
24606
  return request.params;
24256
24607
  }
@@ -24308,7 +24659,7 @@ function decodeSortKey(value2) {
24308
24659
  return value2;
24309
24660
  }
24310
24661
  function queryFingerprint(value2) {
24311
- return createHash3("sha256").update(JSON.stringify(value2)).digest("hex");
24662
+ return createHash4("sha256").update(JSON.stringify(value2)).digest("hex");
24312
24663
  }
24313
24664
  function cursorPayload(value2) {
24314
24665
  return {
@@ -24322,7 +24673,7 @@ function cursorPayload(value2) {
24322
24673
  };
24323
24674
  }
24324
24675
  function parseCursorPayload(value2) {
24325
- if (!isRecord7(value2) || value2.formatVersion !== 1)
24676
+ if (!isRecord8(value2) || value2.formatVersion !== 1)
24326
24677
  throw new Error("Host cursor is invalid");
24327
24678
  const { queryFingerprint: fingerprint, sortDirection: sortDirection2, officialCursor, officialDone } = value2;
24328
24679
  const { externalAnchor: externalAnchor2, externalDone } = value2;
@@ -24331,7 +24682,7 @@ function parseCursorPayload(value2) {
24331
24682
  }
24332
24683
  let anchor = null;
24333
24684
  if (externalAnchor2 !== null) {
24334
- if (!isRecord7(externalAnchor2) || !Number.isSafeInteger(externalAnchor2.timestamp) || typeof externalAnchor2.threadId !== "string" || externalAnchor2.threadId.length === 0) {
24685
+ if (!isRecord8(externalAnchor2) || !Number.isSafeInteger(externalAnchor2.timestamp) || typeof externalAnchor2.threadId !== "string" || externalAnchor2.threadId.length === 0) {
24335
24686
  throw new Error("Host cursor is invalid");
24336
24687
  }
24337
24688
  anchor = {
@@ -24454,7 +24805,7 @@ function decodeThreadMetadataUpdateRequest(request) {
24454
24805
  if (params.gitInfo === null) {
24455
24806
  gitInfo = null;
24456
24807
  } else if (params.gitInfo !== void 0) {
24457
- if (!isRecord7(params.gitInfo)) {
24808
+ if (!isRecord8(params.gitInfo)) {
24458
24809
  throw new Error("thread/metadata/update params.gitInfo must be an object or null");
24459
24810
  }
24460
24811
  gitInfo = {};
@@ -24482,7 +24833,7 @@ function optionalCursor(value2, name) {
24482
24833
  return value2;
24483
24834
  }
24484
24835
  function decodeOfficialThreadListPage(value2) {
24485
- if (!isRecord7(value2) || !Array.isArray(value2.data) || value2.data.some((row) => !isRecord7(row))) {
24836
+ if (!isRecord8(value2) || !Array.isArray(value2.data) || value2.data.some((row) => !isRecord8(row))) {
24486
24837
  throw new Error("Official thread/list response is invalid");
24487
24838
  }
24488
24839
  return {
@@ -25294,22 +25645,22 @@ var HarnessAccountInspectionCache = class {
25294
25645
  };
25295
25646
 
25296
25647
  // 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";
25648
+ import { createHash as createHash8, randomUUID as randomUUID10 } from "node:crypto";
25649
+ import os5 from "node:os";
25650
+ import path15 from "node:path";
25300
25651
 
25301
25652
  // packages/host-runtime/src/external-thread-fork.ts
25302
25653
  import nodePath from "node:path";
25303
25654
 
25304
25655
  // 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";
25656
+ import { randomUUID as randomUUID5 } from "node:crypto";
25657
+ import os3 from "node:os";
25658
+ import path9 from "node:path";
25308
25659
 
25309
25660
  // packages/host-runtime/src/external-subagent-threads.ts
25310
- import { createHash as createHash4, randomUUID as randomUUID3 } from "node:crypto";
25661
+ import { createHash as createHash5, randomUUID as randomUUID4 } from "node:crypto";
25311
25662
  function childCreateRequest(parent, nativeRef, id2) {
25312
- const key = createHash4("sha256").update(JSON.stringify([parent.hostThreadId, parent.harnessId, nativeRef.nativeSessionId, id2])).digest("hex");
25663
+ const key = createHash5("sha256").update(JSON.stringify([parent.hostThreadId, parent.harnessId, nativeRef.nativeSessionId, id2])).digest("hex");
25313
25664
  return `subagent:${key}`;
25314
25665
  }
25315
25666
  function subagentMaterializer(store, parent, previousParent) {
@@ -25382,7 +25733,7 @@ function subagentMaterializer(store, parent, previousParent) {
25382
25733
  return rebind(existing, parent);
25383
25734
  }
25384
25735
  const provisional = existing ?? await store.createProvisional({
25385
- hostThreadId: hostThreadIdSchema.parse(randomUUID3()),
25736
+ hostThreadId: hostThreadIdSchema.parse(randomUUID4()),
25386
25737
  createRequestId,
25387
25738
  harnessId: parent.harnessId,
25388
25739
  cwd: parent.cwd,
@@ -25444,8 +25795,8 @@ function sameMapping(left, right) {
25444
25795
  }
25445
25796
  function defaultMappingStoreDirectory(environment) {
25446
25797
  const dataDirectory = environment.CODEXHOST_DATA_DIR;
25447
- return path8.join(
25448
- dataDirectory ? path8.resolve(dataDirectory) : path8.join(os2.homedir(), ".codexhost"),
25798
+ return path9.join(
25799
+ dataDirectory ? path9.resolve(dataDirectory) : path9.join(os3.homedir(), ".codexhost"),
25449
25800
  "mapping-store"
25450
25801
  );
25451
25802
  }
@@ -25542,7 +25893,7 @@ var ExternalThreadRepository = class {
25542
25893
  throw new Error("Derived Snapshot identity does not belong to its Native Session");
25543
25894
  }
25544
25895
  return {
25545
- hostTurnId: hostTurnIdSchema.parse(randomUUID4()),
25896
+ hostTurnId: hostTurnIdSchema.parse(randomUUID5()),
25546
25897
  nativeTurnRef: turn.nativeTurnRef,
25547
25898
  ...turn.checkpoint ? { nativeCheckpointRef: turn.checkpoint } : {}
25548
25899
  };
@@ -25662,7 +26013,7 @@ var ExternalThreadRepository = class {
25662
26013
  const aligned = snapshot.turns.map((turn) => {
25663
26014
  const existing = mappingsByNative.get(nativeTurnKey2(turn.nativeTurnRef));
25664
26015
  const mapping = existing ?? {
25665
- hostTurnId: hostTurnIdSchema.parse(randomUUID4()),
26016
+ hostTurnId: hostTurnIdSchema.parse(randomUUID5()),
25666
26017
  nativeTurnRef: turn.nativeTurnRef,
25667
26018
  ...turn.checkpoint ? { nativeCheckpointRef: turn.checkpoint } : {}
25668
26019
  };
@@ -25689,8 +26040,8 @@ var ExternalThreadRepository = class {
25689
26040
  };
25690
26041
  function createExternalThreadRecordInput(input) {
25691
26042
  return {
25692
- hostThreadId: input.hostThreadId ?? hostThreadIdSchema.parse(randomUUID4()),
25693
- createRequestId: input.createRequestId ?? randomUUID4(),
26043
+ hostThreadId: input.hostThreadId ?? hostThreadIdSchema.parse(randomUUID5()),
26044
+ createRequestId: input.createRequestId ?? randomUUID5(),
25694
26045
  harnessId: input.harnessId,
25695
26046
  cwd: input.cwd,
25696
26047
  ...input.title ? { title: input.title } : {},
@@ -25851,6 +26202,7 @@ async function executeExternalThreadFork(input) {
25851
26202
  return { ok: false, error: mapExternalThreadHarnessError(opened.error, "fork") };
25852
26203
  }
25853
26204
  const session = opened.value;
26205
+ const inheritedPermissionModeId = await inheritSourcePermissionMode(source, session);
25854
26206
  try {
25855
26207
  const derivedNativeRef = session.initialState.nativeRef;
25856
26208
  if (!derivedNativeRef || derivedNativeRef.nativeSessionId === nativeSessionRef.nativeSessionId) {
@@ -25878,7 +26230,8 @@ async function executeExternalThreadFork(input) {
25878
26230
  sessionId: source.sessionId,
25879
26231
  thread,
25880
26232
  turns: aligned.turns,
25881
- ...snapshot.value.state ? { restoredState: snapshot.value.state } : {}
26233
+ ...snapshot.value.state ? { restoredState: snapshot.value.state } : {},
26234
+ ...inheritedPermissionModeId ? { requestedPermissionModeId: inheritedPermissionModeId } : {}
25882
26235
  });
25883
26236
  return {
25884
26237
  ok: true,
@@ -25896,6 +26249,23 @@ async function executeExternalThreadFork(input) {
25896
26249
  };
25897
26250
  }
25898
26251
  }
26252
+ async function inheritSourcePermissionMode(source, session) {
26253
+ const sourceModeId = source.stateObserver.state.effectivePermissionModeId ?? source.requestedPermissionModeId;
26254
+ if (!sourceModeId) return void 0;
26255
+ const configuration = session.capabilities.configuration;
26256
+ if (!configuration.selectPermissionMode || permissionModeFixedAtCreate(configuration)) {
26257
+ return void 0;
26258
+ }
26259
+ try {
26260
+ const selected = await session.execute({
26261
+ type: "permissionMode.select",
26262
+ permissionModeId: sourceModeId
26263
+ });
26264
+ return selected.ok ? sourceModeId : void 0;
26265
+ } catch {
26266
+ return void 0;
26267
+ }
26268
+ }
25899
26269
 
25900
26270
  // packages/host-runtime/src/harness-session-import.ts
25901
26271
  function fixedError(code, message) {
@@ -27460,9 +27830,12 @@ var ExternalTurnSteering = class {
27460
27830
  if (!cancelled.ok) throw new ExternalSteerError(-32074, cancelled.error.message);
27461
27831
  const outcome = await Promise.race([terminal2.promise, failure.promise]);
27462
27832
  clearTimeout(timeout);
27463
- if (failureReason) throw failureReason;
27464
- if (this.#closed)
27465
- throw new ExternalSteerError(-32074, "External steering connection is closed");
27833
+ const assertActive = () => {
27834
+ if (failureReason) throw failureReason;
27835
+ if (this.#closed)
27836
+ throw new ExternalSteerError(-32074, "External steering connection is closed");
27837
+ };
27838
+ assertActive();
27466
27839
  if (outcome.status === "failed") throw new ExternalSteerError(-32074, outcome.error.message);
27467
27840
  if (thread.persistenceError)
27468
27841
  throw new ExternalSteerError(
@@ -27472,7 +27845,7 @@ var ExternalTurnSteering = class {
27472
27845
  if (thread.running || thread.activeTurnId) {
27473
27846
  throw new ExternalSteerError(-32072, "Another External Turn started before replacement");
27474
27847
  }
27475
- return await start(input.text);
27848
+ return await start(input.text, assertActive);
27476
27849
  } finally {
27477
27850
  clearTimeout(timeout);
27478
27851
  if (this.#pending.get(thread.id) === pending) this.#pending.delete(thread.id);
@@ -27480,30 +27853,112 @@ var ExternalTurnSteering = class {
27480
27853
  }
27481
27854
  };
27482
27855
 
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) {
27493
- return typeof value2 === "object" && value2 !== null && !Array.isArray(value2);
27494
- }
27495
- function stringValue(value2) {
27496
- return typeof value2 === "string" && value2.length > 0 ? value2 : null;
27497
- }
27498
- function textFromUserItem(item) {
27856
+ // packages/host-runtime/src/external-command-routing.ts
27857
+ var ExternalCommandError = class extends Error {
27858
+ constructor(code, message) {
27859
+ super(message);
27860
+ this.code = code;
27861
+ }
27862
+ code;
27863
+ };
27864
+ function isExternalCommandCandidate(text) {
27865
+ return /^\/[^\s/]+(?:\s|$)/u.test(text.trimStart());
27866
+ }
27867
+ async function inspectLiveCommandCatalog(commands, timeoutMs = 1e3) {
27868
+ let timeout;
27869
+ try {
27870
+ const result = await Promise.race([
27871
+ commands.list(),
27872
+ new Promise((resolve) => {
27873
+ timeout = setTimeout(() => resolve(null), timeoutMs);
27874
+ })
27875
+ ]);
27876
+ return result?.ok ? harnessCommandCatalogSchema.parse(result.value) : null;
27877
+ } catch {
27878
+ return null;
27879
+ } finally {
27880
+ if (timeout !== void 0) clearTimeout(timeout);
27881
+ }
27882
+ }
27883
+ async function resolveExternalCommand(commands, text, options2 = {}) {
27884
+ const catalog = await commands.list();
27885
+ if (!catalog.ok) throw new ExternalCommandError(-32073, catalog.error.message);
27886
+ const commandText = text.trim();
27887
+ const matched = catalog.value.commands.toSorted((left, right) => right.invocation.length - left.invocation.length).find((command) => {
27888
+ if (commandText === command.invocation) return true;
27889
+ return command.argumentMode === "text" && commandText.startsWith(`${command.invocation} `);
27890
+ });
27891
+ if (!matched) {
27892
+ const name = /^\/(\S+)/u.exec(commandText)?.[1] ?? "";
27893
+ if (name && !isExcludedLiveCommand(name, "command") && options2.liveCatalogPending?.(catalog.value)) {
27894
+ return null;
27895
+ }
27896
+ throw new ExternalCommandError(
27897
+ -32078,
27898
+ "External Harness does not expose the requested command"
27899
+ );
27900
+ }
27901
+ const argumentText = commandText.slice(matched.invocation.length).trimStart();
27902
+ return {
27903
+ commandId: matched.id,
27904
+ ...argumentText.length > 0 ? { arguments: { text: argumentText } } : {}
27905
+ };
27906
+ }
27907
+
27908
+ // packages/host-runtime/src/live-command-catalog-cache.ts
27909
+ import path10 from "node:path";
27910
+ var MAX_ENTRIES = 64;
27911
+ function isLiveCommandCatalog(catalog, staticCatalog) {
27912
+ const staticIds = new Set(staticCatalog.commands.map(({ id: id2 }) => id2));
27913
+ return catalog.commands.some(({ id: id2 }) => !staticIds.has(id2));
27914
+ }
27915
+ var LiveCommandCatalogCache = class {
27916
+ #entries = /* @__PURE__ */ new Map();
27917
+ #key(harnessId, cwd) {
27918
+ return `${harnessId}\0${path10.resolve(cwd)}`;
27919
+ }
27920
+ remember(harnessId, cwd, catalog) {
27921
+ const key = this.#key(harnessId, cwd);
27922
+ this.#entries.delete(key);
27923
+ this.#entries.set(key, catalog);
27924
+ while (this.#entries.size > MAX_ENTRIES) {
27925
+ const oldest = this.#entries.keys().next().value;
27926
+ if (oldest === void 0) break;
27927
+ this.#entries.delete(oldest);
27928
+ }
27929
+ }
27930
+ lookup(harnessId, cwd) {
27931
+ return this.#entries.get(this.#key(harnessId, cwd));
27932
+ }
27933
+ };
27934
+ function sameWorkspace(left, right) {
27935
+ return path10.resolve(left) === path10.resolve(right);
27936
+ }
27937
+
27938
+ // packages/host-runtime/src/harness-delegation-coordinator.ts
27939
+ import { createHash as createHash7, randomUUID as randomUUID6 } from "node:crypto";
27940
+ import path11 from "node:path";
27941
+
27942
+ // packages/host-runtime/src/delegation-snapshot.ts
27943
+ import { createHash as createHash6 } from "node:crypto";
27944
+ var CURSOR_PREFIX = "codexhost:thread-messages:v1:";
27945
+ var DEFAULT_MESSAGE_LIMIT = 25;
27946
+ var MAX_MESSAGE_LIMIT = 100;
27947
+ function isRecord9(value2) {
27948
+ return typeof value2 === "object" && value2 !== null && !Array.isArray(value2);
27949
+ }
27950
+ function stringValue(value2) {
27951
+ return typeof value2 === "string" && value2.length > 0 ? value2 : null;
27952
+ }
27953
+ function textFromUserItem(item) {
27499
27954
  if (!Array.isArray(item.content)) return "";
27500
27955
  return item.content.flatMap(
27501
- (part) => isRecord8(part) && part.type === "text" && typeof part.text === "string" ? [part.text] : []
27956
+ (part) => isRecord9(part) && part.type === "text" && typeof part.text === "string" ? [part.text] : []
27502
27957
  ).join("\n");
27503
27958
  }
27504
27959
  function threadStatus(value2, running) {
27505
27960
  if (running) return "running";
27506
- if (isRecord8(value2)) {
27961
+ if (isRecord9(value2)) {
27507
27962
  if (value2.type === "active") return "running";
27508
27963
  }
27509
27964
  return "completed";
@@ -27520,10 +27975,10 @@ function allVisibleMessages(turns) {
27520
27975
  const turnId = stringValue(turn.id);
27521
27976
  if (!turnId || !Array.isArray(turn.items)) continue;
27522
27977
  const agentItems = turn.items.filter(
27523
- (item) => isRecord8(item) && item.type === "agentMessage"
27978
+ (item) => isRecord9(item) && item.type === "agentMessage"
27524
27979
  );
27525
27980
  for (const item of turn.items) {
27526
- if (!isRecord8(item)) continue;
27981
+ if (!isRecord9(item)) continue;
27527
27982
  const id2 = stringValue(item.id);
27528
27983
  if (!id2) continue;
27529
27984
  if (item.type === "userMessage") {
@@ -27539,7 +27994,7 @@ function allVisibleMessages(turns) {
27539
27994
  return messages;
27540
27995
  }
27541
27996
  function cursorFingerprint(threadId2) {
27542
- return createHash5("sha256").update(threadId2).digest("hex");
27997
+ return createHash6("sha256").update(threadId2).digest("hex");
27543
27998
  }
27544
27999
  function encodeCursor(threadId2, offset) {
27545
28000
  const payload = JSON.stringify({ version: 1, fingerprint: cursorFingerprint(threadId2), offset });
@@ -27598,7 +28053,7 @@ function projectDelegationThreadSnapshot(input) {
27598
28053
  const progress = latestTurnMessages.filter((message) => message.phase !== "final" && message.text.trim()).map(({ id: id2, turnId, text }) => ({ id: id2, turnId, text }));
27599
28054
  const result = input.running ? { availability: "pending" } : final ? { availability: "available", text: final.text } : {
27600
28055
  availability: "unavailable",
27601
- ...isRecord8(latestTurn?.error) && typeof latestTurn.error.message === "string" ? { message: latestTurn.error.message } : {}
28056
+ ...isRecord9(latestTurn?.error) && typeof latestTurn.error.message === "string" ? { message: latestTurn.error.message } : {}
27602
28057
  };
27603
28058
  const offset = options2.view === "messages" ? decodeCursor(input.threadId, options2.cursor) : visible.length;
27604
28059
  const page = options2.view === "messages" ? [] : void 0;
@@ -27634,10 +28089,10 @@ function terminal(status) {
27634
28089
  return status === "completed" || status === "failed" || status === "interrupted";
27635
28090
  }
27636
28091
  function taskDigest(input) {
27637
- return createHash6("sha256").update(
28092
+ return createHash7("sha256").update(
27638
28093
  JSON.stringify({
27639
28094
  task: input.task,
27640
- cwd: path9.resolve(input.cwd),
28095
+ cwd: path11.resolve(input.cwd),
27641
28096
  modelId: input.model?.id ?? null,
27642
28097
  thinkingOptionId: input.thinkingOptionId ?? null
27643
28098
  })
@@ -27708,7 +28163,7 @@ var HarnessDelegationCoordinator = class {
27708
28163
  return {
27709
28164
  harnessId: input.harnessId,
27710
28165
  inspection: await adapter.inspect({
27711
- ...input.cwd ? { cwd: path9.resolve(input.cwd) } : {},
28166
+ ...input.cwd ? { cwd: path11.resolve(input.cwd) } : {},
27712
28167
  ...input.refresh !== void 0 ? { refresh: input.refresh } : {}
27713
28168
  })
27714
28169
  };
@@ -27722,7 +28177,7 @@ var HarnessDelegationCoordinator = class {
27722
28177
  const result = await this.#startOfficial({ ...input, parentThreadId, cwd: selectedCwd });
27723
28178
  return { ...result, parentThreadId, cwd: result.cwd ?? selectedCwd };
27724
28179
  }
27725
- const startInput = { ...input, parentThreadId, cwd: path9.resolve(selectedCwd) };
28180
+ const startInput = { ...input, parentThreadId, cwd: path11.resolve(selectedCwd) };
27726
28181
  if (!this.#adapters.has(input.harnessId)) {
27727
28182
  throw new DelegationControlError(
27728
28183
  "HARNESS_NOT_FOUND",
@@ -27762,10 +28217,10 @@ var HarnessDelegationCoordinator = class {
27762
28217
  });
27763
28218
  this.#validateConfiguration(inspected.inspection, input.model, input.thinkingOptionId);
27764
28219
  }
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();
28220
+ const delegationId = hostThreadIdSchema.parse(randomUUID6());
28221
+ const childThreadId = hostThreadIdSchema.parse(randomUUID6());
28222
+ const turnId = hostTurnIdSchema.parse(randomUUID6());
28223
+ const createRequestId = input.requestId ? `delegation:${input.requestId}` : randomUUID6();
27769
28224
  let record3 = await this.#repository.createProvisional(
27770
28225
  createExternalThreadRecordInput({
27771
28226
  hostThreadId: childThreadId,
@@ -27897,7 +28352,7 @@ var HarnessDelegationCoordinator = class {
27897
28352
  if (thread.running || thread.activeTurnId) {
27898
28353
  throw new DelegationControlError("THREAD_BUSY", "Thread already has an active Turn");
27899
28354
  }
27900
- const turnId = hostTurnIdSchema.parse(randomUUID5());
28355
+ const turnId = hostTurnIdSchema.parse(randomUUID6());
27901
28356
  try {
27902
28357
  await this.#startExternalTurn(thread, input.message, turnId);
27903
28358
  } catch (error51) {
@@ -28151,7 +28606,7 @@ var HarnessDelegationCoordinator = class {
28151
28606
 
28152
28607
  // packages/host-runtime/src/harness-plugin-loader.ts
28153
28608
  import { readdir as readdir3, realpath as realpath2 } from "node:fs/promises";
28154
- import path11 from "node:path";
28609
+ import path13 from "node:path";
28155
28610
  import { pathToFileURL } from "node:url";
28156
28611
 
28157
28612
  // packages/host-runtime/src/harness-plugin-registry.ts
@@ -28188,25 +28643,25 @@ var HarnessPluginRegistry = class {
28188
28643
  };
28189
28644
 
28190
28645
  // 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";
28646
+ import { open as open5, realpath, stat as stat3 } from "node:fs/promises";
28647
+ import path12 from "node:path";
28193
28648
  function inside(root, candidate) {
28194
- const relative = path10.relative(root, candidate);
28195
- return relative !== "" && !path10.isAbsolute(relative) && relative !== ".." && !relative.startsWith(`..${path10.sep}`);
28649
+ const relative = path12.relative(root, candidate);
28650
+ return relative !== "" && !path12.isAbsolute(relative) && relative !== ".." && !relative.startsWith(`..${path12.sep}`);
28196
28651
  }
28197
28652
  async function pluginResourcePath(root, relative) {
28198
- if (path10.isAbsolute(relative) || !inside(root, path10.resolve(root, relative))) {
28653
+ if (path12.isAbsolute(relative) || !inside(root, path12.resolve(root, relative))) {
28199
28654
  throw new Error("Plugin resource escapes its root");
28200
28655
  }
28201
- const resolved = await realpath(path10.resolve(root, relative));
28202
- if (!inside(root, resolved) || !(await stat2(resolved)).isFile()) {
28656
+ const resolved = await realpath(path12.resolve(root, relative));
28657
+ if (!inside(root, resolved) || !(await stat3(resolved)).isFile()) {
28203
28658
  throw new Error("Plugin resource must be a regular file inside its root");
28204
28659
  }
28205
28660
  return resolved;
28206
28661
  }
28207
28662
  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");
28663
+ if (!(await stat3(file2)).isFile()) throw new Error("Plugin resource is not a regular file");
28664
+ const handle = await open5(file2, "r");
28210
28665
  try {
28211
28666
  const info = await handle.stat();
28212
28667
  if (!info.isFile() || info.size > maximum) throw new Error("Plugin resource exceeds its limit");
@@ -28360,7 +28815,7 @@ async function loadHarnessPlugins(options2) {
28360
28815
  const enabledIds = /* @__PURE__ */ new Set();
28361
28816
  const roots = /* @__PURE__ */ new Set();
28362
28817
  for (const configuredRoot of options2.roots) {
28363
- if (!path11.isAbsolute(configuredRoot)) {
28818
+ if (!path13.isAbsolute(configuredRoot)) {
28364
28819
  diagnose({ code: "invalidRoot" });
28365
28820
  continue;
28366
28821
  }
@@ -28390,7 +28845,7 @@ async function loadHarnessPlugins(options2) {
28390
28845
  for (const directory of directories) {
28391
28846
  try {
28392
28847
  const file2 = await pluginResourcePath(root, `${directory.name}/manifest.json`);
28393
- const pluginRoot = await realpath2(path11.join(root, directory.name));
28848
+ const pluginRoot = await realpath2(path13.join(root, directory.name));
28394
28849
  await pluginResourcePath(pluginRoot, "manifest.json");
28395
28850
  const manifest = harnessPluginManifestSchema.parse(
28396
28851
  JSON.parse(
@@ -28485,28 +28940,28 @@ async function loadHarnessPlugins(options2) {
28485
28940
  }
28486
28941
 
28487
28942
  // 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";
28943
+ import { randomUUID as randomUUID7 } from "node:crypto";
28944
+ import { mkdir as mkdir5, readFile as readFile7, rename as rename4, rm as rm5, stat as stat4, writeFile as writeFile3 } from "node:fs/promises";
28945
+ import os4 from "node:os";
28946
+ import path14 from "node:path";
28492
28947
  var HarnessLaunchSettingsStore = class {
28493
28948
  #directory;
28494
28949
  #initial = /* @__PURE__ */ new Map();
28495
28950
  constructor(environment) {
28496
- this.#directory = path12.join(
28497
- environment.CODEXHOST_DATA_DIR ? path12.resolve(environment.CODEXHOST_DATA_DIR) : path12.join(os3.homedir(), ".codexhost"),
28951
+ this.#directory = path14.join(
28952
+ environment.CODEXHOST_DATA_DIR ? path14.resolve(environment.CODEXHOST_DATA_DIR) : path14.join(os4.homedir(), ".codexhost"),
28498
28953
  "harness-launch-settings"
28499
28954
  );
28500
28955
  }
28501
28956
  #file(id2) {
28502
- return path12.join(this.#directory, `${harnessPluginIdSchema.parse(id2)}.json`);
28957
+ return path14.join(this.#directory, `${harnessPluginIdSchema.parse(id2)}.json`);
28503
28958
  }
28504
28959
  async #read(id2) {
28505
28960
  try {
28506
28961
  const value2 = harnessLaunchPathSchema.parse(
28507
- JSON.parse(await readFile6(this.#file(id2), "utf8"))
28962
+ JSON.parse(await readFile7(this.#file(id2), "utf8"))
28508
28963
  );
28509
- if (!path12.isAbsolute(value2)) throw new Error("Expected an absolute entrypoint path");
28964
+ if (!path14.isAbsolute(value2)) throw new Error("Expected an absolute entrypoint path");
28510
28965
  return value2;
28511
28966
  } catch (error51) {
28512
28967
  if (error51 && typeof error51 === "object" && "code" in error51 && error51.code === "ENOENT")
@@ -28532,22 +28987,22 @@ var HarnessLaunchSettingsStore = class {
28532
28987
  const initial = await this.initialCommand(id2) ?? null;
28533
28988
  const file2 = this.#file(id2);
28534
28989
  if (value2 === null) {
28535
- await rm4(file2, { force: true });
28990
+ await rm5(file2, { force: true });
28536
28991
  } else {
28537
28992
  value2 = harnessLaunchPathSchema.parse(value2);
28538
- if (!path12.isAbsolute(value2))
28993
+ if (!path14.isAbsolute(value2))
28539
28994
  throw new Error("Use an absolute entrypoint path without arguments");
28540
- const metadata = await stat3(value2).catch(() => void 0);
28995
+ const metadata = await stat4(value2).catch(() => void 0);
28541
28996
  if (!metadata?.isDirectory() && !metadata?.isFile())
28542
28997
  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`;
28998
+ await mkdir5(this.#directory, { recursive: true, mode: 448 });
28999
+ const temporary = `${file2}.${randomUUID7()}.tmp`;
28545
29000
  try {
28546
29001
  await writeFile3(temporary, `${JSON.stringify(value2)}
28547
29002
  `, { mode: 384, flag: "wx" });
28548
- await rename3(temporary, file2);
29003
+ await rename4(temporary, file2);
28549
29004
  } finally {
28550
- await rm4(temporary, { force: true });
29005
+ await rm5(temporary, { force: true });
28551
29006
  }
28552
29007
  }
28553
29008
  return { path: value2, restartRequired: value2 !== initial };
@@ -28710,11 +29165,11 @@ function spawnOfficialAppServerConnection(input) {
28710
29165
  }
28711
29166
 
28712
29167
  // packages/host-runtime/src/account/codex-account-control.ts
28713
- function isRecord9(value2) {
29168
+ function isRecord10(value2) {
28714
29169
  return typeof value2 === "object" && value2 !== null && !Array.isArray(value2);
28715
29170
  }
28716
29171
  function currentCodexAccountFromOfficialRead(result) {
28717
- if (!isRecord9(result) || !isRecord9(result.account) || result.account.type !== "chatgpt") {
29172
+ if (!isRecord10(result) || !isRecord10(result.account) || result.account.type !== "chatgpt") {
28718
29173
  return null;
28719
29174
  }
28720
29175
  const email3 = external_exports.string().email().max(320).safeParse(result.account.email);
@@ -28744,13 +29199,13 @@ var SingleNativeCodexAccount = class {
28744
29199
  };
28745
29200
 
28746
29201
  // packages/host-runtime/src/codex-runtime/official-runtime-owner.ts
28747
- import { randomUUID as randomUUID8 } from "node:crypto";
29202
+ import { randomUUID as randomUUID9 } from "node:crypto";
28748
29203
 
28749
29204
  // packages/host-runtime/src/official-request-broker.ts
28750
- import { randomUUID as randomUUID7 } from "node:crypto";
29205
+ import { randomUUID as randomUUID8 } from "node:crypto";
28751
29206
  var INTERNAL_REQUEST_PREFIX = "codexhost:official:";
28752
29207
  var MAX_RETIRED_IDS = 1024;
28753
- function isRecord10(value2) {
29208
+ function isRecord11(value2) {
28754
29209
  return typeof value2 === "object" && value2 !== null && !Array.isArray(value2);
28755
29210
  }
28756
29211
  var OfficialRequestBroker = class {
@@ -28763,7 +29218,7 @@ var OfficialRequestBroker = class {
28763
29218
  constructor(input) {
28764
29219
  this.#send = input.send;
28765
29220
  this.#timeoutMs = input.timeoutMs ?? 3e4;
28766
- this.#nextId = input.nextId ?? (() => `${INTERNAL_REQUEST_PREFIX}${randomUUID7()}`);
29221
+ this.#nextId = input.nextId ?? (() => `${INTERNAL_REQUEST_PREFIX}${randomUUID8()}`);
28767
29222
  }
28768
29223
  get pendingCount() {
28769
29224
  return this.#pending.size;
@@ -28793,7 +29248,7 @@ var OfficialRequestBroker = class {
28793
29248
  });
28794
29249
  }
28795
29250
  handle(value2) {
28796
- if (!isRecord10(value2) || typeof value2.id !== "string") return false;
29251
+ if (!isRecord11(value2) || typeof value2.id !== "string") return false;
28797
29252
  const pending = this.#pending.get(value2.id);
28798
29253
  if (!pending) return this.#retired.has(value2.id);
28799
29254
  clearTimeout(pending.timeout);
@@ -29117,7 +29572,7 @@ var OfficialRuntimeOwner = class {
29117
29572
  }
29118
29573
  #attach(role, output, onBackendStopped) {
29119
29574
  const client = {
29120
- id: randomUUID8(),
29575
+ id: randomUUID9(),
29121
29576
  role,
29122
29577
  output,
29123
29578
  ...onBackendStopped ? { onBackendStopped } : {},
@@ -29275,7 +29730,7 @@ var OfficialRuntimeOwner = class {
29275
29730
  if (!object4(value2)) return client.output(event);
29276
29731
  if (typeof value2.id === "string" || typeof value2.id === "number") {
29277
29732
  if (typeof value2.method === "string") {
29278
- const id2 = `codexhost:server:${client.id}:${event.generation}:${randomUUID8()}`;
29733
+ const id2 = `codexhost:server:${client.id}:${event.generation}:${randomUUID9()}`;
29279
29734
  client.serverRequests.set(id2, value2.id);
29280
29735
  const projected = { ...value2, id: id2 };
29281
29736
  return client.output({
@@ -29513,11 +29968,11 @@ function createOwnedConnectionBackend(factory) {
29513
29968
  }
29514
29969
 
29515
29970
  // packages/host-runtime/src/route-observation.ts
29516
- function isRecord11(value2) {
29971
+ function isRecord12(value2) {
29517
29972
  return typeof value2 === "object" && value2 !== null && !Array.isArray(value2);
29518
29973
  }
29519
29974
  function classifyThreadPurpose(request) {
29520
- return isRecord11(request.params) && request.params.ephemeral === true ? "ephemeral" : "conversation";
29975
+ return isRecord12(request.params) && request.params.ephemeral === true ? "ephemeral" : "conversation";
29521
29976
  }
29522
29977
  var RequestRouteObservationTracker = class {
29523
29978
  #nextCreateOrdinal = 0;
@@ -29542,13 +29997,13 @@ var RequestRouteObservationTracker = class {
29542
29997
  this.#createByThreadId.set(threadId2, tracked);
29543
29998
  }
29544
29999
  bindOfficialResponse(response) {
29545
- if (!isRecord11(response) || !("id" in response)) return;
30000
+ if (!isRecord12(response) || !("id" in response)) return;
29546
30001
  const tracked = this.#pendingByRequestId.get(response.id);
29547
30002
  if (!tracked) return;
29548
30003
  this.#pendingByRequestId.delete(response.id);
29549
30004
  const result = response.result;
29550
- const thread = isRecord11(result) ? result.thread : null;
29551
- if (isRecord11(thread) && typeof thread.id === "string") {
30005
+ const thread = isRecord12(result) ? result.thread : null;
30006
+ if (isRecord12(thread) && typeof thread.id === "string") {
29552
30007
  this.#createByThreadId.set(thread.id, tracked);
29553
30008
  }
29554
30009
  }
@@ -29670,25 +30125,25 @@ function resolveExternalSessionTreeIds(records) {
29670
30125
  const resolve = (start) => {
29671
30126
  const cached2 = resolved.get(start.hostThreadId);
29672
30127
  if (cached2) return cached2;
29673
- const path27 = [];
30128
+ const path28 = [];
29674
30129
  const visited = /* @__PURE__ */ new Set();
29675
30130
  let current = start;
29676
30131
  while (true) {
29677
30132
  const known = resolved.get(current.hostThreadId);
29678
30133
  if (known) {
29679
- for (const record3 of path27) resolved.set(record3.hostThreadId, known);
30134
+ for (const record3 of path28) resolved.set(record3.hostThreadId, known);
29680
30135
  return known;
29681
30136
  }
29682
30137
  if (visited.has(current.hostThreadId)) {
29683
30138
  throw new Error("External Thread Fork tree contains a cycle");
29684
30139
  }
29685
30140
  visited.add(current.hostThreadId);
29686
- path27.push(current);
30141
+ path28.push(current);
29687
30142
  const sourceId = current.subagent?.parentHostThreadId ?? current.forkSource?.hostThreadId;
29688
30143
  const source = sourceId ? byId.get(sourceId) : void 0;
29689
30144
  if (!source) {
29690
30145
  const root = current.hostThreadId;
29691
- for (const record3 of path27) resolved.set(record3.hostThreadId, root);
30146
+ for (const record3 of path28) resolved.set(record3.hostThreadId, root);
29692
30147
  return root;
29693
30148
  }
29694
30149
  current = source;
@@ -29742,11 +30197,11 @@ var OfficialThreadListError = class extends Error {
29742
30197
  }
29743
30198
  rpcError;
29744
30199
  };
29745
- function isRecord12(value2) {
30200
+ function isRecord13(value2) {
29746
30201
  return typeof value2 === "object" && value2 !== null && !Array.isArray(value2);
29747
30202
  }
29748
30203
  function officialThreadListPageFromResponse(response) {
29749
- if (isRecord12(response.error)) {
30204
+ if (isRecord13(response.error)) {
29750
30205
  if (!Number.isSafeInteger(response.error.code) || typeof response.error.message !== "string") {
29751
30206
  throw new Error("Official thread/list error response is invalid");
29752
30207
  }
@@ -29914,14 +30369,14 @@ var THREAD_USAGE_UPDATED_METHOD = "codexhost/thread/usage/updated";
29914
30369
  function delay3(milliseconds) {
29915
30370
  return new Promise((resolve) => setTimeout(resolve, milliseconds));
29916
30371
  }
29917
- function isRecord13(value2) {
30372
+ function isRecord14(value2) {
29918
30373
  return typeof value2 === "object" && value2 !== null && !Array.isArray(value2);
29919
30374
  }
29920
30375
  function isCreditsAdapter(adapter) {
29921
30376
  return typeof adapter.credits === "function";
29922
30377
  }
29923
30378
  function projectAccountCredits(value2) {
29924
- if (!isRecord13(value2)) return null;
30379
+ if (!isRecord14(value2)) return null;
29925
30380
  const rest = { ...value2 };
29926
30381
  delete rest.fetchedAt;
29927
30382
  const parsed = accountCreditsSnapshotSchema.safeParse(rest);
@@ -30044,12 +30499,12 @@ function classifyCreateRequestRoute(request, defaultAgent) {
30044
30499
  };
30045
30500
  }
30046
30501
  function requestObject(request) {
30047
- if (!isRecord13(request.params)) throw new Error(`${request.method} params must be an object`);
30502
+ if (!isRecord14(request.params)) throw new Error(`${request.method} params must be an object`);
30048
30503
  return request.params;
30049
30504
  }
30050
30505
  function requestText(params) {
30051
30506
  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");
30507
+ const text = params.input.filter((item) => isRecord14(item) && item.type === "text").map((item) => item.text).filter((value2) => typeof value2 === "string").join("\n");
30053
30508
  if (!text) throw new Error("turn/start must contain text input");
30054
30509
  return text;
30055
30510
  }
@@ -30103,6 +30558,7 @@ var AppServerHost = class {
30103
30558
  #accountInspections = new HarnessAccountInspectionCache();
30104
30559
  #externalRuntime;
30105
30560
  #externalSteering = new ExternalTurnSteering();
30561
+ #liveCommandCache = new LiveCommandCatalogCache();
30106
30562
  #repository;
30107
30563
  #pendingDesktopApprovals = /* @__PURE__ */ new Map();
30108
30564
  #pendingDesktopQuestions = /* @__PURE__ */ new Map();
@@ -30144,7 +30600,7 @@ var AppServerHost = class {
30144
30600
  this.#launchSettings = new HarnessLaunchSettingsStore(
30145
30601
  this.#options.pluginContext?.environment ?? environment
30146
30602
  );
30147
- const permanentHome = path13.resolve(environment.CODEX_HOME ?? path13.join(os4.homedir(), ".codex"));
30603
+ const permanentHome = path15.resolve(environment.CODEX_HOME ?? path15.join(os5.homedir(), ".codex"));
30148
30604
  this.#ownsOfficialRuntimeScope = options2.officialRuntimeScope === void 0;
30149
30605
  this.#officialRuntimeScope = options2.officialRuntimeScope ?? new OfficialRuntimeScope({
30150
30606
  diagnosticOutput: this.#options.diagnosticOutput,
@@ -30406,12 +30862,12 @@ var AppServerHost = class {
30406
30862
  for (const resolve of waiters) resolve();
30407
30863
  }
30408
30864
  #observeOfficialTurnStartResponse(value2) {
30409
- if (!isRecord13(value2) || !("id" in value2)) return;
30865
+ if (!isRecord14(value2) || !("id" in value2)) return;
30410
30866
  const threadId2 = this.#pendingOfficialTurnStarts.get(value2.id);
30411
30867
  if (!threadId2) return;
30412
30868
  this.#pendingOfficialTurnStarts.delete(value2.id);
30413
- const result = isRecord13(value2.result) ? value2.result : null;
30414
- const turn = result && isRecord13(result.turn) ? result.turn : null;
30869
+ const result = isRecord14(value2.result) ? value2.result : null;
30870
+ const turn = result && isRecord14(result.turn) ? result.turn : null;
30415
30871
  if (turn && typeof turn.id === "string") {
30416
30872
  this.#activeOfficialTurns.set(threadId2, turn.id);
30417
30873
  }
@@ -30425,7 +30881,7 @@ var AppServerHost = class {
30425
30881
  async #forwardDesktop() {
30426
30882
  for await (const frame of readLfFrames(this.#options.desktopInput)) {
30427
30883
  const parsed = parseJsonFrame(frame);
30428
- if (isRecord13(parsed) && parsed.method === "initialized" && !("id" in parsed)) {
30884
+ if (isRecord14(parsed) && parsed.method === "initialized" && !("id" in parsed)) {
30429
30885
  continue;
30430
30886
  }
30431
30887
  if (await this.#handleDesktopApprovalResponse(parsed)) continue;
@@ -30449,7 +30905,7 @@ var AppServerHost = class {
30449
30905
  }
30450
30906
  continue;
30451
30907
  }
30452
- const threadId2 = isRecord13(request.params) && typeof request.params.threadId === "string" ? request.params.threadId : void 0;
30908
+ const threadId2 = isRecord14(request.params) && typeof request.params.threadId === "string" ? request.params.threadId : void 0;
30453
30909
  this.#dispatchDesktopRequest(
30454
30910
  () => this.#desktopRequests.run(
30455
30911
  threadId2,
@@ -30677,7 +31133,7 @@ var AppServerHost = class {
30677
31133
  rpcError(request, -32602, "Invalid Harness command inspection params")
30678
31134
  );
30679
31135
  } else {
30680
- await this.#writeHarnessCommandCatalog(request, params.data.harnessId);
31136
+ await this.#writeHarnessCommandCatalog(request, params.data.harnessId, params.data.cwd);
30681
31137
  }
30682
31138
  return;
30683
31139
  }
@@ -30774,7 +31230,7 @@ var AppServerHost = class {
30774
31230
  return;
30775
31231
  }
30776
31232
  if (request.method === "thread/fork") {
30777
- const params = isRecord13(request.params) ? request.params : {};
31233
+ const params = isRecord14(request.params) ? request.params : {};
30778
31234
  const resolution = typeof params.threadId === "string" ? await this.#resolveExternalThread(params.threadId) : { kind: "official" };
30779
31235
  if (resolution.kind === "error") {
30780
31236
  await this.#writer.json(rpcError(request, resolution.error.code, resolution.error.message));
@@ -30795,7 +31251,7 @@ var AppServerHost = class {
30795
31251
  }
30796
31252
  }
30797
31253
  if (request.method === "thread/revert") {
30798
- const params = isRecord13(request.params) ? request.params : {};
31254
+ const params = isRecord14(request.params) ? request.params : {};
30799
31255
  const resolution = typeof params.threadId === "string" ? await this.#resolveExternalThread(params.threadId) : { kind: "official" };
30800
31256
  if (resolution.kind === "error") {
30801
31257
  await this.#writer.json(rpcError(request, resolution.error.code, resolution.error.message));
@@ -30816,7 +31272,7 @@ var AppServerHost = class {
30816
31272
  }
30817
31273
  }
30818
31274
  if (request.method === "thread/rollback") {
30819
- const params = isRecord13(request.params) ? request.params : {};
31275
+ const params = isRecord14(request.params) ? request.params : {};
30820
31276
  const resolution = typeof params.threadId === "string" ? await this.#resolveExternalThread(params.threadId) : { kind: "official" };
30821
31277
  if (resolution.kind === "error") {
30822
31278
  await this.#writer.json(rpcError(request, resolution.error.code, resolution.error.message));
@@ -30972,7 +31428,7 @@ var AppServerHost = class {
30972
31428
  return;
30973
31429
  }
30974
31430
  }
30975
- if (request.method.startsWith("thread/") && !EXPLICIT_EXTERNAL_THREAD_METHODS.has(request.method) && isRecord13(request.params) && typeof request.params.threadId === "string") {
31431
+ if (request.method.startsWith("thread/") && !EXPLICIT_EXTERNAL_THREAD_METHODS.has(request.method) && isRecord14(request.params) && typeof request.params.threadId === "string") {
30976
31432
  const location = await this.#locateExternalThread(request.params.threadId);
30977
31433
  if (await this.#writeResolutionError(request, location)) return;
30978
31434
  if (location.kind === "external") {
@@ -30982,10 +31438,30 @@ var AppServerHost = class {
30982
31438
  return;
30983
31439
  }
30984
31440
  }
30985
- await this.#forwardOfficialRequest(request, frame);
31441
+ await this.#forwardOfficialRequest(
31442
+ request,
31443
+ await this.#rewriteOfficialDelegationMentions(request, frame)
31444
+ );
31445
+ }
31446
+ /** Native Codex Turns: turn `#` delegation chips into an explicit Skill-backed request. */
31447
+ async #rewriteOfficialDelegationMentions(request, frame) {
31448
+ if (request.method !== "turn/start" && request.method !== "turn/steer") return frame;
31449
+ if (!isRecord14(request.params) || !Array.isArray(request.params.input)) return frame;
31450
+ const input = request.params.input;
31451
+ if (!input.some(
31452
+ (item) => isRecord14(item) && typeof item.text === "string" && item.text.includes(DELEGATION_MENTION_PATH_PREFIX)
31453
+ )) {
31454
+ return frame;
31455
+ }
31456
+ const rewritten = rewriteDelegationMentionInput(input, await managedDelegationSkillReference());
31457
+ if (!rewritten) return frame;
31458
+ return encodeJsonFrame({
31459
+ ...request,
31460
+ params: { ...request.params, input: rewritten }
31461
+ });
30986
31462
  }
30987
31463
  async #forwardOfficialNonRequest(value2, frame) {
30988
- const response = isRecord13(value2) ? value2 : null;
31464
+ const response = isRecord14(value2) ? value2 : null;
30989
31465
  const request = response && (typeof response.id === "string" || typeof response.id === "number") ? this.#officialServerRequests.get(response.id) : null;
30990
31466
  if (request !== void 0 && response) {
30991
31467
  this.#officialServerRequests.delete(response.id);
@@ -31014,7 +31490,7 @@ var AppServerHost = class {
31014
31490
  const parsed = input.value;
31015
31491
  this.#observeOfficialTurnStartResponse(parsed);
31016
31492
  let forwarded = parsed;
31017
- if (isRecord13(parsed) && typeof parsed.method === "string" && "id" in parsed) {
31493
+ if (isRecord14(parsed) && typeof parsed.method === "string" && "id" in parsed) {
31018
31494
  const originalId = parsed.id;
31019
31495
  if (typeof originalId === "string" || typeof originalId === "number") {
31020
31496
  const forwardedId = `codexhost:official:${++this.#nextOfficialServerRequestId}`;
@@ -31022,7 +31498,7 @@ var AppServerHost = class {
31022
31498
  forwarded = { ...parsed, id: forwardedId };
31023
31499
  }
31024
31500
  }
31025
- const accountScopedNotification = isRecord13(parsed) && typeof parsed.method === "string" && (parsed.method === "account/updated" || parsed.method.startsWith("account/rateLimits/"));
31501
+ const accountScopedNotification = isRecord14(parsed) && typeof parsed.method === "string" && (parsed.method === "account/updated" || parsed.method.startsWith("account/rateLimits/"));
31026
31502
  if (accountScopedNotification) {
31027
31503
  if (parsed.method === "account/updated") this.#officialRateLimits.reset(input.accountId);
31028
31504
  }
@@ -31091,10 +31567,10 @@ var AppServerHost = class {
31091
31567
  }
31092
31568
  }
31093
31569
  async #observeOfficialTurnLifecycle(value2) {
31094
- if (!isRecord13(value2) || !isRecord13(value2.params)) return;
31570
+ if (!isRecord14(value2) || !isRecord14(value2.params)) return;
31095
31571
  const params = value2.params;
31096
31572
  if (value2.method === "turn/started" && typeof params.threadId === "string") {
31097
- const turn = isRecord13(params.turn) ? params.turn : null;
31573
+ const turn = isRecord14(params.turn) ? params.turn : null;
31098
31574
  if (turn && typeof turn.id === "string") {
31099
31575
  this.#forgetPendingOfficialTurnStarts(params.threadId);
31100
31576
  this.#activeOfficialTurns.set(params.threadId, turn.id);
@@ -31107,7 +31583,7 @@ var AppServerHost = class {
31107
31583
  const delegation = await this.#repository.getDelegationByChild(
31108
31584
  hostThreadIdSchema.parse(params.threadId)
31109
31585
  );
31110
- const turn = isRecord13(params.turn) ? params.turn : null;
31586
+ const turn = isRecord14(params.turn) ? params.turn : null;
31111
31587
  const status = turn?.status === "failed" ? "failed" : turn?.status === "interrupted" || turn?.status === "cancelled" ? "interrupted" : "completed";
31112
31588
  if (this.#pendingOfficialDelegationThreads.has(params.threadId)) {
31113
31589
  this.#pendingOfficialTerminalStatuses.set(params.threadId, status);
@@ -31137,28 +31613,28 @@ var AppServerHost = class {
31137
31613
  }
31138
31614
  async #readOfficialThreadCwd(threadId2) {
31139
31615
  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;
31616
+ if (isRecord14(response.error)) return void 0;
31617
+ const result = isRecord14(response.result) ? response.result : null;
31618
+ const thread = result && isRecord14(result.thread) ? result.thread : null;
31143
31619
  return thread && typeof thread.cwd === "string" && thread.cwd.trim() ? thread.cwd : void 0;
31144
31620
  }
31145
31621
  async #inspectOfficialDelegationTarget(input) {
31146
31622
  const response = await this.#requestOfficial("model/list", {});
31147
- if (isRecord13(response.error)) {
31623
+ if (isRecord14(response.error)) {
31148
31624
  throw new DelegationControlError(
31149
31625
  "DELEGATION_FAILED",
31150
31626
  typeof response.error.message === "string" ? response.error.message : "Official Model catalog could not be read"
31151
31627
  );
31152
31628
  }
31153
- const result = isRecord13(response.result) ? response.result : null;
31629
+ const result = isRecord14(response.result) ? response.result : null;
31154
31630
  const data = result && Array.isArray(result.data) ? result.data : [];
31155
31631
  const thinkingById = /* @__PURE__ */ new Map();
31156
31632
  const models = data.flatMap((candidate) => {
31157
- if (!isRecord13(candidate) || typeof candidate.model !== "string" || !candidate.model.trim()) {
31633
+ if (!isRecord14(candidate) || typeof candidate.model !== "string" || !candidate.model.trim()) {
31158
31634
  return [];
31159
31635
  }
31160
31636
  const supportedThinkingOptionIds = Array.isArray(candidate.supportedReasoningEfforts) ? candidate.supportedReasoningEfforts.flatMap((option) => {
31161
- if (!isRecord13(option) || typeof option.reasoningEffort !== "string" || !option.reasoningEffort.trim()) {
31637
+ if (!isRecord14(option) || typeof option.reasoningEffort !== "string" || !option.reasoningEffort.trim()) {
31162
31638
  return [];
31163
31639
  }
31164
31640
  const id2 = harnessThinkingOptionIdSchema.safeParse(option.reasoningEffort);
@@ -31178,9 +31654,9 @@ var AppServerHost = class {
31178
31654
  ];
31179
31655
  });
31180
31656
  const defaultEntry = data.find(
31181
- (candidate) => isRecord13(candidate) && candidate.isDefault === true
31657
+ (candidate) => isRecord14(candidate) && candidate.isDefault === true
31182
31658
  );
31183
- const defaultModel = isRecord13(defaultEntry) && typeof defaultEntry.model === "string" ? encodeOfficialCodexModelRef(defaultEntry.model) : void 0;
31659
+ const defaultModel = isRecord14(defaultEntry) && typeof defaultEntry.model === "string" ? encodeOfficialCodexModelRef(defaultEntry.model) : void 0;
31184
31660
  return {
31185
31661
  harnessId: input.harnessId,
31186
31662
  inspection: {
@@ -31210,7 +31686,7 @@ var AppServerHost = class {
31210
31686
  throw new DelegationControlError("INVALID_ARGUMENT", "Official Model Ref is invalid");
31211
31687
  }
31212
31688
  const nativeModelId = requestedModel ? decodeOfficialCodexModelRef(requestedModel) : void 0;
31213
- const digest2 = createHash7("sha256").update(
31689
+ const digest2 = createHash8("sha256").update(
31214
31690
  JSON.stringify({
31215
31691
  task: input.task,
31216
31692
  cwd: input.cwd,
@@ -31286,8 +31762,8 @@ var AppServerHost = class {
31286
31762
  ephemeral: false,
31287
31763
  historyMode: "paginated"
31288
31764
  });
31289
- const startedResult = isRecord13(started.result) ? started.result : null;
31290
- const thread = startedResult && isRecord13(startedResult.thread) ? startedResult.thread : null;
31765
+ const startedResult = isRecord14(started.result) ? started.result : null;
31766
+ const thread = startedResult && isRecord14(startedResult.thread) ? startedResult.thread : null;
31291
31767
  const threadId2 = thread && typeof thread.id === "string" ? thread.id : null;
31292
31768
  if (!threadId2) throw new Error("Official thread/start returned no Thread identity");
31293
31769
  this.#pendingOfficialDelegationThreads.add(threadId2);
@@ -31299,8 +31775,8 @@ var AppServerHost = class {
31299
31775
  ...nativeModelId ? { model: nativeModelId } : {},
31300
31776
  ...input.thinkingOptionId ? { effort: input.thinkingOptionId } : {}
31301
31777
  });
31302
- const turnResult = isRecord13(turn.result) ? turn.result : null;
31303
- const turnValue = turnResult && isRecord13(turnResult.turn) ? turnResult.turn : null;
31778
+ const turnResult = isRecord14(turn.result) ? turn.result : null;
31779
+ const turnValue = turnResult && isRecord14(turnResult.turn) ? turnResult.turn : null;
31304
31780
  const parsedTurnId = turnValue && typeof turnValue.id === "string" ? turnValue.id : null;
31305
31781
  if (!parsedTurnId) throw new Error("Official turn/start returned no Turn identity");
31306
31782
  turnId = parsedTurnId;
@@ -31311,7 +31787,7 @@ var AppServerHost = class {
31311
31787
  throw error51;
31312
31788
  }
31313
31789
  this.#activeOfficialTurns.set(threadId2, turnId);
31314
- const delegationId = hostThreadIdSchema.parse(randomUUID9());
31790
+ const delegationId = hostThreadIdSchema.parse(randomUUID10());
31315
31791
  try {
31316
31792
  const source = await this.#repository.find(input.parentThreadId);
31317
31793
  const pendingTerminal = this.#pendingOfficialTerminalStatuses.get(threadId2);
@@ -31370,27 +31846,27 @@ var AppServerHost = class {
31370
31846
  threadId: input.threadId,
31371
31847
  includeTurns: true
31372
31848
  });
31373
- if (isRecord13(current.error) || !isRecord13(current.result)) {
31849
+ if (isRecord14(current.error) || !isRecord14(current.result)) {
31374
31850
  throw new DelegationControlError("THREAD_NOT_FOUND", "Official Thread was not found");
31375
31851
  }
31376
- const currentThread = isRecord13(current.result.thread) ? current.result.thread : null;
31852
+ const currentThread = isRecord14(current.result.thread) ? current.result.thread : null;
31377
31853
  const currentTurns = currentThread && Array.isArray(currentThread.turns) ? currentThread.turns : [];
31378
31854
  const latestTurn = currentTurns.at(-1);
31379
- if (currentThread && isRecord13(currentThread.status) && currentThread.status.type === "active" || isRecord13(latestTurn) && (latestTurn.status === "inProgress" || latestTurn.status === "running")) {
31855
+ if (currentThread && isRecord14(currentThread.status) && currentThread.status.type === "active" || isRecord14(latestTurn) && (latestTurn.status === "inProgress" || latestTurn.status === "running")) {
31380
31856
  throw new DelegationControlError("THREAD_BUSY", "Thread already has an active Turn");
31381
31857
  }
31382
31858
  const response = await this.#requestOfficial("turn/start", {
31383
31859
  threadId: input.threadId,
31384
31860
  input: [{ type: "text", text: input.message }]
31385
31861
  });
31386
- if (isRecord13(response.error)) {
31862
+ if (isRecord14(response.error)) {
31387
31863
  throw new DelegationControlError(
31388
31864
  "DELEGATION_FAILED",
31389
31865
  typeof response.error.message === "string" ? response.error.message : "Turn start failed"
31390
31866
  );
31391
31867
  }
31392
- const result = isRecord13(response.result) ? response.result : null;
31393
- const turn = result && isRecord13(result.turn) ? result.turn : null;
31868
+ const result = isRecord14(response.result) ? response.result : null;
31869
+ const turn = result && isRecord14(result.turn) ? result.turn : null;
31394
31870
  const turnId = turn && typeof turn.id === "string" ? turn.id : null;
31395
31871
  if (!turnId) throw new Error("Official turn/start returned no Turn identity");
31396
31872
  this.#activeOfficialTurns.set(input.threadId, turnId);
@@ -31412,13 +31888,13 @@ var AppServerHost = class {
31412
31888
  threadId: input.threadId,
31413
31889
  includeTurns: true
31414
31890
  });
31415
- if (isRecord13(current.error) || !isRecord13(current.result)) {
31891
+ if (isRecord14(current.error) || !isRecord14(current.result)) {
31416
31892
  throw new DelegationControlError("THREAD_NOT_FOUND", "Official Thread was not found");
31417
31893
  }
31418
- const currentThread = isRecord13(current.result.thread) ? current.result.thread : null;
31894
+ const currentThread = isRecord14(current.result.thread) ? current.result.thread : null;
31419
31895
  const currentTurns = currentThread && Array.isArray(currentThread.turns) ? currentThread.turns : [];
31420
31896
  const latestTurn = currentTurns.at(-1);
31421
- if (isRecord13(latestTurn) && typeof latestTurn.id === "string" && (latestTurn.status === "inProgress" || latestTurn.status === "running")) {
31897
+ if (isRecord14(latestTurn) && typeof latestTurn.id === "string" && (latestTurn.status === "inProgress" || latestTurn.status === "running")) {
31422
31898
  turnId = latestTurn.id;
31423
31899
  this.#activeOfficialTurns.set(input.threadId, turnId);
31424
31900
  } else {
@@ -31429,7 +31905,7 @@ var AppServerHost = class {
31429
31905
  threadId: input.threadId,
31430
31906
  turnId
31431
31907
  });
31432
- if (isRecord13(response.error)) {
31908
+ if (isRecord14(response.error)) {
31433
31909
  throw new DelegationControlError(
31434
31910
  "DELEGATION_FAILED",
31435
31911
  typeof response.error.message === "string" ? response.error.message : "Turn cancel failed"
@@ -31442,18 +31918,18 @@ var AppServerHost = class {
31442
31918
  threadId: input.threadId,
31443
31919
  includeTurns: true
31444
31920
  });
31445
- if (isRecord13(response.error)) {
31921
+ if (isRecord14(response.error)) {
31446
31922
  throw new DelegationControlError(
31447
31923
  "THREAD_NOT_FOUND",
31448
31924
  typeof response.error.message === "string" ? response.error.message : "Official Thread was not found"
31449
31925
  );
31450
31926
  }
31451
- const result = isRecord13(response.result) ? response.result : null;
31452
- const thread = result && isRecord13(result.thread) ? result.thread : null;
31927
+ const result = isRecord14(response.result) ? response.result : null;
31928
+ const thread = result && isRecord14(result.thread) ? result.thread : null;
31453
31929
  if (!thread)
31454
31930
  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";
31931
+ const turns = Array.isArray(thread.turns) ? thread.turns.filter((turn) => isRecord14(turn)) : [];
31932
+ const running = this.#activeOfficialTurns.has(input.threadId) || isRecord14(thread.status) && thread.status.type === "active";
31457
31933
  const snapshot = projectDelegationThreadSnapshot({
31458
31934
  threadId: input.threadId,
31459
31935
  harnessId: "codex",
@@ -31475,7 +31951,7 @@ var AppServerHost = class {
31475
31951
  async #listDelegationThreads(input) {
31476
31952
  const [sortKey, sortDirection2] = input.sort.split("-");
31477
31953
  const request = {
31478
- id: `codexhost:delegation-list:${randomUUID9()}`,
31954
+ id: `codexhost:delegation-list:${randomUUID10()}`,
31479
31955
  method: "thread/list",
31480
31956
  params: {
31481
31957
  cwd: input.cwd ? [input.cwd] : null,
@@ -31503,7 +31979,7 @@ var AppServerHost = class {
31503
31979
  threads: result.data.flatMap((entry) => {
31504
31980
  if (typeof entry.id !== "string") return [];
31505
31981
  const record3 = records.find((candidate) => candidate.hostThreadId === entry.id);
31506
- const status = isRecord13(entry.status) && entry.status.type === "active" ? "running" : "completed";
31982
+ const status = isRecord14(entry.status) && entry.status.type === "active" ? "running" : "completed";
31507
31983
  return [
31508
31984
  {
31509
31985
  threadId: entry.id,
@@ -31823,21 +32299,67 @@ var AppServerHost = class {
31823
32299
  await this.#writer.json(rpcEnvelope(request, { result: { commands: [] } }));
31824
32300
  return;
31825
32301
  }
31826
- await this.#writeHarnessCommandCatalog(request, location.record.harnessId);
32302
+ const loaded = this.#externalRuntime.get(params.data.threadId);
32303
+ if (loaded) {
32304
+ const catalog = await this.#inspectLoadedCommands(loaded);
32305
+ if (catalog) {
32306
+ await this.#writer.json(rpcEnvelope(request, { result: jsonValueSchema.parse(catalog) }));
32307
+ return;
32308
+ }
32309
+ }
32310
+ await this.#writeHarnessCommandCatalog(
32311
+ request,
32312
+ location.record.harnessId,
32313
+ loaded?.cwd ?? location.record.cwd,
32314
+ params.data.threadId
32315
+ );
31827
32316
  }
31828
- async #writeHarnessCommandCatalog(request, harnessId) {
32317
+ /**
32318
+ * Catalog of a loaded Session, marked live or static. A live catalog is
32319
+ * remembered for its Harness and workspace so later drafts there can show it.
32320
+ */
32321
+ async #inspectLoadedCommands(thread) {
32322
+ if (!thread.session.commands) return null;
32323
+ const catalog = await inspectLiveCommandCatalog(thread.session.commands);
32324
+ if (!catalog) return null;
32325
+ const staticCatalog = this.#externalAdapters.get(thread.harnessId)?.commandCatalog;
32326
+ if (staticCatalog && !isLiveCommandCatalog(catalog, staticCatalog)) return null;
32327
+ const live = { ...catalog, source: "live" };
32328
+ this.#liveCommandCache.remember(thread.harnessId, thread.cwd, live);
32329
+ return live;
32330
+ }
32331
+ async #writeHarnessCommandCatalog(request, harnessId, cwd, inspectedThreadId) {
31829
32332
  await this.#waitForPlugins();
31830
32333
  const adapter = this.#externalAdapters.get(harnessId);
31831
32334
  if (!adapter) {
31832
32335
  await this.#writer.json(rpcError(request, -32077, `Harness '${harnessId}' is unavailable`));
31833
32336
  return;
31834
32337
  }
32338
+ let catalog;
31835
32339
  try {
31836
- const catalog = harnessCommandCatalogSchema.parse(adapter.commandCatalog ?? { commands: [] });
31837
- await this.#writer.json(rpcEnvelope(request, { result: jsonValueSchema.parse(catalog) }));
32340
+ catalog = harnessCommandCatalogSchema.parse({
32341
+ ...adapter.commandCatalog ?? { commands: [] },
32342
+ ...adapter.liveCommandCatalog ? { source: "static" } : {}
32343
+ });
31838
32344
  } catch {
31839
32345
  await this.#writer.json(rpcError(request, -32078, "Harness command catalog is invalid"));
32346
+ return;
31840
32347
  }
32348
+ if (cwd && adapter.liveCommandCatalog) {
32349
+ for (const thread of this.#externalRuntime.values()) {
32350
+ if (thread.id === inspectedThreadId) continue;
32351
+ if (thread.harnessId !== harnessId || !sameWorkspace(thread.cwd, cwd)) continue;
32352
+ const live = await this.#inspectLoadedCommands(thread);
32353
+ if (live) {
32354
+ catalog = live;
32355
+ break;
32356
+ }
32357
+ }
32358
+ if (catalog.source === "static") {
32359
+ catalog = this.#liveCommandCache.lookup(harnessId, cwd) ?? catalog;
32360
+ }
32361
+ }
32362
+ await this.#writer.json(rpcEnvelope(request, { result: jsonValueSchema.parse(catalog) }));
31841
32363
  }
31842
32364
  async #executeThreadCommand(request) {
31843
32365
  const params = threadCommandExecuteParamsSchema.safeParse(request.params);
@@ -31889,39 +32411,43 @@ var AppServerHost = class {
31889
32411
  return;
31890
32412
  }
31891
32413
  try {
31892
- await this.#startExternalCommand(
31893
- request,
32414
+ const started = await this.#beginExternalCommand(
31894
32415
  thread,
31895
32416
  params.commandId,
31896
32417
  params.arguments,
31897
- params.turnId,
31898
- "command"
32418
+ params.turnId
31899
32419
  );
32420
+ try {
32421
+ const result = threadCommandExecuteResultSchema.parse({
32422
+ accepted: true,
32423
+ turnId: started.turnId
32424
+ });
32425
+ await this.#writer.json(rpcEnvelope(request, { result: jsonValueSchema.parse(result) }));
32426
+ } finally {
32427
+ started.gate.resolve();
32428
+ }
31900
32429
  } catch (error51) {
31901
32430
  this.#diagnose(error51);
31902
32431
  await this.#writer.json(
31903
- rpcError(request, -32073, `External Harness command failed: ${errorMessage3(error51)}`)
32432
+ error51 instanceof ExternalCommandError ? rpcError(request, error51.code, error51.message) : rpcError(request, -32073, `External Harness command failed: ${errorMessage3(error51)}`)
31904
32433
  );
31905
32434
  }
31906
32435
  } finally {
31907
32436
  this.#pendingExternalCommandRequests.delete(thread.id);
31908
32437
  }
31909
32438
  }
31910
- async #startExternalCommand(request, thread, commandId, arguments_2, requestedTurnId, responseKind) {
32439
+ async #beginExternalCommand(thread, commandId, arguments_2, requestedTurnId) {
31911
32440
  const commands = thread.session.commands;
31912
32441
  if (!commands) {
31913
- await this.#writer.json(
31914
- rpcError(request, -32078, "External Harness does not expose commands")
31915
- );
31916
- return;
32442
+ throw new ExternalCommandError(-32078, "External Harness does not expose commands");
31917
32443
  }
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;
32444
+ if (this.#closeRequested || this.#externalRuntime.get(thread.id) !== thread) {
32445
+ throw new ExternalCommandError(-32073, "External Thread is no longer available");
32446
+ }
32447
+ if (thread.running || thread.activeTurnId) {
32448
+ throw new ExternalCommandError(-32072, "External Thread already has an active operation");
31923
32449
  }
31924
- const turnId = requestedTurnId ?? hostTurnIdSchema.parse(randomUUID9());
32450
+ const turnId = requestedTurnId ?? hostTurnIdSchema.parse(randomUUID10());
31925
32451
  const projection = {
31926
32452
  projector: new CodexTurnProjector({
31927
32453
  threadId: thread.id,
@@ -31936,13 +32462,14 @@ var AppServerHost = class {
31936
32462
  thread.projectedTurns.set(turnId, projection);
31937
32463
  thread.responseGates.set(turnId, gate);
31938
32464
  thread.ephemeralTurnIds.add(turnId);
31939
- let result;
31940
32465
  try {
31941
- result = await commands.execute({
32466
+ const result = await commands.execute({
31942
32467
  turnId,
31943
32468
  commandId,
31944
32469
  ...arguments_2 ? { arguments: arguments_2 } : {}
31945
32470
  });
32471
+ if (!result.ok) throw new ExternalCommandError(-32073, result.error.message);
32472
+ return { turnId: result.value.turnId, turn: projection.projector.pendingTurn(), gate };
31946
32473
  } catch (error51) {
31947
32474
  thread.running = false;
31948
32475
  thread.activeTurnId = null;
@@ -31953,28 +32480,6 @@ var AppServerHost = class {
31953
32480
  this.#signalActiveWorkChanged();
31954
32481
  throw error51;
31955
32482
  }
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
32483
  }
31979
32484
  async #selectThreadModel(request) {
31980
32485
  const params = threadModelSelectParamsSchema.safeParse(request.params);
@@ -32597,10 +33102,10 @@ var AppServerHost = class {
32597
33102
  ...typeof params.serviceTier === "string" ? { serviceTier: params.serviceTier } : {}
32598
33103
  });
32599
33104
  try {
32600
- if (params.initialTurnsPage !== void 0 && params.initialTurnsPage !== null && !isRecord13(params.initialTurnsPage)) {
33105
+ if (params.initialTurnsPage !== void 0 && params.initialTurnsPage !== null && !isRecord14(params.initialTurnsPage)) {
32601
33106
  throw new ExternalHistoryRequestError("initialTurnsPage must be an object");
32602
33107
  }
32603
- const initialPageParams = isRecord13(params.initialTurnsPage) ? params.initialTurnsPage : null;
33108
+ const initialPageParams = isRecord14(params.initialTurnsPage) ? params.initialTurnsPage : null;
32604
33109
  const initialTurnsPage = initialPageParams ? listExternalTurns(turns, initialPageParams) : null;
32605
33110
  const paginated = thread.record.historyMode === "paginated";
32606
33111
  const turnsBackwardsCursor = paginated ? listExternalTurns(turns, { limit: 1, itemsView: "notLoaded" }).backwardsCursor : null;
@@ -32695,53 +33200,8 @@ var AppServerHost = class {
32695
33200
  await this.#writer.json(rpcError(request, -32602, errorMessage3(error51)));
32696
33201
  return;
32697
33202
  }
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
33203
  try {
32744
- const started = await this.#beginExternalTurn(thread, text);
33204
+ const started = await this.#beginExternalInputTurn(thread, text);
32745
33205
  try {
32746
33206
  await this.#writer.json(rpcEnvelope(request, { result: { turn: started.turn } }));
32747
33207
  } finally {
@@ -32751,7 +33211,7 @@ var AppServerHost = class {
32751
33211
  await this.#writer.json(
32752
33212
  rpcError(
32753
33213
  request,
32754
- error51 instanceof ExternalSteerError ? error51.code : -32073,
33214
+ error51 instanceof ExternalSteerError || error51 instanceof ExternalCommandError ? error51.code : -32073,
32755
33215
  errorMessage3(error51)
32756
33216
  )
32757
33217
  );
@@ -32762,7 +33222,7 @@ var AppServerHost = class {
32762
33222
  const started = await this.#externalSteering.run(
32763
33223
  thread,
32764
33224
  requestObject(request),
32765
- (text) => this.#beginExternalTurn(thread, text)
33225
+ (text, assertActive) => this.#beginExternalInputTurn(thread, text, assertActive)
32766
33226
  );
32767
33227
  try {
32768
33228
  await this.#writer.json(rpcEnvelope(request, { result: { turnId: started.turnId } }));
@@ -32773,7 +33233,7 @@ var AppServerHost = class {
32773
33233
  await this.#writer.json(
32774
33234
  rpcError(
32775
33235
  request,
32776
- error51 instanceof ExternalSteerError ? error51.code : -32074,
33236
+ error51 instanceof ExternalSteerError || error51 instanceof ExternalCommandError ? error51.code : -32074,
32777
33237
  errorMessage3(error51)
32778
33238
  )
32779
33239
  );
@@ -32781,6 +33241,37 @@ var AppServerHost = class {
32781
33241
  this.#signalActiveWorkChanged();
32782
33242
  }
32783
33243
  }
33244
+ /** Keep command restoration and dispatch identical for start and steer submissions. */
33245
+ async #beginExternalInputTurn(thread, inputText, assertActive) {
33246
+ const text = restoreHarnessCommandMentions(inputText);
33247
+ const commands = thread.session.commands;
33248
+ if (!commands || !isExternalCommandCandidate(text)) {
33249
+ assertActive?.();
33250
+ return this.#beginExternalTurn(thread, text);
33251
+ }
33252
+ this.#pendingExternalCommandRequests.add(thread.id);
33253
+ try {
33254
+ const adapter = this.#externalAdapters.get(thread.harnessId);
33255
+ const command = await resolveExternalCommand(commands, text, {
33256
+ liveCatalogPending: (catalog) => adapter?.liveCommandCatalog === true && !isLiveCommandCatalog(catalog, adapter.commandCatalog ?? { commands: [] })
33257
+ });
33258
+ assertActive?.();
33259
+ if (!command) {
33260
+ this.#pendingExternalCommandRequests.delete(thread.id);
33261
+ return await this.#beginExternalTurn(thread, text);
33262
+ }
33263
+ return await this.#beginExternalCommand(thread, command.commandId, command.arguments);
33264
+ } catch (error51) {
33265
+ if (error51 instanceof ExternalCommandError || error51 instanceof ExternalSteerError) throw error51;
33266
+ this.#diagnose(error51);
33267
+ throw new ExternalCommandError(
33268
+ -32073,
33269
+ `External Harness command failed: ${errorMessage3(error51)}`
33270
+ );
33271
+ } finally {
33272
+ this.#pendingExternalCommandRequests.delete(thread.id);
33273
+ }
33274
+ }
32784
33275
  async #beginExternalTurn(thread, text) {
32785
33276
  if (this.#closeRequested || this.#externalRuntime.get(thread.id) !== thread) {
32786
33277
  throw new ExternalSteerError(-32073, "External Thread is no longer available");
@@ -32788,7 +33279,7 @@ var AppServerHost = class {
32788
33279
  if (thread.running || thread.activeTurnId || this.#pendingExternalCommandRequests.has(thread.id)) {
32789
33280
  throw new ExternalSteerError(-32072, "External Thread already has an active Turn");
32790
33281
  }
32791
- const turnId = hostTurnIdSchema.parse(randomUUID9());
33282
+ const turnId = hostTurnIdSchema.parse(randomUUID10());
32792
33283
  const startedAtMs = Date.now();
32793
33284
  const projection = {
32794
33285
  projector: new CodexTurnProjector({
@@ -32807,7 +33298,7 @@ var AppServerHost = class {
32807
33298
  const result = await thread.session.execute({
32808
33299
  type: "turn.start",
32809
33300
  turnId,
32810
- input: [{ type: "text", text }]
33301
+ input: [{ type: "text", text: rewriteDelegationMentionText(text) }]
32811
33302
  });
32812
33303
  if (!result.ok) throw new ExternalSteerError(-32073, result.error.message);
32813
33304
  return { turnId, turn: projection.projector.pendingTurn(), gate };
@@ -33109,7 +33600,7 @@ var AppServerHost = class {
33109
33600
  const previousItems = new Map(
33110
33601
  child.turns.flatMap(
33111
33602
  (turn) => Array.isArray(turn.items) ? turn.items.flatMap(
33112
- (item) => isRecord13(item) && typeof item.id === "string" ? [[item.id, JSON.stringify(item)]] : []
33603
+ (item) => isRecord14(item) && typeof item.id === "string" ? [[item.id, JSON.stringify(item)]] : []
33113
33604
  ) : []
33114
33605
  )
33115
33606
  );
@@ -33122,7 +33613,7 @@ var AppServerHost = class {
33122
33613
  for (const turn of child.turns) {
33123
33614
  if (typeof turn.id !== "string" || !Array.isArray(turn.items)) continue;
33124
33615
  const changedItems = turn.items.filter(
33125
- (item) => isRecord13(item) && typeof item.id === "string" && previousItems.get(item.id) !== JSON.stringify(item)
33616
+ (item) => isRecord14(item) && typeof item.id === "string" && previousItems.get(item.id) !== JSON.stringify(item)
33126
33617
  );
33127
33618
  if (changedItems.length > 0) {
33128
33619
  await this.#writer.json({
@@ -33254,7 +33745,7 @@ var AppServerHost = class {
33254
33745
  }
33255
33746
  }
33256
33747
  async #handleDesktopApprovalResponse(value2) {
33257
- if (!isRecord13(value2) || !isHostApprovalRequestId(value2.id)) return false;
33748
+ if (!isRecord14(value2) || !isHostApprovalRequestId(value2.id)) return false;
33258
33749
  const requestId = value2.id;
33259
33750
  const pending = this.#pendingDesktopApprovals.get(requestId);
33260
33751
  if (!pending) return true;
@@ -33336,7 +33827,7 @@ var AppServerHost = class {
33336
33827
  try {
33337
33828
  result = projection.projector.projectQuestion(
33338
33829
  interaction,
33339
- hostItemIdSchema.parse(randomUUID9())
33830
+ hostItemIdSchema.parse(randomUUID10())
33340
33831
  );
33341
33832
  } catch (error51) {
33342
33833
  this.#diagnose(error51);
@@ -33381,7 +33872,7 @@ var AppServerHost = class {
33381
33872
  }
33382
33873
  }
33383
33874
  async #handleDesktopQuestionResponse(value2) {
33384
- if (!isRecord13(value2) || !isHostQuestionRequestId(value2.id)) return false;
33875
+ if (!isRecord14(value2) || !isHostQuestionRequestId(value2.id)) return false;
33385
33876
  const requestId = value2.id;
33386
33877
  const pending = this.#pendingDesktopQuestions.get(requestId);
33387
33878
  if (!pending) return true;
@@ -33502,19 +33993,19 @@ var AppServerHost = class {
33502
33993
  };
33503
33994
 
33504
33995
  // packages/host-runtime/src/native-account-host.ts
33505
- import { mkdir as mkdir7, realpath as realpath3 } from "node:fs/promises";
33996
+ import { mkdir as mkdir8, realpath as realpath3 } from "node:fs/promises";
33506
33997
  import { homedir } from "node:os";
33507
- import path17 from "node:path";
33998
+ import path19 from "node:path";
33508
33999
 
33509
34000
  // packages/host-runtime/src/codex-runtime/owned-official-backends.ts
33510
- import { createHash as createHash8, randomBytes } from "node:crypto";
34001
+ import { createHash as createHash9, randomBytes } from "node:crypto";
33511
34002
  import { Writable as Writable2 } from "node:stream";
33512
34003
 
33513
34004
  // packages/host-runtime/src/remote-app-server.ts
33514
34005
  import { createServer } from "node:http";
33515
34006
  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";
34007
+ import { chmod as chmod3, lstat as lstat6, mkdir as mkdir7, rm as rm7 } from "node:fs/promises";
34008
+ import path17 from "node:path";
33518
34009
  import { PassThrough } from "node:stream";
33519
34010
 
33520
34011
  // node_modules/ws/wrapper.mjs
@@ -33529,10 +34020,10 @@ var import_websocket_server = __toESM(require_websocket_server(), 1);
33529
34020
  var wrapper_default = import_websocket.default;
33530
34021
 
33531
34022
  // 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";
34023
+ import { randomUUID as randomUUID11 } from "node:crypto";
34024
+ 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
34025
  import { uptime } from "node:os";
33535
- import path14 from "node:path";
34026
+ import path16 from "node:path";
33536
34027
  import { setTimeout as delay4 } from "node:timers/promises";
33537
34028
  var LOCK_RETRY_COUNT = 200;
33538
34029
  var LOCK_RETRY_DELAY_MS = 25;
@@ -33595,7 +34086,7 @@ async function readLockEntrySnapshot(filePath) {
33595
34086
  throw error51;
33596
34087
  });
33597
34088
  if (metadata === null || !metadata.isFile()) return null;
33598
- const source = await readFile7(filePath, "utf8").catch((error51) => {
34089
+ const source = await readFile8(filePath, "utf8").catch((error51) => {
33599
34090
  if (error51.code === "ENOENT") return null;
33600
34091
  throw error51;
33601
34092
  });
@@ -33606,7 +34097,7 @@ async function readLockEntrySnapshot(filePath) {
33606
34097
  source,
33607
34098
  identity: { dev: metadata.dev, ino: metadata.ino },
33608
34099
  mtimeMs: metadata.mtimeMs,
33609
- record: record3 && path14.basename(filePath) === lockEntryName(record3.ownerToken) ? record3 : null
34100
+ record: record3 && path16.basename(filePath) === lockEntryName(record3.ownerToken) ? record3 : null
33610
34101
  };
33611
34102
  }
33612
34103
  function lockEntryIsAbandoned(snapshot) {
@@ -33618,7 +34109,7 @@ async function removeAbandonedLockEntry(snapshot) {
33618
34109
  if (current === null || current.source !== snapshot.source || !sameUnixFileIdentity(current.identity, snapshot.identity) || !lockEntryIsAbandoned(current)) {
33619
34110
  return false;
33620
34111
  }
33621
- await rm5(snapshot.filePath, { force: true });
34112
+ await rm6(snapshot.filePath, { force: true });
33622
34113
  return true;
33623
34114
  }
33624
34115
  async function readLockEntryCatalog(lockDirectory) {
@@ -33627,7 +34118,7 @@ async function readLockEntryCatalog(lockDirectory) {
33627
34118
  let unsettled = false;
33628
34119
  for (const name of names) {
33629
34120
  if (!name.startsWith(LOCK_ENTRY_PREFIX) || !name.endsWith(LOCK_ENTRY_SUFFIX)) continue;
33630
- const snapshot = await readLockEntrySnapshot(path14.join(lockDirectory, name));
34121
+ const snapshot = await readLockEntrySnapshot(path16.join(lockDirectory, name));
33631
34122
  if (snapshot === null) continue;
33632
34123
  if (lockEntryIsAbandoned(snapshot)) {
33633
34124
  if (!await removeAbandonedLockEntry(snapshot)) unsettled = true;
@@ -33642,7 +34133,7 @@ async function readLockEntryCatalog(lockDirectory) {
33642
34133
  return { entries, unsettled };
33643
34134
  }
33644
34135
  async function preparePrivateLockDirectory(lockDirectory) {
33645
- await mkdir5(lockDirectory, { mode: 448 }).catch((error51) => {
34136
+ await mkdir6(lockDirectory, { mode: 448 }).catch((error51) => {
33646
34137
  if (error51.code !== "EEXIST") throw error51;
33647
34138
  });
33648
34139
  const metadata = await lstat5(lockDirectory);
@@ -33655,8 +34146,8 @@ async function preparePrivateLockDirectory(lockDirectory) {
33655
34146
  await chmod2(lockDirectory, 448);
33656
34147
  }
33657
34148
  async function writeLockRecordAtomic(lockDirectory, entryPath, record3) {
33658
- const temporary = path14.join(lockDirectory, `.tmp-${record3.ownerToken}-${randomUUID10()}`);
33659
- const handle = await open5(temporary, "wx", 384);
34149
+ const temporary = path16.join(lockDirectory, `.tmp-${record3.ownerToken}-${randomUUID11()}`);
34150
+ const handle = await open6(temporary, "wx", 384);
33660
34151
  try {
33661
34152
  await handle.writeFile(`${JSON.stringify(record3)}
33662
34153
  `, "utf8");
@@ -33665,15 +34156,15 @@ async function writeLockRecordAtomic(lockDirectory, entryPath, record3) {
33665
34156
  await handle.close();
33666
34157
  }
33667
34158
  try {
33668
- await rename4(temporary, entryPath);
34159
+ await rename5(temporary, entryPath);
33669
34160
  } finally {
33670
- await rm5(temporary, { force: true });
34161
+ await rm6(temporary, { force: true });
33671
34162
  }
33672
34163
  }
33673
34164
  async function removeOwnedLockEntry(entryPath, ownerToken) {
33674
34165
  const snapshot = await readLockEntrySnapshot(entryPath);
33675
34166
  if (snapshot?.record?.ownerToken !== ownerToken) return;
33676
- await rm5(entryPath, { force: true });
34167
+ await rm6(entryPath, { force: true });
33677
34168
  }
33678
34169
  async function legacyLockState(legacyPath) {
33679
34170
  const metadata = await lstat5(legacyPath).catch((error51) => {
@@ -33682,7 +34173,7 @@ async function legacyLockState(legacyPath) {
33682
34173
  });
33683
34174
  if (metadata === null) return "absent";
33684
34175
  if (!metadata.isFile()) return "blocking";
33685
- const source = await readFile7(legacyPath, "utf8").catch((error51) => {
34176
+ const source = await readFile8(legacyPath, "utf8").catch((error51) => {
33686
34177
  if (error51.code === "ENOENT") return null;
33687
34178
  throw error51;
33688
34179
  });
@@ -33693,7 +34184,7 @@ async function legacyLockState(legacyPath) {
33693
34184
  return ownerIsAbandoned(record3, metadata.mtimeMs) ? "abandoned" : "blocking";
33694
34185
  }
33695
34186
  async function tryAcquireLegacyCompatibilityGuard(legacyPath, record3) {
33696
- const handle = await open5(legacyPath, "wx", 384).catch((error51) => {
34187
+ const handle = await open6(legacyPath, "wx", 384).catch((error51) => {
33697
34188
  if (error51.code === "EEXIST") return null;
33698
34189
  throw error51;
33699
34190
  });
@@ -33719,7 +34210,7 @@ async function releaseLegacyCompatibilityGuard(legacyPath, guard) {
33719
34210
  throw error51;
33720
34211
  });
33721
34212
  if (metadata?.isFile() && sameUnixFileIdentity({ dev: metadata.dev, ino: metadata.ino }, guard.identity)) {
33722
- await rm5(legacyPath, { force: true });
34213
+ await rm6(legacyPath, { force: true });
33723
34214
  }
33724
34215
  }
33725
34216
  }
@@ -33730,8 +34221,8 @@ async function withRemoteAppServerSocketInitializationLock(socketPath, action) {
33730
34221
  const legacyPath = `${socketPath}.initializing`;
33731
34222
  const lockDirectory = `${socketPath}.initializers`;
33732
34223
  await preparePrivateLockDirectory(lockDirectory);
33733
- const ownerToken = randomUUID10();
33734
- const entryPath = path14.join(lockDirectory, lockEntryName(ownerToken));
34224
+ const ownerToken = randomUUID11();
34225
+ const entryPath = path16.join(lockDirectory, lockEntryName(ownerToken));
33735
34226
  const baseRecord = {
33736
34227
  version: 2,
33737
34228
  ownerToken,
@@ -33905,14 +34396,14 @@ function remoteAppServerSocketPath(environment, listenUrl = "unix://") {
33905
34396
  throw new Error("Remote app-server listener must use a Unix URL");
33906
34397
  }
33907
34398
  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);
34399
+ if (explicit.length > 0) return path17.posix.resolve(decodeURIComponent(explicit));
34400
+ const codexHome = environment.CODEX_HOME ?? (environment.HOME ? path17.posix.join(environment.HOME, ".codex") : void 0);
33910
34401
  if (!codexHome)
33911
34402
  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");
34403
+ return path17.posix.join(codexHome, "app-server-control", "app-server-control.sock");
33913
34404
  }
33914
34405
  function officialListenerArgumentsForRemoteListener(arguments_2, socketPath) {
33915
- if (!path15.posix.isAbsolute(socketPath)) {
34406
+ if (!path17.posix.isAbsolute(socketPath)) {
33916
34407
  throw new Error("Shared official app-server socket path must be absolute");
33917
34408
  }
33918
34409
  if (remoteUnixListenerUrl(arguments_2) === null) {
@@ -34020,10 +34511,10 @@ async function removeStaleSocket(socketPath) {
34020
34511
  });
34021
34512
  });
34022
34513
  if (active) throw new Error(`Remote app-server socket is already in use at ${socketPath}`);
34023
- await rm6(socketPath, { force: true });
34514
+ await rm7(socketPath, { force: true });
34024
34515
  }
34025
34516
  async function prepareRemoteAppServerSocketDirectory(socketPath) {
34026
- const socketDirectory = path15.dirname(socketPath);
34517
+ const socketDirectory = path17.dirname(socketPath);
34027
34518
  const existing = await lstat6(socketDirectory).catch((error51) => {
34028
34519
  if (error51.code === "ENOENT") return null;
34029
34520
  throw error51;
@@ -34037,7 +34528,7 @@ async function prepareRemoteAppServerSocketDirectory(socketPath) {
34037
34528
  );
34038
34529
  }
34039
34530
  }
34040
- await mkdir6(socketDirectory, { recursive: true, mode: 448 });
34531
+ await mkdir7(socketDirectory, { recursive: true, mode: 448 });
34041
34532
  await chmod3(socketDirectory, 448);
34042
34533
  }
34043
34534
  function sendOutputFrames(socket, output) {
@@ -34210,7 +34701,7 @@ function createRemoteAppServerWebSocketListener(input) {
34210
34701
  if (ownedSocketIdentity) {
34211
34702
  const current = await unixSocketIdentity(input.socketPath);
34212
34703
  if (current && sameUnixFileIdentity2(current, ownedSocketIdentity)) {
34213
- await rm6(input.socketPath, { force: true });
34704
+ await rm7(input.socketPath, { force: true });
34214
34705
  }
34215
34706
  ownedSocketIdentity = null;
34216
34707
  }
@@ -34228,20 +34719,20 @@ function createRemoteAppServerWebSocketListener(input) {
34228
34719
 
34229
34720
  // packages/host-runtime/src/remote-official-app-server.ts
34230
34721
  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";
34722
+ import { randomUUID as randomUUID12 } from "node:crypto";
34723
+ import { lstat as lstat7, rm as rm8 } from "node:fs/promises";
34724
+ import path18 from "node:path";
34234
34725
  var DEFAULT_CLOSE_TIMEOUT_MS = 2e3;
34235
34726
  var DEFAULT_LISTEN_TIMEOUT_MS = 1e4;
34236
- function remoteOfficialAppServerSocketPath(desktopControlSocketPath, token = randomUUID11()) {
34237
- if (!path16.posix.isAbsolute(desktopControlSocketPath)) {
34727
+ function remoteOfficialAppServerSocketPath(desktopControlSocketPath, token = randomUUID12()) {
34728
+ if (!path18.posix.isAbsolute(desktopControlSocketPath)) {
34238
34729
  throw new Error("Desktop control socket path must be absolute");
34239
34730
  }
34240
34731
  if (!/^[A-Za-z0-9-]+$/u.test(token) || !/[A-Za-z0-9]/u.test(token)) {
34241
34732
  throw new Error("Shared official app-server socket token is invalid");
34242
34733
  }
34243
34734
  const compactToken = token.replaceAll("-", "").slice(0, 15);
34244
- return path16.posix.join(path16.posix.dirname(desktopControlSocketPath), `.c-${compactToken}.sock`);
34735
+ return path18.posix.join(path18.posix.dirname(desktopControlSocketPath), `.c-${compactToken}.sock`);
34245
34736
  }
34246
34737
  function errorMessage4(error51) {
34247
34738
  return error51 instanceof Error ? error51.message : String(error51);
@@ -34313,7 +34804,7 @@ function createRemoteOfficialAppServerListener(input) {
34313
34804
  if (ownedSocketIdentity === null) return;
34314
34805
  const current = await socketIdentity(input.socketPath).catch(() => null);
34315
34806
  if (current && sameUnixFileIdentity3(current, ownedSocketIdentity)) {
34316
- await rm7(input.socketPath, { force: true });
34807
+ await rm8(input.socketPath, { force: true });
34317
34808
  }
34318
34809
  ownedSocketIdentity = null;
34319
34810
  };
@@ -34674,7 +35165,7 @@ function createOwnedLoopbackBackend(input) {
34674
35165
  "--ws-auth",
34675
35166
  "capability-token",
34676
35167
  "--ws-token-sha256",
34677
- createHash8("sha256").update(capabilityToken).digest("hex")
35168
+ createHash9("sha256").update(capabilityToken).digest("hex")
34678
35169
  ],
34679
35170
  // Managed stderr may carry credential-bearing errors. Never forward raw bytes.
34680
35171
  diagnosticOutput: new Writable2({
@@ -34727,21 +35218,21 @@ function createOwnedUnixBackend(input) {
34727
35218
 
34728
35219
  // packages/host-runtime/src/native-account-host.ts
34729
35220
  async function canonicalCodexHome(home) {
34730
- const absolute = path17.resolve(home);
35221
+ const absolute = path19.resolve(home);
34731
35222
  try {
34732
35223
  return await realpath3(absolute);
34733
35224
  } catch (error51) {
34734
35225
  if (!(error51 instanceof Error && "code" in error51 && error51.code === "ENOENT")) throw error51;
34735
- const parent = path17.dirname(absolute);
35226
+ const parent = path19.dirname(absolute);
34736
35227
  if (parent === absolute) throw error51;
34737
- return path17.join(await canonicalCodexHome(parent), path17.basename(absolute));
35228
+ return path19.join(await canonicalCodexHome(parent), path19.basename(absolute));
34738
35229
  }
34739
35230
  }
34740
35231
  async function prepareLocalCodex(input) {
34741
35232
  const home = await canonicalCodexHome(
34742
- input.environment.CODEX_HOME ?? path17.join(homedir(), ".codex")
35233
+ input.environment.CODEX_HOME ?? path19.join(homedir(), ".codex")
34743
35234
  );
34744
- await mkdir7(home, { recursive: true });
35235
+ await mkdir8(home, { recursive: true });
34745
35236
  const scope = new OfficialRuntimeScope({
34746
35237
  permanentHome: home,
34747
35238
  diagnosticOutput: input.diagnosticOutput,
@@ -34905,18 +35396,18 @@ var DelegationControlRegistry = class {
34905
35396
  };
34906
35397
 
34907
35398
  // packages/host-runtime/src/installed-harness-plugins.ts
34908
- import os5 from "node:os";
34909
- import path19 from "node:path";
35399
+ import os6 from "node:os";
35400
+ import path21 from "node:path";
34910
35401
  import { fileURLToPath } from "node:url";
34911
35402
 
34912
35403
  // packages/host-runtime/src/launcher-url-opener.ts
34913
35404
  import { spawn as spawn4 } from "node:child_process";
34914
- import path18 from "node:path";
35405
+ import path20 from "node:path";
34915
35406
  var LOOPBACK_HOSTS = /* @__PURE__ */ new Set(["127.0.0.1", "localhost", "[::1]"]);
34916
35407
  var OPEN_TIMEOUT_MS = 1e4;
34917
35408
  function createLauncherUrlOpener(environment, spawnLauncher = (command, arguments_2, options2) => spawn4(command, arguments_2, options2)) {
34918
35409
  const launcher = environment.CODEXHOST_LAUNCHER_EXECUTABLE;
34919
- if (!launcher || !path18.isAbsolute(launcher)) return void 0;
35410
+ if (!launcher || !path20.isAbsolute(launcher)) return void 0;
34920
35411
  const launcherEnvironment = Object.fromEntries(
34921
35412
  Object.entries(environment).filter(([name]) => {
34922
35413
  const normalized = name.toUpperCase();
@@ -34974,9 +35465,9 @@ function installedHarnessPluginOptions(environment, managedRemoteHost = false, h
34974
35465
  const opener = managedRemoteHost ? void 0 : createLauncherUrlOpener(environment);
34975
35466
  return {
34976
35467
  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"),
35468
+ path21.join(path21.dirname(fileURLToPath(hostRuntimeUrl)), "plugins"),
35469
+ environment[HARNESS_PLUGIN_DIRECTORY_ENV] ?? path21.join(
35470
+ environment.CODEXHOST_DATA_DIR ? path21.resolve(environment.CODEXHOST_DATA_DIR) : path21.join(os6.homedir(), ".codexhost"),
34980
35471
  "plugins"
34981
35472
  )
34982
35473
  ],
@@ -35100,171 +35591,10 @@ async function startDelegationControlServer(input) {
35100
35591
  };
35101
35592
  }
35102
35593
 
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
35594
  // packages/host-runtime/src/remote-control-app-server.ts
35265
35595
  import { randomUUID as randomUUID13 } from "node:crypto";
35266
35596
  import { mkdir as mkdir9, open as open7, rename as rename6, rm as rm9 } from "node:fs/promises";
35267
- import path21 from "node:path";
35597
+ import path22 from "node:path";
35268
35598
  var REMOTE_CONTROL_BRIDGE_PIPE_ENV = "CODEXHOST_REMOTE_CONTROL_BRIDGE_PIPE";
35269
35599
  var REMOTE_CONTROL_BRIDGE_NODE_ENV = "CODEXHOST_REMOTE_CONTROL_BRIDGE_NODE_PATH";
35270
35600
  var REMOTE_CONTROL_BRIDGE_RUNTIME_ENV = "CODEXHOST_REMOTE_CONTROL_BRIDGE_RUNTIME_PATH";
@@ -35275,8 +35605,8 @@ var BRIDGE_READY_METHOD = "codexhost/remote-control-bridge/ready";
35275
35605
  function absoluteEnvironmentPath2(environment, name, fallback, platform = process.platform) {
35276
35606
  const value2 = environment[name] ?? fallback;
35277
35607
  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;
35608
+ if (path22.isAbsolute(value2)) return path22.normalize(value2);
35609
+ return platform === "win32" && path22.win32.isAbsolute(value2) ? path22.win32.normalize(value2) : null;
35280
35610
  }
35281
35611
  function nodeCompatibleWindowsPath(value2) {
35282
35612
  if (value2.startsWith("\\\\?\\UNC\\")) return `\\\\${value2.slice(8)}`;
@@ -35290,13 +35620,13 @@ function remoteControlBridgePipePath(processId = process.pid, instanceId = rando
35290
35620
  }
35291
35621
  function remoteControlBridgeDescriptorPath(environment) {
35292
35622
  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);
35623
+ if (!root || !path22.isAbsolute(root)) return null;
35624
+ return path22.join(path22.normalize(root), "codexhost", REMOTE_CONTROL_BRIDGE_DESCRIPTOR_FILE);
35295
35625
  }
35296
35626
  async function publishRemoteControlAppServerDescriptor(plan) {
35297
- const directory = path21.dirname(plan.descriptorPath);
35627
+ const directory = path22.dirname(plan.descriptorPath);
35298
35628
  await mkdir9(directory, { recursive: true, mode: 448 });
35299
- const temporaryPath = path21.join(
35629
+ const temporaryPath = path22.join(
35300
35630
  directory,
35301
35631
  `.${REMOTE_CONTROL_BRIDGE_DESCRIPTOR_FILE}.${plan.descriptor.ownerPid}.${randomUUID13()}.tmp`
35302
35632
  );
@@ -35597,9 +35927,9 @@ function hasLauncherManagedUpdateRuntime(environment, hostRuntimePath) {
35597
35927
  if (!environment[UPDATE_RUNTIME_ENV.launcherPid]) return false;
35598
35928
  const npmPackageRoot = environment[UPDATE_RUNTIME_ENV.npmPackageRoot];
35599
35929
  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) === "";
35930
+ if (!path23.isAbsolute(npmPackageRoot) || !path23.isAbsolute(hostRuntimePath)) return false;
35931
+ const runtimePackageRoot = path23.dirname(path23.dirname(path23.normalize(hostRuntimePath)));
35932
+ return path23.relative(path23.normalize(npmPackageRoot), runtimePackageRoot) === "";
35603
35933
  }
35604
35934
  function requiredRuntimeConfiguration(environment) {
35605
35935
  const stockCodexPath = environment[STOCK_CODEX_PATH_ENV];
@@ -35745,8 +36075,8 @@ async function runHostRuntime(input) {
35745
36075
  const socketPath = remoteAppServerSocketPath(delegationEnvironment, listenUrl);
35746
36076
  const officialPlan = createRemoteOfficialAppServerPlan(input.arguments, socketPath);
35747
36077
  const officialRuntimeScope = new OfficialRuntimeScope({
35748
- permanentHome: path22.resolve(
35749
- delegationEnvironment.CODEX_HOME ?? path22.join(homedir2(), ".codex")
36078
+ permanentHome: path23.resolve(
36079
+ delegationEnvironment.CODEX_HOME ?? path23.join(homedir2(), ".codex")
35750
36080
  ),
35751
36081
  diagnosticOutput: process.stderr,
35752
36082
  createBackend: () => createOwnedUnixBackend({
@@ -35842,7 +36172,7 @@ import {
35842
36172
  stat as stat5,
35843
36173
  writeFile as writeFile4
35844
36174
  } from "node:fs/promises";
35845
- import path23 from "node:path";
36175
+ import path24 from "node:path";
35846
36176
  var MANIFEST_FORMAT = 1;
35847
36177
  var WRAPPER_MARKER = "# codexhost remote SSH wrapper v1";
35848
36178
  var PROFILE_START = "# >>> codexhost remote SSH >>>";
@@ -35853,25 +36183,25 @@ function resolvePaths(options2) {
35853
36183
  if (!configuredHome) {
35854
36184
  throw new Error("A non-root HOME is required for remote Host installation");
35855
36185
  }
35856
- const home = path23.resolve(configuredHome);
35857
- if (!home || home === path23.parse(home).root) {
36186
+ const home = path24.resolve(configuredHome);
36187
+ if (!home || home === path24.parse(home).root) {
35858
36188
  throw new Error("A non-root HOME is required for remote Host installation");
35859
36189
  }
35860
- const installRoot = path23.resolve(options2.installRoot ?? path23.join(home, ".codexhost", "remote"));
35861
- const profilePath = path23.resolve(
35862
- options2.profilePath ?? path23.join(
36190
+ const installRoot = path24.resolve(options2.installRoot ?? path24.join(home, ".codexhost", "remote"));
36191
+ const profilePath = path24.resolve(
36192
+ options2.profilePath ?? path24.join(
35863
36193
  home,
35864
- path23.basename(environment.SHELL ?? "") === "zsh" ? ".zshenv" : path23.basename(environment.SHELL ?? "") === "bash" ? ".bashrc" : ".profile"
36194
+ path24.basename(environment.SHELL ?? "") === "zsh" ? ".zshenv" : path24.basename(environment.SHELL ?? "") === "bash" ? ".bashrc" : ".profile"
35865
36195
  )
35866
36196
  );
35867
- const binDirectory = path23.join(installRoot, "bin");
36197
+ const binDirectory = path24.join(installRoot, "bin");
35868
36198
  return {
35869
36199
  home,
35870
36200
  installRoot,
35871
36201
  binDirectory,
35872
- wrapperPath: path23.join(binDirectory, "codex"),
35873
- manifestPath: path23.join(installRoot, "manifest.json"),
35874
- dataDirectory: path23.join(installRoot, "data"),
36202
+ wrapperPath: path24.join(binDirectory, "codex"),
36203
+ manifestPath: path24.join(installRoot, "manifest.json"),
36204
+ dataDirectory: path24.join(installRoot, "data"),
35875
36205
  profilePath
35876
36206
  };
35877
36207
  }
@@ -35890,7 +36220,7 @@ async function fileSha256(filePath) {
35890
36220
  return createHash10("sha256").update(await readFile9(filePath)).digest("hex");
35891
36221
  }
35892
36222
  async function executable(filePath, label) {
35893
- const absolute = path23.resolve(filePath);
36223
+ const absolute = path24.resolve(filePath);
35894
36224
  try {
35895
36225
  if (!(await stat5(absolute)).isFile()) throw new Error("not a regular file");
35896
36226
  await access(absolute, fsConstants.X_OK);
@@ -35900,7 +36230,7 @@ async function executable(filePath, label) {
35900
36230
  return absolute;
35901
36231
  }
35902
36232
  async function existingFile(filePath, label) {
35903
- const absolute = path23.resolve(filePath);
36233
+ const absolute = path24.resolve(filePath);
35904
36234
  try {
35905
36235
  const metadata = await stat5(absolute);
35906
36236
  if (!metadata.isFile()) throw new Error("not a regular file");
@@ -35910,9 +36240,9 @@ async function existingFile(filePath, label) {
35910
36240
  return absolute;
35911
36241
  }
35912
36242
  async function discoverExecutable(name, environment) {
35913
- for (const directory of (environment.PATH ?? "").split(path23.delimiter)) {
36243
+ for (const directory of (environment.PATH ?? "").split(path24.delimiter)) {
35914
36244
  if (!directory) continue;
35915
- const candidate = path23.resolve(directory, name);
36245
+ const candidate = path24.resolve(directory, name);
35916
36246
  try {
35917
36247
  await access(candidate, fsConstants.X_OK);
35918
36248
  return candidate;
@@ -35923,10 +36253,10 @@ async function discoverExecutable(name, environment) {
35923
36253
  return null;
35924
36254
  }
35925
36255
  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`
36256
+ await mkdir10(path24.dirname(filePath), { recursive: true, mode: 448 });
36257
+ const temporary = path24.join(
36258
+ path24.dirname(filePath),
36259
+ `.${path24.basename(filePath)}.${process.pid}.${randomUUID14()}.tmp`
35930
36260
  );
35931
36261
  try {
35932
36262
  if (typeof contents === "string") {
@@ -35947,10 +36277,10 @@ async function writeAtomic(filePath, contents, mode) {
35947
36277
  }
35948
36278
  }
35949
36279
  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`
36280
+ await mkdir10(path24.dirname(filePath), { recursive: true, mode: 448 });
36281
+ const temporary = path24.join(
36282
+ path24.dirname(filePath),
36283
+ `.${path24.basename(filePath)}.${process.pid}.${randomUUID14()}.tmp`
35954
36284
  );
35955
36285
  try {
35956
36286
  await copyFile3(sourcePath, temporary);
@@ -35991,8 +36321,8 @@ function removeManagedProfileBlock(contents) {
35991
36321
  function installManagedProfileBlock(contents, manifest) {
35992
36322
  const base = removeManagedProfileBlock(contents);
35993
36323
  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}"`,
36324
+ `export CODEX_INSTALL_DIR=${shellQuote(path24.dirname(manifest.wrapperPath))}`,
36325
+ `export PATH=${shellQuote(path24.dirname(manifest.wrapperPath))}:${shellQuote(path24.dirname(manifest.nodePath))}:${shellQuote(path24.dirname(manifest.stockCodexPath))}:"\${PATH:-/usr/local/bin:/usr/bin:/bin}"`,
35996
36326
  `export CODEXHOST_STOCK_CODEX_PATH=${shellQuote(manifest.stockCodexPath)}`,
35997
36327
  `export CODEXHOST_HOST_NODE_PATH=${shellQuote(manifest.nodePath)}`,
35998
36328
  `export CODEXHOST_HOST_RUNTIME_PATH=${shellQuote(manifest.hostRuntimePath)}`,
@@ -36008,7 +36338,7 @@ function installManagedProfileBlock(contents, manifest) {
36008
36338
  PROFILE_END,
36009
36339
  ""
36010
36340
  ].join("\n");
36011
- if (path23.basename(manifest.profilePath) === ".bashrc") return `${block}${base}`;
36341
+ if (path24.basename(manifest.profilePath) === ".bashrc") return `${block}${base}`;
36012
36342
  const separator = base.length > 0 && !base.endsWith("\n") ? "\n" : "";
36013
36343
  return `${base}${separator}${block}`;
36014
36344
  }
@@ -36074,9 +36404,9 @@ async function readManifest(filePath) {
36074
36404
  ];
36075
36405
  const optionalPaths = ["claudeCommand", "profileBackupPath"];
36076
36406
  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])
36407
+ (key) => typeof manifest[key] !== "string" || !path24.isAbsolute(manifest[key])
36078
36408
  ) || optionalPaths.some(
36079
- (key) => manifest[key] !== void 0 && (typeof manifest[key] !== "string" || !path23.isAbsolute(manifest[key]))
36409
+ (key) => manifest[key] !== void 0 && (typeof manifest[key] !== "string" || !path24.isAbsolute(manifest[key]))
36080
36410
  ) || manifest.entrypointSha256 !== void 0 && (typeof manifest.entrypointSha256 !== "string" || !/^[a-f0-9]{64}$/u.test(manifest.entrypointSha256))) {
36081
36411
  throw new Error("Remote Host manifest has an unsupported format");
36082
36412
  }
@@ -36302,7 +36632,7 @@ async function uninstallRemoteHost(options2) {
36302
36632
  import { spawn as spawn5 } from "node:child_process";
36303
36633
  import { stat as stat6 } from "node:fs/promises";
36304
36634
  import net3 from "node:net";
36305
- import path24 from "node:path";
36635
+ import path25 from "node:path";
36306
36636
  import { Duplex } from "node:stream";
36307
36637
  var CODEXHOST_STATUS_METHOD = "codexhost/update/status";
36308
36638
  var DIRECT_PROBE_TIMEOUT_MS = 5e3;
@@ -36321,9 +36651,9 @@ function classifyRemoteHostProbeResponse(response, socketPath) {
36321
36651
  }
36322
36652
  var lifecycleDependencyOverrides = {};
36323
36653
  function socketPathFor(environment) {
36324
- const codexHome = environment.CODEX_HOME ?? (environment.HOME ? path24.join(environment.HOME, ".codex") : void 0);
36654
+ const codexHome = environment.CODEX_HOME ?? (environment.HOME ? path25.join(environment.HOME, ".codex") : void 0);
36325
36655
  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");
36656
+ return path25.join(codexHome, "app-server-control", "app-server-control.sock");
36327
36657
  }
36328
36658
  async function defaultSocketExists(socketPath) {
36329
36659
  const metadata = await stat6(socketPath).catch((error51) => {
@@ -36450,14 +36780,14 @@ function installedManifest(status) {
36450
36780
  function managedEnvironment(manifest, environment) {
36451
36781
  return {
36452
36782
  ...environment,
36453
- CODEX_INSTALL_DIR: path24.dirname(manifest.wrapperPath),
36783
+ CODEX_INSTALL_DIR: path25.dirname(manifest.wrapperPath),
36454
36784
  CODEXHOST_STOCK_CODEX_PATH: manifest.stockCodexPath,
36455
36785
  CODEXHOST_HOST_NODE_PATH: manifest.nodePath,
36456
36786
  CODEXHOST_HOST_RUNTIME_PATH: manifest.hostRuntimePath,
36457
36787
  CODEXHOST_DATA_DIR: manifest.dataDirectory,
36458
36788
  CODEXHOST_DEFAULT_AGENT: "codex",
36459
36789
  CODEXHOST_REMOTE_SSH_MANAGED: "1",
36460
- PATH: `${path24.dirname(manifest.wrapperPath)}${path24.delimiter}${path24.dirname(manifest.stockCodexPath)}${path24.delimiter}${environment.PATH ?? "/usr/bin:/bin"}`
36790
+ PATH: `${path25.dirname(manifest.wrapperPath)}${path25.delimiter}${path25.dirname(manifest.stockCodexPath)}${path25.delimiter}${environment.PATH ?? "/usr/bin:/bin"}`
36461
36791
  };
36462
36792
  }
36463
36793
  async function defaultRunTerminator(manifest, socketPath, role, environment) {
@@ -36793,25 +37123,25 @@ function consumeBrokerFrames(socket, onFrame, onError) {
36793
37123
 
36794
37124
  // packages/harness-broker/dist/paths.js
36795
37125
  import os7 from "node:os";
36796
- import path25 from "node:path";
37126
+ import path26 from "node:path";
36797
37127
  var HARNESS_BROKER_DESCRIPTOR_ENV = "CODEXHOST_CLAUDE_BROKER_DESCRIPTOR";
36798
37128
  var HARNESS_BROKER_DESCRIPTOR_FILE = "claude-code-broker-v1.json";
36799
37129
  var HARNESS_BROKER_SOCKET_FILE = "claude-code-broker-v1.sock";
36800
37130
  function defaultHarnessBrokerDirectory(environment = process.env) {
36801
37131
  const home = environment.HOME || os7.homedir();
36802
- return path25.join(home, ".codexhost", "harness-broker");
37132
+ return path26.join(home, ".codexhost", "harness-broker");
36803
37133
  }
36804
37134
  function defaultHarnessBrokerDescriptorPath(environment = process.env, harnessId = "claude-code") {
36805
37135
  harnessPluginIdSchema.parse(harnessId);
36806
37136
  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);
37137
+ return path26.join(defaultHarnessBrokerDirectory(environment), `${harnessId}-broker-v1.json`);
37138
+ return environment[HARNESS_BROKER_DESCRIPTOR_ENV] ?? path26.join(defaultHarnessBrokerDirectory(environment), HARNESS_BROKER_DESCRIPTOR_FILE);
36809
37139
  }
36810
37140
  function defaultHarnessBrokerSocketPath(environment = process.env, harnessId = "claude-code") {
36811
37141
  harnessPluginIdSchema.parse(harnessId);
36812
37142
  if (harnessId !== "claude-code")
36813
- return path25.join(defaultHarnessBrokerDirectory(environment), `${harnessId}-broker-v1.sock`);
36814
- return path25.join(defaultHarnessBrokerDirectory(environment), HARNESS_BROKER_SOCKET_FILE);
37143
+ return path26.join(defaultHarnessBrokerDirectory(environment), `${harnessId}-broker-v1.sock`);
37144
+ return path26.join(defaultHarnessBrokerDirectory(environment), HARNESS_BROKER_SOCKET_FILE);
36815
37145
  }
36816
37146
 
36817
37147
  // packages/harness-broker/dist/validation.js
@@ -37027,7 +37357,7 @@ var harnessOutputSchema = external_exports.custom((value2) => {
37027
37357
  import { randomBytes as randomBytes3, randomUUID as randomUUID15 } from "node:crypto";
37028
37358
  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
37359
  import net4, {} from "node:net";
37030
- import path26 from "node:path";
37360
+ import path27 from "node:path";
37031
37361
  function harnessError(message, retryable = true) {
37032
37362
  return { code: "unavailable", message, retryable, stage: "harnessBroker" };
37033
37363
  }
@@ -37150,13 +37480,13 @@ async function prepareUnixSocketPath(socketPath) {
37150
37480
  }
37151
37481
  async function startHarnessBrokerServer(input) {
37152
37482
  harnessPluginIdSchema.parse(input.adapter.harnessId);
37153
- if (process.platform !== "win32" && path26.dirname(input.descriptorPath) !== path26.dirname(input.socketPath)) {
37483
+ if (process.platform !== "win32" && path27.dirname(input.descriptorPath) !== path27.dirname(input.socketPath)) {
37154
37484
  throw new Error("Harness broker descriptor and socket must share one private directory");
37155
37485
  }
37156
37486
  if (process.platform === "darwin" && Buffer.byteLength(input.socketPath) > 103) {
37157
37487
  throw new Error("Harness broker Unix socket path is too long for macOS");
37158
37488
  }
37159
- await privateDirectory(path26.dirname(input.descriptorPath));
37489
+ await privateDirectory(path27.dirname(input.descriptorPath));
37160
37490
  await assertNoLiveDescriptor(input.descriptorPath);
37161
37491
  if (process.platform !== "win32")
37162
37492
  await prepareUnixSocketPath(input.socketPath);