@inerrata-corporation/errata 2.0.6-dev.2752 → 2.0.6-dev.2759
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/errata.mjs +122 -11
- package/package.json +1 -1
package/errata.mjs
CHANGED
|
@@ -71189,7 +71189,7 @@ var init_report_render = __esm({
|
|
|
71189
71189
|
init_src6();
|
|
71190
71190
|
import { closeSync as closeSync2, existsSync as existsSync34, openSync as openSync2, readFileSync as readFileSync35, renameSync as renameSync4, statSync as statSync8 } from "node:fs";
|
|
71191
71191
|
import { join as join40, resolve as pathResolve2 } from "node:path";
|
|
71192
|
-
import { spawn as
|
|
71192
|
+
import { spawn as spawn5 } from "node:child_process";
|
|
71193
71193
|
|
|
71194
71194
|
// src/daemon.ts
|
|
71195
71195
|
import { existsSync as existsSync26, writeFileSync as writeFileSync22 } from "node:fs";
|
|
@@ -79907,7 +79907,7 @@ function createWatchBreaker(deps) {
|
|
|
79907
79907
|
}
|
|
79908
79908
|
|
|
79909
79909
|
// src/engine.ts
|
|
79910
|
-
var DAEMON_VERSION = true ? "2.0.6-dev.
|
|
79910
|
+
var DAEMON_VERSION = true ? "2.0.6-dev.2759" : "2.0.0-alpha.0";
|
|
79911
79911
|
var IGNORED_PATH = /[\\/](?:\.git|node_modules|\.errata|\.claude|\.codex|\.cursor|\.turbo|\.next|dist|coverage|test-results|playwright-report|__pycache__)(?:[\\/]|$)/;
|
|
79912
79912
|
var IGNORED_NOISE = /castalia\.db|eventlog\.sqlite|turn-cursors/;
|
|
79913
79913
|
var GIT_OP_MUTE_MS = 4e3;
|
|
@@ -85577,6 +85577,7 @@ var SessionAffinity = class {
|
|
|
85577
85577
|
};
|
|
85578
85578
|
|
|
85579
85579
|
// src/multi.ts
|
|
85580
|
+
init_checkout_root();
|
|
85580
85581
|
var PROCESS_STARTED_AT = Date.now();
|
|
85581
85582
|
var SELF_ENTRY = process.argv[1] ? pathResolve(process.argv[1]) : "";
|
|
85582
85583
|
var LOCAL_BUILD_ENTRY = SELF_ENTRY && !isInstalledEntry(SELF_ENTRY) ? SELF_ENTRY : void 0;
|
|
@@ -86124,6 +86125,19 @@ async function startMultiDaemon(opts = {}) {
|
|
|
86124
86125
|
if (owner) break;
|
|
86125
86126
|
owner = ownerOf(records, p);
|
|
86126
86127
|
}
|
|
86128
|
+
if (!owner) {
|
|
86129
|
+
for (const p of [primary, ...others]) {
|
|
86130
|
+
if (!p) continue;
|
|
86131
|
+
const gitRoot = nearestGitRoot(p);
|
|
86132
|
+
const main2 = gitRoot ? mainCheckoutOfWorktree(gitRoot) : null;
|
|
86133
|
+
if (!main2) continue;
|
|
86134
|
+
owner = ownerOf(records, main2);
|
|
86135
|
+
if (!owner && listWorkspaceEntries().some((e) => pickOwnerRoot([e.path], main2))) {
|
|
86136
|
+
if (attachWorkspace(main2).attached) owner = ownerOf(records, main2);
|
|
86137
|
+
}
|
|
86138
|
+
if (owner) break;
|
|
86139
|
+
}
|
|
86140
|
+
}
|
|
86127
86141
|
if (!owner && others.length > 0) {
|
|
86128
86142
|
const registryRoots = listWorkspaceEntries().map((e) => e.path);
|
|
86129
86143
|
const registered = others.map((p) => pickOwnerRoot(registryRoots, p)).find((r) => r != null);
|
|
@@ -87552,9 +87566,9 @@ function deriveAuthBase(verificationUri) {
|
|
|
87552
87566
|
}
|
|
87553
87567
|
function openInBrowser(url2) {
|
|
87554
87568
|
try {
|
|
87555
|
-
void import("node:child_process").then(({ spawn:
|
|
87569
|
+
void import("node:child_process").then(({ spawn: spawn6 }) => {
|
|
87556
87570
|
const [cmd2, args2] = process.platform === "win32" ? ["cmd", ["/c", "start", "", url2]] : process.platform === "darwin" ? ["open", [url2]] : ["xdg-open", [url2]];
|
|
87557
|
-
|
|
87571
|
+
spawn6(cmd2, args2, { detached: true, stdio: "ignore" }).unref();
|
|
87558
87572
|
});
|
|
87559
87573
|
} catch {
|
|
87560
87574
|
}
|
|
@@ -87634,6 +87648,7 @@ function installedHarnessVersion(bin) {
|
|
|
87634
87648
|
}
|
|
87635
87649
|
async function diagnoseInstallation(cfg, dependencies) {
|
|
87636
87650
|
const checks = [];
|
|
87651
|
+
if (dependencies.codexHooks) checks.push(...await dependencies.codexHooks());
|
|
87637
87652
|
const profileName = cfg.activeInstallationProfile;
|
|
87638
87653
|
const profile = profileName ? cfg.installationProfiles[profileName] : void 0;
|
|
87639
87654
|
checks.push(
|
|
@@ -87727,6 +87742,97 @@ async function diagnoseInstallation(cfg, dependencies) {
|
|
|
87727
87742
|
};
|
|
87728
87743
|
}
|
|
87729
87744
|
|
|
87745
|
+
// src/codex-doctor.ts
|
|
87746
|
+
import { spawn as spawn4 } from "node:child_process";
|
|
87747
|
+
import { createInterface } from "node:readline";
|
|
87748
|
+
function readCodexHookState(cwd, options = {}) {
|
|
87749
|
+
return new Promise((resolve7, reject) => {
|
|
87750
|
+
const child = spawn4(options.bin ?? "codex", options.args ?? ["app-server", "--stdio"], {
|
|
87751
|
+
cwd,
|
|
87752
|
+
windowsHide: true,
|
|
87753
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
87754
|
+
});
|
|
87755
|
+
const lines = createInterface({ input: child.stdout });
|
|
87756
|
+
let settled = false;
|
|
87757
|
+
let size = 0;
|
|
87758
|
+
let hooks;
|
|
87759
|
+
let features;
|
|
87760
|
+
const finish = (error48) => {
|
|
87761
|
+
if (settled) return;
|
|
87762
|
+
settled = true;
|
|
87763
|
+
clearTimeout(timer);
|
|
87764
|
+
lines.close();
|
|
87765
|
+
child.kill();
|
|
87766
|
+
if (error48) reject(error48);
|
|
87767
|
+
else resolve7({ ...hooks, features });
|
|
87768
|
+
};
|
|
87769
|
+
const timer = setTimeout(() => finish(new Error("Codex hook inspection timed out")), options.timeoutMs ?? 1e4);
|
|
87770
|
+
const send = (id, method, params) => {
|
|
87771
|
+
child.stdin.write(JSON.stringify({ id, method, params }) + "\n");
|
|
87772
|
+
};
|
|
87773
|
+
child.on("error", () => finish(new Error("Codex could not be started for hook inspection")));
|
|
87774
|
+
child.on("exit", () => finish(new Error("Codex exited before returning its hook state")));
|
|
87775
|
+
child.stdin.on("error", () => finish(new Error("Codex hook inspection connection closed")));
|
|
87776
|
+
child.stderr.resume();
|
|
87777
|
+
child.stdout.on("data", (chunk) => {
|
|
87778
|
+
size += chunk.length;
|
|
87779
|
+
if (size > 2e6) finish(new Error("Codex hook inspection exceeded its response budget"));
|
|
87780
|
+
});
|
|
87781
|
+
lines.on("line", (line) => {
|
|
87782
|
+
if (settled) return;
|
|
87783
|
+
let message2;
|
|
87784
|
+
try {
|
|
87785
|
+
message2 = JSON.parse(line);
|
|
87786
|
+
} catch {
|
|
87787
|
+
return;
|
|
87788
|
+
}
|
|
87789
|
+
if (![1, 2, 3].includes(message2.id)) return;
|
|
87790
|
+
if (message2.error) return finish(new Error("Codex does not support hook inspection; update Codex and review /hooks"));
|
|
87791
|
+
if (message2.id === 1) {
|
|
87792
|
+
child.stdin.write(JSON.stringify({ method: "initialized" }) + "\n");
|
|
87793
|
+
send(2, "hooks/list", { cwds: [cwd] });
|
|
87794
|
+
send(3, "config/read", { cwd, includeLayers: false });
|
|
87795
|
+
} else if (message2.id === 2) {
|
|
87796
|
+
const entry = message2.result?.data?.[0];
|
|
87797
|
+
if (!Array.isArray(entry?.hooks)) return finish(new Error("Codex returned no hook inspection result"));
|
|
87798
|
+
hooks = { hooks: entry.hooks, errors: entry.errors };
|
|
87799
|
+
} else {
|
|
87800
|
+
if (!message2.result?.config) return finish(new Error("Codex returned no effective configuration"));
|
|
87801
|
+
features = message2.result.config.features ?? {};
|
|
87802
|
+
}
|
|
87803
|
+
if (hooks && features) finish();
|
|
87804
|
+
});
|
|
87805
|
+
send(1, "initialize", {
|
|
87806
|
+
clientInfo: { name: "errata_doctor", version: "1.0.0" },
|
|
87807
|
+
capabilities: { experimentalApi: true }
|
|
87808
|
+
});
|
|
87809
|
+
});
|
|
87810
|
+
}
|
|
87811
|
+
function assessCodexHooks(state) {
|
|
87812
|
+
const check2 = (status, detail) => [{ id: "codex_hooks", status, detail }];
|
|
87813
|
+
if (state.errors?.length) return check2("fail", "Codex could not load hook configuration; inspect /hooks for errors");
|
|
87814
|
+
if ((state.features?.hooks ?? state.features?.codex_hooks) === false) {
|
|
87815
|
+
return check2("fail", "Codex hooks are explicitly disabled; left unchanged");
|
|
87816
|
+
}
|
|
87817
|
+
const hooks = state.hooks.filter((h) => h.command?.includes("errata-relay.mjs"));
|
|
87818
|
+
const required2 = ["sessionStart", "userPromptSubmit", "preToolUse", "postToolUse", "stop"];
|
|
87819
|
+
const missing = required2.filter((event) => !hooks.some((h) => h.eventName === event));
|
|
87820
|
+
const checks = [];
|
|
87821
|
+
if (missing.length) checks.push(...check2("fail", `Errata hooks missing or outdated in this checkout (${missing.join(", ")}); run errata install-hooks codex here`));
|
|
87822
|
+
if (hooks.some((h) => !h.enabled)) checks.push(...check2("fail", "Errata hooks are disabled in Codex; review /hooks; left unchanged"));
|
|
87823
|
+
if (hooks.some((h) => !["trusted", "managed"].includes(h.trustStatus))) {
|
|
87824
|
+
checks.push(...check2("fail", "Errata hooks need review/trust in Codex /hooks before they can run; project trust is separate"));
|
|
87825
|
+
}
|
|
87826
|
+
return checks.length ? checks : check2("pass", "Codex discovers enabled, trusted Errata hooks; verify live context and capture in a session");
|
|
87827
|
+
}
|
|
87828
|
+
async function diagnoseCodexHooks(cwd) {
|
|
87829
|
+
try {
|
|
87830
|
+
return assessCodexHooks(await readCodexHookState(cwd));
|
|
87831
|
+
} catch (error48) {
|
|
87832
|
+
return [{ id: "codex_hooks", status: "fail", detail: error48 instanceof Error ? error48.message : "Cannot verify Codex hooks" }];
|
|
87833
|
+
}
|
|
87834
|
+
}
|
|
87835
|
+
|
|
87730
87836
|
// src/whoami.ts
|
|
87731
87837
|
async function resolveWhoami(client, actingHandle) {
|
|
87732
87838
|
return actingHandle ? client.contextAs(actingHandle) : client.context();
|
|
@@ -87819,8 +87925,8 @@ function buildCodexHooksToml(port, options) {
|
|
|
87819
87925
|
};
|
|
87820
87926
|
if (!Number.isInteger(port) || port < 1 || port > 65535) throw new Error("Invalid hook port");
|
|
87821
87927
|
const command = quote(options.nodePath) + " " + quote(options.relayPath) + " " + port;
|
|
87822
|
-
const handlers = ["SessionStart", "UserPromptSubmit", "PreToolUse", "PostToolUse"].map(
|
|
87823
|
-
(event) => "[[hooks." + event + "]]\n" + (
|
|
87928
|
+
const handlers = ["SessionStart", "UserPromptSubmit", "PreToolUse", "PostToolUse", "Stop"].map(
|
|
87929
|
+
(event) => "[[hooks." + event + "]]\n" + (["UserPromptSubmit", "Stop"].includes(event) ? "" : 'matcher = ".*"\n') + "\n[[hooks." + event + '.hooks]]\ntype = "command"\ncommand = ' + JSON.stringify(command) + "\ntimeout = 10\nadditionalContextLimit = 5000\n"
|
|
87824
87930
|
);
|
|
87825
87931
|
return CODEX_HOOKS_BEGIN + "\n" + handlers.join("\n") + CODEX_HOOKS_END + "\n";
|
|
87826
87932
|
}
|
|
@@ -87853,7 +87959,8 @@ try {
|
|
|
87853
87959
|
} catch { /* An unavailable daemon must never block the agent. */ }
|
|
87854
87960
|
};
|
|
87855
87961
|
if (event === 'PreToolUse' || event === 'PostToolUse') await post('hook', true);
|
|
87856
|
-
|
|
87962
|
+
// Stop sees the final assistant message, including turns with no tools.
|
|
87963
|
+
if (event === 'PostToolUse' || event === 'Stop') await post('turn');
|
|
87857
87964
|
if (['SessionStart', 'UserPromptSubmit', 'PostToolUse'].includes(event)) {
|
|
87858
87965
|
// Run after capture, so changes already rendered by the daemon arrive now.
|
|
87859
87966
|
// Background extraction finishing later arrives at the next tool boundary.
|
|
@@ -88752,6 +88859,7 @@ async function cmdWhoami(args2) {
|
|
|
88752
88859
|
async function cmdDoctor(args2) {
|
|
88753
88860
|
const cfg = loadConfig();
|
|
88754
88861
|
const report = await diagnoseInstallation(cfg, {
|
|
88862
|
+
...hasCodexConfig(process.cwd()) ? { codexHooks: () => diagnoseCodexHooks(process.cwd()) } : {},
|
|
88755
88863
|
inspect: () => inspectCloudEndpoint(cfg.cloudUrl),
|
|
88756
88864
|
authenticate: async () => {
|
|
88757
88865
|
const me = await authedCloudClient(cfg).me();
|
|
@@ -90197,7 +90305,7 @@ function spawnDaemonDetached(options = {}) {
|
|
|
90197
90305
|
out2 = openSync2(logPath, "a");
|
|
90198
90306
|
} catch {
|
|
90199
90307
|
}
|
|
90200
|
-
|
|
90308
|
+
spawn5(cmd2, args2, {
|
|
90201
90309
|
detached: true,
|
|
90202
90310
|
stdio: ["ignore", out2, out2],
|
|
90203
90311
|
windowsHide: true,
|
|
@@ -90419,12 +90527,15 @@ async function installCursorMcpConfig() {
|
|
|
90419
90527
|
console.log(` \u26A0\uFE0F reload Cursor (Cmd/Ctrl-Shift-P \u2192 "Reload Window") to pick it up.`);
|
|
90420
90528
|
}
|
|
90421
90529
|
async function installCodexHooks(port) {
|
|
90422
|
-
const
|
|
90530
|
+
const gitRoot = nearestGitRoot(process.cwd());
|
|
90531
|
+
const hookRoot = gitRoot && mainCheckoutOfWorktree(gitRoot) ? gitRoot : ROOT;
|
|
90532
|
+
const file2 = writeCodexHooks(hookRoot, port);
|
|
90423
90533
|
console.log(`installed Codex hooks \u2192 ${file2}`);
|
|
90424
90534
|
console.log(" Context loads on SessionStart/UserPromptSubmit and refreshes after tools when changed.");
|
|
90425
|
-
console.log(" Tool capture
|
|
90535
|
+
console.log(" Tool and final-reply capture are configured; hooks must be trusted before they run.");
|
|
90426
90536
|
console.log(" Restart/resume Codex to reload config, then review and trust the hooks with /hooks.");
|
|
90427
|
-
console.log("
|
|
90537
|
+
console.log(" Run `errata doctor` here to check hook discovery and trust; installation alone is not activation.");
|
|
90538
|
+
console.log(" Respect an explicit [features] hooks = false setting (older builds use codex_hooks).");
|
|
90428
90539
|
console.log(" Older Codex versions may not support every event; update if hooks do not fire.");
|
|
90429
90540
|
}
|
|
90430
90541
|
async function refreshLinkedCodexHooks(args2) {
|