transcript-viewer 0.10.0__tar.gz → 0.11.0__tar.gz
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.
- transcript_viewer-0.10.0/README.md → transcript_viewer-0.11.0/PKG-INFO +27 -0
- transcript_viewer-0.10.0/PKG-INFO → transcript_viewer-0.11.0/README.md +14 -13
- transcript_viewer-0.11.0/design/Anchor.dc.html +297 -0
- transcript_viewer-0.11.0/design/Dense.dc.html +395 -0
- transcript_viewer-0.11.0/design/Hover.dc.html +271 -0
- transcript_viewer-0.11.0/design/Main.dc.html +529 -0
- transcript_viewer-0.11.0/design/Quiet.dc.html +253 -0
- transcript_viewer-0.11.0/design/canvas.json +61 -0
- transcript_viewer-0.11.0/design/delegation-timeline.html +10394 -0
- {transcript_viewer-0.10.0 → transcript_viewer-0.11.0}/pyproject.toml +2 -2
- {transcript_viewer-0.10.0 → transcript_viewer-0.11.0}/src/transcript_viewer/page.html +391 -2
- {transcript_viewer-0.10.0 → transcript_viewer-0.11.0}/tests/page.test.js +178 -1
- {transcript_viewer-0.10.0 → transcript_viewer-0.11.0}/uv.lock +5 -5
- {transcript_viewer-0.10.0 → transcript_viewer-0.11.0}/.coverage +0 -0
- {transcript_viewer-0.10.0 → transcript_viewer-0.11.0}/.github/workflows/publish.yml +0 -0
- {transcript_viewer-0.10.0 → transcript_viewer-0.11.0}/.github/workflows/test.yml +0 -0
- {transcript_viewer-0.10.0 → transcript_viewer-0.11.0}/.gitignore +0 -0
- {transcript_viewer-0.10.0 → transcript_viewer-0.11.0}/src/transcript_viewer/__init__.py +0 -0
- {transcript_viewer-0.10.0 → transcript_viewer-0.11.0}/src/transcript_viewer/ai.py +0 -0
- {transcript_viewer-0.10.0 → transcript_viewer-0.11.0}/src/transcript_viewer/cli.py +0 -0
- {transcript_viewer-0.10.0 → transcript_viewer-0.11.0}/src/transcript_viewer/config.py +0 -0
- {transcript_viewer-0.10.0 → transcript_viewer-0.11.0}/src/transcript_viewer/corpus.py +0 -0
- {transcript_viewer-0.10.0 → transcript_viewer-0.11.0}/src/transcript_viewer/fetch.py +0 -0
- {transcript_viewer-0.10.0 → transcript_viewer-0.11.0}/src/transcript_viewer/library.py +0 -0
- {transcript_viewer-0.10.0 → transcript_viewer-0.11.0}/src/transcript_viewer/store.py +0 -0
- {transcript_viewer-0.10.0 → transcript_viewer-0.11.0}/src/transcript_viewer/viewer.py +0 -0
- {transcript_viewer-0.10.0 → transcript_viewer-0.11.0}/tests/fixtures/big-command.json +0 -0
- {transcript_viewer-0.10.0 → transcript_viewer-0.11.0}/tests/test_ai.py +0 -0
- {transcript_viewer-0.10.0 → transcript_viewer-0.11.0}/tests/test_cli.py +0 -0
- {transcript_viewer-0.10.0 → transcript_viewer-0.11.0}/tests/test_config.py +0 -0
- {transcript_viewer-0.10.0 → transcript_viewer-0.11.0}/tests/test_corpus.py +0 -0
- {transcript_viewer-0.10.0 → transcript_viewer-0.11.0}/tests/test_fetch.py +0 -0
- {transcript_viewer-0.10.0 → transcript_viewer-0.11.0}/tests/test_library.py +0 -0
- {transcript_viewer-0.10.0 → transcript_viewer-0.11.0}/tests/test_page.py +0 -0
- {transcript_viewer-0.10.0 → transcript_viewer-0.11.0}/tests/test_readme.py +0 -0
- {transcript_viewer-0.10.0 → transcript_viewer-0.11.0}/tests/test_store.py +0 -0
- {transcript_viewer-0.10.0 → transcript_viewer-0.11.0}/tests/test_stream.py +0 -0
- {transcript_viewer-0.10.0 → transcript_viewer-0.11.0}/tests/test_style.py +0 -0
- {transcript_viewer-0.10.0 → transcript_viewer-0.11.0}/tests/test_tidiness.py +0 -0
- {transcript_viewer-0.10.0 → transcript_viewer-0.11.0}/tests/test_viewer.py +0 -0
|
@@ -1,3 +1,16 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: transcript-viewer
|
|
3
|
+
Version: 0.11.0
|
|
4
|
+
Summary: Browse agent transcripts in a local, dependency-free web viewer.
|
|
5
|
+
License: MIT
|
|
6
|
+
Requires-Python: >=3.12
|
|
7
|
+
Requires-Dist: atif-make>=0.7.1
|
|
8
|
+
Provides-Extra: ai
|
|
9
|
+
Requires-Dist: anthropic>=0.40; extra == 'ai'
|
|
10
|
+
Provides-Extra: parquet
|
|
11
|
+
Requires-Dist: atif-make[parquet]>=0.5.0; extra == 'parquet'
|
|
12
|
+
Description-Content-Type: text/markdown
|
|
13
|
+
|
|
1
14
|
# transcript-viewer
|
|
2
15
|
|
|
3
16
|
Browse agent transcripts in a local web viewer — what Claude Code, Codex and
|
|
@@ -166,6 +179,20 @@ If that directory is still there, the first run moves it to
|
|
|
166
179
|
`~/.transcript-viewer` — index, annotations and stored keys together — and says
|
|
167
180
|
so. Nothing is left behind and nothing is copied twice.
|
|
168
181
|
|
|
182
|
+
A run that delegated shows a **timeline** above its steps: one lane per
|
|
183
|
+
subagent, laid out on the clock. It exists for the one thing a nested box
|
|
184
|
+
cannot say — that two subagents were running at the same moment, which 25 pairs
|
|
185
|
+
in the corpus this was built against were. Clicking a lane opens the box the
|
|
186
|
+
transcript already has for it rather than showing the same thing twice.
|
|
187
|
+
|
|
188
|
+
Where a session spans days but holds hours of work — one runs 10.3 days and
|
|
189
|
+
contains 5.3 hours, with 31 gaps over an hour — the quiet stretches are skipped
|
|
190
|
+
so the work is legible, and both the count and the total skipped are stated on
|
|
191
|
+
the axis. A short subagent keeps a clickable minimum width, so where a bar is at
|
|
192
|
+
that floor its width is not its duration; the card carries the real one. A
|
|
193
|
+
transcript with no timestamps lays the same lanes out by step instead and says
|
|
194
|
+
so, and one that delegated nothing shows no timeline at all.
|
|
195
|
+
|
|
169
196
|
**Clear library** above the tree forgets every session at once, after saying
|
|
170
197
|
how many and what it will touch. Files are left alone by the same rule as a
|
|
171
198
|
single removal — only copies the viewer made itself are deleted — and stored
|
|
@@ -1,16 +1,3 @@
|
|
|
1
|
-
Metadata-Version: 2.5
|
|
2
|
-
Name: transcript-viewer
|
|
3
|
-
Version: 0.10.0
|
|
4
|
-
Summary: Browse agent transcripts in a local, dependency-free web viewer.
|
|
5
|
-
License: MIT
|
|
6
|
-
Requires-Python: >=3.12
|
|
7
|
-
Requires-Dist: atif-make>=0.7.0
|
|
8
|
-
Provides-Extra: ai
|
|
9
|
-
Requires-Dist: anthropic>=0.40; extra == 'ai'
|
|
10
|
-
Provides-Extra: parquet
|
|
11
|
-
Requires-Dist: atif-make[parquet]>=0.5.0; extra == 'parquet'
|
|
12
|
-
Description-Content-Type: text/markdown
|
|
13
|
-
|
|
14
1
|
# transcript-viewer
|
|
15
2
|
|
|
16
3
|
Browse agent transcripts in a local web viewer — what Claude Code, Codex and
|
|
@@ -179,6 +166,20 @@ If that directory is still there, the first run moves it to
|
|
|
179
166
|
`~/.transcript-viewer` — index, annotations and stored keys together — and says
|
|
180
167
|
so. Nothing is left behind and nothing is copied twice.
|
|
181
168
|
|
|
169
|
+
A run that delegated shows a **timeline** above its steps: one lane per
|
|
170
|
+
subagent, laid out on the clock. It exists for the one thing a nested box
|
|
171
|
+
cannot say — that two subagents were running at the same moment, which 25 pairs
|
|
172
|
+
in the corpus this was built against were. Clicking a lane opens the box the
|
|
173
|
+
transcript already has for it rather than showing the same thing twice.
|
|
174
|
+
|
|
175
|
+
Where a session spans days but holds hours of work — one runs 10.3 days and
|
|
176
|
+
contains 5.3 hours, with 31 gaps over an hour — the quiet stretches are skipped
|
|
177
|
+
so the work is legible, and both the count and the total skipped are stated on
|
|
178
|
+
the axis. A short subagent keeps a clickable minimum width, so where a bar is at
|
|
179
|
+
that floor its width is not its duration; the card carries the real one. A
|
|
180
|
+
transcript with no timestamps lays the same lanes out by step instead and says
|
|
181
|
+
so, and one that delegated nothing shows no timeline at all.
|
|
182
|
+
|
|
182
183
|
**Clear library** above the tree forgets every session at once, after saying
|
|
183
184
|
how many and what it will touch. Files are left alone by the same rule as a
|
|
184
185
|
single removal — only copies the viewer made itself are deleted — and stored
|
|
@@ -0,0 +1,297 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html>
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8" />
|
|
5
|
+
<script src="./support.js"></script>
|
|
6
|
+
</head>
|
|
7
|
+
<body>
|
|
8
|
+
<x-dc>
|
|
9
|
+
<helmet>
|
|
10
|
+
<link
|
|
11
|
+
rel="stylesheet"
|
|
12
|
+
href="https://fonts.googleapis.com/css2?family=Newsreader:opsz,wght@6..72,400;6..72,600&family=IBM+Plex+Mono:wght@400;500;600&display=swap"
|
|
13
|
+
/>
|
|
14
|
+
<style>
|
|
15
|
+
.root {
|
|
16
|
+
--bg: #18161c;
|
|
17
|
+
--surface: #232028;
|
|
18
|
+
--panel: #1d1b22;
|
|
19
|
+
--ink: #eae4d8;
|
|
20
|
+
--muted: #948d80;
|
|
21
|
+
--line: #332f3a;
|
|
22
|
+
--accent: #d3894b;
|
|
23
|
+
--soft: rgba(211, 137, 75, 0.13);
|
|
24
|
+
--hl: rgba(211, 137, 75, 0.25);
|
|
25
|
+
--dim: var(--muted);
|
|
26
|
+
--faint: var(--muted);
|
|
27
|
+
--sunk: var(--bg);
|
|
28
|
+
--shadow:
|
|
29
|
+
0 1px 2px rgba(0, 0, 0, 0.4), 0 10px 30px rgba(0, 0, 0, 0.45);
|
|
30
|
+
--font-ui: "Helvetica Neue", Helvetica, Arial, sans-serif;
|
|
31
|
+
--font-serif: Newsreader, Georgia, serif;
|
|
32
|
+
--font-mono: "IBM Plex Mono", ui-monospace, monospace;
|
|
33
|
+
}
|
|
34
|
+
body {
|
|
35
|
+
margin: 0;
|
|
36
|
+
font-family: var(--font-ui);
|
|
37
|
+
}
|
|
38
|
+
a {
|
|
39
|
+
color: #d3894b;
|
|
40
|
+
}
|
|
41
|
+
a:hover {
|
|
42
|
+
color: #b0522a;
|
|
43
|
+
}
|
|
44
|
+
.bar {
|
|
45
|
+
position: absolute;
|
|
46
|
+
top: 4px;
|
|
47
|
+
height: 14px;
|
|
48
|
+
border-radius: 3px;
|
|
49
|
+
background: var(--accent);
|
|
50
|
+
opacity: 0.85;
|
|
51
|
+
}
|
|
52
|
+
.rule {
|
|
53
|
+
position: absolute;
|
|
54
|
+
left: 0;
|
|
55
|
+
right: 0;
|
|
56
|
+
top: 11px;
|
|
57
|
+
height: 1px;
|
|
58
|
+
background: var(--line);
|
|
59
|
+
}
|
|
60
|
+
</style>
|
|
61
|
+
</helmet>
|
|
62
|
+
|
|
63
|
+
<div
|
|
64
|
+
class="root"
|
|
65
|
+
style="
|
|
66
|
+
background: var(--bg);
|
|
67
|
+
color: var(--ink);
|
|
68
|
+
font-family: var(--font-ui);
|
|
69
|
+
width: 900px;
|
|
70
|
+
min-height: 560px;
|
|
71
|
+
box-sizing: border-box;
|
|
72
|
+
padding: 22px;
|
|
73
|
+
"
|
|
74
|
+
>
|
|
75
|
+
<div
|
|
76
|
+
style="
|
|
77
|
+
display: flex;
|
|
78
|
+
align-items: baseline;
|
|
79
|
+
gap: 12px;
|
|
80
|
+
margin-bottom: 10px;
|
|
81
|
+
"
|
|
82
|
+
>
|
|
83
|
+
<h2
|
|
84
|
+
style="
|
|
85
|
+
margin: 0;
|
|
86
|
+
font: 600 15px var(--font-serif);
|
|
87
|
+
letter-spacing: -0.01em;
|
|
88
|
+
"
|
|
89
|
+
>
|
|
90
|
+
Delegation
|
|
91
|
+
</h2>
|
|
92
|
+
<span style="font: 11px var(--font-mono); color: var(--muted)"
|
|
93
|
+
>a lane and the step that started it</span
|
|
94
|
+
>
|
|
95
|
+
</div>
|
|
96
|
+
|
|
97
|
+
<!-- The chart, with one lane picked out -->
|
|
98
|
+
<div
|
|
99
|
+
style="
|
|
100
|
+
border: 1px solid var(--line);
|
|
101
|
+
border-radius: 9px;
|
|
102
|
+
background: var(--panel);
|
|
103
|
+
padding: 14px 16px 12px;
|
|
104
|
+
"
|
|
105
|
+
>
|
|
106
|
+
<sc-for list="{{lanes}}" as="lane" hint-placeholder-count="3">
|
|
107
|
+
<div
|
|
108
|
+
style="display:grid;grid-template-columns:150px 1fr;gap:0 12px;align-items:center;
|
|
109
|
+
padding:2px 0;opacity:{{lane.dim}}"
|
|
110
|
+
>
|
|
111
|
+
<div style="display: flex; align-items: baseline; gap: 7px">
|
|
112
|
+
<span
|
|
113
|
+
style="
|
|
114
|
+
color: var(--accent);
|
|
115
|
+
font-weight: 700;
|
|
116
|
+
font-size: 11px;
|
|
117
|
+
"
|
|
118
|
+
>⤷</span
|
|
119
|
+
>
|
|
120
|
+
<span style="font: 12px var(--font-mono); color: var(--accent)"
|
|
121
|
+
>{{lane.kind}}</span
|
|
122
|
+
>
|
|
123
|
+
</div>
|
|
124
|
+
<div style="position: relative; height: 22px">
|
|
125
|
+
<div class="rule"></div>
|
|
126
|
+
<span
|
|
127
|
+
class="bar"
|
|
128
|
+
style="left:{{lane.at}};width:{{lane.w}}"
|
|
129
|
+
></span>
|
|
130
|
+
<span
|
|
131
|
+
style="position:absolute;top:2px;left:{{lane.at}};font:10px var(--font-mono);
|
|
132
|
+
color:var(--accent);margin-left:-46px;opacity:{{lane.tagOn}}"
|
|
133
|
+
>step 128</span
|
|
134
|
+
>
|
|
135
|
+
</div>
|
|
136
|
+
</div>
|
|
137
|
+
</sc-for>
|
|
138
|
+
</div>
|
|
139
|
+
|
|
140
|
+
<!-- The leader: the chart and the transcript are the same run, so the tie is
|
|
141
|
+
drawn rather than described. -->
|
|
142
|
+
<div style="position: relative; height: 34px; margin-left: 162px">
|
|
143
|
+
<span
|
|
144
|
+
style="
|
|
145
|
+
position: absolute;
|
|
146
|
+
left: 24%;
|
|
147
|
+
top: 0;
|
|
148
|
+
bottom: 8px;
|
|
149
|
+
width: 1px;
|
|
150
|
+
background: var(--accent);
|
|
151
|
+
opacity: 0.5;
|
|
152
|
+
"
|
|
153
|
+
></span>
|
|
154
|
+
<span
|
|
155
|
+
style="
|
|
156
|
+
position: absolute;
|
|
157
|
+
left: 24%;
|
|
158
|
+
bottom: 2px;
|
|
159
|
+
width: 7px;
|
|
160
|
+
height: 7px;
|
|
161
|
+
border-radius: 999px;
|
|
162
|
+
background: var(--accent);
|
|
163
|
+
margin-left: -3px;
|
|
164
|
+
"
|
|
165
|
+
></span>
|
|
166
|
+
</div>
|
|
167
|
+
|
|
168
|
+
<!-- The step, exactly as the transcript draws it, with the delegation inside -->
|
|
169
|
+
<div
|
|
170
|
+
style="
|
|
171
|
+
position: relative;
|
|
172
|
+
margin: 0 0 10px 46px;
|
|
173
|
+
padding: 9px 15px 11px;
|
|
174
|
+
border-left: 2px solid var(--ink);
|
|
175
|
+
border-radius: 0 9px 9px 0;
|
|
176
|
+
background: var(--panel);
|
|
177
|
+
"
|
|
178
|
+
>
|
|
179
|
+
<div
|
|
180
|
+
style="
|
|
181
|
+
font: 10px var(--font-mono);
|
|
182
|
+
color: var(--faint);
|
|
183
|
+
margin-bottom: 5px;
|
|
184
|
+
"
|
|
185
|
+
>
|
|
186
|
+
128 · agent · 09:41:06 · claude-opus-5
|
|
187
|
+
</div>
|
|
188
|
+
<div style="font-size: 13.5px; line-height: 1.55; margin-bottom: 9px">
|
|
189
|
+
I'll look for everywhere the theme is applied before changing the
|
|
190
|
+
token.
|
|
191
|
+
</div>
|
|
192
|
+
|
|
193
|
+
<!-- the existing .branch component, unchanged: 1px accent, radius 9, ⤷ -->
|
|
194
|
+
<div
|
|
195
|
+
style="
|
|
196
|
+
border: 1px solid var(--accent);
|
|
197
|
+
border-radius: 9px;
|
|
198
|
+
background: var(--panel);
|
|
199
|
+
overflow: hidden;
|
|
200
|
+
"
|
|
201
|
+
>
|
|
202
|
+
<div
|
|
203
|
+
style="
|
|
204
|
+
padding: 9px 12px;
|
|
205
|
+
font-size: 12.5px;
|
|
206
|
+
display: flex;
|
|
207
|
+
gap: 9px;
|
|
208
|
+
align-items: center;
|
|
209
|
+
color: var(--accent);
|
|
210
|
+
"
|
|
211
|
+
>
|
|
212
|
+
<span style="font-weight: 700">⤷</span>
|
|
213
|
+
<b style="font-weight: 700">Explore</b>
|
|
214
|
+
<span
|
|
215
|
+
style="
|
|
216
|
+
color: var(--dim);
|
|
217
|
+
font-weight: 400;
|
|
218
|
+
overflow: hidden;
|
|
219
|
+
text-overflow: ellipsis;
|
|
220
|
+
white-space: nowrap;
|
|
221
|
+
"
|
|
222
|
+
>find every place the theme is set</span
|
|
223
|
+
>
|
|
224
|
+
<span
|
|
225
|
+
style="
|
|
226
|
+
border: 1px solid var(--accent);
|
|
227
|
+
border-radius: 999px;
|
|
228
|
+
padding: 1px 7px;
|
|
229
|
+
font-size: 10px;
|
|
230
|
+
color: var(--accent);
|
|
231
|
+
white-space: nowrap;
|
|
232
|
+
"
|
|
233
|
+
>12 steps</span
|
|
234
|
+
>
|
|
235
|
+
<span
|
|
236
|
+
style="
|
|
237
|
+
border: 1px solid var(--line);
|
|
238
|
+
border-radius: 999px;
|
|
239
|
+
padding: 1px 7px;
|
|
240
|
+
font-size: 10px;
|
|
241
|
+
color: var(--dim);
|
|
242
|
+
white-space: nowrap;
|
|
243
|
+
margin-left: auto;
|
|
244
|
+
"
|
|
245
|
+
>
|
|
246
|
+
4m 12s
|
|
247
|
+
</span>
|
|
248
|
+
<span
|
|
249
|
+
style="
|
|
250
|
+
font: 10px var(--font-mono);
|
|
251
|
+
color: var(--faint);
|
|
252
|
+
white-space: nowrap;
|
|
253
|
+
"
|
|
254
|
+
>
|
|
255
|
+
in timeline
|
|
256
|
+
</span>
|
|
257
|
+
</div>
|
|
258
|
+
</div>
|
|
259
|
+
</div>
|
|
260
|
+
|
|
261
|
+
<div
|
|
262
|
+
style="
|
|
263
|
+
font-size: 11.5px;
|
|
264
|
+
color: var(--faint);
|
|
265
|
+
line-height: 1.5;
|
|
266
|
+
padding-left: 46px;
|
|
267
|
+
"
|
|
268
|
+
>
|
|
269
|
+
The tie runs both ways: a lane carries the step number that started
|
|
270
|
+
it, and the step keeps the box it always had, now also saying how long
|
|
271
|
+
the subagent took and offering the way back out to the timeline.
|
|
272
|
+
</div>
|
|
273
|
+
</div>
|
|
274
|
+
</x-dc>
|
|
275
|
+
|
|
276
|
+
<script data-dc-script data-props="{}">
|
|
277
|
+
class Component extends DCLogic {
|
|
278
|
+
renderVals() {
|
|
279
|
+
const raw = [
|
|
280
|
+
{ kind: "Explore", at: 6, end: 14, on: false },
|
|
281
|
+
{ kind: "Explore", at: 24, end: 33, on: true },
|
|
282
|
+
{ kind: "general-purpose", at: 38, end: 41, on: false },
|
|
283
|
+
];
|
|
284
|
+
return {
|
|
285
|
+
lanes: raw.map((r) => ({
|
|
286
|
+
kind: r.kind,
|
|
287
|
+
at: r.at + "%",
|
|
288
|
+
w: r.end - r.at + "%",
|
|
289
|
+
dim: r.on ? "1" : ".45",
|
|
290
|
+
tagOn: r.on ? "1" : "0",
|
|
291
|
+
})),
|
|
292
|
+
};
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
</script>
|
|
296
|
+
</body>
|
|
297
|
+
</html>
|