@jigyasudham/veto 3.1.2 → 3.2.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.
Files changed (84) hide show
  1. package/README.md +29 -1
  2. package/dist/bin/veto-server.d.ts +3 -0
  3. package/dist/bin/veto-server.d.ts.map +1 -0
  4. package/dist/bin/veto-server.js +18 -0
  5. package/dist/bin/veto-server.js.map +1 -0
  6. package/dist/cli.js +51 -1
  7. package/dist/cli.js.map +1 -1
  8. package/dist/host.d.ts +23 -0
  9. package/dist/host.d.ts.map +1 -0
  10. package/dist/host.js +81 -0
  11. package/dist/host.js.map +1 -0
  12. package/dist/server/handlers/observability.d.ts.map +1 -1
  13. package/dist/server/handlers/observability.js +16 -1
  14. package/dist/server/handlers/observability.js.map +1 -1
  15. package/dist/server/handlers/session.d.ts.map +1 -1
  16. package/dist/server/handlers/session.js +18 -5
  17. package/dist/server/handlers/session.js.map +1 -1
  18. package/dist/server.d.ts +1 -0
  19. package/dist/server.d.ts.map +1 -1
  20. package/dist/server.js +50 -4
  21. package/dist/server.js.map +1 -1
  22. package/dist/tools/definitions.d.ts +3 -3
  23. package/dist/tools/definitions.js +3 -3
  24. package/dist/tools/definitions.js.map +1 -1
  25. package/dist/transcripts/adapters/claude.d.ts +2 -24
  26. package/dist/transcripts/adapters/claude.d.ts.map +1 -1
  27. package/dist/transcripts/adapters/claude.js +31 -129
  28. package/dist/transcripts/adapters/claude.js.map +1 -1
  29. package/dist/transcripts/adapters/codex.d.ts +4 -0
  30. package/dist/transcripts/adapters/codex.d.ts.map +1 -0
  31. package/dist/transcripts/adapters/codex.js +120 -0
  32. package/dist/transcripts/adapters/codex.js.map +1 -0
  33. package/dist/transcripts/adapters/gemini.d.ts +4 -0
  34. package/dist/transcripts/adapters/gemini.d.ts.map +1 -0
  35. package/dist/transcripts/adapters/gemini.js +124 -0
  36. package/dist/transcripts/adapters/gemini.js.map +1 -0
  37. package/dist/transcripts/adapters/index.d.ts +16 -0
  38. package/dist/transcripts/adapters/index.d.ts.map +1 -0
  39. package/dist/transcripts/adapters/index.js +36 -0
  40. package/dist/transcripts/adapters/index.js.map +1 -0
  41. package/dist/transcripts/adapters/jsonl.d.ts +67 -0
  42. package/dist/transcripts/adapters/jsonl.d.ts.map +1 -0
  43. package/dist/transcripts/adapters/jsonl.js +138 -0
  44. package/dist/transcripts/adapters/jsonl.js.map +1 -0
  45. package/dist/transcripts/archive.d.ts.map +1 -1
  46. package/dist/transcripts/archive.js +2 -1
  47. package/dist/transcripts/archive.js.map +1 -1
  48. package/dist/transcripts/discover.d.ts +50 -0
  49. package/dist/transcripts/discover.d.ts.map +1 -0
  50. package/dist/transcripts/discover.js +247 -0
  51. package/dist/transcripts/discover.js.map +1 -0
  52. package/dist/transcripts/expand.d.ts +33 -2
  53. package/dist/transcripts/expand.d.ts.map +1 -1
  54. package/dist/transcripts/expand.js +95 -9
  55. package/dist/transcripts/expand.js.map +1 -1
  56. package/dist/transcripts/ingest.js +2 -2
  57. package/dist/transcripts/ingest.js.map +1 -1
  58. package/dist/transcripts/mapping.d.ts +8 -0
  59. package/dist/transcripts/mapping.d.ts.map +1 -1
  60. package/dist/transcripts/mapping.js +1 -1
  61. package/dist/transcripts/mapping.js.map +1 -1
  62. package/dist/transcripts/metric.d.ts +80 -0
  63. package/dist/transcripts/metric.d.ts.map +1 -0
  64. package/dist/transcripts/metric.js +306 -0
  65. package/dist/transcripts/metric.js.map +1 -0
  66. package/dist/transcripts/on-save.d.ts +18 -0
  67. package/dist/transcripts/on-save.d.ts.map +1 -1
  68. package/dist/transcripts/on-save.js +41 -2
  69. package/dist/transcripts/on-save.js.map +1 -1
  70. package/dist/transcripts/pyramid.d.ts +8 -0
  71. package/dist/transcripts/pyramid.d.ts.map +1 -1
  72. package/dist/transcripts/pyramid.js +40 -6
  73. package/dist/transcripts/pyramid.js.map +1 -1
  74. package/dist/transcripts/recall.d.ts +2 -0
  75. package/dist/transcripts/recall.d.ts.map +1 -1
  76. package/dist/transcripts/recall.js +36 -12
  77. package/dist/transcripts/recall.js.map +1 -1
  78. package/dist/transcripts/search.d.ts.map +1 -1
  79. package/dist/transcripts/search.js +20 -11
  80. package/dist/transcripts/search.js.map +1 -1
  81. package/dist/transcripts/toc.js +3 -4
  82. package/dist/transcripts/toc.js.map +1 -1
  83. package/package.json +3 -3
  84. package/server.json +2 -2
