bb-cc-lite 0.1.0 → 0.1.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/README.md +10 -2
- package/assets/statusline-demo.gif +0 -0
- package/dist/cli.js +8 -44
- package/dist/cli.js.map +1 -1
- package/dist/decision-presentation.d.ts +9 -0
- package/dist/decision-presentation.js +10 -0
- package/dist/decision-presentation.js.map +1 -0
- package/dist/event-store-persistence.d.ts +5 -0
- package/dist/event-store-persistence.js +41 -0
- package/dist/event-store-persistence.js.map +1 -0
- package/dist/event-store-queries.d.ts +9 -0
- package/dist/event-store-queries.js +47 -0
- package/dist/event-store-queries.js.map +1 -0
- package/dist/hook-payload.d.ts +3 -0
- package/dist/hook-payload.js +90 -0
- package/dist/hook-payload.js.map +1 -0
- package/dist/hook-summary.d.ts +12 -0
- package/dist/hook-summary.js +25 -0
- package/dist/hook-summary.js.map +1 -0
- package/dist/hooks.d.ts +2 -14
- package/dist/hooks.js +2 -126
- package/dist/hooks.js.map +1 -1
- package/dist/renderer.d.ts +2 -2
- package/dist/renderer.js.map +1 -1
- package/dist/session.d.ts +3 -0
- package/dist/session.js +9 -0
- package/dist/session.js.map +1 -0
- package/dist/settings.js +1 -1
- package/dist/settings.js.map +1 -1
- package/dist/signals.js +2 -2
- package/dist/signals.js.map +1 -1
- package/dist/statusline.d.ts +1 -0
- package/dist/statusline.js +33 -0
- package/dist/statusline.js.map +1 -0
- package/dist/store.d.ts +3 -10
- package/dist/store.js +3 -84
- package/dist/store.js.map +1 -1
- package/dist/tool-metadata.d.ts +8 -0
- package/dist/tool-metadata.js +31 -0
- package/dist/tool-metadata.js.map +1 -0
- package/dist/transcript-reader.d.ts +9 -0
- package/dist/transcript-reader.js +45 -0
- package/dist/transcript-reader.js.map +1 -0
- package/dist/transcript.d.ts +2 -3
- package/dist/transcript.js +11 -63
- package/dist/transcript.js.map +1 -1
- package/dist/why.d.ts +7 -0
- package/dist/why.js +16 -0
- package/dist/why.js.map +1 -0
- package/package.json +7 -7
package/README.md
CHANGED
|
@@ -8,6 +8,8 @@ Claude Code does not always fail loudly. Sometimes it loops, fills context, spen
|
|
|
8
8
|
|
|
9
9
|

