Some checks failed
✅ Check / 🔬 ESLint (push) Failing after 21s
✅ Check / 🏷️ Typecheck (push) Failing after 11s
✅ Check / 🔎 Test (push) Failing after 11s
✅ Check / e2e-test (push) Failing after 11s
✅ Check / 🔨 Build (push) Failing after 11s
🚀 Deploy / 🚀 Deploy (doc) (push) Failing after 12s
🚀 Deploy / 🚀 Deploy (demo) (push) Failing after 12s
🚀 Deploy / 🚀 Deploy (supabase) (push) Failing after 18s
35 lines
1.2 KiB
JavaScript
Executable File
35 lines
1.2 KiB
JavaScript
Executable File
#!/usr/bin/env node
|
|
// Stop: drop a per-session sentinel file so a managed launcher (e.g. CRM
|
|
// Builder's chat-service PtySession) knows the turn is complete. Stop fires after
|
|
// the JSONL transcript is fully written, so the watcher can emit its result event
|
|
// only once the transcript is flushed.
|
|
//
|
|
// The sentinel directory is a launcher extension point: config.launcher
|
|
// .turnSentinelDir (see .claude/rules/launcher-interface.md). When it is unset
|
|
// (no managed launcher), this hook is INERT: no directory is created, no path is
|
|
// hardcoded. Atomic CRM's config sets it to /tmp/pty-sentinels, preserving the
|
|
// current CRM Builder behavior.
|
|
|
|
import { closeSync, mkdirSync, openSync, readFileSync } from "node:fs";
|
|
import { join } from "node:path";
|
|
import { loadConfig, launcher } from "./lib/config.mjs";
|
|
|
|
let sid = "";
|
|
try {
|
|
sid = JSON.parse(readFileSync(0, "utf8")).session_id || "";
|
|
} catch {
|
|
// no session id -> nothing to signal
|
|
}
|
|
|
|
let dir = null;
|
|
try {
|
|
dir = launcher(loadConfig()).turnSentinelDir || null;
|
|
} catch {
|
|
dir = null; // fail-open: a config error must never break the Stop hook
|
|
}
|
|
|
|
if (sid && dir) {
|
|
mkdirSync(dir, { recursive: true });
|
|
closeSync(openSync(join(dir, `pty-turn-done-${sid}`), "w"));
|
|
}
|