@@ -0,0 +1,50 @@
1
+ export type DiscoveredSession = {
2
+ source: 'codex' | 'gemini';
3
+ sourceSessionId: string;
4
+ transcriptPath: string;
5
+ projectDir: string | null;
6
+ mtimeMs: number;
7
+ };
8
+ export type DiscoverResult = {
9
+ scanned: number;
10
+ recorded: number;
11
+ sessions: DiscoveredSession[];
12
+ };
13
+ export declare function codexSessionsDir(): string;
14
+ export declare function geminiTmpDir(): string;
15
+ /**
16
+ * Codex: ~/.codex/sessions/YYYY/MM/DD/rollout-<ts>-<uuid>.jsonl.
17
+ * The session id and the project (`cwd`) both live in the leading session_meta
18
+ * line, so one bounded head-read per file answers both.
19
+ */
20
+ export declare function discoverCodexSessions(limit?: number): DiscoveredSession[];
21
+ /**
22
+ * Gemini: ~/.gemini/tmp/<project>/chats/session-<ts>-<id>.jsonl, with the real
23
+ * project path in the sibling `<project>/.project_root` file (the directory name
24
+ * itself is a slug or a hash, so it cannot be mapped back on its own).
25
+ *
26
+ * MOST OF THESE FILES ARE NOT SESSIONS. Antigravity's agent-to-agent server
27
+ * drops a header-only stub per project/run, all of them reporting the SAME
28
+ * literal session id, "a2a-server". On this developer's machine that is 2,347 of
29
+ * 2,367 files, and not one contains a single conversation record. They are
30
+ * skipped for two independent reasons: they carry nothing to recall, and one id
31
+ * shared across many projects would otherwise collide in `archives`
32
+ * (UNIQUE(source, source_session_id)) and let one project's mapping overwrite
33
+ * another's. Because the stubs are also the NEWEST files, filtering has to
34
+ * happen before the newest-first cap or the real sessions never survive it.
35
+ */
36
+ export declare function discoverGeminiSessions(limit?: number): DiscoveredSession[];
37
+ /**
38
+ * Discover and record mappings for one source. Best-effort: never throws.
39
+ *
40
+ * When two files claim the same session id — Gemini's Antigravity stub sessions
41
+ * all report the literal id "a2a-server" — the newest file wins, so the mapping
42
+ * is deterministic instead of depending on directory order.
43
+ */
44
+ export declare function discoverSessions(source: 'codex' | 'gemini', limit?: number): DiscoverResult;
45
+ /**
46
+ * Whether any discovered session belongs to `projectDir` — lets the save path
47
+ * skip a capture attempt that could only bind the wrong project's session.
48
+ */
49
+ export declare function hasSessionForProject(sessions: DiscoveredSession[], projectDir: string): boolean;
50
+ //# sourceMappingURL=discover.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"discover.d.ts","sourceRoot":"","sources":["../../src/transcripts/discover.ts"],"names":[],"mappings":"AA6BA,MAAM,MAAM,iBAAiB,GAAG;IAC9B,MAAM,EAAE,OAAO,GAAG,QAAQ,CAAC;IAC3B,eAAe,EAAE,MAAM,CAAC;IACxB,cAAc,EAAE,MAAM,CAAC;IACvB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,iBAAiB,EAAE,CAAA;CAAE,CAAC;AAoDlG,wBAAgB,gBAAgB,IAAI,MAAM,CAEzC;AAED,wBAAgB,YAAY,IAAI,MAAM,CAErC;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,SAAiB,GAAG,iBAAiB,EAAE,CAcjF;AAOD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,SAAiB,GAAG,iBAAiB,EAAE,CAwClF;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,OAAO,GAAG,QAAQ,EAAE,KAAK,SAAiB,GAAG,cAAc,CA8BnG;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,iBAAiB,EAAE,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAG/F"}
@@ -0,0 +1,247 @@
1
+ // Session discovery for the CLIs that have no statusline hook (v3.2).
2
+ //
3
+ // Claude Code renders a statusline on every turn and hands Veto both its session
4
+ // id and transcript path, so `mapping.ts` just UPSERTs what it is given. Codex
5
+ // and Gemini expose no such hook — Veto only runs inside them as an MCP server,
6
+ // which never sees the host's own transcript path. So for those two the mapping
7
+ // has to be DISCOVERED from disk instead: find the session files, read which
8
+ // project each belongs to, and record the same session_map rows the statusline
9
+ // would have written. Everything downstream (archive → ingest → recall) is then
10
+ // identical across all three sources.
11
+ //
12
+ // Cost control — this runs on the save path, so it must stay cheap and bounded:
13
+ // • candidates are sorted by mtime and capped (MAX_CANDIDATES) — a machine with
14
+ // thousands of old sessions still does a fixed amount of work;
15
+ // • only a bounded HEAD of each file is read, never the whole transcript;
16
+ // • it is best-effort and never throws, exactly like capture itself.
17
+ import { readdirSync, statSync, existsSync, openSync, readSync, closeSync, readFileSync } from 'node:fs';
18
+ import { homedir } from 'node:os';
19
+ import { join } from 'node:path';
20
+ import { recordSessionMapping } from './mapping.js';
21
+ import { normalizeProjectDir } from '../memory/local.js';
22
+ // Newest-first cap on how many session files one discovery pass will inspect.
23
+ const MAX_CANDIDATES = 40;
24
+ // Enough to cover a Codex session_meta line (which embeds the base instructions)
25
+ // or a Gemini header line, without reading a multi-MB transcript.
26
+ const HEAD_BYTES = 256 * 1024;
27
+ /** Read at most `HEAD_BYTES` from the front of a file (transcripts can be huge). */
28
+ function readHead(path) {
29
+ let fd = null;
30
+ try {
31
+ fd = openSync(path, 'r');
32
+ const buf = Buffer.allocUnsafe(HEAD_BYTES);
33
+ const n = readSync(fd, buf, 0, HEAD_BYTES, 0);
34
+ return buf.toString('utf8', 0, n);
35
+ }
36
+ catch {
37
+ return '';
38
+ }
39
+ finally {
40
+ if (fd !== null) {
41
+ try {
42
+ closeSync(fd);
43
+ }
44
+ catch { /* ignore */ }
45
+ }
46
+ }
47
+ }
48
+ /** First complete JSON line of a file, or null if the head holds none. */
49
+ function firstJsonLine(path) {
50
+ const head = readHead(path);
51
+ const nl = head.indexOf('\n');
52
+ const line = nl === -1 ? head : head.slice(0, nl);
53
+ if (!line.trim())
54
+ return null;
55
+ try {
56
+ const o = JSON.parse(line);
57
+ return o && typeof o === 'object' ? o : null;
58
+ }
59
+ catch {
60
+ return null;
61
+ }
62
+ }
63
+ function listFiles(dir, match, out, depth = 0) {
64
+ if (depth > 5 || !existsSync(dir))
65
+ return;
66
+ let entries;
67
+ try {
68
+ entries = readdirSync(dir, { withFileTypes: true });
69
+ }
70
+ catch {
71
+ return;
72
+ }
73
+ for (const e of entries) {
74
+ const p = join(dir, e.name);
75
+ if (e.isDirectory())
76
+ listFiles(p, match, out, depth + 1);
77
+ else if (match(e.name))
78
+ out.push(p);
79
+ }
80
+ }
81
+ /** Newest-first, capped: the bound that keeps discovery off the critical path. */
82
+ function newestFirst(paths, limit = MAX_CANDIDATES) {
83
+ const withTime = [];
84
+ for (const p of paths) {
85
+ try {
86
+ withTime.push({ path: p, mtimeMs: statSync(p).mtimeMs });
87
+ }
88
+ catch { /* vanished */ }
89
+ }
90
+ withTime.sort((a, b) => b.mtimeMs - a.mtimeMs);
91
+ return withTime.slice(0, limit);
92
+ }
93
+ export function codexSessionsDir() {
94
+ return process.env.CODEX_HOME ? join(process.env.CODEX_HOME, 'sessions') : join(homedir(), '.codex', 'sessions');
95
+ }
96
+ export function geminiTmpDir() {
97
+ return process.env.GEMINI_DIR ? join(process.env.GEMINI_DIR, 'tmp') : join(homedir(), '.gemini', 'tmp');
98
+ }
99
+ /**
100
+ * Codex: ~/.codex/sessions/YYYY/MM/DD/rollout-<ts>-<uuid>.jsonl.
101
+ * The session id and the project (`cwd`) both live in the leading session_meta
102
+ * line, so one bounded head-read per file answers both.
103
+ */
104
+ export function discoverCodexSessions(limit = MAX_CANDIDATES) {
105
+ const files = [];
106
+ listFiles(codexSessionsDir(), (n) => n.startsWith('rollout-') && n.endsWith('.jsonl'), files);
107
+ const out = [];
108
+ for (const { path, mtimeMs } of newestFirst(files, limit)) {
109
+ const first = firstJsonLine(path);
110
+ const payload = first && typeof first.payload === 'object' ? first.payload : null;
111
+ if (!payload || first?.type !== 'session_meta')
112
+ continue;
113
+ const id = typeof payload.id === 'string' ? payload.id : null;
114
+ if (!id)
115
+ continue;
116
+ const cwd = typeof payload.cwd === 'string' && payload.cwd ? payload.cwd : null;
117
+ out.push({ source: 'codex', sourceSessionId: id, transcriptPath: path, projectDir: cwd, mtimeMs });
118
+ }
119
+ return out;
120
+ }
121
+ // A real Gemini CLI session names its file after its session UUID
122
+ // (session-<ts>-<8 hex>.jsonl) and reports that UUID in the header.
123
+ const GEMINI_REAL_FILE_RE = /-[0-9a-f]{8}\.jsonl$/;
124
+ const UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
125
+ /**
126
+ * Gemini: ~/.gemini/tmp/<project>/chats/session-<ts>-<id>.jsonl, with the real
127
+ * project path in the sibling `<project>/.project_root` file (the directory name
128
+ * itself is a slug or a hash, so it cannot be mapped back on its own).
129
+ *
130
+ * MOST OF THESE FILES ARE NOT SESSIONS. Antigravity's agent-to-agent server
131
+ * drops a header-only stub per project/run, all of them reporting the SAME
132
+ * literal session id, "a2a-server". On this developer's machine that is 2,347 of
133
+ * 2,367 files, and not one contains a single conversation record. They are
134
+ * skipped for two independent reasons: they carry nothing to recall, and one id
135
+ * shared across many projects would otherwise collide in `archives`
136
+ * (UNIQUE(source, source_session_id)) and let one project's mapping overwrite
137
+ * another's. Because the stubs are also the NEWEST files, filtering has to
138
+ * happen before the newest-first cap or the real sessions never survive it.
139
+ */
140
+ export function discoverGeminiSessions(limit = MAX_CANDIDATES) {
141
+ const root = geminiTmpDir();
142
+ if (!existsSync(root))
143
+ return [];
144
+ let dirs;
145
+ try {
146
+ dirs = readdirSync(root, { withFileTypes: true });
147
+ }
148
+ catch {
149
+ return [];
150
+ }
151
+ const all = [];
152
+ const named = [];
153
+ for (const d of dirs) {
154
+ if (!d.isDirectory())
155
+ continue;
156
+ const chats = join(root, d.name, 'chats');
157
+ if (!existsSync(chats))
158
+ continue;
159
+ let projectDir = null;
160
+ const rootFile = join(root, d.name, '.project_root');
161
+ if (existsSync(rootFile)) {
162
+ try {
163
+ projectDir = readFileSync(rootFile, 'utf8').trim() || null;
164
+ }
165
+ catch {
166
+ projectDir = null;
167
+ }
168
+ }
169
+ let names;
170
+ try {
171
+ names = readdirSync(chats);
172
+ }
173
+ catch {
174
+ continue;
175
+ }
176
+ for (const n of names) {
177
+ if (!n.endsWith('.jsonl'))
178
+ continue;
179
+ const entry = { path: join(chats, n), projectDir };
180
+ all.push(entry);
181
+ if (GEMINI_REAL_FILE_RE.test(n))
182
+ named.push(entry);
183
+ }
184
+ }
185
+ // The filename filter is a free prefilter, but the header check below is the
186
+ // authority — so if a future rename makes the pattern match nothing, fall back
187
+ // to inspecting everything rather than silently discovering no sessions.
188
+ const files = named.length > 0 ? named : all;
189
+ const byPath = new Map(files.map(f => [f.path, f.projectDir]));
190
+ const out = [];
191
+ for (const { path, mtimeMs } of newestFirst(files.map(f => f.path), limit)) {
192
+ const header = firstJsonLine(path);
193
+ const id = header && typeof header.sessionId === 'string' ? header.sessionId : null;
194
+ if (!id || !UUID_RE.test(id))
195
+ continue;
196
+ out.push({ source: 'gemini', sourceSessionId: id, transcriptPath: path, projectDir: byPath.get(path) ?? null, mtimeMs });
197
+ }
198
+ return out;
199
+ }
200
+ /**
201
+ * Discover and record mappings for one source. Best-effort: never throws.
202
+ *
203
+ * When two files claim the same session id — Gemini's Antigravity stub sessions
204
+ * all report the literal id "a2a-server" — the newest file wins, so the mapping
205
+ * is deterministic instead of depending on directory order.
206
+ */
207
+ export function discoverSessions(source, limit = MAX_CANDIDATES) {
208
+ let sessions = [];
209
+ try {
210
+ sessions = source === 'codex' ? discoverCodexSessions(limit) : discoverGeminiSessions(limit);
211
+ }
212
+ catch {
213
+ return { scanned: 0, recorded: 0, sessions: [] };
214
+ }
215
+ const newestById = new Map();
216
+ for (const s of sessions) {
217
+ const prev = newestById.get(s.sourceSessionId);
218
+ if (!prev || s.mtimeMs > prev.mtimeMs)
219
+ newestById.set(s.sourceSessionId, s);
220
+ }
221
+ let recorded = 0;
222
+ for (const s of newestById.values()) {
223
+ try {
224
+ recordSessionMapping({
225
+ source: s.source,
226
+ sourceSessionId: s.sourceSessionId,
227
+ transcriptPath: s.transcriptPath,
228
+ projectDir: s.projectDir,
229
+ // The transcript's mtime, not now — several sessions are recorded in one
230
+ // pass and capture picks the most recent one for the project.
231
+ lastSeenAt: new Date(s.mtimeMs).toISOString(),
232
+ });
233
+ recorded++;
234
+ }
235
+ catch { /* mapping is best-effort */ }
236
+ }
237
+ return { scanned: sessions.length, recorded, sessions: [...newestById.values()] };
238
+ }
239
+ /**
240
+ * Whether any discovered session belongs to `projectDir` — lets the save path
241
+ * skip a capture attempt that could only bind the wrong project's session.
242
+ */
243
+ export function hasSessionForProject(sessions, projectDir) {
244
+ const want = normalizeProjectDir(projectDir);
245
+ return sessions.some(s => s.projectDir && normalizeProjectDir(s.projectDir) === want);
246
+ }
247
+ //# sourceMappingURL=discover.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"discover.js","sourceRoot":"","sources":["../../src/transcripts/discover.ts"],"names":[],"mappings":"AAAA,sEAAsE;AACtE,EAAE;AACF,iFAAiF;AACjF,+EAA+E;AAC/E,gFAAgF;AAChF,gFAAgF;AAChF,6EAA6E;AAC7E,+EAA+E;AAC/E,gFAAgF;AAChF,sCAAsC;AACtC,EAAE;AACF,gFAAgF;AAChF,kFAAkF;AAClF,mEAAmE;AACnE,4EAA4E;AAC5E,uEAAuE;AAEvE,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,UAAU,EAAE,QAAQ,EAAE,QAAQ,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACzG,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AACpD,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAEzD,8EAA8E;AAC9E,MAAM,cAAc,GAAG,EAAE,CAAC;AAC1B,iFAAiF;AACjF,kEAAkE;AAClE,MAAM,UAAU,GAAG,GAAG,GAAG,IAAI,CAAC;AAY9B,oFAAoF;AACpF,SAAS,QAAQ,CAAC,IAAY;IAC5B,IAAI,EAAE,GAAkB,IAAI,CAAC;IAC7B,IAAI,CAAC;QACH,EAAE,GAAG,QAAQ,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;QACzB,MAAM,GAAG,GAAG,MAAM,CAAC,WAAW,CAAC,UAAU,CAAC,CAAC;QAC3C,MAAM,CAAC,GAAG,QAAQ,CAAC,EAAE,EAAE,GAAG,EAAE,CAAC,EAAE,UAAU,EAAE,CAAC,CAAC,CAAC;QAC9C,OAAO,GAAG,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;IACpC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;YAAS,CAAC;QACT,IAAI,EAAE,KAAK,IAAI,EAAE,CAAC;YAAC,IAAI,CAAC;gBAAC,SAAS,CAAC,EAAE,CAAC,CAAC;YAAC,CAAC;YAAC,MAAM,CAAC,CAAC,YAAY,CAAC,CAAC;QAAC,CAAC;IACpE,CAAC;AACH,CAAC;AAED,0EAA0E;AAC1E,SAAS,aAAa,CAAC,IAAY;IACjC,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;IAC5B,MAAM,EAAE,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9B,MAAM,IAAI,GAAG,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IAClD,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE;QAAE,OAAO,IAAI,CAAC;IAC9B,IAAI,CAAC;QACH,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAY,CAAC;QACtC,OAAO,CAAC,IAAI,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,CAA4B,CAAC,CAAC,CAAC,IAAI,CAAC;IAC1E,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,SAAS,SAAS,CAAC,GAAW,EAAE,KAAgC,EAAE,GAAa,EAAE,KAAK,GAAG,CAAC;IACxF,IAAI,KAAK,GAAG,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC;QAAE,OAAO;IAC1C,IAAI,OAAO,CAAC;IACZ,IAAI,CAAC;QAAC,OAAO,GAAG,WAAW,CAAC,GAAG,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;IAAC,CAAC;IAAC,MAAM,CAAC;QAAC,OAAO;IAAC,CAAC;IAC9E,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;QACxB,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;QAC5B,IAAI,CAAC,CAAC,WAAW,EAAE;YAAE,SAAS,CAAC,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,KAAK,GAAG,CAAC,CAAC,CAAC;aACpD,IAAI,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC;YAAE,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACtC,CAAC;AACH,CAAC;AAED,kFAAkF;AAClF,SAAS,WAAW,CAAC,KAAe,EAAE,KAAK,GAAG,cAAc;IAC1D,MAAM,QAAQ,GAAwC,EAAE,CAAC;IACzD,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;QACtB,IAAI,CAAC;YAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC;QAAC,CAAC;QAAC,MAAM,CAAC,CAAC,cAAc,CAAC,CAAC;IAC5F,CAAC;IACD,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC;IAC/C,OAAO,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;AAClC,CAAC;AAED,MAAM,UAAU,gBAAgB;IAC9B,OAAO,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,QAAQ,EAAE,UAAU,CAAC,CAAC;AACnH,CAAC;AAED,MAAM,UAAU,YAAY;IAC1B,OAAO,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,KAAK,CAAC,CAAC;AAC1G,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,qBAAqB,CAAC,KAAK,GAAG,cAAc;IAC1D,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,SAAS,CAAC,gBAAgB,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,KAAK,CAAC,CAAC;IAC9F,MAAM,GAAG,GAAwB,EAAE,CAAC;IACpC,KAAK,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,WAAW,CAAC,KAAK,EAAE,KAAK,CAAC,EAAE,CAAC;QAC1D,MAAM,KAAK,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC;QAClC,MAAM,OAAO,GAAG,KAAK,IAAI,OAAO,KAAK,CAAC,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,OAAkC,CAAC,CAAC,CAAC,IAAI,CAAC;QAC7G,IAAI,CAAC,OAAO,IAAI,KAAK,EAAE,IAAI,KAAK,cAAc;YAAE,SAAS;QACzD,MAAM,EAAE,GAAG,OAAO,OAAO,CAAC,EAAE,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;QAC9D,IAAI,CAAC,EAAE;YAAE,SAAS;QAClB,MAAM,GAAG,GAAG,OAAO,OAAO,CAAC,GAAG,KAAK,QAAQ,IAAI,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC;QAChF,GAAG,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,eAAe,EAAE,EAAE,EAAE,cAAc,EAAE,IAAI,EAAE,UAAU,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC,CAAC;IACrG,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,kEAAkE;AAClE,oEAAoE;AACpE,MAAM,mBAAmB,GAAG,sBAAsB,CAAC;AACnD,MAAM,OAAO,GAAG,iEAAiE,CAAC;AAElF;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,sBAAsB,CAAC,KAAK,GAAG,cAAc;IAC3D,MAAM,IAAI,GAAG,YAAY,EAAE,CAAC;IAC5B,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;QAAE,OAAO,EAAE,CAAC;IACjC,IAAI,IAAI,CAAC;IACT,IAAI,CAAC;QAAC,IAAI,GAAG,WAAW,CAAC,IAAI,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;IAAC,CAAC;IAAC,MAAM,CAAC;QAAC,OAAO,EAAE,CAAC;IAAC,CAAC;IAE/E,MAAM,GAAG,GAAkD,EAAE,CAAC;IAC9D,MAAM,KAAK,GAAkD,EAAE,CAAC;IAChE,KAAK,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC;QACrB,IAAI,CAAC,CAAC,CAAC,WAAW,EAAE;YAAE,SAAS;QAC/B,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QAC1C,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC;YAAE,SAAS;QACjC,IAAI,UAAU,GAAkB,IAAI,CAAC;QACrC,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,eAAe,CAAC,CAAC;QACrD,IAAI,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;YACzB,IAAI,CAAC;gBAAC,UAAU,GAAG,YAAY,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,IAAI,EAAE,IAAI,IAAI,CAAC;YAAC,CAAC;YAAC,MAAM,CAAC;gBAAC,UAAU,GAAG,IAAI,CAAC;YAAC,CAAC;QAClG,CAAC;QACD,IAAI,KAAK,CAAC;QACV,IAAI,CAAC;YAAC,KAAK,GAAG,WAAW,CAAC,KAAK,CAAC,CAAC;QAAC,CAAC;QAAC,MAAM,CAAC;YAAC,SAAS;QAAC,CAAC;QACvD,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;YACtB,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC;gBAAE,SAAS;YACpC,MAAM,KAAK,GAAG,EAAE,IAAI,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC;YACnD,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAChB,IAAI,mBAAmB,CAAC,IAAI,CAAC,CAAC,CAAC;gBAAE,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACrD,CAAC;IACH,CAAC;IAED,6EAA6E;IAC7E,+EAA+E;IAC/E,yEAAyE;IACzE,MAAM,KAAK,GAAG,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC;IAC7C,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;IAC/D,MAAM,GAAG,GAAwB,EAAE,CAAC;IACpC,KAAK,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,WAAW,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,CAAC,EAAE,CAAC;QAC3E,MAAM,MAAM,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC;QACnC,MAAM,EAAE,GAAG,MAAM,IAAI,OAAO,MAAM,CAAC,SAAS,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC;QACpF,IAAI,CAAC,EAAE,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;YAAE,SAAS;QACvC,GAAG,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,eAAe,EAAE,EAAE,EAAE,cAAc,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC;IAC3H,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,gBAAgB,CAAC,MAA0B,EAAE,KAAK,GAAG,cAAc;IACjF,IAAI,QAAQ,GAAwB,EAAE,CAAC;IACvC,IAAI,CAAC;QACH,QAAQ,GAAG,MAAM,KAAK,OAAO,CAAC,CAAC,CAAC,qBAAqB,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,sBAAsB,CAAC,KAAK,CAAC,CAAC;IAC/F,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC;IACnD,CAAC;IAED,MAAM,UAAU,GAAG,IAAI,GAAG,EAA6B,CAAC;IACxD,KAAK,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;QACzB,MAAM,IAAI,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC;QAC/C,IAAI,CAAC,IAAI,IAAI,CAAC,CAAC,OAAO,GAAG,IAAI,CAAC,OAAO;YAAE,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,eAAe,EAAE,CAAC,CAAC,CAAC;IAC9E,CAAC;IAED,IAAI,QAAQ,GAAG,CAAC,CAAC;IACjB,KAAK,MAAM,CAAC,IAAI,UAAU,CAAC,MAAM,EAAE,EAAE,CAAC;QACpC,IAAI,CAAC;YACH,oBAAoB,CAAC;gBACnB,MAAM,EAAE,CAAC,CAAC,MAAM;gBAChB,eAAe,EAAE,CAAC,CAAC,eAAe;gBAClC,cAAc,EAAE,CAAC,CAAC,cAAc;gBAChC,UAAU,EAAE,CAAC,CAAC,UAAU;gBACxB,yEAAyE;gBACzE,8DAA8D;gBAC9D,UAAU,EAAE,IAAI,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,WAAW,EAAE;aAC9C,CAAC,CAAC;YACH,QAAQ,EAAE,CAAC;QACb,CAAC;QAAC,MAAM,CAAC,CAAC,4BAA4B,CAAC,CAAC;IAC1C,CAAC;IACD,OAAO,EAAE,OAAO,EAAE,QAAQ,CAAC,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC,GAAG,UAAU,CAAC,MAAM,EAAE,CAAC,EAAE,CAAC;AACpF,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,oBAAoB,CAAC,QAA6B,EAAE,UAAkB;IACpF,MAAM,IAAI,GAAG,mBAAmB,CAAC,UAAU,CAAC,CAAC;IAC7C,OAAO,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,UAAU,IAAI,mBAAmB,CAAC,CAAC,CAAC,UAAU,CAAC,KAAK,IAAI,CAAC,CAAC;AACxF,CAAC"}
@@ -1,5 +1,15 @@
1
1
  import type { ArchiveRow } from './schema.js';
