cclaw-cli 0.48.8 → 0.48.9
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.
|
@@ -99,6 +99,63 @@ async function readStdin() {
|
|
|
99
99
|
});
|
|
100
100
|
}
|
|
101
101
|
|
|
102
|
+
async function runCclawInternal(root, args) {
|
|
103
|
+
return await new Promise((resolve) => {
|
|
104
|
+
let settled = false;
|
|
105
|
+
let stderr = "";
|
|
106
|
+
const finalize = (value) => {
|
|
107
|
+
if (settled) return;
|
|
108
|
+
settled = true;
|
|
109
|
+
resolve(value);
|
|
110
|
+
};
|
|
111
|
+
let child;
|
|
112
|
+
try {
|
|
113
|
+
child = spawn("cclaw", ["internal", ...args], {
|
|
114
|
+
cwd: root,
|
|
115
|
+
env: process.env,
|
|
116
|
+
stdio: ["ignore", "ignore", "pipe"]
|
|
117
|
+
});
|
|
118
|
+
} catch (error) {
|
|
119
|
+
const code = error && typeof error === "object" && "code" in error ? String(error.code) : "";
|
|
120
|
+
finalize({
|
|
121
|
+
code: 1,
|
|
122
|
+
stderr,
|
|
123
|
+
missingBinary: code === "ENOENT"
|
|
124
|
+
});
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
child.stderr?.on("data", (chunk) => {
|
|
128
|
+
stderr += String(chunk ?? "");
|
|
129
|
+
if (stderr.length > 8000) {
|
|
130
|
+
stderr = stderr.slice(-8000);
|
|
131
|
+
}
|
|
132
|
+
});
|
|
133
|
+
child.on("error", (error) => {
|
|
134
|
+
const code = error && typeof error === "object" && "code" in error ? String(error.code) : "";
|
|
135
|
+
finalize({
|
|
136
|
+
code: 1,
|
|
137
|
+
stderr,
|
|
138
|
+
missingBinary: code === "ENOENT"
|
|
139
|
+
});
|
|
140
|
+
});
|
|
141
|
+
child.on("close", (code, signal) => {
|
|
142
|
+
if (signal) {
|
|
143
|
+
finalize({
|
|
144
|
+
code: 1,
|
|
145
|
+
stderr,
|
|
146
|
+
missingBinary: false
|
|
147
|
+
});
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
finalize({
|
|
151
|
+
code: typeof code === "number" ? code : 1,
|
|
152
|
+
stderr,
|
|
153
|
+
missingBinary: false
|
|
154
|
+
});
|
|
155
|
+
});
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
|
|
102
159
|
function detectHarness(env) {
|
|
103
160
|
if (env.CLAUDE_PROJECT_DIR) return "claude";
|
|
104
161
|
if (env.CURSOR_PROJECT_DIR || env.CURSOR_PROJECT_ROOT) return "cursor";
|
|
@@ -1446,6 +1503,24 @@ async function handleContextMonitor(runtime) {
|
|
|
1446
1503
|
return 0;
|
|
1447
1504
|
}
|
|
1448
1505
|
|
|
1506
|
+
async function handleVerifyCurrentState(runtime) {
|
|
1507
|
+
const mode = process.env.CCLAW_WORKFLOW_GUARD_MODE === "strict"
|
|
1508
|
+
? "strict"
|
|
1509
|
+
: DEFAULT_WORKFLOW_GUARD_MODE;
|
|
1510
|
+
const result = await runCclawInternal(runtime.root, ["verify-current-state", "--quiet"]);
|
|
1511
|
+
if (result.missingBinary) {
|
|
1512
|
+
process.stderr.write("[cclaw] codex hook: cclaw binary is required for verify-current-state\\n");
|
|
1513
|
+
return 1;
|
|
1514
|
+
}
|
|
1515
|
+
if (mode === "strict") {
|
|
1516
|
+
if (result.code !== 0 && result.stderr.trim().length > 0) {
|
|
1517
|
+
process.stderr.write(result.stderr);
|
|
1518
|
+
}
|
|
1519
|
+
return result.code === 0 ? 0 : 1;
|
|
1520
|
+
}
|
|
1521
|
+
return 0;
|
|
1522
|
+
}
|
|
1523
|
+
|
|
1449
1524
|
function normalizeHookName(rawName) {
|
|
1450
1525
|
const value = normalizeText(rawName).toLowerCase();
|
|
1451
1526
|
if (value === "session-start" || value === "session-start.sh") return "session-start";
|
|
@@ -1454,6 +1529,7 @@ function normalizeHookName(rawName) {
|
|
|
1454
1529
|
if (value === "prompt-guard" || value === "prompt-guard.sh") return "prompt-guard";
|
|
1455
1530
|
if (value === "workflow-guard" || value === "workflow-guard.sh") return "workflow-guard";
|
|
1456
1531
|
if (value === "context-monitor" || value === "context-monitor.sh") return "context-monitor";
|
|
1532
|
+
if (value === "verify-current-state") return "verify-current-state";
|
|
1457
1533
|
return "";
|
|
1458
1534
|
}
|
|
1459
1535
|
|
|
@@ -1463,7 +1539,7 @@ async function main() {
|
|
|
1463
1539
|
process.stderr.write(
|
|
1464
1540
|
"[cclaw] run-hook: usage: node " +
|
|
1465
1541
|
RUNTIME_ROOT +
|
|
1466
|
-
"/hooks/run-hook.mjs <session-start|stop-checkpoint|pre-compact|prompt-guard|workflow-guard|context-monitor>\\n"
|
|
1542
|
+
"/hooks/run-hook.mjs <session-start|stop-checkpoint|pre-compact|prompt-guard|workflow-guard|context-monitor|verify-current-state>\\n"
|
|
1467
1543
|
);
|
|
1468
1544
|
process.exitCode = 1;
|
|
1469
1545
|
return;
|
|
@@ -1508,6 +1584,10 @@ async function main() {
|
|
|
1508
1584
|
process.exitCode = await handleContextMonitor(runtime);
|
|
1509
1585
|
return;
|
|
1510
1586
|
}
|
|
1587
|
+
if (hookName === "verify-current-state") {
|
|
1588
|
+
process.exitCode = await handleVerifyCurrentState(runtime);
|
|
1589
|
+
return;
|
|
1590
|
+
}
|
|
1511
1591
|
process.stderr.write("[cclaw] run-hook: unsupported hook " + hookName + "\\n");
|
|
1512
1592
|
process.exitCode = 1;
|
|
1513
1593
|
} catch (error) {
|
package/dist/content/observe.js
CHANGED
|
@@ -1660,7 +1660,7 @@ exit 0
|
|
|
1660
1660
|
* Updated hooks.json generators with PreToolUse/PostToolUse observation.
|
|
1661
1661
|
*/
|
|
1662
1662
|
function hookDispatcherCommand(scriptName) {
|
|
1663
|
-
return `
|
|
1663
|
+
return `node ${RUNTIME_ROOT}/hooks/run-hook.mjs ${scriptName}`;
|
|
1664
1664
|
}
|
|
1665
1665
|
export function claudeHooksJsonWithObservation() {
|
|
1666
1666
|
return JSON.stringify({
|
|
@@ -1799,7 +1799,7 @@ export function codexHooksJsonWithObservation() {
|
|
|
1799
1799
|
command: hookDispatcherCommand("workflow-guard.sh")
|
|
1800
1800
|
}, {
|
|
1801
1801
|
type: "command",
|
|
1802
|
-
command: "
|
|
1802
|
+
command: hookDispatcherCommand("verify-current-state")
|
|
1803
1803
|
}]
|
|
1804
1804
|
}],
|
|
1805
1805
|
PreToolUse: [{
|
|
@@ -272,9 +272,9 @@ export default function cclawPlugin(ctx) {
|
|
|
272
272
|
});
|
|
273
273
|
}
|
|
274
274
|
|
|
275
|
-
async function runHookScript(
|
|
275
|
+
async function runHookScript(hookName, payload = {}) {
|
|
276
276
|
const { spawn } = await import("node:child_process");
|
|
277
|
-
const
|
|
277
|
+
const hookRuntimePath = join(root, "${RUNTIME_ROOT}/hooks/run-hook.mjs");
|
|
278
278
|
const input = typeof payload === "string" ? payload : JSON.stringify(payload ?? {});
|
|
279
279
|
return scheduleHookTask(() => new Promise((resolve) => {
|
|
280
280
|
let stderr = "";
|
|
@@ -287,7 +287,7 @@ export default function cclawPlugin(ctx) {
|
|
|
287
287
|
|
|
288
288
|
let child;
|
|
289
289
|
try {
|
|
290
|
-
child = spawn(
|
|
290
|
+
child = spawn(process.execPath, [hookRuntimePath, hookName], {
|
|
291
291
|
cwd: root,
|
|
292
292
|
stdio: ["pipe", "ignore", "pipe"]
|
|
293
293
|
});
|
|
@@ -299,7 +299,7 @@ export default function cclawPlugin(ctx) {
|
|
|
299
299
|
const timer = setTimeout(() => {
|
|
300
300
|
child.kill("SIGKILL");
|
|
301
301
|
if (stderr.length > 0) {
|
|
302
|
-
console.error("[cclaw] opencode hook timeout: " +
|
|
302
|
+
console.error("[cclaw] opencode hook timeout: " + hookName + " stderr=" + stderr.slice(-1200));
|
|
303
303
|
}
|
|
304
304
|
finish(false);
|
|
305
305
|
}, 20_000);
|
|
@@ -318,7 +318,7 @@ export default function cclawPlugin(ctx) {
|
|
|
318
318
|
clearTimeout(timer);
|
|
319
319
|
const ok = code === 0;
|
|
320
320
|
if (!ok && stderr.length > 0) {
|
|
321
|
-
console.error("[cclaw] opencode hook failed: " +
|
|
321
|
+
console.error("[cclaw] opencode hook failed: " + hookName + " stderr=" + stderr.slice(-1200));
|
|
322
322
|
}
|
|
323
323
|
finish(ok);
|
|
324
324
|
});
|
package/dist/doctor.js
CHANGED
|
@@ -879,7 +879,7 @@ export async function doctorChecks(projectRoot, options = {}) {
|
|
|
879
879
|
const codexWiringOk = codexSessionCmds.some((cmd) => cmd.includes("session-start.sh")) &&
|
|
880
880
|
codexUserPromptCmds.some((cmd) => cmd.includes("prompt-guard.sh")) &&
|
|
881
881
|
codexUserPromptCmds.some((cmd) => cmd.includes("workflow-guard.sh")) &&
|
|
882
|
-
codexUserPromptCmds.some((cmd) => cmd.includes("verify-current-state
|
|
882
|
+
codexUserPromptCmds.some((cmd) => cmd.includes("verify-current-state")) &&
|
|
883
883
|
codexPreCmds.some((cmd) => cmd.includes("prompt-guard.sh")) &&
|
|
884
884
|
codexPreCmds.some((cmd) => cmd.includes("workflow-guard.sh")) &&
|
|
885
885
|
codexPostCmds.some((cmd) => cmd.includes("context-monitor.sh")) &&
|
package/dist/install.js
CHANGED
|
@@ -1356,12 +1356,13 @@ function stripManagedHookCommands(value) {
|
|
|
1356
1356
|
function isManagedRuntimeHookCommand(command) {
|
|
1357
1357
|
const normalized = command.trim().replace(/\s+/gu, " ");
|
|
1358
1358
|
if (/(^|\s)(?:bash\s+)?(?:\.\/)?\.cclaw\/hooks\/(?:session-start|stop-checkpoint|pre-compact|prompt-guard|workflow-guard|context-monitor)\.sh(?:\s|$)/u.test(normalized) ||
|
|
1359
|
-
/(^|\s)(?:bash\s+)?(?:\.\/)?\.cclaw\/hooks\/run-hook\.cmd\s+(?:session-start|stop-checkpoint|pre-compact|prompt-guard|workflow-guard|context-monitor)(?:\.sh)?(?:\s|$)/u.test(normalized)
|
|
1359
|
+
/(^|\s)(?:bash\s+)?(?:\.\/)?\.cclaw\/hooks\/run-hook\.cmd\s+(?:session-start|stop-checkpoint|pre-compact|prompt-guard|workflow-guard|context-monitor)(?:\.sh)?(?:\s|$)/u.test(normalized) ||
|
|
1360
|
+
/(^|\s)(?:node\s+)?(?:"|')?(?:\.\/)?\.cclaw\/hooks\/run-hook\.mjs(?:"|')?\s+(?:session-start|stop-checkpoint|pre-compact|prompt-guard|workflow-guard|context-monitor|verify-current-state)(?:\.sh)?(?:\s|$)/u.test(normalized)) {
|
|
1360
1361
|
return true;
|
|
1361
1362
|
}
|
|
1362
1363
|
// Codex UserPromptSubmit non-blocking state nudge:
|
|
1363
|
-
//
|
|
1364
|
-
return /internal verify-current-state
|
|
1364
|
+
// legacy shell and newer Node wrappers call this internal command.
|
|
1365
|
+
return /internal verify-current-state(?:\s|$)/u.test(normalized);
|
|
1365
1366
|
}
|
|
1366
1367
|
async function removeManagedHookEntries(hookFilePath) {
|
|
1367
1368
|
if (!(await exists(hookFilePath)))
|