|
|
10
10
|
|
|
11
|
+
The demo above is generated from real `bb-cc-lite statusline` output.
|
|
12
|
+
|
|
11
13
|
## Install
|
|
12
14
|
|
|
13
15
|
```bash
|
|
@@ -28,8 +30,8 @@ Hooks are optional. They run in the background and skip `UserPromptSubmit`.
|
|
|
28
30
|
|
|
29
31
|
```text
|
|
30
32
|
bb: Healthy | ctx 42% | $0.18 | cache warm | continue normally
|
|
31
|
-
bb: Careful | ctx 82% |
|
|
32
|
-
bb: Stop | Bash failed 3x running tests | fix the test setup manually, then ask Claude to rerun only that test
|
|
33
|
+
bb: Careful | ctx 82% | Context is getting tight | ask Claude for a 6-bullet handoff before more work
|
|
34
|
+
bb: Stop | why: Bash failed 3x running tests | do: fix the test setup manually, then ask Claude to rerun only that test
|
|
33
35
|
```
|
|
34
36
|
|
|
35
37
|
`Healthy` means keep going. `Careful` means slow down. `Stop` means take over before Claude burns more turns.
|
|
@@ -46,6 +48,12 @@ Reason: Bash failed 3x running tests. Claude is retrying a broken test loop.
|
|
|
46
48
|
Next action: fix the test setup manually, then ask Claude to rerun only that test.
|
|
47
49
|
```
|
|
48
50
|
|
|
51
|
+
By default, `why` explains the latest recorded decision. To inspect a specific Claude Code session, pass its session id:
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
bb-cc-lite why --session <session-id>
|
|
55
|
+
```
|
|
56
|
+
|
|
49
57
|
## Privacy
|
|
50
58
|
|
|
51
59
|
By default, `bb-cc-lite` does not upload transcripts, store raw prompts, store raw tool output, store file contents, or print raw prompt/tool text.
|
|
Binary file
|
package/dist/cli.js
CHANGED
|
@@ -1,14 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { formatDoctorChecks, runDoctor } from "./doctor.js";
|
|
3
|
-
import {
|
|
4
|
-
import { hashValue } from "./paths.js";
|
|
5
|
-
import { estimateCostUsd, loadPricing } from "./pricing.js";
|
|
6
|
-
import { renderStatusLine } from "./renderer.js";
|
|
7
|
-
import { decide } from "./signals.js";
|
|
3
|
+
import { parseHookPayload } from "./hook-payload.js";
|
|
8
4
|
import { installStatusLine, uninstallStatusLine } from "./settings.js";
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
5
|
+
import { readStdin } from "./status-input.js";
|
|
6
|
+
import { createStatusLine } from "./statusline.js";
|
|
7
|
+
import { recordHookEvent } from "./store.js";
|
|
8
|
+
import { formatWhy, getWhyDecision } from "./why.js";
|
|
12
9
|
async function main() {
|
|
13
10
|
const args = parseArgs(process.argv.slice(2));
|
|
14
11
|
switch (args.command) {
|
|
@@ -77,29 +74,7 @@ async function commandUninstall(args) {
|
|
|
77
74
|
async function commandStatusLine() {
|
|
78
75
|
try {
|
|
79
76
|
const raw = await readStdin();
|
|
80
|
-
|
|
81
|
-
const sessionKey = hashValue(input.sessionId);
|
|
82
|
-
const transcript = mergeHookSummary(await parseTranscriptTail(input.transcriptPath), sessionKey
|
|
83
|
-
? await hookSummary(sessionKey)
|
|
84
|
-
: {
|
|
85
|
-
failedToolResults: 0,
|
|
86
|
-
toolCalls: 0,
|
|
87
|
-
compactionEvents: 0,
|
|
88
|
-
repeatedFailures: []
|
|
89
|
-
});
|
|
90
|
-
const usage = mergeUsage(input.usage, transcript.usage);
|
|
91
|
-
if (input.costUsd === undefined) {
|
|
92
|
-
const estimated = estimateCostUsd(input.model.id || input.model.displayName, usage, await loadPricing());
|
|
93
|
-
if (estimated !== undefined) {
|
|
94
|
-
input.costUsd = estimated;
|
|
95
|
-
input.costSource = "estimated";
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
const previous = sessionKey ? await latestDecision(sessionKey) : undefined;
|
|
99
|
-
const decision = decide(input, transcript, { previous });
|
|
100
|
-
await recordDecision(decision);
|
|
101
|
-
const width = input.terminalWidth || process.stdout.columns;
|
|
102
|
-
process.stdout.write(`${renderStatusLine(decision, width)}\n`);
|
|
77
|
+
process.stdout.write(`${await createStatusLine(raw, process.stdout.columns)}\n`);
|
|
103
78
|
}
|
|
104
79
|
catch {
|
|
105
80
|
process.stdout.write("bb: Careful | statusline crashed | run bb-cc-lite doctor\n");
|
|
@@ -118,8 +93,7 @@ async function commandHook(args) {
|
|
|
118
93
|
}
|
|
119
94
|
}
|
|
120
95
|
async function commandWhy(args) {
|
|
121
|
-
const
|
|
122
|
-
const decision = await latestDecision(sessionKey);
|
|
96
|
+
const decision = await getWhyDecision({ sessionId: stringFlag(args, "session") });
|
|
123
97
|
if (args.flags.json) {
|
|
124
98
|
console.log(JSON.stringify(decision || null, null, 2));
|
|
125
99
|
return;
|
|
@@ -143,16 +117,6 @@ async function commandDoctor(args) {
|
|
|
143
117
|
process.exitCode = 1;
|
|
144
118
|
}
|
|
145
119
|
}
|
|
146
|
-
function formatWhy(decision) {
|
|
147
|
-
const cost = decision.costUsd === undefined
|
|
148
|
-
? ""
|
|
149
|
-
: `\nCost evidence: ${decision.costSource === "estimated" ? "estimated " : ""}$${decision.costUsd.toFixed(4)}.`;
|
|
150
|
-
return [
|
|
151
|
-
`Last decision: ${decision.state}.`,
|
|
152
|
-
`Reason: ${decision.primaryEvidence}. ${decision.impact}.`,
|
|
153
|
-
`Next action: ${decision.action}.${cost}`
|
|
154
|
-
].join("\n");
|
|
155
|
-
}
|
|
156
120
|
function parseArgs(argv) {
|
|
157
121
|
const [command = "help", ...rest] = argv;
|
|
158
122
|
const flags = {};
|
|
@@ -196,7 +160,7 @@ function printHelp() {
|
|
|
196
160
|
Usage:
|
|
197
161
|
bb-cc-lite install [--scope local|project|user] [--replace] [--hooks]
|
|
198
162
|
bb-cc-lite statusline
|
|
199
|
-
bb-cc-lite why [--json]
|
|
163
|
+
bb-cc-lite why [--session <id>] [--json]
|
|
200
164
|
bb-cc-lite doctor [--scope local|project|user] [--transcript <path>] [--refresh-pricing]
|
|
201
165
|
bb-cc-lite uninstall [--scope local|project|user]
|
|
202
166
|
`);
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,kBAAkB,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAC5D,OAAO,EAAE,gBAAgB,EAAE,
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,kBAAkB,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAC5D,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,EAAE,iBAAiB,EAAE,mBAAmB,EAAsB,MAAM,eAAe,CAAC;AAC3F,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAC9C,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACnD,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAQrD,KAAK,UAAU,IAAI;IACjB,MAAM,IAAI,GAAG,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IAC9C,QAAQ,IAAI,CAAC,OAAO,EAAE,CAAC;QACrB,KAAK,SAAS;YACZ,MAAM,cAAc,CAAC,IAAI,CAAC,CAAC;YAC3B,MAAM;QACR,KAAK,WAAW;YACd,MAAM,gBAAgB,CAAC,IAAI,CAAC,CAAC;YAC7B,MAAM;QACR,KAAK,YAAY;YACf,MAAM,iBAAiB,EAAE,CAAC;YAC1B,MAAM;QACR,KAAK,KAAK;YACR,MAAM,UAAU,CAAC,IAAI,CAAC,CAAC;YACvB,MAAM;QACR,KAAK,QAAQ;YACX,MAAM,aAAa,CAAC,IAAI,CAAC,CAAC;YAC1B,MAAM;QACR,KAAK,MAAM;YACT,MAAM,WAAW,CAAC,IAAI,CAAC,CAAC;YACxB,MAAM;QACR,KAAK,MAAM,CAAC;QACZ,KAAK,QAAQ,CAAC;QACd,KAAK,IAAI;YACP,SAAS,EAAE,CAAC;YACZ,MAAM;QACR;YACE,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;gBAClB,SAAS,EAAE,CAAC;YACd,CAAC;iBAAM,CAAC;gBACN,OAAO,CAAC,KAAK,CAAC,oBAAoB,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC;gBAClD,SAAS,EAAE,CAAC;gBACZ,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;YACvB,CAAC;IACL,CAAC;AACH,CAAC;AAED,KAAK,UAAU,cAAc,CAAC,IAAgB;IAC5C,MAAM,MAAM,GAAG,MAAM,iBAAiB,CAAC;QACrC,KAAK,EAAE,SAAS,CAAC,IAAI,CAAC;QACtB,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC;QACpC,KAAK,EAAE,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC;QAChC,UAAU,EAAE,UAAU,CAAC,IAAI,EAAE,SAAS,CAAC;QACvC,OAAO,EAAE,UAAU,CAAC,IAAI,EAAE,MAAM,CAAC;KAClC,CAAC,CAAC;IACH,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAC5B,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;QACnB,OAAO,CAAC,GAAG,CAAC,YAAY,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC;IAC5C,CAAC;IACD,IAAI,MAAM,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;QAChC,OAAO,CAAC,GAAG,CAAC,8CAA8C,MAAM,CAAC,MAAM,CAAC,KAAK,YAAY,CAAC,CAAC;IAC7F,CAAC;AACH,CAAC;AAED,KAAK,UAAU,gBAAgB,CAAC,IAAgB;IAC9C,MAAM,MAAM,GAAG,MAAM,mBAAmB,CAAC;QACvC,KAAK,EAAE,SAAS,CAAC,IAAI,CAAC;QACtB,KAAK,EAAE,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC;QAChC,UAAU,EAAE,UAAU,CAAC,IAAI,EAAE,SAAS,CAAC;QACvC,OAAO,EAAE,UAAU,CAAC,IAAI,EAAE,MAAM,CAAC;KAClC,CAAC,CAAC;IACH,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAC5B,IAAI,MAAM,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;QAChC,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;IACvB,CAAC;AACH,CAAC;AAED,KAAK,UAAU,iBAAiB;IAC9B,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,SAAS,EAAE,CAAC;QAC9B,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,MAAM,gBAAgB,CAAC,GAAG,EAAE,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IACnF,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,4DAA4D,CAAC,CAAC;IACrF,CAAC;AACH,CAAC;AAED,KAAK,UAAU,WAAW,CAAC,IAAgB;IACzC,IAAI,CAAC;QACH,MAAM,iBAAiB,GACrB,UAAU,CAAC,IAAI,EAAE,iBAAiB,CAAC,IAAI,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,KAAK,mBAAmB,CAAC,CAAC;QACzG,MAAM,KAAK,GAAG,gBAAgB,CAAC,MAAM,SAAS,EAAE,EAAE,iBAAiB,CAAC,CAAC;QACrE,IAAI,KAAK,EAAE,CAAC;YACV,MAAM,eAAe,CAAC,KAAK,CAAC,CAAC;QAC/B,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,6DAA6D;IAC/D,CAAC;AACH,CAAC;AAED,KAAK,UAAU,UAAU,CAAC,IAAgB;IACxC,MAAM,QAAQ,GAAG,MAAM,cAAc,CAAC,EAAE,SAAS,EAAE,UAAU,CAAC,IAAI,EAAE,SAAS,CAAC,EAAE,CAAC,CAAC;IAClF,IAAI,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;QACpB,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,QAAQ,IAAI,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QACvD,OAAO;IACT,CAAC;IACD,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,OAAO,CAAC,GAAG,CAAC,kGAAkG,CAAC,CAAC;QAChH,OAAO;IACT,CAAC;IACD,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC;AACnC,CAAC;AAED,KAAK,UAAU,aAAa,CAAC,IAAgB;IAC3C,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC;QAC7B,KAAK,EAAE,SAAS,CAAC,IAAI,CAAC;QACtB,UAAU,EAAE,UAAU,CAAC,IAAI,EAAE,SAAS,CAAC;QACvC,OAAO,EAAE,UAAU,CAAC,IAAI,EAAE,MAAM,CAAC;QACjC,cAAc,EAAE,UAAU,CAAC,IAAI,EAAE,YAAY,CAAC;QAC9C,cAAc,EAAE,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC;KACvD,CAAC,CAAC;IACH,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC,MAAM,CAAC,CAAC,CAAC;IACxC,IAAI,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,KAAK,KAAK,MAAM,CAAC,EAAE,CAAC;QACnD,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;IACvB,CAAC;AACH,CAAC;AAED,SAAS,SAAS,CAAC,IAAc;IAC/B,MAAM,CAAC,OAAO,GAAG,MAAM,EAAE,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC;IACzC,MAAM,KAAK,GAAqC,EAAE,CAAC;IACnD,MAAM,WAAW,GAAa,EAAE,CAAC;IACjC,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,IAAI,CAAC,MAAM,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC;QACpD,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC;QACxB,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;YAC1B,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YACtB,SAAS;QACX,CAAC;QACD,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;QACzD,IAAI,WAAW,KAAK,SAAS,EAAE,CAAC;YAC9B,KAAK,CAAC,MAAM,CAAC,GAAG,WAAW,CAAC;YAC5B,SAAS;QACX,CAAC;QACD,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC;QAC7B,IAAI,IAAI,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;YACnC,KAAK,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC;YACrB,KAAK,IAAI,CAAC,CAAC;QACb,CAAC;aAAM,CAAC;YACN,KAAK,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC;QACvB,CAAC;IACH,CAAC;IACD,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,WAAW,EAAE,CAAC;AACzC,CAAC;AAED,SAAS,SAAS,CAAC,IAAgB;IACjC,MAAM,KAAK,GAAG,UAAU,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,OAAO,CAAC;IACnD,IAAI,KAAK,KAAK,OAAO,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,MAAM,EAAE,CAAC;QACjE,OAAO,KAAK,CAAC;IACf,CAAC;IACD,MAAM,IAAI,KAAK,CAAC,mBAAmB,KAAK,oCAAoC,CAAC,CAAC;AAChF,CAAC;AAED,SAAS,UAAU,CAAC,IAAgB,EAAE,IAAY;IAChD,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC/B,OAAO,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;AACvD,CAAC;AAED,SAAS,SAAS;IAChB,OAAO,CAAC,GAAG,CAAC;;;;;;;;CAQb,CAAC,CAAC;AACH,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,KAAc,EAAE,EAAE;IAC9B,OAAO,CAAC,KAAK,CAAC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;IACtE,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;AACvB,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { Decision, DecisionEvidence, DecisionState } from "./types.js";
|
|
2
|
+
export interface DecisionPresentation {
|
|
3
|
+
state: DecisionState;
|
|
4
|
+
primaryEvidence: string;
|
|
5
|
+
evidence: DecisionEvidence[];
|
|
6
|
+
impact: string;
|
|
7
|
+
action: string;
|
|
8
|
+
}
|
|
9
|
+
export declare function toDecisionPresentation(decision: Decision): DecisionPresentation;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export function toDecisionPresentation(decision) {
|
|
2
|
+
return {
|
|
3
|
+
state: decision.state,
|
|
4
|
+
primaryEvidence: decision.primaryEvidence,
|
|
5
|
+
evidence: decision.evidence,
|
|
6
|
+
impact: decision.impact,
|
|
7
|
+
action: decision.action
|
|
8
|
+
};
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=decision-presentation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"decision-presentation.js","sourceRoot":"","sources":["../src/decision-presentation.ts"],"names":[],"mappings":"AAUA,MAAM,UAAU,sBAAsB,CAAC,QAAkB;IACvD,OAAO;QACL,KAAK,EAAE,QAAQ,CAAC,KAAK;QACrB,eAAe,EAAE,QAAQ,CAAC,eAAe;QACzC,QAAQ,EAAE,QAAQ,CAAC,QAAQ;QAC3B,MAAM,EAAE,QAAQ,CAAC,MAAM;QACvB,MAAM,EAAE,QAAQ,CAAC,MAAM;KACxB,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { EventStoreData } from "./types.js";
|
|
2
|
+
export declare const STORE_LIMIT = 100;
|
|
3
|
+
export declare const HOOK_STORE_LIMIT = 500;
|
|
4
|
+
export declare function readStore(storePath?: string): Promise<EventStoreData>;
|
|
5
|
+
export declare function writeStore(store: EventStoreData, storePath: string): Promise<void>;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { chmod, mkdir, readFile, rename, writeFile } from "node:fs/promises";
|
|
2
|
+
import { dirname } from "node:path";
|
|
3
|
+
import { eventStorePath } from "./paths.js";
|
|
4
|
+
export const STORE_LIMIT = 100;
|
|
5
|
+
export const HOOK_STORE_LIMIT = 500;
|
|
6
|
+
export async function readStore(storePath = eventStorePath()) {
|
|
7
|
+
try {
|
|
8
|
+
const parsed = JSON.parse(await readFile(storePath, "utf8"));
|
|
9
|
+
return {
|
|
10
|
+
version: 1,
|
|
11
|
+
updatedAt: typeof parsed.updatedAt === "string" ? parsed.updatedAt : new Date(0).toISOString(),
|
|
12
|
+
decisions: Array.isArray(parsed.decisions) ? parsed.decisions.filter(isStoredDecision).slice(-STORE_LIMIT) : [],
|
|
13
|
+
hookEvents: Array.isArray(parsed.hookEvents) ? parsed.hookEvents.filter(isStoredHookEvent).slice(-HOOK_STORE_LIMIT) : []
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
catch {
|
|
17
|
+
return { version: 1, updatedAt: new Date(0).toISOString(), decisions: [], hookEvents: [] };
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
export async function writeStore(store, storePath) {
|
|
21
|
+
await mkdir(dirname(storePath), { recursive: true, mode: 0o700 });
|
|
22
|
+
const tempPath = `${storePath}.${process.pid}.tmp`;
|
|
23
|
+
await writeFile(tempPath, `${JSON.stringify(store, null, 2)}\n`, { encoding: "utf8", mode: 0o600 });
|
|
24
|
+
await chmod(tempPath, 0o600);
|
|
25
|
+
await rename(tempPath, storePath);
|
|
26
|
+
}
|
|
27
|
+
function isStoredDecision(value) {
|
|
28
|
+
if (typeof value !== "object" || value === null) {
|
|
29
|
+
return false;
|
|
30
|
+
}
|
|
31
|
+
const record = value;
|
|
32
|
+
return typeof record.id === "string" && typeof record.state === "string" && typeof record.action === "string";
|
|
33
|
+
}
|
|
34
|
+
function isStoredHookEvent(value) {
|
|
35
|
+
if (typeof value !== "object" || value === null) {
|
|
36
|
+
return false;
|
|
37
|
+
}
|
|
38
|
+
const record = value;
|
|
39
|
+
return typeof record.id === "string" && typeof record.kind === "string" && typeof record.timestamp === "string";
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=event-store-persistence.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"event-store-persistence.js","sourceRoot":"","sources":["../src/event-store-persistence.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { StoredDecision, ToolFailureSummary } from "./types.js";
|
|
2
|
+
export declare function latestDecision(sessionKey?: string, storePath?: string): Promise<StoredDecision | undefined>;
|
|
3
|
+
export declare function hookSummary(sessionKey: string | undefined, storePath?: string): Promise<{
|
|
4
|
+
failedToolResults: number;
|
|
5
|
+
toolCalls: number;
|
|
6
|
+
compactionEvents: number;
|
|
7
|
+
repeatedFailures: ToolFailureSummary[];
|
|
8
|
+
latestTimestamp?: string;
|
|
9
|
+
}>;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { readStore } from "./event-store-persistence.js";
|
|
2
|
+
export async function latestDecision(sessionKey, storePath) {
|
|
3
|
+
const store = await readStore(storePath);
|
|
4
|
+
const decisions = sessionKey ? store.decisions.filter((decision) => decision.sessionKey === sessionKey) : store.decisions;
|
|
5
|
+
return decisions.at(-1);
|
|
6
|
+
}
|
|
7
|
+
export async function hookSummary(sessionKey, storePath) {
|
|
8
|
+
const store = await readStore(storePath);
|
|
9
|
+
const events = store.hookEvents.filter((event) => !sessionKey || event.sessionKey === sessionKey);
|
|
10
|
+
const failures = new Map();
|
|
11
|
+
let failedToolResults = 0;
|
|
12
|
+
let toolCalls = 0;
|
|
13
|
+
let compactionEvents = 0;
|
|
14
|
+
let latestTimestamp;
|
|
15
|
+
for (const event of events) {
|
|
16
|
+
latestTimestamp = !latestTimestamp || event.timestamp > latestTimestamp ? event.timestamp : latestTimestamp;
|
|
17
|
+
if (event.kind === "tool_failure") {
|
|
18
|
+
failedToolResults += 1;
|
|
19
|
+
toolCalls += 1;
|
|
20
|
+
const toolName = event.toolName || "tool";
|
|
21
|
+
const key = `${toolName}:${event.purpose || ""}`;
|
|
22
|
+
const existing = failures.get(key);
|
|
23
|
+
failures.set(key, {
|
|
24
|
+
toolName,
|
|
25
|
+
purpose: event.purpose,
|
|
26
|
+
count: (existing?.count || 0) + 1
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
else if (event.kind === "tool_success") {
|
|
30
|
+
toolCalls += 1;
|
|
31
|
+
}
|
|
32
|
+
else if (event.kind === "tool_batch") {
|
|
33
|
+
toolCalls += event.toolCount || 0;
|
|
34
|
+
}
|
|
35
|
+
else if (event.kind === "compaction") {
|
|
36
|
+
compactionEvents += 1;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
return {
|
|
40
|
+
failedToolResults,
|
|
41
|
+
toolCalls,
|
|
42
|
+
compactionEvents,
|
|
43
|
+
repeatedFailures: [...failures.values()].filter((failure) => failure.count >= 2),
|
|
44
|
+
latestTimestamp
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=event-store-queries.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"event-store-queries.js","sourceRoot":"","sources":["../src/event-store-queries.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,8BAA8B,CAAC;AAGzD,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,UAAmB,EAAE,SAAkB;IAC1E,MAAM,KAAK,GAAG,MAAM,SAAS,CAAC,SAAS,CAAC,CAAC;IACzC,MAAM,SAAS,GAAG,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,UAAU,KAAK,UAAU,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC;IAC1H,OAAO,SAAS,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;AAC1B,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,UAA8B,EAC9B,SAAkB;IAQlB,MAAM,KAAK,GAAG,MAAM,SAAS,CAAC,SAAS,CAAC,CAAC;IACzC,MAAM,MAAM,GAAG,KAAK,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,UAAU,IAAI,KAAK,CAAC,UAAU,KAAK,UAAU,CAAC,CAAC;IAClG,MAAM,QAAQ,GAAG,IAAI,GAAG,EAA8B,CAAC;IACvD,IAAI,iBAAiB,GAAG,CAAC,CAAC;IAC1B,IAAI,SAAS,GAAG,CAAC,CAAC;IAClB,IAAI,gBAAgB,GAAG,CAAC,CAAC;IACzB,IAAI,eAAmC,CAAC;IAExC,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,eAAe,GAAG,CAAC,eAAe,IAAI,KAAK,CAAC,SAAS,GAAG,eAAe,CAAC,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,eAAe,CAAC;QAC5G,IAAI,KAAK,CAAC,IAAI,KAAK,cAAc,EAAE,CAAC;YAClC,iBAAiB,IAAI,CAAC,CAAC;YACvB,SAAS,IAAI,CAAC,CAAC;YACf,MAAM,QAAQ,GAAG,KAAK,CAAC,QAAQ,IAAI,MAAM,CAAC;YAC1C,MAAM,GAAG,GAAG,GAAG,QAAQ,IAAI,KAAK,CAAC,OAAO,IAAI,EAAE,EAAE,CAAC;YACjD,MAAM,QAAQ,GAAG,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YACnC,QAAQ,CAAC,GAAG,CAAC,GAAG,EAAE;gBAChB,QAAQ;gBACR,OAAO,EAAE,KAAK,CAAC,OAAO;gBACtB,KAAK,EAAE,CAAC,QAAQ,EAAE,KAAK,IAAI,CAAC,CAAC,GAAG,CAAC;aAClC,CAAC,CAAC;QACL,CAAC;aAAM,IAAI,KAAK,CAAC,IAAI,KAAK,cAAc,EAAE,CAAC;YACzC,SAAS,IAAI,CAAC,CAAC;QACjB,CAAC;aAAM,IAAI,KAAK,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC;YACvC,SAAS,IAAI,KAAK,CAAC,SAAS,IAAI,CAAC,CAAC;QACpC,CAAC;aAAM,IAAI,KAAK,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC;YACvC,gBAAgB,IAAI,CAAC,CAAC;QACxB,CAAC;IACH,CAAC;IAED,OAAO;QACL,iBAAiB;QACjB,SAAS;QACT,gBAAgB;QAChB,gBAAgB,EAAE,CAAC,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,IAAI,CAAC,CAAC;QAChF,eAAe;KAChB,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import type { DerivedHookEvent } from "./types.js";
|
|
2
|
+
export declare const SAFE_HOOK_EVENTS: readonly ["PostToolUse", "PostToolUseFailure", "PostToolBatch", "PreCompact", "PostCompact", "Stop", "SessionEnd"];
|
|
3
|
+
export declare function parseHookPayload(raw: string, fallbackEventName?: string): DerivedHookEvent | undefined;
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { hashValue } from "./paths.js";
|
|
2
|
+
import { asRecord, numberField, stringField } from "./status-input.js";
|
|
3
|
+
import { classifyToolPurpose, safeToolName } from "./tool-metadata.js";
|
|
4
|
+
export const SAFE_HOOK_EVENTS = [
|
|
5
|
+
"PostToolUse",
|
|
6
|
+
"PostToolUseFailure",
|
|
7
|
+
"PostToolBatch",
|
|
8
|
+
"PreCompact",
|
|
9
|
+
"PostCompact",
|
|
10
|
+
"Stop",
|
|
11
|
+
"SessionEnd"
|
|
12
|
+
];
|
|
13
|
+
export function parseHookPayload(raw, fallbackEventName) {
|
|
14
|
+
let parsed;
|
|
15
|
+
try {
|
|
16
|
+
parsed = JSON.parse(raw.trim() || "{}");
|
|
17
|
+
}
|
|
18
|
+
catch {
|
|
19
|
+
return undefined;
|
|
20
|
+
}
|
|
21
|
+
const root = asRecord(parsed);
|
|
22
|
+
if (!root) {
|
|
23
|
+
return undefined;
|
|
24
|
+
}
|
|
25
|
+
const hookEventName = stringField(root.hook_event_name) || stringField(root.event) || fallbackEventName || "unknown";
|
|
26
|
+
const sessionId = stringField(root.session_id) || stringField(root.sessionId);
|
|
27
|
+
const base = {
|
|
28
|
+
timestamp: stringField(root.timestamp) || new Date().toISOString(),
|
|
29
|
+
hookEventName,
|
|
30
|
+
sessionKey: hashValue(sessionId)
|
|
31
|
+
};
|
|
32
|
+
if (hookEventName === "PostToolUseFailure") {
|
|
33
|
+
const toolName = safeToolName(stringField(root.tool_name) || stringField(root.toolName));
|
|
34
|
+
return {
|
|
35
|
+
...base,
|
|
36
|
+
kind: "tool_failure",
|
|
37
|
+
toolName,
|
|
38
|
+
purpose: classifyToolPurpose(toolName, root.tool_input ?? root.toolInput)
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
if (hookEventName === "PostToolUse") {
|
|
42
|
+
const toolName = safeToolName(stringField(root.tool_name) || stringField(root.toolName));
|
|
43
|
+
return {
|
|
44
|
+
...base,
|
|
45
|
+
kind: "tool_success",
|
|
46
|
+
toolName,
|
|
47
|
+
purpose: classifyToolPurpose(toolName, root.tool_input ?? root.toolInput)
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
if (hookEventName === "PostToolBatch") {
|
|
51
|
+
return {
|
|
52
|
+
...base,
|
|
53
|
+
kind: "tool_batch",
|
|
54
|
+
toolCount: countBatchTools(root)
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
if (hookEventName === "PreCompact" || hookEventName === "PostCompact") {
|
|
58
|
+
return {
|
|
59
|
+
...base,
|
|
60
|
+
kind: "compaction"
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
if (hookEventName === "Stop" || hookEventName === "StopFailure") {
|
|
64
|
+
return {
|
|
65
|
+
...base,
|
|
66
|
+
kind: "stop"
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
if (hookEventName === "SessionEnd") {
|
|
70
|
+
return {
|
|
71
|
+
...base,
|
|
72
|
+
kind: "session_end"
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
return undefined;
|
|
76
|
+
}
|
|
77
|
+
function countBatchTools(root) {
|
|
78
|
+
const values = [root.tools, root.tool_uses, root.toolUses, root.results, root.tool_results, root.toolResults];
|
|
79
|
+
for (const value of values) {
|
|
80
|
+
if (Array.isArray(value)) {
|
|
81
|
+
return value.length;
|
|
82
|
+
}
|
|
83
|
+
const count = numberField(value);
|
|
84
|
+
if (count !== undefined) {
|
|
85
|
+
return Math.max(0, Math.floor(count));
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
return 0;
|
|
89
|
+
}
|
|
90
|
+
//# sourceMappingURL=hook-payload.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hook-payload.js","sourceRoot":"","sources":["../src/hook-payload.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { TranscriptSummary } from "./types.js";
|
|
2
|
+
export declare function mergeHookSummary(transcript: TranscriptSummary, hookData: {
|
|
3
|
+
failedToolResults: number;
|
|
4
|
+
toolCalls: number;
|
|
5
|
+
compactionEvents: number;
|
|
6
|
+
repeatedFailures: Array<{
|
|
7
|
+
toolName: string;
|
|
8
|
+
count: number;
|
|
9
|
+
purpose?: string;
|
|
10
|
+
}>;
|
|
11
|
+
latestTimestamp?: string;
|
|
12
|
+
}): TranscriptSummary;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export function mergeHookSummary(transcript, hookData) {
|
|
2
|
+
const repeatedFailures = new Map();
|
|
3
|
+
for (const failure of [...transcript.repeatedFailures, ...hookData.repeatedFailures]) {
|
|
4
|
+
const key = `${failure.toolName}:${failure.purpose || ""}`;
|
|
5
|
+
const existing = repeatedFailures.get(key);
|
|
6
|
+
repeatedFailures.set(key, {
|
|
7
|
+
toolName: failure.toolName,
|
|
8
|
+
purpose: failure.purpose,
|
|
9
|
+
count: Math.max(existing?.count || 0, failure.count)
|
|
10
|
+
});
|
|
11
|
+
}
|
|
12
|
+
return {
|
|
13
|
+
...transcript,
|
|
14
|
+
toolCalls: Math.max(transcript.toolCalls, hookData.toolCalls),
|
|
15
|
+
failedToolResults: Math.max(transcript.failedToolResults, hookData.failedToolResults),
|
|
16
|
+
repeatedFailures: [...repeatedFailures.values()].filter((failure) => failure.count >= 2),
|
|
17
|
+
compactionEvents: Math.max(transcript.compactionEvents, hookData.compactionEvents),
|
|
18
|
+
latestTimestamp: transcript.latestTimestamp && hookData.latestTimestamp
|
|
19
|
+
? transcript.latestTimestamp > hookData.latestTimestamp
|
|
20
|
+
? transcript.latestTimestamp
|
|
21
|
+
: hookData.latestTimestamp
|
|
22
|
+
: transcript.latestTimestamp || hookData.latestTimestamp
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=hook-summary.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hook-summary.js","sourceRoot":"","sources":["../src/hook-summary.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,gBAAgB,CAC9B,UAA6B,EAC7B,QAMC;IAED,MAAM,gBAAgB,GAAG,IAAI,GAAG,EAAiE,CAAC;IAClG,KAAK,MAAM,OAAO,IAAI,CAAC,GAAG,UAAU,CAAC,gBAAgB,EAAE,GAAG,QAAQ,CAAC,gBAAgB,CAAC,EAAE,CAAC;QACrF,MAAM,GAAG,GAAG,GAAG,OAAO,CAAC,QAAQ,IAAI,OAAO,CAAC,OAAO,IAAI,EAAE,EAAE,CAAC;QAC3D,MAAM,QAAQ,GAAG,gBAAgB,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAC3C,gBAAgB,CAAC,GAAG,CAAC,GAAG,EAAE;YACxB,QAAQ,EAAE,OAAO,CAAC,QAAQ;YAC1B,OAAO,EAAE,OAAO,CAAC,OAAO;YACxB,KAAK,EAAE,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,KAAK,IAAI,CAAC,EAAE,OAAO,CAAC,KAAK,CAAC;SACrD,CAAC,CAAC;IACL,CAAC;IAED,OAAO;QACL,GAAG,UAAU;QACb,SAAS,EAAE,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,SAAS,EAAE,QAAQ,CAAC,SAAS,CAAC;QAC7D,iBAAiB,EAAE,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,iBAAiB,EAAE,QAAQ,CAAC,iBAAiB,CAAC;QACrF,gBAAgB,EAAE,CAAC,GAAG,gBAAgB,CAAC,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,IAAI,CAAC,CAAC;QACxF,gBAAgB,EAAE,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,gBAAgB,EAAE,QAAQ,CAAC,gBAAgB,CAAC;QAClF,eAAe,EACb,UAAU,CAAC,eAAe,IAAI,QAAQ,CAAC,eAAe;YACpD,CAAC,CAAC,UAAU,CAAC,eAAe,GAAG,QAAQ,CAAC,eAAe;gBACrD,CAAC,CAAC,UAAU,CAAC,eAAe;gBAC5B,CAAC,CAAC,QAAQ,CAAC,eAAe;YAC5B,CAAC,CAAC,UAAU,CAAC,eAAe,IAAI,QAAQ,CAAC,eAAe;KAC7D,CAAC;AACJ,CAAC"}
|
package/dist/hooks.d.ts
CHANGED
|
@@ -1,14 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
export
|
|
3
|
-
export declare function parseHookPayload(raw: string, fallbackEventName?: string): DerivedHookEvent | undefined;
|
|
4
|
-
export declare function mergeHookSummary(transcript: TranscriptSummary, hookData: {
|
|
5
|
-
failedToolResults: number;
|
|
6
|
-
toolCalls: number;
|
|
7
|
-
compactionEvents: number;
|
|
8
|
-
repeatedFailures: Array<{
|
|
9
|
-
toolName: string;
|
|
10
|
-
count: number;
|
|
11
|
-
purpose?: string;
|
|
12
|
-
}>;
|
|
13
|
-
latestTimestamp?: string;
|
|
14
|
-
}): TranscriptSummary;
|
|
1
|
+
export { SAFE_HOOK_EVENTS, parseHookPayload } from "./hook-payload.js";
|
|
2
|
+
export { mergeHookSummary } from "./hook-summary.js";
|
package/dist/hooks.js
CHANGED
|
@@ -1,127 +1,3 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
const TEST_COMMAND_RE = /\b(npm|pnpm|yarn|bun)\s+(run\s+)?(test|vitest|jest)|\b(vitest|jest|mocha|pytest|cargo\s+test|go\s+test|rspec|playwright\s+test)\b/i;
|
|
4
|
-
export const SAFE_HOOK_EVENTS = [
|
|
5
|
-
"PostToolUse",
|
|
6
|
-
"PostToolUseFailure",
|
|
7
|
-
"PostToolBatch",
|
|
8
|
-
"PreCompact",
|
|
9
|
-
"PostCompact",
|
|
10
|
-
"Stop",
|
|
11
|
-
"SessionEnd"
|
|
12
|
-
];
|
|
13
|
-
export function parseHookPayload(raw, fallbackEventName) {
|
|
14
|
-
let parsed;
|
|
15
|
-
try {
|
|
16
|
-
parsed = JSON.parse(raw.trim() || "{}");
|
|
17
|
-
}
|
|
18
|
-
catch {
|
|
19
|
-
return undefined;
|
|
20
|
-
}
|
|
21
|
-
const root = asRecord(parsed);
|
|
22
|
-
if (!root) {
|
|
23
|
-
return undefined;
|
|
24
|
-
}
|
|
25
|
-
const hookEventName = stringField(root.hook_event_name) || stringField(root.event) || fallbackEventName || "unknown";
|
|
26
|
-
const sessionId = stringField(root.session_id) || stringField(root.sessionId);
|
|
27
|
-
const base = {
|
|
28
|
-
timestamp: stringField(root.timestamp) || new Date().toISOString(),
|
|
29
|
-
hookEventName,
|
|
30
|
-
sessionKey: hashValue(sessionId)
|
|
31
|
-
};
|
|
32
|
-
if (hookEventName === "PostToolUseFailure") {
|
|
33
|
-
const toolName = safeToolName(stringField(root.tool_name) || stringField(root.toolName));
|
|
34
|
-
return {
|
|
35
|
-
...base,
|
|
36
|
-
kind: "tool_failure",
|
|
37
|
-
toolName,
|
|
38
|
-
purpose: classifyToolPurpose(toolName, root.tool_input ?? root.toolInput)
|
|
39
|
-
};
|
|
40
|
-
}
|
|
41
|
-
if (hookEventName === "PostToolUse") {
|
|
42
|
-
const toolName = safeToolName(stringField(root.tool_name) || stringField(root.toolName));
|
|
43
|
-
return {
|
|
44
|
-
...base,
|
|
45
|
-
kind: "tool_success",
|
|
46
|
-
toolName,
|
|
47
|
-
purpose: classifyToolPurpose(toolName, root.tool_input ?? root.toolInput)
|
|
48
|
-
};
|
|
49
|
-
}
|
|
50
|
-
if (hookEventName === "PostToolBatch") {
|
|
51
|
-
return {
|
|
52
|
-
...base,
|
|
53
|
-
kind: "tool_batch",
|
|
54
|
-
toolCount: countBatchTools(root)
|
|
55
|
-
};
|
|
56
|
-
}
|
|
57
|
-
if (hookEventName === "PreCompact" || hookEventName === "PostCompact") {
|
|
58
|
-
return {
|
|
59
|
-
...base,
|
|
60
|
-
kind: "compaction"
|
|
61
|
-
};
|
|
62
|
-
}
|
|
63
|
-
if (hookEventName === "Stop" || hookEventName === "StopFailure") {
|
|
64
|
-
return {
|
|
65
|
-
...base,
|
|
66
|
-
kind: "stop"
|
|
67
|
-
};
|
|
68
|
-
}
|
|
69
|
-
if (hookEventName === "SessionEnd") {
|
|
70
|
-
return {
|
|
71
|
-
...base,
|
|
72
|
-
kind: "session_end"
|
|
73
|
-
};
|
|
74
|
-
}
|
|
75
|
-
return undefined;
|
|
76
|
-
}
|
|
77
|
-
export function mergeHookSummary(transcript, hookData) {
|
|
78
|
-
const repeatedFailures = new Map();
|
|
79
|
-
for (const failure of [...transcript.repeatedFailures, ...hookData.repeatedFailures]) {
|
|
80
|
-
const key = `${failure.toolName}:${failure.purpose || ""}`;
|
|
81
|
-
const existing = repeatedFailures.get(key);
|
|
82
|
-
repeatedFailures.set(key, {
|
|
83
|
-
toolName: failure.toolName,
|
|
84
|
-
purpose: failure.purpose,
|
|
85
|
-
count: Math.max(existing?.count || 0, failure.count)
|
|
86
|
-
});
|
|
87
|
-
}
|
|
88
|
-
return {
|
|
89
|
-
...transcript,
|
|
90
|
-
toolCalls: Math.max(transcript.toolCalls, hookData.toolCalls),
|
|
91
|
-
failedToolResults: Math.max(transcript.failedToolResults, hookData.failedToolResults),
|
|
92
|
-
repeatedFailures: [...repeatedFailures.values()].filter((failure) => failure.count >= 2),
|
|
93
|
-
compactionEvents: Math.max(transcript.compactionEvents, hookData.compactionEvents),
|
|
94
|
-
latestTimestamp: transcript.latestTimestamp && hookData.latestTimestamp
|
|
95
|
-
? transcript.latestTimestamp > hookData.latestTimestamp
|
|
96
|
-
? transcript.latestTimestamp
|
|
97
|
-
: hookData.latestTimestamp
|
|
98
|
-
: transcript.latestTimestamp || hookData.latestTimestamp
|
|
99
|
-
};
|
|
100
|
-
}
|
|
101
|
-
function classifyToolPurpose(toolName, input) {
|
|
102
|
-
if (toolName !== "Bash") {
|
|
103
|
-
return undefined;
|
|
104
|
-
}
|
|
105
|
-
const command = stringField(asRecord(input)?.command);
|
|
106
|
-
return command && TEST_COMMAND_RE.test(command) ? "tests" : undefined;
|
|
107
|
-
}
|
|
108
|
-
function countBatchTools(root) {
|
|
109
|
-
const values = [root.tools, root.tool_uses, root.toolUses, root.results, root.tool_results, root.toolResults];
|
|
110
|
-
for (const value of values) {
|
|
111
|
-
if (Array.isArray(value)) {
|
|
112
|
-
return value.length;
|
|
113
|
-
}
|
|
114
|
-
const count = numberField(value);
|
|
115
|
-
if (count !== undefined) {
|
|
116
|
-
return Math.max(0, Math.floor(count));
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
return 0;
|
|
120
|
-
}
|
|
121
|
-
function safeToolName(toolName) {
|
|
122
|
-
if (!toolName) {
|
|
123
|
-
return "tool";
|
|
124
|
-
}
|
|
125
|
-
return /^[A-Za-z][A-Za-z0-9_-]{0,32}$/u.test(toolName) ? toolName : "tool";
|
|
126
|
-
}
|
|
1
|
+
export { SAFE_HOOK_EVENTS, parseHookPayload } from "./hook-payload.js";
|
|
2
|
+
export { mergeHookSummary } from "./hook-summary.js";
|
|
127
3
|
//# sourceMappingURL=hooks.js.map
|
package/dist/hooks.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hooks.js","sourceRoot":"","sources":["../src/hooks.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"hooks.js","sourceRoot":"","sources":["../src/hooks.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACvE,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC"}
|
package/dist/renderer.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
export declare function renderStatusLine(decision:
|
|
1
|
+
import type { DecisionPresentation } from "./decision-presentation.js";
|
|
2
|
+
export declare function renderStatusLine(decision: DecisionPresentation, width?: number): string;
|
package/dist/renderer.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"renderer.js","sourceRoot":"","sources":["../src/renderer.ts"],"names":[],"mappings":"AAEA,MAAM,aAAa,GAAG,GAAG,CAAC;AAC1B,MAAM,KAAK,GAAG,WAAW,CAAC;AAC1B,MAAM,MAAM,
|
|
1
|
+
{"version":3,"file":"renderer.js","sourceRoot":"","sources":["../src/renderer.ts"],"names":[],"mappings":"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"}
|