context-lens 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (119) hide show
  1. package/README.md +120 -25
  2. package/dist/cli-utils.d.ts +2 -1
  3. package/dist/cli-utils.d.ts.map +1 -1
  4. package/dist/cli-utils.js +40 -13
  5. package/dist/cli-utils.js.map +1 -1
  6. package/dist/cli.js +184 -68
  7. package/dist/cli.js.map +1 -1
  8. package/dist/core/conversation.d.ts +63 -0
  9. package/dist/core/conversation.d.ts.map +1 -0
  10. package/dist/core/conversation.js +305 -0
  11. package/dist/core/conversation.js.map +1 -0
  12. package/dist/core/health.d.ts +7 -0
  13. package/dist/core/health.d.ts.map +1 -0
  14. package/dist/core/health.js +311 -0
  15. package/dist/core/health.js.map +1 -0
  16. package/dist/core/models.d.ts +36 -0
  17. package/dist/core/models.d.ts.map +1 -0
  18. package/dist/core/models.js +111 -0
  19. package/dist/core/models.js.map +1 -0
  20. package/dist/core/parse.d.ts +17 -0
  21. package/dist/core/parse.d.ts.map +1 -0
  22. package/dist/core/parse.js +349 -0
  23. package/dist/core/parse.js.map +1 -0
  24. package/dist/core/routing.d.ts +47 -0
  25. package/dist/core/routing.d.ts.map +1 -0
  26. package/dist/core/routing.js +132 -0
  27. package/dist/core/routing.js.map +1 -0
  28. package/dist/core/security.d.ts +8 -0
  29. package/dist/core/security.d.ts.map +1 -0
  30. package/dist/core/security.js +222 -0
  31. package/dist/core/security.js.map +1 -0
  32. package/dist/core/source.d.ts +22 -0
  33. package/dist/core/source.d.ts.map +1 -0
  34. package/dist/core/source.js +56 -0
  35. package/dist/core/source.js.map +1 -0
  36. package/dist/core/tokens.d.ts +29 -0
  37. package/dist/core/tokens.d.ts.map +1 -0
  38. package/dist/core/tokens.js +163 -0
  39. package/dist/core/tokens.js.map +1 -0
  40. package/dist/core.d.ts +14 -22
  41. package/dist/core.d.ts.map +1 -1
  42. package/dist/core.js +14 -471
  43. package/dist/core.js.map +1 -1
  44. package/dist/http/headers.d.ts +25 -0
  45. package/dist/http/headers.d.ts.map +1 -0
  46. package/dist/http/headers.js +54 -0
  47. package/dist/http/headers.js.map +1 -0
  48. package/dist/lhar/composition.d.ts +12 -0
  49. package/dist/lhar/composition.d.ts.map +1 -0
  50. package/dist/lhar/composition.js +258 -0
  51. package/dist/lhar/composition.js.map +1 -0
  52. package/dist/lhar/export.d.ts +5 -0
  53. package/dist/lhar/export.d.ts.map +1 -0
  54. package/dist/lhar/export.js +59 -0
  55. package/dist/lhar/export.js.map +1 -0
  56. package/dist/lhar/record.d.ts +6 -0
  57. package/dist/lhar/record.d.ts.map +1 -0
  58. package/dist/lhar/record.js +216 -0
  59. package/dist/lhar/record.js.map +1 -0
  60. package/dist/lhar/response.d.ts +11 -0
  61. package/dist/lhar/response.d.ts.map +1 -0
  62. package/dist/lhar/response.js +132 -0
  63. package/dist/lhar/response.js.map +1 -0
  64. package/dist/lhar-types.generated.d.ts +24 -3
  65. package/dist/lhar-types.generated.d.ts.map +1 -1
  66. package/dist/lhar.d.ts +12 -19
  67. package/dist/lhar.d.ts.map +1 -1
  68. package/dist/lhar.js +16 -473
  69. package/dist/lhar.js.map +1 -1
  70. package/dist/server/api.d.ts +8 -0
  71. package/dist/server/api.d.ts.map +1 -0
  72. package/dist/server/api.js +292 -0
  73. package/dist/server/api.js.map +1 -0
  74. package/dist/server/config.d.ts +13 -0
  75. package/dist/server/config.d.ts.map +1 -0
  76. package/dist/server/config.js +36 -0
  77. package/dist/server/config.js.map +1 -0
  78. package/dist/server/projection.d.ts +9 -0
  79. package/dist/server/projection.d.ts.map +1 -0
  80. package/dist/server/projection.js +47 -0
  81. package/dist/server/projection.js.map +1 -0
  82. package/dist/server/proxy.d.ts +13 -0
  83. package/dist/server/proxy.d.ts.map +1 -0
  84. package/dist/server/proxy.js +218 -0
  85. package/dist/server/proxy.js.map +1 -0
  86. package/dist/server/static.d.ts +9 -0
  87. package/dist/server/static.d.ts.map +1 -0
  88. package/dist/server/static.js +78 -0
  89. package/dist/server/static.js.map +1 -0
  90. package/dist/server/store.d.ts +81 -0
  91. package/dist/server/store.d.ts.map +1 -0
  92. package/dist/server/store.js +632 -0
  93. package/dist/server/store.js.map +1 -0
  94. package/dist/server/webui.d.ts +5 -0
  95. package/dist/server/webui.d.ts.map +1 -0
  96. package/dist/server/webui.js +42 -0
  97. package/dist/server/webui.js.map +1 -0
  98. package/dist/server-utils.d.ts +2 -2
  99. package/dist/server-utils.d.ts.map +1 -1
  100. package/dist/server-utils.js +12 -21
  101. package/dist/server-utils.js.map +1 -1
  102. package/dist/server.js +31 -697
  103. package/dist/server.js.map +1 -1
  104. package/dist/types.d.ts +94 -10
  105. package/dist/types.d.ts.map +1 -1
  106. package/dist/version.generated.d.ts +2 -0
  107. package/dist/version.generated.d.ts.map +1 -0
  108. package/dist/version.generated.js +2 -0
  109. package/dist/version.generated.js.map +1 -0
  110. package/findings-screenshot.png +0 -0
  111. package/messages-screenshot.png +0 -0
  112. package/package.json +23 -10
  113. package/schema/lhar.schema.json +58 -4
  114. package/screenshot-overview.png +0 -0
  115. package/sessions-screenshot.png +0 -0
  116. package/timeline-screenshot.png +0 -0
  117. package/diff.png +0 -0
  118. package/overview-sidebar.png +0 -0
  119. package/public/index.html +0 -2804
