Files

141 lines
4.9 KiB
TypeScript
Raw Permalink Normal View History

import { describe, it } from "node:test";
import assert from "node:assert/strict";
import fs from "node:fs";
import os from "node:os";
import path from "node:path";
import { fileURLToPath } from "node:url";
import {
parseHookPayload,
resolveSessionForHook,
runHookTick,
shouldEmitAnnotation,
} from "../src/hook.js";
import { findSessionDirById } from "../src/session.js";
import { formatCompactLine, writeStatusFiles } from "../src/status.js";
import { loadSnapshotFromDir } from "../src/session.js";
import { installGlobalHooks, buildHookManifest } from "../src/install.js";
const pkgRoot = path.join(path.dirname(fileURLToPath(import.meta.url)), "..", "..");
const fixtureSession = path.join(pkgRoot, "fixtures", "session");
describe("hook / live status", () => {
it("parses hook payload sessionId", () => {
const p = parseHookPayload(
JSON.stringify({ sessionId: "abc", cwd: "/tmp/x", hookEventName: "stop" }),
);
assert.equal(p.sessionId, "abc");
assert.equal(p.cwd, "/tmp/x");
});
it("formatCompactLine includes context percent from fixture", () => {
const snap = loadSnapshotFromDir(fixtureSession)!;
assert.ok(snap);
const line = formatCompactLine(snap, null);
assert.match(line, /\[hud\]/);
assert.match(line, /37%/);
assert.match(line, /Grok 4\.5|ctx|tools/);
});
it("writeStatusFiles creates status-line.txt", () => {
const tmp = fs.mkdtempSync(path.join(os.tmpdir(), "hud-"));
const snap = loadSnapshotFromDir(fixtureSession)!;
const r = writeStatusFiles(snap, null, tmp);
assert.ok(fs.existsSync(r.compactPath));
const text = fs.readFileSync(r.compactPath, "utf8");
assert.match(text, /37%/);
fs.rmSync(tmp, { recursive: true, force: true });
});
it("runHookTick against fixture via session-dir home layout", async () => {
const tmp = fs.mkdtempSync(path.join(os.tmpdir(), "hud-home-"));
// Build mini grok home with fixture session
const sid = "fixture-session-001";
const dir = path.join(
tmp,
"sessions",
encodeURIComponent("/Users/dex/demo/CoachFlow"),
sid,
);
fs.mkdirSync(dir, { recursive: true });
for (const f of ["signals.json", "summary.json", "updates.jsonl"]) {
fs.copyFileSync(path.join(fixtureSession, f), path.join(dir, f));
}
fs.writeFileSync(
path.join(tmp, "active_sessions.json"),
JSON.stringify([
{
session_id: sid,
pid: process.pid,
cwd: "/Users/dex/demo/CoachFlow",
},
]),
);
const found = findSessionDirById(tmp, sid);
assert.ok(found);
const result = await runHookTick({
payloadRaw: JSON.stringify({ sessionId: sid, hookEventName: "stop" }),
env: {
GROK_SESSION_ID: sid,
GROK_HOOK_EVENT: "stop",
},
grokHome: tmp,
forceAnnotate: true,
noUsage: true,
});
assert.equal(result.code, 0);
assert.ok(result.compact);
assert.match(result.compact!, /37%/);
assert.ok(fs.existsSync(path.join(tmp, "hud", "status-line.txt")));
fs.rmSync(tmp, { recursive: true, force: true });
});
it("shouldEmitAnnotation always true for Stop", () => {
const tmp = fs.mkdtempSync(path.join(os.tmpdir(), "hud-th-"));
assert.equal(shouldEmitAnnotation("stop", tmp), true);
assert.equal(shouldEmitAnnotation("Stop", tmp), true);
fs.rmSync(tmp, { recursive: true, force: true });
});
it("buildHookManifest points at node + hook.js", () => {
const m = buildHookManifest("/abs/hook.js") as {
hooks: { Stop: { hooks: { command: string }[] }[] };
};
assert.match(m.hooks.Stop[0]!.hooks[0]!.command, /hook\.js/);
});
it("installGlobalHooks writes ~/.grok style hooks file", () => {
const tmp = fs.mkdtempSync(path.join(os.tmpdir(), "hud-inst-"));
// ensure dist hook exists (built)
const hookJs = path.join(pkgRoot, "dist", "src", "hook.js");
assert.ok(fs.existsSync(hookJs), "dist must be built before this test");
const { hooksPath } = installGlobalHooks({ grokHome: tmp, root: pkgRoot });
assert.ok(fs.existsSync(hooksPath));
const body = fs.readFileSync(hooksPath, "utf8");
assert.match(body, /Stop/);
assert.match(body, /hook\.js/);
fs.rmSync(tmp, { recursive: true, force: true });
});
it("resolveSessionForHook uses env session id", () => {
const tmp = fs.mkdtempSync(path.join(os.tmpdir(), "hud-res-"));
const sid = "fixture-session-001";
const dir = path.join(tmp, "sessions", "proj", sid);
fs.mkdirSync(dir, { recursive: true });
for (const f of ["signals.json", "summary.json", "updates.jsonl"]) {
fs.copyFileSync(path.join(fixtureSession, f), path.join(dir, f));
}
const snap = resolveSessionForHook(
{},
{ GROK_SESSION_ID: sid },
tmp,
);
assert.ok(snap);
assert.equal(snap!.sessionId, sid);
assert.equal(snap!.contextPercent, 37);
fs.rmSync(tmp, { recursive: true, force: true });
});
});