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