holycodex 0.10.2 → 0.10.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -0
- package/dist/cli.js +253 -25
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -9,4 +9,8 @@ bunx holycodex@dev doctor
|
|
|
9
9
|
|
|
10
10
|
Use `holycodex --help` for commands, autonomy options, and service tiers. `--fast` selects the fast tier; `--no-fast` or omitting both tier flags selects the default. Stable releases use `bunx holycodex`; development releases use npm's `dev` dist-tag.
|
|
11
11
|
|
|
12
|
+
Default and `--no-codex-autonomous` installs use Codex Approve for me semantics: `approval_policy = "on-request"`, `approvals_reviewer = "auto_review"`, and `sandbox_mode = "workspace-write"`. Autonomous modes omit the reviewer and retain their documented sandbox behavior. The optional `holycodex-config` permission profile remains available without forcing `default_permissions`, so users may select Full access or another profile.
|
|
13
|
+
|
|
14
|
+
Install also attempts to add or enable the official `codex-security@openai-curated` plugin through structured Codex CLI commands. External availability failures are non-fatal and reported in human and JSON results. Cleanup leaves this independent official plugin installed. Build Web Apps remains separately managed by Codex.
|
|
15
|
+
|
|
12
16
|
Repository, documentation, license, and security notices: https://github.com/davidbasilefilho/holycodex
|
package/dist/cli.js
CHANGED
|
@@ -614,6 +614,7 @@ var string$1 = (params) => {
|
|
|
614
614
|
};
|
|
615
615
|
var integer = /^-?\d+$/;
|
|
616
616
|
var number$1 = /^-?\d+(?:\.\d+)?$/;
|
|
617
|
+
var boolean$1 = /^(?:true|false)$/i;
|
|
617
618
|
var lowercase = /^[^A-Z]*$/;
|
|
618
619
|
var uppercase = /^[^a-z]*$/;
|
|
619
620
|
//#endregion
|
|
@@ -1408,6 +1409,24 @@ var $ZodNumberFormat = /*@__PURE__*/ $constructor("$ZodNumberFormat", (inst, def
|
|
|
1408
1409
|
$ZodCheckNumberFormat.init(inst, def);
|
|
1409
1410
|
$ZodNumber.init(inst, def);
|
|
1410
1411
|
});
|
|
1412
|
+
var $ZodBoolean = /*@__PURE__*/ $constructor("$ZodBoolean", (inst, def) => {
|
|
1413
|
+
$ZodType.init(inst, def);
|
|
1414
|
+
inst._zod.pattern = boolean$1;
|
|
1415
|
+
inst._zod.parse = (payload, _ctx) => {
|
|
1416
|
+
if (def.coerce) try {
|
|
1417
|
+
payload.value = Boolean(payload.value);
|
|
1418
|
+
} catch (_) {}
|
|
1419
|
+
const input = payload.value;
|
|
1420
|
+
if (typeof input === "boolean") return payload;
|
|
1421
|
+
payload.issues.push({
|
|
1422
|
+
expected: "boolean",
|
|
1423
|
+
code: "invalid_type",
|
|
1424
|
+
input,
|
|
1425
|
+
inst
|
|
1426
|
+
});
|
|
1427
|
+
return payload;
|
|
1428
|
+
};
|
|
1429
|
+
});
|
|
1411
1430
|
var $ZodUnknown = /*@__PURE__*/ $constructor("$ZodUnknown", (inst, def) => {
|
|
1412
1431
|
$ZodType.init(inst, def);
|
|
1413
1432
|
inst._zod.parse = (payload) => payload;
|
|
@@ -2623,6 +2642,13 @@ function _int(Class, params) {
|
|
|
2623
2642
|
});
|
|
2624
2643
|
}
|
|
2625
2644
|
// @__NO_SIDE_EFFECTS__
|
|
2645
|
+
function _boolean(Class, params) {
|
|
2646
|
+
return new Class({
|
|
2647
|
+
type: "boolean",
|
|
2648
|
+
...normalizeParams(params)
|
|
2649
|
+
});
|
|
2650
|
+
}
|
|
2651
|
+
// @__NO_SIDE_EFFECTS__
|
|
2626
2652
|
function _unknown(Class) {
|
|
2627
2653
|
return new Class({ type: "unknown" });
|
|
2628
2654
|
}
|
|
@@ -3168,6 +3194,9 @@ var numberProcessor = (schema, ctx, _json, _params) => {
|
|
|
3168
3194
|
else if (typeof maximum === "number") json.maximum = maximum;
|
|
3169
3195
|
if (typeof multipleOf === "number") json.multipleOf = multipleOf;
|
|
3170
3196
|
};
|
|
3197
|
+
var booleanProcessor = (_schema, _ctx, json, _params) => {
|
|
3198
|
+
json.type = "boolean";
|
|
3199
|
+
};
|
|
3171
3200
|
var neverProcessor = (_schema, _ctx, json, _params) => {
|
|
3172
3201
|
json.not = {};
|
|
3173
3202
|
};
|
|
@@ -3851,6 +3880,14 @@ var ZodNumberFormat = /*@__PURE__*/ $constructor("ZodNumberFormat", (inst, def)
|
|
|
3851
3880
|
function int(params) {
|
|
3852
3881
|
return /* @__PURE__ */ _int(ZodNumberFormat, params);
|
|
3853
3882
|
}
|
|
3883
|
+
var ZodBoolean = /*@__PURE__*/ $constructor("ZodBoolean", (inst, def) => {
|
|
3884
|
+
$ZodBoolean.init(inst, def);
|
|
3885
|
+
ZodType.init(inst, def);
|
|
3886
|
+
inst._zod.processJSONSchema = (ctx, json, params) => booleanProcessor(inst, ctx, json, params);
|
|
3887
|
+
});
|
|
3888
|
+
function boolean(params) {
|
|
3889
|
+
return /* @__PURE__ */ _boolean(ZodBoolean, params);
|
|
3890
|
+
}
|
|
3854
3891
|
var ZodUnknown = /*@__PURE__*/ $constructor("ZodUnknown", (inst, def) => {
|
|
3855
3892
|
$ZodUnknown.init(inst, def);
|
|
3856
3893
|
ZodType.init(inst, def);
|
|
@@ -4252,7 +4289,7 @@ function superRefine(fn, params) {
|
|
|
4252
4289
|
}
|
|
4253
4290
|
//#endregion
|
|
4254
4291
|
//#region packages/cli/src/catalog.ts
|
|
4255
|
-
var VERSION = "0.10.
|
|
4292
|
+
var VERSION = "0.10.3";
|
|
4256
4293
|
var SKILLS = [
|
|
4257
4294
|
"ast-grep",
|
|
4258
4295
|
"caveman",
|
|
@@ -4804,17 +4841,46 @@ var defaultManagedProcessRuntime = {
|
|
|
4804
4841
|
/** Runs managed process. */
|
|
4805
4842
|
async function runManagedProcess(input, runtime = defaultManagedProcessRuntime) {
|
|
4806
4843
|
return await new Promise((resolve) => {
|
|
4807
|
-
|
|
4808
|
-
|
|
4809
|
-
|
|
4810
|
-
|
|
4811
|
-
|
|
4812
|
-
|
|
4813
|
-
|
|
4814
|
-
|
|
4815
|
-
|
|
4816
|
-
|
|
4817
|
-
|
|
4844
|
+
let child;
|
|
4845
|
+
try {
|
|
4846
|
+
child = (runtime.spawnChild ?? spawn)(input.command, [...input.args], {
|
|
4847
|
+
...input.cwd === void 0 ? {} : { cwd: input.cwd },
|
|
4848
|
+
...input.env === void 0 ? {} : { env: input.env },
|
|
4849
|
+
stdio: [
|
|
4850
|
+
"pipe",
|
|
4851
|
+
"pipe",
|
|
4852
|
+
"pipe"
|
|
4853
|
+
],
|
|
4854
|
+
windowsHide: true,
|
|
4855
|
+
detached: input.platform !== "win32"
|
|
4856
|
+
});
|
|
4857
|
+
} catch (error) {
|
|
4858
|
+
resolve({
|
|
4859
|
+
exitCode: null,
|
|
4860
|
+
stdout: "",
|
|
4861
|
+
stderr: "",
|
|
4862
|
+
timedOut: false,
|
|
4863
|
+
matched: false,
|
|
4864
|
+
outputTruncated: false,
|
|
4865
|
+
error: error instanceof Error ? error.message : String(error)
|
|
4866
|
+
});
|
|
4867
|
+
return;
|
|
4868
|
+
}
|
|
4869
|
+
const childStdin = child.stdin;
|
|
4870
|
+
const childStdout = child.stdout;
|
|
4871
|
+
const childStderr = child.stderr;
|
|
4872
|
+
if (childStdin === null || childStdout === null || childStderr === null) {
|
|
4873
|
+
resolve({
|
|
4874
|
+
exitCode: null,
|
|
4875
|
+
stdout: "",
|
|
4876
|
+
stderr: "",
|
|
4877
|
+
timedOut: false,
|
|
4878
|
+
matched: false,
|
|
4879
|
+
outputTruncated: false,
|
|
4880
|
+
error: "Managed process did not expose piped standard streams."
|
|
4881
|
+
});
|
|
4882
|
+
return;
|
|
4883
|
+
}
|
|
4818
4884
|
let stdout = {
|
|
4819
4885
|
head: "",
|
|
4820
4886
|
tail: "",
|
|
@@ -4859,11 +4925,11 @@ async function runManagedProcess(input, runtime = defaultManagedProcessRuntime)
|
|
|
4859
4925
|
terminate();
|
|
4860
4926
|
}
|
|
4861
4927
|
};
|
|
4862
|
-
|
|
4928
|
+
childStdout.on("data", (chunk) => {
|
|
4863
4929
|
stdout = appendOutput(stdout, chunk.toString(), input.maxOutputChars);
|
|
4864
4930
|
inspectMatch();
|
|
4865
4931
|
});
|
|
4866
|
-
|
|
4932
|
+
childStderr.on("data", (chunk) => {
|
|
4867
4933
|
stderr = appendOutput(stderr, chunk.toString(), input.maxOutputChars);
|
|
4868
4934
|
inspectMatch();
|
|
4869
4935
|
});
|
|
@@ -4874,8 +4940,8 @@ async function runManagedProcess(input, runtime = defaultManagedProcessRuntime)
|
|
|
4874
4940
|
terminate();
|
|
4875
4941
|
}, input.timeoutMs);
|
|
4876
4942
|
timeout.unref();
|
|
4877
|
-
if (input.stdin === void 0)
|
|
4878
|
-
else
|
|
4943
|
+
if (input.stdin === void 0) childStdin.end();
|
|
4944
|
+
else childStdin.end(input.stdin);
|
|
4879
4945
|
});
|
|
4880
4946
|
}
|
|
4881
4947
|
/** Terminates process tree. */
|
|
@@ -5167,8 +5233,8 @@ function installConfig(input, mode, _platform, plan = DEFAULT_PLAN, maxSubagents
|
|
|
5167
5233
|
const tables = firstTable < 0 ? "" : base.slice(firstTable);
|
|
5168
5234
|
const controlled = [
|
|
5169
5235
|
"approval_policy",
|
|
5236
|
+
"approvals_reviewer",
|
|
5170
5237
|
"sandbox_mode",
|
|
5171
|
-
"default_permissions",
|
|
5172
5238
|
"max_concurrent_threads_per_session",
|
|
5173
5239
|
"status_line",
|
|
5174
5240
|
"model_verbosity",
|
|
@@ -5176,8 +5242,8 @@ function installConfig(input, mode, _platform, plan = DEFAULT_PLAN, maxSubagents
|
|
|
5176
5242
|
].map((key) => rootValue(root, key));
|
|
5177
5243
|
const preservedRoot = [
|
|
5178
5244
|
"approval_policy",
|
|
5245
|
+
"approvals_reviewer",
|
|
5179
5246
|
"sandbox_mode",
|
|
5180
|
-
"default_permissions",
|
|
5181
5247
|
"max_concurrent_threads_per_session",
|
|
5182
5248
|
"status_line",
|
|
5183
5249
|
"model_verbosity",
|
|
@@ -5191,9 +5257,10 @@ function installConfig(input, mode, _platform, plan = DEFAULT_PLAN, maxSubagents
|
|
|
5191
5257
|
const model = hasModel ? "" : `model = "${rootRoute.model}"\n`;
|
|
5192
5258
|
const effort = hasEffort ? "" : `model_reasoning_effort = "${rootRoute.reasoningEffort}"\n`;
|
|
5193
5259
|
const approval = mode === "default" ? "on-request" : "never";
|
|
5260
|
+
const approvalsReviewer = mode === "default" ? "approvals_reviewer = \"auto_review\"\n" : "";
|
|
5194
5261
|
const sandbox = mode === "dangerous" ? "danger-full-access" : "workspace-write";
|
|
5195
5262
|
const original = originalControlled ? `${ORIGINAL_ROOT}${Buffer.from(originalControlled).toString("base64")}\n` : "";
|
|
5196
|
-
const rootBlock = `${START}\n${PLAN_PREFIX}${plan}\n${FAST_MODE_PREFIX}${fastMode}\n${maxSubagents === void 0 ? "" : `${MAX_SUBAGENTS_PREFIX}${maxSubagents}\n`}${original}${model}${effort}model_verbosity = "low"\nservice_tier = "${fastMode === "fast-all" ? "fast" : "default"}"\napproval_policy = "${approval}"\
|
|
5263
|
+
const rootBlock = `${START}\n${PLAN_PREFIX}${plan}\n${FAST_MODE_PREFIX}${fastMode}\n${maxSubagents === void 0 ? "" : `${MAX_SUBAGENTS_PREFIX}${maxSubagents}\n`}${original}${model}${effort}model_verbosity = "low"\nservice_tier = "${fastMode === "fast-all" ? "fast" : "default"}"\napproval_policy = "${approval}"\n${approvalsReviewer}sandbox_mode = "${sandbox}"\nstatus_line = ${mergedStatusLine(rootValue(root, "status_line"))}\n${END}`;
|
|
5197
5264
|
let configured = `${preservedRoot ? `${preservedRoot}\n` : ""}${rootBlock}${tables ? `\n\n${tables}` : ""}`;
|
|
5198
5265
|
configured = injectTableKeys(configured, `permissions.${MANAGED_PERMISSION_PROFILE}`, [["description", "\"HolyCodex config.toml permissions.\""], ["extends", "\":workspace\""]]);
|
|
5199
5266
|
configured = injectTableKeys(configured, `permissions.${MANAGED_PERMISSION_PROFILE}.network`, [["enabled", "true"]]);
|
|
@@ -5309,11 +5376,12 @@ function tableInteger(config, table, key) {
|
|
|
5309
5376
|
}
|
|
5310
5377
|
function autonomy(config) {
|
|
5311
5378
|
const approval = rootTomlString(config, "approval_policy");
|
|
5379
|
+
const approvalsReviewer = rootTomlString(config, "approvals_reviewer");
|
|
5312
5380
|
const sandbox = rootTomlString(config, "sandbox_mode");
|
|
5313
5381
|
const network = tableBoolean(config, "sandbox_workspace_write", "network_access");
|
|
5314
|
-
if (approval === "on-request" && sandbox === "workspace-write" && network === true) return "safe-workspace";
|
|
5315
|
-
if (approval === "never" && sandbox === "workspace-write" && network === true) return "autonomous-workspace";
|
|
5316
|
-
if (approval === "never" && sandbox === "danger-full-access") return "dangerous";
|
|
5382
|
+
if (approval === "on-request" && approvalsReviewer === "auto_review" && sandbox === "workspace-write" && network === true) return "safe-workspace";
|
|
5383
|
+
if (approval === "never" && approvalsReviewer === void 0 && sandbox === "workspace-write" && network === true) return "autonomous-workspace";
|
|
5384
|
+
if (approval === "never" && approvalsReviewer === void 0 && sandbox === "danger-full-access") return "dangerous";
|
|
5317
5385
|
return "unknown";
|
|
5318
5386
|
}
|
|
5319
5387
|
/** Runs HolyCodex installation and environment health checks. */
|
|
@@ -5396,7 +5464,7 @@ async function doctor(home = process.env.CODEX_HOME ?? join(homedir(), ".codex")
|
|
|
5396
5464
|
checks.push(["default", "fast"].includes(rootTomlString(config, "service_tier") ?? "") && (managedFastMode === void 0 || rootTomlString(config, "service_tier") === (managedFastMode === "fast-all" ? "fast" : "default")) ? check("service-tier", "ok", "service-tier-ready", "Codex service tier is explicitly managed.") : check("service-tier", "error", "service-tier-stale", "service_tier does not match the managed Fast mode.", "Reinstall HolyCodex with --fast, --fast-all, or --no-fast."));
|
|
5397
5465
|
checks.push(rootTomlString(config, "model_verbosity") === "low" ? check("root-verbosity", "ok", "root-verbosity-ready", "Root model verbosity is forced to low.") : check("root-verbosity", "error", "root-verbosity-stale", "Root model verbosity must be low.", "Reinstall HolyCodex."));
|
|
5398
5466
|
checks.push(preset === void 0 || expectedMaxSubagents === void 0 || tableInteger(config, "agents", "max_threads") !== expectedMaxSubagents + 1 || tableInteger(config, "agents", "max_depth") !== preset.usage.maxDepth ? check("agent-usage", "error", "agent-usage-stale", "Agent concurrency configuration does not match the selected routing plan or explicit override.", "Reinstall HolyCodex.") : check("agent-usage", "ok", "agent-usage-ready", `Agent concurrency allows ${expectedMaxSubagents} direct subagent${expectedMaxSubagents === 1 ? "" : "s"}.`));
|
|
5399
|
-
checks.push(mode === "unknown" ? check("autonomy", "error", "invalid-autonomy-config", "Approval, sandbox, and network settings do not match a supported mode.", "Rerun install with the intended autonomy flag.") : mode === "dangerous" ? check("autonomy", "warning", "dangerous-autonomy", "Explicit dangerous autonomy is active; workspace containment is removed.") : check("autonomy", "ok", `${mode}-ready`, mode === "safe-workspace" ? "Safe workspace autonomy is active." : "Approval-free workspace autonomy is active."));
|
|
5467
|
+
checks.push(mode === "unknown" ? check("autonomy", "error", "invalid-autonomy-config", "Approval policy, approval reviewer, sandbox, and network settings do not match a supported mode.", "Rerun install with the intended autonomy flag.") : mode === "dangerous" ? check("autonomy", "warning", "dangerous-autonomy", "Explicit dangerous autonomy is active; workspace containment is removed.") : check("autonomy", "ok", `${mode}-ready`, mode === "safe-workspace" ? "Safe workspace autonomy is active." : "Approval-free workspace autonomy is active."));
|
|
5400
5468
|
checks.push(tableBoolean(config, "features", "default_mode_request_user_input") === true ? check("user-input", "ok", "user-input-ready", "default_mode_request_user_input is enabled.") : check("user-input", "error", "user-input-disabled", "default_mode_request_user_input is not enabled.", "Rerun holycodex install."));
|
|
5401
5469
|
checks.push(tableStringArray(config, "desktop", "enabled-reasoning-efforts")?.join(",") === "low,medium,high" ? check("desktop-reasoning", "ok", "desktop-reasoning-ready", "Desktop exposes low, medium, and high reasoning efforts.") : check("desktop-reasoning", "error", "desktop-reasoning-stale", "Desktop reasoning choices must be low, medium, and high.", "Reinstall HolyCodex."));
|
|
5402
5470
|
checks.push(tableBoolean(config, "desktop", "show-context-window-usage") === true ? check("desktop-context-usage", "ok", "desktop-context-usage-ready", "Desktop context-window usage is visible.") : check("desktop-context-usage", "error", "desktop-context-usage-hidden", "Desktop context-window usage is not enabled.", "Reinstall HolyCodex."));
|
|
@@ -5424,6 +5492,156 @@ async function doctor(home = process.env.CODEX_HOME ?? join(homedir(), ".codex")
|
|
|
5424
5492
|
};
|
|
5425
5493
|
}
|
|
5426
5494
|
//#endregion
|
|
5495
|
+
//#region packages/cli/src/codex-security.ts
|
|
5496
|
+
var CODEX_SECURITY_PLUGIN = "codex-security@openai-curated";
|
|
5497
|
+
var CODEX_PLUGIN_TIMEOUT_MS = 2e4;
|
|
5498
|
+
var MAX_CODEX_OUTPUT_CHARS = 64 * 1024;
|
|
5499
|
+
var PluginEntrySchema = looseObject({
|
|
5500
|
+
pluginId: string(),
|
|
5501
|
+
installed: boolean().optional(),
|
|
5502
|
+
enabled: boolean().optional()
|
|
5503
|
+
});
|
|
5504
|
+
var PluginListSchema = looseObject({
|
|
5505
|
+
installed: array(PluginEntrySchema),
|
|
5506
|
+
available: array(PluginEntrySchema)
|
|
5507
|
+
});
|
|
5508
|
+
var PluginAddSchema = looseObject({ pluginId: string() });
|
|
5509
|
+
/** Installs or enables the official Codex Security plugin without failing HolyCodex installation. */
|
|
5510
|
+
async function installCodexSecurity(runProcess = runManagedProcess, platform = process.platform, env = process.env) {
|
|
5511
|
+
const listed = await runCodexPlugin(runProcess, [
|
|
5512
|
+
"plugin",
|
|
5513
|
+
"list",
|
|
5514
|
+
"--available",
|
|
5515
|
+
"--json"
|
|
5516
|
+
], platform, env);
|
|
5517
|
+
const listFailure = externalFailure(listed);
|
|
5518
|
+
if (listFailure !== void 0) return listFailure;
|
|
5519
|
+
const parsedList = parseJson(listed.stdout, PluginListSchema);
|
|
5520
|
+
if (parsedList === void 0) return skipped("invalid-response");
|
|
5521
|
+
const installed = parsedList.installed.find((plugin) => plugin.pluginId === CODEX_SECURITY_PLUGIN);
|
|
5522
|
+
if (installed?.installed === true && installed.enabled === true) return { status: "already-installed" };
|
|
5523
|
+
const wasDisabled = installed?.installed === true;
|
|
5524
|
+
const available = parsedList.available.some((plugin) => plugin.pluginId === CODEX_SECURITY_PLUGIN);
|
|
5525
|
+
if (!wasDisabled && !available) return skipped("plugin-unavailable");
|
|
5526
|
+
const added = await runCodexPlugin(runProcess, [
|
|
5527
|
+
"plugin",
|
|
5528
|
+
"add",
|
|
5529
|
+
CODEX_SECURITY_PLUGIN,
|
|
5530
|
+
"--json"
|
|
5531
|
+
], platform, env);
|
|
5532
|
+
const addFailure = externalFailure(added);
|
|
5533
|
+
if (addFailure !== void 0) return addFailure;
|
|
5534
|
+
if (parseJson(added.stdout, PluginAddSchema)?.pluginId !== CODEX_SECURITY_PLUGIN) return skipped("invalid-response");
|
|
5535
|
+
return { status: wasDisabled ? "enabled" : "installed" };
|
|
5536
|
+
}
|
|
5537
|
+
async function runCodexPlugin(runProcess, args, platform, env) {
|
|
5538
|
+
try {
|
|
5539
|
+
return await runProcess({
|
|
5540
|
+
command: "codex",
|
|
5541
|
+
args,
|
|
5542
|
+
platform,
|
|
5543
|
+
timeoutMs: CODEX_PLUGIN_TIMEOUT_MS,
|
|
5544
|
+
maxOutputChars: MAX_CODEX_OUTPUT_CHARS,
|
|
5545
|
+
env
|
|
5546
|
+
});
|
|
5547
|
+
} catch (error) {
|
|
5548
|
+
if (!isUnavailableProcessError(error)) throw error;
|
|
5549
|
+
return {
|
|
5550
|
+
exitCode: null,
|
|
5551
|
+
stdout: "",
|
|
5552
|
+
stderr: "",
|
|
5553
|
+
timedOut: false,
|
|
5554
|
+
matched: false,
|
|
5555
|
+
outputTruncated: false,
|
|
5556
|
+
error: "Codex executable unavailable."
|
|
5557
|
+
};
|
|
5558
|
+
}
|
|
5559
|
+
}
|
|
5560
|
+
function externalFailure(result) {
|
|
5561
|
+
if (result.timedOut) return skipped("timeout");
|
|
5562
|
+
if (result.error !== void 0) return skipped("codex-unavailable");
|
|
5563
|
+
if (result.exitCode === 0) return void 0;
|
|
5564
|
+
const diagnostic = parseUnknownJson(result.stderr) ?? parseUnknownJson(result.stdout);
|
|
5565
|
+
if (diagnostic === void 0) return skipped("invalid-response");
|
|
5566
|
+
return skipped(classifyStructuredFailure(diagnostic));
|
|
5567
|
+
}
|
|
5568
|
+
function classifyStructuredFailure(value) {
|
|
5569
|
+
const code = structuredErrorCode(value);
|
|
5570
|
+
if (code === void 0) return "invalid-response";
|
|
5571
|
+
if ([
|
|
5572
|
+
"401",
|
|
5573
|
+
"UNAUTHENTICATED",
|
|
5574
|
+
"AUTHENTICATION_REQUIRED"
|
|
5575
|
+
].includes(code)) return "unauthenticated";
|
|
5576
|
+
if ([
|
|
5577
|
+
"502",
|
|
5578
|
+
"503",
|
|
5579
|
+
"504",
|
|
5580
|
+
"MARKETPLACE_UNAVAILABLE",
|
|
5581
|
+
"MARKETPLACE_LOAD_FAILED",
|
|
5582
|
+
"CATALOG_UNAVAILABLE"
|
|
5583
|
+
].includes(code)) return "marketplace-unavailable";
|
|
5584
|
+
if ([
|
|
5585
|
+
"404",
|
|
5586
|
+
"PLUGIN_NOT_FOUND",
|
|
5587
|
+
"PLUGIN_UNAVAILABLE"
|
|
5588
|
+
].includes(code)) return "plugin-unavailable";
|
|
5589
|
+
if ([
|
|
5590
|
+
"403",
|
|
5591
|
+
"INSTALLATION_REJECTED",
|
|
5592
|
+
"PERMISSION_DENIED",
|
|
5593
|
+
"POLICY_REJECTED",
|
|
5594
|
+
"ACCOUNT_RESTRICTED"
|
|
5595
|
+
].includes(code)) return "installation-rejected";
|
|
5596
|
+
return "invalid-response";
|
|
5597
|
+
}
|
|
5598
|
+
function structuredErrorCode(value) {
|
|
5599
|
+
if (!isRecord(value)) return void 0;
|
|
5600
|
+
const nested = value.error;
|
|
5601
|
+
if (nested !== void 0) {
|
|
5602
|
+
const nestedCode = structuredErrorCode(nested);
|
|
5603
|
+
if (nestedCode !== void 0) return nestedCode;
|
|
5604
|
+
}
|
|
5605
|
+
for (const key of [
|
|
5606
|
+
"code",
|
|
5607
|
+
"status",
|
|
5608
|
+
"statusCode"
|
|
5609
|
+
]) {
|
|
5610
|
+
const candidate = value[key];
|
|
5611
|
+
if (typeof candidate === "string" || typeof candidate === "number") return String(candidate).trim().toUpperCase();
|
|
5612
|
+
}
|
|
5613
|
+
}
|
|
5614
|
+
function parseJson(input, schema) {
|
|
5615
|
+
const value = parseUnknownJson(input);
|
|
5616
|
+
if (value === void 0) return void 0;
|
|
5617
|
+
const parsed = schema.safeParse(value);
|
|
5618
|
+
return parsed.success ? parsed.data : void 0;
|
|
5619
|
+
}
|
|
5620
|
+
function parseUnknownJson(input) {
|
|
5621
|
+
try {
|
|
5622
|
+
return JSON.parse(input);
|
|
5623
|
+
} catch {
|
|
5624
|
+
return;
|
|
5625
|
+
}
|
|
5626
|
+
}
|
|
5627
|
+
function isRecord(value) {
|
|
5628
|
+
return typeof value === "object" && value !== null;
|
|
5629
|
+
}
|
|
5630
|
+
function isUnavailableProcessError(value) {
|
|
5631
|
+
if (!isRecord(value)) return false;
|
|
5632
|
+
return [
|
|
5633
|
+
"EACCES",
|
|
5634
|
+
"ENOENT",
|
|
5635
|
+
"EPERM"
|
|
5636
|
+
].includes(String(value.code).toUpperCase());
|
|
5637
|
+
}
|
|
5638
|
+
function skipped(reason) {
|
|
5639
|
+
return {
|
|
5640
|
+
status: "skipped",
|
|
5641
|
+
reason
|
|
5642
|
+
};
|
|
5643
|
+
}
|
|
5644
|
+
//#endregion
|
|
5427
5645
|
//#region packages/cli/src/files.ts
|
|
5428
5646
|
/** Provides exists. */
|
|
5429
5647
|
async function exists(path) {
|
|
@@ -5471,7 +5689,8 @@ async function readText(path) {
|
|
|
5471
5689
|
//#region packages/cli/src/install.ts
|
|
5472
5690
|
var defaultRuntime = {
|
|
5473
5691
|
platform: process.platform,
|
|
5474
|
-
gitBash: resolveGitBashForCurrentProcess
|
|
5692
|
+
gitBash: resolveGitBashForCurrentProcess,
|
|
5693
|
+
runProcess: runManagedProcess
|
|
5475
5694
|
};
|
|
5476
5695
|
function paths(home = process.env.CODEX_HOME ?? join(homedir(), ".codex")) {
|
|
5477
5696
|
const marketplaceCache = join(home, "plugins", "cache", "holycodex");
|
|
@@ -5536,6 +5755,7 @@ async function install(options, runtime = defaultRuntime) {
|
|
|
5536
5755
|
await rm(path, { recursive: true });
|
|
5537
5756
|
removedLegacy.push(path);
|
|
5538
5757
|
}
|
|
5758
|
+
const codexSecurity = await installCodexSecurity(runtime.runProcess, runtime.platform, process.env);
|
|
5539
5759
|
return {
|
|
5540
5760
|
action: "install",
|
|
5541
5761
|
changed: [
|
|
@@ -5546,6 +5766,7 @@ async function install(options, runtime = defaultRuntime) {
|
|
|
5546
5766
|
],
|
|
5547
5767
|
backups,
|
|
5548
5768
|
plan,
|
|
5769
|
+
codexSecurity,
|
|
5549
5770
|
...options.maxSubagents === void 0 ? {} : { maxSubagents: options.maxSubagents }
|
|
5550
5771
|
};
|
|
5551
5772
|
}
|
|
@@ -5728,7 +5949,14 @@ function renderRunResult(result, color) {
|
|
|
5728
5949
|
const action = result.action === "install" ? "Updated" : "Removed";
|
|
5729
5950
|
const empty = result.action === "install" ? "changes" : "removal";
|
|
5730
5951
|
const backup = result.backups.length === 0 ? "" : `\n Existing HolyCodex files were backed up before ${result.action === "install" ? "replacement" : "cleanup"}.`;
|
|
5731
|
-
return `${title}\n ${result.changed.length === 0 ? `No HolyCodex-managed files needed ${empty}.` : `${action} HolyCodex configuration, plugin files, and agent profiles.`}${backup}\n`;
|
|
5952
|
+
return `${title}\n ${result.changed.length === 0 ? `No HolyCodex-managed files needed ${empty}.` : `${action} HolyCodex configuration, plugin files, and agent profiles.`}${backup}${renderCodexSecurity(result)}\n`;
|
|
5953
|
+
}
|
|
5954
|
+
function renderCodexSecurity(result) {
|
|
5955
|
+
if (result.codexSecurity === void 0) return "";
|
|
5956
|
+
if (result.codexSecurity.status === "installed") return "\n Installed official Codex Security plugin.";
|
|
5957
|
+
if (result.codexSecurity.status === "enabled") return "\n Enabled existing official Codex Security plugin.";
|
|
5958
|
+
if (result.codexSecurity.status === "already-installed") return "\n Official Codex Security plugin is already installed and enabled.";
|
|
5959
|
+
return `\n Skipped official Codex Security plugin: ${result.codexSecurity.reason}.`;
|
|
5732
5960
|
}
|
|
5733
5961
|
/** Renders notice. */
|
|
5734
5962
|
function renderNotice(kind, message, color) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "holycodex",
|
|
3
|
-
"version": "0.10.
|
|
3
|
+
"version": "0.10.3",
|
|
4
4
|
"description": "Lean Codex-only agent toolkit installer and doctor",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"agents",
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
"prepack": "vp run --workspace-root build"
|
|
40
40
|
},
|
|
41
41
|
"dependencies": {
|
|
42
|
-
"@holycodex/plugin": "0.10.
|
|
42
|
+
"@holycodex/plugin": "0.10.3",
|
|
43
43
|
"zod": "^4.4.3"
|
|
44
44
|
},
|
|
45
45
|
"engines": {
|