holycodex 0.12.7 → 0.13.0-dev.203.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/README.md +1 -1
  2. package/dist/cli.js +1436 -1273
  3. package/package.json +2 -2
package/dist/cli.js CHANGED
@@ -1,4 +1,5 @@
1
1
  import process$1 from "node:process";
2
+ import { createInterface } from "node:readline/promises";
2
3
  import { access, copyFile, cp, lstat, mkdir, mkdtemp, readFile, readdir, readlink, rename, rm, stat, writeFile } from "node:fs/promises";
3
4
  import { homedir, tmpdir } from "node:os";
4
5
  import { delimiter, dirname, join } from "node:path";
@@ -4391,7 +4392,7 @@ function superRefine(fn, params) {
4391
4392
  }
4392
4393
  //#endregion
4393
4394
  //#region packages/cli/src/catalog.ts
4394
- var VERSION = "0.12.7";
4395
+ var VERSION = "0.13.0-dev.203.1";
4395
4396
  var SKILLS = [
4396
4397
  "ast-grep",
4397
4398
  "babysit-ci",
@@ -4537,12 +4538,16 @@ var LUNA_MAX = {
4537
4538
  model: "gpt-5.6-luna",
4538
4539
  reasoningEffort: "max"
4539
4540
  };
4541
+ var SOL_HIGH = {
4542
+ model: "gpt-5.6-sol",
4543
+ reasoningEffort: "high"
4544
+ };
4540
4545
  function uniformStageRoutes(...routes) {
4541
4546
  return Object.fromEntries(WORKFLOW_STAGES.map((stage) => [stage, [...routes]]));
4542
4547
  }
4543
4548
  var MODEL_ROUTING_PLANS = ModelRoutingPlansSchema.parse({
4544
4549
  go: {
4545
- root: LUNA_HIGH,
4550
+ root: SOL_HIGH,
4546
4551
  agents: {
4547
4552
  explorer: LUNA_HIGH,
4548
4553
  librarian: LUNA_HIGH,
@@ -5071,13 +5076,16 @@ var INSTALL_FLAGS = /* @__PURE__ */ new Set([
5071
5076
  "--codex-autonomous",
5072
5077
  "--no-codex-autonomous",
5073
5078
  "--dangerous-codex-autonomous",
5079
+ "--computer-use",
5080
+ "--no-computer-use",
5081
+ "--no-tui",
5074
5082
  "--fast",
5075
5083
  "--fast-all",
5076
5084
  "--no-fast",
5077
5085
  "--json",
5078
5086
  "--verbose"
5079
5087
  ]);
5080
- var SHARED_FLAGS = /* @__PURE__ */ new Set(["--json"]);
5088
+ var SHARED_FLAGS = /* @__PURE__ */ new Set(["--json", "--no-tui"]);
5081
5089
  /** Strictly parses command-specific HolyCodex CLI arguments. */
5082
5090
  function parseCliArguments(args) {
5083
5091
  if (args.length === 0 || args[0] === "--help" || args[0] === "-h") return base("help");
@@ -5130,6 +5138,8 @@ function parseCliArguments(args) {
5130
5138
  "--no-fast"
5131
5139
  ].filter((flag) => values.has(flag));
5132
5140
  if (fastFlags.length > 1) throw new Error(`Conflicting Fast flags: ${fastFlags.join(", ")}`);
5141
+ const computerUseFlags = ["--computer-use", "--no-computer-use"].filter((flag) => values.has(flag));
5142
+ if (computerUseFlags.length > 1) throw new Error(`Conflicting Computer Use flags: ${computerUseFlags.join(", ")}`);
5133
5143
  const planValue = values.get("--plan") ?? "plus-low";
5134
5144
  const plan = PlanNameSchema.safeParse(planValue);
5135
5145
  if (!plan.success) throw new Error(`Unknown plan: ${String(planValue)}. Valid plans: ${PLAN_NAMES.join(", ")}.`);
@@ -5146,13 +5156,16 @@ function parseCliArguments(args) {
5146
5156
  mode: "default"
5147
5157
  } : { requested: false };
5148
5158
  const fast = FastModeSchema.parse(values.has("--fast-all") ? "fast-all" : values.has("--fast") ? "fast" : "standard");
5159
+ const computerUse = values.has("--computer-use") ? "enabled" : values.has("--no-computer-use") ? "disabled" : void 0;
5149
5160
  return {
5150
5161
  action: "run",
5151
5162
  command,
5152
5163
  json: values.has("--json"),
5164
+ noTui: values.has("--no-tui"),
5153
5165
  plan: plan.data,
5154
5166
  ...maxValue === void 0 ? {} : { maxSubagents: Number(maxValue) },
5155
5167
  autonomy,
5168
+ ...computerUse === void 0 ? {} : { computerUse },
5156
5169
  fast,
5157
5170
  verbose: values.has("--verbose")
5158
5171
  };
@@ -5161,6 +5174,7 @@ function base(action) {
5161
5174
  return {
5162
5175
  action,
5163
5176
  json: false,
5177
+ noTui: false,
5164
5178
  plan: DEFAULT_PLAN,
5165
5179
  autonomy: { requested: false },
5166
5180
  fast: "standard",
@@ -5416,1385 +5430,1491 @@ function errorCode(value) {
5416
5430
  return typeof code === "string" ? code : void 0;
5417
5431
  }
5418
5432
  //#endregion
5419
- //#region packages/cli/src/toml.ts
5420
- var TOML_TABLE = /^[ \t]*(?:\[[^\]\r\n]+\]|\[\[[^\]\r\n]+\]\])[ \t]*(?:#.*)?$/m;
5421
- /** Reads a root TOML string value. */
5422
- function rootTomlString(input, key) {
5423
- const table = TOML_TABLE.exec(input);
5424
- const root = table === null ? input : input.slice(0, table.index);
5425
- const match = new RegExp(String.raw`^[ \t]*${escapeRegExp$1(key)}[ \t]*=[ \t]*(?:"((?:\\.|[^"\\\r\n])*)"|'([^'\r\n]*)')[ \t]*(?:#.*)?$`, "m").exec(root);
5426
- if (match === null) return void 0;
5427
- if (match[2] !== void 0) return match[2];
5428
- try {
5429
- return string().safeParse(JSON.parse(`"${match[1] ?? ""}"`)).data;
5430
- } catch {
5431
- return;
5432
- }
5433
- }
5434
- /** Reads a root TOML string array. */
5435
- function rootTomlStringArray(input, key) {
5436
- return parseRootTomlStringArray(input, key)?.items;
5437
- }
5438
- /** Reads the source text of a root TOML string array. */
5439
- function rootTomlStringArraySource(input, key) {
5440
- return parseRootTomlStringArray(input, key)?.source;
5433
+ //#region packages/cli/src/codex-launcher.ts
5434
+ var CODEX_PACKAGE_SPEC = "@openai/codex@latest";
5435
+ /** Derives safe process facts for the default installation flow. */
5436
+ function defaultCodexLauncherRuntimeFacts(platform = process.platform, env = process.env) {
5437
+ const bun = typeof process.versions.bun === "string";
5438
+ const allowPackageResolution = env.HOLYCODEX_TEST_SKIP_PACKAGE_RESOLUTION !== "1";
5439
+ const npmExecPath = bun ? void 0 : env.npm_execpath;
5440
+ return {
5441
+ allowPackageResolution,
5442
+ platform,
5443
+ execPath: process.execPath,
5444
+ runtime: bun ? "bun" : "node",
5445
+ ...npmExecPath === void 0 ? {} : { npmExecPath },
5446
+ availableRunners: ["npm", "pnpm"],
5447
+ npm: platform === "win32" ? "npm.cmd" : "npm",
5448
+ pnpm: platform === "win32" ? "pnpm.cmd" : "pnpm"
5449
+ };
5441
5450
  }
5442
- function parseRootTomlStringArray(input, key) {
5443
- const table = TOML_TABLE.exec(input);
5444
- const root = table === null ? input : input.slice(0, table.index);
5445
- const assignment = new RegExp(String.raw`^[ \t]*${escapeRegExp$1(key)}[ \t]*=`, "m").exec(root);
5446
- if (assignment === null) return void 0;
5447
- const start = root.indexOf("[", assignment.index + assignment[0].length);
5448
- if (start < 0) return void 0;
5449
- const items = [];
5450
- let quote;
5451
- let raw = "";
5452
- let escaped = false;
5453
- let comment = false;
5454
- for (let index = start + 1; index < root.length; index += 1) {
5455
- const character = root[index];
5456
- if (comment) {
5457
- if (character === "\n") comment = false;
5458
- continue;
5459
- }
5460
- if (quote === "\"") {
5461
- if (escaped) {
5462
- raw += character;
5463
- escaped = false;
5464
- } else if (character === "\\") {
5465
- raw += character;
5466
- escaped = true;
5467
- } else if (character === "\"") {
5468
- try {
5469
- const parsed = string().safeParse(JSON.parse(`"${raw}"`));
5470
- if (!parsed.success) return void 0;
5471
- items.push(parsed.data);
5472
- } catch {
5473
- return;
5474
- }
5475
- quote = void 0;
5476
- raw = "";
5477
- } else raw += character;
5478
- continue;
5479
- }
5480
- if (quote === "'") {
5481
- if (character === "'") {
5482
- items.push(raw);
5483
- quote = void 0;
5484
- raw = "";
5485
- } else raw += character;
5486
- continue;
5487
- }
5488
- if (character === "#") comment = true;
5489
- else if (character === "\"" || character === "'") quote = character;
5490
- else if (character === "]") {
5491
- const suffix = /^[ \t]*(?:#.*)?(?=\r?\n|$)/.exec(root.slice(index + 1))?.[0] ?? "";
5492
- return {
5493
- source: root.slice(assignment.index, index + 1 + suffix.length),
5494
- items
5495
- };
5496
- }
5451
+ /** Builds ordered Codex launcher candidates once for an installation. */
5452
+ function createCodexLauncherCandidates(input = {}) {
5453
+ const facts = input.runtimeFacts ?? {};
5454
+ const candidates = [];
5455
+ const injected = input.injected === void 0 ? [] : toArray(input.injected);
5456
+ for (const candidate of injected) {
5457
+ const launcher = normalizeLauncher(candidate, "injected");
5458
+ if (launcher !== void 0) candidates.push(launcher);
5497
5459
  }
5460
+ const pathLauncher = normalizeLauncher(facts.pathCodex ?? "codex", "path");
5461
+ if (pathLauncher !== void 0) candidates.push(pathLauncher);
5462
+ if (facts.allowPackageResolution === false) return deduplicate(candidates);
5463
+ if ((facts.runtime ?? (typeof process.versions.bun === "string" ? "bun" : "node")) === "bun") {
5464
+ const bunLauncher = normalizeLauncher({
5465
+ command: facts.execPath ?? process.execPath,
5466
+ argsPrefix: ["x", CODEX_PACKAGE_SPEC],
5467
+ source: "bunx"
5468
+ }, "bunx");
5469
+ if (bunLauncher !== void 0) candidates.push(bunLauncher);
5470
+ }
5471
+ const nodeRunner = facts.nodeRunner ?? activeNodeRunner(facts);
5472
+ if (nodeRunner !== void 0) {
5473
+ const launcher = normalizeLauncher(nodeRunner, nodeRunnerSource(nodeRunner));
5474
+ if (launcher !== void 0) candidates.push(launcher);
5475
+ }
5476
+ const availableRunners = facts.availableRunners ?? [];
5477
+ if (facts.npm !== false && (facts.npm !== void 0 || availableRunners.includes("npm"))) candidates.push(packageLauncher(facts.npm, facts.platform, "npm-exec"));
5478
+ if (facts.pnpm !== false && (facts.pnpm !== void 0 || availableRunners.includes("pnpm"))) candidates.push(packageLauncher(facts.pnpm, facts.platform, "pnpm-exec"));
5479
+ return deduplicate(candidates);
5498
5480
  }
5499
- function escapeRegExp$1(value) {
5500
- return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
5501
- }
5502
- //#endregion
5503
- //#region packages/cli/src/permission-selection.ts
5504
- var PERMISSION_KEYS = [
5505
- "default_permissions",
5506
- "approval_policy",
5507
- "approvals_reviewer",
5508
- "sandbox_mode"
5509
- ];
5510
- var AUTONOMY_PREFIX = "# holycodex autonomy: ";
5511
- var ORIGINAL_PERMISSION_PREFIX = "# holycodex original permissions: ";
5512
- /** Normalizes legacy string callers while preserving an omitted request. */
5513
- function normalizeRequestedAutonomy(value) {
5514
- if (value === void 0) return { requested: false };
5515
- if (typeof value === "string") return {
5516
- requested: true,
5517
- mode: value
5518
- };
5519
- return value;
5481
+ /** Appends command arguments to a launcher prefix without mutating either array. */
5482
+ function codexLauncherArgs(launcher, args) {
5483
+ return [...launcher.argsPrefix, ...args];
5520
5484
  }
5521
- /** Reads the raw root permission selection without filling missing values. */
5522
- function readRawPermissionSelection(input) {
5523
- const defaultPermissions = rootTomlString(input, "default_permissions");
5524
- const approvalPolicy = rootTomlString(input, "approval_policy");
5525
- const approvalsReviewer = rootTomlString(input, "approvals_reviewer");
5526
- const sandboxMode = rootTomlString(input, "sandbox_mode");
5485
+ function activeNodeRunner(facts) {
5486
+ if (facts.npmExecPath === void 0 || facts.execPath === void 0) return void 0;
5487
+ const source = packageRunnerSource(facts.npmExecPath);
5488
+ if (source === void 0) return void 0;
5527
5489
  return {
5528
- ...defaultPermissions === void 0 ? {} : { defaultPermissions },
5529
- ...approvalPolicy === void 0 ? {} : { approvalPolicy },
5530
- ...approvalsReviewer === void 0 ? {} : { approvalsReviewer },
5531
- ...sandboxMode === void 0 ? {} : { sandboxMode }
5490
+ command: facts.execPath,
5491
+ argsPrefix: source === "npm-exec" ? [
5492
+ facts.npmExecPath,
5493
+ "exec",
5494
+ "--yes",
5495
+ "--package",
5496
+ CODEX_PACKAGE_SPEC,
5497
+ "--",
5498
+ "codex"
5499
+ ] : [
5500
+ facts.npmExecPath,
5501
+ "dlx",
5502
+ CODEX_PACKAGE_SPEC
5503
+ ],
5504
+ source
5532
5505
  };
5533
5506
  }
5534
- /** Returns root assignment lines for permission keys in source order. */
5535
- function readPermissionLines(input) {
5536
- const firstTable = input.search(/^\s*\[/m);
5537
- const root = firstTable < 0 ? input : input.slice(0, firstTable);
5538
- const keys = new Set(PERMISSION_KEYS);
5539
- return root.split(/\r?\n/).filter((line) => {
5540
- const key = /^\s*([A-Za-z0-9_-]+)\s*=/.exec(line)?.[1];
5541
- return key !== void 0 && keys.has(key);
5542
- });
5507
+ function packageRunnerSource(path) {
5508
+ const basename = path.replaceAll("\\", "/").split("/").pop()?.toLowerCase() ?? "";
5509
+ if ([
5510
+ "npm",
5511
+ "npm.cmd",
5512
+ "npm-cli.js",
5513
+ "npm-cli.cjs"
5514
+ ].includes(basename)) return "npm-exec";
5515
+ if ([
5516
+ "pnpm",
5517
+ "pnpm.cmd",
5518
+ "pnpm.js",
5519
+ "pnpm.cjs"
5520
+ ].includes(basename)) return "pnpm-exec";
5543
5521
  }
5544
- /** Removes all root permission assignment lines while preserving other text. */
5545
- function removePermissionLines(input) {
5546
- const firstTable = input.search(/^\s*\[/m);
5547
- const root = firstTable < 0 ? input : input.slice(0, firstTable);
5548
- const tables = firstTable < 0 ? "" : input.slice(firstTable);
5549
- const keys = PERMISSION_KEYS.map((key) => key.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"));
5550
- return `${root.split(/\r?\n/).filter((line) => !new RegExp(`^\\s*(?:${keys.join("|")})\\s*=`).test(line)).join("\n").trim()}${tables ? `\n${tables.trimStart()}` : ""}`.trim();
5522
+ function nodeRunnerSource(value) {
5523
+ if (typeof value === "object" && value !== null && "source" in value) {
5524
+ if (value.source === "pnpm-exec") return "pnpm-exec";
5525
+ if (value.source === "npm-exec") return "npm-exec";
5526
+ }
5527
+ return "npm-exec";
5551
5528
  }
5552
- /** Returns the exact tuple represented by an explicit autonomy mode. */
5553
- function permissionSelectionForMode(mode) {
5554
- if (mode === "default") return {
5555
- approvalPolicy: "on-request",
5556
- approvalsReviewer: "auto_review",
5557
- sandboxMode: "workspace-write"
5558
- };
5559
- if (mode === "autonomous") return {
5560
- approvalPolicy: "never",
5561
- sandboxMode: "workspace-write"
5562
- };
5529
+ function packageLauncher(command, platform, source) {
5563
5530
  return {
5564
- approvalPolicy: "never",
5565
- sandboxMode: "danger-full-access"
5531
+ command: typeof command === "string" ? command : source === "npm-exec" ? platform === "win32" ? "npm.cmd" : "npm" : platform === "win32" ? "pnpm.cmd" : "pnpm",
5532
+ argsPrefix: source === "npm-exec" ? [
5533
+ "exec",
5534
+ "--yes",
5535
+ "--package",
5536
+ CODEX_PACKAGE_SPEC,
5537
+ "--",
5538
+ "codex"
5539
+ ] : ["dlx", CODEX_PACKAGE_SPEC],
5540
+ source
5566
5541
  };
5567
5542
  }
5568
- /** Identifies generated tuples from current and historical installers. */
5569
- function permissionSelectionMatchesMode(selection, mode) {
5570
- if (permissionSelectionsEqual(selection, permissionSelectionForMode(mode))) return true;
5571
- return mode === "default" && permissionSelectionsEqual(selection, {
5572
- approvalPolicy: "on-request",
5573
- sandboxMode: "workspace-write"
5574
- });
5575
- }
5576
- /** Compares all raw permission fields, including intentional omissions. */
5577
- function permissionSelectionsEqual(left, right) {
5578
- return PERMISSION_KEYS.every((key) => {
5579
- const field = permissionField(key);
5580
- return left[field] === right[field];
5581
- });
5543
+ function toArray(value) {
5544
+ return Array.isArray(value) ? value : [value];
5582
5545
  }
5583
- /** Identifies a historical generated tuple, if one is exact. */
5584
- function inferAutonomyMode(selection) {
5585
- for (const mode of [
5586
- "default",
5587
- "autonomous",
5588
- "dangerous"
5589
- ]) if (permissionSelectionMatchesMode(selection, mode)) return mode;
5590
- return "custom";
5591
- }
5592
- /** Reads deterministic autonomy metadata from a managed block. */
5593
- function readAutonomyMetadata(input) {
5594
- const value = new RegExp(`^${escapeRegExp(AUTONOMY_PREFIX)}(.+)$`, "m").exec(input)?.[1]?.trim();
5595
- if (value === "default" || value === "autonomous" || value === "dangerous" || value === "custom") return value;
5596
- }
5597
- /** Encodes durable original root permission assignment provenance. */
5598
- function originalPermissionMetadata(lines) {
5599
- return `${ORIGINAL_PERMISSION_PREFIX}${lines.length === 0 ? "-" : Buffer.from(lines.join("\n"), "utf8").toString("base64")}\n`;
5600
- }
5601
- /** Reads durable original root permission assignment provenance. */
5602
- function readOriginalPermissionMetadata(input) {
5603
- const encoded = new RegExp(`^${escapeRegExp(ORIGINAL_PERMISSION_PREFIX)}([A-Za-z0-9+/=_-]+)$`, "m").exec(input)?.[1];
5604
- if (encoded === void 0) return void 0;
5605
- if (encoded === "-") return [];
5606
- return Buffer.from(encoded, "base64").toString("utf8").split(/\r?\n/).filter(Boolean);
5607
- }
5608
- /** Returns a generated tuple for an explicit request or preserves a live omitted selection. */
5609
- function selectPermissionSelection(live, request) {
5610
- if (request.requested) return permissionSelectionForMode(request.mode);
5611
- if (Object.keys(live).length > 0) return live;
5612
- return permissionSelectionForMode("default");
5613
- }
5614
- var AUTONOMY_METADATA_PREFIX = AUTONOMY_PREFIX;
5615
- function permissionField(key) {
5616
- if (key === "default_permissions") return "defaultPermissions";
5617
- if (key === "approval_policy") return "approvalPolicy";
5618
- if (key === "approvals_reviewer") return "approvalsReviewer";
5619
- return "sandboxMode";
5546
+ function normalizeLauncher(value, source) {
5547
+ if (typeof value === "string") {
5548
+ const command = value.trim();
5549
+ return command === "" ? void 0 : {
5550
+ command,
5551
+ argsPrefix: [],
5552
+ source
5553
+ };
5554
+ }
5555
+ if (typeof value !== "object" || value === null || typeof value.command !== "string") return void 0;
5556
+ const command = value.command.trim();
5557
+ if (command === "" || !Array.isArray(value.argsPrefix)) return void 0;
5558
+ if (!value.argsPrefix.every((arg) => typeof arg === "string")) return void 0;
5559
+ return {
5560
+ command,
5561
+ argsPrefix: [...value.argsPrefix],
5562
+ source
5563
+ };
5620
5564
  }
5621
- function escapeRegExp(value) {
5622
- return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
5565
+ function deduplicate(candidates) {
5566
+ const seen = /* @__PURE__ */ new Set();
5567
+ const result = [];
5568
+ for (const candidate of candidates) {
5569
+ const key = JSON.stringify([candidate.command, candidate.argsPrefix]);
5570
+ if (seen.has(key)) continue;
5571
+ seen.add(key);
5572
+ result.push(candidate);
5573
+ }
5574
+ return result;
5623
5575
  }
5624
5576
  //#endregion
5625
- //#region packages/cli/src/config.ts
5626
- var START = "# >>> holycodex managed >>>";
5627
- var END = "# <<< holycodex managed <<<";
5628
- var ORIGINAL_ROOT = "# holycodex original root: ";
5629
- var ORIGINAL_TABLE_KEY = "# holycodex original table key: ";
5630
- var PLAN_PREFIX = "# holycodex plan: ";
5631
- var FAST_MODE_PREFIX = "# holycodex fast: ";
5632
- var WORKFLOW_POLICY_PREFIX = "# holycodex workflow-policy: ";
5633
- var OLD_NAMESPACES = [
5634
- "marketplaces.sisyphuslabs",
5635
- "plugins.\"omo@sisyphuslabs\"",
5636
- "marketplaces.lazycodex",
5637
- "plugins.\"omo@lazycodex\"",
5638
- "marketplaces.code-yeongyu-codex-plugins",
5639
- "plugins.\"omo@code-yeongyu-codex-plugins\"",
5640
- "agents.plan",
5641
- "agents.metis",
5642
- "agents.momus",
5643
- "agents.oracle",
5644
- "agents.sisyphus",
5645
- "agents.prometheus",
5646
- "agents.atlas",
5647
- "agents.hephaestus",
5648
- "hooks.state.\"omo@sisyphuslabs",
5649
- "hooks.state.\"omo@lazycodex",
5650
- "hooks.state.\"omo@code-yeongyu-codex-plugins"
5651
- ];
5652
- function readOriginalRootMetadata(input) {
5653
- const encoded = input.match(/^# holycodex original root: ([A-Za-z0-9+/=]+)$/m)?.[1];
5654
- return encoded === void 0 ? void 0 : Buffer.from(encoded, "base64").toString("utf8");
5655
- }
5656
- function readLegacyGeneratedRoot(input) {
5657
- const body = input.match(/^# >>> holycodex managed >>>\r?\n([\s\S]*?)^# <<< holycodex managed <<</m)?.[1];
5658
- if (body === void 0 || readPermissionLines(body).length === 0) return void 0;
5659
- return inferAutonomyMode(readRawPermissionSelection(body)) === "custom" ? void 0 : body;
5660
- }
5661
- /** Removes managed configuration and restores durable original values. */
5662
- function removeManaged(input, preserveGeneratedPermissions = false) {
5663
- const escapedStart = START.replaceAll(">", "\\>");
5664
- const escapedEnd = END.replaceAll("<", "\\<");
5665
- return input.replace(new RegExp(`${escapedStart}([\\s\\S]*?)${escapedEnd}(?:\\r?\\n){0,2}`, "g"), (_match, body) => {
5666
- const original = readOriginalRootMetadata(body);
5667
- const originalPermissions = readOriginalPermissionMetadata(body);
5668
- const currentPermissions = readPermissionLines(body);
5669
- const currentSelection = readRawPermissionSelection(body);
5670
- const metadata = readAutonomyMetadata(body);
5671
- const expected = metadata === void 0 || metadata === "custom" ? originalPermissions === void 0 ? void 0 : readRawPermissionSelection(originalPermissions.join("\n")) : permissionSelectionForMode(metadata);
5672
- const generated = metadata !== void 0 && metadata !== "custom" ? permissionSelectionMatchesMode(currentSelection, metadata) : expected !== void 0 ? permissionSelectionsEqual(currentSelection, expected) : metadata === void 0 && [
5673
- "default",
5674
- "autonomous",
5675
- "dangerous"
5676
- ].some((mode) => permissionSelectionMatchesMode(currentSelection, mode));
5677
- const preserveCurrent = preserveGeneratedPermissions || !generated;
5678
- if (original !== void 0) return `${preserveCurrent ? `${removePermissionLines(original)}${currentPermissions.length === 0 ? "" : `\n${currentPermissions.join("\n")}`}`.trim() : `${removePermissionLines(original)}${(originalPermissions ?? readPermissionLines(original)).length === 0 ? "" : `\n${(originalPermissions ?? readPermissionLines(original)).join("\n")}`}`.trim()}\n`;
5679
- if (!preserveCurrent && originalPermissions !== void 0) return `${originalPermissions.join("\n")}\n`;
5680
- if (preserveCurrent && currentPermissions.length > 0) return `${currentPermissions.join("\n")}\n`;
5681
- const tableKeys = [...body.matchAll(/^# holycodex original table key: ([A-Za-z0-9+/=]+)$/gm)].flatMap((match) => match[1] === void 0 ? [] : [match[1]]);
5682
- return tableKeys.length === 0 ? "" : `${tableKeys.map((key) => Buffer.from(key, "base64").toString("utf8")).join("\n")}\n`;
5683
- }).trim();
5684
- }
5685
- /** Removes legacy omo. */
5686
- function removeLegacyOmo(input) {
5687
- return input.split(/(?=^\s*\[)/m).filter((section) => {
5688
- const header = /^\s*\[([^\]]+)]/.exec(section)?.[1];
5689
- if (header === void 0) return true;
5690
- if (OLD_NAMESPACES.some((name) => header === name || header.startsWith(`${name}.`) || name.includes("\"omo@") && header.startsWith(name))) return false;
5691
- return ![
5692
- "agents.explorer",
5693
- "agents.librarian",
5694
- "agents.worker"
5695
- ].some((name) => header === name || header.startsWith(`${name}.`)) || !/(?:sisyphuslabs|omo@|oh-my|code-yeongyu)/i.test(section);
5696
- }).join("").trimEnd();
5697
- }
5698
- function injectTableKeys(input, table, entries) {
5699
- const match = new RegExp(`^\\s*\\[${table.replaceAll(".", "\\.")}]\\s*(?:#.*)?$`, "m").exec(input);
5700
- const tail = match === null ? "" : input.slice(match.index + match[0].length);
5701
- const tableEnd = nextTableBoundary(tail);
5702
- const tableBody = tableEnd < 0 ? tail : tail.slice(0, tableEnd);
5703
- const managed = `${START}\n${entries.map(([key]) => new RegExp(`^[ \\t]*${key}[ \\t]*=.*$`, "m").exec(tableBody)?.[0]).filter((value) => value !== void 0).map((value) => `${ORIGINAL_TABLE_KEY}${Buffer.from(value).toString("base64")}\n`).join("")}${entries.map(([key, value]) => `${key} = ${value}`).join("\n")}\n${END}`;
5704
- if (match === null) return `${input.trimEnd()}\n\n${START}\n[${table}]\n${entries.map(([key, value]) => `${key} = ${value}`).join("\n")}\n${END}`.trim();
5705
- const bodyStart = match.index + match[0].length;
5706
- const next = nextTableBoundary(input.slice(bodyStart));
5707
- const bodyEnd = next < 0 ? input.length : bodyStart + next;
5708
- const cleanedBody = entries.reduce((body, [key]) => body.replace(new RegExp(`^\\s*${key}\\s*=.*\\r?\\n?`, "gm"), ""), input.slice(bodyStart, bodyEnd)).trim();
5709
- const suffix = input.slice(bodyEnd).trimStart();
5710
- return `${input.slice(0, bodyStart)}\n${cleanedBody ? `${cleanedBody}\n` : ""}${managed}${suffix ? `\n${suffix}` : ""}`.trim();
5711
- }
5712
- function nextTableBoundary(input) {
5713
- const header = /^\s*\[/m.exec(input)?.index ?? -1;
5714
- const managedHeader = /^# >>> holycodex managed >>>\r?\n\s*\[/m.exec(input)?.index ?? -1;
5715
- if (header < 0) return managedHeader;
5716
- if (managedHeader < 0) return header;
5717
- return Math.min(header, managedHeader);
5718
- }
5719
- function tableSource(input, table) {
5720
- const match = new RegExp(`^\\s*\\[${table.replaceAll(".", "\\.")}]\\s*(?:#.*)?$`, "m").exec(input);
5721
- if (match === null) return void 0;
5722
- const tail = input.slice(match.index + match[0].length);
5723
- const end = nextTableBoundary(tail);
5724
- return end < 0 ? tail : tail.slice(0, end);
5577
+ //#region packages/cli/src/codex-security.ts
5578
+ var CODEX_SECURITY_PLUGIN = {
5579
+ id: "codex-security@openai-curated",
5580
+ marketplace: "openai-curated"
5581
+ };
5582
+ var COMPUTER_USE_PLUGIN = {
5583
+ id: "computer-use@openai-bundled",
5584
+ marketplace: "openai-bundled"
5585
+ };
5586
+ var BUILD_WEB_APPS_PLUGIN = {
5587
+ id: "build-web-apps@openai-curated",
5588
+ marketplace: "openai-curated"
5589
+ };
5590
+ var CODEX_PLUGIN_OPERATIONAL_TIMEOUT_MS = 15e3;
5591
+ var CODEX_PACKAGE_BOOTSTRAP_TIMEOUT_MS = 12e4;
5592
+ var MAX_CODEX_CATALOG_DIAGNOSTIC_CHARS = 256 * 1024;
5593
+ var MAX_JSON_DOCUMENTS = 16;
5594
+ var MAX_MARKETPLACE_ATTEMPTS = 2;
5595
+ var SPAWN_UNAVAILABLE_CODES = /* @__PURE__ */ new Set([
5596
+ "EACCES",
5597
+ "ENOENT",
5598
+ "EPERM"
5599
+ ]);
5600
+ var FATAL_AUTH_CODES = /* @__PURE__ */ new Set([
5601
+ "401",
5602
+ "UNAUTHENTICATED",
5603
+ "AUTHENTICATION_REQUIRED"
5604
+ ]);
5605
+ var FATAL_ACCOUNT_CODES = /* @__PURE__ */ new Set(["ACCOUNT_REQUIRED", "ACCOUNT_NOT_FOUND"]);
5606
+ var FATAL_MARKETPLACE_CODES = /* @__PURE__ */ new Set([
5607
+ "502",
5608
+ "503",
5609
+ "504",
5610
+ "MARKETPLACE_UNAVAILABLE",
5611
+ "MARKETPLACE_LOAD_FAILED",
5612
+ "CATALOG_UNAVAILABLE"
5613
+ ]);
5614
+ var FATAL_PLUGIN_CODES = /* @__PURE__ */ new Set([
5615
+ "404",
5616
+ "PLUGIN_NOT_FOUND",
5617
+ "PLUGIN_UNAVAILABLE"
5618
+ ]);
5619
+ var FATAL_POLICY_CODES = /* @__PURE__ */ new Set([
5620
+ "403",
5621
+ "ACCOUNT_RESTRICTED",
5622
+ "ACCOUNT_UNAVAILABLE",
5623
+ "ACCOUNT_SUSPENDED",
5624
+ "ACCOUNT_DISABLED",
5625
+ "INSTALLATION_REJECTED",
5626
+ "PERMISSION_DENIED",
5627
+ "POLICY_REJECTED"
5628
+ ]);
5629
+ /** Installs or enables the official Codex Security plugin without failing HolyCodex installation. */
5630
+ async function installCodexSecurity(runProcess = runManagedProcess, platform = process.platform, env = process.env, options = {}) {
5631
+ return installOfficialPlugin(CODEX_SECURITY_PLUGIN, runProcess, platform, env, options);
5725
5632
  }
5726
- function rootValue(input, key) {
5727
- if (key === "status_line") return rootTomlStringArraySource(input, key);
5728
- return new RegExp(`^\\s*${key}\\s*=.*$`, "m").exec(input)?.[0];
5633
+ /** Installs or enables the official Computer Use plugin without failing HolyCodex installation. */
5634
+ async function installComputerUse(runProcess = runManagedProcess, platform = process.platform, env = process.env, options = {}) {
5635
+ return installOfficialPlugin(COMPUTER_USE_PLUGIN, runProcess, platform, env, options);
5729
5636
  }
5730
- function removeRootValue(input, value) {
5731
- return value === void 0 ? input : input.replace(value, "");
5637
+ /** Installs or enables the official Build Web Apps plugin without failing HolyCodex installation. */
5638
+ async function installBuildWebApps(runProcess = runManagedProcess, platform = process.platform, env = process.env, options = {}) {
5639
+ return installOfficialPlugin(BUILD_WEB_APPS_PLUGIN, runProcess, platform, env, options);
5732
5640
  }
5733
- function removeRootKey(input, key) {
5734
- let updated = input;
5735
- for (;;) {
5736
- const value = rootValue(updated, key);
5737
- if (value === void 0) return updated;
5738
- updated = removeRootValue(updated, value);
5641
+ /** Verifies one official plugin without installing or enabling it. */
5642
+ async function verifyOfficialPlugin(plugin, runProcess = runManagedProcess, platform = process.platform, env = process.env, options = {}) {
5643
+ const runtimeFacts = options.runtimeFacts ?? (runProcess === runManagedProcess ? defaultCodexLauncherRuntimeFacts(platform) : void 0);
5644
+ const candidates = createCodexLauncherCandidates({
5645
+ ...options.injected === void 0 ? {} : { injected: options.injected },
5646
+ ...runtimeFacts === void 0 ? {} : { runtimeFacts }
5647
+ });
5648
+ const attemptedLaunchers = [];
5649
+ const fallbackReasons = [];
5650
+ for (const launcher of candidates) {
5651
+ attemptedLaunchers.push(launcher.source);
5652
+ const outcome = inspectListResult(await runCodexPlugin(runProcess, launcher, [
5653
+ "plugin",
5654
+ "list",
5655
+ "--json"
5656
+ ], platform, env, "list"), launcher);
5657
+ if (outcome.kind === "selected") {
5658
+ const state = findPlugin(outcome.catalog, plugin.id);
5659
+ if (state?.installed === true && state.enabled === true) return {
5660
+ status: "verified",
5661
+ launcherSource: launcher.source
5662
+ };
5663
+ if (state !== void 0) return {
5664
+ status: "missing",
5665
+ attemptedLaunchers
5666
+ };
5667
+ fallbackReasons.push("plugin-unavailable");
5668
+ continue;
5669
+ }
5670
+ if (outcome.kind === "fatal") return {
5671
+ status: "unavailable",
5672
+ reason: outcome.reason,
5673
+ attemptedLaunchers
5674
+ };
5675
+ fallbackReasons.push(outcome.reason);
5739
5676
  }
5677
+ if (fallbackReasons.length === 0) return {
5678
+ status: "missing",
5679
+ attemptedLaunchers
5680
+ };
5681
+ return {
5682
+ status: "unavailable",
5683
+ reason: finalFallbackReason(fallbackReasons),
5684
+ attemptedLaunchers
5685
+ };
5740
5686
  }
5741
- /** Reads the explicitly recorded model routing plan from managed configuration. */
5742
- function readManagedPlan(input) {
5743
- const value = new RegExp(`^${PLAN_PREFIX}(.+)$`, "m").exec(input)?.[1]?.trim();
5744
- return PLAN_NAMES.find((plan) => plan === value);
5687
+ /** Installs or enables one official Codex plugin through a verified catalog entry. */
5688
+ async function installOfficialPlugin(plugin, runProcess = runManagedProcess, platform = process.platform, env = process.env, options = {}) {
5689
+ const runtimeFacts = options.runtimeFacts ?? (runProcess === runManagedProcess ? defaultCodexLauncherRuntimeFacts(platform) : void 0);
5690
+ const candidates = createCodexLauncherCandidates({
5691
+ ...options.injected === void 0 ? {} : { injected: options.injected },
5692
+ ...runtimeFacts === void 0 ? {} : { runtimeFacts }
5693
+ });
5694
+ const attemptedLaunchers = [];
5695
+ const fallbackReasons = [];
5696
+ for (const launcher of candidates) {
5697
+ attemptedLaunchers.push(launcher.source);
5698
+ let installedOutcome = inspectListResult(await runCodexPlugin(runProcess, launcher, [
5699
+ "plugin",
5700
+ "list",
5701
+ "--json"
5702
+ ], platform, env, "list"), launcher);
5703
+ if (launcher.source === "path" && installedOutcome.kind === "fallback" && installedOutcome.reason === "download-failed") installedOutcome = inspectListResult(await runCodexPlugin(runProcess, launcher, [
5704
+ "plugin",
5705
+ "list",
5706
+ "--json"
5707
+ ], platform, env, "list"), launcher);
5708
+ if (installedOutcome.kind === "fallback") {
5709
+ fallbackReasons.push(installedOutcome.reason);
5710
+ continue;
5711
+ }
5712
+ if (installedOutcome.kind === "fatal") return skipped(installedOutcome.reason, attemptedLaunchers);
5713
+ const installedPlugin = findPlugin(installedOutcome.catalog, plugin.id);
5714
+ if (installedPlugin?.installed === true && installedPlugin.enabled === true) return {
5715
+ status: "already-installed",
5716
+ launcherSource: launcher.source
5717
+ };
5718
+ const wasDisabled = installedPlugin?.installed === true;
5719
+ if (!wasDisabled) {
5720
+ const catalogOutcome = inspectListResult(await runCodexPlugin(runProcess, launcher, [
5721
+ "plugin",
5722
+ "list",
5723
+ "--available",
5724
+ "--json"
5725
+ ], platform, env, "list"), launcher);
5726
+ if (catalogOutcome.kind === "fallback") {
5727
+ fallbackReasons.push(catalogOutcome.reason);
5728
+ continue;
5729
+ }
5730
+ if (catalogOutcome.kind === "fatal") return skipped(catalogOutcome.reason, attemptedLaunchers);
5731
+ let pluginAvailable = findPlugin(catalogOutcome.catalog, plugin.id) !== void 0;
5732
+ if (!pluginAvailable) {
5733
+ const marketplaceOutcome = await inspectMarketplaceWithRetry(runProcess, launcher, platform, env);
5734
+ if (marketplaceOutcome.kind === "fallback") {
5735
+ fallbackReasons.push(marketplaceOutcome.reason);
5736
+ continue;
5737
+ }
5738
+ if (marketplaceOutcome.kind === "fatal") return skipped(marketplaceOutcome.reason, attemptedLaunchers);
5739
+ if (plugin.id === COMPUTER_USE_PLUGIN.id && !marketplaceOutcome.marketplaces.includes(plugin.marketplace)) {
5740
+ const refreshedCatalog = inspectListResult(await runCodexPlugin(runProcess, launcher, [
5741
+ "plugin",
5742
+ "list",
5743
+ "--available",
5744
+ "--json"
5745
+ ], platform, env, "list"), launcher);
5746
+ if (refreshedCatalog.kind === "selected") pluginAvailable = findPlugin(refreshedCatalog.catalog, plugin.id) !== void 0;
5747
+ else fallbackReasons.push(refreshedCatalog.reason);
5748
+ }
5749
+ if (!pluginAvailable) {
5750
+ fallbackReasons.push(marketplaceOutcome.marketplaces.includes(plugin.marketplace) ? "plugin-not-offered" : "marketplace-unavailable");
5751
+ continue;
5752
+ }
5753
+ }
5754
+ }
5755
+ const addOutcome = inspectAddResult(await runCodexPlugin(runProcess, launcher, [
5756
+ "plugin",
5757
+ "add",
5758
+ plugin.id,
5759
+ "--json"
5760
+ ], platform, env, "add"), launcher);
5761
+ if (addOutcome.kind === "fallback") {
5762
+ fallbackReasons.push(addOutcome.reason);
5763
+ continue;
5764
+ }
5765
+ if (addOutcome.kind === "fatal") return skipped(addOutcome.reason, attemptedLaunchers);
5766
+ const verification = inspectListResult(await runCodexPlugin(runProcess, launcher, [
5767
+ "plugin",
5768
+ "list",
5769
+ "--json"
5770
+ ], platform, env, "list"), launcher);
5771
+ if (verification.kind === "fallback") {
5772
+ fallbackReasons.push(verification.reason);
5773
+ continue;
5774
+ }
5775
+ if (verification.kind === "fatal") return skipped(verification.reason, attemptedLaunchers);
5776
+ const verifiedPlugin = findPlugin(verification.catalog, plugin.id);
5777
+ if (verifiedPlugin?.installed !== true || verifiedPlugin.enabled !== true) {
5778
+ fallbackReasons.push("verification-failed");
5779
+ continue;
5780
+ }
5781
+ return {
5782
+ status: wasDisabled ? "enabled" : "installed",
5783
+ launcherSource: launcher.source
5784
+ };
5785
+ }
5786
+ return skipped(finalFallbackReason(fallbackReasons), attemptedLaunchers);
5745
5787
  }
5746
- /** Reads the explicitly recorded managed Fast mode. */
5747
- function readManagedFastMode(input) {
5748
- const value = new RegExp(`^${FAST_MODE_PREFIX}(.+)$`, "m").exec(input)?.[1]?.trim();
5749
- return FastModeSchema.safeParse(value).data;
5788
+ async function inspectMarketplaceWithRetry(runProcess, launcher, platform, env) {
5789
+ let outcome = {
5790
+ kind: "fallback",
5791
+ reason: "marketplace-unavailable"
5792
+ };
5793
+ for (let attempt = 0; attempt < MAX_MARKETPLACE_ATTEMPTS; attempt += 1) {
5794
+ outcome = inspectMarketplaceResult(await runCodexPlugin(runProcess, launcher, [
5795
+ "plugin",
5796
+ "marketplace",
5797
+ "list",
5798
+ "--json"
5799
+ ], platform, env, "list"), launcher);
5800
+ if (!isRetryableMarketplaceOutcome(outcome) || attempt + 1 === MAX_MARKETPLACE_ATTEMPTS) return outcome;
5801
+ await new Promise((resolve) => setTimeout(resolve, 100 * (attempt + 1)));
5802
+ }
5803
+ return outcome;
5750
5804
  }
5751
- /** Reads the plan-authoritative workflow policy metadata from managed configuration. */
5752
- function readManagedWorkflowPolicy(input) {
5753
- const raw = new RegExp(`^${WORKFLOW_POLICY_PREFIX.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}(.+)$`, "m").exec(input)?.[1];
5754
- if (raw === void 0) return void 0;
5805
+ function isRetryableMarketplaceOutcome(outcome) {
5806
+ return (outcome.kind === "fallback" || outcome.kind === "fatal") && (outcome.reason === "marketplace-unavailable" || outcome.reason === "timeout");
5807
+ }
5808
+ async function runCodexPlugin(runProcess, launcher, args, platform, env, operation) {
5755
5809
  try {
5756
- const value = JSON.parse(raw);
5757
- if (typeof value !== "object" || value === null) return void 0;
5758
- const record = value;
5759
- const plan = PLAN_NAMES.find((name) => name === record.plan);
5760
- const limits = record.limits;
5761
- const usage = record.projectedUsage;
5762
- const size = record.softSizeGuidance;
5763
- if (plan === void 0 || typeof limits !== "object" || limits === null || typeof usage !== "object" || usage === null || typeof size !== "object" || size === null) return void 0;
5810
+ return await runProcess({
5811
+ command: launcher.command,
5812
+ args: codexLauncherArgs(launcher, args),
5813
+ platform,
5814
+ timeoutMs: timeoutFor(launcher, operation),
5815
+ maxOutputChars: MAX_CODEX_CATALOG_DIAGNOSTIC_CHARS,
5816
+ env
5817
+ });
5818
+ } catch (error) {
5819
+ const code = thrownErrorCode(error);
5820
+ if (!isUnavailableThrownError(error) && !(isPackageLauncher(launcher) && isBootstrapThrownError(error))) throw error;
5764
5821
  return {
5765
- plan,
5766
- limits,
5767
- projectedUsage: usage,
5768
- softSizeGuidance: size
5822
+ exitCode: null,
5823
+ stdout: "",
5824
+ stderr: "",
5825
+ timedOut: false,
5826
+ matched: false,
5827
+ outputTruncated: false,
5828
+ error: "Codex launcher could not be started.",
5829
+ ...code === void 0 ? {} : { errorCode: code }
5769
5830
  };
5770
- } catch {
5771
- return;
5772
5831
  }
5773
5832
  }
5774
- /** Identifies explicit Root route overrides preserved from active managed configuration. */
5775
- function readPreservedRootOverrides(input) {
5776
- const managedRoot = new RegExp(`^${START}\\r?\\n([\\s\\S]*?)^${END}\\r?$`, "m").exec(input)?.[1];
5777
- if (managedRoot === void 0) return {
5778
- model: false,
5779
- reasoningEffort: false,
5780
- webSearch: false
5833
+ function inspectListResult(result, launcher) {
5834
+ if (result.timedOut) return {
5835
+ kind: "fallback",
5836
+ reason: "timeout"
5781
5837
  };
5782
- const plan = readManagedPlan(managedRoot);
5783
- const model = rootTomlString(input, "model");
5784
- const reasoningEffort = rootTomlString(input, "model_reasoning_effort");
5785
- if (plan === void 0 || model === void 0 || reasoningEffort === void 0) return {
5786
- model: false,
5787
- reasoningEffort: false,
5788
- webSearch: false
5838
+ if (result.outputTruncated) return {
5839
+ kind: "fallback",
5840
+ reason: "invalid-response"
5789
5841
  };
5790
- if (MANAGED_ROOT_MODEL_HISTORY_BY_PLAN[plan].some((route) => route.model === model && route.reasoningEffort === reasoningEffort)) return {
5791
- model: false,
5792
- reasoningEffort: false,
5793
- webSearch: rootTomlString(managedRoot, "web_search") !== "live"
5842
+ const failure = classifyFailure(result, launcher);
5843
+ if (failure !== void 0) return failure;
5844
+ const catalog = parsePluginCatalog(result.stdout);
5845
+ if (catalog === void 0) return {
5846
+ kind: "fallback",
5847
+ reason: "invalid-response"
5794
5848
  };
5795
- const preset = MODEL_ROUTING_PLANS[plan].root;
5796
5849
  return {
5797
- model: model !== preset.model,
5798
- reasoningEffort: reasoningEffort !== preset.reasoningEffort,
5799
- webSearch: rootTomlString(managedRoot, "web_search") !== "live"
5850
+ kind: "selected",
5851
+ catalog
5800
5852
  };
5801
5853
  }
5802
- function preserveManagedRootPreferences(input, base) {
5803
- const managedRoot = new RegExp(`^${START}\\r?\\n([\\s\\S]*?)^${END}\\r?$`, "m").exec(input)?.[1];
5804
- if (managedRoot === void 0) return base;
5805
- const firstTable = base.search(/^\s*\[/m);
5806
- const root = firstTable < 0 ? base : base.slice(0, firstTable);
5807
- const tables = firstTable < 0 ? "" : base.slice(firstTable);
5808
- let updatedRoot = root.trim();
5809
- const overrides = readPreservedRootOverrides(input);
5810
- for (const [key, preserve] of [
5811
- ["model", overrides.model],
5812
- ["model_reasoning_effort", overrides.reasoningEffort],
5813
- ["web_search", overrides.webSearch]
5814
- ]) {
5815
- const live = rootValue(managedRoot, key)?.trim();
5816
- if (!preserve || live === void 0) continue;
5817
- if (rootValue(root, key)?.trim() === live) continue;
5818
- updatedRoot = removeRootValue(updatedRoot, rootValue(updatedRoot, key)).trim();
5819
- updatedRoot = `${updatedRoot}${updatedRoot ? "\n" : ""}${live}`;
5820
- }
5821
- if (updatedRoot === root.trim()) return base;
5822
- return `${updatedRoot}${tables ? `\n${tables.trimStart()}` : ""}`;
5854
+ function inspectAddResult(result, launcher) {
5855
+ if (result.timedOut) return {
5856
+ kind: "fallback",
5857
+ reason: "timeout"
5858
+ };
5859
+ const failure = classifyFailure(result, launcher);
5860
+ if (failure !== void 0) return failure;
5861
+ return { kind: "added" };
5823
5862
  }
5824
- function mergedStatusLine(original) {
5825
- if (original === void 0) return "[\"model-with-reasoning\", \"context-remaining\", \"current-dir\"]";
5826
- const items = rootTomlStringArray(original, "status_line") ?? [];
5827
- if (!items.includes("context-remaining")) items.push("context-remaining");
5828
- return `[${items.map((item) => JSON.stringify(item)).join(", ")}]`;
5863
+ function inspectMarketplaceResult(result, launcher) {
5864
+ if (result.timedOut) return {
5865
+ kind: "fallback",
5866
+ reason: "timeout"
5867
+ };
5868
+ if (result.outputTruncated) return {
5869
+ kind: "fallback",
5870
+ reason: "invalid-response"
5871
+ };
5872
+ const failure = classifyFailure(result, launcher);
5873
+ if (failure !== void 0) return failure;
5874
+ const marketplaces = parseMarketplaceNames(result.stdout);
5875
+ return marketplaces === void 0 ? {
5876
+ kind: "fallback",
5877
+ reason: "invalid-response"
5878
+ } : {
5879
+ kind: "selected",
5880
+ marketplaces
5881
+ };
5829
5882
  }
5830
- /** Installs config. */
5831
- function installConfig(input, mode, _platform, plan = DEFAULT_PLAN, maxSubagents, fastMode = "standard") {
5832
- const request = normalizeRequestedAutonomy(mode);
5833
- const priorAutonomy = readAutonomyMetadata(input);
5834
- const previousOriginalRoot = readOriginalRootMetadata(input);
5835
- const legacyGeneratedRoot = readLegacyGeneratedRoot(input);
5836
- const originalPermissionLines = readOriginalPermissionMetadata(input);
5837
- const base = preserveManagedRootPreferences(input, removeLegacyOmo(removeManaged(input, !request.requested)));
5838
- const firstTable = base.search(/^\s*\[/m);
5839
- const root = firstTable < 0 ? base : base.slice(0, firstTable);
5840
- const tables = firstTable < 0 ? "" : base.slice(firstTable);
5841
- const permissions = selectPermissionSelection(readRawPermissionSelection(root), request);
5842
- const effectiveAutonomy = request.requested ? inferAutonomyMode(permissions) : priorAutonomy ?? inferAutonomyMode(permissions);
5843
- const rootPermissionLines = [
5844
- permissions.approvalPolicy === void 0 ? void 0 : `approval_policy = ${JSON.stringify(permissions.approvalPolicy)}`,
5845
- permissions.approvalsReviewer === void 0 ? void 0 : `approvals_reviewer = ${JSON.stringify(permissions.approvalsReviewer)}`,
5846
- permissions.sandboxMode === void 0 ? void 0 : `sandbox_mode = ${JSON.stringify(permissions.sandboxMode)}`
5847
- ].filter((line) => line !== void 0);
5848
- const hadManagedAutonomy = readAutonomyMetadata(input) !== void 0;
5849
- const hadOriginalRoot = /^# holycodex original root:/m.test(input);
5850
- const permissionLines = originalPermissionLines ?? (legacyGeneratedRoot !== void 0 && previousOriginalRoot === void 0 ? [] : previousOriginalRoot === void 0 ? hadManagedAutonomy && !hadOriginalRoot ? [] : readPermissionLines(root) : readPermissionLines(previousOriginalRoot));
5851
- const controlled = [
5852
- "web_search",
5853
- "approval_policy",
5854
- "approvals_reviewer",
5855
- "sandbox_mode",
5856
- "max_concurrent_threads_per_session",
5857
- "status_line",
5858
- "model_verbosity",
5859
- "service_tier",
5860
- ...request.requested ? ["default_permissions"] : []
5861
- ].map((key) => rootValue(root, key));
5862
- const preservedRoot = [
5863
- "web_search",
5864
- "approval_policy",
5865
- "approvals_reviewer",
5866
- "sandbox_mode",
5867
- "max_concurrent_threads_per_session",
5868
- "status_line",
5869
- "model_verbosity",
5870
- "service_tier",
5871
- ...request.requested ? ["default_permissions"] : []
5872
- ].reduce(removeRootKey, root).trim();
5873
- const originalControlled = controlled.filter((value) => value !== void 0).sort((left, right) => root.indexOf(left) - root.indexOf(right)).join("\n");
5874
- const hasModel = /^\s*model\s*=/m.test(preservedRoot);
5875
- const hasEffort = /^\s*model_reasoning_effort\s*=/m.test(preservedRoot);
5876
- const rootRoute = MODEL_ROUTING_PLANS[plan].root;
5877
- const model = hasModel ? "" : `model = "${rootRoute.model}"\n`;
5878
- const effort = hasEffort ? "" : `model_reasoning_effort = "${rootRoute.reasoningEffort}"\n`;
5879
- const originalSource = previousOriginalRoot === void 0 ? priorAutonomy === void 0 && legacyGeneratedRoot === void 0 ? originalControlled : "" : removePermissionLines(previousOriginalRoot);
5880
- const original = originalSource ? `${ORIGINAL_ROOT}${Buffer.from(originalSource).toString("base64")}\n` : "";
5881
- const rootServiceTier = fastMode === "fast-all" ? "fast" : "default";
5882
- const priorManagedRoot = new RegExp(`^${START}\\r?\\n([\\s\\S]*?)^${END}\\r?$`, "m").exec(input)?.[1];
5883
- const webSearch = readPreservedRootOverrides(input).webSearch ? rootTomlString(priorManagedRoot ?? "", "web_search") ?? "live" : "live";
5884
- const statusLine = mergedStatusLine(rootValue(root, "status_line") ?? rootTomlStringArraySource(tableSource(base, "tui") ?? "", "status_line"));
5885
- const workflow = MODEL_ROUTING_PLANS[plan].workflow;
5886
- const rootBlock = `${START}\n${PLAN_PREFIX}${plan}\n${FAST_MODE_PREFIX}${fastMode}\n${WORKFLOW_POLICY_PREFIX}${JSON.stringify({
5887
- plan,
5888
- limits: workflow.limits,
5889
- projectedUsage: workflow.projectedUsage,
5890
- softSizeGuidance: workflow.softSizeGuidance
5891
- })}\n${AUTONOMY_METADATA_PREFIX}${effectiveAutonomy}\n${original}${originalPermissionMetadata(permissionLines)}${model}${effort}web_search = ${JSON.stringify(webSearch)}\nmodel_verbosity = "low"\nservice_tier = "${rootServiceTier}"\n${rootPermissionLines.join("\n")}\n${END}`;
5892
- let configured = `${preservedRoot ? `${preservedRoot}\n` : ""}${rootBlock}${tables ? `\n\n${tables}` : ""}`;
5893
- const legacyMultiAgentV2 = /\bmulti_agent_v2\s*=\s*(true|false)/.exec(configured)?.[1];
5894
- configured = injectTableKeys(configured, "features", [
5895
- ["default_mode_request_user_input", "true"],
5896
- ["multi_agent", "true"],
5897
- ...legacyMultiAgentV2 === void 0 ? [] : [["multi_agent_v2", legacyMultiAgentV2]]
5898
- ]);
5899
- configured = injectTableKeys(configured, "agents", [["max_concurrent_threads_per_session", String((maxSubagents ?? workflow.limits.concurrency) + 1)]]);
5900
- configured = injectTableKeys(configured, "tui", [["status_line", statusLine]]);
5901
- if (effectiveAutonomy !== "dangerous") configured = injectTableKeys(configured, "sandbox_workspace_write", [["network_access", "true"]]);
5902
- configured = injectTableKeys(configured, "desktop", [["show-context-window-usage", "true"]]);
5903
- if (_platform === "win32") configured = injectTableKeys(configured, "windows", [["sandbox", "\"unelevated\""]]);
5904
- for (const agent of AGENTS) configured = injectTableKeys(configured, `agents.${agent}`, [["config_file", `"holycodex/agents/${agent}.toml"`]]);
5905
- const plugin = `${START}\n[plugins."holycodex@holycodex"]\nenabled = true\n${END}`;
5906
- return `${configured.trim()}\n\n${plugin}\n`;
5907
- }
5908
- //#endregion
5909
- //#region packages/cli/src/context7.ts
5910
- var RUNNERS = [
5911
- {
5912
- executable: "nubx",
5913
- command: "nubx",
5914
- prefix: ["-y"]
5915
- },
5916
- {
5917
- executable: "nub",
5918
- command: "nub",
5919
- prefix: ["dlx"]
5920
- },
5921
- {
5922
- executable: "bunx",
5923
- command: "bunx",
5924
- prefix: []
5925
- },
5926
- {
5927
- executable: "bun",
5928
- command: "bun",
5929
- prefix: ["x"]
5930
- },
5931
- {
5932
- executable: "pnpmx",
5933
- command: "pnpmx",
5934
- prefix: []
5935
- },
5936
- {
5937
- executable: "pnpm",
5938
- command: "pnpm",
5939
- prefix: ["dlx"]
5940
- },
5941
- {
5942
- executable: "npmx",
5943
- command: "npmx",
5944
- prefix: ["--yes"]
5945
- },
5946
- {
5947
- executable: "npm",
5948
- command: "npx",
5949
- prefix: ["--yes"]
5950
- },
5951
- {
5952
- executable: "yarn",
5953
- command: "yarn",
5954
- prefix: ["dlx"]
5955
- }
5956
- ];
5957
- /** Constructs the supported direct Context7 invocation for the first available runner. */
5958
- function context7Command(args, executableExists = executableOnPath, env = process.env) {
5959
- const runner = RUNNERS.find((candidate) => executableExists(candidate.executable));
5960
- if (runner === void 0) return void 0;
5961
- return {
5962
- command: runner.command,
5963
- args: [
5964
- ...runner.prefix,
5965
- "ctx7@latest",
5966
- ...args
5967
- ],
5968
- env: {
5969
- ...env,
5970
- CI: env.CI ?? "1"
5971
- }
5972
- };
5883
+ function findPlugin(catalog, pluginId) {
5884
+ return catalog.plugins.find(({ id }) => id === pluginId);
5973
5885
  }
5974
- /** Reports whether an executable can be resolved from PATH. */
5975
- function executableOnPath(name) {
5976
- const path = process.env.PATH;
5977
- if (path === void 0) return false;
5978
- const extensions = process.platform === "win32" ? [
5979
- ".exe",
5980
- ".cmd",
5981
- ".bat",
5982
- ""
5983
- ] : [""];
5984
- for (const directory of path.split(delimiter)) for (const extension of extensions) try {
5985
- if (process.getBuiltinModule("node:fs").existsSync(`${directory}/${name}${extension}`)) return true;
5986
- } catch {
5987
- continue;
5886
+ function classifyFailure(result, launcher) {
5887
+ if (result.error !== void 0) {
5888
+ if (isUnavailableProcessError(result)) return {
5889
+ kind: "fallback",
5890
+ reason: "codex-unavailable"
5891
+ };
5892
+ return {
5893
+ kind: "fallback",
5894
+ reason: isPackageLauncher(launcher) ? "download-failed" : "invalid-response"
5895
+ };
5988
5896
  }
5989
- return false;
5990
- }
5991
- //#endregion
5992
- //#region packages/cli/src/doctor.ts
5993
- var DOCTOR_LSP_IDLE_SHUTDOWN_MS = 1e3;
5994
- var COMPATIBILITY_KEYS = ["desktop.show-context-window-usage"];
5995
- async function runCommand(name, args, env) {
5996
- const result = await runManagedProcess({
5997
- command: name,
5998
- args,
5999
- platform: process.platform,
6000
- timeoutMs: 15e3,
6001
- maxOutputChars: 64 * 1024,
6002
- ...env === void 0 ? {} : { env }
6003
- });
6004
- return {
6005
- ok: result.exitCode === 0 && !result.timedOut && result.error === void 0,
6006
- output: `${result.stdout}\n${result.stderr}`.trim() || result.error || ""
5897
+ if (result.exitCode === 0) return void 0;
5898
+ const failureReason = classifyFailureReason(structuredErrorCodeFromOutput(result.stderr) ?? structuredErrorCodeFromOutput(result.stdout), sanitizeDiagnostic(result.stderr));
5899
+ if (failureReason === "unauthenticated" || failureReason === "installation-rejected") return {
5900
+ kind: "fatal",
5901
+ reason: failureReason
6007
5902
  };
6008
- }
6009
- var defaultRuntime$1 = {
6010
- platform: process.platform,
6011
- command: runCommand,
6012
- executable: executableOnPath,
6013
- gitBash: resolveGitBashForCurrentProcess
6014
- };
6015
- function check(id, status, code, detail, fix) {
6016
5903
  return {
6017
- id,
6018
- status,
6019
- code,
6020
- detail,
6021
- ...fix === void 0 ? {} : { fix }
5904
+ kind: "fallback",
5905
+ reason: failureReason
6022
5906
  };
6023
5907
  }
6024
- async function missingFiles(root, paths) {
6025
- const missing = [];
6026
- for (const path of paths) try {
6027
- await access(join(root, path));
6028
- } catch {
6029
- missing.push(path);
5908
+ function classifyFailureReason(code, diagnostic) {
5909
+ if (code !== void 0) {
5910
+ if (FATAL_AUTH_CODES.has(code) || FATAL_ACCOUNT_CODES.has(code)) return "unauthenticated";
5911
+ if (FATAL_MARKETPLACE_CODES.has(code)) return "marketplace-unavailable";
5912
+ if (FATAL_PLUGIN_CODES.has(code)) return "plugin-unavailable";
5913
+ if (FATAL_POLICY_CODES.has(code)) return "installation-rejected";
5914
+ if (SPAWN_UNAVAILABLE_CODES.has(code)) return "codex-unavailable";
5915
+ if ([
5916
+ "ETIMEDOUT",
5917
+ "ECONNRESET",
5918
+ "ECONNREFUSED",
5919
+ "EAI_AGAIN",
5920
+ "ENETUNREACH"
5921
+ ].includes(code)) return "download-failed";
6030
5922
  }
6031
- return missing;
5923
+ const lower = diagnostic.toLowerCase();
5924
+ if (/unknown (?:command|subcommand)|unrecognized (?:command|subcommand)|invalid subcommand/.test(lower)) return "unsupported";
5925
+ if (/not supported on (?:this )?platform|unsupported (?:platform|architecture)|no matching (?:binary|package)|platform package|not compatible/.test(lower)) return "unsupported";
5926
+ if (/unauthenticated|authentication required|not logged in|account (?:required|not found)/.test(lower)) return "unauthenticated";
5927
+ if (/account (?:restricted|unavailable|suspended|disabled)/.test(lower)) return "installation-rejected";
5928
+ if (/marketplace|catalog/.test(lower)) return "marketplace-unavailable";
5929
+ if (/eai_again|enetwork|network|timed out|timeout|download|fetch|resolve package/.test(lower)) return "download-failed";
5930
+ if (/plugin (?:not found|unavailable|missing)/.test(lower)) return "plugin-unavailable";
5931
+ if (/permission denied|policy|rejected|forbidden/.test(lower)) return "installation-rejected";
5932
+ return "invalid-response";
6032
5933
  }
6033
- function tableBody(config, table) {
6034
- return new RegExp(`^\\s*\\[${table.replaceAll(".", "\\.")}]\\s*$([\\s\\S]*?)(?=^\\s*\\[|(?![\\s\\S]))`, "m").exec(config)?.[1];
5934
+ function finalFallbackReason(reasons) {
5935
+ if (reasons.length > 0 && reasons.every((reason) => reason === "plugin-not-offered")) return "all-launchers-lacked-plugin";
5936
+ if (reasons.includes("verification-failed")) return "verification-failed";
5937
+ if (reasons.includes("plugin-not-offered")) return "plugin-not-offered";
5938
+ if (reasons.includes("timeout")) return "timeout";
5939
+ if (reasons.includes("unsupported")) return "unsupported";
5940
+ if (reasons.includes("marketplace-unavailable")) return "marketplace-unavailable";
5941
+ if (reasons.includes("download-failed")) return "download-failed";
5942
+ if (reasons.includes("plugin-unavailable")) return "plugin-unavailable";
5943
+ if (reasons.includes("invalid-response")) return "invalid-response";
5944
+ return "codex-unavailable";
6035
5945
  }
6036
- function tableValue(config, table, key) {
6037
- const body = tableBody(config, table);
6038
- return body === void 0 ? void 0 : new RegExp(`^\\s*${key.replaceAll("-", "\\-")}\\s*=\\s*(.+?)\\s*$`, "m").exec(body)?.[1];
5946
+ function timeoutFor(launcher, operation) {
5947
+ return operation === "list" && isPackageLauncher(launcher) ? CODEX_PACKAGE_BOOTSTRAP_TIMEOUT_MS : CODEX_PLUGIN_OPERATIONAL_TIMEOUT_MS;
6039
5948
  }
6040
- function autonomy(config) {
6041
- const approval = rootTomlString(config, "approval_policy");
6042
- const reviewer = rootTomlString(config, "approvals_reviewer");
6043
- const sandbox = rootTomlString(config, "sandbox_mode");
6044
- const network = tableValue(config, "sandbox_workspace_write", "network_access");
6045
- if (approval === "on-request" && reviewer === "auto_review" && sandbox === "workspace-write" && network === "true") return "safe-workspace";
6046
- if (approval === "never" && reviewer === void 0 && sandbox === "workspace-write" && network === "true") return "autonomous-workspace";
6047
- if (approval === "never" && reviewer === void 0 && sandbox === "danger-full-access") return "dangerous";
6048
- return "unknown";
5949
+ function isPackageLauncher(launcher) {
5950
+ return launcher.source === "bunx" || launcher.source === "npm-exec" || launcher.source === "pnpm-exec";
6049
5951
  }
6050
- /** Runs installation, configuration, runtime, and override health checks. */
6051
- async function doctor(home = process.env.CODEX_HOME ?? join(homedir(), ".codex"), runtime = defaultRuntime$1) {
6052
- const checks = [];
6053
- const pluginRoot = join(home, "plugins", "cache", "holycodex", "holycodex", VERSION);
6054
- const agentRoot = join(home, "holycodex", "agents");
6055
- const configPath = join(home, "config.toml");
6056
- let config = "";
6057
- try {
6058
- config = await readFile(configPath, "utf8");
6059
- } catch {
6060
- checks.push(check("config", "error", "config-missing", `Missing ${configPath}.`, "Run holycodex install."));
6061
- }
6062
- const missing = await missingFiles(pluginRoot, [
6063
- ".codex-plugin/plugin.json",
6064
- "hooks/hooks.json",
6065
- ...requiredPackageRuntimes(runtime.platform).map((file) => `runtime/${file}`),
6066
- ...AGENTS.map((name) => `agents/${name}.toml`),
6067
- ...SKILLS.map((name) => `skills/${name}/SKILL.md`)
6068
- ]);
6069
- checks.push(missing.length === 0 ? check("package", "ok", "package-ready", `Plugin ${VERSION}, runtimes, agents, and ${SKILLS.length} skills are present.`) : check("package", "error", "package-incomplete", `Missing ${missing.join(", ")}.`, "Reinstall HolyCodex."));
6070
- const webSearchOverride = readPreservedRootOverrides(config).webSearch;
6071
- checks.push(rootTomlString(config, "web_search") === "live" ? check("web-search", "ok", "live-web-search", "Managed web search defaults to live.") : webSearchOverride ? check("web-search", "ok", "web-search-override", "An intentional user web-search override is preserved.") : check("web-search", "error", "web-search-not-live", "Managed web search is not live.", "Reinstall HolyCodex."));
6072
- const status = rootTomlStringArray(config, "status_line") ?? rootTomlStringArray(tableBody(config, "tui") ?? "", "status_line");
6073
- checks.push(status?.includes("context-remaining") ? check("context-visibility", "ok", "context-visible", "Context-window usage remains visible.") : check("context-visibility", "error", "context-hidden", "The status line does not show context remaining.", "Reinstall HolyCodex."));
6074
- checks.push(check("screenshot", "ok", "screenshot-default-preserved", "HolyCodex does not override the enabled Codex screenshot default."));
6075
- const context7 = context7Command(["--version"], runtime.executable);
6076
- if (context7 === void 0) checks.push(check("context7", "error", "context7-runner-missing", "No supported direct Context7 runner is available.", "Install nub, Bun, pnpm, npm, or Yarn."));
6077
- else checks.push(check("context7", "ok", "context7-cli-ready", `${context7.command} constructs a valid direct ctx7@latest command.`));
6078
- const lsp = await runtime.command(process.execPath, [
6079
- join(pluginRoot, "runtime", "lsp.js"),
6080
- "status",
6081
- "--json"
6082
- ], {
6083
- ...process.env,
6084
- HOLYCODEX_LSP_IDLE_SHUTDOWN_MS: String(DOCTOR_LSP_IDLE_SHUTDOWN_MS),
6085
- HOLYCODEX_LSP_IDLE_CHECK_INTERVAL_MS: "50"
6086
- });
6087
- checks.push(lsp.ok ? check("lsp", "ok", "lsp-cli-ready", "The LSP CLI and daemon are reachable.") : check("lsp", "error", "lsp-cli-failed", lsp.output || "LSP CLI failed.", "Reinstall HolyCodex and inspect the reported daemon log."));
6088
- if (runtime.platform === "win32") {
6089
- const resolution = runtime.gitBash();
6090
- checks.push(resolution.found ? check("git-bash", "ok", "git-bash-launcher-ready", `Git Bash resolves at ${resolution.path}; the bundled launcher is present.`) : check("git-bash", "error", "git-bash-unavailable", resolution.installHint, resolution.installHint));
6091
- }
6092
- const plan = readManagedPlan(config);
6093
- const overrides = readPreservedRootOverrides(config);
6094
- const fast = readManagedFastMode(config);
6095
- const workflow = readManagedWorkflowPolicy(config);
6096
- checks.push(plan === void 0 ? check("routes", "error", "route-plan-missing", "Managed route plan metadata is missing.", "Reinstall HolyCodex.") : check("routes", "ok", "routes-ready", `${plan} workflow policy is active with permitted stage routes.`));
6097
- checks.push(plan === void 0 || workflow === void 0 ? check("workflow", "error", "workflow-settings-missing", "Managed workflow settings are missing or invalid.", "Reinstall HolyCodex.") : JSON.stringify(workflow) === JSON.stringify({
6098
- plan,
6099
- limits: MODEL_ROUTING_PLANS[plan].workflow.limits,
6100
- projectedUsage: MODEL_ROUTING_PLANS[plan].workflow.projectedUsage,
6101
- softSizeGuidance: MODEL_ROUTING_PLANS[plan].workflow.softSizeGuidance
6102
- }) ? check("workflow", "ok", "workflow-settings-ready", `${plan} workflow target and maximum limits, projected usage, and size guidance match the catalog.`) : check("workflow", "error", "workflow-settings-drift", `${plan} workflow settings do not match the authoritative catalog.`, "Reinstall HolyCodex."));
6103
- checks.push(missing.includes("runtime/workflow.js") ? check("workflow-runtime", "error", "workflow-runtime-missing", "The isolated workflow runtime is missing.", "Reinstall HolyCodex.") : check("workflow-runtime", "ok", "workflow-runtime-ready", "The isolated workflow runtime is present."));
6104
- const manifest = await readFile(join(pluginRoot, ".codex-plugin", "plugin.json"), "utf8").catch(() => "");
6105
- const mcpManifest = await access(join(pluginRoot, ".mcp.json")).then(() => true).catch(() => false);
6106
- checks.push(!mcpManifest && !manifest.includes("mcpServers") && !manifest.includes("MCP Tools") ? check("mcp", "ok", "mcp-free", "The installation does not declare MCP servers or tools.") : check("mcp", "error", "mcp-declared", "The installation declares MCP servers or tools.", "Reinstall HolyCodex from a MCP-free package."));
6107
- checks.push(overrides.model || overrides.reasoningEffort ? check("root-overrides", "ok", "root-overrides-preserved", "Intentional Root model or reasoning overrides are preserved and healthy.") : check("root-overrides", "ok", "root-managed-defaults", "Root uses managed route defaults."));
6108
- if (plan !== void 0 && fast === void 0) checks.push(check("fast", "warning", "fast-metadata-missing", "Fast metadata is missing; doctor will not guess a service tier.", "Reinstall with an explicit Fast mode."));
6109
- if (plan !== void 0) for (const agent of AGENTS) {
6110
- const source = await readFile(join(agentRoot, `${agent}.toml`), "utf8").catch(() => "");
6111
- const expected = MODEL_ROUTING_PLANS[plan].agents[agent];
6112
- const overridden = rootTomlString(source, "model") !== expected.model || rootTomlString(source, "model_reasoning_effort") !== expected.reasoningEffort;
6113
- checks.push(check(`agent-${agent}`, "ok", overridden ? "agent-override-preserved" : "agent-managed-default", overridden ? `${agent} has an intentional healthy route override.` : `${agent} uses managed route defaults.`));
5952
+ /** Normalizes supported flat and marketplace-oriented Codex catalogs. */
5953
+ function parsePluginCatalog(input) {
5954
+ for (const value of parseJsonDocuments(input) ?? []) {
5955
+ const plugins = parseCatalogValue(value);
5956
+ if (plugins !== void 0) return { plugins };
6114
5957
  }
6115
- for (const key of COMPATIBILITY_KEYS) if (config.includes(key.split(".")[1] ?? key)) checks.push(check(`compat-${key}`, "warning", "compatibility-sensitive-key", `${key} is compatibility-sensitive and isolated from supported managed Codex keys.`));
6116
- return {
6117
- healthy: checks.every((item) => item.status !== "error"),
6118
- autonomy: autonomy(config),
6119
- checks
6120
- };
6121
- }
6122
- //#endregion
6123
- //#region packages/cli/src/codex-launcher.ts
6124
- var CODEX_PACKAGE_SPEC = "@openai/codex@latest";
6125
- /** Derives safe process facts for the default installation flow. */
6126
- function defaultCodexLauncherRuntimeFacts(platform = process.platform, env = process.env) {
6127
- const bun = typeof process.versions.bun === "string";
6128
- const allowPackageResolution = env.HOLYCODEX_TEST_SKIP_PACKAGE_RESOLUTION !== "1";
6129
- const npmExecPath = bun ? void 0 : env.npm_execpath;
6130
- return {
6131
- allowPackageResolution,
6132
- platform,
6133
- execPath: process.execPath,
6134
- runtime: bun ? "bun" : "node",
6135
- ...npmExecPath === void 0 ? {} : { npmExecPath },
6136
- availableRunners: ["npm", "pnpm"],
6137
- npm: platform === "win32" ? "npm.cmd" : "npm",
6138
- pnpm: platform === "win32" ? "pnpm.cmd" : "pnpm"
6139
- };
6140
5958
  }
6141
- /** Builds ordered Codex launcher candidates once for an installation. */
6142
- function createCodexLauncherCandidates(input = {}) {
6143
- const facts = input.runtimeFacts ?? {};
6144
- const candidates = [];
6145
- const injected = input.injected === void 0 ? [] : toArray(input.injected);
6146
- for (const candidate of injected) {
6147
- const launcher = normalizeLauncher(candidate, "injected");
6148
- if (launcher !== void 0) candidates.push(launcher);
5959
+ function parseMarketplaceNames(input) {
5960
+ for (const value of parseJsonDocuments(input) ?? []) {
5961
+ if (!isRecord(value) || !Array.isArray(value.marketplaces)) continue;
5962
+ const names = [];
5963
+ for (const marketplace of value.marketplaces) {
5964
+ if (!isRecord(marketplace)) {
5965
+ names.length = 0;
5966
+ break;
5967
+ }
5968
+ const name = stringField(marketplace, ["name"]);
5969
+ if (name === void 0) {
5970
+ names.length = 0;
5971
+ break;
5972
+ }
5973
+ names.push(name);
5974
+ }
5975
+ if (names.length > 0 || value.marketplaces.length === 0) return names;
6149
5976
  }
6150
- const pathLauncher = normalizeLauncher(facts.pathCodex ?? "codex", "path");
6151
- if (pathLauncher !== void 0) candidates.push(pathLauncher);
6152
- if (facts.allowPackageResolution === false) return deduplicate(candidates);
6153
- if ((facts.runtime ?? (typeof process.versions.bun === "string" ? "bun" : "node")) === "bun") {
6154
- const bunLauncher = normalizeLauncher({
6155
- command: facts.execPath ?? process.execPath,
6156
- argsPrefix: ["x", CODEX_PACKAGE_SPEC],
6157
- source: "bunx"
6158
- }, "bunx");
6159
- if (bunLauncher !== void 0) candidates.push(bunLauncher);
5977
+ }
5978
+ function parseCatalogValue(value) {
5979
+ if (Array.isArray(value)) return parseMarketplaceEntries(value);
5980
+ if (!isRecord(value)) return void 0;
5981
+ if ("installed" in value || "available" in value) {
5982
+ if (!Array.isArray(value.installed) || !Array.isArray(value.available)) return void 0;
5983
+ const installed = parsePluginEntries(value.installed, void 0, true);
5984
+ const available = parsePluginEntries(value.available, void 0, false);
5985
+ return installed === void 0 || available === void 0 ? void 0 : [...installed, ...available];
6160
5986
  }
6161
- const nodeRunner = facts.nodeRunner ?? activeNodeRunner(facts);
6162
- if (nodeRunner !== void 0) {
6163
- const launcher = normalizeLauncher(nodeRunner, nodeRunnerSource(nodeRunner));
6164
- if (launcher !== void 0) candidates.push(launcher);
5987
+ if ("marketplaces" in value) return Array.isArray(value.marketplaces) ? parseMarketplaceEntries(value.marketplaces) : void 0;
5988
+ if ("plugins" in value) return parseMarketplaceEntry(value);
5989
+ }
5990
+ function parseMarketplaceEntries(entries) {
5991
+ const plugins = [];
5992
+ for (const entry of entries) {
5993
+ const parsed = parseMarketplaceEntry(entry);
5994
+ if (parsed === void 0) return void 0;
5995
+ plugins.push(...parsed);
6165
5996
  }
6166
- const availableRunners = facts.availableRunners ?? [];
6167
- if (facts.npm !== false && (facts.npm !== void 0 || availableRunners.includes("npm"))) candidates.push(packageLauncher(facts.npm, facts.platform, "npm-exec"));
6168
- if (facts.pnpm !== false && (facts.pnpm !== void 0 || availableRunners.includes("pnpm"))) candidates.push(packageLauncher(facts.pnpm, facts.platform, "pnpm-exec"));
6169
- return deduplicate(candidates);
5997
+ return plugins;
6170
5998
  }
6171
- /** Appends command arguments to a launcher prefix without mutating either array. */
6172
- function codexLauncherArgs(launcher, args) {
6173
- return [...launcher.argsPrefix, ...args];
5999
+ function parseMarketplaceEntry(value) {
6000
+ if (!isRecord(value) || !Array.isArray(value.plugins)) return void 0;
6001
+ const marketplace = stringField(value, [
6002
+ "marketplace",
6003
+ "marketplaceId",
6004
+ "marketplaceName",
6005
+ "id",
6006
+ "name"
6007
+ ]);
6008
+ if (marketplace === void 0) return void 0;
6009
+ return parsePluginEntries(value.plugins, marketplace);
6174
6010
  }
6175
- function activeNodeRunner(facts) {
6176
- if (facts.npmExecPath === void 0 || facts.execPath === void 0) return void 0;
6177
- const source = packageRunnerSource(facts.npmExecPath);
6178
- if (source === void 0) return void 0;
6011
+ function parsePluginEntries(entries, parentMarketplace, defaultInstalled) {
6012
+ const plugins = [];
6013
+ for (const value of entries) {
6014
+ const plugin = parsePluginEntry(value, parentMarketplace, defaultInstalled);
6015
+ if (plugin === void 0) return void 0;
6016
+ plugins.push(plugin);
6017
+ }
6018
+ return plugins;
6019
+ }
6020
+ function parsePluginEntry(value, parentMarketplace, defaultInstalled = false) {
6021
+ if (!isRecord(value)) return void 0;
6022
+ const rawId = stringField(value, [
6023
+ "pluginId",
6024
+ "id",
6025
+ "name"
6026
+ ]);
6027
+ if (rawId === void 0) return void 0;
6028
+ const marketplace = stringField(value, [
6029
+ "marketplace",
6030
+ "marketplaceId",
6031
+ "marketplaceName"
6032
+ ]) ?? parentMarketplace;
6033
+ const id = rawId.includes("@") ? rawId : marketplace === void 0 ? rawId : `${rawId}@${marketplace}`;
6034
+ const state = stringField(value, [
6035
+ "installationState",
6036
+ "installState",
6037
+ "status",
6038
+ "state"
6039
+ ]);
6040
+ const policy = isRecord(value.policy) ? stringField(value.policy, ["installation"]) : void 0;
6179
6041
  return {
6180
- command: facts.execPath,
6181
- argsPrefix: source === "npm-exec" ? [
6182
- facts.npmExecPath,
6183
- "exec",
6184
- "--yes",
6185
- "--package",
6186
- CODEX_PACKAGE_SPEC,
6187
- "--",
6188
- "codex"
6189
- ] : [
6190
- facts.npmExecPath,
6191
- "dlx",
6192
- CODEX_PACKAGE_SPEC
6193
- ],
6194
- source
6042
+ id,
6043
+ installed: booleanField(value.installed) ?? installedFromState(state ?? policy) ?? defaultInstalled,
6044
+ enabled: booleanField(value.enabled) ?? enabledFromState(state) ?? false
6195
6045
  };
6196
6046
  }
6197
- function packageRunnerSource(path) {
6198
- const basename = path.replaceAll("\\", "/").split("/").pop()?.toLowerCase() ?? "";
6047
+ function stringField(value, keys) {
6048
+ for (const key of keys) {
6049
+ const candidate = value[key];
6050
+ if (typeof candidate === "string" && candidate.trim() !== "") return candidate.trim();
6051
+ }
6052
+ }
6053
+ function booleanField(value) {
6054
+ if (typeof value === "boolean") return value;
6055
+ if (typeof value !== "string") return void 0;
6056
+ if (value.toLowerCase() === "true") return true;
6057
+ if (value.toLowerCase() === "false") return false;
6058
+ }
6059
+ function installedFromState(value) {
6060
+ if (value === void 0) return void 0;
6061
+ const state = value.toLowerCase().replaceAll("-", "_");
6199
6062
  if ([
6200
- "npm",
6201
- "npm.cmd",
6202
- "npm-cli.js",
6203
- "npm-cli.cjs"
6204
- ].includes(basename)) return "npm-exec";
6063
+ "installed",
6064
+ "enabled",
6065
+ "disabled",
6066
+ "installed_by_default"
6067
+ ].includes(state)) return true;
6205
6068
  if ([
6206
- "pnpm",
6207
- "pnpm.cmd",
6208
- "pnpm.js",
6209
- "pnpm.cjs"
6210
- ].includes(basename)) return "pnpm-exec";
6069
+ "available",
6070
+ "not_installed",
6071
+ "uninstalled",
6072
+ "not_available"
6073
+ ].includes(state)) return false;
6211
6074
  }
6212
- function nodeRunnerSource(value) {
6213
- if (typeof value === "object" && value !== null && "source" in value) {
6214
- if (value.source === "pnpm-exec") return "pnpm-exec";
6215
- if (value.source === "npm-exec") return "npm-exec";
6075
+ function enabledFromState(value) {
6076
+ if (value === void 0) return void 0;
6077
+ const state = value.toLowerCase();
6078
+ if (state === "enabled") return true;
6079
+ if (state === "disabled") return false;
6080
+ }
6081
+ function parseJsonDocuments(input) {
6082
+ const wholeDocument = tryParseJson(input);
6083
+ if (wholeDocument !== void 0) return [wholeDocument];
6084
+ const lines = input.split(/\r?\n/).map((line) => line.trim()).filter(Boolean);
6085
+ if (lines.length === 0) return void 0;
6086
+ for (let index = 1; index < lines.length; index += 1) {
6087
+ const document = tryParseJson(lines.slice(index).join("\n"));
6088
+ if (document !== void 0) return [document];
6216
6089
  }
6217
- return "npm-exec";
6090
+ const documents = [];
6091
+ let parsedDocument = false;
6092
+ for (const line of lines) {
6093
+ const document = tryParseJson(line);
6094
+ if (document === void 0) {
6095
+ if (parsedDocument) return void 0;
6096
+ continue;
6097
+ }
6098
+ documents.push(document);
6099
+ if (documents.length > MAX_JSON_DOCUMENTS) return void 0;
6100
+ parsedDocument = true;
6101
+ }
6102
+ return documents.length === 0 ? void 0 : documents;
6218
6103
  }
6219
- function packageLauncher(command, platform, source) {
6220
- return {
6221
- command: typeof command === "string" ? command : source === "npm-exec" ? platform === "win32" ? "npm.cmd" : "npm" : platform === "win32" ? "pnpm.cmd" : "pnpm",
6222
- argsPrefix: source === "npm-exec" ? [
6223
- "exec",
6224
- "--yes",
6225
- "--package",
6226
- CODEX_PACKAGE_SPEC,
6227
- "--",
6228
- "codex"
6229
- ] : ["dlx", CODEX_PACKAGE_SPEC],
6230
- source
6231
- };
6104
+ function tryParseJson(input) {
6105
+ try {
6106
+ return JSON.parse(input);
6107
+ } catch {
6108
+ return;
6109
+ }
6232
6110
  }
6233
- function toArray(value) {
6234
- return Array.isArray(value) ? value : [value];
6111
+ function structuredErrorCodeFromOutput(input) {
6112
+ for (const value of parseJsonDocuments(input) ?? []) {
6113
+ const code = structuredErrorCode(value);
6114
+ if (code !== void 0) return code;
6115
+ }
6235
6116
  }
6236
- function normalizeLauncher(value, source) {
6237
- if (typeof value === "string") {
6238
- const command = value.trim();
6239
- return command === "" ? void 0 : {
6240
- command,
6241
- argsPrefix: [],
6242
- source
6243
- };
6117
+ function structuredErrorCode(value) {
6118
+ if (!isRecord(value)) return void 0;
6119
+ if (value.error !== void 0) {
6120
+ const nestedCode = structuredErrorCode(value.error);
6121
+ if (nestedCode !== void 0) return nestedCode;
6244
6122
  }
6245
- if (typeof value !== "object" || value === null || typeof value.command !== "string") return void 0;
6246
- const command = value.command.trim();
6247
- if (command === "" || !Array.isArray(value.argsPrefix)) return void 0;
6248
- if (!value.argsPrefix.every((arg) => typeof arg === "string")) return void 0;
6123
+ for (const key of [
6124
+ "code",
6125
+ "status",
6126
+ "statusCode"
6127
+ ]) {
6128
+ const candidate = value[key];
6129
+ if (typeof candidate === "string" || typeof candidate === "number") return String(candidate).trim().toUpperCase();
6130
+ }
6131
+ }
6132
+ function sanitizeDiagnostic(input) {
6133
+ return input.replaceAll(/(?:[A-Za-z]:)?[\\/][^\s"']+/g, "<path>").replaceAll(/(token|secret|password|authorization)\s*[:=]\s*[^\s,}]+/gi, "$1=<redacted>").slice(0, 2048);
6134
+ }
6135
+ function isRecord(value) {
6136
+ return typeof value === "object" && value !== null;
6137
+ }
6138
+ function isUnavailableProcessError(result) {
6139
+ if (result.errorCode !== void 0 && SPAWN_UNAVAILABLE_CODES.has(result.errorCode.toUpperCase())) return true;
6140
+ const error = result.error?.toUpperCase() ?? "";
6141
+ return [...SPAWN_UNAVAILABLE_CODES].some((code) => new RegExp(`(?:^|\\s)${code}(?:$|\\s)`).test(error));
6142
+ }
6143
+ function isUnavailableThrownError(value) {
6144
+ const code = thrownErrorCode(value);
6145
+ return code !== void 0 && SPAWN_UNAVAILABLE_CODES.has(code.toUpperCase());
6146
+ }
6147
+ function isBootstrapThrownError(value) {
6148
+ const code = thrownErrorCode(value)?.toUpperCase();
6149
+ if (code !== void 0 && [
6150
+ "ETIMEDOUT",
6151
+ "ECONNRESET",
6152
+ "ECONNREFUSED",
6153
+ "EAI_AGAIN",
6154
+ "ENETUNREACH"
6155
+ ].includes(code)) return true;
6156
+ if (!(value instanceof Error)) return false;
6157
+ return /bootstrap|network|download|fetch|timeout|timed out/i.test(value.message);
6158
+ }
6159
+ function thrownErrorCode(value) {
6160
+ if (typeof value !== "object" || value === null || !("code" in value)) return void 0;
6161
+ const code = value.code;
6162
+ return typeof code === "string" ? code : void 0;
6163
+ }
6164
+ function skipped(reason, attemptedLaunchers) {
6249
6165
  return {
6250
- command,
6251
- argsPrefix: [...value.argsPrefix],
6252
- source
6166
+ status: "skipped",
6167
+ reason,
6168
+ attemptedLaunchers: [...attemptedLaunchers]
6253
6169
  };
6254
6170
  }
6255
- function deduplicate(candidates) {
6256
- const seen = /* @__PURE__ */ new Set();
6257
- const result = [];
6258
- for (const candidate of candidates) {
6259
- const key = JSON.stringify([candidate.command, candidate.argsPrefix]);
6260
- if (seen.has(key)) continue;
6261
- seen.add(key);
6262
- result.push(candidate);
6263
- }
6264
- return result;
6265
- }
6266
6171
  //#endregion
6267
- //#region packages/cli/src/codex-security.ts
6268
- var CODEX_SECURITY_PLUGIN = {
6269
- id: "codex-security@openai-curated",
6270
- marketplace: "openai-curated"
6271
- };
6272
- var COMPUTER_USE_PLUGIN = {
6273
- id: "computer-use@openai-bundled",
6274
- marketplace: "openai-bundled"
6275
- };
6276
- var BUILD_WEB_APPS_PLUGIN = {
6277
- id: "build-web-apps@openai-curated",
6278
- marketplace: "openai-curated"
6279
- };
6280
- var CODEX_PLUGIN_OPERATIONAL_TIMEOUT_MS = 15e3;
6281
- var CODEX_PACKAGE_BOOTSTRAP_TIMEOUT_MS = 12e4;
6282
- var MAX_CODEX_CATALOG_DIAGNOSTIC_CHARS = 256 * 1024;
6283
- var MAX_JSON_DOCUMENTS = 16;
6284
- var SPAWN_UNAVAILABLE_CODES = /* @__PURE__ */ new Set([
6285
- "EACCES",
6286
- "ENOENT",
6287
- "EPERM"
6288
- ]);
6289
- var FATAL_AUTH_CODES = /* @__PURE__ */ new Set([
6290
- "401",
6291
- "UNAUTHENTICATED",
6292
- "AUTHENTICATION_REQUIRED"
6293
- ]);
6294
- var FATAL_ACCOUNT_CODES = /* @__PURE__ */ new Set(["ACCOUNT_REQUIRED", "ACCOUNT_NOT_FOUND"]);
6295
- var FATAL_MARKETPLACE_CODES = /* @__PURE__ */ new Set([
6296
- "502",
6297
- "503",
6298
- "504",
6299
- "MARKETPLACE_UNAVAILABLE",
6300
- "MARKETPLACE_LOAD_FAILED",
6301
- "CATALOG_UNAVAILABLE"
6302
- ]);
6303
- var FATAL_PLUGIN_CODES = /* @__PURE__ */ new Set([
6304
- "404",
6305
- "PLUGIN_NOT_FOUND",
6306
- "PLUGIN_UNAVAILABLE"
6307
- ]);
6308
- var FATAL_POLICY_CODES = /* @__PURE__ */ new Set([
6309
- "403",
6310
- "ACCOUNT_RESTRICTED",
6311
- "ACCOUNT_UNAVAILABLE",
6312
- "ACCOUNT_SUSPENDED",
6313
- "ACCOUNT_DISABLED",
6314
- "INSTALLATION_REJECTED",
6315
- "PERMISSION_DENIED",
6316
- "POLICY_REJECTED"
6317
- ]);
6318
- /** Installs or enables the official Codex Security plugin without failing HolyCodex installation. */
6319
- async function installCodexSecurity(runProcess = runManagedProcess, platform = process.platform, env = process.env, options = {}) {
6320
- return installOfficialPlugin(CODEX_SECURITY_PLUGIN, runProcess, platform, env, options);
6172
+ //#region packages/cli/src/toml.ts
6173
+ var TOML_TABLE = /^[ \t]*(?:\[[^\]\r\n]+\]|\[\[[^\]\r\n]+\]\])[ \t]*(?:#.*)?$/m;
6174
+ /** Reads a root TOML string value. */
6175
+ function rootTomlString(input, key) {
6176
+ const table = TOML_TABLE.exec(input);
6177
+ const root = table === null ? input : input.slice(0, table.index);
6178
+ const match = new RegExp(String.raw`^[ \t]*${escapeRegExp$1(key)}[ \t]*=[ \t]*(?:"((?:\\.|[^"\\\r\n])*)"|'([^'\r\n]*)')[ \t]*(?:#.*)?$`, "m").exec(root);
6179
+ if (match === null) return void 0;
6180
+ if (match[2] !== void 0) return match[2];
6181
+ try {
6182
+ return string().safeParse(JSON.parse(`"${match[1] ?? ""}"`)).data;
6183
+ } catch {
6184
+ return;
6185
+ }
6321
6186
  }
6322
- /** Installs or enables the official Computer Use plugin without failing HolyCodex installation. */
6323
- async function installComputerUse(runProcess = runManagedProcess, platform = process.platform, env = process.env, options = {}) {
6324
- return installOfficialPlugin(COMPUTER_USE_PLUGIN, runProcess, platform, env, options);
6187
+ /** Reads a root TOML string array. */
6188
+ function rootTomlStringArray(input, key) {
6189
+ return parseRootTomlStringArray(input, key)?.items;
6325
6190
  }
6326
- /** Installs or enables the official Build Web Apps plugin without failing HolyCodex installation. */
6327
- async function installBuildWebApps(runProcess = runManagedProcess, platform = process.platform, env = process.env, options = {}) {
6328
- return installOfficialPlugin(BUILD_WEB_APPS_PLUGIN, runProcess, platform, env, options);
6191
+ /** Reads the source text of a root TOML string array. */
6192
+ function rootTomlStringArraySource(input, key) {
6193
+ return parseRootTomlStringArray(input, key)?.source;
6329
6194
  }
6330
- /** Installs or enables one official Codex plugin through a verified catalog entry. */
6331
- async function installOfficialPlugin(plugin, runProcess = runManagedProcess, platform = process.platform, env = process.env, options = {}) {
6332
- const runtimeFacts = options.runtimeFacts ?? (runProcess === runManagedProcess ? defaultCodexLauncherRuntimeFacts(platform) : void 0);
6333
- const candidates = createCodexLauncherCandidates({
6334
- ...options.injected === void 0 ? {} : { injected: options.injected },
6335
- ...runtimeFacts === void 0 ? {} : { runtimeFacts }
6336
- });
6337
- const attemptedLaunchers = [];
6338
- const fallbackReasons = [];
6339
- for (const launcher of candidates) {
6340
- attemptedLaunchers.push(launcher.source);
6341
- let installedOutcome = inspectListResult(await runCodexPlugin(runProcess, launcher, [
6342
- "plugin",
6343
- "list",
6344
- "--json"
6345
- ], platform, env, "list"), launcher);
6346
- if (launcher.source === "path" && installedOutcome.kind === "fallback" && installedOutcome.reason === "download-failed") installedOutcome = inspectListResult(await runCodexPlugin(runProcess, launcher, [
6347
- "plugin",
6348
- "list",
6349
- "--json"
6350
- ], platform, env, "list"), launcher);
6351
- if (installedOutcome.kind === "fallback") {
6352
- fallbackReasons.push(installedOutcome.reason);
6195
+ function parseRootTomlStringArray(input, key) {
6196
+ const table = TOML_TABLE.exec(input);
6197
+ const root = table === null ? input : input.slice(0, table.index);
6198
+ const assignment = new RegExp(String.raw`^[ \t]*${escapeRegExp$1(key)}[ \t]*=`, "m").exec(root);
6199
+ if (assignment === null) return void 0;
6200
+ const start = root.indexOf("[", assignment.index + assignment[0].length);
6201
+ if (start < 0) return void 0;
6202
+ const items = [];
6203
+ let quote;
6204
+ let raw = "";
6205
+ let escaped = false;
6206
+ let comment = false;
6207
+ for (let index = start + 1; index < root.length; index += 1) {
6208
+ const character = root[index];
6209
+ if (comment) {
6210
+ if (character === "\n") comment = false;
6353
6211
  continue;
6354
6212
  }
6355
- if (installedOutcome.kind === "fatal") return skipped(installedOutcome.reason, attemptedLaunchers);
6356
- const installedPlugin = findPlugin(installedOutcome.catalog, plugin.id);
6357
- if (installedPlugin?.installed === true && installedPlugin.enabled === true) return {
6358
- status: "already-installed",
6359
- launcherSource: launcher.source
6360
- };
6361
- const wasDisabled = installedPlugin?.installed === true;
6362
- if (!wasDisabled) {
6363
- const catalogOutcome = inspectListResult(await runCodexPlugin(runProcess, launcher, [
6364
- "plugin",
6365
- "list",
6366
- "--available",
6367
- "--json"
6368
- ], platform, env, "list"), launcher);
6369
- if (catalogOutcome.kind === "fallback") {
6370
- fallbackReasons.push(catalogOutcome.reason);
6371
- continue;
6372
- }
6373
- if (catalogOutcome.kind === "fatal") return skipped(catalogOutcome.reason, attemptedLaunchers);
6374
- let pluginAvailable = findPlugin(catalogOutcome.catalog, plugin.id) !== void 0;
6375
- if (!pluginAvailable) {
6376
- const marketplaceOutcome = inspectMarketplaceResult(await runCodexPlugin(runProcess, launcher, [
6377
- "plugin",
6378
- "marketplace",
6379
- "list",
6380
- "--json"
6381
- ], platform, env, "list"), launcher);
6382
- if (marketplaceOutcome.kind === "fallback") {
6383
- fallbackReasons.push(marketplaceOutcome.reason);
6384
- continue;
6385
- }
6386
- if (marketplaceOutcome.kind === "fatal") return skipped(marketplaceOutcome.reason, attemptedLaunchers);
6387
- if (plugin.id === COMPUTER_USE_PLUGIN.id && !marketplaceOutcome.marketplaces.includes(plugin.marketplace)) {
6388
- const refreshedCatalog = inspectListResult(await runCodexPlugin(runProcess, launcher, [
6389
- "plugin",
6390
- "list",
6391
- "--available",
6392
- "--json"
6393
- ], platform, env, "list"), launcher);
6394
- if (refreshedCatalog.kind === "selected") pluginAvailable = findPlugin(refreshedCatalog.catalog, plugin.id) !== void 0;
6395
- else fallbackReasons.push(refreshedCatalog.reason);
6396
- }
6397
- if (!pluginAvailable) {
6398
- fallbackReasons.push(marketplaceOutcome.marketplaces.includes(plugin.marketplace) ? "plugin-not-offered" : "marketplace-unavailable");
6399
- continue;
6213
+ if (quote === "\"") {
6214
+ if (escaped) {
6215
+ raw += character;
6216
+ escaped = false;
6217
+ } else if (character === "\\") {
6218
+ raw += character;
6219
+ escaped = true;
6220
+ } else if (character === "\"") {
6221
+ try {
6222
+ const parsed = string().safeParse(JSON.parse(`"${raw}"`));
6223
+ if (!parsed.success) return void 0;
6224
+ items.push(parsed.data);
6225
+ } catch {
6226
+ return;
6400
6227
  }
6401
- }
6402
- }
6403
- const addOutcome = inspectAddResult(await runCodexPlugin(runProcess, launcher, [
6404
- "plugin",
6405
- "add",
6406
- plugin.id,
6407
- "--json"
6408
- ], platform, env, "add"), launcher);
6409
- if (addOutcome.kind === "fallback") {
6410
- fallbackReasons.push(addOutcome.reason);
6228
+ quote = void 0;
6229
+ raw = "";
6230
+ } else raw += character;
6411
6231
  continue;
6412
6232
  }
6413
- if (addOutcome.kind === "fatal") return skipped(addOutcome.reason, attemptedLaunchers);
6414
- const verification = inspectListResult(await runCodexPlugin(runProcess, launcher, [
6415
- "plugin",
6416
- "list",
6417
- "--json"
6418
- ], platform, env, "list"), launcher);
6419
- if (verification.kind === "fallback") {
6420
- fallbackReasons.push(verification.reason);
6233
+ if (quote === "'") {
6234
+ if (character === "'") {
6235
+ items.push(raw);
6236
+ quote = void 0;
6237
+ raw = "";
6238
+ } else raw += character;
6421
6239
  continue;
6422
6240
  }
6423
- if (verification.kind === "fatal") return skipped(verification.reason, attemptedLaunchers);
6424
- const verifiedPlugin = findPlugin(verification.catalog, plugin.id);
6425
- if (verifiedPlugin?.installed !== true || verifiedPlugin.enabled !== true) {
6426
- fallbackReasons.push("verification-failed");
6427
- continue;
6241
+ if (character === "#") comment = true;
6242
+ else if (character === "\"" || character === "'") quote = character;
6243
+ else if (character === "]") {
6244
+ const suffix = /^[ \t]*(?:#.*)?(?=\r?\n|$)/.exec(root.slice(index + 1))?.[0] ?? "";
6245
+ return {
6246
+ source: root.slice(assignment.index, index + 1 + suffix.length),
6247
+ items
6248
+ };
6428
6249
  }
6429
- return {
6430
- status: wasDisabled ? "enabled" : "installed",
6431
- launcherSource: launcher.source
6432
- };
6433
6250
  }
6434
- return skipped(finalFallbackReason(fallbackReasons), attemptedLaunchers);
6435
6251
  }
6436
- async function runCodexPlugin(runProcess, launcher, args, platform, env, operation) {
6437
- try {
6438
- return await runProcess({
6439
- command: launcher.command,
6440
- args: codexLauncherArgs(launcher, args),
6441
- platform,
6442
- timeoutMs: timeoutFor(launcher, operation),
6443
- maxOutputChars: MAX_CODEX_CATALOG_DIAGNOSTIC_CHARS,
6444
- env
6445
- });
6446
- } catch (error) {
6447
- const code = thrownErrorCode(error);
6448
- if (!isUnavailableThrownError(error) && !(isPackageLauncher(launcher) && isBootstrapThrownError(error))) throw error;
6449
- return {
6450
- exitCode: null,
6451
- stdout: "",
6452
- stderr: "",
6453
- timedOut: false,
6454
- matched: false,
6455
- outputTruncated: false,
6456
- error: "Codex launcher could not be started.",
6457
- ...code === void 0 ? {} : { errorCode: code }
6458
- };
6459
- }
6252
+ function escapeRegExp$1(value) {
6253
+ return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
6254
+ }
6255
+ //#endregion
6256
+ //#region packages/cli/src/permission-selection.ts
6257
+ var PERMISSION_KEYS = [
6258
+ "default_permissions",
6259
+ "approval_policy",
6260
+ "approvals_reviewer",
6261
+ "sandbox_mode"
6262
+ ];
6263
+ var AUTONOMY_PREFIX = "# holycodex autonomy: ";
6264
+ var ORIGINAL_PERMISSION_PREFIX = "# holycodex original permissions: ";
6265
+ /** Normalizes legacy string callers while preserving an omitted request. */
6266
+ function normalizeRequestedAutonomy(value) {
6267
+ if (value === void 0) return { requested: false };
6268
+ if (typeof value === "string") return {
6269
+ requested: true,
6270
+ mode: value
6271
+ };
6272
+ return value;
6273
+ }
6274
+ /** Reads the raw root permission selection without filling missing values. */
6275
+ function readRawPermissionSelection(input) {
6276
+ const defaultPermissions = rootTomlString(input, "default_permissions");
6277
+ const approvalPolicy = rootTomlString(input, "approval_policy");
6278
+ const approvalsReviewer = rootTomlString(input, "approvals_reviewer");
6279
+ const sandboxMode = rootTomlString(input, "sandbox_mode");
6280
+ return {
6281
+ ...defaultPermissions === void 0 ? {} : { defaultPermissions },
6282
+ ...approvalPolicy === void 0 ? {} : { approvalPolicy },
6283
+ ...approvalsReviewer === void 0 ? {} : { approvalsReviewer },
6284
+ ...sandboxMode === void 0 ? {} : { sandboxMode }
6285
+ };
6286
+ }
6287
+ /** Returns root assignment lines for permission keys in source order. */
6288
+ function readPermissionLines(input) {
6289
+ const firstTable = input.search(/^\s*\[/m);
6290
+ const root = firstTable < 0 ? input : input.slice(0, firstTable);
6291
+ const keys = new Set(PERMISSION_KEYS);
6292
+ return root.split(/\r?\n/).filter((line) => {
6293
+ const key = /^\s*([A-Za-z0-9_-]+)\s*=/.exec(line)?.[1];
6294
+ return key !== void 0 && keys.has(key);
6295
+ });
6296
+ }
6297
+ /** Removes all root permission assignment lines while preserving other text. */
6298
+ function removePermissionLines(input) {
6299
+ const firstTable = input.search(/^\s*\[/m);
6300
+ const root = firstTable < 0 ? input : input.slice(0, firstTable);
6301
+ const tables = firstTable < 0 ? "" : input.slice(firstTable);
6302
+ const keys = PERMISSION_KEYS.map((key) => key.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"));
6303
+ return `${root.split(/\r?\n/).filter((line) => !new RegExp(`^\\s*(?:${keys.join("|")})\\s*=`).test(line)).join("\n").trim()}${tables ? `\n${tables.trimStart()}` : ""}`.trim();
6304
+ }
6305
+ /** Returns the exact tuple represented by an explicit autonomy mode. */
6306
+ function permissionSelectionForMode(mode) {
6307
+ if (mode === "default") return {
6308
+ approvalPolicy: "on-request",
6309
+ approvalsReviewer: "auto_review",
6310
+ sandboxMode: "workspace-write"
6311
+ };
6312
+ if (mode === "autonomous") return {
6313
+ approvalPolicy: "never",
6314
+ sandboxMode: "workspace-write"
6315
+ };
6316
+ return {
6317
+ approvalPolicy: "never",
6318
+ sandboxMode: "danger-full-access"
6319
+ };
6320
+ }
6321
+ /** Identifies generated tuples from current and historical installers. */
6322
+ function permissionSelectionMatchesMode(selection, mode) {
6323
+ if (permissionSelectionsEqual(selection, permissionSelectionForMode(mode))) return true;
6324
+ return mode === "default" && permissionSelectionsEqual(selection, {
6325
+ approvalPolicy: "on-request",
6326
+ sandboxMode: "workspace-write"
6327
+ });
6328
+ }
6329
+ /** Compares all raw permission fields, including intentional omissions. */
6330
+ function permissionSelectionsEqual(left, right) {
6331
+ return PERMISSION_KEYS.every((key) => {
6332
+ const field = permissionField(key);
6333
+ return left[field] === right[field];
6334
+ });
6335
+ }
6336
+ /** Identifies a historical generated tuple, if one is exact. */
6337
+ function inferAutonomyMode(selection) {
6338
+ for (const mode of [
6339
+ "default",
6340
+ "autonomous",
6341
+ "dangerous"
6342
+ ]) if (permissionSelectionMatchesMode(selection, mode)) return mode;
6343
+ return "custom";
6344
+ }
6345
+ /** Reads deterministic autonomy metadata from a managed block. */
6346
+ function readAutonomyMetadata(input) {
6347
+ const value = new RegExp(`^${escapeRegExp(AUTONOMY_PREFIX)}(.+)$`, "m").exec(input)?.[1]?.trim();
6348
+ if (value === "default" || value === "autonomous" || value === "dangerous" || value === "custom") return value;
6349
+ }
6350
+ /** Encodes durable original root permission assignment provenance. */
6351
+ function originalPermissionMetadata(lines) {
6352
+ return `${ORIGINAL_PERMISSION_PREFIX}${lines.length === 0 ? "-" : Buffer.from(lines.join("\n"), "utf8").toString("base64")}\n`;
6353
+ }
6354
+ /** Reads durable original root permission assignment provenance. */
6355
+ function readOriginalPermissionMetadata(input) {
6356
+ const encoded = new RegExp(`^${escapeRegExp(ORIGINAL_PERMISSION_PREFIX)}([A-Za-z0-9+/=_-]+)$`, "m").exec(input)?.[1];
6357
+ if (encoded === void 0) return void 0;
6358
+ if (encoded === "-") return [];
6359
+ return Buffer.from(encoded, "base64").toString("utf8").split(/\r?\n/).filter(Boolean);
6360
+ }
6361
+ /** Returns a generated tuple for an explicit request or preserves a live omitted selection. */
6362
+ function selectPermissionSelection(live, request) {
6363
+ if (request.requested) return permissionSelectionForMode(request.mode);
6364
+ if (Object.keys(live).length > 0) return live;
6365
+ return permissionSelectionForMode("default");
6366
+ }
6367
+ var AUTONOMY_METADATA_PREFIX = AUTONOMY_PREFIX;
6368
+ function permissionField(key) {
6369
+ if (key === "default_permissions") return "defaultPermissions";
6370
+ if (key === "approval_policy") return "approvalPolicy";
6371
+ if (key === "approvals_reviewer") return "approvalsReviewer";
6372
+ return "sandboxMode";
6373
+ }
6374
+ function escapeRegExp(value) {
6375
+ return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
6376
+ }
6377
+ //#endregion
6378
+ //#region packages/cli/src/config.ts
6379
+ var START = "# >>> holycodex managed >>>";
6380
+ var END = "# <<< holycodex managed <<<";
6381
+ var ORIGINAL_ROOT = "# holycodex original root: ";
6382
+ var ORIGINAL_TABLE_KEY = "# holycodex original table key: ";
6383
+ var PLAN_PREFIX = "# holycodex plan: ";
6384
+ var FAST_MODE_PREFIX = "# holycodex fast: ";
6385
+ var WORKFLOW_POLICY_PREFIX = "# holycodex workflow-policy: ";
6386
+ var COMPUTER_USE_PREFIX = "# holycodex computer-use: ";
6387
+ var OLD_NAMESPACES = [
6388
+ "marketplaces.sisyphuslabs",
6389
+ "plugins.\"omo@sisyphuslabs\"",
6390
+ "marketplaces.lazycodex",
6391
+ "plugins.\"omo@lazycodex\"",
6392
+ "marketplaces.code-yeongyu-codex-plugins",
6393
+ "plugins.\"omo@code-yeongyu-codex-plugins\"",
6394
+ "agents.plan",
6395
+ "agents.metis",
6396
+ "agents.momus",
6397
+ "agents.oracle",
6398
+ "agents.sisyphus",
6399
+ "agents.prometheus",
6400
+ "agents.atlas",
6401
+ "agents.hephaestus",
6402
+ "hooks.state.\"omo@sisyphuslabs",
6403
+ "hooks.state.\"omo@lazycodex",
6404
+ "hooks.state.\"omo@code-yeongyu-codex-plugins"
6405
+ ];
6406
+ function readOriginalRootMetadata(input) {
6407
+ const encoded = input.match(/^# holycodex original root: ([A-Za-z0-9+/=]+)$/m)?.[1];
6408
+ return encoded === void 0 ? void 0 : Buffer.from(encoded, "base64").toString("utf8");
6409
+ }
6410
+ function readLegacyGeneratedRoot(input) {
6411
+ const body = input.match(/^# >>> holycodex managed >>>\r?\n([\s\S]*?)^# <<< holycodex managed <<</m)?.[1];
6412
+ if (body === void 0 || readPermissionLines(body).length === 0) return void 0;
6413
+ return inferAutonomyMode(readRawPermissionSelection(body)) === "custom" ? void 0 : body;
6414
+ }
6415
+ /** Removes managed configuration and restores durable original values. */
6416
+ function removeManaged(input, preserveGeneratedPermissions = false) {
6417
+ const escapedStart = START.replaceAll(">", "\\>");
6418
+ const escapedEnd = END.replaceAll("<", "\\<");
6419
+ return input.replace(new RegExp(`${escapedStart}([\\s\\S]*?)${escapedEnd}(?:\\r?\\n){0,2}`, "g"), (_match, body) => {
6420
+ const original = readOriginalRootMetadata(body);
6421
+ const originalPermissions = readOriginalPermissionMetadata(body);
6422
+ const currentPermissions = readPermissionLines(body);
6423
+ const currentSelection = readRawPermissionSelection(body);
6424
+ const metadata = readAutonomyMetadata(body);
6425
+ const expected = metadata === void 0 || metadata === "custom" ? originalPermissions === void 0 ? void 0 : readRawPermissionSelection(originalPermissions.join("\n")) : permissionSelectionForMode(metadata);
6426
+ const generated = metadata !== void 0 && metadata !== "custom" ? permissionSelectionMatchesMode(currentSelection, metadata) : expected !== void 0 ? permissionSelectionsEqual(currentSelection, expected) : metadata === void 0 && [
6427
+ "default",
6428
+ "autonomous",
6429
+ "dangerous"
6430
+ ].some((mode) => permissionSelectionMatchesMode(currentSelection, mode));
6431
+ const preserveCurrent = preserveGeneratedPermissions || !generated;
6432
+ if (original !== void 0) return `${preserveCurrent ? `${removePermissionLines(original)}${currentPermissions.length === 0 ? "" : `\n${currentPermissions.join("\n")}`}`.trim() : `${removePermissionLines(original)}${(originalPermissions ?? readPermissionLines(original)).length === 0 ? "" : `\n${(originalPermissions ?? readPermissionLines(original)).join("\n")}`}`.trim()}\n`;
6433
+ if (!preserveCurrent && originalPermissions !== void 0) return `${originalPermissions.join("\n")}\n`;
6434
+ if (preserveCurrent && currentPermissions.length > 0) return `${currentPermissions.join("\n")}\n`;
6435
+ const tableKeys = [...body.matchAll(/^# holycodex original table key: ([A-Za-z0-9+/=]+)$/gm)].flatMap((match) => match[1] === void 0 ? [] : [match[1]]);
6436
+ return tableKeys.length === 0 ? "" : `${tableKeys.map((key) => Buffer.from(key, "base64").toString("utf8")).join("\n")}\n`;
6437
+ }).trim();
6438
+ }
6439
+ /** Removes legacy omo. */
6440
+ function removeLegacyOmo(input) {
6441
+ return input.split(/(?=^\s*\[)/m).filter((section) => {
6442
+ const header = /^\s*\[([^\]]+)]/.exec(section)?.[1];
6443
+ if (header === void 0) return true;
6444
+ if (OLD_NAMESPACES.some((name) => header === name || header.startsWith(`${name}.`) || name.includes("\"omo@") && header.startsWith(name))) return false;
6445
+ return ![
6446
+ "agents.explorer",
6447
+ "agents.librarian",
6448
+ "agents.worker"
6449
+ ].some((name) => header === name || header.startsWith(`${name}.`)) || !/(?:sisyphuslabs|omo@|oh-my|code-yeongyu)/i.test(section);
6450
+ }).join("").trimEnd();
6460
6451
  }
6461
- function inspectListResult(result, launcher) {
6462
- if (result.timedOut) return {
6463
- kind: "fallback",
6464
- reason: "timeout"
6465
- };
6466
- if (result.outputTruncated) return {
6467
- kind: "fallback",
6468
- reason: "invalid-response"
6469
- };
6470
- const failure = classifyFailure(result, launcher);
6471
- if (failure !== void 0) return failure;
6472
- const catalog = parsePluginCatalog(result.stdout);
6473
- if (catalog === void 0) return {
6474
- kind: "fallback",
6475
- reason: "invalid-response"
6476
- };
6477
- return {
6478
- kind: "selected",
6479
- catalog
6480
- };
6452
+ function injectTableKeys(input, table, entries) {
6453
+ const match = new RegExp(`^\\s*\\[${table.replaceAll(".", "\\.")}]\\s*(?:#.*)?$`, "m").exec(input);
6454
+ const tail = match === null ? "" : input.slice(match.index + match[0].length);
6455
+ const tableEnd = nextTableBoundary(tail);
6456
+ const tableBody = tableEnd < 0 ? tail : tail.slice(0, tableEnd);
6457
+ const managed = `${START}\n${entries.map(([key]) => new RegExp(`^[ \\t]*${key}[ \\t]*=.*$`, "m").exec(tableBody)?.[0]).filter((value) => value !== void 0).map((value) => `${ORIGINAL_TABLE_KEY}${Buffer.from(value).toString("base64")}\n`).join("")}${entries.map(([key, value]) => `${key} = ${value}`).join("\n")}\n${END}`;
6458
+ if (match === null) return `${input.trimEnd()}\n\n${START}\n[${table}]\n${entries.map(([key, value]) => `${key} = ${value}`).join("\n")}\n${END}`.trim();
6459
+ const bodyStart = match.index + match[0].length;
6460
+ const next = nextTableBoundary(input.slice(bodyStart));
6461
+ const bodyEnd = next < 0 ? input.length : bodyStart + next;
6462
+ const cleanedBody = entries.reduce((body, [key]) => body.replace(new RegExp(`^\\s*${key}\\s*=.*\\r?\\n?`, "gm"), ""), input.slice(bodyStart, bodyEnd)).trim();
6463
+ const suffix = input.slice(bodyEnd).trimStart();
6464
+ return `${input.slice(0, bodyStart)}\n${cleanedBody ? `${cleanedBody}\n` : ""}${managed}${suffix ? `\n${suffix}` : ""}`.trim();
6481
6465
  }
6482
- function inspectAddResult(result, launcher) {
6483
- if (result.timedOut) return {
6484
- kind: "fallback",
6485
- reason: "timeout"
6486
- };
6487
- const failure = classifyFailure(result, launcher);
6488
- if (failure !== void 0) return failure;
6489
- return { kind: "added" };
6466
+ function nextTableBoundary(input) {
6467
+ const header = /^\s*\[/m.exec(input)?.index ?? -1;
6468
+ const managedHeader = /^# >>> holycodex managed >>>\r?\n\s*\[/m.exec(input)?.index ?? -1;
6469
+ if (header < 0) return managedHeader;
6470
+ if (managedHeader < 0) return header;
6471
+ return Math.min(header, managedHeader);
6490
6472
  }
6491
- function inspectMarketplaceResult(result, launcher) {
6492
- if (result.timedOut) return {
6493
- kind: "fallback",
6494
- reason: "timeout"
6495
- };
6496
- if (result.outputTruncated) return {
6497
- kind: "fallback",
6498
- reason: "invalid-response"
6499
- };
6500
- const failure = classifyFailure(result, launcher);
6501
- if (failure !== void 0) return failure;
6502
- const marketplaces = parseMarketplaceNames(result.stdout);
6503
- return marketplaces === void 0 ? {
6504
- kind: "fallback",
6505
- reason: "invalid-response"
6506
- } : {
6507
- kind: "selected",
6508
- marketplaces
6509
- };
6473
+ function tableSource(input, table) {
6474
+ const match = new RegExp(`^\\s*\\[${table.replaceAll(".", "\\.")}]\\s*(?:#.*)?$`, "m").exec(input);
6475
+ if (match === null) return void 0;
6476
+ const tail = input.slice(match.index + match[0].length);
6477
+ const end = nextTableBoundary(tail);
6478
+ return end < 0 ? tail : tail.slice(0, end);
6510
6479
  }
6511
- function findPlugin(catalog, pluginId) {
6512
- return catalog.plugins.find(({ id }) => id === pluginId);
6480
+ function rootValue(input, key) {
6481
+ if (key === "status_line") return rootTomlStringArraySource(input, key);
6482
+ return new RegExp(`^\\s*${key}\\s*=.*$`, "m").exec(input)?.[0];
6513
6483
  }
6514
- function classifyFailure(result, launcher) {
6515
- if (result.error !== void 0) {
6516
- if (isUnavailableProcessError(result)) return {
6517
- kind: "fallback",
6518
- reason: "codex-unavailable"
6519
- };
6520
- return {
6521
- kind: "fallback",
6522
- reason: isPackageLauncher(launcher) ? "download-failed" : "invalid-response"
6523
- };
6524
- }
6525
- if (result.exitCode === 0) return void 0;
6526
- const failureReason = classifyFailureReason(structuredErrorCodeFromOutput(result.stderr) ?? structuredErrorCodeFromOutput(result.stdout), sanitizeDiagnostic(result.stderr));
6527
- if (failureReason === "unauthenticated" || failureReason === "installation-rejected") return {
6528
- kind: "fatal",
6529
- reason: failureReason
6530
- };
6531
- return {
6532
- kind: "fallback",
6533
- reason: failureReason
6534
- };
6484
+ function removeRootValue(input, value) {
6485
+ return value === void 0 ? input : input.replace(value, "");
6535
6486
  }
6536
- function classifyFailureReason(code, diagnostic) {
6537
- if (code !== void 0) {
6538
- if (FATAL_AUTH_CODES.has(code) || FATAL_ACCOUNT_CODES.has(code)) return "unauthenticated";
6539
- if (FATAL_MARKETPLACE_CODES.has(code)) return "marketplace-unavailable";
6540
- if (FATAL_PLUGIN_CODES.has(code)) return "plugin-unavailable";
6541
- if (FATAL_POLICY_CODES.has(code)) return "installation-rejected";
6542
- if (SPAWN_UNAVAILABLE_CODES.has(code)) return "codex-unavailable";
6543
- if ([
6544
- "ETIMEDOUT",
6545
- "ECONNRESET",
6546
- "ECONNREFUSED",
6547
- "EAI_AGAIN",
6548
- "ENETUNREACH"
6549
- ].includes(code)) return "download-failed";
6487
+ function removeRootKey(input, key) {
6488
+ let updated = input;
6489
+ for (;;) {
6490
+ const value = rootValue(updated, key);
6491
+ if (value === void 0) return updated;
6492
+ updated = removeRootValue(updated, value);
6550
6493
  }
6551
- const lower = diagnostic.toLowerCase();
6552
- if (/unknown (?:command|subcommand)|unrecognized (?:command|subcommand)|invalid subcommand/.test(lower)) return "unsupported";
6553
- if (/not supported on (?:this )?platform|unsupported (?:platform|architecture)|no matching (?:binary|package)|platform package|not compatible/.test(lower)) return "unsupported";
6554
- if (/unauthenticated|authentication required|not logged in|account (?:required|not found)/.test(lower)) return "unauthenticated";
6555
- if (/account (?:restricted|unavailable|suspended|disabled)/.test(lower)) return "installation-rejected";
6556
- if (/marketplace|catalog/.test(lower)) return "marketplace-unavailable";
6557
- if (/eai_again|enetwork|network|timed out|timeout|download|fetch|resolve package/.test(lower)) return "download-failed";
6558
- if (/plugin (?:not found|unavailable|missing)/.test(lower)) return "plugin-unavailable";
6559
- if (/permission denied|policy|rejected|forbidden/.test(lower)) return "installation-rejected";
6560
- return "invalid-response";
6561
6494
  }
6562
- function finalFallbackReason(reasons) {
6563
- if (reasons.length > 0 && reasons.every((reason) => reason === "plugin-not-offered")) return "all-launchers-lacked-plugin";
6564
- if (reasons.includes("verification-failed")) return "verification-failed";
6565
- if (reasons.includes("plugin-not-offered")) return "plugin-not-offered";
6566
- if (reasons.includes("timeout")) return "timeout";
6567
- if (reasons.includes("unsupported")) return "unsupported";
6568
- if (reasons.includes("marketplace-unavailable")) return "marketplace-unavailable";
6569
- if (reasons.includes("download-failed")) return "download-failed";
6570
- if (reasons.includes("plugin-unavailable")) return "plugin-unavailable";
6571
- if (reasons.includes("invalid-response")) return "invalid-response";
6572
- return "codex-unavailable";
6495
+ /** Reads the explicitly recorded model routing plan from managed configuration. */
6496
+ function readManagedPlan(input) {
6497
+ const value = new RegExp(`^${PLAN_PREFIX}(.+)$`, "m").exec(input)?.[1]?.trim();
6498
+ return PLAN_NAMES.find((plan) => plan === value);
6573
6499
  }
6574
- function timeoutFor(launcher, operation) {
6575
- return operation === "list" && isPackageLauncher(launcher) ? CODEX_PACKAGE_BOOTSTRAP_TIMEOUT_MS : CODEX_PLUGIN_OPERATIONAL_TIMEOUT_MS;
6500
+ /** Reads the explicitly recorded managed Fast mode. */
6501
+ function readManagedFastMode(input) {
6502
+ const value = new RegExp(`^${FAST_MODE_PREFIX}(.+)$`, "m").exec(input)?.[1]?.trim();
6503
+ return FastModeSchema.safeParse(value).data;
6576
6504
  }
6577
- function isPackageLauncher(launcher) {
6578
- return launcher.source === "bunx" || launcher.source === "npm-exec" || launcher.source === "pnpm-exec";
6505
+ /** Reads the explicit managed Computer Use choice. */
6506
+ function readManagedComputerUse(input) {
6507
+ const value = new RegExp(`^${COMPUTER_USE_PREFIX}(.+)$`, "m").exec(input)?.[1]?.trim();
6508
+ return value === "enabled" || value === "disabled" ? value : void 0;
6509
+ }
6510
+ /** Reads the plan-authoritative workflow policy metadata from managed configuration. */
6511
+ function readManagedWorkflowPolicy(input) {
6512
+ const raw = new RegExp(`^${WORKFLOW_POLICY_PREFIX.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}(.+)$`, "m").exec(input)?.[1];
6513
+ if (raw === void 0) return void 0;
6514
+ try {
6515
+ const value = JSON.parse(raw);
6516
+ if (typeof value !== "object" || value === null) return void 0;
6517
+ const record = value;
6518
+ const plan = PLAN_NAMES.find((name) => name === record.plan);
6519
+ const limits = record.limits;
6520
+ const usage = record.projectedUsage;
6521
+ const size = record.softSizeGuidance;
6522
+ if (plan === void 0 || typeof limits !== "object" || limits === null || typeof usage !== "object" || usage === null || typeof size !== "object" || size === null) return void 0;
6523
+ return {
6524
+ plan,
6525
+ limits,
6526
+ projectedUsage: usage,
6527
+ softSizeGuidance: size
6528
+ };
6529
+ } catch {
6530
+ return;
6531
+ }
6532
+ }
6533
+ /** Identifies explicit Root route overrides preserved from active managed configuration. */
6534
+ function readPreservedRootOverrides(input) {
6535
+ const managedRoot = new RegExp(`^${START}\\r?\\n([\\s\\S]*?)^${END}\\r?$`, "m").exec(input)?.[1];
6536
+ if (managedRoot === void 0) return {
6537
+ model: false,
6538
+ reasoningEffort: false,
6539
+ webSearch: false
6540
+ };
6541
+ const plan = readManagedPlan(managedRoot);
6542
+ const model = rootTomlString(input, "model");
6543
+ const reasoningEffort = rootTomlString(input, "model_reasoning_effort");
6544
+ if (plan === void 0 || model === void 0 || reasoningEffort === void 0) return {
6545
+ model: false,
6546
+ reasoningEffort: false,
6547
+ webSearch: false
6548
+ };
6549
+ if (MANAGED_ROOT_MODEL_HISTORY_BY_PLAN[plan].some((route) => route.model === model && route.reasoningEffort === reasoningEffort)) return {
6550
+ model: false,
6551
+ reasoningEffort: false,
6552
+ webSearch: rootTomlString(managedRoot, "web_search") !== "live"
6553
+ };
6554
+ const preset = MODEL_ROUTING_PLANS[plan].root;
6555
+ return {
6556
+ model: model !== preset.model,
6557
+ reasoningEffort: reasoningEffort !== preset.reasoningEffort,
6558
+ webSearch: rootTomlString(managedRoot, "web_search") !== "live"
6559
+ };
6579
6560
  }
6580
- /** Normalizes supported flat and marketplace-oriented Codex catalogs. */
6581
- function parsePluginCatalog(input) {
6582
- for (const value of parseJsonDocuments(input) ?? []) {
6583
- const plugins = parseCatalogValue(value);
6584
- if (plugins !== void 0) return { plugins };
6561
+ function preserveManagedRootPreferences(input, base) {
6562
+ const managedRoot = new RegExp(`^${START}\\r?\\n([\\s\\S]*?)^${END}\\r?$`, "m").exec(input)?.[1];
6563
+ if (managedRoot === void 0) return base;
6564
+ const firstTable = base.search(/^\s*\[/m);
6565
+ const root = firstTable < 0 ? base : base.slice(0, firstTable);
6566
+ const tables = firstTable < 0 ? "" : base.slice(firstTable);
6567
+ let updatedRoot = root.trim();
6568
+ const overrides = readPreservedRootOverrides(input);
6569
+ for (const [key, preserve] of [
6570
+ ["model", overrides.model],
6571
+ ["model_reasoning_effort", overrides.reasoningEffort],
6572
+ ["web_search", overrides.webSearch]
6573
+ ]) {
6574
+ const live = rootValue(managedRoot, key)?.trim();
6575
+ if (!preserve || live === void 0) continue;
6576
+ if (rootValue(root, key)?.trim() === live) continue;
6577
+ updatedRoot = removeRootValue(updatedRoot, rootValue(updatedRoot, key)).trim();
6578
+ updatedRoot = `${updatedRoot}${updatedRoot ? "\n" : ""}${live}`;
6585
6579
  }
6580
+ if (updatedRoot === root.trim()) return base;
6581
+ return `${updatedRoot}${tables ? `\n${tables.trimStart()}` : ""}`;
6586
6582
  }
6587
- function parseMarketplaceNames(input) {
6588
- for (const value of parseJsonDocuments(input) ?? []) {
6589
- if (!isRecord(value) || !Array.isArray(value.marketplaces)) continue;
6590
- const names = [];
6591
- for (const marketplace of value.marketplaces) {
6592
- if (!isRecord(marketplace)) {
6593
- names.length = 0;
6594
- break;
6595
- }
6596
- const name = stringField(marketplace, ["name"]);
6597
- if (name === void 0) {
6598
- names.length = 0;
6599
- break;
6600
- }
6601
- names.push(name);
6602
- }
6603
- if (names.length > 0 || value.marketplaces.length === 0) return names;
6604
- }
6583
+ function mergedStatusLine(original) {
6584
+ if (original === void 0) return "[\"model-with-reasoning\", \"context-remaining\", \"current-dir\"]";
6585
+ const items = rootTomlStringArray(original, "status_line") ?? [];
6586
+ if (!items.includes("context-remaining")) items.push("context-remaining");
6587
+ return `[${items.map((item) => JSON.stringify(item)).join(", ")}]`;
6605
6588
  }
6606
- function parseCatalogValue(value) {
6607
- if (Array.isArray(value)) return parseMarketplaceEntries(value);
6608
- if (!isRecord(value)) return void 0;
6609
- if ("installed" in value || "available" in value) {
6610
- if (!Array.isArray(value.installed) || !Array.isArray(value.available)) return void 0;
6611
- const installed = parsePluginEntries(value.installed, void 0, true);
6612
- const available = parsePluginEntries(value.available, void 0, false);
6613
- return installed === void 0 || available === void 0 ? void 0 : [...installed, ...available];
6589
+ /** Installs config. */
6590
+ function installConfig(input, mode, _platform, plan = DEFAULT_PLAN, maxSubagents, fastMode = "standard", computerUse) {
6591
+ const request = normalizeRequestedAutonomy(mode);
6592
+ const effectiveComputerUse = computerUse ?? readManagedComputerUse(input) ?? "disabled";
6593
+ const priorAutonomy = readAutonomyMetadata(input);
6594
+ const previousOriginalRoot = readOriginalRootMetadata(input);
6595
+ const legacyGeneratedRoot = readLegacyGeneratedRoot(input);
6596
+ const originalPermissionLines = readOriginalPermissionMetadata(input);
6597
+ const base = preserveManagedRootPreferences(input, removeLegacyOmo(removeManaged(input, !request.requested)));
6598
+ const firstTable = base.search(/^\s*\[/m);
6599
+ const root = firstTable < 0 ? base : base.slice(0, firstTable);
6600
+ const tables = firstTable < 0 ? "" : base.slice(firstTable);
6601
+ const permissions = selectPermissionSelection(readRawPermissionSelection(root), request);
6602
+ const effectiveAutonomy = request.requested ? inferAutonomyMode(permissions) : priorAutonomy ?? inferAutonomyMode(permissions);
6603
+ const rootPermissionLines = [
6604
+ permissions.approvalPolicy === void 0 ? void 0 : `approval_policy = ${JSON.stringify(permissions.approvalPolicy)}`,
6605
+ permissions.approvalsReviewer === void 0 ? void 0 : `approvals_reviewer = ${JSON.stringify(permissions.approvalsReviewer)}`,
6606
+ permissions.sandboxMode === void 0 ? void 0 : `sandbox_mode = ${JSON.stringify(permissions.sandboxMode)}`
6607
+ ].filter((line) => line !== void 0);
6608
+ const hadManagedAutonomy = readAutonomyMetadata(input) !== void 0;
6609
+ const hadOriginalRoot = /^# holycodex original root:/m.test(input);
6610
+ const permissionLines = originalPermissionLines ?? (legacyGeneratedRoot !== void 0 && previousOriginalRoot === void 0 ? [] : previousOriginalRoot === void 0 ? hadManagedAutonomy && !hadOriginalRoot ? [] : readPermissionLines(root) : readPermissionLines(previousOriginalRoot));
6611
+ const controlled = [
6612
+ "web_search",
6613
+ "approval_policy",
6614
+ "approvals_reviewer",
6615
+ "sandbox_mode",
6616
+ "max_concurrent_threads_per_session",
6617
+ "status_line",
6618
+ "model_verbosity",
6619
+ "service_tier",
6620
+ ...request.requested ? ["default_permissions"] : []
6621
+ ].map((key) => rootValue(root, key));
6622
+ const preservedRoot = [
6623
+ "web_search",
6624
+ "approval_policy",
6625
+ "approvals_reviewer",
6626
+ "sandbox_mode",
6627
+ "max_concurrent_threads_per_session",
6628
+ "status_line",
6629
+ "model_verbosity",
6630
+ "service_tier",
6631
+ ...request.requested ? ["default_permissions"] : []
6632
+ ].reduce(removeRootKey, root).trim();
6633
+ const originalControlled = controlled.filter((value) => value !== void 0).sort((left, right) => root.indexOf(left) - root.indexOf(right)).join("\n");
6634
+ const hasModel = /^\s*model\s*=/m.test(preservedRoot);
6635
+ const hasEffort = /^\s*model_reasoning_effort\s*=/m.test(preservedRoot);
6636
+ const rootRoute = MODEL_ROUTING_PLANS[plan].root;
6637
+ const model = hasModel ? "" : `model = "${rootRoute.model}"\n`;
6638
+ const effort = hasEffort ? "" : `model_reasoning_effort = "${rootRoute.reasoningEffort}"\n`;
6639
+ const originalSource = previousOriginalRoot === void 0 ? priorAutonomy === void 0 && legacyGeneratedRoot === void 0 ? originalControlled : "" : removePermissionLines(previousOriginalRoot);
6640
+ const original = originalSource ? `${ORIGINAL_ROOT}${Buffer.from(originalSource).toString("base64")}\n` : "";
6641
+ const rootServiceTier = fastMode === "fast-all" ? "fast" : "default";
6642
+ const priorManagedRoot = new RegExp(`^${START}\\r?\\n([\\s\\S]*?)^${END}\\r?$`, "m").exec(input)?.[1];
6643
+ const webSearch = readPreservedRootOverrides(input).webSearch ? rootTomlString(priorManagedRoot ?? "", "web_search") ?? "live" : "live";
6644
+ const statusLine = mergedStatusLine(rootValue(root, "status_line") ?? rootTomlStringArraySource(tableSource(base, "tui") ?? "", "status_line"));
6645
+ const workflow = MODEL_ROUTING_PLANS[plan].workflow;
6646
+ const rootBlock = `${START}\n${PLAN_PREFIX}${plan}\n${FAST_MODE_PREFIX}${fastMode}\n${WORKFLOW_POLICY_PREFIX}${JSON.stringify({
6647
+ plan,
6648
+ limits: workflow.limits,
6649
+ projectedUsage: workflow.projectedUsage,
6650
+ softSizeGuidance: workflow.softSizeGuidance
6651
+ })}\n${AUTONOMY_METADATA_PREFIX}${effectiveAutonomy}\n${COMPUTER_USE_PREFIX}${effectiveComputerUse}\n${original}${originalPermissionMetadata(permissionLines)}${model}${effort}web_search = ${JSON.stringify(webSearch)}\nmodel_verbosity = "low"\nservice_tier = "${rootServiceTier}"\n${rootPermissionLines.join("\n")}\n${END}`;
6652
+ let configured = `${preservedRoot ? `${preservedRoot}\n` : ""}${rootBlock}${tables ? `\n\n${tables}` : ""}`;
6653
+ const legacyMultiAgentV2 = /\bmulti_agent_v2\s*=\s*(true|false)/.exec(configured)?.[1];
6654
+ configured = injectTableKeys(configured, "features", [
6655
+ ["default_mode_request_user_input", "true"],
6656
+ ["multi_agent", "true"],
6657
+ ...legacyMultiAgentV2 === void 0 ? [] : [["multi_agent_v2", legacyMultiAgentV2]]
6658
+ ]);
6659
+ configured = injectTableKeys(configured, "agents", [["max_concurrent_threads_per_session", String((maxSubagents ?? workflow.limits.concurrency) + 1)]]);
6660
+ configured = injectTableKeys(configured, "tui", [["status_line", statusLine]]);
6661
+ if (effectiveAutonomy !== "dangerous") configured = injectTableKeys(configured, "sandbox_workspace_write", [["network_access", "true"]]);
6662
+ configured = injectTableKeys(configured, "desktop", [["show-context-window-usage", "true"]]);
6663
+ if (_platform === "win32") configured = injectTableKeys(configured, "windows", [["sandbox", "\"unelevated\""]]);
6664
+ for (const agent of AGENTS) configured = injectTableKeys(configured, `agents.${agent}`, [["config_file", `"holycodex/agents/${agent}.toml"`]]);
6665
+ const plugin = `${START}\n[plugins."holycodex@holycodex"]\nenabled = true\n${END}`;
6666
+ return `${configured.trim()}\n\n${plugin}\n`;
6667
+ }
6668
+ //#endregion
6669
+ //#region packages/cli/src/context7.ts
6670
+ var RUNNERS = [
6671
+ {
6672
+ executable: "nubx",
6673
+ command: "nubx",
6674
+ prefix: ["-y"]
6675
+ },
6676
+ {
6677
+ executable: "nub",
6678
+ command: "nub",
6679
+ prefix: ["dlx"]
6680
+ },
6681
+ {
6682
+ executable: "bunx",
6683
+ command: "bunx",
6684
+ prefix: []
6685
+ },
6686
+ {
6687
+ executable: "bun",
6688
+ command: "bun",
6689
+ prefix: ["x"]
6690
+ },
6691
+ {
6692
+ executable: "pnpmx",
6693
+ command: "pnpmx",
6694
+ prefix: []
6695
+ },
6696
+ {
6697
+ executable: "pnpm",
6698
+ command: "pnpm",
6699
+ prefix: ["dlx"]
6700
+ },
6701
+ {
6702
+ executable: "npmx",
6703
+ command: "npmx",
6704
+ prefix: ["--yes"]
6705
+ },
6706
+ {
6707
+ executable: "npm",
6708
+ command: "npx",
6709
+ prefix: ["--yes"]
6710
+ },
6711
+ {
6712
+ executable: "yarn",
6713
+ command: "yarn",
6714
+ prefix: ["dlx"]
6614
6715
  }
6615
- if ("marketplaces" in value) return Array.isArray(value.marketplaces) ? parseMarketplaceEntries(value.marketplaces) : void 0;
6616
- if ("plugins" in value) return parseMarketplaceEntry(value);
6716
+ ];
6717
+ /** Constructs the supported direct Context7 invocation for the first available runner. */
6718
+ function context7Command(args, executableExists = executableOnPath, env = process.env) {
6719
+ const runner = RUNNERS.find((candidate) => executableExists(candidate.executable));
6720
+ if (runner === void 0) return void 0;
6721
+ return {
6722
+ command: runner.command,
6723
+ args: [
6724
+ ...runner.prefix,
6725
+ "ctx7@latest",
6726
+ ...args
6727
+ ],
6728
+ env: {
6729
+ ...env,
6730
+ CI: env.CI ?? "1"
6731
+ }
6732
+ };
6617
6733
  }
6618
- function parseMarketplaceEntries(entries) {
6619
- const plugins = [];
6620
- for (const entry of entries) {
6621
- const parsed = parseMarketplaceEntry(entry);
6622
- if (parsed === void 0) return void 0;
6623
- plugins.push(...parsed);
6734
+ /** Reports whether an executable can be resolved from PATH. */
6735
+ function executableOnPath(name) {
6736
+ const path = process.env.PATH;
6737
+ if (path === void 0) return false;
6738
+ const extensions = process.platform === "win32" ? [
6739
+ ".exe",
6740
+ ".cmd",
6741
+ ".bat",
6742
+ ""
6743
+ ] : [""];
6744
+ for (const directory of path.split(delimiter)) for (const extension of extensions) try {
6745
+ if (process.getBuiltinModule("node:fs").existsSync(`${directory}/${name}${extension}`)) return true;
6746
+ } catch {
6747
+ continue;
6624
6748
  }
6625
- return plugins;
6749
+ return false;
6626
6750
  }
6627
- function parseMarketplaceEntry(value) {
6628
- if (!isRecord(value) || !Array.isArray(value.plugins)) return void 0;
6629
- const marketplace = stringField(value, [
6630
- "marketplace",
6631
- "marketplaceId",
6632
- "marketplaceName",
6633
- "id",
6634
- "name"
6635
- ]);
6636
- if (marketplace === void 0) return void 0;
6637
- return parsePluginEntries(value.plugins, marketplace);
6751
+ //#endregion
6752
+ //#region packages/cli/src/core-instructions.ts
6753
+ /** Shared HolyCodex root instructions. */
6754
+ var CORE_INSTRUCTIONS = "HolyCodex: Root is user-facing. Before updates, classify intent and load required skills. Start with \"I detect [intent] intent — [action].\" Choose the accurate intent naturally; no fixed intent taxonomy applies. `plan` and `plan-review` instead own their exact heading and intent as the first visible block; no other mode prints a heading. Do not conceal orchestration. Give concise updates naming each specialist type and what it will do, such as \"Explorer maps X\", \"Librarian verifies Y\", or \"Worker implements Z\". Do not disclose Root orchestration mechanics or explain why delegation is running unless asked. Skills govern method only. Root owns interaction, intent, scope, architecture, product choices, ambiguity, integration, external state, and final judgment and verification. Root is not another implementation branch: evaluate specialist output against scope, fixed architecture, user decisions, repository conventions, and proof; reject or repair weak output and integrate only accepted work. On every plan other than Go, always delegate at least one bounded task through a CLI workflow. Never skip delegation because direct local work is cheaper or sufficient, and never invoke regular Codex collaboration subagents. If the workflow runtime is unavailable or cannot perform the required operation, report the blocker instead of bypassing delegation. Missing task-child visibility is not a reason to avoid workflows. Go does not support workflows, so Root works directly without specialist subagents. A task may contain multiple sequential workflows. Prefer the smallest useful fan-out, stop discovery when evidence is sufficient, and avoid duplicate investigation. The selected plan is authoritative: enforce its permitted model routes for each agent and stage, low verbosity, Fast as the only service-tier variation, concurrency, soft target calls, hard maximum calls, workflow depth, retries, loop iterations, fan-out, projected usage, and soft-size guidance. Root should remain near target calls and exceed them only when intermediate evidence justifies more work; the hard maximum is only a safety and quota ceiling. Larger plans do not automatically consume larger allowances. Keep explorer, librarian, and worker selectable only where the plan permits. Root owns workflow integration and final proof. After any code or manifest implementation, Root loads `code-review` exactly once before final response; it also loads `code-review` for a user-requested snippet, file, directory, diff, patch, or PR review. That skill owns the final audit, repair, proportional checks and reruns, reinspection, diff, and status. Classify unknowns: delegate facts, ask material decisions, and state and use safe reversible defaults. Whenever Root needs user input or would ask any question, it must use `request_user_input` when that tool is available, in every scenario and mode. Root must never stop or reply with a plain-text question when the tool is available. If the tool is unavailable, use a safe reversible default where possible or report a non-question blocker. Never repeat questions or ask discoverable facts. Root must use `request_user_input` immediately before committing, pushing, creating or moving tags, building or compiling, publishing, deploying, destructive or irreversible actions, permission changes, financial actions, sending, or any other externally visible action. Earlier general authorization does not replace this immediate approval unless the user explicitly authorized that exact action in the current turn. Root controls browser and native desktop UI itself. Explorer is repository-read-only, Librarian research-only, and Worker cannot alter dashboards, accounts, permissions, or external state. Specialists never delegate, broaden, review, or make final judgments.";
6755
+ var NATIVE_IO_INSTRUCTIONS = "For `plan` and `plan-review` headings, never print provisionally. Never delegate browser or computer control. For frontend creation, redesign, or visual verification, use installed Build Web Apps `frontend-app-builder` for concept, approval, implementation, and visual verification. For authorized security reviews, audits, scans, threat models, vulnerabilities, or attack paths, use matching installed Codex Security plugin skills. Use these capabilities instead of manual-click instructions, shell-as-GUI, or public research as a substitute for authenticated control. Use Codex native `apply_patch` for workspace file creation, updates, moves, and deletion. Use available native read or shell tools for file inspection and repository search. Do not re-read files only to verify a successful `apply_patch` call.";
6756
+ var COMPUTER_USE_INSTRUCTIONS = "For native desktop tasks, use the available Computer Use capability.";
6757
+ var CODE_REVIEW_ACTIVATION_POLICY = "After loading `code-review`, its first visible line is **CODE REVIEW MODE ACTIVATED**.";
6758
+ /** Gets core instructions with platform and active agent-capacity context. */
6759
+ function coreInstructions(platform, capacity, computerUseEnabled = false) {
6760
+ const threads = capacity?.maxThreads;
6761
+ const depth = capacity?.maxDepth;
6762
+ const capacityInstructions = threads === void 0 || depth === void 0 ? "Before delegation, use active collaboration tool instructions as the authoritative agent-capacity limit." : `Host agent capacity: agents.max_concurrent_threads_per_session=${threads} includes Root. The host nesting limit is ${depth}; the active plan's maxCalls is the hard workflow call ceiling and targetCalls is soft planning guidance. Its lower concurrency, depth, and fan-out limits remain authoritative. On plans other than Go, Root always delegates at least one bounded task through a CLI workflow and reports a blocker if that runtime is unavailable or cannot perform the operation. Go does not support workflows, so Root works directly without specialist subagents.`;
6763
+ const platformInstructions = platform === "win32" ? ` ${WINDOWS_SHELL_POLICY}` : "";
6764
+ return `${CORE_INSTRUCTIONS} ${LITE_WRITING_POLICY} ${CONTEXT7_POLICY} ${NATIVE_IO_INSTRUCTIONS}${computerUseEnabled ? ` ${COMPUTER_USE_INSTRUCTIONS}` : ""} ${CODE_REVIEW_ACTIVATION_POLICY} ${capacityInstructions}${platformInstructions}`;
6638
6765
  }
6639
- function parsePluginEntries(entries, parentMarketplace, defaultInstalled) {
6640
- const plugins = [];
6641
- for (const value of entries) {
6642
- const plugin = parsePluginEntry(value, parentMarketplace, defaultInstalled);
6643
- if (plugin === void 0) return void 0;
6644
- plugins.push(plugin);
6645
- }
6646
- return plugins;
6766
+ //#endregion
6767
+ //#region packages/cli/src/doctor.ts
6768
+ var DOCTOR_LSP_IDLE_SHUTDOWN_MS = 1e3;
6769
+ var COMPATIBILITY_KEYS = ["desktop.show-context-window-usage"];
6770
+ async function runCommand(name, args, env) {
6771
+ const result = await runManagedProcess({
6772
+ command: name,
6773
+ args,
6774
+ platform: process.platform,
6775
+ timeoutMs: 15e3,
6776
+ maxOutputChars: 64 * 1024,
6777
+ ...env === void 0 ? {} : { env }
6778
+ });
6779
+ return {
6780
+ ok: result.exitCode === 0 && !result.timedOut && result.error === void 0,
6781
+ output: `${result.stdout}\n${result.stderr}`.trim() || result.error || ""
6782
+ };
6647
6783
  }
6648
- function parsePluginEntry(value, parentMarketplace, defaultInstalled = false) {
6649
- if (!isRecord(value)) return void 0;
6650
- const rawId = stringField(value, [
6651
- "pluginId",
6652
- "id",
6653
- "name"
6654
- ]);
6655
- if (rawId === void 0) return void 0;
6656
- const marketplace = stringField(value, [
6657
- "marketplace",
6658
- "marketplaceId",
6659
- "marketplaceName"
6660
- ]) ?? parentMarketplace;
6661
- const id = rawId.includes("@") ? rawId : marketplace === void 0 ? rawId : `${rawId}@${marketplace}`;
6662
- const state = stringField(value, [
6663
- "installationState",
6664
- "installState",
6665
- "status",
6666
- "state"
6667
- ]);
6668
- const policy = isRecord(value.policy) ? stringField(value.policy, ["installation"]) : void 0;
6784
+ var defaultRuntime$1 = {
6785
+ platform: process.platform,
6786
+ command: runCommand,
6787
+ executable: executableOnPath,
6788
+ gitBash: resolveGitBashForCurrentProcess
6789
+ };
6790
+ function check(id, status, code, detail, fix) {
6669
6791
  return {
6670
6792
  id,
6671
- installed: booleanField(value.installed) ?? installedFromState(state ?? policy) ?? defaultInstalled,
6672
- enabled: booleanField(value.enabled) ?? enabledFromState(state) ?? false
6793
+ status,
6794
+ code,
6795
+ detail,
6796
+ ...fix === void 0 ? {} : { fix }
6673
6797
  };
6674
6798
  }
6675
- function stringField(value, keys) {
6676
- for (const key of keys) {
6677
- const candidate = value[key];
6678
- if (typeof candidate === "string" && candidate.trim() !== "") return candidate.trim();
6799
+ async function missingFiles(root, paths) {
6800
+ const missing = [];
6801
+ for (const path of paths) try {
6802
+ await access(join(root, path));
6803
+ } catch {
6804
+ missing.push(path);
6679
6805
  }
6806
+ return missing;
6680
6807
  }
6681
- function booleanField(value) {
6682
- if (typeof value === "boolean") return value;
6683
- if (typeof value !== "string") return void 0;
6684
- if (value.toLowerCase() === "true") return true;
6685
- if (value.toLowerCase() === "false") return false;
6686
- }
6687
- function installedFromState(value) {
6688
- if (value === void 0) return void 0;
6689
- const state = value.toLowerCase().replaceAll("-", "_");
6690
- if ([
6691
- "installed",
6692
- "enabled",
6693
- "disabled",
6694
- "installed_by_default"
6695
- ].includes(state)) return true;
6696
- if ([
6697
- "available",
6698
- "not_installed",
6699
- "uninstalled",
6700
- "not_available"
6701
- ].includes(state)) return false;
6808
+ function tableBody(config, table) {
6809
+ return new RegExp(`^\\s*\\[${table.replaceAll(".", "\\.")}]\\s*$([\\s\\S]*?)(?=^\\s*\\[|(?![\\s\\S]))`, "m").exec(config)?.[1];
6702
6810
  }
6703
- function enabledFromState(value) {
6704
- if (value === void 0) return void 0;
6705
- const state = value.toLowerCase();
6706
- if (state === "enabled") return true;
6707
- if (state === "disabled") return false;
6811
+ function tableValue(config, table, key) {
6812
+ const body = tableBody(config, table);
6813
+ return body === void 0 ? void 0 : new RegExp(`^\\s*${key.replaceAll("-", "\\-")}\\s*=\\s*(.+?)\\s*$`, "m").exec(body)?.[1];
6708
6814
  }
6709
- function parseJsonDocuments(input) {
6710
- const wholeDocument = tryParseJson(input);
6711
- if (wholeDocument !== void 0) return [wholeDocument];
6712
- const lines = input.split(/\r?\n/).map((line) => line.trim()).filter(Boolean);
6713
- if (lines.length === 0) return void 0;
6714
- for (let index = 1; index < lines.length; index += 1) {
6715
- const document = tryParseJson(lines.slice(index).join("\n"));
6716
- if (document !== void 0) return [document];
6717
- }
6718
- const documents = [];
6719
- let parsedDocument = false;
6720
- for (const line of lines) {
6721
- const document = tryParseJson(line);
6722
- if (document === void 0) {
6723
- if (parsedDocument) return void 0;
6724
- continue;
6725
- }
6726
- documents.push(document);
6727
- if (documents.length > MAX_JSON_DOCUMENTS) return void 0;
6728
- parsedDocument = true;
6729
- }
6730
- return documents.length === 0 ? void 0 : documents;
6815
+ function autonomy(config) {
6816
+ const approval = rootTomlString(config, "approval_policy");
6817
+ const reviewer = rootTomlString(config, "approvals_reviewer");
6818
+ const sandbox = rootTomlString(config, "sandbox_mode");
6819
+ const network = tableValue(config, "sandbox_workspace_write", "network_access");
6820
+ if (approval === "on-request" && reviewer === "auto_review" && sandbox === "workspace-write" && network === "true") return "safe-workspace";
6821
+ if (approval === "never" && reviewer === void 0 && sandbox === "workspace-write" && network === "true") return "autonomous-workspace";
6822
+ if (approval === "never" && reviewer === void 0 && sandbox === "danger-full-access") return "dangerous";
6823
+ return "unknown";
6731
6824
  }
6732
- function tryParseJson(input) {
6825
+ /** Runs installation, configuration, runtime, and override health checks. */
6826
+ async function doctor(home = process.env.CODEX_HOME ?? join(homedir(), ".codex"), runtime = defaultRuntime$1) {
6827
+ const checks = [];
6828
+ const pluginRoot = join(home, "plugins", "cache", "holycodex", "holycodex", VERSION);
6829
+ const agentRoot = join(home, "holycodex", "agents");
6830
+ const configPath = join(home, "config.toml");
6831
+ let config = "";
6733
6832
  try {
6734
- return JSON.parse(input);
6833
+ config = await readFile(configPath, "utf8");
6735
6834
  } catch {
6736
- return;
6737
- }
6738
- }
6739
- function structuredErrorCodeFromOutput(input) {
6740
- for (const value of parseJsonDocuments(input) ?? []) {
6741
- const code = structuredErrorCode(value);
6742
- if (code !== void 0) return code;
6835
+ checks.push(check("config", "error", "config-missing", `Missing ${configPath}.`, "Run holycodex install."));
6743
6836
  }
6744
- }
6745
- function structuredErrorCode(value) {
6746
- if (!isRecord(value)) return void 0;
6747
- if (value.error !== void 0) {
6748
- const nestedCode = structuredErrorCode(value.error);
6749
- if (nestedCode !== void 0) return nestedCode;
6837
+ const missing = await missingFiles(pluginRoot, [
6838
+ ".codex-plugin/plugin.json",
6839
+ "hooks/hooks.json",
6840
+ ...requiredPackageRuntimes(runtime.platform).map((file) => `runtime/${file}`),
6841
+ ...AGENTS.map((name) => `agents/${name}.toml`),
6842
+ ...SKILLS.map((name) => `skills/${name}/SKILL.md`)
6843
+ ]);
6844
+ checks.push(missing.length === 0 ? check("package", "ok", "package-ready", `Plugin ${VERSION}, runtimes, agents, and ${SKILLS.length} skills are present.`) : check("package", "error", "package-incomplete", `Missing ${missing.join(", ")}.`, "Reinstall HolyCodex."));
6845
+ const webSearchOverride = readPreservedRootOverrides(config).webSearch;
6846
+ checks.push(rootTomlString(config, "web_search") === "live" ? check("web-search", "ok", "live-web-search", "Managed web search defaults to live.") : webSearchOverride ? check("web-search", "ok", "web-search-override", "An intentional user web-search override is preserved.") : check("web-search", "error", "web-search-not-live", "Managed web search is not live.", "Reinstall HolyCodex."));
6847
+ const computerUse = readManagedComputerUse(config);
6848
+ if (computerUse === void 0) checks.push(check("computer-use", "error", "computer-use-choice-missing", "Computer Use has no explicit managed enabled or disabled choice.", "Run holycodex install --computer-use or holycodex install --no-computer-use."));
6849
+ else if (computerUse === "disabled") checks.push(check("computer-use", "ok", "computer-use-disabled", "Computer Use is explicitly disabled; no Computer Use plugin or Root guidance is required."));
6850
+ else {
6851
+ const instructionsActive = coreInstructions(runtime.platform, void 0, true).includes("For native desktop tasks, use the available Computer Use capability.");
6852
+ const verification = instructionsActive ? await verifyComputerUse(runtime) : { status: "missing" };
6853
+ checks.push(!instructionsActive ? check("computer-use", "error", "computer-use-instructions-missing", "Computer Use is enabled, but Root-only Computer Use guidance is not active.", "Reinstall HolyCodex.") : verification.status === "verified" ? check("computer-use", "ok", "computer-use-ready", `Computer Use is enabled and the official plugin is installed and enabled via ${verification.launcherSource}.`) : verification.status === "missing" ? check("computer-use", "error", "computer-use-plugin-missing", "Computer Use is enabled, but the official plugin is not installed and enabled.", "Run holycodex install --computer-use.") : verification.reason === "unsupported" ? check("computer-use", "error", "computer-use-incompatible", "Computer Use is enabled, but the official plugin is incompatible with this Codex runtime or platform.", "Upgrade Codex or disable Computer Use with holycodex install --no-computer-use.") : verification.reason === "marketplace-unavailable" || verification.reason === "timeout" ? check("computer-use", "error", "computer-use-plugin-unavailable", `Computer Use is enabled, but the official marketplace could not be reached (${verification.reason}).`, "Restore Codex marketplace access and run holycodex install --computer-use.") : check("computer-use", "error", "computer-use-installation-failed", `Computer Use is enabled, but installation or verification failed (${verification.reason}).`, "Resolve the reported Codex authentication, permission, configuration, or verification failure and run holycodex install --computer-use."));
6750
6854
  }
6751
- for (const key of [
6752
- "code",
6855
+ const status = rootTomlStringArray(config, "status_line") ?? rootTomlStringArray(tableBody(config, "tui") ?? "", "status_line");
6856
+ checks.push(status?.includes("context-remaining") ? check("context-visibility", "ok", "context-visible", "Context-window usage remains visible.") : check("context-visibility", "error", "context-hidden", "The status line does not show context remaining.", "Reinstall HolyCodex."));
6857
+ checks.push(check("screenshot", "ok", "screenshot-default-preserved", "HolyCodex does not override the enabled Codex screenshot default."));
6858
+ const context7 = context7Command(["--version"], runtime.executable);
6859
+ if (context7 === void 0) checks.push(check("context7", "error", "context7-runner-missing", "No supported direct Context7 runner is available.", "Install nub, Bun, pnpm, npm, or Yarn."));
6860
+ else checks.push(check("context7", "ok", "context7-cli-ready", `${context7.command} constructs a valid direct ctx7@latest command.`));
6861
+ const lsp = await runtime.command(process.execPath, [
6862
+ join(pluginRoot, "runtime", "lsp.js"),
6753
6863
  "status",
6754
- "statusCode"
6755
- ]) {
6756
- const candidate = value[key];
6757
- if (typeof candidate === "string" || typeof candidate === "number") return String(candidate).trim().toUpperCase();
6864
+ "--json"
6865
+ ], {
6866
+ ...process.env,
6867
+ HOLYCODEX_LSP_IDLE_SHUTDOWN_MS: String(DOCTOR_LSP_IDLE_SHUTDOWN_MS),
6868
+ HOLYCODEX_LSP_IDLE_CHECK_INTERVAL_MS: "50"
6869
+ });
6870
+ checks.push(lsp.ok ? check("lsp", "ok", "lsp-cli-ready", "The LSP CLI and daemon are reachable.") : check("lsp", "error", "lsp-cli-failed", lsp.output || "LSP CLI failed.", "Reinstall HolyCodex and inspect the reported daemon log."));
6871
+ if (runtime.platform === "win32") {
6872
+ const resolution = runtime.gitBash();
6873
+ checks.push(resolution.found ? check("git-bash", "ok", "git-bash-launcher-ready", `Git Bash resolves at ${resolution.path}; the bundled launcher is present.`) : check("git-bash", "error", "git-bash-unavailable", resolution.installHint, resolution.installHint));
6758
6874
  }
6759
- }
6760
- function sanitizeDiagnostic(input) {
6761
- return input.replaceAll(/(?:[A-Za-z]:)?[\\/][^\s"']+/g, "<path>").replaceAll(/(token|secret|password|authorization)\s*[:=]\s*[^\s,}]+/gi, "$1=<redacted>").slice(0, 2048);
6762
- }
6763
- function isRecord(value) {
6764
- return typeof value === "object" && value !== null;
6765
- }
6766
- function isUnavailableProcessError(result) {
6767
- if (result.errorCode !== void 0 && SPAWN_UNAVAILABLE_CODES.has(result.errorCode.toUpperCase())) return true;
6768
- const error = result.error?.toUpperCase() ?? "";
6769
- return [...SPAWN_UNAVAILABLE_CODES].some((code) => new RegExp(`(?:^|\\s)${code}(?:$|\\s)`).test(error));
6770
- }
6771
- function isUnavailableThrownError(value) {
6772
- const code = thrownErrorCode(value);
6773
- return code !== void 0 && SPAWN_UNAVAILABLE_CODES.has(code.toUpperCase());
6774
- }
6775
- function isBootstrapThrownError(value) {
6776
- const code = thrownErrorCode(value)?.toUpperCase();
6777
- if (code !== void 0 && [
6778
- "ETIMEDOUT",
6779
- "ECONNRESET",
6780
- "ECONNREFUSED",
6781
- "EAI_AGAIN",
6782
- "ENETUNREACH"
6783
- ].includes(code)) return true;
6784
- if (!(value instanceof Error)) return false;
6785
- return /bootstrap|network|download|fetch|timeout|timed out/i.test(value.message);
6786
- }
6787
- function thrownErrorCode(value) {
6788
- if (typeof value !== "object" || value === null || !("code" in value)) return void 0;
6789
- const code = value.code;
6790
- return typeof code === "string" ? code : void 0;
6791
- }
6792
- function skipped(reason, attemptedLaunchers) {
6875
+ const plan = readManagedPlan(config);
6876
+ const overrides = readPreservedRootOverrides(config);
6877
+ const fast = readManagedFastMode(config);
6878
+ const workflow = readManagedWorkflowPolicy(config);
6879
+ checks.push(plan === void 0 ? check("routes", "error", "route-plan-missing", "Managed route plan metadata is missing.", "Reinstall HolyCodex.") : check("routes", "ok", "routes-ready", `${plan} workflow policy is active with permitted stage routes.`));
6880
+ checks.push(plan === void 0 || workflow === void 0 ? check("workflow", "error", "workflow-settings-missing", "Managed workflow settings are missing or invalid.", "Reinstall HolyCodex.") : JSON.stringify(workflow) === JSON.stringify({
6881
+ plan,
6882
+ limits: MODEL_ROUTING_PLANS[plan].workflow.limits,
6883
+ projectedUsage: MODEL_ROUTING_PLANS[plan].workflow.projectedUsage,
6884
+ softSizeGuidance: MODEL_ROUTING_PLANS[plan].workflow.softSizeGuidance
6885
+ }) ? check("workflow", "ok", "workflow-settings-ready", `${plan} workflow target and maximum limits, projected usage, and size guidance match the catalog.`) : check("workflow", "error", "workflow-settings-drift", `${plan} workflow settings do not match the authoritative catalog.`, "Reinstall HolyCodex."));
6886
+ checks.push(missing.includes("runtime/workflow.js") ? check("workflow-runtime", "error", "workflow-runtime-missing", "The isolated workflow runtime is missing.", "Reinstall HolyCodex.") : check("workflow-runtime", "ok", "workflow-runtime-ready", "The isolated workflow runtime is present."));
6887
+ const manifest = await readFile(join(pluginRoot, ".codex-plugin", "plugin.json"), "utf8").catch(() => "");
6888
+ const mcpManifest = await access(join(pluginRoot, ".mcp.json")).then(() => true).catch(() => false);
6889
+ checks.push(!mcpManifest && !manifest.includes("mcpServers") && !manifest.includes("MCP Tools") ? check("mcp", "ok", "mcp-free", "The installation does not declare MCP servers or tools.") : check("mcp", "error", "mcp-declared", "The installation declares MCP servers or tools.", "Reinstall HolyCodex from a MCP-free package."));
6890
+ checks.push(overrides.model || overrides.reasoningEffort ? check("root-overrides", "ok", "root-overrides-preserved", "Intentional Root model or reasoning overrides are preserved and healthy.") : check("root-overrides", "ok", "root-managed-defaults", "Root uses managed route defaults."));
6891
+ if (plan !== void 0 && fast === void 0) checks.push(check("fast", "warning", "fast-metadata-missing", "Fast metadata is missing; doctor will not guess a service tier.", "Reinstall with an explicit Fast mode."));
6892
+ if (plan !== void 0) for (const agent of AGENTS) {
6893
+ const source = await readFile(join(agentRoot, `${agent}.toml`), "utf8").catch(() => "");
6894
+ const expected = MODEL_ROUTING_PLANS[plan].agents[agent];
6895
+ const overridden = rootTomlString(source, "model") !== expected.model || rootTomlString(source, "model_reasoning_effort") !== expected.reasoningEffort;
6896
+ checks.push(check(`agent-${agent}`, "ok", overridden ? "agent-override-preserved" : "agent-managed-default", overridden ? `${agent} has an intentional healthy route override.` : `${agent} uses managed route defaults.`));
6897
+ }
6898
+ for (const key of COMPATIBILITY_KEYS) if (config.includes(key.split(".")[1] ?? key)) checks.push(check(`compat-${key}`, "warning", "compatibility-sensitive-key", `${key} is compatibility-sensitive and isolated from supported managed Codex keys.`));
6793
6899
  return {
6794
- status: "skipped",
6795
- reason,
6796
- attemptedLaunchers: [...attemptedLaunchers]
6900
+ healthy: checks.every((item) => item.status !== "error"),
6901
+ autonomy: autonomy(config),
6902
+ checks
6903
+ };
6904
+ }
6905
+ async function verifyComputerUse(runtime) {
6906
+ const runProcess = async (input) => {
6907
+ const result = await runtime.command(input.command, input.args, input.env);
6908
+ return {
6909
+ exitCode: result.ok ? 0 : 1,
6910
+ stdout: result.ok ? result.output : "",
6911
+ stderr: result.ok ? "" : result.output,
6912
+ timedOut: false,
6913
+ matched: false,
6914
+ outputTruncated: false
6915
+ };
6797
6916
  };
6917
+ return verifyOfficialPlugin(COMPUTER_USE_PLUGIN, runProcess, runtime.platform, process.env);
6798
6918
  }
6799
6919
  //#endregion
6800
6920
  //#region packages/cli/src/files.ts
@@ -6880,6 +7000,8 @@ async function install(options, runtime = defaultRuntime) {
6880
7000
  notify(options, "prerequisites", "Checking prerequisites", "complete");
6881
7001
  const plan = options.plan ?? "plus-low";
6882
7002
  const target = paths();
7003
+ const existingConfig = await readText(target.config);
7004
+ const computerUseChoice = await resolveComputerUseChoice(existingConfig, options);
6883
7005
  const root = backupRoot();
6884
7006
  notify(options, "backup", "Backing up existing installation", "running");
6885
7007
  const configBackup = await backup(target.config, root);
@@ -6893,19 +7015,19 @@ async function install(options, runtime = defaultRuntime) {
6893
7015
  ].filter((path) => path !== void 0);
6894
7016
  notify(options, "backup", "Backing up existing installation", "complete", `${backups.length} saved`);
6895
7017
  notify(options, "configuration", "Preparing configuration", "running");
6896
- const existingConfig = await readText(target.config);
6897
7018
  const previousPlan = readManagedPlan(existingConfig);
6898
7019
  const fastMode = options.fast ?? "standard";
6899
- const config = installConfig(existingConfig, options.autonomy, runtime.platform, plan, options.maxSubagents, fastMode);
7020
+ const config = installConfig(existingConfig, options.autonomy, runtime.platform, plan, options.maxSubagents, fastMode, computerUseChoice);
6900
7021
  notify(options, "configuration", "Preparing configuration", "complete", plan);
6901
7022
  notify(options, "staging", "Staging plugin and agent files", "running");
6902
7023
  const existingAgentPreferences = await readAgentPreferences(target.agents, previousPlan);
6903
7024
  const staging = await mkdtemp(join(tmpdir(), "holycodex-stage-"));
6904
7025
  const stagedCache = join(staging, "cache");
6905
7026
  const stagedAgents = join(staging, "agents");
6906
- await cp(pluginRoot, stagedCache, { recursive: true });
7027
+ const sourcePluginRoot = runtime.pluginRoot ?? pluginRoot;
7028
+ await cp(sourcePluginRoot, stagedCache, { recursive: true });
6907
7029
  await writeInstalledAgents(join(stagedCache, "agents"), runtime.platform, plan, fastMode);
6908
- await cp(join(pluginRoot, "agents"), stagedAgents, { recursive: true });
7030
+ await cp(join(sourcePluginRoot, "agents"), stagedAgents, { recursive: true });
6909
7031
  await writeInstalledAgents(stagedAgents, runtime.platform, plan, fastMode);
6910
7032
  await preserveAgentPreferences(stagedAgents, existingAgentPreferences, plan, fastMode);
6911
7033
  notify(options, "staging", "Staging plugin and agent files", "complete");
@@ -6940,8 +7062,15 @@ async function install(options, runtime = defaultRuntime) {
6940
7062
  codexSecurity = await installCodexSecurity(runtime.runProcess, runtime.platform, process.env);
6941
7063
  notify(options, "codex-security", "Installing Codex Security", "complete", pluginProgressDetail(codexSecurity));
6942
7064
  notify(options, "computer-use", "Installing Computer Use", "running");
6943
- computerUse = await installComputerUse(runtime.runProcess, runtime.platform, process.env);
6944
- notify(options, "computer-use", "Installing Computer Use", "complete", pluginProgressDetail(computerUse));
7065
+ if (computerUseChoice === "enabled") {
7066
+ const installed = await installComputerUse(runtime.runProcess, runtime.platform, process.env);
7067
+ if (installed.status === "skipped") throw computerUseFailure(installed);
7068
+ computerUse = installed;
7069
+ notify(options, "computer-use", "Installing Computer Use", "complete", pluginProgressDetail(installed));
7070
+ } else {
7071
+ computerUse = { status: "disabled" };
7072
+ notify(options, "computer-use", "Computer Use disabled", "complete", "disabled");
7073
+ }
6945
7074
  notify(options, "build-web-apps", "Installing Build Web Apps", "running");
6946
7075
  buildWebApps = await installBuildWebApps(runtime.runProcess, runtime.platform, process.env);
6947
7076
  notify(options, "build-web-apps", "Installing Build Web Apps", "complete", pluginProgressDetail(buildWebApps));
@@ -6975,6 +7104,18 @@ async function install(options, runtime = defaultRuntime) {
6975
7104
  buildWebApps
6976
7105
  };
6977
7106
  }
7107
+ async function resolveComputerUseChoice(existingConfig, options) {
7108
+ if (options.computerUse !== void 0) return options.computerUse;
7109
+ const managed = readManagedComputerUse(existingConfig);
7110
+ if (managed !== void 0) return managed;
7111
+ if (options.promptComputerUse !== void 0) return options.promptComputerUse();
7112
+ if (options.interactive === true) throw new Error("Interactive Computer Use selection is unavailable on this surface.");
7113
+ throw new Error("Computer Use choice is required for a new non-interactive installation. Re-run with --computer-use or --no-computer-use.");
7114
+ }
7115
+ function computerUseFailure(result) {
7116
+ const reason = result.reason.replaceAll("-", " ");
7117
+ return /* @__PURE__ */ new Error(`Computer Use is enabled, but the official plugin could not be installed or verified (${reason}). Re-run with --computer-use after resolving the Codex launcher or marketplace issue, or choose --no-computer-use.`);
7118
+ }
6978
7119
  function notify(options, step, label, status, detail) {
6979
7120
  options.onProgress?.({
6980
7121
  step,
@@ -7007,7 +7148,7 @@ async function restoreTarget(target, source) {
7007
7148
  }
7008
7149
  async function removeObsoleteVersionCaches(cacheRoot) {
7009
7150
  if (!await exists(cacheRoot)) return;
7010
- for (const entry of await readdir(cacheRoot)) if (entry !== "0.12.7") await rm(join(cacheRoot, entry), {
7151
+ for (const entry of await readdir(cacheRoot)) if (entry !== "0.13.0-dev.203.1") await rm(join(cacheRoot, entry), {
7011
7152
  recursive: true,
7012
7153
  force: true
7013
7154
  });
@@ -7177,12 +7318,12 @@ function renderHelp(version, color) {
7177
7318
  const section = (text) => paint(color, BOLD, text);
7178
7319
  const muted = (text) => paint(color, DIM, text);
7179
7320
  return `${title}\n${muted("Lean Codex toolkit installer and doctor")}\n\n${section("USAGE")}\n holycodex <command> [options]\n\n${section("COMMANDS")}\n install Install or update HolyCodex\n cleanup Remove HolyCodex-owned state\n doctor Diagnose installation and runtime\n\n${section("OPTIONS")}\n --plan <plan> Model routing plan for install: ${PLAN_HELP}\n Default: ${DEFAULT_PLAN}\n --max-subagents <count> Override concurrent direct subagents for install\n --fast Use Fast for generated subagents only\n --fast-all Use Fast for Root and generated subagents\n --no-fast Use Standard for Root and generated subagents\n -h, --help Show help\n -v, --version Show version\n --no-tui Accepted; commands remain noninteractive\n --codex-autonomous Never ask; keep workspace sandbox\n --no-codex-autonomous Safe interactive defaults\n --dangerous-codex-autonomous Never ask; disable filesystem sandbox\n install --verbose Show detailed install steps
7180
- --json Print machine-readable output\n`;
7321
+ --json Print machine-readable output\n --computer-use Enable and verify the official Computer Use plugin\n --no-computer-use Keep Computer Use disabled\n`;
7181
7322
  }
7182
7323
  /** Renders install-specific model plan and option help. */
7183
7324
  function renderInstallHelp(version, color) {
7184
7325
  const title = paint(color, `${BOLD}${CYAN}`, `HolyCodex ${version}`);
7185
- const section = (text) => paint(color, BOLD, text);
7326
+ const section = (text) => `${paint(color, BOLD, text)}${text === "Options:" ? "\n --computer-use Enable and verify the official Computer Use plugin\n --no-computer-use Keep Computer Use disabled" : ""}`;
7186
7327
  return `${title}\n\n${section("Usage:")}\n holycodex install [options]\n\n${section("Options:")}\n --plan <plan> Model routing plan: ${PLAN_HELP}\n Default: ${DEFAULT_PLAN}\n --max-subagents <count> Override concurrent direct subagents\n --fast Use Fast for generated subagents only\n --fast-all Use Fast for Root and generated subagents\n --no-fast Use Standard for Root and generated subagents\n -v, --verbose Show detailed install steps
7187
7328
  --json Print machine-readable output\n --no-tui Accepted; install remains noninteractive\n --codex-autonomous Never ask; keep workspace sandbox\n --no-codex-autonomous Safe interactive defaults\n --dangerous-codex-autonomous Never ask; disable filesystem sandbox\n -h, --help Show help\n\nPlans provide increasing expected model usage and capability. Fast flags are mutually exclusive.\n\n${section("Examples:")}\n bunx holycodex install\n bunx holycodex install --plan go\n bunx holycodex install --plan plus-low --fast\n bunx holycodex install --plan plus-high\n bunx holycodex install --plan pro-5x --fast-all\n bunx holycodex install --plan pro-20x --no-fast\n`;
7188
7329
  }
@@ -7211,10 +7352,14 @@ function renderRunResult(result, color) {
7211
7352
  function renderOfficialPlugins(result) {
7212
7353
  return [
7213
7354
  renderOfficialPlugin("Codex Security", result.codexSecurity),
7214
- renderOfficialPlugin("Computer Use", result.computerUse),
7355
+ renderComputerUse(result.computerUse),
7215
7356
  renderOfficialPlugin("Build Web Apps", result.buildWebApps)
7216
7357
  ].join("");
7217
7358
  }
7359
+ function renderComputerUse(result) {
7360
+ if (result?.status === "disabled") return "\n Computer Use is disabled.";
7361
+ return renderOfficialPlugin("Computer Use", result);
7362
+ }
7218
7363
  function renderOfficialPlugin(name, plugin) {
7219
7364
  if (plugin === void 0) return "";
7220
7365
  if (plugin.status === "installed") return `\n Installed official ${name} plugin.`;
@@ -7261,8 +7406,14 @@ async function main() {
7261
7406
  process$1.stdout.write(`${VERSION}\n`);
7262
7407
  return;
7263
7408
  }
7409
+ const interactiveInstall = parsed.command === "install" && parsed.noTui === false && parsed.json === false && process$1.stdin.isTTY === true && process$1.stdout.isTTY === true;
7264
7410
  const options = {
7265
7411
  autonomy: parsed.autonomy,
7412
+ ...parsed.computerUse === void 0 ? {} : { computerUse: parsed.computerUse },
7413
+ ...parsed.command === "install" ? {
7414
+ interactive: interactiveInstall,
7415
+ ...interactiveInstall ? { promptComputerUse } : {}
7416
+ } : {},
7266
7417
  fast: parsed.fast,
7267
7418
  json: parsed.json,
7268
7419
  plan: parsed.plan,
@@ -7280,6 +7431,18 @@ async function main() {
7280
7431
  const result = parsed.command === "install" ? await install(options) : await cleanup(options);
7281
7432
  process$1.stdout.write(parsed.json ? `${JSON.stringify(result)}\n` : renderRunResult(result, stdoutColor));
7282
7433
  }
7434
+ async function promptComputerUse() {
7435
+ const readline = createInterface({
7436
+ input: process$1.stdin,
7437
+ output: process$1.stdout
7438
+ });
7439
+ try {
7440
+ const answer = await readline.question("Enable Computer Use? [y/N] ");
7441
+ return /^y(?:es)?$/i.test(answer.trim()) ? "enabled" : "disabled";
7442
+ } finally {
7443
+ readline.close();
7444
+ }
7445
+ }
7283
7446
  try {
7284
7447
  await main();
7285
7448
  } catch (error) {