braintracker 1.2.0 → 1.4.0
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 +8 -13
- package/braintracker/hooks/post_turn.js +13 -14
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -31,23 +31,18 @@ Removes the hook files and cleans up `~/.claude/settings.json`.
|
|
|
31
31
|
|
|
32
32
|
## Verify
|
|
33
33
|
|
|
34
|
-
|
|
34
|
+
After a conversation, two files are written per session under `~/.claude/plugin/cache/braintracker/<project>/` (`<project>` is the working directory name):
|
|
35
|
+
|
|
36
|
+
**Full conversation transcript** — every message, all text and tool content:
|
|
35
37
|
|
|
36
38
|
```bash
|
|
37
|
-
cat ~/.claude/plugin/cache/braintracker/<project>/<session_id>.
|
|
39
|
+
cat ~/.claude/plugin/cache/braintracker/<project>/<session_id>.transcript.json
|
|
38
40
|
```
|
|
39
41
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
```
|
|
43
|
-
|
|
44
|
-
"type": "skill_invocation",
|
|
45
|
-
"session_id": "abc123",
|
|
46
|
-
"skill": "review",
|
|
47
|
-
"triggered_by": "review this PR",
|
|
48
|
-
"started_at": "2026-05-25T10:00:00Z",
|
|
49
|
-
"duration_seconds": 4.2
|
|
50
|
-
}
|
|
42
|
+
**Event log** — one JSON line per turn / skill invocation:
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
cat ~/.claude/plugin/cache/braintracker/<project>/<session_id>.jsonl
|
|
51
46
|
```
|
|
52
47
|
|
|
53
48
|
## How It Works
|
|
@@ -10,32 +10,31 @@ process.stdin.on('end', () => {
|
|
|
10
10
|
try { payload = JSON.parse(raw); } catch { process.exit(0); }
|
|
11
11
|
|
|
12
12
|
const sessionId = payload.session_id;
|
|
13
|
+
if (!sessionId) process.exit(0);
|
|
14
|
+
|
|
13
15
|
const prj = path.basename(process.cwd());
|
|
14
16
|
const cacheDir = path.join(os.homedir(), '.claude', 'plugin', 'cache', 'braintracker', prj);
|
|
15
|
-
|
|
17
|
+
fs.mkdirSync(cacheDir, { recursive: true });
|
|
18
|
+
|
|
19
|
+
let messages = [];
|
|
20
|
+
try {
|
|
21
|
+
if (payload.transcript_path) {
|
|
22
|
+
messages = fs.readFileSync(payload.transcript_path, 'utf8')
|
|
23
|
+
.trim().split('\n').map(l => JSON.parse(l));
|
|
24
|
+
}
|
|
25
|
+
} catch { /* transcript unavailable */ }
|
|
16
26
|
|
|
27
|
+
const preFile = path.join(cacheDir, `${sessionId}.turn.pre.json`);
|
|
17
28
|
let preData;
|
|
18
29
|
try { preData = JSON.parse(fs.readFileSync(preFile, 'utf8')); } catch { process.exit(0); }
|
|
19
30
|
|
|
20
|
-
const transcript = payload.transcript || [];
|
|
21
|
-
const lastAssistant = [...transcript].reverse().find(m => m.role === 'assistant');
|
|
22
|
-
let assistantResponse = '';
|
|
23
|
-
if (lastAssistant) {
|
|
24
|
-
const c = lastAssistant.content;
|
|
25
|
-
if (typeof c === 'string') {
|
|
26
|
-
assistantResponse = c;
|
|
27
|
-
} else if (Array.isArray(c)) {
|
|
28
|
-
assistantResponse = c.filter(b => b.type === 'text').map(b => b.text).join('');
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
|
|
32
31
|
const entry = {
|
|
33
32
|
type: 'conversation_turn',
|
|
34
33
|
session_id: sessionId,
|
|
35
34
|
user_prompt: preData.prompt,
|
|
36
|
-
assistant_response: assistantResponse,
|
|
37
35
|
started_at: new Date(preData.start_time).toISOString(),
|
|
38
36
|
duration_seconds: (Date.now() - preData.start_time) / 1000,
|
|
37
|
+
messages,
|
|
39
38
|
};
|
|
40
39
|
|
|
41
40
|
const logFile = path.join(cacheDir, `${sessionId}.jsonl`);
|