holycodex 0.8.1 → 0.8.2-dev.29763019035.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.
- package/THIRD-PARTY-NOTICES.md +0 -2
- package/dist/cli.js +188 -220
- package/package.json +2 -2
package/THIRD-PARTY-NOTICES.md
CHANGED
|
@@ -9,5 +9,3 @@ The caveman communication concept is adapted from [juliusbrussee/caveman](https:
|
|
|
9
9
|
HolyCodex agent routing and orchestration instructions adapt bounded-role, task-ownership, non-overlapping-write, session-reuse, and verification-planning concepts from [alvinunreal/oh-my-opencode-slim](https://github.com/alvinunreal/oh-my-opencode-slim) at commit `7bc7b56856ee693812d87d68615757d4d1c2e218`, principally `src/agents/{orchestrator,explorer,librarian,fixer}.ts`, `src/skills/verification-planning/SKILL.md`, and `docs/background-orchestration.md`. OpenCode runtime APIs, hooks, council, ACP, companion, and background-session mechanics were not copied. Upstream material is MIT licensed; its license is preserved in `packages/plugin/plugin/LICENSE-OH-MY-OPENCODE-SLIM-MIT.txt`.
|
|
10
10
|
|
|
11
11
|
The bundled LSP runtime at `packages/plugin/plugin/runtime/lsp.js` is derived from `code-yeongyu/oh-my-openagent`'s `lsp-tools-mcp`. Copyright (c) 2026 Yeongyu Kim; used under the MIT License preserved at `packages/plugin/plugin/runtime/LICENSE-LSP-MIT.txt`.
|
|
12
|
-
|
|
13
|
-
The `codexslimedit` package and HolyCodex integration adapt compact-read and line-range edit behavior from [ASidorenkoCode/openslimedit](https://github.com/ASidorenkoCode/openslimedit) at commit `d5014929d6f66729b887df74a65ed6d22c3b522b`. Copyright (c) 2026 Artur; used under the MIT License preserved in both published packages. OpenCode hook APIs and token-saving claims were not copied.
|
package/dist/cli.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import process$1 from "node:process";
|
|
2
|
-
import { execFileSync, spawn, spawnSync } from "node:child_process";
|
|
3
2
|
import { access, copyFile, cp, lstat, mkdir, readFile, readdir, readlink, rename, rm, stat, writeFile } from "node:fs/promises";
|
|
4
3
|
import { homedir, tmpdir } from "node:os";
|
|
5
4
|
import { dirname, join } from "node:path";
|
|
5
|
+
import { execFileSync, spawn, spawnSync } from "node:child_process";
|
|
6
6
|
import { existsSync } from "node:fs";
|
|
7
7
|
import { Buffer } from "node:buffer";
|
|
8
8
|
import { pluginRoot } from "@holycodex/plugin";
|
|
@@ -3924,170 +3924,8 @@ function superRefine(fn, params) {
|
|
|
3924
3924
|
return /* @__PURE__ */ _superRefine(fn, params);
|
|
3925
3925
|
}
|
|
3926
3926
|
//#endregion
|
|
3927
|
-
//#region packages/mcp-stdio-core/src/process.ts
|
|
3928
|
-
var TRUNCATED_MARKER = "\n... diagnostic output truncated ...\n";
|
|
3929
|
-
var defaultManagedProcessRuntime = {
|
|
3930
|
-
terminationGraceMs: 2e3,
|
|
3931
|
-
kill: killProcessTree
|
|
3932
|
-
};
|
|
3933
|
-
/** Runs managed process. */
|
|
3934
|
-
async function runManagedProcess(input, runtime = defaultManagedProcessRuntime) {
|
|
3935
|
-
return await new Promise((resolve) => {
|
|
3936
|
-
const child = spawn(input.command, [...input.args], {
|
|
3937
|
-
...input.cwd === void 0 ? {} : { cwd: input.cwd },
|
|
3938
|
-
...input.env === void 0 ? {} : { env: input.env },
|
|
3939
|
-
stdio: [
|
|
3940
|
-
"pipe",
|
|
3941
|
-
"pipe",
|
|
3942
|
-
"pipe"
|
|
3943
|
-
],
|
|
3944
|
-
windowsHide: true,
|
|
3945
|
-
detached: input.platform !== "win32"
|
|
3946
|
-
});
|
|
3947
|
-
let stdout = {
|
|
3948
|
-
head: "",
|
|
3949
|
-
tail: "",
|
|
3950
|
-
truncated: false
|
|
3951
|
-
};
|
|
3952
|
-
let stderr = {
|
|
3953
|
-
head: "",
|
|
3954
|
-
tail: "",
|
|
3955
|
-
truncated: false
|
|
3956
|
-
};
|
|
3957
|
-
let timedOut = false;
|
|
3958
|
-
let matched = false;
|
|
3959
|
-
let settled = false;
|
|
3960
|
-
let forceKillTimeout;
|
|
3961
|
-
const finish = (exitCode, error) => {
|
|
3962
|
-
if (settled) return;
|
|
3963
|
-
settled = true;
|
|
3964
|
-
clearTimeout(timeout);
|
|
3965
|
-
if (forceKillTimeout !== void 0) clearTimeout(forceKillTimeout);
|
|
3966
|
-
resolve({
|
|
3967
|
-
exitCode,
|
|
3968
|
-
stdout: outputText(stdout),
|
|
3969
|
-
stderr: outputText(stderr),
|
|
3970
|
-
timedOut,
|
|
3971
|
-
matched,
|
|
3972
|
-
outputTruncated: stdout.truncated || stderr.truncated,
|
|
3973
|
-
...error === void 0 ? {} : { error }
|
|
3974
|
-
});
|
|
3975
|
-
};
|
|
3976
|
-
const terminate = () => {
|
|
3977
|
-
if (forceKillTimeout !== void 0) return;
|
|
3978
|
-
runtime.kill(child, input.platform, "SIGTERM");
|
|
3979
|
-
forceKillTimeout = setTimeout(() => {
|
|
3980
|
-
runtime.kill(child, input.platform, "SIGKILL");
|
|
3981
|
-
}, runtime.terminationGraceMs);
|
|
3982
|
-
forceKillTimeout.unref();
|
|
3983
|
-
};
|
|
3984
|
-
const inspectMatch = () => {
|
|
3985
|
-
if (matched || input.matchOutput === void 0) return;
|
|
3986
|
-
if (input.matchOutput(`${outputText(stdout)}\n${outputText(stderr)}`)) {
|
|
3987
|
-
matched = true;
|
|
3988
|
-
terminate();
|
|
3989
|
-
}
|
|
3990
|
-
};
|
|
3991
|
-
child.stdout.on("data", (chunk) => {
|
|
3992
|
-
stdout = appendOutput(stdout, chunk.toString(), input.maxOutputChars);
|
|
3993
|
-
inspectMatch();
|
|
3994
|
-
});
|
|
3995
|
-
child.stderr.on("data", (chunk) => {
|
|
3996
|
-
stderr = appendOutput(stderr, chunk.toString(), input.maxOutputChars);
|
|
3997
|
-
inspectMatch();
|
|
3998
|
-
});
|
|
3999
|
-
child.once("error", (error) => finish(null, error.message));
|
|
4000
|
-
child.once("close", (code) => finish(code));
|
|
4001
|
-
const timeout = setTimeout(() => {
|
|
4002
|
-
timedOut = true;
|
|
4003
|
-
terminate();
|
|
4004
|
-
}, input.timeoutMs);
|
|
4005
|
-
timeout.unref();
|
|
4006
|
-
if (input.stdin === void 0) child.stdin.end();
|
|
4007
|
-
else child.stdin.end(input.stdin);
|
|
4008
|
-
});
|
|
4009
|
-
}
|
|
4010
|
-
/** Terminates process tree. */
|
|
4011
|
-
function killProcessTree(child, platform, signal = "SIGTERM", runTaskkill = (command, args) => spawnSync(command, [...args], {
|
|
4012
|
-
stdio: "ignore",
|
|
4013
|
-
windowsHide: true
|
|
4014
|
-
})) {
|
|
4015
|
-
if (platform === "win32" && child.pid !== void 0) {
|
|
4016
|
-
const result = runTaskkill("taskkill", [
|
|
4017
|
-
"/pid",
|
|
4018
|
-
String(child.pid),
|
|
4019
|
-
"/f",
|
|
4020
|
-
"/t"
|
|
4021
|
-
]);
|
|
4022
|
-
if (result.error === void 0 && result.status === 0) return;
|
|
4023
|
-
}
|
|
4024
|
-
if (platform !== "win32" && child.pid !== void 0) try {
|
|
4025
|
-
process.kill(-child.pid, signal);
|
|
4026
|
-
return;
|
|
4027
|
-
} catch {}
|
|
4028
|
-
try {
|
|
4029
|
-
child.kill(signal);
|
|
4030
|
-
} catch {}
|
|
4031
|
-
}
|
|
4032
|
-
function appendOutput(state, chunk, limit) {
|
|
4033
|
-
const safeLimit = Math.max(1, limit);
|
|
4034
|
-
const headLimit = Math.ceil(safeLimit / 2);
|
|
4035
|
-
const tailLimit = Math.floor(safeLimit / 2);
|
|
4036
|
-
if (!state.truncated && state.head.length + chunk.length <= safeLimit) return {
|
|
4037
|
-
...state,
|
|
4038
|
-
head: state.head + chunk
|
|
4039
|
-
};
|
|
4040
|
-
const combined = state.truncated ? chunk : state.head + chunk;
|
|
4041
|
-
return {
|
|
4042
|
-
head: state.truncated ? state.head : combined.slice(0, headLimit),
|
|
4043
|
-
tail: `${state.tail}${combined.slice(state.truncated ? 0 : headLimit)}`.slice(-tailLimit),
|
|
4044
|
-
truncated: true
|
|
4045
|
-
};
|
|
4046
|
-
}
|
|
4047
|
-
function outputText(state) {
|
|
4048
|
-
return state.truncated ? `${state.head}${TRUNCATED_MARKER}${state.tail}` : state.head;
|
|
4049
|
-
}
|
|
4050
|
-
//#endregion
|
|
4051
|
-
//#region packages/cli/src/package-runner.ts
|
|
4052
|
-
var PACKAGE_INSTALL_TIMEOUT_MS = 12e4;
|
|
4053
|
-
var PACKAGE_INSTALL_OUTPUT_LIMIT = 4e3;
|
|
4054
|
-
/** Detects whether Bun or npm invoked HolyCodex. */
|
|
4055
|
-
function detectPackageRunner(env = process.env) {
|
|
4056
|
-
const executable = (env.npm_execpath ?? "").split(/[\\/]/).at(-1)?.toLowerCase().replace(/\.exe$/, "");
|
|
4057
|
-
const userAgent = env.npm_config_user_agent?.trim().split(/[\s/]/, 1)[0]?.toLowerCase();
|
|
4058
|
-
return executable === "bun" || userAgent === "bun" ? "bun" : "npm";
|
|
4059
|
-
}
|
|
4060
|
-
/** Builds the runner-specific codexslimedit invocation. */
|
|
4061
|
-
function codexSlimEditInvocation(input) {
|
|
4062
|
-
const args = [input.packageVersion.includes("-dev.") ? "codexslimedit@dev" : "codexslimedit@latest", ...input.includeVersion ? ["--version"] : []];
|
|
4063
|
-
return input.packageRunner === "bun" ? {
|
|
4064
|
-
command: "bunx",
|
|
4065
|
-
args
|
|
4066
|
-
} : {
|
|
4067
|
-
command: input.platform === "win32" ? "npx.cmd" : "npx",
|
|
4068
|
-
args: ["--yes", ...args]
|
|
4069
|
-
};
|
|
4070
|
-
}
|
|
4071
|
-
/** Pre-resolves codexslimedit through the invoking package runner. */
|
|
4072
|
-
async function installCodexSlimEdit(input, env = process.env) {
|
|
4073
|
-
if (env.NODE_ENV === "test" && env.HOLYCODEX_TEST_SKIP_PACKAGE_RESOLUTION === "1") return;
|
|
4074
|
-
const invocation = codexSlimEditInvocation({
|
|
4075
|
-
...input,
|
|
4076
|
-
includeVersion: true
|
|
4077
|
-
});
|
|
4078
|
-
const result = await runManagedProcess({
|
|
4079
|
-
...invocation,
|
|
4080
|
-
platform: input.platform,
|
|
4081
|
-
timeoutMs: PACKAGE_INSTALL_TIMEOUT_MS,
|
|
4082
|
-
maxOutputChars: PACKAGE_INSTALL_OUTPUT_LIMIT
|
|
4083
|
-
});
|
|
4084
|
-
if (result.exitCode === 0 && !result.timedOut) return;
|
|
4085
|
-
const detail = result.error ?? (result.stderr.trim() || result.stdout.trim() || "unknown package error");
|
|
4086
|
-
throw new Error(`Could not install codexslimedit with ${invocation.command}: ${detail}. Check package registry and network access, then retry HolyCodex installation.`);
|
|
4087
|
-
}
|
|
4088
|
-
//#endregion
|
|
4089
3927
|
//#region packages/cli/src/catalog.ts
|
|
4090
|
-
var VERSION = "0.8.1";
|
|
3928
|
+
var VERSION = "0.8.2-dev.29763019035.1";
|
|
4091
3929
|
var SKILLS = [
|
|
4092
3930
|
"ast-grep",
|
|
4093
3931
|
"caveman",
|
|
@@ -4161,7 +3999,12 @@ var RoutingPresetSchema = strictObject({
|
|
|
4161
3999
|
worker: ModelRouteSchema
|
|
4162
4000
|
}),
|
|
4163
4001
|
usage: strictObject({
|
|
4164
|
-
|
|
4002
|
+
maxSubagents: union([
|
|
4003
|
+
literal(0),
|
|
4004
|
+
literal(1),
|
|
4005
|
+
literal(2),
|
|
4006
|
+
literal(3)
|
|
4007
|
+
]),
|
|
4165
4008
|
maxDepth: literal(1)
|
|
4166
4009
|
})
|
|
4167
4010
|
});
|
|
@@ -4195,7 +4038,7 @@ var MODEL_ROUTING_PLANS = ModelRoutingPlansSchema.parse({
|
|
|
4195
4038
|
}
|
|
4196
4039
|
},
|
|
4197
4040
|
usage: {
|
|
4198
|
-
|
|
4041
|
+
maxSubagents: 0,
|
|
4199
4042
|
maxDepth: 1
|
|
4200
4043
|
}
|
|
4201
4044
|
},
|
|
@@ -4219,14 +4062,14 @@ var MODEL_ROUTING_PLANS = ModelRoutingPlansSchema.parse({
|
|
|
4219
4062
|
}
|
|
4220
4063
|
},
|
|
4221
4064
|
usage: {
|
|
4222
|
-
|
|
4065
|
+
maxSubagents: 1,
|
|
4223
4066
|
maxDepth: 1
|
|
4224
4067
|
}
|
|
4225
4068
|
},
|
|
4226
4069
|
plus: {
|
|
4227
4070
|
root: {
|
|
4228
4071
|
model: "gpt-5.6-sol",
|
|
4229
|
-
reasoningEffort: "
|
|
4072
|
+
reasoningEffort: "low"
|
|
4230
4073
|
},
|
|
4231
4074
|
agents: {
|
|
4232
4075
|
explorer: {
|
|
@@ -4243,7 +4086,7 @@ var MODEL_ROUTING_PLANS = ModelRoutingPlansSchema.parse({
|
|
|
4243
4086
|
}
|
|
4244
4087
|
},
|
|
4245
4088
|
usage: {
|
|
4246
|
-
|
|
4089
|
+
maxSubagents: 2,
|
|
4247
4090
|
maxDepth: 1
|
|
4248
4091
|
}
|
|
4249
4092
|
},
|
|
@@ -4267,7 +4110,7 @@ var MODEL_ROUTING_PLANS = ModelRoutingPlansSchema.parse({
|
|
|
4267
4110
|
}
|
|
4268
4111
|
},
|
|
4269
4112
|
usage: {
|
|
4270
|
-
|
|
4113
|
+
maxSubagents: 2,
|
|
4271
4114
|
maxDepth: 1
|
|
4272
4115
|
}
|
|
4273
4116
|
},
|
|
@@ -4291,7 +4134,7 @@ var MODEL_ROUTING_PLANS = ModelRoutingPlansSchema.parse({
|
|
|
4291
4134
|
}
|
|
4292
4135
|
},
|
|
4293
4136
|
usage: {
|
|
4294
|
-
|
|
4137
|
+
maxSubagents: 2,
|
|
4295
4138
|
maxDepth: 1
|
|
4296
4139
|
}
|
|
4297
4140
|
},
|
|
@@ -4315,7 +4158,7 @@ var MODEL_ROUTING_PLANS = ModelRoutingPlansSchema.parse({
|
|
|
4315
4158
|
}
|
|
4316
4159
|
},
|
|
4317
4160
|
usage: {
|
|
4318
|
-
|
|
4161
|
+
maxSubagents: 2,
|
|
4319
4162
|
maxDepth: 1
|
|
4320
4163
|
}
|
|
4321
4164
|
}
|
|
@@ -4455,19 +4298,13 @@ var GENERATED_RUNTIMES = [
|
|
|
4455
4298
|
"git-bash.js",
|
|
4456
4299
|
"git-bash-resolver.js",
|
|
4457
4300
|
"LICENSE-LSP-MIT.txt",
|
|
4458
|
-
"LICENSE-OPENSLIMEDIT-MIT.txt",
|
|
4459
4301
|
"lsp.js",
|
|
4460
4302
|
"mcp-stdio-core.js",
|
|
4461
4303
|
"rules.js"
|
|
4462
4304
|
];
|
|
4463
4305
|
var WINDOWS_SHELL_POLICY = "On native Windows, before the first shell action, inspect callable and deferred tools until `mcp__git_bash__run` is resolved. Use it for every shell command, including Git, Bash, POSIX, package, build, test, and script commands. If unavailable, stop and report the blocker. Never fall back to PowerShell or cmd.";
|
|
4464
4306
|
/** Provides effective mcp servers. */
|
|
4465
|
-
function effectiveMcpServers(platform
|
|
4466
|
-
const codexSlimEdit = codexSlimEditInvocation({
|
|
4467
|
-
packageRunner,
|
|
4468
|
-
platform,
|
|
4469
|
-
packageVersion: VERSION
|
|
4470
|
-
});
|
|
4307
|
+
function effectiveMcpServers(platform) {
|
|
4471
4308
|
return {
|
|
4472
4309
|
...platform === "win32" ? { git_bash: {
|
|
4473
4310
|
command: "node",
|
|
@@ -4480,10 +4317,6 @@ function effectiveMcpServers(platform, packageRunner = "bun") {
|
|
|
4480
4317
|
args: ["runtime/lsp.js", "mcp"],
|
|
4481
4318
|
cwd: "."
|
|
4482
4319
|
},
|
|
4483
|
-
codexslimedit: {
|
|
4484
|
-
...codexSlimEdit,
|
|
4485
|
-
enabled_tools: ["read_file", "apply_patch"]
|
|
4486
|
-
},
|
|
4487
4320
|
context7: {
|
|
4488
4321
|
command: "bunx",
|
|
4489
4322
|
args: ["@upstash/context7-mcp"]
|
|
@@ -4576,6 +4409,130 @@ function missing(checkedPaths) {
|
|
|
4576
4409
|
};
|
|
4577
4410
|
}
|
|
4578
4411
|
//#endregion
|
|
4412
|
+
//#region packages/mcp-stdio-core/src/process.ts
|
|
4413
|
+
var TRUNCATED_MARKER = "\n... diagnostic output truncated ...\n";
|
|
4414
|
+
var defaultManagedProcessRuntime = {
|
|
4415
|
+
terminationGraceMs: 2e3,
|
|
4416
|
+
kill: killProcessTree
|
|
4417
|
+
};
|
|
4418
|
+
/** Runs managed process. */
|
|
4419
|
+
async function runManagedProcess(input, runtime = defaultManagedProcessRuntime) {
|
|
4420
|
+
return await new Promise((resolve) => {
|
|
4421
|
+
const child = spawn(input.command, [...input.args], {
|
|
4422
|
+
...input.cwd === void 0 ? {} : { cwd: input.cwd },
|
|
4423
|
+
...input.env === void 0 ? {} : { env: input.env },
|
|
4424
|
+
stdio: [
|
|
4425
|
+
"pipe",
|
|
4426
|
+
"pipe",
|
|
4427
|
+
"pipe"
|
|
4428
|
+
],
|
|
4429
|
+
windowsHide: true,
|
|
4430
|
+
detached: input.platform !== "win32"
|
|
4431
|
+
});
|
|
4432
|
+
let stdout = {
|
|
4433
|
+
head: "",
|
|
4434
|
+
tail: "",
|
|
4435
|
+
truncated: false
|
|
4436
|
+
};
|
|
4437
|
+
let stderr = {
|
|
4438
|
+
head: "",
|
|
4439
|
+
tail: "",
|
|
4440
|
+
truncated: false
|
|
4441
|
+
};
|
|
4442
|
+
let timedOut = false;
|
|
4443
|
+
let matched = false;
|
|
4444
|
+
let settled = false;
|
|
4445
|
+
let forceKillTimeout;
|
|
4446
|
+
const finish = (exitCode, error) => {
|
|
4447
|
+
if (settled) return;
|
|
4448
|
+
settled = true;
|
|
4449
|
+
clearTimeout(timeout);
|
|
4450
|
+
if (forceKillTimeout !== void 0) clearTimeout(forceKillTimeout);
|
|
4451
|
+
resolve({
|
|
4452
|
+
exitCode,
|
|
4453
|
+
stdout: outputText(stdout),
|
|
4454
|
+
stderr: outputText(stderr),
|
|
4455
|
+
timedOut,
|
|
4456
|
+
matched,
|
|
4457
|
+
outputTruncated: stdout.truncated || stderr.truncated,
|
|
4458
|
+
...error === void 0 ? {} : { error }
|
|
4459
|
+
});
|
|
4460
|
+
};
|
|
4461
|
+
const terminate = () => {
|
|
4462
|
+
if (forceKillTimeout !== void 0) return;
|
|
4463
|
+
runtime.kill(child, input.platform, "SIGTERM");
|
|
4464
|
+
forceKillTimeout = setTimeout(() => {
|
|
4465
|
+
runtime.kill(child, input.platform, "SIGKILL");
|
|
4466
|
+
}, runtime.terminationGraceMs);
|
|
4467
|
+
forceKillTimeout.unref();
|
|
4468
|
+
};
|
|
4469
|
+
const inspectMatch = () => {
|
|
4470
|
+
if (matched || input.matchOutput === void 0) return;
|
|
4471
|
+
if (input.matchOutput(`${outputText(stdout)}\n${outputText(stderr)}`)) {
|
|
4472
|
+
matched = true;
|
|
4473
|
+
terminate();
|
|
4474
|
+
}
|
|
4475
|
+
};
|
|
4476
|
+
child.stdout.on("data", (chunk) => {
|
|
4477
|
+
stdout = appendOutput(stdout, chunk.toString(), input.maxOutputChars);
|
|
4478
|
+
inspectMatch();
|
|
4479
|
+
});
|
|
4480
|
+
child.stderr.on("data", (chunk) => {
|
|
4481
|
+
stderr = appendOutput(stderr, chunk.toString(), input.maxOutputChars);
|
|
4482
|
+
inspectMatch();
|
|
4483
|
+
});
|
|
4484
|
+
child.once("error", (error) => finish(null, error.message));
|
|
4485
|
+
child.once("close", (code) => finish(code));
|
|
4486
|
+
const timeout = setTimeout(() => {
|
|
4487
|
+
timedOut = true;
|
|
4488
|
+
terminate();
|
|
4489
|
+
}, input.timeoutMs);
|
|
4490
|
+
timeout.unref();
|
|
4491
|
+
if (input.stdin === void 0) child.stdin.end();
|
|
4492
|
+
else child.stdin.end(input.stdin);
|
|
4493
|
+
});
|
|
4494
|
+
}
|
|
4495
|
+
/** Terminates process tree. */
|
|
4496
|
+
function killProcessTree(child, platform, signal = "SIGTERM", runTaskkill = (command, args) => spawnSync(command, [...args], {
|
|
4497
|
+
stdio: "ignore",
|
|
4498
|
+
windowsHide: true
|
|
4499
|
+
})) {
|
|
4500
|
+
if (platform === "win32" && child.pid !== void 0) {
|
|
4501
|
+
const result = runTaskkill("taskkill", [
|
|
4502
|
+
"/pid",
|
|
4503
|
+
String(child.pid),
|
|
4504
|
+
"/f",
|
|
4505
|
+
"/t"
|
|
4506
|
+
]);
|
|
4507
|
+
if (result.error === void 0 && result.status === 0) return;
|
|
4508
|
+
}
|
|
4509
|
+
if (platform !== "win32" && child.pid !== void 0) try {
|
|
4510
|
+
process.kill(-child.pid, signal);
|
|
4511
|
+
return;
|
|
4512
|
+
} catch {}
|
|
4513
|
+
try {
|
|
4514
|
+
child.kill(signal);
|
|
4515
|
+
} catch {}
|
|
4516
|
+
}
|
|
4517
|
+
function appendOutput(state, chunk, limit) {
|
|
4518
|
+
const safeLimit = Math.max(1, limit);
|
|
4519
|
+
const headLimit = Math.ceil(safeLimit / 2);
|
|
4520
|
+
const tailLimit = Math.floor(safeLimit / 2);
|
|
4521
|
+
if (!state.truncated && state.head.length + chunk.length <= safeLimit) return {
|
|
4522
|
+
...state,
|
|
4523
|
+
head: state.head + chunk
|
|
4524
|
+
};
|
|
4525
|
+
const combined = state.truncated ? chunk : state.head + chunk;
|
|
4526
|
+
return {
|
|
4527
|
+
head: state.truncated ? state.head : combined.slice(0, headLimit),
|
|
4528
|
+
tail: `${state.tail}${combined.slice(state.truncated ? 0 : headLimit)}`.slice(-tailLimit),
|
|
4529
|
+
truncated: true
|
|
4530
|
+
};
|
|
4531
|
+
}
|
|
4532
|
+
function outputText(state) {
|
|
4533
|
+
return state.truncated ? `${state.head}${TRUNCATED_MARKER}${state.tail}` : state.head;
|
|
4534
|
+
}
|
|
4535
|
+
//#endregion
|
|
4579
4536
|
//#region packages/cli/src/toml.ts
|
|
4580
4537
|
var TOML_TABLE = /^[ \t]*(?:\[[^\]\r\n]+\]|\[\[[^\]\r\n]+\]\])[ \t]*(?:#.*)?$/m;
|
|
4581
4538
|
/** Reads a root TOML string value. */
|
|
@@ -4666,6 +4623,7 @@ var END = "# <<< holycodex managed <<<";
|
|
|
4666
4623
|
var ORIGINAL_ROOT = "# holycodex original root: ";
|
|
4667
4624
|
var ORIGINAL_TABLE_KEY = "# holycodex original table key: ";
|
|
4668
4625
|
var PLAN_PREFIX = "# holycodex plan: ";
|
|
4626
|
+
var MAX_SUBAGENTS_PREFIX = "# holycodex max-subagents: ";
|
|
4669
4627
|
var OLD_NAMESPACES = [
|
|
4670
4628
|
"marketplaces.sisyphuslabs",
|
|
4671
4629
|
"plugins.\"omo@sisyphuslabs\"",
|
|
@@ -4743,6 +4701,16 @@ function readManagedPlan(input) {
|
|
|
4743
4701
|
const value = new RegExp(`^${PLAN_PREFIX}(.+)$`, "m").exec(input)?.[1]?.trim();
|
|
4744
4702
|
return PLAN_NAMES.find((plan) => plan === value);
|
|
4745
4703
|
}
|
|
4704
|
+
/** Reads an explicit managed direct-subagent override. */
|
|
4705
|
+
function readManagedMaxSubagents(input) {
|
|
4706
|
+
const raw = new RegExp(`^${MAX_SUBAGENTS_PREFIX}(.*)$`, "m").exec(input)?.[1]?.trim();
|
|
4707
|
+
if (raw === void 0) return { configured: false };
|
|
4708
|
+
if (!/^[0-3]$/.test(raw)) return { configured: true };
|
|
4709
|
+
return {
|
|
4710
|
+
configured: true,
|
|
4711
|
+
value: Number(raw)
|
|
4712
|
+
};
|
|
4713
|
+
}
|
|
4746
4714
|
/** Identifies explicit Root route overrides preserved from active managed configuration. */
|
|
4747
4715
|
function readPreservedRootOverrides(input) {
|
|
4748
4716
|
const managedRoot = new RegExp(`^${START}\\r?\\n([\\s\\S]*?)^${END}\\r?$`, "m").exec(input)?.[1];
|
|
@@ -4797,7 +4765,7 @@ function mergedStatusLine(original) {
|
|
|
4797
4765
|
return `[${items.map((item) => JSON.stringify(item)).join(", ")}]`;
|
|
4798
4766
|
}
|
|
4799
4767
|
/** Installs config. */
|
|
4800
|
-
function installConfig(input, mode, _platform, plan = DEFAULT_PLAN) {
|
|
4768
|
+
function installConfig(input, mode, _platform, plan = DEFAULT_PLAN, maxSubagents) {
|
|
4801
4769
|
const base = preserveManagedRootPreferences(input, removeLegacyOmo(removeManaged(input)));
|
|
4802
4770
|
const firstTable = base.search(/^\s*\[/m);
|
|
4803
4771
|
const root = firstTable < 0 ? base : base.slice(0, firstTable);
|
|
@@ -4814,17 +4782,20 @@ function installConfig(input, mode, _platform, plan = DEFAULT_PLAN) {
|
|
|
4814
4782
|
const hasEffort = /^\s*model_reasoning_effort\s*=/m.test(preservedRoot);
|
|
4815
4783
|
const hasVerbosity = /^\s*model_verbosity\s*=/m.test(preservedRoot);
|
|
4816
4784
|
const rootRoute = MODEL_ROUTING_PLANS[plan].root;
|
|
4785
|
+
const effectiveMaxSubagents = maxSubagents ?? MODEL_ROUTING_PLANS[plan].usage.maxSubagents;
|
|
4817
4786
|
const model = hasModel ? "" : `model = "${rootRoute.model}"\n`;
|
|
4818
4787
|
const effort = hasEffort ? "" : `model_reasoning_effort = "${rootRoute.reasoningEffort}"\n`;
|
|
4819
4788
|
const verbosity = hasVerbosity ? "" : "model_verbosity = \"low\"\n";
|
|
4820
4789
|
const approval = mode === "default" ? "on-request" : "never";
|
|
4821
4790
|
const sandbox = mode === "dangerous" ? "danger-full-access" : "workspace-write";
|
|
4822
|
-
|
|
4791
|
+
const original = originalRoot ? `${ORIGINAL_ROOT}${Buffer.from(originalRoot).toString("base64")}\n` : "";
|
|
4792
|
+
const preserved = preservedRoot ? `${preservedRoot}\n` : "";
|
|
4793
|
+
let configured = `${`${START}\n${PLAN_PREFIX}${plan}\n${maxSubagents === void 0 ? "" : `${MAX_SUBAGENTS_PREFIX}${maxSubagents}\n`}${original}${model}${effort}${verbosity}${preserved}approval_policy = "${approval}"\nsandbox_mode = "${sandbox}"\nstatus_line = ${mergedStatusLine(controlled[3])}\n${END}`}${tables ? `\n\n${tables}` : ""}`;
|
|
4823
4794
|
configured = injectTableKey(configured, "features", "default_mode_request_user_input", "true");
|
|
4824
4795
|
configured = injectTableKey(configured, "features", "multi_agent", "true");
|
|
4825
4796
|
configured = injectTableKey(configured, "features", "multi_agent_v2", "true");
|
|
4826
4797
|
const usage = MODEL_ROUTING_PLANS[plan].usage;
|
|
4827
|
-
configured = injectTableKey(configured, "agents", "max_threads", String(
|
|
4798
|
+
configured = injectTableKey(configured, "agents", "max_threads", String(effectiveMaxSubagents + 1));
|
|
4828
4799
|
configured = injectTableKey(configured, "agents", "max_depth", String(usage.maxDepth));
|
|
4829
4800
|
if (mode !== "dangerous") configured = injectTableKey(configured, "sandbox_workspace_write", "network_access", "true");
|
|
4830
4801
|
for (const agent of AGENTS) configured = injectTableKey(configured, `agents.${agent}`, "config_file", `"holycodex/agents/${agent}.toml"`);
|
|
@@ -4879,10 +4850,7 @@ async function startContext7(platform) {
|
|
|
4879
4850
|
}
|
|
4880
4851
|
var defaultRuntime$1 = {
|
|
4881
4852
|
platform: process.platform,
|
|
4882
|
-
command: (name, args) =>
|
|
4883
|
-
ok: true,
|
|
4884
|
-
output: "package resolution skipped in tests"
|
|
4885
|
-
}) : runCommand(name, args, process.platform),
|
|
4853
|
+
command: (name, args) => runCommand(name, args, process.platform),
|
|
4886
4854
|
context7: () => startContext7(process.platform),
|
|
4887
4855
|
gitBash: resolveGitBashForCurrentProcess
|
|
4888
4856
|
};
|
|
@@ -4937,6 +4905,13 @@ async function doctor(home = process.env.CODEX_HOME ?? join(homedir(), ".codex")
|
|
|
4937
4905
|
const pluginRoot = join(home, "plugins", "cache", "holycodex", "holycodex", VERSION);
|
|
4938
4906
|
const agentRoot = join(home, "holycodex", "agents");
|
|
4939
4907
|
const configPath = join(home, "config.toml");
|
|
4908
|
+
let config = "";
|
|
4909
|
+
let configAvailable = true;
|
|
4910
|
+
try {
|
|
4911
|
+
config = await readFile(configPath, "utf8");
|
|
4912
|
+
} catch {
|
|
4913
|
+
configAvailable = false;
|
|
4914
|
+
}
|
|
4940
4915
|
const missing = await missingFiles(pluginRoot, [
|
|
4941
4916
|
".codex-plugin/plugin.json",
|
|
4942
4917
|
".mcp.json",
|
|
@@ -4961,12 +4936,6 @@ async function doctor(home = process.env.CODEX_HOME ?? join(homedir(), ".codex")
|
|
|
4961
4936
|
const expected = expectedMcps[name];
|
|
4962
4937
|
checks.push(configured === void 0 || expected === void 0 ? check(`mcp-${name}`, "error", "missing-required-mcp", `${name} is not configured.`, "Reinstall HolyCodex.") : !mcpConfigMatches(configured, expected) ? check(`mcp-${name}`, "error", "invalid-required-mcp-config", `${name} configuration is stale or contains unsupported settings.`, "Reinstall HolyCodex.") : check(`mcp-${name}`, "ok", "required-mcp-ready", `${name} is configured locally.`));
|
|
4963
4938
|
}
|
|
4964
|
-
const codexSlimEdit = servers?.codexslimedit;
|
|
4965
|
-
const codexSlimEditConfig = ["bun", "npm"].map((runner) => effectiveMcpServers(runtime.platform, runner).codexslimedit).find((expected) => {
|
|
4966
|
-
return expected !== void 0 && codexSlimEdit !== void 0 && mcpConfigMatches(codexSlimEdit, expected);
|
|
4967
|
-
});
|
|
4968
|
-
const codexSlimEditStarted = codexSlimEditConfig === void 0 ? void 0 : await runtime.command(codexSlimEditConfig.command, [...codexSlimEditConfig.args, "--version"]);
|
|
4969
|
-
checks.push(codexSlimEdit === void 0 ? check("mcp-codexslimedit", "error", "missing-codexslimedit", "codexslimedit is not configured.", "Reinstall HolyCodex.") : codexSlimEditStarted?.ok === true ? check("mcp-codexslimedit", "ok", "codexslimedit-ready", "codexslimedit is configured through npm or Bun.") : codexSlimEditConfig === void 0 ? check("mcp-codexslimedit", "error", "invalid-codexslimedit-config", "codexslimedit configuration is stale or uses an unsupported runner.", "Reinstall HolyCodex.") : check("mcp-codexslimedit", "error", "codexslimedit-unavailable", `codexslimedit could not start: ${codexSlimEditStarted?.output || "unknown runner error"}`, "Check the configured package runner and network access, then reinstall HolyCodex."));
|
|
4970
4939
|
const gitBashConfig = servers?.git_bash;
|
|
4971
4940
|
if (runtime.platform === "win32" && gitBashConfig !== void 0) {
|
|
4972
4941
|
const expected = effectiveMcpServers("win32").git_bash;
|
|
@@ -4997,19 +4966,16 @@ async function doctor(home = process.env.CODEX_HOME ?? join(homedir(), ".codex")
|
|
|
4997
4966
|
const gitBash = runtime.gitBash();
|
|
4998
4967
|
checks.push(gitBash.found ? check("git-bash", "ok", "git-bash-ready", `Git Bash: ${gitBash.path ?? "configured"}.`) : check("git-bash", "error", "missing-git-bash", "Git Bash is required on Windows but unavailable.", gitBash.installHint));
|
|
4999
4968
|
} else checks.push(check("git-bash", "ok", "git-bash-not-applicable", "Git Bash is not applicable on this platform."));
|
|
5000
|
-
|
|
5001
|
-
try {
|
|
5002
|
-
config = await readFile(configPath, "utf8");
|
|
5003
|
-
} catch {
|
|
5004
|
-
checks.push(check("codex-config", "error", "missing-codex-config", `Missing ${configPath}.`, "Run holycodex install."));
|
|
5005
|
-
}
|
|
4969
|
+
if (!configAvailable) checks.push(check("codex-config", "error", "missing-codex-config", `Missing ${configPath}.`, "Run holycodex install."));
|
|
5006
4970
|
const mode = autonomy(config);
|
|
5007
4971
|
const plan = readManagedPlan(config);
|
|
5008
4972
|
checks.push(plan === void 0 ? check("routing-plan", "error", "routing-plan-missing", "No managed model routing plan is recorded.", "Rerun holycodex install.") : check("routing-plan", "ok", "routing-plan-ready", `Model routing plan ${plan} is active.`));
|
|
5009
4973
|
const preset = plan === void 0 ? void 0 : MODEL_ROUTING_PLANS[plan];
|
|
4974
|
+
const managedMaxSubagents = readManagedMaxSubagents(config);
|
|
4975
|
+
const expectedMaxSubagents = managedMaxSubagents.configured ? managedMaxSubagents.value : preset?.usage.maxSubagents;
|
|
5010
4976
|
const rootOverrides = readPreservedRootOverrides(config);
|
|
5011
4977
|
checks.push(preset !== void 0 && rootTomlString(config, "model") === preset.root.model && rootTomlString(config, "model_reasoning_effort") === preset.root.reasoningEffort ? check("root-model", "ok", "root-model-ready", "Root model matches the selected routing plan.") : rootOverrides.model || rootOverrides.reasoningEffort ? check("root-model", "ok", "root-model-override", "Root model uses an intentionally preserved explicit override.") : check("root-model", "error", "root-model-stale", "Root model configuration does not match the selected routing plan.", "Reinstall HolyCodex."));
|
|
5012
|
-
checks.push(preset === void 0 || tableInteger(config, "agents", "max_threads") !==
|
|
4978
|
+
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"}.`));
|
|
5013
4979
|
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."));
|
|
5014
4980
|
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."));
|
|
5015
4981
|
checks.push(rootTomlStringArray(config, "status_line")?.includes("context-remaining") === true ? check("context-visibility", "warning", "context-visible-support-unverified", "status_line includes context-remaining. Current official Codex config documents this item, but publishes no minimum compatible Codex version.") : check("context-visibility", "error", "context-hidden", "status_line does not include context-remaining.", "Rerun holycodex install."));
|
|
@@ -5078,13 +5044,7 @@ async function readText(path) {
|
|
|
5078
5044
|
//#region packages/cli/src/install.ts
|
|
5079
5045
|
var defaultRuntime = {
|
|
5080
5046
|
platform: process.platform,
|
|
5081
|
-
gitBash: resolveGitBashForCurrentProcess
|
|
5082
|
-
packageRunner: detectPackageRunner(),
|
|
5083
|
-
installCodexSlimEdit: async (packageRunner) => installCodexSlimEdit({
|
|
5084
|
-
packageRunner,
|
|
5085
|
-
packageVersion: VERSION,
|
|
5086
|
-
platform: process.platform
|
|
5087
|
-
})
|
|
5047
|
+
gitBash: resolveGitBashForCurrentProcess
|
|
5088
5048
|
};
|
|
5089
5049
|
function paths(home = process.env.CODEX_HOME ?? join(homedir(), ".codex")) {
|
|
5090
5050
|
const marketplaceCache = join(home, "plugins", "cache", "holycodex");
|
|
@@ -5114,7 +5074,6 @@ function assertGitBashReady(platform, resolution) {
|
|
|
5114
5074
|
/** Provides install. */
|
|
5115
5075
|
async function install(options, runtime = defaultRuntime) {
|
|
5116
5076
|
assertGitBashReady(runtime.platform, runtime.gitBash());
|
|
5117
|
-
await runtime.installCodexSlimEdit(runtime.packageRunner);
|
|
5118
5077
|
const plan = options.plan ?? "plus";
|
|
5119
5078
|
const target = paths();
|
|
5120
5079
|
const root = backupRoot();
|
|
@@ -5126,7 +5085,8 @@ async function install(options, runtime = defaultRuntime) {
|
|
|
5126
5085
|
].filter((path) => path !== void 0);
|
|
5127
5086
|
const existingConfig = await readText(target.config);
|
|
5128
5087
|
const previousPlan = readManagedPlan(existingConfig);
|
|
5129
|
-
const
|
|
5088
|
+
const maxSubagents = options.maxSubagents ?? MODEL_ROUTING_PLANS[plan].usage.maxSubagents;
|
|
5089
|
+
const config = installConfig(existingConfig, options.autonomy, runtime.platform, plan, options.maxSubagents);
|
|
5130
5090
|
await atomicWrite(target.config, config);
|
|
5131
5091
|
await rm(target.marketplaceCache, {
|
|
5132
5092
|
recursive: true,
|
|
@@ -5134,7 +5094,7 @@ async function install(options, runtime = defaultRuntime) {
|
|
|
5134
5094
|
});
|
|
5135
5095
|
await mkdir(dirname(target.cache), { recursive: true });
|
|
5136
5096
|
await cp(pluginRoot, target.cache, { recursive: true });
|
|
5137
|
-
await writePlatformPlugin(target.cache, runtime.platform, plan
|
|
5097
|
+
await writePlatformPlugin(target.cache, runtime.platform, plan);
|
|
5138
5098
|
const existingAgentPreferences = await readAgentPreferences(target.agents, previousPlan);
|
|
5139
5099
|
await rm(target.agents, {
|
|
5140
5100
|
recursive: true,
|
|
@@ -5158,7 +5118,8 @@ async function install(options, runtime = defaultRuntime) {
|
|
|
5158
5118
|
...removedLegacy
|
|
5159
5119
|
],
|
|
5160
5120
|
backups,
|
|
5161
|
-
plan
|
|
5121
|
+
plan,
|
|
5122
|
+
maxSubagents
|
|
5162
5123
|
};
|
|
5163
5124
|
}
|
|
5164
5125
|
async function readAgentPreferences(root, previousPlan) {
|
|
@@ -5189,8 +5150,8 @@ async function preserveAgentPreferences(root, preferences) {
|
|
|
5189
5150
|
function replaceTomlString(input, key, value) {
|
|
5190
5151
|
return input.replace(new RegExp(`^${key}\\s*=.*$`, "m"), `${key} = ${JSON.stringify(value)}`);
|
|
5191
5152
|
}
|
|
5192
|
-
async function writePlatformPlugin(root, platform, plan
|
|
5193
|
-
await atomicWrite(join(root, ".mcp.json"), `${JSON.stringify({ mcpServers: effectiveMcpServers(platform
|
|
5153
|
+
async function writePlatformPlugin(root, platform, plan) {
|
|
5154
|
+
await atomicWrite(join(root, ".mcp.json"), `${JSON.stringify({ mcpServers: effectiveMcpServers(platform) }, null, 2)}\n`);
|
|
5194
5155
|
await writeInstalledAgents(join(root, "agents"), platform, plan);
|
|
5195
5156
|
}
|
|
5196
5157
|
async function writeInstalledAgents(root, platform, plan) {
|
|
@@ -5270,13 +5231,13 @@ function renderHelp(version, color) {
|
|
|
5270
5231
|
const title = paint(color, `${BOLD}${CYAN}`, `HOLYCODEX ${version}`);
|
|
5271
5232
|
const section = (text) => paint(color, BOLD, text);
|
|
5272
5233
|
const muted = (text) => paint(color, DIM, text);
|
|
5273
|
-
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 -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 --json Print machine-readable output\n`;
|
|
5234
|
+
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 <0-3> Override concurrent direct subagents for install\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 --json Print machine-readable output\n`;
|
|
5274
5235
|
}
|
|
5275
5236
|
/** Renders install-specific model plan and option help. */
|
|
5276
5237
|
function renderInstallHelp(version, color) {
|
|
5277
5238
|
const title = paint(color, `${BOLD}${CYAN}`, `HOLYCODEX ${version}`);
|
|
5278
5239
|
const section = (text) => paint(color, BOLD, text);
|
|
5279
|
-
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 --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.\n\n${section("Examples:")}\n bunx holycodex install\n bunx holycodex install --plan go\n bunx holycodex install --plan plus-low\n bunx holycodex install --plan plus-high\n bunx holycodex install --plan pro-5x\n bunx holycodex install --plan pro-20x\n`;
|
|
5240
|
+
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 <0-3> Override concurrent direct subagents\n --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.\n\n${section("Examples:")}\n bunx holycodex install\n bunx holycodex install --plan go\n bunx holycodex install --plan plus-low\n bunx holycodex install --plan plus-high\n bunx holycodex install --plan pro-5x\n bunx holycodex install --plan pro-20x\n`;
|
|
5280
5241
|
}
|
|
5281
5242
|
/** Renders error. */
|
|
5282
5243
|
function renderError(message, color) {
|
|
@@ -5304,7 +5265,7 @@ async function main() {
|
|
|
5304
5265
|
const args = process$1.argv.slice(2);
|
|
5305
5266
|
const stdoutColor = supportsColor(process$1.stdout.isTTY, process$1.env.NO_COLOR);
|
|
5306
5267
|
const stderrColor = supportsColor(process$1.stderr.isTTY, process$1.env.NO_COLOR);
|
|
5307
|
-
const command = args.find((arg, index) => !arg.startsWith("-") && args[index - 1] !== "--plan");
|
|
5268
|
+
const command = args.find((arg, index) => !arg.startsWith("-") && args[index - 1] !== "--plan" && args[index - 1] !== "--max-subagents");
|
|
5308
5269
|
if (args.includes("--help") || args.includes("-h") || args.length === 0) {
|
|
5309
5270
|
process$1.stdout.write(command === "install" ? renderInstallHelp(VERSION, stdoutColor) : renderHelp(VERSION, stdoutColor));
|
|
5310
5271
|
return;
|
|
@@ -5320,6 +5281,12 @@ async function main() {
|
|
|
5320
5281
|
const parsedPlan = PlanNameSchema.safeParse(planValue);
|
|
5321
5282
|
if (!parsedPlan.success) throw new Error(`Unknown plan: ${planValue}. Valid plans: ${PLAN_NAMES.join(", ")}.`);
|
|
5322
5283
|
const plan = parsedPlan.data;
|
|
5284
|
+
if (args.flatMap((arg, index) => arg === "--max-subagents" ? [index] : []).length > 1) throw new Error("--max-subagents may be specified only once.");
|
|
5285
|
+
const maxSubagentsIndex = args.indexOf("--max-subagents");
|
|
5286
|
+
const maxSubagentsValue = maxSubagentsIndex < 0 ? void 0 : args[maxSubagentsIndex + 1];
|
|
5287
|
+
if (maxSubagentsIndex >= 0 && (maxSubagentsValue === void 0 || maxSubagentsValue.startsWith("-") || maxSubagentsValue === command)) throw new Error("Missing --max-subagents value. Valid range: 0-3.");
|
|
5288
|
+
if (maxSubagentsValue !== void 0 && !/^[0-3]$/.test(maxSubagentsValue)) throw new Error(`Invalid --max-subagents value: ${maxSubagentsValue}. Valid range: 0-3.`);
|
|
5289
|
+
const maxSubagents = maxSubagentsValue === void 0 ? void 0 : Number(maxSubagentsValue);
|
|
5323
5290
|
const autonomyFlags = args.filter((arg) => [
|
|
5324
5291
|
"--codex-autonomous",
|
|
5325
5292
|
"--no-codex-autonomous",
|
|
@@ -5333,7 +5300,8 @@ async function main() {
|
|
|
5333
5300
|
const options = {
|
|
5334
5301
|
autonomy: args.includes("--dangerous-codex-autonomous") ? "dangerous" : args.includes("--codex-autonomous") ? "autonomous" : "default",
|
|
5335
5302
|
json: args.includes("--json"),
|
|
5336
|
-
plan
|
|
5303
|
+
plan,
|
|
5304
|
+
...maxSubagents === void 0 ? {} : { maxSubagents }
|
|
5337
5305
|
};
|
|
5338
5306
|
if (command === "doctor") {
|
|
5339
5307
|
const result = await doctor();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "holycodex",
|
|
3
|
-
"version": "0.8.1",
|
|
3
|
+
"version": "0.8.2-dev.29763019035.1",
|
|
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.8.1",
|
|
42
|
+
"@holycodex/plugin": "0.8.2-dev.29763019035.1",
|
|
43
43
|
"zod": "^4.4.3"
|
|
44
44
|
},
|
|
45
45
|
"engines": {
|