@@ -0,0 +1,632 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+ import { computeAgentKey, computeFingerprint, computeHealthScore, detectSource, estimateCost, estimateTokens, extractConversationLabel, extractSessionId, extractToolsUsed, extractWorkingDirectory, getContextLimit, rescaleContextTokens, scanSecurity, } from "../core.js";
4
+ import { analyzeComposition, buildLharRecord, buildSessionLine, normalizeComposition, parseResponseUsage, } from "../lhar.js";
5
+ import { safeFilenamePart } from "../server-utils.js";
6
+ import { projectEntry } from "./projection.js";
7
+ export class Store {
8
+ dataDir;
9
+ stateFile;
10
+ detailDir;
11
+ maxSessions;
12
+ maxCompactMessages;
13
+ privacy;
14
+ capturedRequests = [];
15
+ conversations = new Map(); // fingerprint -> conversation
16
+ responseIdToConvo = new Map(); // response_id -> conversationId
17
+ diskSessionsWritten = new Set();
18
+ dataRevision = 0;
19
+ nextEntryId = 1;
20
+ // SSE change listeners
21
+ changeListeners = new Set();
22
+ constructor(opts) {
23
+ this.dataDir = opts.dataDir;
24
+ this.stateFile = opts.stateFile;
25
+ this.detailDir = path.join(opts.dataDir, "details");
26
+ this.maxSessions = opts.maxSessions;
27
+ this.maxCompactMessages = opts.maxCompactMessages;
28
+ this.privacy = opts.privacy ?? "standard";
29
+ try {
30
+ fs.mkdirSync(this.dataDir, { recursive: true });
31
+ }
32
+ catch {
33
+ /* Directory may already exist */
34
+ }
35
+ try {
36
+ fs.mkdirSync(this.detailDir, { recursive: true });
37
+ }
38
+ catch {
39
+ /* Directory may already exist */
40
+ }
41
+ }
42
+ getRevision() {
43
+ return this.dataRevision;
44
+ }
45
+ getPrivacy() {
46
+ return this.privacy;
47
+ }
48
+ // --- SSE event emitter ---
49
+ on(_event, listener) {
50
+ this.changeListeners.add(listener);
51
+ }
52
+ off(_event, listener) {
53
+ this.changeListeners.delete(listener);
54
+ }
55
+ emitChange(type, conversationId) {
56
+ const event = {
57
+ type,
58
+ revision: this.dataRevision,
59
+ conversationId,
60
+ };
61
+ for (const listener of this.changeListeners) {
62
+ try {
63
+ listener(event);
64
+ }
65
+ catch {
66
+ // Don't let a broken SSE connection crash the store
67
+ }
68
+ }
69
+ }
70
+ getCapturedRequests() {
71
+ return this.capturedRequests;
72
+ }
73
+ getConversations() {
74
+ return this.conversations;
75
+ }
76
+ loadState() {
77
+ let content;
78
+ try {
79
+ content = fs.readFileSync(this.stateFile, "utf8");
80
+ }
81
+ catch {
82
+ return; // No state file, fresh start
83
+ }
84
+ const lines = content.split("\n").filter((l) => l.length > 0);
85
+ let loadedEntries = 0;
86
+ let maxId = 0;
87
+ for (const line of lines) {
88
+ try {
89
+ const record = JSON.parse(line);
90
+ if (record.type === "conversation") {
91
+ const c = record.data;
92
+ this.conversations.set(c.id, c);
93
+ this.diskSessionsWritten.add(c.id);
94
+ }
95
+ else if (record.type === "entry") {
96
+ const projected = record.data;
97
+ const entry = {
98
+ ...projected,
99
+ response: projected.response || { raw: true },
100
+ requestHeaders: {},
101
+ responseHeaders: {},
102
+ rawBody: undefined,
103
+ healthScore: projected.healthScore ?? null,
104
+ securityAlerts: projected.securityAlerts || [],
105
+ };
106
+ this.capturedRequests.push(entry);
107
+ if (entry.id > maxId)
108
+ maxId = entry.id;
109
+ loadedEntries++;
110
+ }
111
+ }
112
+ catch (err) {
113
+ console.error("State parse error:", err instanceof Error ? err.message : String(err));
114
+ }
115
+ }
116
+ if (loadedEntries > 0) {
117
+ this.nextEntryId = maxId + 1;
118
+ this.dataRevision = 1;
119
+ // Loaded entries are already compact (projectEntry strips heavy data before saving).
120
+ // Do NOT call compactEntry here. It would destroy the preserved response usage data.
121
+ // TODO: Consider introducing a formal versioned migration system (schema version
122
+ // tracking, ordered migration list, "already applied" checks) if the number of
123
+ // ad hoc migrations here keeps growing. For now each migration is idempotent and
124
+ // detects whether it needs to run by inspecting the data.
125
+ //
126
+ // Order matters: image migration fixes inflated per-message tokens from base64 data
127
+ // BEFORE the usage backfill rescales everything proportionally.
128
+ const migrated = this.migrateImageTokenCounts();
129
+ this.backfillTotalTokensFromUsage();
130
+ this.backfillHealthScores();
131
+ if (migrated > 0) {
132
+ this.saveState();
133
+ }
134
+ console.log(`Restored ${loadedEntries} entries from ${this.conversations.size} conversations`);
135
+ }
136
+ }
137
+ // Store captured request
138
+ storeRequest(contextInfo, responseData, source, rawBody, meta, requestHeaders) {
139
+ const resolvedSource = detectSource(contextInfo, source, requestHeaders);
140
+ const fingerprint = computeFingerprint(contextInfo, rawBody ?? null, this.responseIdToConvo);
141
+ const rawSessionId = extractSessionId(rawBody ?? null);
142
+ // Register or look up conversation
143
+ let conversationId = null;
144
+ if (fingerprint) {
145
+ if (!this.conversations.has(fingerprint)) {
146
+ this.conversations.set(fingerprint, {
147
+ id: fingerprint,
148
+ label: extractConversationLabel(contextInfo),
149
+ source: resolvedSource || "unknown",
150
+ workingDirectory: extractWorkingDirectory(contextInfo, rawBody ?? null),
151
+ firstSeen: new Date().toISOString(),
152
+ sessionId: rawSessionId,
153
+ });
154
+ }
155
+ else {
156
+ const convo = this.conversations.get(fingerprint);
157
+ // Backfill source if first request couldn't detect it
158
+ if (convo.source === "unknown" &&
159
+ resolvedSource &&
160
+ resolvedSource !== "unknown") {
161
+ convo.source = resolvedSource;
162
+ }
163
+ // Backfill working directory if first request didn't have it
164
+ if (!convo.workingDirectory) {
165
+ const wd = extractWorkingDirectory(contextInfo, rawBody ?? null);
166
+ if (wd)
167
+ convo.workingDirectory = wd;
168
+ }
169
+ }
170
+ conversationId = fingerprint;
171
+ }
172
+ // Agent key: distinguishes agents within a session (main vs subagents)
173
+ const agentKey = computeAgentKey(contextInfo);
174
+ const agentLabel = extractConversationLabel(contextInfo);
175
+ // Compute composition and cost
176
+ const composition = analyzeComposition(contextInfo, rawBody);
177
+ const usage = parseResponseUsage(responseData);
178
+ // Validate estimation accuracy before overriding with actuals
179
+ const actualInputTokens = usage.inputTokens + usage.cacheReadTokens + usage.cacheWriteTokens;
180
+ if (actualInputTokens > 0) {
181
+ const estimated = contextInfo.totalTokens;
182
+ const actual = actualInputTokens;
183
+ const diff = Math.abs(actual - estimated);
184
+ const pct = estimated > 0 ? (diff / estimated) * 100 : 0;
185
+ // Log significant estimation errors (>20% off or >10K tokens off)
186
+ if (pct > 20 || diff > 10_000) {
187
+ console.warn(`Token estimation off by ${pct.toFixed(1)}% (estimated: ${estimated.toLocaleString()}, actual: ${actual.toLocaleString()}) for ${contextInfo.model}`);
188
+ }
189
+ // Rescale all sub-totals and per-message tokens to match the
190
+ // authoritative API usage. This preserves relative proportions while
191
+ // ensuring totalTokens === systemTokens + toolsTokens + messagesTokens.
192
+ rescaleContextTokens(contextInfo, actualInputTokens);
193
+ }
194
+ // Normalize composition so sum(composition[].tokens) === totalTokens.
195
+ // This must happen after the totalTokens override so both systems agree.
196
+ normalizeComposition(composition, contextInfo.totalTokens);
197
+ // Calculate cost with proper cache token pricing
198
+ const inputTok = usage.inputTokens || contextInfo.totalTokens;
199
+ const outputTok = usage.outputTokens;
200
+ const costUsd = estimateCost(contextInfo.model, inputTok, outputTok, usage.cacheReadTokens, usage.cacheWriteTokens);
201
+ const entry = {
202
+ id: this.nextEntryId++,
203
+ timestamp: new Date().toISOString(),
204
+ contextInfo,
205
+ response: responseData,
206
+ contextLimit: getContextLimit(contextInfo.model),
207
+ source: resolvedSource || "unknown",
208
+ conversationId,
209
+ agentKey,
210
+ agentLabel,
211
+ httpStatus: meta?.httpStatus ?? null,
212
+ timings: meta?.timings ?? null,
213
+ requestBytes: meta?.requestBytes ?? 0,
214
+ responseBytes: meta?.responseBytes ?? 0,
215
+ targetUrl: meta?.targetUrl ?? null,
216
+ requestHeaders: meta?.requestHeaders ?? {},
217
+ responseHeaders: meta?.responseHeaders ?? {},
218
+ rawBody,
219
+ composition,
220
+ costUsd,
221
+ healthScore: null,
222
+ securityAlerts: [],
223
+ };
224
+ // Compute health score
225
+ const sameConvo = conversationId
226
+ ? this.capturedRequests.filter((e) => e.conversationId === conversationId)
227
+ : [];
228
+ const prevMain = sameConvo
229
+ .filter((e) => !e.agentKey)
230
+ .sort((a, b) => new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime())[0];
231
+ // Collect all tools used across the conversation (including current entry)
232
+ const sessionToolsUsed = new Set();
233
+ for (const e of sameConvo) {
234
+ for (const tool of extractToolsUsed(e.contextInfo.messages)) {
235
+ sessionToolsUsed.add(tool);
236
+ }
237
+ }
238
+ // Also scan current entry (not yet in capturedRequests)
239
+ for (const tool of extractToolsUsed(contextInfo.messages)) {
240
+ sessionToolsUsed.add(tool);
241
+ }
242
+ const turnCount = sameConvo.filter((e) => !e.agentKey).length + 1;
243
+ entry.healthScore = computeHealthScore(entry, prevMain ? prevMain.contextInfo.totalTokens : null, sessionToolsUsed, turnCount);
244
+ // Security scanning must happen before compaction strips message content
245
+ const securityResult = scanSecurity(contextInfo);
246
+ entry.securityAlerts = securityResult.alerts;
247
+ // Track response IDs for Responses API chaining
248
+ const respId = responseData.id ||
249
+ responseData.response_id;
250
+ if (respId && conversationId) {
251
+ this.responseIdToConvo.set(respId, conversationId);
252
+ }
253
+ this.capturedRequests.unshift(entry);
254
+ // Evict oldest sessions when we exceed the session limit
255
+ if (this.conversations.size > this.maxSessions) {
256
+ // Find the oldest session by its most recent entry timestamp
257
+ const sessionLatest = new Map();
258
+ for (const r of this.capturedRequests) {
259
+ if (r.conversationId) {
260
+ const t = new Date(r.timestamp).getTime();
261
+ const cur = sessionLatest.get(r.conversationId) || 0;
262
+ if (t > cur)
263
+ sessionLatest.set(r.conversationId, t);
264
+ }
265
+ }
266
+ // Sort sessions oldest-first, evict until we're at the limit
267
+ const sorted = [...sessionLatest.entries()].sort((a, b) => a[1] - b[1]);
268
+ const toEvict = sorted
269
+ .slice(0, sorted.length - this.maxSessions)
270
+ .map((s) => s[0]);
271
+ const evictSet = new Set(toEvict);
272
+ // Remove all entries belonging to evicted sessions
273
+ for (let i = this.capturedRequests.length - 1; i >= 0; i--) {
274
+ const evictEntry = this.capturedRequests[i];
275
+ if (evictEntry.conversationId &&
276
+ evictSet.has(evictEntry.conversationId)) {
277
+ // Remove detail file
278
+ const detailPath = path.join(this.detailDir, `${evictEntry.id}.json`);
279
+ try {
280
+ fs.unlinkSync(detailPath);
281
+ }
282
+ catch {
283
+ /* may not exist */
284
+ }
285
+ this.capturedRequests.splice(i, 1);
286
+ }
287
+ }
288
+ for (const cid of toEvict) {
289
+ this.conversations.delete(cid);
290
+ this.diskSessionsWritten.delete(cid);
291
+ for (const [rid, rcid] of this.responseIdToConvo) {
292
+ if (rcid === cid)
293
+ this.responseIdToConvo.delete(rid);
294
+ }
295
+ }
296
+ }
297
+ this.dataRevision++;
298
+ this.emitChange("entry-added", conversationId);
299
+ this.logToDisk(entry);
300
+ this.saveEntryDetail(entry);
301
+ this.compactEntry(entry);
302
+ this.saveState();
303
+ return entry;
304
+ }
305
+ deleteConversation(convoId) {
306
+ this.removeConversationDetails(convoId);
307
+ this.conversations.delete(convoId);
308
+ for (let i = this.capturedRequests.length - 1; i >= 0; i--) {
309
+ if (this.capturedRequests[i].conversationId === convoId)
310
+ this.capturedRequests.splice(i, 1);
311
+ }
312
+ this.diskSessionsWritten.delete(convoId);
313
+ for (const [rid, cid] of this.responseIdToConvo) {
314
+ if (cid === convoId)
315
+ this.responseIdToConvo.delete(rid);
316
+ }
317
+ this.dataRevision++;
318
+ this.emitChange("conversation-deleted", convoId);
319
+ this.saveState();
320
+ }
321
+ resetAll() {
322
+ // Remove all detail files
323
+ try {
324
+ const files = fs.readdirSync(this.detailDir);
325
+ for (const f of files) {
326
+ try {
327
+ fs.unlinkSync(path.join(this.detailDir, f));
328
+ }
329
+ catch {
330
+ /* ignore */
331
+ }
332
+ }
333
+ }
334
+ catch {
335
+ /* directory may not exist */
336
+ }
337
+ this.capturedRequests.length = 0;
338
+ this.conversations.clear();
339
+ this.diskSessionsWritten.clear();
340
+ this.responseIdToConvo.clear();
341
+ this.nextEntryId = 1;
342
+ this.dataRevision++;
343
+ this.emitChange("reset");
344
+ this.saveState();
345
+ }
346
+ // ----- Internals -----
347
+ /** Backfill health scores for entries loaded from state that don't have one. */
348
+ backfillHealthScores() {
349
+ // Process oldest-first so previousTokens lookups work correctly.
350
+ const sorted = [...this.capturedRequests].sort((a, b) => new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime());
351
+ for (const entry of sorted) {
352
+ if (entry.healthScore)
353
+ continue;
354
+ const sameConvo = entry.conversationId
355
+ ? sorted.filter((e) => e.conversationId === entry.conversationId &&
356
+ new Date(e.timestamp).getTime() <
357
+ new Date(entry.timestamp).getTime())
358
+ : [];
359
+ const prevMain = sameConvo
360
+ .filter((e) => !e.agentKey)
361
+ .sort((a, b) => new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime())[0];
362
+ // Collect all tools used across the conversation (up to this entry)
363
+ const sessionToolsUsed = new Set();
364
+ for (const e of [...sameConvo, entry]) {
365
+ for (const tool of extractToolsUsed(e.contextInfo.messages)) {
366
+ sessionToolsUsed.add(tool);
367
+ }
368
+ }
369
+ const turnCount = sameConvo.filter((e) => !e.agentKey).length + (entry.agentKey ? 0 : 1);
370
+ entry.healthScore = computeHealthScore(entry, prevMain ? prevMain.contextInfo.totalTokens : null, sessionToolsUsed, turnCount);
371
+ }
372
+ }
373
+ /**
374
+ * Recalculate token counts for messages that contain image blocks.
375
+ *
376
+ * Before the image token fix, estimateTokens() would stringify base64 image
377
+ * data, producing millions of phantom tokens. Persisted entries still have
378
+ * those inflated counts. This migration recalculates from the compacted
379
+ /**
380
+ * Backfill totalTokens from API usage data for entries that only have estimates.
381
+ * The estimate (chars/4) can be wildly inaccurate; the API's real token count
382
+ * (input + cacheRead + cacheWrite) is authoritative.
383
+ */
384
+ backfillTotalTokensFromUsage() {
385
+ let fixed = 0;
386
+ for (const entry of this.capturedRequests) {
387
+ const usage = parseResponseUsage(entry.response);
388
+ const actual = usage.inputTokens + usage.cacheReadTokens + usage.cacheWriteTokens;
389
+ if (actual > 0 && actual !== entry.contextInfo.totalTokens) {
390
+ rescaleContextTokens(entry.contextInfo, actual);
391
+ fixed++;
392
+ }
393
+ }
394
+ if (fixed > 0) {
395
+ console.log(`Fixed totalTokens from API usage for ${fixed} entries`);
396
+ }
397
+ }
398
+ /**
399
+ * Migrate image token counts: re-estimate token counts for messages containing
400
+ * contentBlocks (which have no base64 data) using the fixed estimateTokens().
401
+ */
402
+ migrateImageTokenCounts() {
403
+ let migrated = 0;
404
+ const updateTotals = (ci, messagesTokens) => {
405
+ ci.messagesTokens = messagesTokens;
406
+ ci.totalTokens = ci.systemTokens + ci.toolsTokens + ci.messagesTokens;
407
+ };
408
+ for (const entry of this.capturedRequests) {
409
+ const ci = entry.contextInfo;
410
+ let messagesTokens = 0;
411
+ let changed = false;
412
+ for (const msg of ci.messages) {
413
+ if (!msg.contentBlocks || msg.contentBlocks.length === 0) {
414
+ messagesTokens += msg.tokens;
415
+ continue;
416
+ }
417
+ // Check if any block (or nested content in tool_result) is an image
418
+ const hasImage = msg.contentBlocks.some((b) => {
419
+ if (b.type === "image")
420
+ return true;
421
+ if (b.type === "tool_result" && Array.isArray(b.content)) {
422
+ return b.content.some((inner) => inner?.type === "image");
423
+ }
424
+ return false;
425
+ });
426
+ if (!hasImage) {
427
+ messagesTokens += msg.tokens;
428
+ continue;
429
+ }
430
+ // Recalculate from compacted contentBlocks (no base64 data)
431
+ const newTokens = estimateTokens(msg.contentBlocks);
432
+ if (newTokens < msg.tokens) {
433
+ msg.tokens = newTokens;
434
+ changed = true;
435
+ }
436
+ messagesTokens += msg.tokens;
437
+ }
438
+ if (changed) {
439
+ updateTotals(ci, messagesTokens);
440
+ migrated++;
441
+ }
442
+ else if (ci.messagesTokens !== messagesTokens) {
443
+ // Messages with images may have been truncated during compaction,
444
+ // leaving messagesTokens inflated even though no image blocks remain.
445
+ // Fix by recalculating from the actual per-message token counts.
446
+ updateTotals(ci, messagesTokens);
447
+ migrated++;
448
+ }
449
+ }
450
+ if (migrated > 0) {
451
+ console.log(`Migrated ${migrated} entries with inflated image token counts`);
452
+ }
453
+ return migrated;
454
+ }
455
+ /**
456
+ * Save full contextInfo for an entry to disk so the UI can retrieve
457
+ * uncompacted message content on demand.
458
+ */
459
+ saveEntryDetail(entry) {
460
+ const detailPath = path.join(this.detailDir, `${entry.id}.json`);
461
+ try {
462
+ fs.writeFileSync(detailPath, JSON.stringify({
463
+ contextInfo: entry.contextInfo,
464
+ }));
465
+ }
466
+ catch (err) {
467
+ console.error("Detail save error:", err instanceof Error ? err.message : String(err));
468
+ }
469
+ }
470
+ /**
471
+ * Load full contextInfo for an entry from disk.
472
+ * Returns null if the detail file doesn't exist (old entries before this feature).
473
+ */
474
+ getEntryDetail(entryId) {
475
+ const detailPath = path.join(this.detailDir, `${entryId}.json`);
476
+ try {
477
+ const data = JSON.parse(fs.readFileSync(detailPath, "utf-8"));
478
+ return data.contextInfo ?? null;
479
+ }
480
+ catch {
481
+ return null;
482
+ }
483
+ }
484
+ /**
485
+ * Remove detail files for entries belonging to a conversation.
486
+ */
487
+ removeConversationDetails(convoId) {
488
+ for (const entry of this.capturedRequests) {
489
+ if (entry.conversationId === convoId) {
490
+ const detailPath = path.join(this.detailDir, `${entry.id}.json`);
491
+ try {
492
+ fs.unlinkSync(detailPath);
493
+ }
494
+ catch {
495
+ /* file may not exist */
496
+ }
497
+ }
498
+ }
499
+ }
500
+ logToDisk(entry) {
501
+ const safeSource = safeFilenamePart(entry.source || "unknown");
502
+ const safeConvo = entry.conversationId
503
+ ? safeFilenamePart(entry.conversationId)
504
+ : null;
505
+ const filename = safeConvo
506
+ ? `${safeSource}-${safeConvo}.lhar`
507
+ : "ungrouped.lhar";
508
+ const filePath = path.join(this.dataDir, filename);
509
+ let output = "";
510
+ // Write session preamble on first entry for this conversation
511
+ if (entry.conversationId &&
512
+ !this.diskSessionsWritten.has(entry.conversationId)) {
513
+ this.diskSessionsWritten.add(entry.conversationId);
514
+ const convo = this.conversations.get(entry.conversationId);
515
+ if (convo) {
516
+ const sessionLine = buildSessionLine(entry.conversationId, convo, entry.contextInfo.model);
517
+ output += `${JSON.stringify(sessionLine)}\n`;
518
+ }
519
+ }
520
+ const record = buildLharRecord(entry, this.capturedRequests, this.privacy);
521
+ output += `${JSON.stringify(record)}\n`;
522
+ try {
523
+ fs.appendFileSync(filePath, output);
524
+ }
525
+ catch (err) {
526
+ console.error("Log write error:", err instanceof Error ? err.message : String(err));
527
+ }
528
+ }
529
+ // Compact a content block: keep tool metadata, truncate text.
530
+ // Full content is available via the detail API (per-entry files on disk).
531
+ compactBlock(b) {
532
+ const limit = 200;
533
+ switch (b.type) {
534
+ case "tool_use":
535
+ return { type: "tool_use", id: b.id, name: b.name, input: {} };
536
+ case "tool_result": {
537
+ const rc = typeof b.content === "string"
538
+ ? b.content.slice(0, limit)
539
+ : Array.isArray(b.content)
540
+ ? b.content.map((bb) => this.compactBlock(bb))
541
+ : "";
542
+ return { type: "tool_result", tool_use_id: b.tool_use_id, content: rc };
543
+ }
544
+ case "text":
545
+ return { type: "text", text: (b.text || "").slice(0, limit) };
546
+ case "input_text":
547
+ return { type: "input_text", text: (b.text || "").slice(0, limit) };
548
+ case "image":
549
+ return { type: "image" };
550
+ default: {
551
+ // Handle thinking blocks and other unknown types; truncate text-like fields
552
+ const any = b;
553
+ if (any.thinking)
554
+ return {
555
+ ...any,
556
+ thinking: any.thinking.slice(0, limit),
557
+ };
558
+ if (any.text)
559
+ return { ...any, text: any.text.slice(0, limit) };
560
+ return b;
561
+ }
562
+ }
563
+ }
564
+ compactMessages(messages) {
565
+ const limit = 200;
566
+ const msgs = messages.length > this.maxCompactMessages
567
+ ? messages.slice(-this.maxCompactMessages)
568
+ : messages;
569
+ return msgs.map((m) => ({
570
+ role: m.role,
571
+ content: typeof m.content === "string" ? m.content.slice(0, limit) : "",
572
+ tokens: m.tokens,
573
+ contentBlocks: m.contentBlocks?.map((b) => this.compactBlock(b)) ?? null,
574
+ }));
575
+ }
576
+ // Compact contextInfo: keep metadata and token counts, drop large text payloads
577
+ compactContextInfo(ci) {
578
+ return {
579
+ provider: ci.provider,
580
+ apiFormat: ci.apiFormat,
581
+ model: ci.model,
582
+ systemTokens: ci.systemTokens,
583
+ toolsTokens: ci.toolsTokens,
584
+ messagesTokens: ci.messagesTokens,
585
+ totalTokens: ci.totalTokens,
586
+ systemPrompts: [],
587
+ tools: [],
588
+ messages: this.compactMessages(ci.messages),
589
+ };
590
+ }
591
+ // Release heavy data from an entry after it's been logged to disk
592
+ compactEntry(entry) {
593
+ // Extract and preserve usage data from response before dropping it
594
+ const usage = parseResponseUsage(entry.response);
595
+ entry.response = {
596
+ usage: {
597
+ input_tokens: usage.inputTokens,
598
+ output_tokens: usage.outputTokens,
599
+ cache_read_input_tokens: usage.cacheReadTokens,
600
+ cache_creation_input_tokens: usage.cacheWriteTokens,
601
+ },
602
+ model: usage.model,
603
+ stop_reason: usage.finishReasons[0] || null,
604
+ };
605
+ entry.rawBody = undefined;
606
+ entry.requestHeaders = {};
607
+ entry.responseHeaders = {};
608
+ // Compact contextInfo in-place
609
+ entry.contextInfo.systemPrompts = [];
610
+ entry.contextInfo.tools = [];
611
+ entry.contextInfo.messages = this.compactMessages(entry.contextInfo.messages);
612
+ }
613
+ saveState() {
614
+ let lines = "";
615
+ for (const [, convo] of this.conversations) {
616
+ lines += `${JSON.stringify({ type: "conversation", data: convo })}\n`;
617
+ }
618
+ for (const entry of this.capturedRequests) {
619
+ lines += `${JSON.stringify({
620
+ type: "entry",
621
+ data: projectEntry(entry, this.compactContextInfo(entry.contextInfo)),
622
+ })}\n`;
623
+ }
624
+ try {
625
+ fs.writeFileSync(this.stateFile, lines);
626
+ }
627
+ catch (err) {
628
+ console.error("State save error:", err instanceof Error ? err.message : String(err));
629
+ }
630
+ }
631
+ }
632
+ //# sourceMappingURL=store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store.js","sourceRoot":"","sources":["../../src/server/store.ts"],"names":[],"mappings":"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"}