@arcreflex/agent-transcripts 0.1.9 → 0.1.11
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/CLAUDE.md +3 -1
- package/README.md +71 -52
- package/package.json +1 -1
- package/scripts/infer-cc-types.prose +87 -0
- package/src/adapters/claude-code.ts +291 -53
- package/src/adapters/index.ts +0 -6
- package/src/archive.ts +267 -0
- package/src/cli.ts +96 -63
- package/src/convert.ts +19 -86
- package/src/parse.ts +0 -3
- package/src/render-html.ts +38 -195
- package/src/render-index.ts +15 -178
- package/src/render.ts +25 -88
- package/src/serve.ts +124 -215
- package/src/title.ts +24 -102
- package/src/types.ts +5 -0
- package/src/utils/naming.ts +8 -13
- package/src/utils/summary.ts +1 -4
- package/src/utils/text.ts +5 -0
- package/src/utils/theme.ts +152 -0
- package/src/utils/tree.ts +85 -1
- package/src/watch.ts +178 -0
- package/test/archive.test.ts +264 -0
- package/test/fixtures/claude/branching.input.jsonl +6 -0
- package/test/fixtures/claude/branching.output.md +25 -0
- package/test/naming.test.ts +98 -0
- package/test/summary.test.ts +144 -0
- package/test/tree.test.ts +217 -0
- package/tsconfig.json +1 -1
- package/src/cache.ts +0 -129
- package/src/sync.ts +0 -294
- package/src/utils/provenance.ts +0 -212
package/CLAUDE.md
CHANGED
|
@@ -4,7 +4,9 @@
|
|
|
4
4
|
|
|
5
5
|
## Architectural Notes
|
|
6
6
|
|
|
7
|
-
- **Source paths are stable**: Session source paths (e.g., `~/.claude/projects/.../sessions/`) are standardized by the tools that create them.
|
|
7
|
+
- **Source paths are stable**: Session source paths (e.g., `~/.claude/projects/.../sessions/`) are standardized by the tools that create them. Archive entries store the absolute source path for traceability.
|
|
8
|
+
- **Archive is the central store**: All derived data (titles, etc.) lives on archive entries. Rendered HTML is in-memory only (LRU in serve). No persistent cache layer.
|
|
9
|
+
- **Serve is snapshot-based**: `serve` loads the archive once at startup. It does not live-reload when `watch` archives new sessions. This is a known simplification — revisit if live-updating becomes important.
|
|
8
10
|
|
|
9
11
|
## Verification
|
|
10
12
|
|
package/README.md
CHANGED
|
@@ -17,30 +17,35 @@ src/
|
|
|
17
17
|
render.ts # Intermediate format → markdown
|
|
18
18
|
render-html.ts # HTML transcript rendering
|
|
19
19
|
render-index.ts # Index page rendering
|
|
20
|
-
convert.ts #
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
title.ts # LLM title generation
|
|
20
|
+
convert.ts # Direct pipeline (parse → render to stdout or directory)
|
|
21
|
+
archive.ts # Persistent archive store (~/.local/share/agent-transcripts/archive/)
|
|
22
|
+
watch.ts # Continuous archive updates via fs.watch + polling
|
|
23
|
+
serve.ts # HTTP server serving from archive with in-memory LRU
|
|
24
|
+
title.ts # LLM title generation (writes to archive entries)
|
|
25
25
|
types.ts # Core types (Transcript, Message, Adapter)
|
|
26
26
|
adapters/ # Source format adapters (currently: claude-code)
|
|
27
27
|
utils/
|
|
28
28
|
naming.ts # Deterministic output file naming
|
|
29
|
-
provenance.ts # Source tracking via transcripts.json + YAML front matter
|
|
30
29
|
summary.ts # Tool call summary extraction
|
|
31
30
|
openrouter.ts # OpenRouter API client for title generation
|
|
32
31
|
html.ts # HTML escaping utility
|
|
33
|
-
tree.ts # Tree navigation
|
|
32
|
+
tree.ts # Tree navigation and walkTranscriptTree generator
|
|
33
|
+
text.ts # Shared text utilities (truncate)
|
|
34
|
+
theme.ts # Shared CSS theme constants
|
|
34
35
|
test/
|
|
35
36
|
fixtures/ # Snapshot test inputs/outputs
|
|
36
37
|
snapshots.test.ts
|
|
38
|
+
archive.test.ts
|
|
39
|
+
tree.test.ts
|
|
40
|
+
naming.test.ts
|
|
41
|
+
summary.test.ts
|
|
37
42
|
```
|
|
38
43
|
|
|
39
44
|
## Commands
|
|
40
45
|
|
|
41
46
|
```bash
|
|
42
47
|
bun run check # typecheck + prettier
|
|
43
|
-
bun run test # snapshot tests
|
|
48
|
+
bun run test # snapshot tests + archive tests
|
|
44
49
|
bun run format # auto-format
|
|
45
50
|
```
|
|
46
51
|
|
|
@@ -50,9 +55,23 @@ bun run format # auto-format
|
|
|
50
55
|
# Subcommands (convert is default if omitted)
|
|
51
56
|
agent-transcripts convert <file> # Parse and render to stdout
|
|
52
57
|
agent-transcripts convert <file> -o <dir> # Parse and render to directory
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
agent-transcripts
|
|
58
|
+
|
|
59
|
+
# Archive management
|
|
60
|
+
agent-transcripts archive <source> # Archive sessions from source dir
|
|
61
|
+
agent-transcripts archive <source> --archive-dir ~/my-archive
|
|
62
|
+
|
|
63
|
+
# Serving
|
|
64
|
+
agent-transcripts serve # Serve from default archive
|
|
65
|
+
agent-transcripts serve --archive-dir <dir> # Serve from custom archive
|
|
66
|
+
agent-transcripts serve -p 8080 # Custom port
|
|
67
|
+
|
|
68
|
+
# Watching
|
|
69
|
+
agent-transcripts watch <source> # Keep archive updated continuously
|
|
70
|
+
agent-transcripts watch <source> --poll-interval 60000
|
|
71
|
+
|
|
72
|
+
# Title generation
|
|
73
|
+
agent-transcripts title # Generate titles for archive entries
|
|
74
|
+
agent-transcripts title -f # Force regenerate all titles
|
|
56
75
|
|
|
57
76
|
# Use "-" for stdin
|
|
58
77
|
cat session.jsonl | agent-transcripts -
|
|
@@ -60,67 +79,61 @@ cat session.jsonl | agent-transcripts -
|
|
|
60
79
|
|
|
61
80
|
## Architecture
|
|
62
81
|
|
|
63
|
-
|
|
82
|
+
```
|
|
83
|
+
Source (Claude Code sessions)
|
|
84
|
+
↓ [archive / watch]
|
|
85
|
+
Archive (~/.local/share/agent-transcripts/archive/{sessionId}.json)
|
|
86
|
+
↓ [serve]
|
|
87
|
+
HTML (rendered on demand, in-memory LRU)
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
`convert` is a standalone direct pipeline (no archive dependency).
|
|
91
|
+
|
|
92
|
+
`serve` loads the archive once at startup — it won't pick up new sessions archived by a concurrent `watch` without a restart. Live-reloading could be added later (periodic re-listing or file-watch trigger) if needed.
|
|
64
93
|
|
|
65
94
|
- Adapters handle source formats (see `src/adapters/index.ts` for registry)
|
|
66
95
|
- Auto-detection: paths containing `.claude/` → claude-code adapter
|
|
67
96
|
- Branching conversations preserved via `parentMessageRef` on messages
|
|
68
|
-
- Provenance tracking via `transcripts.json` index + YAML front matter
|
|
69
97
|
- Deterministic naming: `{datetime}-{sessionId}.md`
|
|
70
|
-
- Sync uses sessions-index.json for discovery (claude-code), skipping subagent files
|
|
71
|
-
- Sync uses content hash to skip unchanged sources (see Cache section)
|
|
72
98
|
|
|
73
|
-
###
|
|
99
|
+
### Archive
|
|
74
100
|
|
|
75
|
-
|
|
101
|
+
The archive is the central data store at `~/.local/share/agent-transcripts/archive/`:
|
|
76
102
|
|
|
77
103
|
```
|
|
78
|
-
~/.
|
|
79
|
-
{
|
|
104
|
+
~/.local/share/agent-transcripts/archive/
|
|
105
|
+
{sessionId}.json → ArchiveEntry
|
|
80
106
|
```
|
|
81
107
|
|
|
82
108
|
```typescript
|
|
83
|
-
interface
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
109
|
+
interface ArchiveEntry {
|
|
110
|
+
sessionId: string;
|
|
111
|
+
sourcePath: string; // absolute source path
|
|
112
|
+
sourceHash: string; // content hash (invalidation key)
|
|
113
|
+
adapterName: string;
|
|
114
|
+
adapterVersion: string; // e.g. "claude-code:1"
|
|
115
|
+
schemaVersion: number;
|
|
116
|
+
archivedAt: string; // ISO timestamp
|
|
117
|
+
title?: string; // harness-provided or LLM-generated
|
|
118
|
+
transcripts: Transcript[];
|
|
90
119
|
}
|
|
91
120
|
```
|
|
92
121
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
### transcripts.json
|
|
96
|
-
|
|
97
|
-
The index file is a table of contents for the output directory:
|
|
98
|
-
|
|
99
|
-
```typescript
|
|
100
|
-
interface TranscriptsIndex {
|
|
101
|
-
version: 1;
|
|
102
|
-
entries: {
|
|
103
|
-
[outputFilename: string]: {
|
|
104
|
-
source: string; // absolute path to source
|
|
105
|
-
sessionId: string; // full session ID from filename
|
|
106
|
-
segmentIndex?: number; // for multi-transcript sources (1-indexed)
|
|
107
|
-
syncedAt: string; // ISO timestamp
|
|
108
|
-
firstUserMessage: string; // first user message content
|
|
109
|
-
title?: string; // copied from cache for convenience
|
|
110
|
-
messageCount: number;
|
|
111
|
-
startTime: string; // ISO timestamp
|
|
112
|
-
endTime: string; // ISO timestamp
|
|
113
|
-
cwd?: string; // working directory
|
|
114
|
-
};
|
|
115
|
-
};
|
|
116
|
-
}
|
|
117
|
-
```
|
|
122
|
+
Freshness is determined by `sourceHash + adapterVersion + schemaVersion`. When any changes, the entry is re-archived.
|
|
118
123
|
|
|
119
124
|
## Key Types
|
|
120
125
|
|
|
121
126
|
- `Transcript`: source info, warnings, messages array
|
|
122
127
|
- `Message`: union of UserMessage | AssistantMessage | SystemMessage | ToolCallGroup | ErrorMessage
|
|
123
|
-
- `Adapter`: name, discover function, parse function
|
|
128
|
+
- `Adapter`: name, version, discover function, parse function
|
|
129
|
+
|
|
130
|
+
### Titles
|
|
131
|
+
|
|
132
|
+
Transcripts get titles from (in priority order):
|
|
133
|
+
|
|
134
|
+
1. Harness-provided summary (e.g., Claude Code's sessions-index.json `summary` field)
|
|
135
|
+
2. Existing title from previous archive entry
|
|
136
|
+
3. LLM-generated title via OpenRouter (requires `OPENROUTER_API_KEY`)
|
|
124
137
|
|
|
125
138
|
## Adding an Adapter
|
|
126
139
|
|
|
@@ -128,8 +141,14 @@ interface TranscriptsIndex {
|
|
|
128
141
|
2. Register in `src/adapters/index.ts` (adapters map + detection rules)
|
|
129
142
|
3. Add test fixtures in `test/fixtures/<name>/`
|
|
130
143
|
|
|
144
|
+
## Development Scripts
|
|
145
|
+
|
|
146
|
+
- `scripts/infer-cc-types.prose`: open-prose program to infer types from real CC session data
|
|
147
|
+
|
|
131
148
|
## Tests
|
|
132
149
|
|
|
133
150
|
Snapshot-based: `*.input.jsonl` → parse → render → compare against `*.output.md`
|
|
134
151
|
|
|
152
|
+
Archive tests: real fixture files + temp dirs to verify archiving, freshness, listing.
|
|
153
|
+
|
|
135
154
|
To update snapshots: manually edit the expected `.output.md` files.
|
package/package.json
CHANGED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
# Infer TypeScript types from Claude Code session data
|
|
2
|
+
#
|
|
3
|
+
# Usage: prose run scripts/infer-cc-types.prose
|
|
4
|
+
#
|
|
5
|
+
# Examines real CC session directories and updates the type definitions
|
|
6
|
+
# in src/adapters/claude-code.ts to match the current data format.
|
|
7
|
+
|
|
8
|
+
# Agent that synthesizes TypeScript types from JSON examples
|
|
9
|
+
agent type-inferrer:
|
|
10
|
+
model: sonnet
|
|
11
|
+
prompt: """
|
|
12
|
+
You analyze JSON data samples and synthesize TypeScript type definitions.
|
|
13
|
+
|
|
14
|
+
Your output should be:
|
|
15
|
+
- Clean, minimal TypeScript interfaces
|
|
16
|
+
- JSDoc comments explaining non-obvious fields
|
|
17
|
+
- Optional fields marked with ?
|
|
18
|
+
- Union types where the data shows multiple shapes
|
|
19
|
+
- `unknown` (never `any`) for truly dynamic data
|
|
20
|
+
|
|
21
|
+
When you see multiple examples, infer which fields are always present
|
|
22
|
+
(required) vs sometimes present (optional).
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
# Discover CC session data locations (once)
|
|
26
|
+
let discovery = session "Find CC session data"
|
|
27
|
+
model: sonnet
|
|
28
|
+
prompt: """
|
|
29
|
+
Find Claude Code session data on this system.
|
|
30
|
+
|
|
31
|
+
1. Search for sessions-index.json files under ~/.claude
|
|
32
|
+
2. For each, note the directory path and count of .jsonl files
|
|
33
|
+
|
|
34
|
+
Return a structured list of what you found.
|
|
35
|
+
If nothing found, say so clearly.
|
|
36
|
+
"""
|
|
37
|
+
|
|
38
|
+
# Iterate: infer types → implement → check → repeat if needed
|
|
39
|
+
let feedback = "(no feedback)"
|
|
40
|
+
|
|
41
|
+
loop until **feedback indicates success** (max: 5):
|
|
42
|
+
# Parallel type inference
|
|
43
|
+
parallel:
|
|
44
|
+
index_types = session: type-inferrer
|
|
45
|
+
prompt: """
|
|
46
|
+
Analyze the sessions-index.json files from the discovered locations.
|
|
47
|
+
|
|
48
|
+
Generate TypeScript interfaces for:
|
|
49
|
+
- SessionsIndex (the root object)
|
|
50
|
+
- SessionIndexEntry (each entry in the entries array)
|
|
51
|
+
"""
|
|
52
|
+
context: { discovery, feedback }
|
|
53
|
+
|
|
54
|
+
record_types = session: type-inferrer
|
|
55
|
+
prompt: """
|
|
56
|
+
Analyze Claude Code session .jsonl files (sample 20-30 lines from a few files).
|
|
57
|
+
|
|
58
|
+
Generate TypeScript types describing JSONL records.
|
|
59
|
+
- ClaudeRecord (the JSONL line structure)
|
|
60
|
+
- ContentBlock (the message.content array elements)
|
|
61
|
+
"""
|
|
62
|
+
context: { discovery, feedback }
|
|
63
|
+
|
|
64
|
+
# Implement and verify
|
|
65
|
+
feedback = session "Update adapter types"
|
|
66
|
+
model: opus
|
|
67
|
+
prompt: """
|
|
68
|
+
Update the type definitions in src/adapters/claude-code.ts to match these inferred types.
|
|
69
|
+
|
|
70
|
+
## Inferred from sessions-index.json
|
|
71
|
+
{index_types}
|
|
72
|
+
|
|
73
|
+
## Inferred from JSONL records
|
|
74
|
+
{record_types}
|
|
75
|
+
|
|
76
|
+
## Task
|
|
77
|
+
|
|
78
|
+
1. Read the current types in src/adapters/claude-code.ts
|
|
79
|
+
2. Edit to match the inferred types (add new fields, fix types, etc.)
|
|
80
|
+
3. Run: bun run typecheck
|
|
81
|
+
|
|
82
|
+
If typecheck succeeds and you're happy with the types, output a message indicating success.
|
|
83
|
+
If typecheck fails, assess whether the failures reflect a real need to change the code or a flaw in the type design.
|
|
84
|
+
If yes, and you're happy with the types, make the changes and output a message indicating success.
|
|
85
|
+
Otherwise: output feedback requesting revisions to the type design.
|
|
86
|
+
"""
|
|
87
|
+
context: { index_types, record_types }
|