@arcreflex/agent-transcripts 0.1.8 → 0.1.10
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 +4 -0
- package/README.md +52 -3
- package/bun.lock +89 -0
- package/package.json +3 -2
- package/scripts/infer-cc-types.prose +87 -0
- package/src/adapters/claude-code.ts +476 -68
- package/src/cache.ts +129 -0
- package/src/cli.ts +86 -5
- package/src/convert.ts +6 -14
- package/src/render-html.ts +1096 -0
- package/src/render-index.ts +611 -0
- package/src/render.ts +6 -110
- package/src/serve.ts +308 -0
- package/src/sync.ts +132 -18
- package/src/title.ts +172 -0
- package/src/types.ts +9 -0
- package/src/utils/html.ts +12 -0
- package/src/utils/openrouter.ts +116 -0
- package/src/utils/provenance.ts +25 -41
- package/src/utils/tree.ts +116 -0
- package/test/fixtures/claude/non-message-parents.input.jsonl +9 -0
- package/test/fixtures/claude/non-message-parents.output.md +30 -0
package/CLAUDE.md
CHANGED
|
@@ -2,6 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
@README.md
|
|
4
4
|
|
|
5
|
+
## Architectural Notes
|
|
6
|
+
|
|
7
|
+
- **Source paths are stable**: Session source paths (e.g., `~/.claude/projects/.../sessions/`) are standardized by the tools that create them. Don't over-engineer for path changes—use source paths as cache keys directly.
|
|
8
|
+
|
|
5
9
|
## Verification
|
|
6
10
|
|
|
7
11
|
Before committing:
|
package/README.md
CHANGED
|
@@ -15,14 +15,22 @@ src/
|
|
|
15
15
|
cli.ts # CLI entry point, subcommand routing
|
|
16
16
|
parse.ts # Source → intermediate format
|
|
17
17
|
render.ts # Intermediate format → markdown
|
|
18
|
+
render-html.ts # HTML transcript rendering
|
|
19
|
+
render-index.ts # Index page rendering
|
|
18
20
|
convert.ts # Full pipeline with provenance tracking
|
|
19
21
|
sync.ts # Batch sync sessions → markdown
|
|
22
|
+
serve.ts # HTTP server for dynamic transcript serving
|
|
23
|
+
cache.ts # Content-hash-based caching (~/.cache/agent-transcripts/)
|
|
24
|
+
title.ts # LLM title generation
|
|
20
25
|
types.ts # Core types (Transcript, Message, Adapter)
|
|
21
26
|
adapters/ # Source format adapters (currently: claude-code)
|
|
22
27
|
utils/
|
|
23
28
|
naming.ts # Deterministic output file naming
|
|
24
29
|
provenance.ts # Source tracking via transcripts.json + YAML front matter
|
|
25
30
|
summary.ts # Tool call summary extraction
|
|
31
|
+
openrouter.ts # OpenRouter API client for title generation
|
|
32
|
+
html.ts # HTML escaping utility
|
|
33
|
+
tree.ts # Tree navigation utilities
|
|
26
34
|
test/
|
|
27
35
|
fixtures/ # Snapshot test inputs/outputs
|
|
28
36
|
snapshots.test.ts
|
|
@@ -43,6 +51,8 @@ bun run format # auto-format
|
|
|
43
51
|
agent-transcripts convert <file> # Parse and render to stdout
|
|
44
52
|
agent-transcripts convert <file> -o <dir> # Parse and render to directory
|
|
45
53
|
agent-transcripts sync <dir> -o <out> # Batch sync sessions
|
|
54
|
+
agent-transcripts serve <dir> # Serve transcripts via HTTP
|
|
55
|
+
agent-transcripts serve <dir> -p 8080 # Serve on custom port
|
|
46
56
|
|
|
47
57
|
# Use "-" for stdin
|
|
48
58
|
cat session.jsonl | agent-transcripts -
|
|
@@ -58,11 +68,33 @@ Two-stage pipeline: Parse (source → intermediate) → Render (intermediate →
|
|
|
58
68
|
- Provenance tracking via `transcripts.json` index + YAML front matter
|
|
59
69
|
- Deterministic naming: `{datetime}-{sessionId}.md`
|
|
60
70
|
- Sync uses sessions-index.json for discovery (claude-code), skipping subagent files
|
|
61
|
-
- Sync uses
|
|
71
|
+
- Sync uses content hash to skip unchanged sources (see Cache section)
|
|
72
|
+
|
|
73
|
+
### Cache
|
|
74
|
+
|
|
75
|
+
Derived content (rendered outputs, LLM-generated titles) is cached at `~/.cache/agent-transcripts/`:
|
|
76
|
+
|
|
77
|
+
```
|
|
78
|
+
~/.cache/agent-transcripts/
|
|
79
|
+
{source-path-hash}.json → CacheEntry
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
```typescript
|
|
83
|
+
interface CacheEntry {
|
|
84
|
+
contentHash: string; // hash of source content (invalidation key)
|
|
85
|
+
segments: Array<{
|
|
86
|
+
title?: string; // LLM-generated title
|
|
87
|
+
html?: string; // rendered HTML
|
|
88
|
+
md?: string; // rendered markdown
|
|
89
|
+
}>;
|
|
90
|
+
}
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
Cache is keyed by source path (hashed), invalidated by content hash. When source content changes, all cached data is invalidated and regenerated.
|
|
62
94
|
|
|
63
95
|
### transcripts.json
|
|
64
96
|
|
|
65
|
-
The index file
|
|
97
|
+
The index file is a table of contents for the output directory:
|
|
66
98
|
|
|
67
99
|
```typescript
|
|
68
100
|
interface TranscriptsIndex {
|
|
@@ -70,10 +102,15 @@ interface TranscriptsIndex {
|
|
|
70
102
|
entries: {
|
|
71
103
|
[outputFilename: string]: {
|
|
72
104
|
source: string; // absolute path to source
|
|
73
|
-
sourceMtime: number; // ms since epoch
|
|
74
105
|
sessionId: string; // full session ID from filename
|
|
75
106
|
segmentIndex?: number; // for multi-transcript sources (1-indexed)
|
|
76
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
|
|
77
114
|
};
|
|
78
115
|
};
|
|
79
116
|
}
|
|
@@ -85,12 +122,24 @@ interface TranscriptsIndex {
|
|
|
85
122
|
- `Message`: union of UserMessage | AssistantMessage | SystemMessage | ToolCallGroup | ErrorMessage
|
|
86
123
|
- `Adapter`: name, discover function, parse function
|
|
87
124
|
|
|
125
|
+
### Titles
|
|
126
|
+
|
|
127
|
+
Transcripts get titles from (in priority order):
|
|
128
|
+
|
|
129
|
+
1. Harness-provided summary (e.g., Claude Code's sessions-index.json `summary` field)
|
|
130
|
+
2. Cached title from previous sync
|
|
131
|
+
3. LLM-generated title via OpenRouter (requires `OPENROUTER_API_KEY`)
|
|
132
|
+
|
|
88
133
|
## Adding an Adapter
|
|
89
134
|
|
|
90
135
|
1. Create `src/adapters/<name>.ts` implementing `Adapter`
|
|
91
136
|
2. Register in `src/adapters/index.ts` (adapters map + detection rules)
|
|
92
137
|
3. Add test fixtures in `test/fixtures/<name>/`
|
|
93
138
|
|
|
139
|
+
## Development Scripts
|
|
140
|
+
|
|
141
|
+
- `scripts/infer-cc-types.prose`: open-prose program to infer types from real CC session data
|
|
142
|
+
|
|
94
143
|
## Tests
|
|
95
144
|
|
|
96
145
|
Snapshot-based: `*.input.jsonl` → parse → render → compare against `*.output.md`
|
package/bun.lock
CHANGED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
"name": "agent-transcripts",
|
|
7
7
|
"dependencies": {
|
|
8
8
|
"cmd-ts": "^0.13.0",
|
|
9
|
+
"shiki": "^3.21.0",
|
|
9
10
|
},
|
|
10
11
|
"devDependencies": {
|
|
11
12
|
"@types/bun": "^1.1.14",
|
|
@@ -15,40 +16,128 @@
|
|
|
15
16
|
},
|
|
16
17
|
},
|
|
17
18
|
"packages": {
|
|
19
|
+
"@shikijs/core": ["@shikijs/core@3.21.0", "", { "dependencies": { "@shikijs/types": "3.21.0", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4", "hast-util-to-html": "^9.0.5" } }, "sha512-AXSQu/2n1UIQekY8euBJlvFYZIw0PHY63jUzGbrOma4wPxzznJXTXkri+QcHeBNaFxiiOljKxxJkVSoB3PjbyA=="],
|
|
20
|
+
|
|
21
|
+
"@shikijs/engine-javascript": ["@shikijs/engine-javascript@3.21.0", "", { "dependencies": { "@shikijs/types": "3.21.0", "@shikijs/vscode-textmate": "^10.0.2", "oniguruma-to-es": "^4.3.4" } }, "sha512-ATwv86xlbmfD9n9gKRiwuPpWgPENAWCLwYCGz9ugTJlsO2kOzhOkvoyV/UD+tJ0uT7YRyD530x6ugNSffmvIiQ=="],
|
|
22
|
+
|
|
23
|
+
"@shikijs/engine-oniguruma": ["@shikijs/engine-oniguruma@3.21.0", "", { "dependencies": { "@shikijs/types": "3.21.0", "@shikijs/vscode-textmate": "^10.0.2" } }, "sha512-OYknTCct6qiwpQDqDdf3iedRdzj6hFlOPv5hMvI+hkWfCKs5mlJ4TXziBG9nyabLwGulrUjHiCq3xCspSzErYQ=="],
|
|
24
|
+
|
|
25
|
+
"@shikijs/langs": ["@shikijs/langs@3.21.0", "", { "dependencies": { "@shikijs/types": "3.21.0" } }, "sha512-g6mn5m+Y6GBJ4wxmBYqalK9Sp0CFkUqfNzUy2pJglUginz6ZpWbaWjDB4fbQ/8SHzFjYbtU6Ddlp1pc+PPNDVA=="],
|
|
26
|
+
|
|
27
|
+
"@shikijs/themes": ["@shikijs/themes@3.21.0", "", { "dependencies": { "@shikijs/types": "3.21.0" } }, "sha512-BAE4cr9EDiZyYzwIHEk7JTBJ9CzlPuM4PchfcA5ao1dWXb25nv6hYsoDiBq2aZK9E3dlt3WB78uI96UESD+8Mw=="],
|
|
28
|
+
|
|
29
|
+
"@shikijs/types": ["@shikijs/types@3.21.0", "", { "dependencies": { "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-zGrWOxZ0/+0ovPY7PvBU2gIS9tmhSUUt30jAcNV0Bq0gb2S98gwfjIs1vxlmH5zM7/4YxLamT6ChlqqAJmPPjA=="],
|
|
30
|
+
|
|
31
|
+
"@shikijs/vscode-textmate": ["@shikijs/vscode-textmate@10.0.2", "", {}, "sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg=="],
|
|
32
|
+
|
|
18
33
|
"@types/bun": ["@types/bun@1.3.6", "", { "dependencies": { "bun-types": "1.3.6" } }, "sha512-uWCv6FO/8LcpREhenN1d1b6fcspAB+cefwD7uti8C8VffIv0Um08TKMn98FynpTiU38+y2dUO55T11NgDt8VAA=="],
|
|
19
34
|
|
|
35
|
+
"@types/hast": ["@types/hast@3.0.4", "", { "dependencies": { "@types/unist": "*" } }, "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ=="],
|
|
36
|
+
|
|
37
|
+
"@types/mdast": ["@types/mdast@4.0.4", "", { "dependencies": { "@types/unist": "*" } }, "sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA=="],
|
|
38
|
+
|
|
20
39
|
"@types/node": ["@types/node@25.0.9", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-/rpCXHlCWeqClNBwUhDcusJxXYDjZTyE8v5oTO7WbL8eij2nKhUeU89/6xgjU7N4/Vh3He0BtyhJdQbDyhiXAw=="],
|
|
21
40
|
|
|
41
|
+
"@types/unist": ["@types/unist@3.0.3", "", {}, "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q=="],
|
|
42
|
+
|
|
43
|
+
"@ungap/structured-clone": ["@ungap/structured-clone@1.3.0", "", {}, "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g=="],
|
|
44
|
+
|
|
22
45
|
"ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="],
|
|
23
46
|
|
|
24
47
|
"ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="],
|
|
25
48
|
|
|
26
49
|
"bun-types": ["bun-types@1.3.6", "", { "dependencies": { "@types/node": "*" } }, "sha512-OlFwHcnNV99r//9v5IIOgQ9Uk37gZqrNMCcqEaExdkVq3Avwqok1bJFmvGMCkCE0FqzdY8VMOZpfpR3lwI+CsQ=="],
|
|
27
50
|
|
|
51
|
+
"ccount": ["ccount@2.0.1", "", {}, "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg=="],
|
|
52
|
+
|
|
28
53
|
"chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="],
|
|
29
54
|
|
|
55
|
+
"character-entities-html4": ["character-entities-html4@2.1.0", "", {}, "sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA=="],
|
|
56
|
+
|
|
57
|
+
"character-entities-legacy": ["character-entities-legacy@3.0.0", "", {}, "sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ=="],
|
|
58
|
+
|
|
30
59
|
"cmd-ts": ["cmd-ts@0.13.0", "", { "dependencies": { "chalk": "^4.0.0", "debug": "^4.3.4", "didyoumean": "^1.2.2", "strip-ansi": "^6.0.0" } }, "sha512-nsnxf6wNIM/JAS7T/x/1JmbEsjH0a8tezXqqpaL0O6+eV0/aDEnRxwjxpu0VzDdRcaC1ixGSbRlUuf/IU59I4g=="],
|
|
31
60
|
|
|
32
61
|
"color-convert": ["color-convert@2.0.1", "", { "dependencies": { "color-name": "~1.1.4" } }, "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ=="],
|
|
33
62
|
|
|
34
63
|
"color-name": ["color-name@1.1.4", "", {}, "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="],
|
|
35
64
|
|
|
65
|
+
"comma-separated-tokens": ["comma-separated-tokens@2.0.3", "", {}, "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg=="],
|
|
66
|
+
|
|
36
67
|
"debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="],
|
|
37
68
|
|
|
69
|
+
"dequal": ["dequal@2.0.3", "", {}, "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA=="],
|
|
70
|
+
|
|
71
|
+
"devlop": ["devlop@1.1.0", "", { "dependencies": { "dequal": "^2.0.0" } }, "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA=="],
|
|
72
|
+
|
|
38
73
|
"didyoumean": ["didyoumean@1.2.2", "", {}, "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw=="],
|
|
39
74
|
|
|
40
75
|
"has-flag": ["has-flag@4.0.0", "", {}, "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="],
|
|
41
76
|
|
|
77
|
+
"hast-util-to-html": ["hast-util-to-html@9.0.5", "", { "dependencies": { "@types/hast": "^3.0.0", "@types/unist": "^3.0.0", "ccount": "^2.0.0", "comma-separated-tokens": "^2.0.0", "hast-util-whitespace": "^3.0.0", "html-void-elements": "^3.0.0", "mdast-util-to-hast": "^13.0.0", "property-information": "^7.0.0", "space-separated-tokens": "^2.0.0", "stringify-entities": "^4.0.0", "zwitch": "^2.0.4" } }, "sha512-OguPdidb+fbHQSU4Q4ZiLKnzWo8Wwsf5bZfbvu7//a9oTYoqD/fWpe96NuHkoS9h0ccGOTe0C4NGXdtS0iObOw=="],
|
|
78
|
+
|
|
79
|
+
"hast-util-whitespace": ["hast-util-whitespace@3.0.0", "", { "dependencies": { "@types/hast": "^3.0.0" } }, "sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw=="],
|
|
80
|
+
|
|
81
|
+
"html-void-elements": ["html-void-elements@3.0.0", "", {}, "sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg=="],
|
|
82
|
+
|
|
83
|
+
"mdast-util-to-hast": ["mdast-util-to-hast@13.2.1", "", { "dependencies": { "@types/hast": "^3.0.0", "@types/mdast": "^4.0.0", "@ungap/structured-clone": "^1.0.0", "devlop": "^1.0.0", "micromark-util-sanitize-uri": "^2.0.0", "trim-lines": "^3.0.0", "unist-util-position": "^5.0.0", "unist-util-visit": "^5.0.0", "vfile": "^6.0.0" } }, "sha512-cctsq2wp5vTsLIcaymblUriiTcZd0CwWtCbLvrOzYCDZoWyMNV8sZ7krj09FSnsiJi3WVsHLM4k6Dq/yaPyCXA=="],
|
|
84
|
+
|
|
85
|
+
"micromark-util-character": ["micromark-util-character@2.1.1", "", { "dependencies": { "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q=="],
|
|
86
|
+
|
|
87
|
+
"micromark-util-encode": ["micromark-util-encode@2.0.1", "", {}, "sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw=="],
|
|
88
|
+
|
|
89
|
+
"micromark-util-sanitize-uri": ["micromark-util-sanitize-uri@2.0.1", "", { "dependencies": { "micromark-util-character": "^2.0.0", "micromark-util-encode": "^2.0.0", "micromark-util-symbol": "^2.0.0" } }, "sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ=="],
|
|
90
|
+
|
|
91
|
+
"micromark-util-symbol": ["micromark-util-symbol@2.0.1", "", {}, "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q=="],
|
|
92
|
+
|
|
93
|
+
"micromark-util-types": ["micromark-util-types@2.0.2", "", {}, "sha512-Yw0ECSpJoViF1qTU4DC6NwtC4aWGt1EkzaQB8KPPyCRR8z9TWeV0HbEFGTO+ZY1wB22zmxnJqhPyTpOVCpeHTA=="],
|
|
94
|
+
|
|
42
95
|
"ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="],
|
|
43
96
|
|
|
97
|
+
"oniguruma-parser": ["oniguruma-parser@0.12.1", "", {}, "sha512-8Unqkvk1RYc6yq2WBYRj4hdnsAxVze8i7iPfQr8e4uSP3tRv0rpZcbGUDvxfQQcdwHt/e9PrMvGCsa8OqG9X3w=="],
|
|
98
|
+
|
|
99
|
+
"oniguruma-to-es": ["oniguruma-to-es@4.3.4", "", { "dependencies": { "oniguruma-parser": "^0.12.1", "regex": "^6.0.1", "regex-recursion": "^6.0.2" } }, "sha512-3VhUGN3w2eYxnTzHn+ikMI+fp/96KoRSVK9/kMTcFqj1NRDh2IhQCKvYxDnWePKRXY/AqH+Fuiyb7VHSzBjHfA=="],
|
|
100
|
+
|
|
44
101
|
"prettier": ["prettier@3.8.0", "", { "bin": { "prettier": "bin/prettier.cjs" } }, "sha512-yEPsovQfpxYfgWNhCfECjG5AQaO+K3dp6XERmOepyPDVqcJm+bjyCVO3pmU+nAPe0N5dDvekfGezt/EIiRe1TA=="],
|
|
45
102
|
|
|
103
|
+
"property-information": ["property-information@7.1.0", "", {}, "sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ=="],
|
|
104
|
+
|
|
105
|
+
"regex": ["regex@6.1.0", "", { "dependencies": { "regex-utilities": "^2.3.0" } }, "sha512-6VwtthbV4o/7+OaAF9I5L5V3llLEsoPyq9P1JVXkedTP33c7MfCG0/5NOPcSJn0TzXcG9YUrR0gQSWioew3LDg=="],
|
|
106
|
+
|
|
107
|
+
"regex-recursion": ["regex-recursion@6.0.2", "", { "dependencies": { "regex-utilities": "^2.3.0" } }, "sha512-0YCaSCq2VRIebiaUviZNs0cBz1kg5kVS2UKUfNIx8YVs1cN3AV7NTctO5FOKBA+UT2BPJIWZauYHPqJODG50cg=="],
|
|
108
|
+
|
|
109
|
+
"regex-utilities": ["regex-utilities@2.3.0", "", {}, "sha512-8VhliFJAWRaUiVvREIiW2NXXTmHs4vMNnSzuJVhscgmGav3g9VDxLrQndI3dZZVVdp0ZO/5v0xmX516/7M9cng=="],
|
|
110
|
+
|
|
111
|
+
"shiki": ["shiki@3.21.0", "", { "dependencies": { "@shikijs/core": "3.21.0", "@shikijs/engine-javascript": "3.21.0", "@shikijs/engine-oniguruma": "3.21.0", "@shikijs/langs": "3.21.0", "@shikijs/themes": "3.21.0", "@shikijs/types": "3.21.0", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-N65B/3bqL/TI2crrXr+4UivctrAGEjmsib5rPMMPpFp1xAx/w03v8WZ9RDDFYteXoEgY7qZ4HGgl5KBIu1153w=="],
|
|
112
|
+
|
|
113
|
+
"space-separated-tokens": ["space-separated-tokens@2.0.2", "", {}, "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q=="],
|
|
114
|
+
|
|
115
|
+
"stringify-entities": ["stringify-entities@4.0.4", "", { "dependencies": { "character-entities-html4": "^2.0.0", "character-entities-legacy": "^3.0.0" } }, "sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg=="],
|
|
116
|
+
|
|
46
117
|
"strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="],
|
|
47
118
|
|
|
48
119
|
"supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="],
|
|
49
120
|
|
|
121
|
+
"trim-lines": ["trim-lines@3.0.1", "", {}, "sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg=="],
|
|
122
|
+
|
|
50
123
|
"typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="],
|
|
51
124
|
|
|
52
125
|
"undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="],
|
|
126
|
+
|
|
127
|
+
"unist-util-is": ["unist-util-is@6.0.1", "", { "dependencies": { "@types/unist": "^3.0.0" } }, "sha512-LsiILbtBETkDz8I9p1dQ0uyRUWuaQzd/cuEeS1hoRSyW5E5XGmTzlwY1OrNzzakGowI9Dr/I8HVaw4hTtnxy8g=="],
|
|
128
|
+
|
|
129
|
+
"unist-util-position": ["unist-util-position@5.0.0", "", { "dependencies": { "@types/unist": "^3.0.0" } }, "sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA=="],
|
|
130
|
+
|
|
131
|
+
"unist-util-stringify-position": ["unist-util-stringify-position@4.0.0", "", { "dependencies": { "@types/unist": "^3.0.0" } }, "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ=="],
|
|
132
|
+
|
|
133
|
+
"unist-util-visit": ["unist-util-visit@5.1.0", "", { "dependencies": { "@types/unist": "^3.0.0", "unist-util-is": "^6.0.0", "unist-util-visit-parents": "^6.0.0" } }, "sha512-m+vIdyeCOpdr/QeQCu2EzxX/ohgS8KbnPDgFni4dQsfSCtpz8UqDyY5GjRru8PDKuYn7Fq19j1CQ+nJSsGKOzg=="],
|
|
134
|
+
|
|
135
|
+
"unist-util-visit-parents": ["unist-util-visit-parents@6.0.2", "", { "dependencies": { "@types/unist": "^3.0.0", "unist-util-is": "^6.0.0" } }, "sha512-goh1s1TBrqSqukSc8wrjwWhL0hiJxgA8m4kFxGlQ+8FYQ3C/m11FcTs4YYem7V664AhHVvgoQLk890Ssdsr2IQ=="],
|
|
136
|
+
|
|
137
|
+
"vfile": ["vfile@6.0.3", "", { "dependencies": { "@types/unist": "^3.0.0", "vfile-message": "^4.0.0" } }, "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q=="],
|
|
138
|
+
|
|
139
|
+
"vfile-message": ["vfile-message@4.0.3", "", { "dependencies": { "@types/unist": "^3.0.0", "unist-util-stringify-position": "^4.0.0" } }, "sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw=="],
|
|
140
|
+
|
|
141
|
+
"zwitch": ["zwitch@2.0.4", "", {}, "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A=="],
|
|
53
142
|
}
|
|
54
143
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@arcreflex/agent-transcripts",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.10",
|
|
4
4
|
"description": "Transform AI coding agent session files into readable transcripts",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"repository": {
|
|
@@ -21,7 +21,8 @@
|
|
|
21
21
|
"format": "prettier --write ."
|
|
22
22
|
},
|
|
23
23
|
"dependencies": {
|
|
24
|
-
"cmd-ts": "^0.13.0"
|
|
24
|
+
"cmd-ts": "^0.13.0",
|
|
25
|
+
"shiki": "^3.21.0"
|
|
25
26
|
},
|
|
26
27
|
"devDependencies": {
|
|
27
28
|
"@types/bun": "^1.1.14",
|
|
@@ -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 }
|