holycodex 0.7.0 → 0.7.1-dev.29607507877.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/dist/cli.js +30 -4
- package/package.json +2 -2
package/dist/cli.js
CHANGED
|
@@ -7,7 +7,7 @@ import { existsSync } from "node:fs";
|
|
|
7
7
|
import { pluginRoot } from "@holycodex/plugin";
|
|
8
8
|
import { Buffer } from "node:buffer";
|
|
9
9
|
//#region packages/cli/src/catalog.ts
|
|
10
|
-
var VERSION = "0.7.
|
|
10
|
+
var VERSION = "0.7.1-dev.29607507877.1";
|
|
11
11
|
var SKILLS = [
|
|
12
12
|
"ast-grep",
|
|
13
13
|
"caveman",
|
|
@@ -77,6 +77,7 @@ var GENERATED_RUNTIMES = [
|
|
|
77
77
|
"rules.js"
|
|
78
78
|
];
|
|
79
79
|
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.";
|
|
80
|
+
/** Provides effective mcp servers. */
|
|
80
81
|
function effectiveMcpServers(platform) {
|
|
81
82
|
return {
|
|
82
83
|
...platform === "win32" ? { git_bash: {
|
|
@@ -96,6 +97,7 @@ function effectiveMcpServers(platform) {
|
|
|
96
97
|
}
|
|
97
98
|
};
|
|
98
99
|
}
|
|
100
|
+
/** Reads and validates d package runtimes. */
|
|
99
101
|
function requiredPackageRuntimes(platform) {
|
|
100
102
|
return platform === "win32" ? GENERATED_RUNTIMES : GENERATED_RUNTIMES.filter((file) => file !== "git-bash.js");
|
|
101
103
|
}
|
|
@@ -105,6 +107,7 @@ var GIT_BASH_ENV_KEY = "HOLYCODEX_GIT_BASH_PATH";
|
|
|
105
107
|
var PROGRAM_FILES = "C:\\Program Files\\Git\\bin\\bash.exe";
|
|
106
108
|
var PROGRAM_FILES_X86 = "C:\\Program Files (x86)\\Git\\bin\\bash.exe";
|
|
107
109
|
var INVALID_LAUNCHERS = ["\\windows\\system32\\", "\\microsoft\\windowsapps\\"];
|
|
110
|
+
/** Resolves git bash. */
|
|
108
111
|
function resolveGitBash(input) {
|
|
109
112
|
if (input.platform !== "win32") return {
|
|
110
113
|
found: true,
|
|
@@ -153,6 +156,7 @@ function resolveGitBash(input) {
|
|
|
153
156
|
}
|
|
154
157
|
return missing(checkedPaths);
|
|
155
158
|
}
|
|
159
|
+
/** Resolves git bash for current process. */
|
|
156
160
|
function resolveGitBashForCurrentProcess(input = {}) {
|
|
157
161
|
return resolveGitBash({
|
|
158
162
|
platform: input.platform ?? process.platform,
|
|
@@ -185,6 +189,7 @@ var defaultManagedProcessRuntime = {
|
|
|
185
189
|
terminationGraceMs: 2e3,
|
|
186
190
|
kill: killProcessTree
|
|
187
191
|
};
|
|
192
|
+
/** Runs managed process. */
|
|
188
193
|
async function runManagedProcess(input, runtime = defaultManagedProcessRuntime) {
|
|
189
194
|
return await new Promise((resolve) => {
|
|
190
195
|
const child = spawn(input.command, [...input.args], {
|
|
@@ -261,6 +266,7 @@ async function runManagedProcess(input, runtime = defaultManagedProcessRuntime)
|
|
|
261
266
|
else child.stdin.end(input.stdin);
|
|
262
267
|
});
|
|
263
268
|
}
|
|
269
|
+
/** Terminates process tree. */
|
|
264
270
|
function killProcessTree(child, platform, signal = "SIGTERM", runTaskkill = (command, args) => spawnSync(command, [...args], {
|
|
265
271
|
stdio: "ignore",
|
|
266
272
|
windowsHide: true
|
|
@@ -303,6 +309,7 @@ function outputText(state) {
|
|
|
303
309
|
//#endregion
|
|
304
310
|
//#region packages/cli/src/toml.ts
|
|
305
311
|
var TOML_TABLE = /^[ \t]*(?:\[[^\]\r\n]+\]|\[\[[^\]\r\n]+\]\])[ \t]*(?:#.*)?$/m;
|
|
312
|
+
/** Reads a root TOML string value. */
|
|
306
313
|
function rootTomlString(input, key) {
|
|
307
314
|
const table = TOML_TABLE.exec(input);
|
|
308
315
|
const root = table === null ? input : input.slice(0, table.index);
|
|
@@ -316,9 +323,11 @@ function rootTomlString(input, key) {
|
|
|
316
323
|
return;
|
|
317
324
|
}
|
|
318
325
|
}
|
|
326
|
+
/** Reads a root TOML string array. */
|
|
319
327
|
function rootTomlStringArray(input, key) {
|
|
320
328
|
return parseRootTomlStringArray(input, key)?.items;
|
|
321
329
|
}
|
|
330
|
+
/** Reads the source text of a root TOML string array. */
|
|
322
331
|
function rootTomlStringArraySource(input, key) {
|
|
323
332
|
return parseRootTomlStringArray(input, key)?.source;
|
|
324
333
|
}
|
|
@@ -473,6 +482,7 @@ function autonomy(config) {
|
|
|
473
482
|
if (approval === "never" && sandbox === "danger-full-access") return "dangerous";
|
|
474
483
|
return "unknown";
|
|
475
484
|
}
|
|
485
|
+
/** Runs HolyCodex installation and environment health checks. */
|
|
476
486
|
async function doctor(home = process.env.CODEX_HOME ?? join(homedir(), ".codex"), runtime = defaultRuntime$1) {
|
|
477
487
|
const checks = [];
|
|
478
488
|
const pluginRoot = join(home, "plugins", "cache", "holycodex", "holycodex", VERSION);
|
|
@@ -500,12 +510,12 @@ async function doctor(home = process.env.CODEX_HOME ?? join(homedir(), ".codex")
|
|
|
500
510
|
for (const name of requiredMcps) {
|
|
501
511
|
const configured = servers?.[name];
|
|
502
512
|
const expected = expectedMcps[name];
|
|
503
|
-
checks.push(configured === 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.`));
|
|
513
|
+
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.`));
|
|
504
514
|
}
|
|
505
515
|
const gitBashConfig = servers?.git_bash;
|
|
506
516
|
if (runtime.platform === "win32" && gitBashConfig !== void 0) {
|
|
507
517
|
const expected = effectiveMcpServers("win32").git_bash;
|
|
508
|
-
checks.push(mcpConfigMatches(gitBashConfig, expected) ? check("mcp-git_bash-config", "ok", "git-bash-mcp-config-ready", "Git Bash MCP exposes only run through the supported allowlist.") : check("mcp-git_bash-config", "error", "invalid-git-bash-mcp-config", "Git Bash MCP command or enabled_tools configuration is stale.", "Reinstall HolyCodex."));
|
|
518
|
+
checks.push(expected !== void 0 && mcpConfigMatches(gitBashConfig, expected) ? check("mcp-git_bash-config", "ok", "git-bash-mcp-config-ready", "Git Bash MCP exposes only run through the supported allowlist.") : check("mcp-git_bash-config", "error", "invalid-git-bash-mcp-config", "Git Bash MCP command or enabled_tools configuration is stale.", "Reinstall HolyCodex."));
|
|
509
519
|
} else if (runtime.platform !== "win32" && gitBashConfig !== void 0) checks.push(check("mcp-git_bash-config", "error", "unexpected-git-bash-mcp", "Git Bash MCP must not be installed on non-Windows platforms.", "Reinstall HolyCodex for this platform."));
|
|
510
520
|
const context7 = servers?.context7;
|
|
511
521
|
const expectedContext7 = effectiveMcpServers(runtime.platform).context7;
|
|
@@ -518,7 +528,7 @@ async function doctor(home = process.env.CODEX_HOME ?? join(homedir(), ".codex")
|
|
|
518
528
|
if (context7 === void 0) checks.push(check("context7-config", "error", "missing-context7", "Context7 is not configured.", "Reinstall HolyCodex."));
|
|
519
529
|
else if (typeof context7.url === "string") checks.push(check("context7-config", "error", "obsolete-context7-remote", "Context7 still uses a hosted URL.", "Reinstall to use local bunx Context7."));
|
|
520
530
|
else if (obsoleteAuth) checks.push(check("context7-config", "error", "obsolete-context7-auth", "Context7 contains obsolete authentication settings.", "Remove auth settings and reinstall."));
|
|
521
|
-
else if (!mcpConfigMatches(context7, expectedContext7)) checks.push(check("context7-config", "error", "invalid-context7-config", "Context7 launch configuration is stale or contains unsupported settings.", "Repair .mcp.json or reinstall."));
|
|
531
|
+
else if (expectedContext7 === void 0 || !mcpConfigMatches(context7, expectedContext7)) checks.push(check("context7-config", "error", "invalid-context7-config", "Context7 launch configuration is stale or contains unsupported settings.", "Repair .mcp.json or reinstall."));
|
|
522
532
|
else checks.push(check("context7-config", "ok", "local-context7-config", "Local no-auth Context7 is configured."));
|
|
523
533
|
const bun = await runtime.command("bun", ["--version"]);
|
|
524
534
|
const bunx = await runtime.command("bunx", ["--version"]);
|
|
@@ -589,6 +599,7 @@ var OLD_NAMESPACES = [
|
|
|
589
599
|
"hooks.state.\"omo@lazycodex",
|
|
590
600
|
"hooks.state.\"omo@code-yeongyu-codex-plugins"
|
|
591
601
|
];
|
|
602
|
+
/** Removes managed. */
|
|
592
603
|
function removeManaged(input) {
|
|
593
604
|
const escapedStart = START.replaceAll(">", "\\>");
|
|
594
605
|
const escapedEnd = END.replaceAll("<", "\\<");
|
|
@@ -599,6 +610,7 @@ function removeManaged(input) {
|
|
|
599
610
|
return tableKey === void 0 ? "" : `${Buffer.from(tableKey, "base64").toString("utf8")}\n`;
|
|
600
611
|
}).trim();
|
|
601
612
|
}
|
|
613
|
+
/** Removes legacy omo. */
|
|
602
614
|
function removeLegacyOmo(input) {
|
|
603
615
|
return input.split(/(?=^\s*\[)/m).filter((section) => {
|
|
604
616
|
const header = /^\s*\[([^\]]+)]/.exec(section)?.[1];
|
|
@@ -662,6 +674,7 @@ function mergedStatusLine(original) {
|
|
|
662
674
|
if (!items.includes("context-remaining")) items.push("context-remaining");
|
|
663
675
|
return `[${items.map((item) => JSON.stringify(item)).join(", ")}]`;
|
|
664
676
|
}
|
|
677
|
+
/** Installs config. */
|
|
665
678
|
function installConfig(input, mode, _platform) {
|
|
666
679
|
const base = preserveManagedRootPreferences(input, removeLegacyOmo(removeManaged(input)));
|
|
667
680
|
const firstTable = base.search(/^\s*\[/m);
|
|
@@ -695,6 +708,7 @@ function installConfig(input, mode, _platform) {
|
|
|
695
708
|
}
|
|
696
709
|
//#endregion
|
|
697
710
|
//#region packages/cli/src/files.ts
|
|
711
|
+
/** Provides exists. */
|
|
698
712
|
async function exists(path) {
|
|
699
713
|
try {
|
|
700
714
|
await stat(path);
|
|
@@ -704,6 +718,7 @@ async function exists(path) {
|
|
|
704
718
|
throw error;
|
|
705
719
|
}
|
|
706
720
|
}
|
|
721
|
+
/** Provides backup. */
|
|
707
722
|
async function backup(path, root) {
|
|
708
723
|
if (!await exists(path)) return void 0;
|
|
709
724
|
const target = join(root, path.replace(/^([A-Za-z]:)?[\\/]+/, "").replaceAll(":", ""));
|
|
@@ -724,12 +739,14 @@ async function copyBackup(source, target) {
|
|
|
724
739
|
await mkdir(target, { recursive: true });
|
|
725
740
|
for (const entry of await readdir(source)) await copyBackup(join(source, entry), join(target, entry));
|
|
726
741
|
}
|
|
742
|
+
/** Provides atomic write. */
|
|
727
743
|
async function atomicWrite(path, content) {
|
|
728
744
|
await mkdir(dirname(path), { recursive: true });
|
|
729
745
|
const temporary = `${path}.${process.pid}.tmp`;
|
|
730
746
|
await writeFile(temporary, content, "utf8");
|
|
731
747
|
await rename(temporary, path);
|
|
732
748
|
}
|
|
749
|
+
/** Reads text. */
|
|
733
750
|
async function readText(path) {
|
|
734
751
|
return await exists(path) ? readFile(path, "utf8") : "";
|
|
735
752
|
}
|
|
@@ -759,10 +776,12 @@ function paths(home = process.env.CODEX_HOME ?? join(homedir(), ".codex")) {
|
|
|
759
776
|
function backupRoot() {
|
|
760
777
|
return join(tmpdir(), "holycodex-backups", (/* @__PURE__ */ new Date()).toISOString().replaceAll(":", "-"));
|
|
761
778
|
}
|
|
779
|
+
/** Validates git bash ready. */
|
|
762
780
|
function assertGitBashReady(platform, resolution) {
|
|
763
781
|
if (platform !== "win32") return;
|
|
764
782
|
if (!resolution.found) throw new Error(resolution.installHint);
|
|
765
783
|
}
|
|
784
|
+
/** Provides install. */
|
|
766
785
|
async function install(options, runtime = defaultRuntime) {
|
|
767
786
|
assertGitBashReady(runtime.platform, runtime.gitBash());
|
|
768
787
|
const target = paths();
|
|
@@ -846,6 +865,7 @@ async function writePlatformAgents(root, platform) {
|
|
|
846
865
|
await atomicWrite(path, (await readText(path)).replace(`${WINDOWS_SHELL_POLICY}\r\n\r\n`, "").replace(`${WINDOWS_SHELL_POLICY}\n\n`, ""));
|
|
847
866
|
}));
|
|
848
867
|
}
|
|
868
|
+
/** Provides cleanup. */
|
|
849
869
|
async function cleanup(_options) {
|
|
850
870
|
const target = paths();
|
|
851
871
|
const root = backupRoot();
|
|
@@ -893,18 +913,22 @@ var DIM = "\x1B[2m";
|
|
|
893
913
|
function paint(enabled, code, text) {
|
|
894
914
|
return enabled ? `${code}${text}${RESET}` : text;
|
|
895
915
|
}
|
|
916
|
+
/** Checks whether terminal color output is supported. */
|
|
896
917
|
function supportsColor(isTTY, noColor) {
|
|
897
918
|
return isTTY === true && noColor === void 0;
|
|
898
919
|
}
|
|
920
|
+
/** Renders help. */
|
|
899
921
|
function renderHelp(version, color) {
|
|
900
922
|
const title = paint(color, `${BOLD}${CYAN}`, `HOLYCODEX ${version}`);
|
|
901
923
|
const section = (text) => paint(color, BOLD, text);
|
|
902
924
|
const muted = (text) => paint(color, DIM, text);
|
|
903
925
|
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 -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`;
|
|
904
926
|
}
|
|
927
|
+
/** Renders error. */
|
|
905
928
|
function renderError(message, color) {
|
|
906
929
|
return `${paint(color, `${BOLD}${RED}`, "✗ ERROR")} ${message}\n ${paint(color, DIM, "Run holycodex --help for usage.")}\n`;
|
|
907
930
|
}
|
|
931
|
+
/** Renders doctor. */
|
|
908
932
|
function renderDoctor(result, color) {
|
|
909
933
|
return `${result.healthy ? paint(color, GREEN, "✓ HolyCodex doctor: healthy") : paint(color, RED, "✗ HolyCodex doctor: issues found")}\n${result.checks.map((item) => {
|
|
910
934
|
const label = item.status.toUpperCase().padEnd(7);
|
|
@@ -912,9 +936,11 @@ function renderDoctor(result, color) {
|
|
|
912
936
|
return item.fix === void 0 ? line : `${line}\n ${paint(color, DIM, `Fix: ${item.fix}`)}`;
|
|
913
937
|
}).join("\n")}\n`;
|
|
914
938
|
}
|
|
939
|
+
/** Renders run result. */
|
|
915
940
|
function renderRunResult(result, color) {
|
|
916
941
|
return `${paint(color, GREEN, `✓ HolyCodex ${result.action} complete`)}\n Changed: ${result.changed.length}\n Backups: ${result.backups.length}\n`;
|
|
917
942
|
}
|
|
943
|
+
/** Renders notice. */
|
|
918
944
|
function renderNotice(kind, message, color) {
|
|
919
945
|
return `${paint(color, kind === "warning" ? RED : YELLOW, `! ${kind === "warning" ? "WARNING" : "NOTICE"}`)} ${message}\n`;
|
|
920
946
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "holycodex",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.1-dev.29607507877.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.7.
|
|
42
|
+
"@holycodex/plugin": "0.7.1-dev.29607507877.1"
|
|
43
43
|
},
|
|
44
44
|
"engines": {
|
|
45
45
|
"node": ">=20"
|