@kb-labs/core-platform 1.0.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 (56) hide show
  1. package/README.md +108 -0
  2. package/dist/adapters/index.cjs +26 -0
  3. package/dist/adapters/index.cjs.map +1 -0
  4. package/dist/adapters/index.d.cts +125 -0
  5. package/dist/adapters/index.d.ts +125 -0
  6. package/dist/adapters/index.js +21 -0
  7. package/dist/adapters/index.js.map +1 -0
  8. package/dist/artifacts-BUghvkUU.d.cts +273 -0
  9. package/dist/artifacts-Bd-1UVTw.d.ts +273 -0
  10. package/dist/artifacts-DrVnkLzu.d.cts +1374 -0
  11. package/dist/artifacts-DrVnkLzu.d.ts +1374 -0
  12. package/dist/core/index.cjs +4 -0
  13. package/dist/core/index.cjs.map +1 -0
  14. package/dist/core/index.d.cts +2 -0
  15. package/dist/core/index.d.ts +2 -0
  16. package/dist/core/index.js +3 -0
  17. package/dist/core/index.js.map +1 -0
  18. package/dist/database-DGV6a1nj.d.cts +427 -0
  19. package/dist/database-DGV6a1nj.d.ts +427 -0
  20. package/dist/index.cjs +1405 -0
  21. package/dist/index.cjs.map +1 -0
  22. package/dist/index.d.cts +579 -0
  23. package/dist/index.d.ts +579 -0
  24. package/dist/index.js +1381 -0
  25. package/dist/index.js.map +1 -0
  26. package/dist/log-reader-BVohbSMB.d.cts +314 -0
  27. package/dist/log-reader-uOHBLBax.d.ts +314 -0
  28. package/dist/noop/adapters/index.cjs +656 -0
  29. package/dist/noop/adapters/index.cjs.map +1 -0
  30. package/dist/noop/adapters/index.d.cts +71 -0
  31. package/dist/noop/adapters/index.d.ts +71 -0
  32. package/dist/noop/adapters/index.js +637 -0
  33. package/dist/noop/adapters/index.js.map +1 -0
  34. package/dist/noop/core/index.cjs +217 -0
  35. package/dist/noop/core/index.cjs.map +1 -0
  36. package/dist/noop/core/index.d.cts +94 -0
  37. package/dist/noop/core/index.d.ts +94 -0
  38. package/dist/noop/core/index.js +212 -0
  39. package/dist/noop/core/index.js.map +1 -0
  40. package/dist/noop/index.cjs +806 -0
  41. package/dist/noop/index.cjs.map +1 -0
  42. package/dist/noop/index.d.cts +36 -0
  43. package/dist/noop/index.d.ts +36 -0
  44. package/dist/noop/index.js +787 -0
  45. package/dist/noop/index.js.map +1 -0
  46. package/dist/resources-DaufJFad.d.cts +419 -0
  47. package/dist/resources-DaufJFad.d.ts +419 -0
  48. package/dist/serializable/index.cjs +162 -0
  49. package/dist/serializable/index.cjs.map +1 -0
  50. package/dist/serializable/index.d.cts +352 -0
  51. package/dist/serializable/index.d.ts +352 -0
  52. package/dist/serializable/index.js +152 -0
  53. package/dist/serializable/index.js.map +1 -0
  54. package/dist/snapshot-provider--COac4P-.d.ts +923 -0
  55. package/dist/snapshot-provider-nE9wuc1C.d.cts +923 -0
  56. package/package.json +92 -0
