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,218 @@
1
+ import http from "node:http";
2
+ import https from "node:https";
3
+ import url from "node:url";
4
+ import { detectApiFormat, estimateTokens, extractSource, parseContextInfo, resolveTargetUrl, } from "../core.js";
5
+ import { headersForResolution, selectHeaders } from "../server-utils.js";
6
+ function buildForwardHeaders(reqHeaders, targetHost, bodyLength) {
7
+ const forwardHeaders = { ...reqHeaders };
8
+ delete forwardHeaders["x-target-url"];
9
+ delete forwardHeaders.host;
10
+ if (targetHost) {
11
+ forwardHeaders.host = targetHost;
12
+ }
13
+ if (bodyLength != null) {
14
+ delete forwardHeaders["transfer-encoding"];
15
+ forwardHeaders["content-length"] = bodyLength;
16
+ }
17
+ return forwardHeaders;
18
+ }
19
+ function attachProxyLifecycleHandlers(res, proxyReq) {
20
+ // Abort upstream request if client disconnects
21
+ res.on("close", () => {
22
+ if (!proxyReq.destroyed)
23
+ proxyReq.destroy();
24
+ });
25
+ proxyReq.on("error", (err) => {
26
+ // Suppress errors from client-initiated disconnects
27
+ if (res.destroyed)
28
+ return;
29
+ const detail = err.message || ("code" in err ? err.code : "unknown");
30
+ console.error("Proxy error:", detail);
31
+ if (!res.headersSent) {
32
+ res.writeHead(502, { "Content-Type": "application/json" });
33
+ }
34
+ if (!res.destroyed) {
35
+ res.end(JSON.stringify({ error: "Proxy error", details: err.message }));
36
+ }
37
+ });
38
+ }
39
+ export function forwardRequest(req, res, parsedUrl, body, opts) {
40
+ const { targetUrl } = resolveTargetUrl({ pathname: parsedUrl.pathname, search: parsedUrl.search }, headersForResolution(req.headers, req.socket.remoteAddress, opts.allowTargetOverride), opts.upstreams);
41
+ const targetParsed = url.parse(targetUrl);
42
+ // When we buffer the body, replace chunked encoding with exact content-length
43
+ const forwardHeaders = buildForwardHeaders(req.headers, targetParsed.host, body ? body.length : undefined);
44
+ const protocol = targetParsed.protocol === "https:" ? https : http;
45
+ const proxyReq = protocol.request({
46
+ hostname: targetParsed.hostname,
47
+ port: targetParsed.port,
48
+ path: targetParsed.path,
49
+ method: req.method,
50
+ headers: forwardHeaders,
51
+ }, (proxyRes) => {
52
+ if (!res.headersSent)
53
+ res.writeHead(proxyRes.statusCode, proxyRes.headers);
54
+ proxyRes.pipe(res);
55
+ proxyRes.on("error", (err) => {
56
+ console.error("Upstream response error (forward):", err.message);
57
+ if (!res.destroyed)
58
+ res.end();
59
+ });
60
+ });
61
+ attachProxyLifecycleHandlers(res, proxyReq);
62
+ if (body)
63
+ proxyReq.write(body);
64
+ proxyReq.end();
65
+ }
66
+ export function createProxyHandler(store, opts) {
67
+ return function handleProxy(req, res) {
68
+ const parsedUrl = url.parse(req.url);
69
+ const { source, cleanPath } = extractSource(parsedUrl.pathname);
70
+ // Use clean path (without source prefix) for routing
71
+ const cleanUrl = { ...parsedUrl, pathname: cleanPath };
72
+ const { targetUrl, provider } = resolveTargetUrl({ pathname: cleanPath, search: parsedUrl.search }, headersForResolution(req.headers, req.socket.remoteAddress, opts.allowTargetOverride), opts.upstreams);
73
+ const hasAuth = !!req.headers.authorization;
74
+ const sourceTag = source ? `[${source}]` : "";
75
+ console.log(`${req.method} ${req.url} → ${targetUrl} [${provider}] ${sourceTag} auth=${hasAuth}`);
76
+ // For non-POST requests (GET /v1/models, OPTIONS, etc.), pass through directly
77
+ if (req.method !== "POST") {
78
+ forwardRequest(req, res, cleanUrl, null, opts);
79
+ return;
80
+ }
81
+ // Collect body as raw Buffers to avoid corrupting multi-byte UTF-8 at chunk boundaries
82
+ const chunks = [];
83
+ let clientAborted = false;
84
+ req.on("data", (chunk) => {
85
+ chunks.push(chunk);
86
+ });
87
+ req.on("error", () => {
88
+ clientAborted = true;
89
+ });
90
+ req.on("end", () => {
91
+ if (clientAborted)
92
+ return;
93
+ const bodyBuffer = Buffer.concat(chunks);
94
+ const body = bodyBuffer.toString("utf8");
95
+ let bodyData;
96
+ try {
97
+ bodyData = JSON.parse(body);
98
+ }
99
+ catch (_e) {
100
+ console.log(` ⚠ Body is not JSON (${bodyBuffer.length} bytes), capturing raw`);
101
+ // Still capture the raw request even if body isn't JSON
102
+ const rawInfo = {
103
+ provider,
104
+ apiFormat: "raw",
105
+ model: "unknown",
106
+ systemTokens: 0,
107
+ toolsTokens: 0,
108
+ messagesTokens: estimateTokens(body),
109
+ totalTokens: estimateTokens(body),
110
+ systemPrompts: [],
111
+ tools: [],
112
+ messages: [
113
+ {
114
+ role: "raw",
115
+ content: body.substring(0, 2000),
116
+ tokens: estimateTokens(body),
117
+ },
118
+ ],
119
+ };
120
+ store.storeRequest(rawInfo, { raw: true }, source, undefined, undefined, selectHeaders(req.headers));
121
+ forwardRequest(req, res, cleanUrl, bodyBuffer, opts);
122
+ return;
123
+ }
124
+ console.log(` ✓ Parsed JSON body (${Object.keys(bodyData).join(", ")})`);
125
+ const apiFormat = detectApiFormat(cleanPath);
126
+ // Gemini: model is in the URL path, not in the body
127
+ if (apiFormat === "gemini" && !bodyData.model) {
128
+ const modelMatch = cleanPath.match(/\/models\/([^/:]+)/);
129
+ if (modelMatch)
130
+ bodyData.model = modelMatch[1];
131
+ }
132
+ const contextInfo = parseContextInfo(provider, bodyData, apiFormat);
133
+ // Skip capturing utility endpoints (count_tokens, etc.). Not real conversation turns
134
+ const isUtilityEndpoint = /\/count_tokens\b|:countTokens\b|:loadCodeAssist\b|:retrieveUserQuota\b|:listExperiments\b|:onboardUser\b|:fetchAdminControls\b|:recordCodeAssistMetrics\b/.test(cleanPath);
135
+ const targetParsed = url.parse(targetUrl);
136
+ // Ensure content-length matches the exact bytes we forward
137
+ const forwardHeaders = buildForwardHeaders(req.headers, targetParsed.host, bodyBuffer.length);
138
+ // Make request to actual API
139
+ const protocol = targetParsed.protocol === "https:" ? https : http;
140
+ const startTime = performance.now();
141
+ let firstByteTime = 0;
142
+ const reqBytes = bodyBuffer.length;
143
+ const proxyReq = protocol.request({
144
+ hostname: targetParsed.hostname,
145
+ port: targetParsed.port,
146
+ path: targetParsed.path,
147
+ method: req.method,
148
+ headers: forwardHeaders,
149
+ }, (proxyRes) => {
150
+ console.log(` ← ${proxyRes.statusCode} ${proxyRes.statusMessage}`);
151
+ // Forward response headers
152
+ res.writeHead(proxyRes.statusCode, proxyRes.headers);
153
+ const httpStatus = proxyRes.statusCode || 0;
154
+ // Handle streaming vs non-streaming
155
+ const isStreaming = proxyRes.headers["content-type"]?.includes("text/event-stream");
156
+ let respBytes = 0;
157
+ const capturedReqHeaders = selectHeaders(req.headers);
158
+ const capturedResHeaders = selectHeaders(proxyRes.headers);
159
+ // Collect response as Buffer[] to avoid corrupting multi-byte UTF-8 at chunk boundaries
160
+ const respChunks = [];
161
+ proxyRes.on("data", (chunk) => {
162
+ if (!firstByteTime)
163
+ firstByteTime = performance.now();
164
+ respBytes += chunk.length;
165
+ respChunks.push(chunk);
166
+ if (!res.destroyed)
167
+ res.write(chunk);
168
+ });
169
+ proxyRes.on("end", () => {
170
+ const endTime = performance.now();
171
+ if (!firstByteTime)
172
+ firstByteTime = endTime;
173
+ const meta = {
174
+ httpStatus,
175
+ timings: {
176
+ send_ms: Math.round(firstByteTime - startTime),
177
+ wait_ms: Math.round(firstByteTime - startTime),
178
+ receive_ms: Math.round(endTime - firstByteTime),
179
+ total_ms: Math.round(endTime - startTime),
180
+ tokens_per_second: null,
181
+ },
182
+ requestBytes: reqBytes,
183
+ responseBytes: respBytes,
184
+ targetUrl,
185
+ requestHeaders: capturedReqHeaders,
186
+ responseHeaders: capturedResHeaders,
187
+ };
188
+ const respBody = Buffer.concat(respChunks).toString("utf8");
189
+ if (!isUtilityEndpoint) {
190
+ if (isStreaming) {
191
+ store.storeRequest(contextInfo, { streaming: true, chunks: respBody }, source, bodyData, meta, capturedReqHeaders);
192
+ }
193
+ else {
194
+ try {
195
+ const responseData = JSON.parse(respBody);
196
+ store.storeRequest(contextInfo, responseData, source, bodyData, meta, capturedReqHeaders);
197
+ }
198
+ catch (_e) {
199
+ store.storeRequest(contextInfo, { raw: respBody }, source, bodyData, meta, capturedReqHeaders);
200
+ }
201
+ }
202
+ }
203
+ if (!res.destroyed)
204
+ res.end();
205
+ });
206
+ proxyRes.on("error", (err) => {
207
+ console.error("Upstream response error:", err.message);
208
+ if (!res.destroyed)
209
+ res.end();
210
+ });
211
+ });
212
+ attachProxyLifecycleHandlers(res, proxyReq);
213
+ proxyReq.write(bodyBuffer);
214
+ proxyReq.end();
215
+ });
216
+ };
217
+ }
218
+ //# sourceMappingURL=proxy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"proxy.js","sourceRoot":"","sources":["../../src/server/proxy.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ import type http from "node:http";
2
+ /**
3
+ * Create a static file handler that serves from `uiDir` if it exists,
4
+ * otherwise falls back to serving `fallbackHtml` at `/`.
5
+ *
6
+ * Returns a function that handles the request, always responds.
7
+ */
8
+ export declare function createStaticHandler(uiDir: string | null, fallbackHtml: string): (req: http.IncomingMessage, res: http.ServerResponse) => void;
9
+ //# sourceMappingURL=static.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"static.d.ts","sourceRoot":"","sources":["../../src/server/static.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAgBlC;;;;;GAKG;AACH,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,MAAM,GAAG,IAAI,EACpB,YAAY,EAAE,MAAM,GACnB,CAAC,GAAG,EAAE,IAAI,CAAC,eAAe,EAAE,GAAG,EAAE,IAAI,CAAC,cAAc,KAAK,IAAI,CA+D/D"}
@@ -0,0 +1,78 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+ const MIME_TYPES = {
4
+ ".html": "text/html",
5
+ ".js": "application/javascript",
6
+ ".css": "text/css",
7
+ ".json": "application/json",
8
+ ".png": "image/png",
9
+ ".svg": "image/svg+xml",
10
+ ".ico": "image/x-icon",
11
+ ".woff": "font/woff",
12
+ ".woff2": "font/woff2",
13
+ ".map": "application/json",
14
+ };
15
+ /**
16
+ * Create a static file handler that serves from `uiDir` if it exists,
17
+ * otherwise falls back to serving `fallbackHtml` at `/`.
18
+ *
19
+ * Returns a function that handles the request, always responds.
20
+ */
21
+ export function createStaticHandler(uiDir, fallbackHtml) {
22
+ // Check if ui/dist exists at startup
23
+ const uiDirExists = uiDir !== null && fs.existsSync(uiDir);
24
+ return function handleStatic(req, res) {
25
+ if (uiDirExists && uiDir) {
26
+ // Serve from ui/dist
27
+ let reqPath = req.url?.split("?")[0] || "/";
28
+ // Prevent directory traversal
29
+ reqPath = path.normalize(reqPath).replace(/^(\.\.[/\\])+/, "");
30
+ // Map / to /index.html
31
+ if (reqPath === "/")
32
+ reqPath = "/index.html";
33
+ const filePath = path.join(uiDir, reqPath);
34
+ // Ensure we don't serve files outside uiDir
35
+ if (!filePath.startsWith(uiDir)) {
36
+ res.writeHead(403, { "Content-Type": "text/plain" });
37
+ res.end("Forbidden");
38
+ return;
39
+ }
40
+ try {
41
+ const stat = fs.statSync(filePath);
42
+ if (stat.isFile()) {
43
+ const ext = path.extname(filePath).toLowerCase();
44
+ const contentType = MIME_TYPES[ext] || "application/octet-stream";
45
+ const content = fs.readFileSync(filePath);
46
+ res.writeHead(200, { "Content-Type": contentType });
47
+ res.end(content);
48
+ return;
49
+ }
50
+ }
51
+ catch {
52
+ // File not found; fall through to SPA fallback
53
+ }
54
+ // SPA fallback: serve index.html for unmatched routes
55
+ const indexPath = path.join(uiDir, "index.html");
56
+ try {
57
+ const content = fs.readFileSync(indexPath);
58
+ res.writeHead(200, { "Content-Type": "text/html" });
59
+ res.end(content);
60
+ }
61
+ catch {
62
+ res.writeHead(404, { "Content-Type": "text/plain" });
63
+ res.end("Not Found");
64
+ }
65
+ return;
66
+ }
67
+ // Fallback: serve legacy HTML UI
68
+ if (req.url === "/" || req.url === "/index.html") {
69
+ res.writeHead(200, { "Content-Type": "text/html" });
70
+ res.end(fallbackHtml);
71
+ }
72
+ else {
73
+ res.writeHead(404, { "Content-Type": "text/plain" });
74
+ res.end("Not Found");
75
+ }
76
+ };
77
+ }
78
+ //# sourceMappingURL=static.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"static.js","sourceRoot":"","sources":["../../src/server/static.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,81 @@
1
+ import type { CapturedEntry, ContextInfo, Conversation, PrivacyLevel, RequestMeta, ResponseData } from "../types.js";
2
+ export interface StoreChangeEvent {
3
+ type: string;
4
+ revision: number;
5
+ conversationId?: string | null;
6
+ }
7
+ type StoreChangeListener = (event: StoreChangeEvent) => void;
8
+ export declare class Store {
9
+ private readonly dataDir;
10
+ private readonly stateFile;
11
+ private readonly detailDir;
12
+ private readonly maxSessions;
13
+ private readonly maxCompactMessages;
14
+ private readonly privacy;
15
+ private capturedRequests;
16
+ private conversations;
17
+ private responseIdToConvo;
18
+ private diskSessionsWritten;
19
+ private dataRevision;
20
+ private nextEntryId;
21
+ private changeListeners;
22
+ constructor(opts: {
23
+ dataDir: string;
24
+ stateFile: string;
25
+ maxSessions: number;
26
+ maxCompactMessages: number;
27
+ privacy?: PrivacyLevel;
28
+ });
29
+ getRevision(): number;
30
+ getPrivacy(): PrivacyLevel;
31
+ on(_event: "change", listener: StoreChangeListener): void;
32
+ off(_event: "change", listener: StoreChangeListener): void;
33
+ private emitChange;
34
+ getCapturedRequests(): CapturedEntry[];
35
+ getConversations(): Map<string, Conversation>;
36
+ loadState(): void;
37
+ storeRequest(contextInfo: ContextInfo, responseData: ResponseData, source: string | null, rawBody?: Record<string, any>, meta?: RequestMeta, requestHeaders?: Record<string, string>): CapturedEntry;
38
+ deleteConversation(convoId: string): void;
39
+ resetAll(): void;
40
+ /** Backfill health scores for entries loaded from state that don't have one. */
41
+ private backfillHealthScores;
42
+ /**
43
+ * Recalculate token counts for messages that contain image blocks.
44
+ *
45
+ * Before the image token fix, estimateTokens() would stringify base64 image
46
+ * data, producing millions of phantom tokens. Persisted entries still have
47
+ * those inflated counts. This migration recalculates from the compacted
48
+ /**
49
+ * Backfill totalTokens from API usage data for entries that only have estimates.
50
+ * The estimate (chars/4) can be wildly inaccurate; the API's real token count
51
+ * (input + cacheRead + cacheWrite) is authoritative.
52
+ */
53
+ private backfillTotalTokensFromUsage;
54
+ /**
55
+ * Migrate image token counts: re-estimate token counts for messages containing
56
+ * contentBlocks (which have no base64 data) using the fixed estimateTokens().
57
+ */
58
+ private migrateImageTokenCounts;
59
+ /**
60
+ * Save full contextInfo for an entry to disk so the UI can retrieve
61
+ * uncompacted message content on demand.
62
+ */
63
+ private saveEntryDetail;
64
+ /**
65
+ * Load full contextInfo for an entry from disk.
66
+ * Returns null if the detail file doesn't exist (old entries before this feature).
67
+ */
68
+ getEntryDetail(entryId: number): ContextInfo | null;
69
+ /**
70
+ * Remove detail files for entries belonging to a conversation.
71
+ */
72
+ private removeConversationDetails;
73
+ private logToDisk;
74
+ private compactBlock;
75
+ private compactMessages;
76
+ private compactContextInfo;
77
+ private compactEntry;
78
+ private saveState;
79
+ }
80
+ export {};
81
+ //# sourceMappingURL=store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../src/server/store.ts"],"names":[],"mappings":"AAyBA,OAAO,KAAK,EACV,aAAa,EAEb,WAAW,EACX,YAAY,EACZ,YAAY,EACZ,WAAW,EACX,YAAY,EACb,MAAM,aAAa,CAAC;AAGrB,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAChC;AAED,KAAK,mBAAmB,GAAG,CAAC,KAAK,EAAE,gBAAgB,KAAK,IAAI,CAAC;AAE7D,qBAAa,KAAK;IAChB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAS;IAC5C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAe;IAEvC,OAAO,CAAC,gBAAgB,CAAuB;IAC/C,OAAO,CAAC,aAAa,CAAmC;IACxD,OAAO,CAAC,iBAAiB,CAA6B;IACtD,OAAO,CAAC,mBAAmB,CAAqB;IAEhD,OAAO,CAAC,YAAY,CAAK;IACzB,OAAO,CAAC,WAAW,CAAK;IAGxB,OAAO,CAAC,eAAe,CAAkC;gBAE7C,IAAI,EAAE;QAChB,OAAO,EAAE,MAAM,CAAC;QAChB,SAAS,EAAE,MAAM,CAAC;QAClB,WAAW,EAAE,MAAM,CAAC;QACpB,kBAAkB,EAAE,MAAM,CAAC;QAC3B,OAAO,CAAC,EAAE,YAAY,CAAC;KACxB;IAoBD,WAAW,IAAI,MAAM;IAIrB,UAAU,IAAI,YAAY;IAM1B,EAAE,CAAC,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,mBAAmB,GAAG,IAAI;IAIzD,GAAG,CAAC,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,mBAAmB,GAAG,IAAI;IAI1D,OAAO,CAAC,UAAU;IAelB,mBAAmB,IAAI,aAAa,EAAE;IAItC,gBAAgB,IAAI,GAAG,CAAC,MAAM,EAAE,YAAY,CAAC;IAI7C,SAAS,IAAI,IAAI;IAgEjB,YAAY,CACV,WAAW,EAAE,WAAW,EACxB,YAAY,EAAE,YAAY,EAC1B,MAAM,EAAE,MAAM,GAAG,IAAI,EACrB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAC7B,IAAI,CAAC,EAAE,WAAW,EAClB,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GACtC,aAAa;IAiNhB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAgBzC,QAAQ,IAAI,IAAI;IA2BhB,gFAAgF;IAChF,OAAO,CAAC,oBAAoB;IA4C5B;;;;;;;;;;OAUG;IACH,OAAO,CAAC,4BAA4B;IAgBpC;;;OAGG;IACH,OAAO,CAAC,uBAAuB;IAwD/B;;;OAGG;IACH,OAAO,CAAC,eAAe;IAiBvB;;;OAGG;IACH,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI;IAUnD;;OAEG;IACH,OAAO,CAAC,yBAAyB;IAajC,OAAO,CAAC,SAAS;IA4CjB,OAAO,CAAC,YAAY;IAmCpB,OAAO,CAAC,eAAe;IAiBvB,OAAO,CAAC,kBAAkB;IAgB1B,OAAO,CAAC,YAAY;IA0BpB,OAAO,CAAC,SAAS;CAoBlB"}