2
2
  export declare function _resetExpandCache(): void;
3
+ /**
4
+ * Hard ceiling on what one expansion may return, in characters.
5
+ *
6
+ * Expansion used to be unbounded: it served the whole raw L0 line, and measured
7
+ * across a real archive that reached 139.6KB from a SINGLE call — roughly 35,000
8
+ * tokens, a third of a 128k context window, spent on one excerpt (council
9
+ * 06b7b55c). ~12k characters is about 3k tokens: enough for any real message,
10
+ * bounded enough that an AI can afford to ask.
11
+ */
12
+ export declare const MAX_EXPAND_CHARS = 12000;
3
13
  export type ExpandResult = {
4
14
  ok: boolean;
5
15
  reason?: string;
@@ -10,11 +20,32 @@ export type ExpandResult = {
10
20
  provenance?: string;
11
21
  fromSeq?: number;
12
22
  toSeq?: number;
23
+ /** True when the payload hit MAX_EXPAND_CHARS and was cut. */
24
+ truncated?: boolean;
25
+ /** 'text' = normalized readable content; 'raw' = exact L0 source bytes. */
26
+ form?: 'text' | 'raw';
13
27
  };
14
28
  /** Serve a byte range from an archive, masked. Bounds are validated first. */
15
29
  export declare function expandBytes(archive: ArchiveRow, offset: number, length: number): ExpandResult;
16
- /** Expand a single event to its exact source line (masked), with a turn/timestamp citation. */
17
- export declare function expandEvent(eventId: string): ExpandResult;
30
+ /**
31
+ * Expand one event.
32
+ *
33
+ * Returns the NORMALIZED, readable content by default. It used to return the raw
34
+ * L0 line, which meant an AI asking for one message received a JSON envelope —
35
+ * `{"parentUuid":"…","isSidechain":false,"type":"user","message":{…}}` — rather
36
+ * than the message. `events.text` already holds that content, normalized and
37
+ * masked at ingest, so serving it needs no new parsing and no per-source
38
+ * coupling in this module (council 06b7b55c).
39
+ *
40
+ * Rule 0 is intact: `raw: true` still serves the exact L0 bytes, and the archive
41
+ * on disk is untouched either way. Both forms are masked on serve and capped.
42
+ */
43
+ export declare function expandEvent(eventId: string, raw?: boolean): ExpandResult;
44
+ /**
45
+ * Expand a seq range as readable text — the conversation, not the file format.
46
+ * `raw` falls back to the exact contiguous L0 byte slice.
47
+ */
48
+ export declare function expandRangeText(archiveId: string, fromSeq: number, toSeq: number): ExpandResult;
18
49
  /** Expand a seq range to the exact contiguous L0 lines it covers (masked). */
19
50
  export declare function expandRange(archiveId: string, fromSeq: number, toSeq: number): ExpandResult;
20
51
  //# sourceMappingURL=expand.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"expand.d.ts","sourceRoot":"","sources":["../../src/transcripts/expand.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,UAAU,EAAY,MAAM,aAAa,CAAC;AAYxD,wBAAgB,iBAAiB,IAAI,IAAI,CAAmB;AAE5D,MAAM,MAAM,YAAY,GAAG;IACzB,EAAE,EAAE,OAAO,CAAC;IACZ,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAkBF,8EAA8E;AAC9E,wBAAgB,WAAW,CAAC,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,YAAY,CAa7F;AAED,+FAA+F;AAC/F,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,YAAY,CASzD;AAED,8EAA8E;AAC9E,wBAAgB,WAAW,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,YAAY,CAa3F"}
1
+ {"version":3,"file":"expand.d.ts","sourceRoot":"","sources":["../../src/transcripts/expand.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,UAAU,EAAY,MAAM,aAAa,CAAC;AAYxD,wBAAgB,iBAAiB,IAAI,IAAI,CAAmB;AAE5D;;;;;;;;GAQG;AACH,eAAO,MAAM,gBAAgB,QAAS,CAAC;AAcvC,MAAM,MAAM,YAAY,GAAG;IACzB,EAAE,EAAE,OAAO,CAAC;IACZ,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,8DAA8D;IAC9D,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,2EAA2E;IAC3E,IAAI,CAAC,EAAE,MAAM,GAAG,KAAK,CAAC;CACvB,CAAC;AAkBF,8EAA8E;AAC9E,wBAAgB,WAAW,CAAC,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,YAAY,CAc7F;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,UAAQ,GAAG,YAAY,CA4BtE;AAYD;;;GAGG;AACH,wBAAgB,eAAe,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,YAAY,CAoB/F;AAED,8EAA8E;AAC9E,wBAAgB,WAAW,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,YAAY,CAa3F"}
@@ -22,6 +22,28 @@ function loadArchive(path) {
22
22
  return buf;
23
23
  }
24
24
  export function _resetExpandCache() { _cache = null; }
25
+ /**
26
+ * Hard ceiling on what one expansion may return, in characters.
27
+ *
28
+ * Expansion used to be unbounded: it served the whole raw L0 line, and measured
29
+ * across a real archive that reached 139.6KB from a SINGLE call — roughly 35,000
30
+ * tokens, a third of a 128k context window, spent on one excerpt (council
31
+ * 06b7b55c). ~12k characters is about 3k tokens: enough for any real message,
32
+ * bounded enough that an AI can afford to ask.
33
+ */
34
+ export const MAX_EXPAND_CHARS = 12_000;
35
+ function clip(text, form = 'text') {
36
+ if (text.length <= MAX_EXPAND_CHARS)
37
+ return { text, truncated: false };
38
+ const advice = form === 'raw'
39
+ ? 'Narrow the range, or drop raw:true for the readable form, which is far smaller.'
40
+ : 'Narrow the range.';
41
+ return {
42
+ text: text.slice(0, MAX_EXPAND_CHARS)
43
+ + `\n\n[… truncated: ${text.length - MAX_EXPAND_CHARS} more characters. ${advice}]`,
44
+ truncated: true,
45
+ };
46
+ }
25
47
  function getArchiveById(id) {
26
48
  const db = getTranscriptsDb();
27
49
  return db.prepare(`SELECT * FROM archives WHERE id = ?`).get(id) ?? null;
@@ -52,14 +74,27 @@ export function expandBytes(archive, offset, length) {
52
74
  return { ok: false, reason: 'out_of_bounds' };
53
75
  }
54
76
  const m = mask(buf.toString('utf8', offset, offset + length));
77
+ const c = clip(m.text, 'raw');
55
78
  return {
56
- ok: true, text: m.text, secretsRedacted: m.count,
79
+ ok: true, text: c.text, secretsRedacted: m.count, truncated: c.truncated, form: 'raw',
57
80
  source: archive.source, sourceSessionId: archive.source_session_id,
58
81
  provenance: cite(archive, { offset, length }),
59
82
  };
60
83
  }
61
- /** Expand a single event to its exact source line (masked), with a turn/timestamp citation. */
62
- export function expandEvent(eventId) {
84
+ /**
85
+ * Expand one event.
86
+ *
87
+ * Returns the NORMALIZED, readable content by default. It used to return the raw
88
+ * L0 line, which meant an AI asking for one message received a JSON envelope —
89
+ * `{"parentUuid":"…","isSidechain":false,"type":"user","message":{…}}` — rather
90
+ * than the message. `events.text` already holds that content, normalized and
91
+ * masked at ingest, so serving it needs no new parsing and no per-source
92
+ * coupling in this module (council 06b7b55c).
93
+ *
94
+ * Rule 0 is intact: `raw: true` still serves the exact L0 bytes, and the archive
95
+ * on disk is untouched either way. Both forms are masked on serve and capped.
96
+ */
97
+ export function expandEvent(eventId, raw = false) {
63
98
  const db = getTranscriptsDb();
64
99
  const ev = db.prepare(`SELECT * FROM events WHERE id = ?`).get(eventId) ?? null;
65
100
  if (!ev)
@@ -67,13 +102,64 @@ export function expandEvent(eventId) {
67
102
  const archive = getArchiveById(ev.archive_id);
68
103
  if (!archive)
69
104
  return { ok: false, reason: 'archive_not_found' };
70
- const r = expandBytes(archive, ev.raw_offset, ev.raw_length);
71
- if (r.ok) {
72
- r.provenance = cite(archive, { seq: ev.seq, ts: ev.ts_utc });
73
- r.fromSeq = ev.seq;
74
- r.toSeq = ev.seq;
105
+ if (raw) {
106
+ const r = expandBytes(archive, ev.raw_offset, ev.raw_length);
107
+ if (r.ok) {
108
+ r.provenance = cite(archive, { seq: ev.seq, ts: ev.ts_utc });
109
+ r.fromSeq = ev.seq;
110
+ r.toSeq = ev.seq;
111
+ }
112
+ return r;
75
113
  }
76
- return r;
114
+ // Masked again on serve even though ingest already masked it: the mask-on-serve
115
+ // guarantee must not depend on what a past parser version wrote.
116
+ const m = mask(labelled(ev));
117
+ const c = clip(m.text);
118
+ return {
119
+ // Ingest masked this text already, so the serve-time pass usually finds
120
+ // nothing new. Report what was redacted FROM THIS CONTENT (counted at
121
+ // ingest) as well, or the number would read 0 on correctly-masked content
122
+ // and look like nothing was ever protected.
123
+ ok: true, text: c.text, secretsRedacted: Math.max(ev.secret_count, m.count),
124
+ truncated: c.truncated, form: 'text',
125
+ source: archive.source, sourceSessionId: archive.source_session_id,
126
+ provenance: cite(archive, { seq: ev.seq, ts: ev.ts_utc }),
127
+ fromSeq: ev.seq, toSeq: ev.seq,
128
+ };
129
+ }
130
+ /** One event as readable text, prefixed with who said it (and which tool). */
131
+ function labelled(ev) {
132
+ const who = ev.kind === 'user_message' ? 'user'
133
+ : ev.kind === 'assistant_message' ? 'assistant'
134
+ : ev.kind === 'tool_call' ? `tool call${ev.tool_name ? ` (${ev.tool_name})` : ''}`
135
+ : ev.kind === 'tool_result' ? `tool result${ev.tool_name ? ` (${ev.tool_name})` : ''}`
136
+ : ev.kind;
137
+ return `[turn ${ev.seq} · ${who}] ${ev.text ?? ''}`.trimEnd();
138
+ }
139
+ /**
140
+ * Expand a seq range as readable text — the conversation, not the file format.
141
+ * `raw` falls back to the exact contiguous L0 byte slice.
142
+ */
143
+ export function expandRangeText(archiveId, fromSeq, toSeq) {
144
+ const db = getTranscriptsDb();
145
+ const archive = getArchiveById(archiveId);
146
+ if (!archive)
147
+ return { ok: false, reason: 'archive_not_found' };
148
+ const lo = Math.min(fromSeq, toSeq), hi = Math.max(fromSeq, toSeq);
149
+ const rows = db.prepare(`SELECT * FROM events WHERE archive_id = ? AND seq BETWEEN ? AND ? AND text IS NOT NULL AND text != ''
150
+ ORDER BY seq`).all(archiveId, lo, hi);
151
+ if (rows.length === 0)
152
+ return { ok: false, reason: 'no_events' };
153
+ const m = mask(rows.map(labelled).join('\n\n'));
154
+ const c = clip(m.text);
155
+ const storedSecrets = rows.reduce((a, r) => a + (r.secret_count ?? 0), 0);
156
+ return {
157
+ ok: true, text: c.text, secretsRedacted: Math.max(storedSecrets, m.count),
158
+ truncated: c.truncated, form: 'text',
159
+ source: archive.source, sourceSessionId: archive.source_session_id,
160
+ provenance: cite(archive, { seq: rows[0].seq, toSeq: rows[rows.length - 1].seq, ts: rows[0].ts_utc }),
161
+ fromSeq: rows[0].seq, toSeq: rows[rows.length - 1].seq,
162
+ };
77
163
  }
78
164
  /** Expand a seq range to the exact contiguous L0 lines it covers (masked). */
79
165
  export function expandRange(archiveId, fromSeq, toSeq) {
@@ -1 +1 @@
1
- {"version":3,"file":"expand.js","sourceRoot":"","sources":["../../src/transcripts/expand.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"expand.js","sourceRoot":"","sources":["../../src/transcripts/expand.ts"],"names":[],"mappings":"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"}
@@ -11,7 +11,7 @@ import { gunzipSync } from 'node:zlib';
11
11
  import { randomUUID } from 'node:crypto';
12
12
  import { getTranscriptsDb } from './store.js';
13
13
  import { resetCaches } from './cache.js';
14
- import { parseClaudeTranscript } from './adapters/claude.js';
14
+ import { parseTranscript } from './adapters/index.js';
15
15
  import { tokenize } from './tokenize.js';
16
16
  import { SEARCHABLE_KINDS } from './schema.js';
17
17
  const SEARCHABLE = new Set(SEARCHABLE_KINDS);
@@ -38,7 +38,7 @@ export function ingestArchive(archiveId) {
38
38
  if (!existsSync(row.archive_path))
39
39
  return { status: 'archive_missing' };
40
40
  const buf = gunzipSync(readFileSync(row.archive_path));
41
- const { events, sessionIds, secretsRedacted } = parseClaudeTranscript(buf);
41
+ const { events, sessionIds, secretsRedacted } = parseTranscript(row.source, buf);
42
42
  if (sessionIds.size > 0 && !sessionIds.has(row.source_session_id)) {
43
43
  return { status: 'session_mismatch', reason: 'archive session id not present in transcript' };
44
44
  }
@@ -1 +1 @@
1
- {"version":3,"file":"ingest.js","sourceRoot":"","sources":["../../src/transcripts/ingest.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ingest.js","sourceRoot":"","sources":["../../src/transcripts/ingest.ts"],"names":[],"mappings":"AAAA,kFAAkF;AAClF,EAAE;AACF,2EAA2E;AAC3E,gFAAgF;AAChF,8EAA8E;AAC9E,gFAAgF;AAChF,kFAAkF;AAClF,mDAAmD;AAEnD,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AACvC,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACzC,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,gBAAgB,EAAkC,MAAM,aAAa,CAAC;AAE/E,MAAM,UAAU,GAAG,IAAI,GAAG,CAAS,gBAAgB,CAAC,CAAC;AAErD,iFAAiF;AACjF,8EAA8E;AAC9E,wEAAwE;AACxE,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,CAAC;AAYhC,SAAS,cAAc,CAAC,SAAiB;IACvC,MAAM,EAAE,GAAG,gBAAgB,EAAE,CAAC;IAC9B,OAAQ,EAAE,CAAC,OAAO,CAAC,qCAAqC,CAAC,CAAC,GAAG,CAAC,SAAS,CAA4B,IAAI,IAAI,CAAC;AAC9G,CAAC;AAED,SAAS,aAAa,CAAC,GAAe;IACpC,OAAO,GAAG,CAAC,cAAc,KAAK,cAAc,CAAC;AAC/C,CAAC;AAED,oEAAoE;AACpE,MAAM,UAAU,aAAa,CAAC,SAAiB;IAC7C,IAAI,CAAC;QACH,MAAM,EAAE,GAAG,gBAAgB,EAAE,CAAC;QAC9B,MAAM,GAAG,GAAG,cAAc,CAAC,SAAS,CAAC,CAAC;QACtC,IAAI,CAAC,GAAG;YAAE,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC;QACzC,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC;YAAE,OAAO,EAAE,MAAM,EAAE,iBAAiB,EAAE,MAAM,EAAE,GAAG,CAAC,mBAAmB,EAAE,CAAC;QAC/F,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,YAAY,CAAC;YAAE,OAAO,EAAE,MAAM,EAAE,iBAAiB,EAAE,CAAC;QAExE,MAAM,GAAG,GAAG,UAAU,CAAC,YAAY,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC,CAAC;QACvD,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,eAAe,EAAE,GAAG,eAAe,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;QAEjF,IAAI,UAAU,CAAC,IAAI,GAAG,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,GAAG,CAAC,iBAAiB,CAAC,EAAE,CAAC;YAClE,OAAO,EAAE,MAAM,EAAE,kBAAkB,EAAE,MAAM,EAAE,8CAA8C,EAAE,CAAC;QAChG,CAAC;QAED,MAAM,GAAG,GAAG,EAAE,CAAC,OAAO,CACpB;;;wEAGkE,CACnE,CAAC;QACF,MAAM,MAAM,GAAG,EAAE,CAAC,OAAO,CACvB;iDAC2C,CAC5C,CAAC;QACF,MAAM,OAAO,GAAG,EAAE,CAAC,OAAO,CACxB;gEAC0D,CAC3D,CAAC;QACF,MAAM,UAAU,GAAG,EAAE,CAAC,OAAO,CAC3B,oEAAoE,CACrE,CAAC;QACF,uEAAuE;QACvE,iDAAiD;QACjD,MAAM,OAAO,GAAG,IAAI,GAAG,EAAkB,CAAC;QAC1C,MAAM,MAAM,GAAG,CAAC,IAAY,EAAU,EAAE;YACtC,IAAI,EAAE,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YAC3B,IAAI,EAAE,KAAK,SAAS,EAAE,CAAC;gBACrB,EAAE,GAAG,MAAM,CAAE,OAAO,CAAC,GAAG,CAAC,IAAI,CAA6B,CAAC,EAAE,CAAC,CAAC;gBAC/D,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;YACxB,CAAC;YACD,OAAO,EAAE,CAAC;QACZ,CAAC,CAAC;QACF,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACjB,IAAI,CAAC;YACH,EAAE,CAAC,OAAO,CAAC,yCAAyC,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;YACrE,EAAE,CAAC,OAAO,CACR,+FAA+F,CAChG,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;YACjB,uEAAuE;YACvE,mEAAmE;YACnE,EAAE,CAAC,OAAO,CACR,8FAA8F,CAC/F,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;YACjB,EAAE,CAAC,OAAO,CAAC,8CAA8C,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;YAC1E,KAAK,MAAM,CAAC,IAAI,MAAM,EAAE,CAAC;gBACvB,MAAM,OAAO,GAAG,UAAU,EAAE,CAAC;gBAC7B,GAAG,CAAC,GAAG,CACL,OAAO,EAAE,SAAS,EAAE,GAAG,CAAC,iBAAiB,EAAE,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC,UAAU,EAAE,CAAC,CAAC,IAAI,EACnF,CAAC,CAAC,UAAU,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC,UAAU,EAAE,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EACzG,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC,SAAS,CAC9C,CAAC;gBACF,mEAAmE;gBACnE,IAAI,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,CAAC;oBACtD,MAAM,MAAM,GAAG,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;oBAChC,MAAM,EAAE,GAAG,IAAI,GAAG,EAAkB,CAAC;oBACrC,KAAK,MAAM,CAAC,IAAI,MAAM;wBAAE,EAAE,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;oBACxD,MAAM,KAAK,GAAG,MAAM,CAAE,MAAM,CAAC,GAAG,CAC9B,OAAO,EAAE,SAAS,EAAE,GAAG,CAAC,iBAAiB,EAAE,GAAG,CAAC,WAAW,EAAE,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,CAC7D,CAAC,EAAE,CAAC,CAAC;oBAClC,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE;wBAAE,UAAU,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;gBAC7E,CAAC;YACH,CAAC;YACD,sEAAsE;YACtE,sEAAsE;YACtE,EAAE,CAAC,OAAO,CACR;uBACe,CAChB,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,EAAE,cAAc,EAAE,SAAS,CAAC,CAAC;YAChD,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YAClB,WAAW,EAAE,CAAC;QAChB,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;YACpB,MAAM,CAAC,CAAC;QACV,CAAC;QAED,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,EAAE,CAAC;IACvE,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC;IACjF,CAAC;AACH,CAAC;AAED,4FAA4F;AAC5F,MAAM,UAAU,aAAa,CAAC,SAAiB;IAC7C,OAAO,aAAa,CAAC,SAAS,CAAC,CAAC;AAClC,CAAC;AAED,0DAA0D;AAC1D,MAAM,UAAU,aAAa,CAAC,eAAuB,EAAE,MAAM,GAAG,QAAQ;IACtE,MAAM,EAAE,GAAG,gBAAgB,EAAE,CAAC;IAC9B,MAAM,GAAG,GAAI,EAAE,CAAC,OAAO,CACrB,oEAAoE,CACrE,CAAC,GAAG,CAAC,MAAM,EAAE,eAAe,CAAgC,IAAI,IAAI,CAAC;IACtE,IAAI,CAAC,GAAG;QAAE,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC;IACzC,OAAO,aAAa,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;AAC/B,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,SAAiB;IACzC,MAAM,EAAE,GAAG,gBAAgB,EAAE,CAAC;IAC9B,OAAO,EAAE,CAAC,OAAO,CAAC,wDAAwD,CAAC,CAAC,GAAG,CAAC,SAAS,CAAe,CAAC;AAC3G,CAAC"}
@@ -4,6 +4,14 @@ export type RecordMappingInput = {
4
4
  sourceSessionId: string;
5
5
  transcriptPath: string;
6
6
  projectDir?: string | null;
7
+ /**
8
+ * When this session was last active, ISO-8601. Defaults to now, which is right
9
+ * for the statusline (it only ever reports a session that is live *right now*).
10
+ * Discovery must pass the transcript's mtime instead: it reconstructs several
11
+ * sessions at once, and stamping them all "now" would flatten the recency that
12
+ * `latestMappingForProject` uses to pick the active one.
13
+ */
14
+ lastSeenAt?: string;
7
15
  };
8
16
  /**
9
17
  * UPSERT a session's transcript path. Idempotent on (source, source_session_id):
@@ -1 +1 @@
1
- {"version":3,"file":"mapping.d.ts","sourceRoot":"","sources":["../../src/transcripts/mapping.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAEjD,MAAM,MAAM,kBAAkB,GAAG;IAC/B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,eAAe,EAAE,MAAM,CAAC;IACxB,cAAc,EAAE,MAAM,CAAC;IACvB,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B,CAAC;AAEF;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,CAAC,EAAE,kBAAkB,GAAG,IAAI,CAYhE;AAED,mDAAmD;AACnD,wBAAgB,iBAAiB,CAAC,eAAe,EAAE,MAAM,EAAE,MAAM,SAAW,GAAG,aAAa,GAAG,IAAI,CAKlG;AAED;;;;GAIG;AACH,wBAAgB,uBAAuB,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,SAAW,GAAG,aAAa,GAAG,IAAI,CAMnG"}
1
+ {"version":3,"file":"mapping.d.ts","sourceRoot":"","sources":["../../src/transcripts/mapping.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAEjD,MAAM,MAAM,kBAAkB,GAAG;IAC/B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,eAAe,EAAE,MAAM,CAAC;IACxB,cAAc,EAAE,MAAM,CAAC;IACvB,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B;;;;;;OAMG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,CAAC,EAAE,kBAAkB,GAAG,IAAI,CAYhE;AAED,mDAAmD;AACnD,wBAAgB,iBAAiB,CAAC,eAAe,EAAE,MAAM,EAAE,MAAM,SAAW,GAAG,aAAa,GAAG,IAAI,CAKlG;AAED;;;;GAIG;AACH,wBAAgB,uBAAuB,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,SAAW,GAAG,aAAa,GAAG,IAAI,CAMnG"}
@@ -15,7 +15,7 @@ import { normalizeProjectDir } from '../memory/local.js';
15
15
  */
16
16
  export function recordSessionMapping(m) {
17
17
  const db = getTranscriptsDb();
18
- const now = new Date().toISOString();
18
+ const now = m.lastSeenAt ?? new Date().toISOString();
19
19
  const proj = m.projectDir ? normalizeProjectDir(m.projectDir) : null;
20
20
  db.prepare(`INSERT INTO session_map (source, source_session_id, transcript_path, project_dir, last_seen_at)
21
21
  VALUES (?, ?, ?, ?, ?)
@@ -1 +1 @@
1
- {"version":3,"file":"mapping.js","sourceRoot":"","sources":["../../src/transcripts/mapping.ts"],"names":[],"mappings":"AAAA,2EAA2E;AAC3E,EAAE;AACF,0EAA0E;AAC1E,yEAAyE;AACzE,0EAA0E;AAC1E,sEAAsE;AACtE,6CAA6C;AAE7C,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAC9C,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAUzD;;;;;GAKG;AACH,MAAM,UAAU,oBAAoB,CAAC,CAAqB;IACxD,MAAM,EAAE,GAAG,gBAAgB,EAAE,CAAC;IAC9B,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IACrC,MAAM,IAAI,GAAG,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IACrE,EAAE,CAAC,OAAO,CACR;;;;;+CAK2C,CAC5C,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,IAAI,QAAQ,EAAE,CAAC,CAAC,eAAe,EAAE,CAAC,CAAC,cAAc,EAAE,IAAI,EAAE,GAAG,CAAC,CAAC;AAC9E,CAAC;AAED,mDAAmD;AACnD,MAAM,UAAU,iBAAiB,CAAC,eAAuB,EAAE,MAAM,GAAG,QAAQ;IAC1E,MAAM,EAAE,GAAG,gBAAgB,EAAE,CAAC;IAC9B,OAAQ,EAAE,CAAC,OAAO,CAChB,sEAAsE,CACvE,CAAC,GAAG,CAAC,MAAM,EAAE,eAAe,CAA+B,IAAI,IAAI,CAAC;AACvE,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,uBAAuB,CAAC,UAAkB,EAAE,MAAM,GAAG,QAAQ;IAC3E,MAAM,EAAE,GAAG,gBAAgB,EAAE,CAAC;IAC9B,MAAM,IAAI,GAAG,mBAAmB,CAAC,UAAU,CAAC,CAAC;IAC7C,OAAQ,EAAE,CAAC,OAAO,CAChB,mGAAmG,CACpG,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,CAA+B,IAAI,IAAI,CAAC;AAC5D,CAAC"}
1
+ {"version":3,"file":"mapping.js","sourceRoot":"","sources":["../../src/transcripts/mapping.ts"],"names":[],"mappings":"AAAA,2EAA2E;AAC3E,EAAE;AACF,0EAA0E;AAC1E,yEAAyE;AACzE,0EAA0E;AAC1E,sEAAsE;AACtE,6CAA6C;AAE7C,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAC9C,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAkBzD;;;;;GAKG;AACH,MAAM,UAAU,oBAAoB,CAAC,CAAqB;IACxD,MAAM,EAAE,GAAG,gBAAgB,EAAE,CAAC;IAC9B,MAAM,GAAG,GAAG,CAAC,CAAC,UAAU,IAAI,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IACrD,MAAM,IAAI,GAAG,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IACrE,EAAE,CAAC,OAAO,CACR;;;;;+CAK2C,CAC5C,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,IAAI,QAAQ,EAAE,CAAC,CAAC,eAAe,EAAE,CAAC,CAAC,cAAc,EAAE,IAAI,EAAE,GAAG,CAAC,CAAC;AAC9E,CAAC;AAED,mDAAmD;AACnD,MAAM,UAAU,iBAAiB,CAAC,eAAuB,EAAE,MAAM,GAAG,QAAQ;IAC1E,MAAM,EAAE,GAAG,gBAAgB,EAAE,CAAC;IAC9B,OAAQ,EAAE,CAAC,OAAO,CAChB,sEAAsE,CACvE,CAAC,GAAG,CAAC,MAAM,EAAE,eAAe,CAA+B,IAAI,IAAI,CAAC;AACvE,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,uBAAuB,CAAC,UAAkB,EAAE,MAAM,GAAG,QAAQ;IAC3E,MAAM,EAAE,GAAG,gBAAgB,EAAE,CAAC;IAC9B,MAAM,IAAI,GAAG,mBAAmB,CAAC,UAAU,CAAC,CAAC;IAC7C,OAAQ,EAAE,CAAC,OAAO,CAChB,mGAAmG,CACpG,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,CAA+B,IAAI,IAAI,CAAC;AAC5D,CAAC"}