package/dist/index.js ADDED
@@ -0,0 +1,1381 @@
1
+ import { createHash } from 'crypto';
2
+ import path from 'path';
3
+
4
+ // src/adapters/llm-types.ts
5
+ var TIER_ORDER = [
6
+ "small",
7
+ "medium",
8
+ "large"
9
+ ];
10
+ function isTierHigher(a, b) {
11
+ return TIER_ORDER.indexOf(a) > TIER_ORDER.indexOf(b);
12
+ }
13
+ function isTierLower(a, b) {
14
+ return TIER_ORDER.indexOf(a) < TIER_ORDER.indexOf(b);
15
+ }
16
+
17
+ // src/wrappers/analytics-llm.ts
18
+ var AnalyticsLLM = class {
19
+ constructor(realLLM, analytics) {
20
+ this.realLLM = realLLM;
21
+ this.analytics = analytics;
22
+ }
23
+ async getProtocolCapabilities() {
24
+ if (!this.realLLM.getProtocolCapabilities) {
25
+ return {
26
+ cache: { supported: false },
27
+ stream: { supported: true }
28
+ };
29
+ }
30
+ return this.realLLM.getProtocolCapabilities();
31
+ }
32
+ /**
33
+ * Generate a completion with analytics tracking.
34
+ */
35
+ async complete(prompt, options) {
36
+ const startTime = Date.now();
37
+ const requestId = generateRequestId();
38
+ const metadata = options?.metadata;
39
+ await this.analytics.track("llm.completion.started", {
40
+ requestId,
41
+ tier: metadata?.tier,
42
+ provider: metadata?.provider,
43
+ model: options?.model,
44
+ cacheRequestedMode: metadata?.cacheDecisionTrace?.cacheRequestedMode,
45
+ cacheAppliedMode: metadata?.cacheDecisionTrace?.cacheAppliedMode,
46
+ streamRequestedMode: metadata?.cacheDecisionTrace?.streamRequestedMode,
47
+ streamAppliedMode: metadata?.cacheDecisionTrace?.streamAppliedMode,
48
+ streamFallback: metadata?.cacheDecisionTrace?.streamFallback,
49
+ promptLength: prompt.length,
50
+ maxTokens: options?.maxTokens,
51
+ temperature: options?.temperature
52
+ });
53
+ try {
54
+ const response = await this.realLLM.complete(prompt, options);
55
+ await this.trackCacheOutcome(requestId, metadata, response);
56
+ const durationMs = Date.now() - startTime;
57
+ const usageMetrics = buildUsageAnalytics(response);
58
+ await this.analytics.track("llm.completion.completed", {
59
+ requestId,
60
+ tier: metadata?.tier,
61
+ provider: metadata?.provider,
62
+ model: response.model,
63
+ cacheRequestedMode: metadata?.cacheDecisionTrace?.cacheRequestedMode,
64
+ cacheAppliedMode: metadata?.cacheDecisionTrace?.cacheAppliedMode,
65
+ streamRequestedMode: metadata?.cacheDecisionTrace?.streamRequestedMode,
66
+ streamAppliedMode: metadata?.cacheDecisionTrace?.streamAppliedMode,
67
+ streamFallback: metadata?.cacheDecisionTrace?.streamFallback,
68
+ ...usageMetrics,
69
+ durationMs
70
+ });
71
+ return response;
72
+ } catch (error) {
73
+ await this.analytics.track("llm.completion.error", {
74
+ requestId,
75
+ tier: metadata?.tier,
76
+ provider: metadata?.provider,
77
+ cacheRequestedMode: metadata?.cacheDecisionTrace?.cacheRequestedMode,
78
+ cacheAppliedMode: metadata?.cacheDecisionTrace?.cacheAppliedMode,
79
+ streamRequestedMode: metadata?.cacheDecisionTrace?.streamRequestedMode,
80
+ streamAppliedMode: metadata?.cacheDecisionTrace?.streamAppliedMode,
81
+ streamFallback: metadata?.cacheDecisionTrace?.streamFallback,
82
+ error: error instanceof Error ? error.message : String(error),
83
+ durationMs: Date.now() - startTime
84
+ });
85
+ throw error;
86
+ }
87
+ }
88
+ /**
89
+ * Stream a completion.
90
+ * Note: Streaming is harder to track token-by-token, so we track start/end only.
91
+ */
92
+ async *stream(prompt, options) {
93
+ const startTime = Date.now();
94
+ const requestId = generateRequestId();
95
+ const metadata = options?.metadata;
96
+ await this.analytics.track("llm.stream.started", {
97
+ requestId,
98
+ tier: metadata?.tier,
99
+ provider: metadata?.provider,
100
+ model: options?.model,
101
+ cacheRequestedMode: metadata?.cacheDecisionTrace?.cacheRequestedMode,
102
+ cacheAppliedMode: metadata?.cacheDecisionTrace?.cacheAppliedMode,
103
+ streamRequestedMode: metadata?.cacheDecisionTrace?.streamRequestedMode,
104
+ streamAppliedMode: metadata?.cacheDecisionTrace?.streamAppliedMode,
105
+ streamFallback: metadata?.cacheDecisionTrace?.streamFallback,
106
+ promptLength: prompt.length
107
+ });
108
+ try {
109
+ let totalChunks = 0;
110
+ let totalLength = 0;
111
+ for await (const chunk of this.realLLM.stream(prompt, options)) {
112
+ totalChunks++;
113
+ totalLength += chunk.length;
114
+ yield chunk;
115
+ }
116
+ await this.analytics.track("llm.stream.completed", {
117
+ requestId,
118
+ tier: metadata?.tier,
119
+ provider: metadata?.provider,
120
+ model: options?.model,
121
+ cacheRequestedMode: metadata?.cacheDecisionTrace?.cacheRequestedMode,
122
+ cacheAppliedMode: metadata?.cacheDecisionTrace?.cacheAppliedMode,
123
+ streamRequestedMode: metadata?.cacheDecisionTrace?.streamRequestedMode,
124
+ streamAppliedMode: metadata?.cacheDecisionTrace?.streamAppliedMode,
125
+ streamFallback: metadata?.cacheDecisionTrace?.streamFallback,
126
+ durationMs: Date.now() - startTime,
127
+ totalChunks,
128
+ totalLength
129
+ });
130
+ } catch (error) {
131
+ await this.analytics.track("llm.stream.error", {
132
+ requestId,
133
+ tier: metadata?.tier,
134
+ provider: metadata?.provider,
135
+ cacheRequestedMode: metadata?.cacheDecisionTrace?.cacheRequestedMode,
136
+ cacheAppliedMode: metadata?.cacheDecisionTrace?.cacheAppliedMode,
137
+ streamRequestedMode: metadata?.cacheDecisionTrace?.streamRequestedMode,
138
+ streamAppliedMode: metadata?.cacheDecisionTrace?.streamAppliedMode,
139
+ streamFallback: metadata?.cacheDecisionTrace?.streamFallback,
140
+ error: error instanceof Error ? error.message : String(error),
141
+ durationMs: Date.now() - startTime
142
+ });
143
+ throw error;
144
+ }
145
+ }
146
+ /**
147
+ * Chat with native tool calling support (optional).
148
+ * Proxies to underlying LLM if it supports chatWithTools.
149
+ */
150
+ async chatWithTools(messages, options) {
151
+ if (!this.realLLM.chatWithTools) {
152
+ throw new Error("Underlying LLM does not support chatWithTools");
153
+ }
154
+ const startTime = Date.now();
155
+ const requestId = generateRequestId();
156
+ const metadata = options?.metadata;
157
+ await this.analytics.track("llm.chatWithTools.started", {
158
+ requestId,
159
+ tier: metadata?.tier,
160
+ provider: metadata?.provider,
161
+ model: options?.model,
162
+ cacheRequestedMode: metadata?.cacheDecisionTrace?.cacheRequestedMode,
163
+ cacheAppliedMode: metadata?.cacheDecisionTrace?.cacheAppliedMode,
164
+ streamRequestedMode: metadata?.cacheDecisionTrace?.streamRequestedMode,
165
+ streamAppliedMode: metadata?.cacheDecisionTrace?.streamAppliedMode,
166
+ streamFallback: metadata?.cacheDecisionTrace?.streamFallback,
167
+ messageCount: messages.length,
168
+ toolCount: options.tools.length,
169
+ toolChoice: options.toolChoice,
170
+ maxTokens: options?.maxTokens,
171
+ temperature: options?.temperature
172
+ });
173
+ try {
174
+ const response = await this.realLLM.chatWithTools(messages, options);
175
+ await this.trackCacheOutcome(requestId, metadata, response);
176
+ const durationMs = Date.now() - startTime;
177
+ const usageMetrics = buildUsageAnalytics(response);
178
+ await this.analytics.track("llm.chatWithTools.completed", {
179
+ requestId,
180
+ tier: metadata?.tier,
181
+ provider: metadata?.provider,
182
+ model: response.model,
183
+ cacheRequestedMode: metadata?.cacheDecisionTrace?.cacheRequestedMode,
184
+ cacheAppliedMode: metadata?.cacheDecisionTrace?.cacheAppliedMode,
185
+ streamRequestedMode: metadata?.cacheDecisionTrace?.streamRequestedMode,
186
+ streamAppliedMode: metadata?.cacheDecisionTrace?.streamAppliedMode,
187
+ streamFallback: metadata?.cacheDecisionTrace?.streamFallback,
188
+ ...usageMetrics,
189
+ toolCallCount: response.toolCalls?.length ?? 0,
190
+ toolNames: response.toolCalls?.map((tc) => tc.name) ?? [],
191
+ durationMs
192
+ });
193
+ return response;
194
+ } catch (error) {
195
+ await this.analytics.track("llm.chatWithTools.error", {
196
+ requestId,
197
+ tier: metadata?.tier,
198
+ provider: metadata?.provider,
199
+ cacheRequestedMode: metadata?.cacheDecisionTrace?.cacheRequestedMode,
200
+ cacheAppliedMode: metadata?.cacheDecisionTrace?.cacheAppliedMode,
201
+ streamRequestedMode: metadata?.cacheDecisionTrace?.streamRequestedMode,
202
+ streamAppliedMode: metadata?.cacheDecisionTrace?.streamAppliedMode,
203
+ streamFallback: metadata?.cacheDecisionTrace?.streamFallback,
204
+ error: error instanceof Error ? error.message : String(error),
205
+ durationMs: Date.now() - startTime
206
+ });
207
+ throw error;
208
+ }
209
+ }
210
+ async trackCacheOutcome(requestId, metadata, response) {
211
+ const trace = metadata?.cacheDecisionTrace;
212
+ if (!trace) {
213
+ return;
214
+ }
215
+ const cacheReadTokens = response.usage.cacheReadTokens ?? 0;
216
+ const cacheWriteTokens = response.usage.cacheWriteTokens ?? 0;
217
+ const basePayload = {
218
+ requestId,
219
+ tier: metadata?.tier,
220
+ provider: metadata?.provider,
221
+ cacheRequestedMode: trace.cacheRequestedMode,
222
+ cacheAppliedMode: trace.cacheAppliedMode,
223
+ cacheSupported: trace.cacheSupported,
224
+ cacheReadTokens,
225
+ cacheWriteTokens,
226
+ promptTokens: response.usage.promptTokens,
227
+ completionTokens: response.usage.completionTokens,
228
+ model: response.model
229
+ };
230
+ if (trace.cacheAppliedMode === "bypass" || trace.cacheRequestedMode === "bypass") {
231
+ await this.analytics.track("llm.cache.bypass", {
232
+ ...basePayload,
233
+ reason: trace.reason ?? "CACHE_BYPASSED"
234
+ });
235
+ return;
236
+ }
237
+ if (cacheReadTokens > 0) {
238
+ await this.analytics.track("llm.cache.hit", basePayload);
239
+ return;
240
+ }
241
+ await this.analytics.track("llm.cache.miss", {
242
+ ...basePayload,
243
+ reason: trace.reason ?? "NO_CACHE_READ_TOKENS"
244
+ });
245
+ }
246
+ };
247
+ function generateRequestId() {
248
+ return `llm-${Date.now()}-${Math.random().toString(36).substring(7)}`;
249
+ }
250
+ function buildUsageAnalytics(response) {
251
+ const model = response.model.toLowerCase();
252
+ const promptTokens = response.usage.promptTokens;
253
+ const completionTokens = response.usage.completionTokens;
254
+ const cacheReadTokens = response.usage.cacheReadTokens ?? 0;
255
+ const cacheWriteTokens = response.usage.cacheWriteTokens ?? 0;
256
+ const billablePromptTokens = response.usage.billablePromptTokens ?? Math.max(promptTokens - cacheReadTokens, 0);
257
+ const totalTokens = promptTokens + completionTokens;
258
+ const billableTotalTokens = billablePromptTokens + completionTokens;
259
+ const pricing = getPricing(model);
260
+ const normalInputTokens = Math.max(promptTokens - cacheReadTokens, 0);
261
+ const cachedInputTokens = cacheReadTokens;
262
+ const cachedInputRate = pricing.cachedInput ?? pricing.input;
263
+ const inputCost = normalInputTokens / 1e6 * pricing.input + cachedInputTokens / 1e6 * cachedInputRate;
264
+ const outputCost = completionTokens / 1e6 * pricing.output;
265
+ const estimatedCost = inputCost + outputCost;
266
+ const uncachedInputCost = promptTokens / 1e6 * pricing.input;
267
+ const uncachedOutputCost = outputCost;
268
+ const estimatedUncachedCost = uncachedInputCost + uncachedOutputCost;
269
+ const estimatedCacheSavingsUsd = Math.max(estimatedUncachedCost - estimatedCost, 0);
270
+ const estimatedSavedPromptTokens = Math.max(promptTokens - billablePromptTokens, 0);
271
+ return {
272
+ promptTokens,
273
+ completionTokens,
274
+ totalTokens,
275
+ cacheReadTokens,
276
+ cacheWriteTokens,
277
+ billablePromptTokens,
278
+ billableTotalTokens,
279
+ estimatedSavedPromptTokens,
280
+ estimatedCost,
281
+ estimatedUncachedCost,
282
+ estimatedCacheSavingsUsd
283
+ };
284
+ }
285
+ function getPricing(model) {
286
+ const pricing = {
287
+ // OpenAI models (2025-01 pricing)
288
+ "gpt-4o-mini": { input: 0.15, output: 0.6, cachedInput: 0.075 },
289
+ "gpt-4o": { input: 2.5, output: 10, cachedInput: 1.25 },
290
+ "gpt-4-turbo": { input: 10, output: 30 },
291
+ "gpt-4": { input: 30, output: 60 },
292
+ "gpt-3.5-turbo": { input: 0.5, output: 1.5 },
293
+ // Claude models (2025-01 pricing)
294
+ // Cached input discounts vary by policy (5m/1h), conservative defaults:
295
+ // if unknown, keep cachedInput equal to input.
296
+ "claude-3-opus": { input: 15, output: 75 },
297
+ "claude-3-sonnet": { input: 3, output: 15 },
298
+ "claude-3-haiku": { input: 0.25, output: 1.25 }
299
+ };
300
+ const sortedKeys = Object.keys(pricing).sort((a, b) => b.length - a.length);
301
+ let modelPricing = pricing["gpt-4o-mini"];
302
+ for (const key of sortedKeys) {
303
+ if (model.includes(key)) {
304
+ modelPricing = pricing[key];
305
+ break;
306
+ }
307
+ }
308
+ return modelPricing;
309
+ }
310
+
311
+ // src/wrappers/analytics-embeddings.ts
312
+ function generateRequestId2() {
313
+ return `emb_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`;
314
+ }
315
+ function estimateCost(textLength, provider = "openai") {
316
+ const pricing = {
317
+ openai: 2e-5,
318
+ // per 1K tokens
319
+ cohere: 1e-4
320
+ // per 1K tokens
321
+ };
322
+ const pricePerK = pricing[provider] || pricing.openai;
323
+ const estimatedTokens = Math.ceil(textLength / 750);
324
+ return estimatedTokens / 1e3 * pricePerK;
325
+ }
326
+ var AnalyticsEmbeddings = class {
327
+ constructor(realEmbeddings, analytics) {
328
+ this.realEmbeddings = realEmbeddings;
329
+ this.analytics = analytics;
330
+ }
331
+ get dimensions() {
332
+ return this.realEmbeddings.dimensions;
333
+ }
334
+ async getDimensions() {
335
+ return this.realEmbeddings.getDimensions();
336
+ }
337
+ async embed(text) {
338
+ const startTime = Date.now();
339
+ const requestId = generateRequestId2();
340
+ await this.analytics.track("embeddings.embed.started", {
341
+ requestId,
342
+ textLength: text.length,
343
+ batchSize: 1
344
+ });
345
+ try {
346
+ const result = await this.realEmbeddings.embed(text);
347
+ const durationMs = Date.now() - startTime;
348
+ await this.analytics.track("embeddings.embed.completed", {
349
+ requestId,
350
+ textLength: text.length,
351
+ dimensions: result.length,
352
+ durationMs,
353
+ estimatedCost: estimateCost(text.length),
354
+ batchSize: 1
355
+ });
356
+ return result;
357
+ } catch (error) {
358
+ await this.analytics.track("embeddings.embed.error", {
359
+ requestId,
360
+ error: error instanceof Error ? error.message : String(error),
361
+ durationMs: Date.now() - startTime
362
+ });
363
+ throw error;
364
+ }
365
+ }
366
+ async embedBatch(texts) {
367
+ const startTime = Date.now();
368
+ const requestId = generateRequestId2();
369
+ const totalTextLength = texts.reduce((sum, text) => sum + text.length, 0);
370
+ await this.analytics.track("embeddings.embedBatch.started", {
371
+ requestId,
372
+ totalTextLength,
373
+ batchSize: texts.length
374
+ });
375
+ try {
376
+ const results = await this.realEmbeddings.embedBatch(texts);
377
+ const durationMs = Date.now() - startTime;
378
+ await this.analytics.track("embeddings.embedBatch.completed", {
379
+ requestId,
380
+ totalTextLength,
381
+ batchSize: texts.length,
382
+ dimensions: results[0]?.length ?? 0,
383
+ durationMs,
384
+ estimatedCost: estimateCost(totalTextLength),
385
+ avgTextLength: Math.round(totalTextLength / texts.length)
386
+ });
387
+ return results;
388
+ } catch (error) {
389
+ await this.analytics.track("embeddings.embedBatch.error", {
390
+ requestId,
391
+ error: error instanceof Error ? error.message : String(error),
392
+ durationMs: Date.now() - startTime,
393
+ batchSize: texts.length
394
+ });
395
+ throw error;
396
+ }
397
+ }
398
+ };
399
+
400
+ // src/wrappers/analytics-vector-store.ts
401
+ function generateRequestId3() {
402
+ return `vec_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`;
403
+ }
404
+ var AnalyticsVectorStore = class {
405
+ constructor(realVectorStore, analytics) {
406
+ this.realVectorStore = realVectorStore;
407
+ this.analytics = analytics;
408
+ }
409
+ async search(query, limit, filter) {
410
+ const startTime = Date.now();
411
+ const requestId = generateRequestId3();
412
+ await this.analytics.track("vectorstore.search.started", {
413
+ requestId,
414
+ dimensions: query.length,
415
+ limit,
416
+ hasFilter: !!filter
417
+ });
418
+ try {
419
+ const results = await this.realVectorStore.search(query, limit, filter);
420
+ const durationMs = Date.now() - startTime;
421
+ const avgScore = results.length > 0 ? results.reduce((sum, r) => sum + r.score, 0) / results.length : 0;
422
+ await this.analytics.track("vectorstore.search.completed", {
423
+ requestId,
424
+ dimensions: query.length,
425
+ limit,
426
+ resultsCount: results.length,
427
+ avgScore,
428
+ durationMs,
429
+ hasFilter: !!filter
430
+ });
431
+ return results;
432
+ } catch (error) {
433
+ await this.analytics.track("vectorstore.search.error", {
434
+ requestId,
435
+ error: error instanceof Error ? error.message : String(error),
436
+ durationMs: Date.now() - startTime
437
+ });
438
+ throw error;
439
+ }
440
+ }
441
+ async upsert(vectors) {
442
+ const startTime = Date.now();
443
+ const requestId = generateRequestId3();
444
+ await this.analytics.track("vectorstore.upsert.started", {
445
+ requestId,
446
+ vectorCount: vectors.length
447
+ });
448
+ try {
449
+ await this.realVectorStore.upsert(vectors);
450
+ const durationMs = Date.now() - startTime;
451
+ await this.analytics.track("vectorstore.upsert.completed", {
452
+ requestId,
453
+ vectorCount: vectors.length,
454
+ durationMs
455
+ });
456
+ } catch (error) {
457
+ await this.analytics.track("vectorstore.upsert.error", {
458
+ requestId,
459
+ error: error instanceof Error ? error.message : String(error),
460
+ durationMs: Date.now() - startTime,
461
+ vectorCount: vectors.length
462
+ });
463
+ throw error;
464
+ }
465
+ }
466
+ async delete(ids) {
467
+ const startTime = Date.now();
468
+ const requestId = generateRequestId3();
469
+ await this.analytics.track("vectorstore.delete.started", {
470
+ requestId,
471
+ idsCount: ids.length
472
+ });
473
+ try {
474
+ await this.realVectorStore.delete(ids);
475
+ const durationMs = Date.now() - startTime;
476
+ await this.analytics.track("vectorstore.delete.completed", {
477
+ requestId,
478
+ idsCount: ids.length,
479
+ durationMs
480
+ });
481
+ } catch (error) {
482
+ await this.analytics.track("vectorstore.delete.error", {
483
+ requestId,
484
+ error: error instanceof Error ? error.message : String(error),
485
+ durationMs: Date.now() - startTime
486
+ });
487
+ throw error;
488
+ }
489
+ }
490
+ async count() {
491
+ const startTime = Date.now();
492
+ const requestId = generateRequestId3();
493
+ try {
494
+ const count = await this.realVectorStore.count();
495
+ const durationMs = Date.now() - startTime;
496
+ await this.analytics.track("vectorstore.count.completed", {
497
+ requestId,
498
+ count,
499
+ durationMs
500
+ });
501
+ return count;
502
+ } catch (error) {
503
+ await this.analytics.track("vectorstore.count.error", {
504
+ requestId,
505
+ error: error instanceof Error ? error.message : String(error),
506
+ durationMs: Date.now() - startTime
507
+ });
508
+ throw error;
509
+ }
510
+ }
511
+ async get(ids) {
512
+ if (!this.realVectorStore.get) {
513
+ throw new Error("get() not implemented by underlying vector store");
514
+ }
515
+ const startTime = Date.now();
516
+ const requestId = generateRequestId3();
517
+ try {
518
+ const results = await this.realVectorStore.get(ids);
519
+ const durationMs = Date.now() - startTime;
520
+ await this.analytics.track("vectorstore.get.completed", {
521
+ requestId,
522
+ idsCount: ids.length,
523
+ resultsCount: results.length,
524
+ durationMs
525
+ });
526
+ return results;
527
+ } catch (error) {
528
+ await this.analytics.track("vectorstore.get.error", {
529
+ requestId,
530
+ error: error instanceof Error ? error.message : String(error),
531
+ durationMs: Date.now() - startTime
532
+ });
533
+ throw error;
534
+ }
535
+ }
536
+ async query(filter) {
537
+ if (!this.realVectorStore.query) {
538
+ throw new Error("query() not implemented by underlying vector store");
539
+ }
540
+ const startTime = Date.now();
541
+ const requestId = generateRequestId3();
542
+ try {
543
+ const results = await this.realVectorStore.query(filter);
544
+ const durationMs = Date.now() - startTime;
545
+ await this.analytics.track("vectorstore.query.completed", {
546
+ requestId,
547
+ resultsCount: results.length,
548
+ durationMs
549
+ });
550
+ return results;
551
+ } catch (error) {
552
+ await this.analytics.track("vectorstore.query.error", {
553
+ requestId,
554
+ error: error instanceof Error ? error.message : String(error),
555
+ durationMs: Date.now() - startTime
556
+ });
557
+ throw error;
558
+ }
559
+ }
560
+ };
561
+
562
+ // src/wrappers/analytics-cache.ts
563
+ function generateRequestId4() {
564
+ return `cache_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`;
565
+ }
566
+ var cacheCounter = 0;
567
+ function shouldSampleCacheEvent(eventType) {
568
+ cacheCounter = (cacheCounter + 1) % 100;
569
+ if (eventType === "cache.get.hit" || eventType === "cache.set.completed") {
570
+ return cacheCounter === 0;
571
+ }
572
+ if (eventType === "cache.get.miss") {
573
+ return cacheCounter % 10 === 0;
574
+ }
575
+ return true;
576
+ }
577
+ var AnalyticsCache = class {
578
+ constructor(realCache, analytics) {
579
+ this.realCache = realCache;
580
+ this.analytics = analytics;
581
+ }
582
+ async get(key) {
583
+ const startTime = Date.now();
584
+ const requestId = generateRequestId4();
585
+ try {
586
+ const result = await this.realCache.get(key);
587
+ const durationMs = Date.now() - startTime;
588
+ const hit = result !== null;
589
+ const eventType = hit ? "cache.get.hit" : "cache.get.miss";
590
+ if (shouldSampleCacheEvent(eventType)) {
591
+ await this.analytics.track(eventType, {
592
+ requestId,
593
+ key,
594
+ durationMs
595
+ });
596
+ }
597
+ return result;
598
+ } catch (error) {
599
+ await this.analytics.track("cache.get.error", {
600
+ requestId,
601
+ key,
602
+ error: error instanceof Error ? error.message : String(error),
603
+ durationMs: Date.now() - startTime
604
+ });
605
+ throw error;
606
+ }
607
+ }
608
+ async set(key, value, ttl) {
609
+ const startTime = Date.now();
610
+ const requestId = generateRequestId4();
611
+ try {
612
+ await this.realCache.set(key, value, ttl);
613
+ const durationMs = Date.now() - startTime;
614
+ if (shouldSampleCacheEvent("cache.set.completed")) {
615
+ await this.analytics.track("cache.set.completed", {
616
+ requestId,
617
+ key,
618
+ ttl: ttl ?? null,
619
+ durationMs
620
+ });
621
+ }
622
+ } catch (error) {
623
+ await this.analytics.track("cache.set.error", {
624
+ requestId,
625
+ key,
626
+ error: error instanceof Error ? error.message : String(error),
627
+ durationMs: Date.now() - startTime
628
+ });
629
+ throw error;
630
+ }
631
+ }
632
+ async delete(key) {
633
+ const startTime = Date.now();
634
+ const requestId = generateRequestId4();
635
+ try {
636
+ await this.realCache.delete(key);
637
+ const durationMs = Date.now() - startTime;
638
+ await this.analytics.track("cache.delete.completed", {
639
+ requestId,
640
+ key,
641
+ durationMs
642
+ });
643
+ } catch (error) {
644
+ await this.analytics.track("cache.delete.error", {
645
+ requestId,
646
+ key,
647
+ error: error instanceof Error ? error.message : String(error),
648
+ durationMs: Date.now() - startTime
649
+ });
650
+ throw error;
651
+ }
652
+ }
653
+ async clear(pattern) {
654
+ const startTime = Date.now();
655
+ const requestId = generateRequestId4();
656
+ try {
657
+ await this.realCache.clear(pattern);
658
+ const durationMs = Date.now() - startTime;
659
+ await this.analytics.track("cache.clear.completed", {
660
+ requestId,
661
+ pattern: pattern ?? null,
662
+ durationMs
663
+ });
664
+ } catch (error) {
665
+ await this.analytics.track("cache.clear.error", {
666
+ requestId,
667
+ pattern: pattern ?? null,
668
+ error: error instanceof Error ? error.message : String(error),
669
+ durationMs: Date.now() - startTime
670
+ });
671
+ throw error;
672
+ }
673
+ }
674
+ async zadd(key, score, member) {
675
+ const startTime = Date.now();
676
+ const requestId = generateRequestId4();
677
+ try {
678
+ await this.realCache.zadd(key, score, member);
679
+ const durationMs = Date.now() - startTime;
680
+ await this.analytics.track("cache.zadd.completed", {
681
+ requestId,
682
+ key,
683
+ durationMs
684
+ });
685
+ } catch (error) {
686
+ await this.analytics.track("cache.zadd.error", {
687
+ requestId,
688
+ key,
689
+ error: error instanceof Error ? error.message : String(error),
690
+ durationMs: Date.now() - startTime
691
+ });
692
+ throw error;
693
+ }
694
+ }
695
+ async zrangebyscore(key, min, max) {
696
+ const startTime = Date.now();
697
+ const requestId = generateRequestId4();
698
+ try {
699
+ const results = await this.realCache.zrangebyscore(key, min, max);
700
+ const durationMs = Date.now() - startTime;
701
+ return results;
702
+ } catch (error) {
703
+ await this.analytics.track("cache.zrangebyscore.error", {
704
+ requestId,
705
+ key,
706
+ error: error instanceof Error ? error.message : String(error),
707
+ durationMs: Date.now() - startTime
708
+ });
709
+ throw error;
710
+ }
711
+ }
712
+ async zrem(key, member) {
713
+ const startTime = Date.now();
714
+ const requestId = generateRequestId4();
715
+ try {
716
+ await this.realCache.zrem(key, member);
717
+ const durationMs = Date.now() - startTime;
718
+ await this.analytics.track("cache.zrem.completed", {
719
+ requestId,
720
+ key,
721
+ durationMs
722
+ });
723
+ } catch (error) {
724
+ await this.analytics.track("cache.zrem.error", {
725
+ requestId,
726
+ key,
727
+ error: error instanceof Error ? error.message : String(error),
728
+ durationMs: Date.now() - startTime
729
+ });
730
+ throw error;
731
+ }
732
+ }
733
+ async setIfNotExists(key, value, ttl) {
734
+ const startTime = Date.now();
735
+ const requestId = generateRequestId4();
736
+ try {
737
+ const result = await this.realCache.setIfNotExists(key, value, ttl);
738
+ const durationMs = Date.now() - startTime;
739
+ await this.analytics.track("cache.setIfNotExists.completed", {
740
+ requestId,
741
+ key,
742
+ success: result,
743
+ ttl: ttl ?? null,
744
+ durationMs
745
+ });
746
+ return result;
747
+ } catch (error) {
748
+ await this.analytics.track("cache.setIfNotExists.error", {
749
+ requestId,
750
+ key,
751
+ error: error instanceof Error ? error.message : String(error),
752
+ durationMs: Date.now() - startTime
753
+ });
754
+ throw error;
755
+ }
756
+ }
757
+ };
758
+
759
+ // src/wrappers/analytics-storage.ts
760
+ function generateRequestId5() {
761
+ return `storage_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`;
762
+ }
763
+ var AnalyticsStorage = class {
764
+ constructor(realStorage, analytics) {
765
+ this.realStorage = realStorage;
766
+ this.analytics = analytics;
767
+ }
768
+ async read(path3) {
769
+ const startTime = Date.now();
770
+ const requestId = generateRequestId5();
771
+ try {
772
+ const result = await this.realStorage.read(path3);
773
+ const durationMs = Date.now() - startTime;
774
+ const bytesRead = result?.length ?? 0;
775
+ await this.analytics.track("storage.read.completed", {
776
+ requestId,
777
+ path: path3,
778
+ bytesRead,
779
+ durationMs,
780
+ found: result !== null
781
+ });
782
+ return result;
783
+ } catch (error) {
784
+ await this.analytics.track("storage.read.error", {
785
+ requestId,
786
+ path: path3,
787
+ error: error instanceof Error ? error.message : String(error),
788
+ durationMs: Date.now() - startTime
789
+ });
790
+ throw error;
791
+ }
792
+ }
793
+ async write(path3, data) {
794
+ const startTime = Date.now();
795
+ const requestId = generateRequestId5();
796
+ try {
797
+ await this.realStorage.write(path3, data);
798
+ const durationMs = Date.now() - startTime;
799
+ await this.analytics.track("storage.write.completed", {
800
+ requestId,
801
+ path: path3,
802
+ bytesWritten: data.length,
803
+ durationMs
804
+ });
805
+ } catch (error) {
806
+ await this.analytics.track("storage.write.error", {
807
+ requestId,
808
+ path: path3,
809
+ error: error instanceof Error ? error.message : String(error),
810
+ durationMs: Date.now() - startTime
811
+ });
812
+ throw error;
813
+ }
814
+ }
815
+ async delete(path3) {
816
+ const startTime = Date.now();
817
+ const requestId = generateRequestId5();
818
+ try {
819
+ await this.realStorage.delete(path3);
820
+ const durationMs = Date.now() - startTime;
821
+ await this.analytics.track("storage.delete.completed", {
822
+ requestId,
823
+ path: path3,
824
+ durationMs
825
+ });
826
+ } catch (error) {
827
+ await this.analytics.track("storage.delete.error", {
828
+ requestId,
829
+ path: path3,
830
+ error: error instanceof Error ? error.message : String(error),
831
+ durationMs: Date.now() - startTime
832
+ });
833
+ throw error;
834
+ }
835
+ }
836
+ async list(prefix) {
837
+ const startTime = Date.now();
838
+ const requestId = generateRequestId5();
839
+ try {
840
+ const results = await this.realStorage.list(prefix);
841
+ const durationMs = Date.now() - startTime;
842
+ await this.analytics.track("storage.list.completed", {
843
+ requestId,
844
+ prefix,
845
+ filesCount: results.length,
846
+ durationMs
847
+ });
848
+ return results;
849
+ } catch (error) {
850
+ await this.analytics.track("storage.list.error", {
851
+ requestId,
852
+ prefix,
853
+ error: error instanceof Error ? error.message : String(error),
854
+ durationMs: Date.now() - startTime
855
+ });
856
+ throw error;
857
+ }
858
+ }
859
+ async exists(path3) {
860
+ const startTime = Date.now();
861
+ const requestId = generateRequestId5();
862
+ try {
863
+ const result = await this.realStorage.exists(path3);
864
+ const durationMs = Date.now() - startTime;
865
+ await this.analytics.track("storage.exists.completed", {
866
+ requestId,
867
+ path: path3,
868
+ exists: result,
869
+ durationMs
870
+ });
871
+ return result;
872
+ } catch (error) {
873
+ await this.analytics.track("storage.exists.error", {
874
+ requestId,
875
+ path: path3,
876
+ error: error instanceof Error ? error.message : String(error),
877
+ durationMs: Date.now() - startTime
878
+ });
879
+ throw error;
880
+ }
881
+ }
882
+ };
883
+
884
+ // src/wrappers/scoped-analytics.ts
885
+ var ScopedAnalytics = class {
886
+ constructor(realAnalytics, scopedSource) {
887
+ this.realAnalytics = realAnalytics;
888
+ this.scopedSource = scopedSource;
889
+ if (realAnalytics.setSource) {
890
+ realAnalytics.setSource(scopedSource);
891
+ }
892
+ }
893
+ async track(event, properties) {
894
+ await this.realAnalytics.track(event, properties);
895
+ }
896
+ async identify(userId, traits) {
897
+ await this.realAnalytics.identify(userId, traits);
898
+ }
899
+ async flush() {
900
+ await this.realAnalytics.flush();
901
+ }
902
+ // Optional methods - delegate if available
903
+ async getEvents(query) {
904
+ if (!this.realAnalytics.getEvents) {
905
+ throw new Error("getEvents not supported by underlying analytics adapter");
906
+ }
907
+ return this.realAnalytics.getEvents(query);
908
+ }
909
+ async getStats() {
910
+ if (!this.realAnalytics.getStats) {
911
+ throw new Error("getStats not supported by underlying analytics adapter");
912
+ }
913
+ return this.realAnalytics.getStats();
914
+ }
915
+ async getBufferStatus() {
916
+ if (!this.realAnalytics.getBufferStatus) {
917
+ return null;
918
+ }
919
+ return this.realAnalytics.getBufferStatus();
920
+ }
921
+ async getDlqStatus() {
922
+ if (!this.realAnalytics.getDlqStatus) {
923
+ return null;
924
+ }
925
+ return this.realAnalytics.getDlqStatus();
926
+ }
927
+ /**
928
+ * Get current source from underlying adapter
929
+ */
930
+ getSource() {
931
+ if (this.realAnalytics.getSource) {
932
+ return this.realAnalytics.getSource();
933
+ }
934
+ return this.scopedSource;
935
+ }
936
+ /**
937
+ * Delegate setSource to underlying adapter
938
+ */
939
+ setSource(source) {
940
+ if (this.realAnalytics.setSource) {
941
+ this.realAnalytics.setSource(source);
942
+ }
943
+ this.scopedSource = source;
944
+ }
945
+ /**
946
+ * Get the scoped source (for testing/debugging)
947
+ */
948
+ getScopedSource() {
949
+ return this.scopedSource;
950
+ }
951
+ /**
952
+ * Get the underlying analytics adapter (for introspection)
953
+ */
954
+ getUnderlyingAdapter() {
955
+ return this.realAnalytics;
956
+ }
957
+ };
958
+ function createScopedAnalytics(analytics, scopedSource) {
959
+ return new ScopedAnalytics(analytics, scopedSource);
960
+ }
961
+ function isScopedAnalytics(analytics) {
962
+ return analytics instanceof ScopedAnalytics;
963
+ }
964
+ function unwrapScopedAnalytics(analytics) {
965
+ if (isScopedAnalytics(analytics)) {
966
+ return analytics.getUnderlyingAdapter();
967
+ }
968
+ return analytics;
969
+ }
970
+
971
+ // src/logging/prefixed-logger.ts
972
+ var SYSTEM_LOG_FIELDS = /* @__PURE__ */ new Set([
973
+ // Core observability
974
+ "reqId",
975
+ "requestId",
976
+ "traceId",
977
+ "spanId",
978
+ "parentSpanId",
979
+ "invocationId",
980
+ "executionId",
981
+ "tenantId",
982
+ "layer",
983
+ // REST context
984
+ "method",
985
+ "url",
986
+ // Workflow context
987
+ "workflowId",
988
+ "runId",
989
+ "stepId",
990
+ "jobId",
991
+ "attempt",
992
+ // Webhook context
993
+ "event",
994
+ "source",
995
+ // Cron context
996
+ "cronId",
997
+ "schedule",
998
+ "scheduledAt",
999
+ "lastRunAt"
1000
+ ]);
1001
+ function createPrefixedLogger(baseLogger, options = {}) {
1002
+ const {
1003
+ prefix = "plugin_",
1004
+ warnOnRename = true,
1005
+ protectedFields = SYSTEM_LOG_FIELDS
1006
+ } = options;
1007
+ return {
1008
+ // Proxy all log methods (defensive check for bind)
1009
+ trace: baseLogger.trace?.bind ? baseLogger.trace.bind(baseLogger) : baseLogger.trace,
1010
+ debug: baseLogger.debug?.bind ? baseLogger.debug.bind(baseLogger) : baseLogger.debug,
1011
+ info: baseLogger.info?.bind ? baseLogger.info.bind(baseLogger) : baseLogger.info,
1012
+ warn: baseLogger.warn?.bind ? baseLogger.warn.bind(baseLogger) : baseLogger.warn,
1013
+ error: baseLogger.error?.bind ? baseLogger.error.bind(baseLogger) : baseLogger.error,
1014
+ fatal: baseLogger.fatal?.bind ? baseLogger.fatal.bind(baseLogger) : baseLogger.fatal,
1015
+ // Proxy optional log buffer
1016
+ getLogBuffer: baseLogger.getLogBuffer?.bind ? baseLogger.getLogBuffer.bind(baseLogger) : baseLogger.getLogBuffer,
1017
+ // Wrap child() to add prefixing
1018
+ child(fields) {
1019
+ const prefixed = {};
1020
+ for (const [key, value] of Object.entries(fields)) {
1021
+ if (protectedFields.has(key)) {
1022
+ const newKey = `${prefix}${key}`;
1023
+ prefixed[newKey] = value;
1024
+ if (warnOnRename && process.env.NODE_ENV !== "production") {
1025
+ console.warn(
1026
+ `[Logger] Field "${key}" is reserved for system observability. Renamed to "${newKey}".`
1027
+ );
1028
+ }
1029
+ } else {
1030
+ prefixed[key] = value;
1031
+ }
1032
+ }
1033
+ return createPrefixedLogger(baseLogger.child(prefixed), options);
1034
+ }
1035
+ };
1036
+ }
1037
+ var MemoryHistoryStore = class {
1038
+ entries = [];
1039
+ maxEntries;
1040
+ constructor(maxEntries = 1e4) {
1041
+ this.maxEntries = maxEntries;
1042
+ }
1043
+ async save(record) {
1044
+ this.entries.push(record);
1045
+ if (this.entries.length > this.maxEntries) {
1046
+ this.entries.shift();
1047
+ }
1048
+ }
1049
+ async find(options) {
1050
+ const { scopeId, queryHash, queryVector, limit = 10 } = options;
1051
+ let results = this.entries.filter((entry) => entry.scopeId === scopeId);
1052
+ if (queryHash) {
1053
+ results = results.filter((entry) => entry.queryHash === queryHash);
1054
+ }
1055
+ if (queryVector && queryVector.length > 0) {
1056
+ results = results.map((entry) => {
1057
+ const similarity = entry.queryVector ? this.cosineSimilarity(queryVector, entry.queryVector) : 0;
1058
+ return { entry, similarity };
1059
+ }).filter((item) => item.similarity > 0.7).sort((a, b) => b.similarity - a.similarity).slice(0, limit).map((item) => item.entry);
1060
+ } else {
1061
+ results = results.slice(0, limit);
1062
+ }
1063
+ return results;
1064
+ }
1065
+ async popular(scopeId, limit = 20) {
1066
+ const counts = /* @__PURE__ */ new Map();
1067
+ for (const entry of this.entries) {
1068
+ if (entry.scopeId !== scopeId) {
1069
+ continue;
1070
+ }
1071
+ const count = counts.get(entry.query) ?? 0;
1072
+ counts.set(entry.query, count + 1);
1073
+ }
1074
+ return Array.from(counts.entries()).map(([query, count]) => ({ query, count })).sort((a, b) => b.count - a.count).slice(0, limit);
1075
+ }
1076
+ async saveReasoningPlan(record) {
1077
+ const targetHash = record.queryHash ?? createHash("sha256").update(record.query.toLowerCase().trim()).digest("hex");
1078
+ const matches = this.entries.filter((entry) => entry.scopeId === record.scopeId && entry.queryHash === targetHash);
1079
+ if (matches.length === 0) {
1080
+ await this.save({ ...record, queryHash: targetHash });
1081
+ return;
1082
+ }
1083
+ for (const entry of matches) {
1084
+ entry.reasoningPlan = record.reasoningPlan;
1085
+ }
1086
+ }
1087
+ cosineSimilarity(vec1, vec2) {
1088
+ if (vec1.length !== vec2.length) {
1089
+ return 0;
1090
+ }
1091
+ let dot = 0;
1092
+ let norm1 = 0;
1093
+ let norm2 = 0;
1094
+ for (let i = 0; i < vec1.length; i++) {
1095
+ dot += vec1[i] * vec2[i];
1096
+ norm1 += vec1[i] * vec1[i];
1097
+ norm2 += vec2[i] * vec2[i];
1098
+ }
1099
+ const denom = Math.sqrt(norm1) * Math.sqrt(norm2);
1100
+ return denom === 0 ? 0 : dot / denom;
1101
+ }
1102
+ };
1103
+
1104
+ // src/learning/memory-feedback-store.ts
1105
+ var MemoryFeedbackStore = class {
1106
+ entries = [];
1107
+ maxEntries;
1108
+ constructor(maxEntries = 1e4) {
1109
+ this.maxEntries = maxEntries;
1110
+ }
1111
+ async save(record) {
1112
+ this.entries.push(record);
1113
+ if (this.entries.length > this.maxEntries) {
1114
+ this.entries.shift();
1115
+ }
1116
+ }
1117
+ async list(scopeId, limit = 100) {
1118
+ const scoped = this.entries.filter((entry) => entry.scopeId === scopeId);
1119
+ return scoped.slice(-limit);
1120
+ }
1121
+ };
1122
+ var FileHistoryStore = class {
1123
+ constructor(storage, options = {}) {
1124
+ this.storage = storage;
1125
+ this.basePath = options.basePath ? this.ensureTrailingSlash(options.basePath) : ".kb/mind/learning/history/";
1126
+ this.filePrefix = options.filePrefix ?? "history-";
1127
+ this.maxRecordsPerFile = options.maxRecordsPerFile ?? 1e3;
1128
+ this.maxFiles = options.maxFiles ?? 30;
1129
+ }
1130
+ basePath;
1131
+ filePrefix;
1132
+ maxRecordsPerFile;
1133
+ maxFiles;
1134
+ async save(record) {
1135
+ const target = await this.getWritableFile();
1136
+ const line = JSON.stringify({ v: 1, record }) + "\n";
1137
+ try {
1138
+ const existing = await this.storage.read(target);
1139
+ const buffer = existing ? Buffer.concat([existing, Buffer.from(line, "utf8")]) : Buffer.from(line, "utf8");
1140
+ await this.storage.write(target, buffer);
1141
+ await this.enforceRotation();
1142
+ } catch (error) {
1143
+ console.error("[FileHistoryStore] Failed to write history", {
1144
+ target,
1145
+ error: error instanceof Error ? error.message : String(error)
1146
+ });
1147
+ }
1148
+ }
1149
+ async find(options) {
1150
+ const files = await this.getFilesSorted();
1151
+ const results = [];
1152
+ for (const file of files) {
1153
+ if (options.limit && results.length >= options.limit) {
1154
+ break;
1155
+ }
1156
+ const buf = await this.storage.read(file);
1157
+ if (!buf) {
1158
+ continue;
1159
+ }
1160
+ const lines = buf.toString("utf8").split("\n").filter(Boolean);
1161
+ for (const line of lines) {
1162
+ if (options.limit && results.length >= options.limit) {
1163
+ break;
1164
+ }
1165
+ try {
1166
+ const parsed = JSON.parse(line);
1167
+ const rec = parsed.record;
1168
+ if (rec.scopeId !== options.scopeId) {
1169
+ continue;
1170
+ }
1171
+ if (options.queryHash && rec.queryHash !== options.queryHash) {
1172
+ continue;
1173
+ }
1174
+ if (options.queryVector && options.queryVector.length > 0 && rec.queryVector) {
1175
+ const similarity = this.cosineSimilarity(options.queryVector, rec.queryVector);
1176
+ if (similarity <= 0.7) {
1177
+ continue;
1178
+ }
1179
+ }
1180
+ results.push(rec);
1181
+ } catch {
1182
+ continue;
1183
+ }
1184
+ }
1185
+ }
1186
+ return options.limit ? results.slice(0, options.limit) : results;
1187
+ }
1188
+ async popular(scopeId, limit = 20) {
1189
+ const files = await this.getFilesSorted();
1190
+ const counts = /* @__PURE__ */ new Map();
1191
+ for (const file of files) {
1192
+ const buf = await this.storage.read(file);
1193
+ if (!buf) {
1194
+ continue;
1195
+ }
1196
+ const lines = buf.toString("utf8").split("\n").filter(Boolean);
1197
+ for (const line of lines) {
1198
+ try {
1199
+ const parsed = JSON.parse(line);
1200
+ const rec = parsed.record;
1201
+ if (rec.scopeId !== scopeId) {
1202
+ continue;
1203
+ }
1204
+ counts.set(rec.query, (counts.get(rec.query) ?? 0) + 1);
1205
+ } catch {
1206
+ continue;
1207
+ }
1208
+ }
1209
+ }
1210
+ return Array.from(counts.entries()).map(([query, count]) => ({ query, count })).sort((a, b) => b.count - a.count).slice(0, limit);
1211
+ }
1212
+ async saveReasoningPlan(record) {
1213
+ const hash = record.queryHash ?? createHash("sha256").update(record.query.toLowerCase().trim()).digest("hex");
1214
+ await this.save({ ...record, queryHash: hash });
1215
+ }
1216
+ async getWritableFile() {
1217
+ const files = await this.getFilesSorted();
1218
+ if (files.length === 0) {
1219
+ return this.segmentPath(Date.now());
1220
+ }
1221
+ const latest = files[files.length - 1];
1222
+ const buf = await this.storage.read(latest);
1223
+ if (!buf) {
1224
+ return latest;
1225
+ }
1226
+ const count = buf.toString("utf8").split("\n").filter(Boolean).length;
1227
+ if (count >= this.maxRecordsPerFile) {
1228
+ return this.segmentPath(Date.now());
1229
+ }
1230
+ return latest;
1231
+ }
1232
+ async getFilesSorted() {
1233
+ const files = await this.storage.list(this.basePath);
1234
+ return files.filter((f) => f.startsWith(this.basePath + this.filePrefix) && f.endsWith(".jsonl")).sort();
1235
+ }
1236
+ segmentPath(ts) {
1237
+ const date = new Date(ts);
1238
+ const day = String(date.getDate()).padStart(2, "0");
1239
+ const month = String(date.getMonth() + 1).padStart(2, "0");
1240
+ const year = date.getFullYear();
1241
+ const filename = `${this.filePrefix}${year}${month}${day}-${ts}.jsonl`;
1242
+ return path.posix.join(this.basePath, filename);
1243
+ }
1244
+ async enforceRotation() {
1245
+ const files = await this.getFilesSorted();
1246
+ if (files.length <= this.maxFiles) {
1247
+ return;
1248
+ }
1249
+ const excess = files.length - this.maxFiles;
1250
+ const toDelete = files.slice(0, excess);
1251
+ await Promise.all(toDelete.map((f) => this.storage.delete(f)));
1252
+ }
1253
+ ensureTrailingSlash(p) {
1254
+ return p.endsWith("/") ? p : `${p}/`;
1255
+ }
1256
+ cosineSimilarity(vec1, vec2) {
1257
+ if (vec1.length !== vec2.length) {
1258
+ return 0;
1259
+ }
1260
+ let dot = 0;
1261
+ let norm1 = 0;
1262
+ let norm2 = 0;
1263
+ for (let i = 0; i < vec1.length; i++) {
1264
+ dot += vec1[i] * vec2[i];
1265
+ norm1 += vec1[i] * vec1[i];
1266
+ norm2 += vec2[i] * vec2[i];
1267
+ }
1268
+ const denom = Math.sqrt(norm1) * Math.sqrt(norm2);
1269
+ return denom === 0 ? 0 : dot / denom;
1270
+ }
1271
+ };
1272
+ var FileFeedbackStore = class {
1273
+ constructor(storage, options = {}) {
1274
+ this.storage = storage;
1275
+ this.basePath = options.basePath ? this.ensureTrailingSlash(options.basePath) : ".kb/mind/learning/feedback/";
1276
+ this.filePrefix = options.filePrefix ?? "feedback-";
1277
+ this.maxRecordsPerFile = options.maxRecordsPerFile ?? 1e3;
1278
+ this.maxFiles = options.maxFiles ?? 30;
1279
+ }
1280
+ basePath;
1281
+ filePrefix;
1282
+ maxRecordsPerFile;
1283
+ maxFiles;
1284
+ async save(record) {
1285
+ const target = await this.getWritableFile();
1286
+ const line = JSON.stringify({ v: 1, record }) + "\n";
1287
+ try {
1288
+ const existing = await this.storage.read(target);
1289
+ const buffer = existing ? Buffer.concat([existing, Buffer.from(line, "utf8")]) : Buffer.from(line, "utf8");
1290
+ await this.storage.write(target, buffer);
1291
+ await this.enforceRotation();
1292
+ } catch (error) {
1293
+ console.error("[FileFeedbackStore] Failed to write feedback", {
1294
+ target,
1295
+ error: error instanceof Error ? error.message : String(error)
1296
+ });
1297
+ }
1298
+ }
1299
+ async list(scopeId, limit = 100) {
1300
+ const files = await this.getFilesSorted();
1301
+ const results = [];
1302
+ for (const file of files) {
1303
+ if (results.length >= limit) {
1304
+ break;
1305
+ }
1306
+ const buf = await this.storage.read(file);
1307
+ if (!buf) {
1308
+ continue;
1309
+ }
1310
+ const lines = buf.toString("utf8").split("\n").filter(Boolean);
1311
+ for (const line of lines) {
1312
+ if (results.length >= limit) {
1313
+ break;
1314
+ }
1315
+ try {
1316
+ const parsed = JSON.parse(line);
1317
+ const rec = parsed.record;
1318
+ if (rec.scopeId !== scopeId) {
1319
+ continue;
1320
+ }
1321
+ results.push(rec);
1322
+ } catch {
1323
+ continue;
1324
+ }
1325
+ }
1326
+ }
1327
+ return results.slice(-limit);
1328
+ }
1329
+ async getWritableFile() {
1330
+ const files = await this.getFilesSorted();
1331
+ if (files.length === 0) {
1332
+ return this.segmentPath(Date.now());
1333
+ }
1334
+ const latest = files[files.length - 1];
1335
+ const buf = await this.storage.read(latest);
1336
+ if (!buf) {
1337
+ return latest;
1338
+ }
1339
+ const count = buf.toString("utf8").split("\n").filter(Boolean).length;
1340
+ if (count >= this.maxRecordsPerFile) {
1341
+ return this.segmentPath(Date.now());
1342
+ }
1343
+ return latest;
1344
+ }
1345
+ async getFilesSorted() {
1346
+ const files = await this.storage.list(this.basePath);
1347
+ return files.filter((f) => f.startsWith(this.basePath + this.filePrefix) && f.endsWith(".jsonl")).sort();
1348
+ }
1349
+ segmentPath(ts) {
1350
+ const date = new Date(ts);
1351
+ const day = String(date.getDate()).padStart(2, "0");
1352
+ const month = String(date.getMonth() + 1).padStart(2, "0");
1353
+ const year = date.getFullYear();
1354
+ const filename = `${this.filePrefix}${year}${month}${day}-${ts}.jsonl`;
1355
+ return path.posix.join(this.basePath, filename);
1356
+ }
1357
+ async enforceRotation() {
1358
+ const files = await this.getFilesSorted();
1359
+ if (files.length <= this.maxFiles) {
1360
+ return;
1361
+ }
1362
+ const excess = files.length - this.maxFiles;
1363
+ const toDelete = files.slice(0, excess);
1364
+ await Promise.all(toDelete.map((f) => this.storage.delete(f)));
1365
+ }
1366
+ ensureTrailingSlash(p) {
1367
+ return p.endsWith("/") ? p : `${p}/`;
1368
+ }
1369
+ };
1370
+
1371
+ // src/runs/run-types.ts
1372
+ var TERMINAL_RUN_STATUSES = /* @__PURE__ */ new Set([
1373
+ "completed",
1374
+ "failed",
1375
+ "failed_by_review",
1376
+ "cancelled"
1377
+ ]);
1378
+
1379
+ export { AnalyticsCache, AnalyticsEmbeddings, AnalyticsLLM, AnalyticsStorage, AnalyticsVectorStore, FileFeedbackStore, FileHistoryStore, MemoryFeedbackStore, MemoryHistoryStore, SYSTEM_LOG_FIELDS, ScopedAnalytics, TERMINAL_RUN_STATUSES, TIER_ORDER, createPrefixedLogger, createScopedAnalytics, isScopedAnalytics, isTierHigher, isTierLower, unwrapScopedAnalytics };
1380
+ //# sourceMappingURL=index.js.map
1381
+ //# sourceMappingURL=index.js.map