@yugenlab/vaayu 0.1.10 → 0.1.12
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.
- package/chunks/{agentic-tool-loop-2FZK72JO.js → agentic-tool-loop-NQESOBLC.js} +2 -2
- package/chunks/akasha-5C5Q6NMP.js +12 -0
- package/chunks/{chunk-JGI4SDWS.js → chunk-26K6DS6N.js} +7 -5
- package/chunks/chunk-5E3ZS5SW.js +529 -0
- package/chunks/{chunk-VJHNE47S.js → chunk-ARZCIITZ.js} +104 -94
- package/chunks/{chunk-PRXQW76U.js → chunk-EG37M4QL.js} +17 -6
- package/chunks/{chunk-HIYHTWFW.js → chunk-FEDPZOZ5.js} +572 -441
- package/chunks/{chunk-O4KV7TFP.js → chunk-GWYC7R2L.js} +38 -20
- package/chunks/chunk-H46F2Y6R.js +134 -0
- package/chunks/{chunk-M7THR63C.js → chunk-HXHDP2PZ.js} +78 -65
- package/chunks/chunk-KVQH4LE7.js +396 -0
- package/chunks/{chunk-TND3MU4Z.js → chunk-LJCT7UYP.js} +86 -68
- package/chunks/{chunk-OT4G2L46.js → chunk-M2RLX5LU.js} +229 -163
- package/chunks/{chunk-IGKYKEKT.js → chunk-NAQKA54E.js} +8 -2
- package/chunks/{chunk-77725AR7.js → chunk-PZ4AQ22L.js} +151 -57
- package/chunks/{chunk-C76USAC5.js → chunk-QFGAB4XD.js} +13 -5
- package/chunks/{chunk-MJ74G5RB.js → chunk-R273KC7J.js} +276 -3
- package/chunks/{chunk-JAWZ7ANC.js → chunk-RVKTGKFD.js} +12 -8
- package/chunks/{chunk-AGK3A7R7.js → chunk-TSOQ2CT3.js} +1430 -1173
- package/chunks/{chunk-YJRXLRTE.js → chunk-VEZ2DI2M.js} +24 -12
- package/chunks/{chunk-N22M7D4P.js → chunk-XP3NIH5F.js} +91 -98
- package/chunks/{chunk-6556EKOB.js → chunk-Y6IZH6FT.js} +42 -26
- package/chunks/{chunk-AS3DJFY3.js → chunk-YRTGGYJU.js} +45 -41
- package/chunks/{consolidation-indexer-VKQ6DNU3.js → consolidation-indexer-KPXORCJ4.js} +9 -9
- package/chunks/database-BX3LVYXS.js +11 -0
- package/chunks/{day-consolidation-BH3QU2SZ.js → day-consolidation-CR3TJFAL.js} +5 -5
- package/chunks/{src-Y3TGMINC.js → dist-ESCM3CP5.js} +31 -21
- package/chunks/graphrag-73XA7LBX.js +14 -0
- package/chunks/hierarchical-temporal-search-GHKVKNZ6.js +8 -0
- package/chunks/hybrid-search-OD756RDV.js +20 -0
- package/chunks/{memory-store-A6WOWLWC.js → memory-store-4GCBR2DZ.js} +4 -4
- package/chunks/periodic-consolidation-IINCHP6L.js +11 -0
- package/chunks/postgres-YLCUNVPQ.js +8 -0
- package/chunks/recall-64RROTUC.js +21 -0
- package/chunks/search-JVCDNTAJ.js +19 -0
- package/chunks/{session-store-3BRPGC6P.js → session-store-3EDQZEDS.js} +12 -6
- package/chunks/{sqlite-DHUQGPR5.js → sqlite-4N7YH2KK.js} +3 -3
- package/chunks/{src-6GVZTUH6.js → src-OPSDZEFI.js} +2 -2
- package/chunks/{suncalc-NOHGYHDU.js → suncalc-RM7URNUR.js} +2 -2
- package/chunks/{tree-RSHKDTCR.js → tree-FIUVGJ5J.js} +2 -2
- package/chunks/{vasana-engine-MU25OQ23.js → vasana-engine-W4PYWT5H.js} +5 -5
- package/gateway.js +38859 -30650
- package/package.json +1 -1
- package/pair-cli.js +2 -2
- package/chunks/chunk-U62ABYKD.js +0 -123
- package/chunks/chunk-UZ6OIVEC.js +0 -198
- package/chunks/graphrag-D7OXWAWD.js +0 -14
- package/chunks/hierarchical-temporal-search-PVHVA3NZ.js +0 -8
- package/chunks/hybrid-search-G2NAJKJ7.js +0 -20
- package/chunks/periodic-consolidation-LMYMNS4Q.js +0 -11
- package/chunks/postgres-WLH3D5HG.js +0 -8
- package/chunks/recall-ZNL4DJ2L.js +0 -21
- package/chunks/search-35JMSGUT.js +0 -19
|
@@ -1,32 +1,43 @@
|
|
|
1
1
|
import {
|
|
2
2
|
getDayFilePath,
|
|
3
3
|
listDayFiles
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-PZ4AQ22L.js";
|
|
5
5
|
import {
|
|
6
6
|
PRESERVATION_RATIOS,
|
|
7
7
|
RecallEngine,
|
|
8
8
|
STREAM_ORDER,
|
|
9
9
|
StreamManager
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-ARZCIITZ.js";
|
|
11
11
|
import {
|
|
12
12
|
createSession,
|
|
13
|
+
getAgentDb,
|
|
14
|
+
init_markdown_parser,
|
|
15
|
+
init_markdown_writer,
|
|
16
|
+
init_session_db,
|
|
17
|
+
init_session_store,
|
|
13
18
|
listSessions,
|
|
14
19
|
loadSession,
|
|
15
20
|
saveSession
|
|
16
|
-
} from "./chunk-
|
|
21
|
+
} from "./chunk-FEDPZOZ5.js";
|
|
17
22
|
import {
|
|
18
23
|
cosineSimilarity,
|
|
19
24
|
estimateTokens
|
|
20
|
-
} from "./chunk-
|
|
25
|
+
} from "./chunk-RVKTGKFD.js";
|
|
21
26
|
import {
|
|
22
27
|
DatabaseManager
|
|
23
|
-
} from "./chunk-
|
|
28
|
+
} from "./chunk-H46F2Y6R.js";
|
|
24
29
|
import {
|
|
25
30
|
SessionError,
|
|
26
|
-
getChitraguptaHome
|
|
27
|
-
|
|
31
|
+
getChitraguptaHome,
|
|
32
|
+
init_dist
|
|
33
|
+
} from "./chunk-KVQH4LE7.js";
|
|
28
34
|
|
|
29
|
-
// ../chitragupta/packages/smriti/
|
|
35
|
+
// ../chitragupta/packages/smriti/dist/index.js
|
|
36
|
+
init_markdown_parser();
|
|
37
|
+
init_markdown_writer();
|
|
38
|
+
init_session_store();
|
|
39
|
+
|
|
40
|
+
// ../chitragupta/packages/smriti/dist/session-export.js
|
|
30
41
|
function exportSessionToJson(session) {
|
|
31
42
|
const messages = session.turns.map((turn) => {
|
|
32
43
|
const msg = {
|
|
@@ -34,8 +45,10 @@ function exportSessionToJson(session) {
|
|
|
34
45
|
content: turn.content,
|
|
35
46
|
turnNumber: turn.turnNumber
|
|
36
47
|
};
|
|
37
|
-
if (turn.agent)
|
|
38
|
-
|
|
48
|
+
if (turn.agent)
|
|
49
|
+
msg.agent = turn.agent;
|
|
50
|
+
if (turn.model)
|
|
51
|
+
msg.model = turn.model;
|
|
39
52
|
if (turn.toolCalls && turn.toolCalls.length > 0) {
|
|
40
53
|
msg.toolCalls = turn.toolCalls.map((tc) => {
|
|
41
54
|
const exported = {
|
|
@@ -43,7 +56,8 @@ function exportSessionToJson(session) {
|
|
|
43
56
|
input: tc.input,
|
|
44
57
|
result: tc.result
|
|
45
58
|
};
|
|
46
|
-
if (tc.isError)
|
|
59
|
+
if (tc.isError)
|
|
60
|
+
exported.isError = true;
|
|
47
61
|
return exported;
|
|
48
62
|
});
|
|
49
63
|
}
|
|
@@ -157,8 +171,10 @@ function importSessionFromJson(data) {
|
|
|
157
171
|
role: msg.role,
|
|
158
172
|
content: msg.content
|
|
159
173
|
};
|
|
160
|
-
if (msg.agent)
|
|
161
|
-
|
|
174
|
+
if (msg.agent)
|
|
175
|
+
turn.agent = msg.agent;
|
|
176
|
+
if (msg.model)
|
|
177
|
+
turn.model = msg.model;
|
|
162
178
|
if (msg.toolCalls && msg.toolCalls.length > 0) {
|
|
163
179
|
turn.toolCalls = msg.toolCalls.map((tc) => {
|
|
164
180
|
const toolCall = {
|
|
@@ -166,7 +182,8 @@ function importSessionFromJson(data) {
|
|
|
166
182
|
input: tc.input,
|
|
167
183
|
result: tc.result
|
|
168
184
|
};
|
|
169
|
-
if (tc.isError)
|
|
185
|
+
if (tc.isError)
|
|
186
|
+
toolCall.isError = true;
|
|
170
187
|
return toolCall;
|
|
171
188
|
});
|
|
172
189
|
}
|
|
@@ -228,13 +245,15 @@ function validateExportedSession(data) {
|
|
|
228
245
|
}
|
|
229
246
|
}
|
|
230
247
|
|
|
231
|
-
// ../chitragupta/packages/smriti/
|
|
248
|
+
// ../chitragupta/packages/smriti/dist/cross-machine-sync.js
|
|
249
|
+
init_dist();
|
|
232
250
|
import fs2 from "node:fs";
|
|
233
251
|
import os from "node:os";
|
|
234
252
|
import path2 from "node:path";
|
|
235
253
|
import crypto2 from "node:crypto";
|
|
236
254
|
|
|
237
|
-
// ../chitragupta/packages/smriti/
|
|
255
|
+
// ../chitragupta/packages/smriti/dist/sync-import.js
|
|
256
|
+
init_dist();
|
|
238
257
|
import fs from "node:fs";
|
|
239
258
|
import path from "node:path";
|
|
240
259
|
import crypto from "node:crypto";
|
|
@@ -288,16 +307,21 @@ function splitMemory(content) {
|
|
|
288
307
|
function mergeMemory(localContent, remoteContent) {
|
|
289
308
|
const localTrimmed = localContent.trim();
|
|
290
309
|
const remoteTrimmed = remoteContent.trim();
|
|
291
|
-
if (!localTrimmed)
|
|
310
|
+
if (!localTrimmed)
|
|
311
|
+
return remoteTrimmed ? `${remoteTrimmed}
|
|
292
312
|
` : "";
|
|
293
|
-
if (!remoteTrimmed)
|
|
313
|
+
if (!remoteTrimmed)
|
|
314
|
+
return localContent.endsWith("\n") ? localContent : `${localContent}
|
|
294
315
|
`;
|
|
295
|
-
if (localContent === remoteContent)
|
|
316
|
+
if (localContent === remoteContent)
|
|
317
|
+
return localContent;
|
|
296
318
|
const local = splitMemory(localContent);
|
|
297
319
|
const remote = splitMemory(remoteContent);
|
|
298
320
|
if (local.entries.length === 0 && remote.entries.length === 0) {
|
|
299
|
-
if (localContent.includes(remoteContent))
|
|
300
|
-
|
|
321
|
+
if (localContent.includes(remoteContent))
|
|
322
|
+
return localContent;
|
|
323
|
+
if (remoteContent.includes(localContent))
|
|
324
|
+
return remoteContent;
|
|
301
325
|
return `${localContent.trimEnd()}
|
|
302
326
|
|
|
303
327
|
---
|
|
@@ -310,7 +334,8 @@ ${remoteContent.trim()}
|
|
|
310
334
|
const mergedEntries = [];
|
|
311
335
|
for (const entry of [...local.entries, ...remote.entries]) {
|
|
312
336
|
const key = sha256(entry.replace(/\s+/g, " ").trim().toLowerCase());
|
|
313
|
-
if (seen.has(key))
|
|
337
|
+
if (seen.has(key))
|
|
338
|
+
continue;
|
|
314
339
|
seen.add(key);
|
|
315
340
|
mergedEntries.push(entry.trim());
|
|
316
341
|
}
|
|
@@ -318,13 +343,15 @@ ${remoteContent.trim()}
|
|
|
318
343
|
if (mergedEntries.length > 0) {
|
|
319
344
|
merged += ENTRY_SEPARATOR + mergedEntries.join(ENTRY_SEPARATOR);
|
|
320
345
|
}
|
|
321
|
-
if (!merged.endsWith("\n"))
|
|
346
|
+
if (!merged.endsWith("\n"))
|
|
347
|
+
merged += "\n";
|
|
322
348
|
return merged;
|
|
323
349
|
}
|
|
324
350
|
function readSyncState(home) {
|
|
325
351
|
const statePath = path.join(home, "sync-state.json");
|
|
326
352
|
try {
|
|
327
|
-
if (!fs.existsSync(statePath))
|
|
353
|
+
if (!fs.existsSync(statePath))
|
|
354
|
+
return {};
|
|
328
355
|
const raw = fs.readFileSync(statePath, "utf-8");
|
|
329
356
|
const parsed = JSON.parse(raw);
|
|
330
357
|
return parsed && typeof parsed === "object" ? parsed : {};
|
|
@@ -368,7 +395,8 @@ function importCrossMachineSnapshot(source, options) {
|
|
|
368
395
|
}
|
|
369
396
|
const targetPath = resolveSnapshotPath(file.path, home);
|
|
370
397
|
if (!fs.existsSync(targetPath)) {
|
|
371
|
-
if (!dryRun)
|
|
398
|
+
if (!dryRun)
|
|
399
|
+
writeTextFile(targetPath, file.content);
|
|
372
400
|
totals.created += 1;
|
|
373
401
|
changedPaths.push(file.path);
|
|
374
402
|
continue;
|
|
@@ -384,13 +412,15 @@ function importCrossMachineSnapshot(source, options) {
|
|
|
384
412
|
totals.skipped += 1;
|
|
385
413
|
continue;
|
|
386
414
|
}
|
|
387
|
-
if (!dryRun)
|
|
415
|
+
if (!dryRun)
|
|
416
|
+
writeTextFile(targetPath, merged);
|
|
388
417
|
totals.merged += 1;
|
|
389
418
|
changedPaths.push(file.path);
|
|
390
419
|
continue;
|
|
391
420
|
}
|
|
392
421
|
if (strategy === "preferRemote") {
|
|
393
|
-
if (!dryRun)
|
|
422
|
+
if (!dryRun)
|
|
423
|
+
writeTextFile(targetPath, file.content);
|
|
394
424
|
totals.updated += 1;
|
|
395
425
|
changedPaths.push(file.path);
|
|
396
426
|
continue;
|
|
@@ -400,7 +430,8 @@ function importCrossMachineSnapshot(source, options) {
|
|
|
400
430
|
continue;
|
|
401
431
|
}
|
|
402
432
|
const conflictPath = createConflictPath(conflictRoot, file.path);
|
|
403
|
-
if (!dryRun)
|
|
433
|
+
if (!dryRun)
|
|
434
|
+
writeTextFile(conflictPath, file.content);
|
|
404
435
|
totals.conflicts += 1;
|
|
405
436
|
conflictPaths.push(toPortablePath(conflictPath, home));
|
|
406
437
|
} catch {
|
|
@@ -458,7 +489,7 @@ function assertSnapshot(value) {
|
|
|
458
489
|
}
|
|
459
490
|
}
|
|
460
491
|
|
|
461
|
-
// ../chitragupta/packages/smriti/
|
|
492
|
+
// ../chitragupta/packages/smriti/dist/cross-machine-sync.js
|
|
462
493
|
var SNAPSHOT_VERSION2 = 1;
|
|
463
494
|
function sha2562(content) {
|
|
464
495
|
return crypto2.createHash("sha256").update(content, "utf-8").digest("hex");
|
|
@@ -471,7 +502,8 @@ function toPortablePath2(absPath, home) {
|
|
|
471
502
|
return rel.split(path2.sep).join("/");
|
|
472
503
|
}
|
|
473
504
|
function listMemoryFiles(memoryRoot) {
|
|
474
|
-
if (!fs2.existsSync(memoryRoot))
|
|
505
|
+
if (!fs2.existsSync(memoryRoot))
|
|
506
|
+
return [];
|
|
475
507
|
const stack = [memoryRoot];
|
|
476
508
|
const files = [];
|
|
477
509
|
while (stack.length > 0) {
|
|
@@ -498,7 +530,8 @@ function listMemoryFiles(memoryRoot) {
|
|
|
498
530
|
function readSyncState2(home) {
|
|
499
531
|
const statePath = path2.join(home, "sync-state.json");
|
|
500
532
|
try {
|
|
501
|
-
if (!fs2.existsSync(statePath))
|
|
533
|
+
if (!fs2.existsSync(statePath))
|
|
534
|
+
return {};
|
|
502
535
|
const raw = fs2.readFileSync(statePath, "utf-8");
|
|
503
536
|
const parsed = JSON.parse(raw);
|
|
504
537
|
return parsed && typeof parsed === "object" ? parsed : {};
|
|
@@ -557,7 +590,8 @@ function createCrossMachineSnapshot(options) {
|
|
|
557
590
|
}
|
|
558
591
|
for (const date of dates) {
|
|
559
592
|
const absPath = getDayFilePath(date);
|
|
560
|
-
if (!fs2.existsSync(absPath))
|
|
593
|
+
if (!fs2.existsSync(absPath))
|
|
594
|
+
continue;
|
|
561
595
|
try {
|
|
562
596
|
const content = fs2.readFileSync(absPath, "utf-8");
|
|
563
597
|
const stat = fs2.statSync(absPath);
|
|
@@ -633,16 +667,16 @@ function getCrossMachineSyncStatus() {
|
|
|
633
667
|
};
|
|
634
668
|
}
|
|
635
669
|
|
|
636
|
-
// ../chitragupta/packages/smriti/
|
|
670
|
+
// ../chitragupta/packages/smriti/dist/branch.js
|
|
671
|
+
init_dist();
|
|
672
|
+
init_session_store();
|
|
637
673
|
function branchSession(sessionId, project, branchName, fromTurn) {
|
|
638
674
|
const original = loadSession(sessionId, project);
|
|
639
675
|
let turnsToKeep = original.turns;
|
|
640
676
|
if (fromTurn !== void 0) {
|
|
641
677
|
turnsToKeep = original.turns.filter((t) => t.turnNumber <= fromTurn);
|
|
642
678
|
if (turnsToKeep.length === 0 && original.turns.length > 0) {
|
|
643
|
-
throw new SessionError(
|
|
644
|
-
`No turns found at or before turn ${fromTurn} in session ${sessionId}`
|
|
645
|
-
);
|
|
679
|
+
throw new SessionError(`No turns found at or before turn ${fromTurn} in session ${sessionId}`);
|
|
646
680
|
}
|
|
647
681
|
}
|
|
648
682
|
const branched = createSession({
|
|
@@ -735,7 +769,7 @@ function createSyntheticRoot(project) {
|
|
|
735
769
|
};
|
|
736
770
|
}
|
|
737
771
|
|
|
738
|
-
// ../chitragupta/packages/smriti/
|
|
772
|
+
// ../chitragupta/packages/smriti/dist/sinkhorn-knopp.js
|
|
739
773
|
function sinkhornKnopp(matrix, maxIterations = 100, epsilon = 1e-6) {
|
|
740
774
|
const n = matrix.length;
|
|
741
775
|
if (n === 0) {
|
|
@@ -748,7 +782,8 @@ function sinkhornKnopp(matrix, maxIterations = 100, epsilon = 1e-6) {
|
|
|
748
782
|
const A = matrix.map((row) => [...row]);
|
|
749
783
|
for (let i = 0; i < n; i++) {
|
|
750
784
|
for (let j = 0; j < m; j++) {
|
|
751
|
-
if (A[i][j] < 0)
|
|
785
|
+
if (A[i][j] < 0)
|
|
786
|
+
A[i][j] = 0;
|
|
752
787
|
}
|
|
753
788
|
}
|
|
754
789
|
for (let i = 0; i < n; i++) {
|
|
@@ -797,7 +832,8 @@ function sinkhornKnopp(matrix, maxIterations = 100, epsilon = 1e-6) {
|
|
|
797
832
|
for (let i = 0; i < n; i++) {
|
|
798
833
|
const rowSum = A[i].reduce((s, v) => s + v, 0);
|
|
799
834
|
const dev = Math.abs(rowSum - 1);
|
|
800
|
-
if (dev > maxDeviation2)
|
|
835
|
+
if (dev > maxDeviation2)
|
|
836
|
+
maxDeviation2 = dev;
|
|
801
837
|
}
|
|
802
838
|
for (let j = 0; j < m; j++) {
|
|
803
839
|
let colSum = 0;
|
|
@@ -805,7 +841,8 @@ function sinkhornKnopp(matrix, maxIterations = 100, epsilon = 1e-6) {
|
|
|
805
841
|
colSum += A[i][j];
|
|
806
842
|
}
|
|
807
843
|
const dev = Math.abs(colSum - 1);
|
|
808
|
-
if (dev > maxDeviation2)
|
|
844
|
+
if (dev > maxDeviation2)
|
|
845
|
+
maxDeviation2 = dev;
|
|
809
846
|
}
|
|
810
847
|
if (maxDeviation2 < epsilon) {
|
|
811
848
|
converged = true;
|
|
@@ -856,7 +893,8 @@ function buildAffinityMatrix(signals) {
|
|
|
856
893
|
}
|
|
857
894
|
function computeTokenBudgets(mixingMatrix, totalBudget, preservationRatios = PRESERVATION_RATIOS) {
|
|
858
895
|
const n = mixingMatrix.length;
|
|
859
|
-
if (n === 0)
|
|
896
|
+
if (n === 0)
|
|
897
|
+
return [];
|
|
860
898
|
const weights = [];
|
|
861
899
|
for (let j = 0; j < n; j++) {
|
|
862
900
|
let colSum = 0;
|
|
@@ -879,7 +917,8 @@ function computeTokenBudgets(mixingMatrix, totalBudget, preservationRatios = PRE
|
|
|
879
917
|
let remainder = totalBudget - allocated;
|
|
880
918
|
const sortedIndices = preservationRatios.map((r, i) => ({ ratio: r, index: i })).sort((a, b) => b.ratio - a.ratio).map((x) => x.index);
|
|
881
919
|
for (const idx of sortedIndices) {
|
|
882
|
-
if (remainder <= 0)
|
|
920
|
+
if (remainder <= 0)
|
|
921
|
+
break;
|
|
883
922
|
budgets[idx] += 1;
|
|
884
923
|
remainder -= 1;
|
|
885
924
|
}
|
|
@@ -892,7 +931,7 @@ function allocateBudgets(signals, totalBudget) {
|
|
|
892
931
|
return { budgets, mixingMatrix, converged };
|
|
893
932
|
}
|
|
894
933
|
|
|
895
|
-
// ../chitragupta/packages/smriti/
|
|
934
|
+
// ../chitragupta/packages/smriti/dist/compactor-signals.js
|
|
896
935
|
var OLLAMA_ENDPOINT = process.env.OLLAMA_HOST ?? "http://localhost:11434";
|
|
897
936
|
var GENERATION_MODEL = "llama3.2";
|
|
898
937
|
function configureCompactorSignals(options) {
|
|
@@ -948,7 +987,8 @@ function keywordExtractSignals(session) {
|
|
|
948
987
|
break;
|
|
949
988
|
}
|
|
950
989
|
}
|
|
951
|
-
if (matched)
|
|
990
|
+
if (matched)
|
|
991
|
+
continue;
|
|
952
992
|
for (const pattern of PROJECT_PATTERNS) {
|
|
953
993
|
if (pattern.test(sentence)) {
|
|
954
994
|
signals.projects.push(sentence.slice(0, 200));
|
|
@@ -956,7 +996,8 @@ function keywordExtractSignals(session) {
|
|
|
956
996
|
break;
|
|
957
997
|
}
|
|
958
998
|
}
|
|
959
|
-
if (matched)
|
|
999
|
+
if (matched)
|
|
1000
|
+
continue;
|
|
960
1001
|
for (const pattern of TASK_PATTERNS) {
|
|
961
1002
|
if (pattern.test(sentence)) {
|
|
962
1003
|
signals.tasks.push(sentence.slice(0, 200));
|
|
@@ -964,7 +1005,8 @@ function keywordExtractSignals(session) {
|
|
|
964
1005
|
break;
|
|
965
1006
|
}
|
|
966
1007
|
}
|
|
967
|
-
if (matched)
|
|
1008
|
+
if (matched)
|
|
1009
|
+
continue;
|
|
968
1010
|
for (const pattern of FLOW_PATTERNS) {
|
|
969
1011
|
if (pattern.test(sentence)) {
|
|
970
1012
|
signals.flow.push(sentence.slice(0, 200));
|
|
@@ -1146,7 +1188,8 @@ function writeDeltaMarkdown(delta) {
|
|
|
1146
1188
|
return lines.join("\n");
|
|
1147
1189
|
}
|
|
1148
1190
|
|
|
1149
|
-
// ../chitragupta/packages/smriti/
|
|
1191
|
+
// ../chitragupta/packages/smriti/dist/compactor.js
|
|
1192
|
+
init_dist();
|
|
1150
1193
|
import fs3 from "fs";
|
|
1151
1194
|
import path3 from "path";
|
|
1152
1195
|
function getCompactionDir() {
|
|
@@ -1156,12 +1199,14 @@ function getDeltaDir() {
|
|
|
1156
1199
|
return path3.join(getChitraguptaHome(), "smriti", "deltas");
|
|
1157
1200
|
}
|
|
1158
1201
|
function updateIdentityStream(streamManager, signals) {
|
|
1159
|
-
if (signals.identity.length === 0)
|
|
1202
|
+
if (signals.identity.length === 0)
|
|
1203
|
+
return;
|
|
1160
1204
|
const entry = signals.identity.map((s) => `- ${s}`).join("\n");
|
|
1161
1205
|
streamManager.append("identity", entry);
|
|
1162
1206
|
}
|
|
1163
1207
|
function updateProjectsStream(streamManager, signals, session) {
|
|
1164
|
-
if (signals.projects.length === 0)
|
|
1208
|
+
if (signals.projects.length === 0)
|
|
1209
|
+
return;
|
|
1165
1210
|
const parts = [];
|
|
1166
1211
|
parts.push(`### Session: ${session.meta.title}`);
|
|
1167
1212
|
parts.push("");
|
|
@@ -1171,7 +1216,8 @@ function updateProjectsStream(streamManager, signals, session) {
|
|
|
1171
1216
|
streamManager.append("projects", parts.join("\n"));
|
|
1172
1217
|
}
|
|
1173
1218
|
function updateTasksStream(streamManager, signals) {
|
|
1174
|
-
if (signals.tasks.length === 0)
|
|
1219
|
+
if (signals.tasks.length === 0)
|
|
1220
|
+
return;
|
|
1175
1221
|
const parts = [];
|
|
1176
1222
|
const newTasks = [];
|
|
1177
1223
|
const completed = [];
|
|
@@ -1339,7 +1385,9 @@ var SessionCompactor = class {
|
|
|
1339
1385
|
const filePath = path3.join(dir, `${delta.sessionId}.md`);
|
|
1340
1386
|
const markdown = writeDeltaMarkdown(delta);
|
|
1341
1387
|
fs3.writeFileSync(filePath, markdown, "utf-8");
|
|
1342
|
-
} catch {
|
|
1388
|
+
} catch (err) {
|
|
1389
|
+
process.stderr.write(`[smriti:compactor] delta save failed: ${err instanceof Error ? err.message : String(err)}
|
|
1390
|
+
`);
|
|
1343
1391
|
}
|
|
1344
1392
|
}
|
|
1345
1393
|
saveMixingMatrix(sessionId, mixingMatrix, signals) {
|
|
@@ -1366,16 +1414,19 @@ var SessionCompactor = class {
|
|
|
1366
1414
|
};
|
|
1367
1415
|
const filePath = path3.join(dir, `${sessionId}.json`);
|
|
1368
1416
|
fs3.writeFileSync(filePath, JSON.stringify(data, null, " "), "utf-8");
|
|
1369
|
-
} catch {
|
|
1417
|
+
} catch (err) {
|
|
1418
|
+
process.stderr.write(`[smriti:compactor] mixing matrix save failed: ${err instanceof Error ? err.message : String(err)}
|
|
1419
|
+
`);
|
|
1370
1420
|
}
|
|
1371
1421
|
}
|
|
1372
1422
|
};
|
|
1373
1423
|
|
|
1374
|
-
// ../chitragupta/packages/smriti/
|
|
1424
|
+
// ../chitragupta/packages/smriti/dist/sinkhorn-budget.js
|
|
1375
1425
|
function computeTokenBudgetsMHC(chunks, totalBudget) {
|
|
1376
1426
|
const result = /* @__PURE__ */ new Map();
|
|
1377
1427
|
const n = chunks.length;
|
|
1378
|
-
if (n === 0)
|
|
1428
|
+
if (n === 0)
|
|
1429
|
+
return result;
|
|
1379
1430
|
if (n === 1) {
|
|
1380
1431
|
result.set(chunks[0].id, totalBudget);
|
|
1381
1432
|
return result;
|
|
@@ -1396,7 +1447,8 @@ function computeTokenBudgetsMHC(chunks, totalBudget) {
|
|
|
1396
1447
|
const importanceAff = Math.max(ci.importance, cj.importance);
|
|
1397
1448
|
const topicBonus = ci.topic && cj.topic && ci.topic === cj.topic ? TOPIC_BONUS : 0;
|
|
1398
1449
|
row[j] = W_RECENCY * recencyAff + W_RELEVANCE * relevanceAff + W_IMPORTANCE * importanceAff + W_TOPIC * topicBonus;
|
|
1399
|
-
if (row[j] < 1e-6)
|
|
1450
|
+
if (row[j] < 1e-6)
|
|
1451
|
+
row[j] = 1e-6;
|
|
1400
1452
|
}
|
|
1401
1453
|
affinity.push(row);
|
|
1402
1454
|
}
|
|
@@ -1413,13 +1465,15 @@ function computeTokenBudgetsMHC(chunks, totalBudget) {
|
|
|
1413
1465
|
let rawTotal = 0;
|
|
1414
1466
|
for (let i = 0; i < n; i++) {
|
|
1415
1467
|
let rowSum = 0;
|
|
1416
|
-
for (let j = 0; j < n; j++)
|
|
1468
|
+
for (let j = 0; j < n; j++)
|
|
1469
|
+
rowSum += dsMatrix[i][j];
|
|
1417
1470
|
rawBudgets[i] = rowSum * composites[i];
|
|
1418
1471
|
rawTotal += rawBudgets[i];
|
|
1419
1472
|
}
|
|
1420
1473
|
if (rawTotal === 0) {
|
|
1421
1474
|
const equal = Math.floor(totalBudget / n);
|
|
1422
|
-
for (let i = 0; i < n; i++)
|
|
1475
|
+
for (let i = 0; i < n; i++)
|
|
1476
|
+
result.set(chunks[i].id, equal);
|
|
1423
1477
|
let rem = totalBudget - equal * n;
|
|
1424
1478
|
for (let i = 0; rem > 0; i++, rem--) {
|
|
1425
1479
|
result.set(chunks[i].id, (result.get(chunks[i].id) ?? 0) + 1);
|
|
@@ -1435,7 +1489,8 @@ function computeTokenBudgetsMHC(chunks, totalBudget) {
|
|
|
1435
1489
|
let remainder = totalBudget - allocated;
|
|
1436
1490
|
const sortedIndices = composites.map((c, i) => ({ composite: c, index: i })).sort((a, b) => b.composite - a.composite).map((x) => x.index);
|
|
1437
1491
|
for (const idx of sortedIndices) {
|
|
1438
|
-
if (remainder <= 0)
|
|
1492
|
+
if (remainder <= 0)
|
|
1493
|
+
break;
|
|
1439
1494
|
const id = chunks[idx].id;
|
|
1440
1495
|
result.set(id, (result.get(id) ?? 0) + 1);
|
|
1441
1496
|
remainder--;
|
|
@@ -1443,15 +1498,19 @@ function computeTokenBudgetsMHC(chunks, totalBudget) {
|
|
|
1443
1498
|
return result;
|
|
1444
1499
|
}
|
|
1445
1500
|
|
|
1446
|
-
// ../chitragupta/packages/smriti/
|
|
1501
|
+
// ../chitragupta/packages/smriti/dist/sinkhorn-accelerated.js
|
|
1447
1502
|
function logsumexp(arr) {
|
|
1448
|
-
if (arr.length === 0)
|
|
1449
|
-
|
|
1503
|
+
if (arr.length === 0)
|
|
1504
|
+
return -Infinity;
|
|
1505
|
+
if (arr.length === 1)
|
|
1506
|
+
return arr[0];
|
|
1450
1507
|
let maxVal = -Infinity;
|
|
1451
1508
|
for (let i = 0; i < arr.length; i++) {
|
|
1452
|
-
if (arr[i] > maxVal)
|
|
1509
|
+
if (arr[i] > maxVal)
|
|
1510
|
+
maxVal = arr[i];
|
|
1453
1511
|
}
|
|
1454
|
-
if (maxVal === -Infinity)
|
|
1512
|
+
if (maxVal === -Infinity)
|
|
1513
|
+
return -Infinity;
|
|
1455
1514
|
let sumExp = 0;
|
|
1456
1515
|
for (let i = 0; i < arr.length; i++) {
|
|
1457
1516
|
sumExp += Math.exp(arr[i] - maxVal);
|
|
@@ -1483,16 +1542,20 @@ function linearSKStep(A) {
|
|
|
1483
1542
|
const m = A[0].length;
|
|
1484
1543
|
for (let i = 0; i < n; i++) {
|
|
1485
1544
|
let rowSum = 0;
|
|
1486
|
-
for (let j = 0; j < m; j++)
|
|
1545
|
+
for (let j = 0; j < m; j++)
|
|
1546
|
+
rowSum += A[i][j];
|
|
1487
1547
|
if (rowSum > 0) {
|
|
1488
|
-
for (let j = 0; j < m; j++)
|
|
1548
|
+
for (let j = 0; j < m; j++)
|
|
1549
|
+
A[i][j] /= rowSum;
|
|
1489
1550
|
}
|
|
1490
1551
|
}
|
|
1491
1552
|
for (let j = 0; j < m; j++) {
|
|
1492
1553
|
let colSum = 0;
|
|
1493
|
-
for (let i = 0; i < n; i++)
|
|
1554
|
+
for (let i = 0; i < n; i++)
|
|
1555
|
+
colSum += A[i][j];
|
|
1494
1556
|
if (colSum > 0) {
|
|
1495
|
-
for (let i = 0; i < n; i++)
|
|
1557
|
+
for (let i = 0; i < n; i++)
|
|
1558
|
+
A[i][j] /= colSum;
|
|
1496
1559
|
}
|
|
1497
1560
|
}
|
|
1498
1561
|
}
|
|
@@ -1502,15 +1565,19 @@ function maxDeviation(A) {
|
|
|
1502
1565
|
let maxDev = 0;
|
|
1503
1566
|
for (let i = 0; i < n; i++) {
|
|
1504
1567
|
let rowSum = 0;
|
|
1505
|
-
for (let j = 0; j < m; j++)
|
|
1568
|
+
for (let j = 0; j < m; j++)
|
|
1569
|
+
rowSum += A[i][j];
|
|
1506
1570
|
const dev = Math.abs(rowSum - 1);
|
|
1507
|
-
if (dev > maxDev)
|
|
1571
|
+
if (dev > maxDev)
|
|
1572
|
+
maxDev = dev;
|
|
1508
1573
|
}
|
|
1509
1574
|
for (let j = 0; j < m; j++) {
|
|
1510
1575
|
let colSum = 0;
|
|
1511
|
-
for (let i = 0; i < n; i++)
|
|
1576
|
+
for (let i = 0; i < n; i++)
|
|
1577
|
+
colSum += A[i][j];
|
|
1512
1578
|
const dev = Math.abs(colSum - 1);
|
|
1513
|
-
if (dev > maxDev)
|
|
1579
|
+
if (dev > maxDev)
|
|
1580
|
+
maxDev = dev;
|
|
1514
1581
|
}
|
|
1515
1582
|
return maxDev;
|
|
1516
1583
|
}
|
|
@@ -1547,18 +1614,25 @@ function sinkhornAccelerated(matrix, opts) {
|
|
|
1547
1614
|
const initialEps = opts?.initialEpsilon ?? 0.01;
|
|
1548
1615
|
const halvingInterval = opts?.epsilonHalvingInterval ?? 10;
|
|
1549
1616
|
const n = matrix.length;
|
|
1550
|
-
if (n === 0)
|
|
1617
|
+
if (n === 0)
|
|
1618
|
+
return { result: [], iterations: 0, converged: true };
|
|
1551
1619
|
const m = matrix[0].length;
|
|
1552
|
-
if (m === 0)
|
|
1620
|
+
if (m === 0)
|
|
1621
|
+
return { result: matrix.map(() => []), iterations: 0, converged: true };
|
|
1553
1622
|
const A = matrix.map((row) => row.map((v) => Math.max(v, 0)));
|
|
1554
1623
|
for (let i = 0; i < n; i++) {
|
|
1555
1624
|
const rowSum = A[i].reduce((s, v) => s + v, 0);
|
|
1556
|
-
if (rowSum === 0)
|
|
1625
|
+
if (rowSum === 0)
|
|
1626
|
+
for (let j = 0; j < m; j++)
|
|
1627
|
+
A[i][j] = 1 / m;
|
|
1557
1628
|
}
|
|
1558
1629
|
for (let j = 0; j < m; j++) {
|
|
1559
1630
|
let colSum = 0;
|
|
1560
|
-
for (let i = 0; i < n; i++)
|
|
1561
|
-
|
|
1631
|
+
for (let i = 0; i < n; i++)
|
|
1632
|
+
colSum += A[i][j];
|
|
1633
|
+
if (colSum === 0)
|
|
1634
|
+
for (let i = 0; i < n; i++)
|
|
1635
|
+
A[i][j] = 1 / n;
|
|
1562
1636
|
}
|
|
1563
1637
|
let currentEps = useAdaptiveEps ? initialEps : targetEpsilon;
|
|
1564
1638
|
let iterations = 0;
|
|
@@ -1594,7 +1668,8 @@ function sinkhornAccelerated(matrix, opts) {
|
|
|
1594
1668
|
const working = useNesterov ? nesterovExtrapolate(current, previous, k) : cloneMatrix(current);
|
|
1595
1669
|
for (let i = 0; i < n; i++) {
|
|
1596
1670
|
for (let j = 0; j < m; j++) {
|
|
1597
|
-
if (working[i][j] < 1e-15)
|
|
1671
|
+
if (working[i][j] < 1e-15)
|
|
1672
|
+
working[i][j] = 1e-15;
|
|
1598
1673
|
}
|
|
1599
1674
|
}
|
|
1600
1675
|
previous = cloneMatrix(current);
|
|
@@ -1609,7 +1684,7 @@ function sinkhornAccelerated(matrix, opts) {
|
|
|
1609
1684
|
return { result: current, iterations, converged };
|
|
1610
1685
|
}
|
|
1611
1686
|
|
|
1612
|
-
// ../chitragupta/packages/smriti/
|
|
1687
|
+
// ../chitragupta/packages/smriti/dist/stream-extractor.js
|
|
1613
1688
|
var IDENTITY_PATTERNS2 = [
|
|
1614
1689
|
/\bi (?:prefer|like|want|hate|always|never|use)\b/i,
|
|
1615
1690
|
/\b(?:my|our) (?:preference|style|convention|workflow|setup)\b/i,
|
|
@@ -1650,7 +1725,8 @@ var TASK_PATTERNS2 = [
|
|
|
1650
1725
|
function scorePatterns(text, patterns) {
|
|
1651
1726
|
let hits = 0;
|
|
1652
1727
|
for (const pattern of patterns) {
|
|
1653
|
-
if (pattern.test(text))
|
|
1728
|
+
if (pattern.test(text))
|
|
1729
|
+
hits++;
|
|
1654
1730
|
}
|
|
1655
1731
|
return hits;
|
|
1656
1732
|
}
|
|
@@ -1663,7 +1739,8 @@ function extractSignals(turn) {
|
|
|
1663
1739
|
};
|
|
1664
1740
|
const sentences = splitSentences(turn.content);
|
|
1665
1741
|
for (const sentence of sentences) {
|
|
1666
|
-
if (sentence.trim().length < 5)
|
|
1742
|
+
if (sentence.trim().length < 5)
|
|
1743
|
+
continue;
|
|
1667
1744
|
const identityScore = scorePatterns(sentence, IDENTITY_PATTERNS2);
|
|
1668
1745
|
const projectScore = scorePatterns(sentence, PROJECT_PATTERNS2);
|
|
1669
1746
|
const taskScore = scorePatterns(sentence, TASK_PATTERNS2);
|
|
@@ -1700,10 +1777,14 @@ function classifyContent(text) {
|
|
|
1700
1777
|
const projectScore = scorePatterns(text, PROJECT_PATTERNS2);
|
|
1701
1778
|
const taskScore = scorePatterns(text, TASK_PATTERNS2);
|
|
1702
1779
|
const maxScore = Math.max(identityScore, projectScore, taskScore);
|
|
1703
|
-
if (maxScore === 0)
|
|
1704
|
-
|
|
1705
|
-
if (
|
|
1706
|
-
|
|
1780
|
+
if (maxScore === 0)
|
|
1781
|
+
return "flow";
|
|
1782
|
+
if (identityScore === maxScore)
|
|
1783
|
+
return "identity";
|
|
1784
|
+
if (projectScore === maxScore)
|
|
1785
|
+
return "projects";
|
|
1786
|
+
if (taskScore === maxScore)
|
|
1787
|
+
return "tasks";
|
|
1707
1788
|
return "flow";
|
|
1708
1789
|
}
|
|
1709
1790
|
function extractSignalsFromTurns(turns) {
|
|
@@ -1728,11 +1809,12 @@ function splitSentences(text) {
|
|
|
1728
1809
|
return sentences;
|
|
1729
1810
|
}
|
|
1730
1811
|
|
|
1731
|
-
// ../chitragupta/packages/smriti/
|
|
1812
|
+
// ../chitragupta/packages/smriti/dist/graphrag-adaptive-scoring.js
|
|
1732
1813
|
function sampleBeta(alpha, beta) {
|
|
1733
1814
|
const x = sampleGamma(alpha);
|
|
1734
1815
|
const y = sampleGamma(beta);
|
|
1735
|
-
if (x + y === 0)
|
|
1816
|
+
if (x + y === 0)
|
|
1817
|
+
return 0.5;
|
|
1736
1818
|
return x / (x + y);
|
|
1737
1819
|
}
|
|
1738
1820
|
function sampleGamma(shape) {
|
|
@@ -1752,8 +1834,10 @@ function sampleGamma(shape) {
|
|
|
1752
1834
|
v = v * v * v;
|
|
1753
1835
|
const u = Math.random();
|
|
1754
1836
|
const zSq = z * z;
|
|
1755
|
-
if (u < 1 - 0.0331 * (zSq * zSq))
|
|
1756
|
-
|
|
1837
|
+
if (u < 1 - 0.0331 * (zSq * zSq))
|
|
1838
|
+
return d * v;
|
|
1839
|
+
if (Math.log(u) < 0.5 * zSq + d * (1 - v + Math.log(v)))
|
|
1840
|
+
return d * v;
|
|
1757
1841
|
}
|
|
1758
1842
|
}
|
|
1759
1843
|
function gaussianRandom() {
|
|
@@ -1819,7 +1903,8 @@ var AdaptiveScorer = class {
|
|
|
1819
1903
|
*/
|
|
1820
1904
|
recordFeedback(queryId, accepted) {
|
|
1821
1905
|
const dominant = this.queryDominants.get(queryId);
|
|
1822
|
-
if (!dominant)
|
|
1906
|
+
if (!dominant)
|
|
1907
|
+
return;
|
|
1823
1908
|
const record = {
|
|
1824
1909
|
timestamp: Date.now(),
|
|
1825
1910
|
accepted,
|
|
@@ -1883,7 +1968,8 @@ var AdaptiveScorer = class {
|
|
|
1883
1968
|
const rawPagerank = sampleBeta(this.pagerankAlpha, this.pagerankBeta);
|
|
1884
1969
|
const rawText = sampleBeta(this.textAlpha, this.textBeta);
|
|
1885
1970
|
const total = rawCosine + rawPagerank + rawText;
|
|
1886
|
-
if (total === 0)
|
|
1971
|
+
if (total === 0)
|
|
1972
|
+
return { ...FIXED_WEIGHTS };
|
|
1887
1973
|
return {
|
|
1888
1974
|
cosine: rawCosine / total,
|
|
1889
1975
|
pagerank: rawPagerank / total,
|
|
@@ -1927,7 +2013,8 @@ var AdaptiveScorer = class {
|
|
|
1927
2013
|
}
|
|
1928
2014
|
};
|
|
1929
2015
|
function mmrRerank(scored, lambda = 0.7, topK = 10) {
|
|
1930
|
-
if (scored.length <= 1 || topK <= 0)
|
|
2016
|
+
if (scored.length <= 1 || topK <= 0)
|
|
2017
|
+
return scored.slice(0, topK);
|
|
1931
2018
|
const k = Math.min(topK, scored.length);
|
|
1932
2019
|
const selected = [];
|
|
1933
2020
|
const remaining = [...scored];
|
|
@@ -1941,7 +2028,8 @@ function mmrRerank(scored, lambda = 0.7, topK = 10) {
|
|
|
1941
2028
|
let maxSim = 0;
|
|
1942
2029
|
for (const sel of selected) {
|
|
1943
2030
|
const sim = computeSimilarity(candidate, sel);
|
|
1944
|
-
if (sim > maxSim)
|
|
2031
|
+
if (sim > maxSim)
|
|
2032
|
+
maxSim = sim;
|
|
1945
2033
|
}
|
|
1946
2034
|
const mmr = lambda * candidate.finalScore - (1 - lambda) * maxSim;
|
|
1947
2035
|
if (mmr > bestMMR) {
|
|
@@ -1962,7 +2050,7 @@ function computeSimilarity(a, b) {
|
|
|
1962
2050
|
return Math.max(0, cosineSimilarity(vecA, vecB));
|
|
1963
2051
|
}
|
|
1964
2052
|
|
|
1965
|
-
// ../chitragupta/packages/smriti/
|
|
2053
|
+
// ../chitragupta/packages/smriti/dist/checkpoint.js
|
|
1966
2054
|
import fs4 from "node:fs";
|
|
1967
2055
|
import path4 from "node:path";
|
|
1968
2056
|
import { randomUUID } from "node:crypto";
|
|
@@ -1971,13 +2059,16 @@ var DEFAULT_INTERVAL = 3e4;
|
|
|
1971
2059
|
var DEFAULT_MAX_CHECKPOINTS = 5;
|
|
1972
2060
|
var CHECKPOINT_EXT = ".json";
|
|
1973
2061
|
function parseCheckpointFilename(filename) {
|
|
1974
|
-
if (!filename.endsWith(CHECKPOINT_EXT))
|
|
2062
|
+
if (!filename.endsWith(CHECKPOINT_EXT))
|
|
2063
|
+
return null;
|
|
1975
2064
|
const base = filename.slice(0, -CHECKPOINT_EXT.length);
|
|
1976
2065
|
const dashIdx = base.indexOf("-");
|
|
1977
|
-
if (dashIdx === -1)
|
|
2066
|
+
if (dashIdx === -1)
|
|
2067
|
+
return null;
|
|
1978
2068
|
const timestamp = Number(base.slice(0, dashIdx));
|
|
1979
2069
|
const uuid = base.slice(dashIdx + 1);
|
|
1980
|
-
if (Number.isNaN(timestamp) || !uuid)
|
|
2070
|
+
if (Number.isNaN(timestamp) || !uuid)
|
|
2071
|
+
return null;
|
|
1981
2072
|
return { timestamp, uuid };
|
|
1982
2073
|
}
|
|
1983
2074
|
var CheckpointManager = class {
|
|
@@ -2021,7 +2112,8 @@ var CheckpointManager = class {
|
|
|
2021
2112
|
*/
|
|
2022
2113
|
async load(sessionId) {
|
|
2023
2114
|
const checkpoints = this.list(sessionId);
|
|
2024
|
-
if (checkpoints.length === 0)
|
|
2115
|
+
if (checkpoints.length === 0)
|
|
2116
|
+
return null;
|
|
2025
2117
|
for (const cp of checkpoints) {
|
|
2026
2118
|
try {
|
|
2027
2119
|
const filePath = this.checkpointPath(sessionId, cp);
|
|
@@ -2042,7 +2134,8 @@ var CheckpointManager = class {
|
|
|
2042
2134
|
*/
|
|
2043
2135
|
list(sessionId) {
|
|
2044
2136
|
const sessionDir = this.sessionDir(sessionId);
|
|
2045
|
-
if (!fs4.existsSync(sessionDir))
|
|
2137
|
+
if (!fs4.existsSync(sessionDir))
|
|
2138
|
+
return [];
|
|
2046
2139
|
let entries;
|
|
2047
2140
|
try {
|
|
2048
2141
|
entries = fs4.readdirSync(sessionDir);
|
|
@@ -2051,9 +2144,11 @@ var CheckpointManager = class {
|
|
|
2051
2144
|
}
|
|
2052
2145
|
const checkpoints = [];
|
|
2053
2146
|
for (const entry of entries) {
|
|
2054
|
-
if (entry.endsWith(".tmp"))
|
|
2147
|
+
if (entry.endsWith(".tmp"))
|
|
2148
|
+
continue;
|
|
2055
2149
|
const parsed = parseCheckpointFilename(entry);
|
|
2056
|
-
if (!parsed)
|
|
2150
|
+
if (!parsed)
|
|
2151
|
+
continue;
|
|
2057
2152
|
const filePath = path4.join(sessionDir, entry);
|
|
2058
2153
|
let size = 0;
|
|
2059
2154
|
let turnCount = 0;
|
|
@@ -2097,7 +2192,8 @@ var CheckpointManager = class {
|
|
|
2097
2192
|
*/
|
|
2098
2193
|
async prune(sessionId) {
|
|
2099
2194
|
const all = this.list(sessionId);
|
|
2100
|
-
if (all.length <= this.maxCheckpoints)
|
|
2195
|
+
if (all.length <= this.maxCheckpoints)
|
|
2196
|
+
return 0;
|
|
2101
2197
|
const toRemove = all.slice(this.maxCheckpoints);
|
|
2102
2198
|
let removed = 0;
|
|
2103
2199
|
for (const cp of toRemove) {
|
|
@@ -2142,7 +2238,8 @@ var CheckpointManager = class {
|
|
|
2142
2238
|
*/
|
|
2143
2239
|
async deleteAll(sessionId) {
|
|
2144
2240
|
const sessionDir = this.sessionDir(sessionId);
|
|
2145
|
-
if (!fs4.existsSync(sessionDir))
|
|
2241
|
+
if (!fs4.existsSync(sessionDir))
|
|
2242
|
+
return;
|
|
2146
2243
|
try {
|
|
2147
2244
|
await fs4.promises.rm(sessionDir, { recursive: true, force: true });
|
|
2148
2245
|
} catch {
|
|
@@ -2157,11 +2254,12 @@ var CheckpointManager = class {
|
|
|
2157
2254
|
}
|
|
2158
2255
|
};
|
|
2159
2256
|
|
|
2160
|
-
// ../chitragupta/packages/smriti/
|
|
2257
|
+
// ../chitragupta/packages/smriti/dist/consolidation.js
|
|
2258
|
+
init_dist();
|
|
2161
2259
|
import fs5 from "fs";
|
|
2162
2260
|
import path5 from "path";
|
|
2163
2261
|
|
|
2164
|
-
// ../chitragupta/packages/smriti/
|
|
2262
|
+
// ../chitragupta/packages/smriti/dist/consolidation-phases.js
|
|
2165
2263
|
var PREFERENCE_PATTERNS = [
|
|
2166
2264
|
/\bi prefer\b/i,
|
|
2167
2265
|
/\balways use\b/i,
|
|
@@ -2255,7 +2353,8 @@ function detectToolSequences(sessions, minObservations) {
|
|
|
2255
2353
|
const ngramEvidence = /* @__PURE__ */ new Map();
|
|
2256
2354
|
for (const session of sessions) {
|
|
2257
2355
|
const toolSeq = extractToolSequence(session);
|
|
2258
|
-
if (toolSeq.length < n)
|
|
2356
|
+
if (toolSeq.length < n)
|
|
2357
|
+
continue;
|
|
2259
2358
|
const sessionNgrams = new Set(ngrams(toolSeq, n));
|
|
2260
2359
|
for (const ng of sessionNgrams) {
|
|
2261
2360
|
if (!ngramSessionCount.has(ng)) {
|
|
@@ -2263,9 +2362,7 @@ function detectToolSequences(sessions, minObservations) {
|
|
|
2263
2362
|
ngramEvidence.set(ng, []);
|
|
2264
2363
|
}
|
|
2265
2364
|
ngramSessionCount.get(ng).add(session.meta.id);
|
|
2266
|
-
ngramEvidence.get(ng).push(
|
|
2267
|
-
`Session "${session.meta.title}": ${ng}`
|
|
2268
|
-
);
|
|
2365
|
+
ngramEvidence.get(ng).push(`Session "${session.meta.title}": ${ng}`);
|
|
2269
2366
|
}
|
|
2270
2367
|
}
|
|
2271
2368
|
for (const [ng, sessionIds] of ngramSessionCount) {
|
|
@@ -2298,9 +2395,7 @@ function detectPreferences(sessions) {
|
|
|
2298
2395
|
}
|
|
2299
2396
|
const hit = preferenceHits.get(key);
|
|
2300
2397
|
hit.sessions.add(session.meta.id);
|
|
2301
|
-
hit.evidence.push(
|
|
2302
|
-
`Session "${session.meta.title}": "${sentence}"`
|
|
2303
|
-
);
|
|
2398
|
+
hit.evidence.push(`Session "${session.meta.title}": "${sentence}"`);
|
|
2304
2399
|
}
|
|
2305
2400
|
}
|
|
2306
2401
|
}
|
|
@@ -2332,9 +2427,7 @@ function detectDecisions(sessions) {
|
|
|
2332
2427
|
}
|
|
2333
2428
|
const hit = decisionHits.get(key);
|
|
2334
2429
|
hit.sessions.add(session.meta.id);
|
|
2335
|
-
hit.evidence.push(
|
|
2336
|
-
`Session "${session.meta.title}": "${sentence}"`
|
|
2337
|
-
);
|
|
2430
|
+
hit.evidence.push(`Session "${session.meta.title}": "${sentence}"`);
|
|
2338
2431
|
}
|
|
2339
2432
|
}
|
|
2340
2433
|
}
|
|
@@ -2366,9 +2459,7 @@ function detectCorrections(sessions) {
|
|
|
2366
2459
|
}
|
|
2367
2460
|
const hit = correctionHits.get(key);
|
|
2368
2461
|
hit.sessions.add(session.meta.id);
|
|
2369
|
-
hit.evidence.push(
|
|
2370
|
-
`Session "${session.meta.title}": "${sentence}"`
|
|
2371
|
-
);
|
|
2462
|
+
hit.evidence.push(`Session "${session.meta.title}": "${sentence}"`);
|
|
2372
2463
|
}
|
|
2373
2464
|
}
|
|
2374
2465
|
}
|
|
@@ -2394,7 +2485,8 @@ function detectConventions(sessions, minObservations) {
|
|
|
2394
2485
|
const fileExtCounts = /* @__PURE__ */ new Map();
|
|
2395
2486
|
for (const session of sessions) {
|
|
2396
2487
|
for (const turn of session.turns) {
|
|
2397
|
-
if (!turn.toolCalls)
|
|
2488
|
+
if (!turn.toolCalls)
|
|
2489
|
+
continue;
|
|
2398
2490
|
for (const tc of turn.toolCalls) {
|
|
2399
2491
|
const extMatch = tc.input.match(/\.([a-z]{1,5})\b/gi);
|
|
2400
2492
|
if (extMatch) {
|
|
@@ -2405,9 +2497,7 @@ function detectConventions(sessions, minObservations) {
|
|
|
2405
2497
|
}
|
|
2406
2498
|
const hit = fileExtCounts.get(extLower);
|
|
2407
2499
|
hit.sessions.add(session.meta.id);
|
|
2408
|
-
hit.evidence.push(
|
|
2409
|
-
`Session "${session.meta.title}": tool ${tc.name} used ${extLower}`
|
|
2410
|
-
);
|
|
2500
|
+
hit.evidence.push(`Session "${session.meta.title}": tool ${tc.name} used ${extLower}`);
|
|
2411
2501
|
}
|
|
2412
2502
|
}
|
|
2413
2503
|
if (tc.name === "edit" || tc.name === "write") {
|
|
@@ -2418,9 +2508,7 @@ function detectConventions(sessions, minObservations) {
|
|
|
2418
2508
|
}
|
|
2419
2509
|
const hit = conventionHits.get(importKey);
|
|
2420
2510
|
hit.sessions.add(session.meta.id);
|
|
2421
|
-
hit.evidence.push(
|
|
2422
|
-
`Session "${session.meta.title}": ${importKey} in ${tc.name} call`
|
|
2423
|
-
);
|
|
2511
|
+
hit.evidence.push(`Session "${session.meta.title}": ${importKey} in ${tc.name} call`);
|
|
2424
2512
|
}
|
|
2425
2513
|
}
|
|
2426
2514
|
}
|
|
@@ -2440,7 +2528,7 @@ function detectConventions(sessions, minObservations) {
|
|
|
2440
2528
|
return patterns;
|
|
2441
2529
|
}
|
|
2442
2530
|
|
|
2443
|
-
// ../chitragupta/packages/smriti/
|
|
2531
|
+
// ../chitragupta/packages/smriti/dist/consolidation-scoring.js
|
|
2444
2532
|
var FNV_OFFSET = 2166136261;
|
|
2445
2533
|
var FNV_PRIME = 16777619;
|
|
2446
2534
|
function fnv1a(input) {
|
|
@@ -2459,8 +2547,10 @@ function textSimilarity(a, b) {
|
|
|
2459
2547
|
const normalize = (s) => s.toLowerCase().trim().replace(/\s+/g, " ");
|
|
2460
2548
|
const na = normalize(a);
|
|
2461
2549
|
const nb = normalize(b);
|
|
2462
|
-
if (na === nb)
|
|
2463
|
-
|
|
2550
|
+
if (na === nb)
|
|
2551
|
+
return 1;
|
|
2552
|
+
if (na.length < 2 || nb.length < 2)
|
|
2553
|
+
return 0;
|
|
2464
2554
|
const bigrams = (s) => {
|
|
2465
2555
|
const map = /* @__PURE__ */ new Map();
|
|
2466
2556
|
for (let i = 0; i < s.length - 1; i++) {
|
|
@@ -2496,10 +2586,7 @@ function mergeWithExisting(candidates, allPatterns, rules) {
|
|
|
2496
2586
|
}
|
|
2497
2587
|
if (bestMatch && bestSimilarity >= SIMILARITY_THRESHOLD) {
|
|
2498
2588
|
bestMatch.observationCount += candidate.observationCount;
|
|
2499
|
-
bestMatch.confidence = Math.min(
|
|
2500
|
-
1,
|
|
2501
|
-
bestMatch.confidence + 0.1 * candidate.observationCount
|
|
2502
|
-
);
|
|
2589
|
+
bestMatch.confidence = Math.min(1, bestMatch.confidence + 0.1 * candidate.observationCount);
|
|
2503
2590
|
bestMatch.lastReinforcedAt = candidate.lastReinforcedAt;
|
|
2504
2591
|
const sessionSet = /* @__PURE__ */ new Set([
|
|
2505
2592
|
...bestMatch.sourceSessionIds,
|
|
@@ -2542,9 +2629,7 @@ function patternToRule(pattern, sessions, timestamp) {
|
|
|
2542
2629
|
};
|
|
2543
2630
|
const category = categoryMap[pattern.type];
|
|
2544
2631
|
const id = generateRuleId(category, pattern.description);
|
|
2545
|
-
const sessionIds = sessions.filter(
|
|
2546
|
-
(s) => pattern.evidence.some((e) => e.includes(s.meta.title))
|
|
2547
|
-
).map((s) => s.meta.id);
|
|
2632
|
+
const sessionIds = sessions.filter((s) => pattern.evidence.some((e) => e.includes(s.meta.title))).map((s) => s.meta.id);
|
|
2548
2633
|
return {
|
|
2549
2634
|
id,
|
|
2550
2635
|
rule: pattern.description,
|
|
@@ -2559,11 +2644,10 @@ function patternToRule(pattern, sessions, timestamp) {
|
|
|
2559
2644
|
};
|
|
2560
2645
|
}
|
|
2561
2646
|
function enforceMaxRules(rules, maxRules) {
|
|
2562
|
-
if (rules.size <= maxRules)
|
|
2647
|
+
if (rules.size <= maxRules)
|
|
2648
|
+
return;
|
|
2563
2649
|
const sorted = [...rules.entries()].sort(([, a], [, b]) => b.confidence - a.confidence);
|
|
2564
|
-
const toKeep = new Set(
|
|
2565
|
-
sorted.slice(0, maxRules).map(([id]) => id)
|
|
2566
|
-
);
|
|
2650
|
+
const toKeep = new Set(sorted.slice(0, maxRules).map(([id]) => id));
|
|
2567
2651
|
for (const id of rules.keys()) {
|
|
2568
2652
|
if (!toKeep.has(id)) {
|
|
2569
2653
|
rules.delete(id);
|
|
@@ -2571,7 +2655,7 @@ function enforceMaxRules(rules, maxRules) {
|
|
|
2571
2655
|
}
|
|
2572
2656
|
}
|
|
2573
2657
|
|
|
2574
|
-
// ../chitragupta/packages/smriti/
|
|
2658
|
+
// ../chitragupta/packages/smriti/dist/consolidation-types.js
|
|
2575
2659
|
var DEFAULT_CONFIG = {
|
|
2576
2660
|
minObservations: 2,
|
|
2577
2661
|
decayRatePerDay: 0.01,
|
|
@@ -2589,6 +2673,8 @@ var ALL_CATEGORIES = [
|
|
|
2589
2673
|
"domain-knowledge",
|
|
2590
2674
|
"relationship"
|
|
2591
2675
|
];
|
|
2676
|
+
|
|
2677
|
+
// ../chitragupta/packages/smriti/dist/consolidation.js
|
|
2592
2678
|
var ConsolidationEngine = class {
|
|
2593
2679
|
config;
|
|
2594
2680
|
rules = /* @__PURE__ */ new Map();
|
|
@@ -2629,6 +2715,7 @@ var ConsolidationEngine = class {
|
|
|
2629
2715
|
const candidateRules = allPatterns.filter((p) => p.frequency >= this.config.minObservations).map((p) => patternToRule(p, sessions, timestamp));
|
|
2630
2716
|
const { newRules, reinforcedRules, weakenedRules } = mergeWithExisting(candidateRules, allPatterns, this.rules);
|
|
2631
2717
|
enforceMaxRules(this.rules, this.config.maxRules);
|
|
2718
|
+
this.decayRules();
|
|
2632
2719
|
this.pruneRules();
|
|
2633
2720
|
const entry = {
|
|
2634
2721
|
timestamp,
|
|
@@ -2642,6 +2729,7 @@ var ConsolidationEngine = class {
|
|
|
2642
2729
|
if (this.history.length > MAX_HISTORY_ENTRIES) {
|
|
2643
2730
|
this.history = this.history.slice(-MAX_HISTORY_ENTRIES);
|
|
2644
2731
|
}
|
|
2732
|
+
this.save();
|
|
2645
2733
|
return {
|
|
2646
2734
|
newRules,
|
|
2647
2735
|
reinforcedRules,
|
|
@@ -2792,9 +2880,7 @@ var ConsolidationEngine = class {
|
|
|
2792
2880
|
}
|
|
2793
2881
|
if (fs5.existsSync(historyPath)) {
|
|
2794
2882
|
try {
|
|
2795
|
-
this.history = JSON.parse(
|
|
2796
|
-
fs5.readFileSync(historyPath, "utf-8")
|
|
2797
|
-
);
|
|
2883
|
+
this.history = JSON.parse(fs5.readFileSync(historyPath, "utf-8"));
|
|
2798
2884
|
} catch (err) {
|
|
2799
2885
|
process.stderr.write(`[consolidation] corrupted history.json, starting fresh: ${err instanceof Error ? err.message : err}
|
|
2800
2886
|
`);
|
|
@@ -2834,7 +2920,7 @@ var ConsolidationEngine = class {
|
|
|
2834
2920
|
}
|
|
2835
2921
|
};
|
|
2836
2922
|
|
|
2837
|
-
// ../chitragupta/packages/smriti/
|
|
2923
|
+
// ../chitragupta/packages/smriti/dist/query-decomposition.js
|
|
2838
2924
|
var CONJUNCTIONS = /\b(and|or|but|that|which|who|where|when|while|although)\b/i;
|
|
2839
2925
|
var TEMPORAL = /\b(when|before|after|last\s+(?:time|week|month|year|day)|yesterday|recently|earlier|previously|ago|since|until)\b/i;
|
|
2840
2926
|
var COMPARATIVE = /\b(vs\.?|versus|compared?\s+to|difference\s+between|between\s+\w+\s+and)\b/i;
|
|
@@ -2844,18 +2930,25 @@ var positionalWeight = (index) => Math.max(0.4, 1 - 0.2 * index);
|
|
|
2844
2930
|
function isComplexQuery(query) {
|
|
2845
2931
|
const trimmed = query.trim();
|
|
2846
2932
|
const words = trimmed.split(/\s+/);
|
|
2847
|
-
if (words.length > COMPLEXITY_WORD_THRESHOLD)
|
|
2848
|
-
|
|
2849
|
-
if (
|
|
2850
|
-
|
|
2933
|
+
if (words.length > COMPLEXITY_WORD_THRESHOLD)
|
|
2934
|
+
return true;
|
|
2935
|
+
if (CONJUNCTIONS.test(trimmed))
|
|
2936
|
+
return true;
|
|
2937
|
+
if (TEMPORAL.test(trimmed))
|
|
2938
|
+
return true;
|
|
2939
|
+
if (COMPARATIVE.test(trimmed))
|
|
2940
|
+
return true;
|
|
2851
2941
|
const quotedTerms = trimmed.match(/["'][^"']+["']/g);
|
|
2852
|
-
if (quotedTerms && quotedTerms.length >= 2)
|
|
2942
|
+
if (quotedTerms && quotedTerms.length >= 2)
|
|
2943
|
+
return true;
|
|
2853
2944
|
const capitalizedWords = words.slice(1).filter((w) => /^[A-Z][a-z]/.test(w));
|
|
2854
|
-
if (capitalizedWords.length >= 2)
|
|
2945
|
+
if (capitalizedWords.length >= 2)
|
|
2946
|
+
return true;
|
|
2855
2947
|
return false;
|
|
2856
2948
|
}
|
|
2857
2949
|
function clampSubQueries(subQueries, maxSubQueries) {
|
|
2858
|
-
if (subQueries.length <= maxSubQueries)
|
|
2950
|
+
if (subQueries.length <= maxSubQueries)
|
|
2951
|
+
return subQueries;
|
|
2859
2952
|
const original = subQueries[0];
|
|
2860
2953
|
const rest = subQueries.slice(1).sort((a, b) => b.weight - a.weight).slice(0, maxSubQueries - 1);
|
|
2861
2954
|
return [original, ...rest];
|
|
@@ -2863,7 +2956,8 @@ function clampSubQueries(subQueries, maxSubQueries) {
|
|
|
2863
2956
|
function extractListEntities(query) {
|
|
2864
2957
|
const listPattern = /([^,]+(?:,\s*[^,]+)*,?\s*(?:and|or)\s+[^,]+)/i;
|
|
2865
2958
|
const match = query.match(listPattern);
|
|
2866
|
-
if (!match)
|
|
2959
|
+
if (!match)
|
|
2960
|
+
return [];
|
|
2867
2961
|
const listPortion = match[1];
|
|
2868
2962
|
const entities = listPortion.split(/,\s*|\s+(?:and|or)\s+/i).map((s) => s.trim()).filter((s) => s.length >= 2);
|
|
2869
2963
|
return entities.length >= 2 ? entities : [];
|
|
@@ -2977,50 +3071,42 @@ function extractKeyTerms(query) {
|
|
|
2977
3071
|
}
|
|
2978
3072
|
function decomposeQuery(query, maxSubQueries) {
|
|
2979
3073
|
const trimmed = query.trim();
|
|
2980
|
-
if (!trimmed)
|
|
3074
|
+
if (!trimmed)
|
|
3075
|
+
return [];
|
|
2981
3076
|
const subQueries = [];
|
|
2982
3077
|
subQueries.push({
|
|
2983
3078
|
query: trimmed,
|
|
2984
3079
|
intent: "original query",
|
|
2985
3080
|
weight: 1
|
|
2986
3081
|
});
|
|
2987
|
-
if (!isComplexQuery(trimmed))
|
|
2988
|
-
|
|
2989
|
-
|
|
2990
|
-
);
|
|
3082
|
+
if (!isComplexQuery(trimmed))
|
|
3083
|
+
return subQueries;
|
|
3084
|
+
const comparativeMatch = trimmed.match(/^(.+?)\s+(?:vs\.?|versus|compared?\s+to)\s+(.+)$/i);
|
|
2991
3085
|
if (comparativeMatch) {
|
|
2992
3086
|
const [, left, right] = comparativeMatch;
|
|
2993
|
-
subQueries.push(
|
|
2994
|
-
|
|
2995
|
-
|
|
2996
|
-
|
|
2997
|
-
|
|
2998
|
-
|
|
2999
|
-
|
|
3000
|
-
|
|
3001
|
-
|
|
3002
|
-
weight: positionalWeight(subQueries.length + 1)
|
|
3003
|
-
}
|
|
3004
|
-
);
|
|
3087
|
+
subQueries.push({
|
|
3088
|
+
query: left.trim(),
|
|
3089
|
+
intent: "comparative left side",
|
|
3090
|
+
weight: positionalWeight(subQueries.length)
|
|
3091
|
+
}, {
|
|
3092
|
+
query: right.trim(),
|
|
3093
|
+
intent: "comparative right side",
|
|
3094
|
+
weight: positionalWeight(subQueries.length + 1)
|
|
3095
|
+
});
|
|
3005
3096
|
return clampSubQueries(subQueries, maxSubQueries);
|
|
3006
3097
|
}
|
|
3007
|
-
const diffBetween = trimmed.match(
|
|
3008
|
-
/difference\s+between\s+(.+?)\s+and\s+(.+)/i
|
|
3009
|
-
);
|
|
3098
|
+
const diffBetween = trimmed.match(/difference\s+between\s+(.+?)\s+and\s+(.+)/i);
|
|
3010
3099
|
if (diffBetween) {
|
|
3011
3100
|
const [, left, right] = diffBetween;
|
|
3012
|
-
subQueries.push(
|
|
3013
|
-
|
|
3014
|
-
|
|
3015
|
-
|
|
3016
|
-
|
|
3017
|
-
|
|
3018
|
-
|
|
3019
|
-
|
|
3020
|
-
|
|
3021
|
-
weight: positionalWeight(subQueries.length + 1)
|
|
3022
|
-
}
|
|
3023
|
-
);
|
|
3101
|
+
subQueries.push({
|
|
3102
|
+
query: left.trim(),
|
|
3103
|
+
intent: "comparison entity A",
|
|
3104
|
+
weight: positionalWeight(subQueries.length)
|
|
3105
|
+
}, {
|
|
3106
|
+
query: right.trim(),
|
|
3107
|
+
intent: "comparison entity B",
|
|
3108
|
+
weight: positionalWeight(subQueries.length + 1)
|
|
3109
|
+
});
|
|
3024
3110
|
return clampSubQueries(subQueries, maxSubQueries);
|
|
3025
3111
|
}
|
|
3026
3112
|
if (CAUSAL.test(trimmed)) {
|
|
@@ -3039,9 +3125,7 @@ function decomposeQuery(query, maxSubQueries) {
|
|
|
3039
3125
|
return clampSubQueries(subQueries, maxSubQueries);
|
|
3040
3126
|
}
|
|
3041
3127
|
}
|
|
3042
|
-
const listMatch = trimmed.match(
|
|
3043
|
-
/^(.*?)(\b\w+(?:\s+\w+)?)(?:,\s*(\b\w+(?:\s+\w+)?))+(?:,?\s*and\s+(\b\w+(?:\s+\w+)?))\b(.*)$/i
|
|
3044
|
-
);
|
|
3128
|
+
const listMatch = trimmed.match(/^(.*?)(\b\w+(?:\s+\w+)?)(?:,\s*(\b\w+(?:\s+\w+)?))+(?:,?\s*and\s+(\b\w+(?:\s+\w+)?))\b(.*)$/i);
|
|
3045
3129
|
if (listMatch) {
|
|
3046
3130
|
const entityParts = extractListEntities(trimmed);
|
|
3047
3131
|
if (entityParts.length >= 2) {
|
|
@@ -3075,14 +3159,14 @@ function decomposeQuery(query, maxSubQueries) {
|
|
|
3075
3159
|
function generateFollowUpQueries(originalQuery, currentResults, previousSubQueries, maxSubQueries) {
|
|
3076
3160
|
const followUps = [];
|
|
3077
3161
|
const queryTerms = extractKeyTerms(originalQuery);
|
|
3078
|
-
const previousQueryTexts = new Set(
|
|
3079
|
-
previousSubQueries.map((sq) => sq.query.toLowerCase())
|
|
3080
|
-
);
|
|
3162
|
+
const previousQueryTexts = new Set(previousSubQueries.map((sq) => sq.query.toLowerCase()));
|
|
3081
3163
|
const contentBag = currentResults.map((r) => `${r.title} ${r.content}`).join(" ").toLowerCase();
|
|
3082
3164
|
for (const term of queryTerms) {
|
|
3083
3165
|
const lowerTerm = term.toLowerCase();
|
|
3084
|
-
if (previousQueryTexts.has(lowerTerm))
|
|
3085
|
-
|
|
3166
|
+
if (previousQueryTexts.has(lowerTerm))
|
|
3167
|
+
continue;
|
|
3168
|
+
if (contentBag.includes(lowerTerm))
|
|
3169
|
+
continue;
|
|
3086
3170
|
followUps.push({
|
|
3087
3171
|
query: term,
|
|
3088
3172
|
intent: `follow-up for missing concept: ${term}`,
|
|
@@ -3090,13 +3174,10 @@ function generateFollowUpQueries(originalQuery, currentResults, previousSubQueri
|
|
|
3090
3174
|
// Follow-ups have lower weight than initial decomposition.
|
|
3091
3175
|
});
|
|
3092
3176
|
}
|
|
3093
|
-
return followUps.slice(
|
|
3094
|
-
0,
|
|
3095
|
-
Math.max(1, maxSubQueries - previousSubQueries.length)
|
|
3096
|
-
);
|
|
3177
|
+
return followUps.slice(0, Math.max(1, maxSubQueries - previousSubQueries.length));
|
|
3097
3178
|
}
|
|
3098
3179
|
|
|
3099
|
-
// ../chitragupta/packages/smriti/
|
|
3180
|
+
// ../chitragupta/packages/smriti/dist/multi-round-retrieval.js
|
|
3100
3181
|
var DEFAULT_CONFIG2 = {
|
|
3101
3182
|
maxSubQueries: 4,
|
|
3102
3183
|
maxRounds: 3,
|
|
@@ -3163,12 +3244,9 @@ var AnveshanaEngine = class {
|
|
|
3163
3244
|
previousTopScore = currentFused.length > 0 ? currentFused[0].score : 0;
|
|
3164
3245
|
let allPreviousSubQueries = [...subQueries];
|
|
3165
3246
|
for (let round = 1; round < this.config.maxRounds; round++) {
|
|
3166
|
-
const followUps = this.generateFollowUp(
|
|
3167
|
-
|
|
3168
|
-
|
|
3169
|
-
allPreviousSubQueries
|
|
3170
|
-
);
|
|
3171
|
-
if (followUps.length === 0) break;
|
|
3247
|
+
const followUps = this.generateFollowUp(query, currentFused, allPreviousSubQueries);
|
|
3248
|
+
if (followUps.length === 0)
|
|
3249
|
+
break;
|
|
3172
3250
|
const roundResults = await this.executeRound(followUps, round);
|
|
3173
3251
|
allRounds.push(...roundResults);
|
|
3174
3252
|
allPreviousSubQueries = [...allPreviousSubQueries, ...followUps];
|
|
@@ -3189,10 +3267,7 @@ var AnveshanaEngine = class {
|
|
|
3189
3267
|
previousTopScore = newTopScore;
|
|
3190
3268
|
}
|
|
3191
3269
|
const finalResults = currentFused.slice(0, this.config.maxResults);
|
|
3192
|
-
const totalRawResults = allRounds.reduce(
|
|
3193
|
-
(sum, r) => sum + r.results.length,
|
|
3194
|
-
0
|
|
3195
|
-
);
|
|
3270
|
+
const totalRawResults = allRounds.reduce((sum, r) => sum + r.results.length, 0);
|
|
3196
3271
|
this.lastStats = {
|
|
3197
3272
|
totalRounds: allRounds.length > 0 ? Math.max(...allRounds.map((r) => r.round)) + 1 : 1,
|
|
3198
3273
|
subQueriesGenerated: allPreviousSubQueries.length,
|
|
@@ -3238,12 +3313,7 @@ var AnveshanaEngine = class {
|
|
|
3238
3313
|
* @returns New sub-queries targeting unrepresented concepts.
|
|
3239
3314
|
*/
|
|
3240
3315
|
generateFollowUp(originalQuery, currentResults, previousSubQueries) {
|
|
3241
|
-
return generateFollowUpQueries(
|
|
3242
|
-
originalQuery,
|
|
3243
|
-
currentResults,
|
|
3244
|
-
previousSubQueries,
|
|
3245
|
-
this.config.maxSubQueries
|
|
3246
|
-
);
|
|
3316
|
+
return generateFollowUpQueries(originalQuery, currentResults, previousSubQueries, this.config.maxSubQueries);
|
|
3247
3317
|
}
|
|
3248
3318
|
/**
|
|
3249
3319
|
* Fuse results from multiple rounds with weighted scoring.
|
|
@@ -3268,12 +3338,10 @@ var AnveshanaEngine = class {
|
|
|
3268
3338
|
if (existing) {
|
|
3269
3339
|
existing.weightedScore += result.score * weight;
|
|
3270
3340
|
existing.foundBy.add(round.subQuery.query);
|
|
3271
|
-
existing.roundScores.push(
|
|
3272
|
-
|
|
3273
|
-
|
|
3274
|
-
|
|
3275
|
-
}))
|
|
3276
|
-
);
|
|
3341
|
+
existing.roundScores.push(...result.roundScores.map((rs) => ({
|
|
3342
|
+
query: rs.query,
|
|
3343
|
+
score: rs.score * weight
|
|
3344
|
+
})));
|
|
3277
3345
|
if (result.content.length > existing.content.length) {
|
|
3278
3346
|
existing.content = result.content;
|
|
3279
3347
|
}
|
|
@@ -3324,16 +3392,14 @@ var AnveshanaEngine = class {
|
|
|
3324
3392
|
const roundResults = [];
|
|
3325
3393
|
const tasks = subQueries.map(async (sq) => {
|
|
3326
3394
|
const hybridResults = await this.hybridSearch.search(sq.query);
|
|
3327
|
-
const multiResults = hybridResults.map(
|
|
3328
|
-
|
|
3329
|
-
|
|
3330
|
-
|
|
3331
|
-
|
|
3332
|
-
|
|
3333
|
-
|
|
3334
|
-
|
|
3335
|
-
})
|
|
3336
|
-
);
|
|
3395
|
+
const multiResults = hybridResults.map((r) => ({
|
|
3396
|
+
id: r.id,
|
|
3397
|
+
title: r.title,
|
|
3398
|
+
content: r.content,
|
|
3399
|
+
foundBy: [sq.query],
|
|
3400
|
+
score: r.score,
|
|
3401
|
+
roundScores: [{ query: sq.query, score: r.score }]
|
|
3402
|
+
}));
|
|
3337
3403
|
roundResults.push({
|
|
3338
3404
|
subQuery: sq,
|
|
3339
3405
|
results: multiResults,
|
|
@@ -3345,10 +3411,11 @@ var AnveshanaEngine = class {
|
|
|
3345
3411
|
}
|
|
3346
3412
|
};
|
|
3347
3413
|
|
|
3348
|
-
// ../chitragupta/packages/smriti/
|
|
3414
|
+
// ../chitragupta/packages/smriti/dist/smaran.js
|
|
3415
|
+
init_dist();
|
|
3349
3416
|
import path7 from "path";
|
|
3350
3417
|
|
|
3351
|
-
// ../chitragupta/packages/smriti/
|
|
3418
|
+
// ../chitragupta/packages/smriti/dist/smaran-store.js
|
|
3352
3419
|
import fs6 from "fs";
|
|
3353
3420
|
import path6 from "path";
|
|
3354
3421
|
function fnv1a2(str) {
|
|
@@ -3359,7 +3426,7 @@ function fnv1a2(str) {
|
|
|
3359
3426
|
}
|
|
3360
3427
|
return hash;
|
|
3361
3428
|
}
|
|
3362
|
-
function
|
|
3429
|
+
function tokenize(text) {
|
|
3363
3430
|
return text.toLowerCase().replace(/[^\w\s]/g, " ").split(/\s+/).filter((t) => t.length > 1);
|
|
3364
3431
|
}
|
|
3365
3432
|
function extractTags(content) {
|
|
@@ -3378,7 +3445,8 @@ function extractTags(content) {
|
|
|
3378
3445
|
[/\bschedule\b|\bcalendar\b|\bmeeting\b|\bappointment\b/, "schedule"]
|
|
3379
3446
|
];
|
|
3380
3447
|
for (const [pattern, tag] of tagPatterns) {
|
|
3381
|
-
if (pattern.test(lower))
|
|
3448
|
+
if (pattern.test(lower))
|
|
3449
|
+
tags.push(tag);
|
|
3382
3450
|
}
|
|
3383
3451
|
return tags;
|
|
3384
3452
|
}
|
|
@@ -3386,9 +3454,11 @@ function parseSimpleYaml(yaml) {
|
|
|
3386
3454
|
const result = {};
|
|
3387
3455
|
for (const line of yaml.split("\n")) {
|
|
3388
3456
|
const trimmed = line.trim();
|
|
3389
|
-
if (!trimmed || trimmed.startsWith("#"))
|
|
3457
|
+
if (!trimmed || trimmed.startsWith("#"))
|
|
3458
|
+
continue;
|
|
3390
3459
|
const colonIdx = trimmed.indexOf(":");
|
|
3391
|
-
if (colonIdx === -1)
|
|
3460
|
+
if (colonIdx === -1)
|
|
3461
|
+
continue;
|
|
3392
3462
|
const key = trimmed.slice(0, colonIdx).trim();
|
|
3393
3463
|
const rawValue = trimmed.slice(colonIdx + 1).trim();
|
|
3394
3464
|
if (rawValue.startsWith("[") && rawValue.endsWith("]")) {
|
|
@@ -3396,9 +3466,12 @@ function parseSimpleYaml(yaml) {
|
|
|
3396
3466
|
result[key] = inner.trim() === "" ? [] : inner.split(",").map((s) => s.trim());
|
|
3397
3467
|
continue;
|
|
3398
3468
|
}
|
|
3399
|
-
if (rawValue === "null" || rawValue === "~")
|
|
3400
|
-
|
|
3401
|
-
else if (rawValue === "
|
|
3469
|
+
if (rawValue === "null" || rawValue === "~")
|
|
3470
|
+
result[key] = null;
|
|
3471
|
+
else if (rawValue === "true")
|
|
3472
|
+
result[key] = true;
|
|
3473
|
+
else if (rawValue === "false")
|
|
3474
|
+
result[key] = false;
|
|
3402
3475
|
else {
|
|
3403
3476
|
const num = Number(rawValue);
|
|
3404
3477
|
result[key] = !Number.isNaN(num) && rawValue !== "" ? num : rawValue;
|
|
@@ -3407,8 +3480,10 @@ function parseSimpleYaml(yaml) {
|
|
|
3407
3480
|
return result;
|
|
3408
3481
|
}
|
|
3409
3482
|
function parseTags(value) {
|
|
3410
|
-
if (Array.isArray(value))
|
|
3411
|
-
|
|
3483
|
+
if (Array.isArray(value))
|
|
3484
|
+
return value.map(String);
|
|
3485
|
+
if (typeof value === "string")
|
|
3486
|
+
return value.split(",").map((s) => s.trim()).filter(Boolean);
|
|
3412
3487
|
return [];
|
|
3413
3488
|
}
|
|
3414
3489
|
function toSmaranMarkdown(entry) {
|
|
@@ -3421,7 +3496,8 @@ function toSmaranMarkdown(entry) {
|
|
|
3421
3496
|
lines.push(entry.tags.length > 0 ? `tags: [${entry.tags.join(", ")}]` : "tags: []");
|
|
3422
3497
|
lines.push(`created: ${entry.createdAt}`);
|
|
3423
3498
|
lines.push(`updated: ${entry.updatedAt}`);
|
|
3424
|
-
if (entry.sessionId)
|
|
3499
|
+
if (entry.sessionId)
|
|
3500
|
+
lines.push(`session: ${entry.sessionId}`);
|
|
3425
3501
|
lines.push(`decayHalfLifeDays: ${entry.decayHalfLifeDays}`);
|
|
3426
3502
|
lines.push("---");
|
|
3427
3503
|
lines.push("");
|
|
@@ -3431,12 +3507,14 @@ function toSmaranMarkdown(entry) {
|
|
|
3431
3507
|
}
|
|
3432
3508
|
function fromSmaranMarkdown(content) {
|
|
3433
3509
|
const fmMatch = content.match(/^---\n([\s\S]*?)\n---/);
|
|
3434
|
-
if (!fmMatch)
|
|
3510
|
+
if (!fmMatch)
|
|
3511
|
+
return null;
|
|
3435
3512
|
const yaml = fmMatch[1];
|
|
3436
3513
|
const body = content.slice(fmMatch[0].length).trim();
|
|
3437
3514
|
const meta = parseSimpleYaml(yaml);
|
|
3438
3515
|
const id = String(meta.id ?? "");
|
|
3439
|
-
if (!id || !body)
|
|
3516
|
+
if (!id || !body)
|
|
3517
|
+
return null;
|
|
3440
3518
|
return {
|
|
3441
3519
|
id,
|
|
3442
3520
|
content: body,
|
|
@@ -3452,13 +3530,15 @@ function fromSmaranMarkdown(content) {
|
|
|
3452
3530
|
}
|
|
3453
3531
|
function loadSmaranEntries(storagePath) {
|
|
3454
3532
|
const entries = /* @__PURE__ */ new Map();
|
|
3455
|
-
if (!fs6.existsSync(storagePath))
|
|
3533
|
+
if (!fs6.existsSync(storagePath))
|
|
3534
|
+
return entries;
|
|
3456
3535
|
const files = fs6.readdirSync(storagePath).filter((f) => f.endsWith(".md"));
|
|
3457
3536
|
for (const file of files) {
|
|
3458
3537
|
try {
|
|
3459
3538
|
const content = fs6.readFileSync(path6.join(storagePath, file), "utf-8");
|
|
3460
3539
|
const entry = fromSmaranMarkdown(content);
|
|
3461
|
-
if (entry)
|
|
3540
|
+
if (entry)
|
|
3541
|
+
entries.set(entry.id, entry);
|
|
3462
3542
|
} catch {
|
|
3463
3543
|
}
|
|
3464
3544
|
}
|
|
@@ -3472,32 +3552,37 @@ function saveSmaranEntry(storagePath, entry) {
|
|
|
3472
3552
|
function deleteSmaranFile(storagePath, id) {
|
|
3473
3553
|
const filePath = path6.join(storagePath, `${id}.md`);
|
|
3474
3554
|
try {
|
|
3475
|
-
if (fs6.existsSync(filePath))
|
|
3555
|
+
if (fs6.existsSync(filePath))
|
|
3556
|
+
fs6.unlinkSync(filePath);
|
|
3476
3557
|
} catch {
|
|
3477
3558
|
}
|
|
3478
3559
|
}
|
|
3479
3560
|
function findSimilarEntry(content, entries) {
|
|
3480
|
-
const queryTerms = new Set(
|
|
3481
|
-
if (queryTerms.size === 0)
|
|
3561
|
+
const queryTerms = new Set(tokenize(content));
|
|
3562
|
+
if (queryTerms.size === 0)
|
|
3563
|
+
return null;
|
|
3482
3564
|
for (const entry of entries) {
|
|
3483
|
-
const entryTerms = new Set(
|
|
3565
|
+
const entryTerms = new Set(tokenize(entry.content));
|
|
3484
3566
|
let overlap = 0;
|
|
3485
3567
|
for (const term of queryTerms) {
|
|
3486
|
-
if (entryTerms.has(term))
|
|
3568
|
+
if (entryTerms.has(term))
|
|
3569
|
+
overlap++;
|
|
3487
3570
|
}
|
|
3488
3571
|
const similarity = overlap / Math.max(queryTerms.size, entryTerms.size);
|
|
3489
|
-
if (similarity > 0.8)
|
|
3572
|
+
if (similarity > 0.8)
|
|
3573
|
+
return entry;
|
|
3490
3574
|
}
|
|
3491
3575
|
return null;
|
|
3492
3576
|
}
|
|
3493
3577
|
function scoreBM25Recall(entries, query, threshold) {
|
|
3494
|
-
const queryTerms =
|
|
3495
|
-
if (queryTerms.length === 0)
|
|
3578
|
+
const queryTerms = tokenize(query);
|
|
3579
|
+
if (queryTerms.length === 0)
|
|
3580
|
+
return [];
|
|
3496
3581
|
const allEntries = [];
|
|
3497
3582
|
const df = /* @__PURE__ */ new Map();
|
|
3498
3583
|
for (const entry of entries) {
|
|
3499
3584
|
allEntries.push(entry);
|
|
3500
|
-
const terms = new Set(
|
|
3585
|
+
const terms = new Set(tokenize(entry.content + " " + entry.tags.join(" ")));
|
|
3501
3586
|
for (const term of terms) {
|
|
3502
3587
|
df.set(term, (df.get(term) ?? 0) + 1);
|
|
3503
3588
|
}
|
|
@@ -3510,30 +3595,33 @@ function scoreBM25Recall(entries, query, threshold) {
|
|
|
3510
3595
|
const scored = [];
|
|
3511
3596
|
for (const entry of allEntries) {
|
|
3512
3597
|
const docText = (entry.content + " " + entry.tags.join(" ")).toLowerCase();
|
|
3513
|
-
const docTerms =
|
|
3598
|
+
const docTerms = tokenize(docText);
|
|
3514
3599
|
let bm25 = 0;
|
|
3515
3600
|
for (const qt of queryTerms) {
|
|
3516
3601
|
const termFreq = docTerms.filter((t) => t === qt).length;
|
|
3517
|
-
if (termFreq === 0)
|
|
3602
|
+
if (termFreq === 0)
|
|
3603
|
+
continue;
|
|
3518
3604
|
const docFreq = df.get(qt) ?? 0;
|
|
3519
3605
|
const idf = Math.log((N - docFreq + 0.5) / (docFreq + 0.5) + 1);
|
|
3520
3606
|
const tf = termFreq * (k1 + 1) / (termFreq + k1 * (1 - b + b * docTerms.length / avgLen));
|
|
3521
3607
|
bm25 += idf * tf;
|
|
3522
3608
|
}
|
|
3523
|
-
if (docText.includes(queryLower))
|
|
3609
|
+
if (docText.includes(queryLower))
|
|
3610
|
+
bm25 *= 1.5;
|
|
3524
3611
|
bm25 *= 0.5 + 0.5 * entry.confidence;
|
|
3525
3612
|
if (entry.decayHalfLifeDays > 0) {
|
|
3526
3613
|
const ageMs = Date.now() - new Date(entry.updatedAt).getTime();
|
|
3527
3614
|
const ageDays = ageMs / (1e3 * 60 * 60 * 24);
|
|
3528
3615
|
bm25 *= Math.exp(-Math.LN2 * ageDays / entry.decayHalfLifeDays);
|
|
3529
3616
|
}
|
|
3530
|
-
if (bm25 >= threshold)
|
|
3617
|
+
if (bm25 >= threshold)
|
|
3618
|
+
scored.push({ entry, score: bm25 });
|
|
3531
3619
|
}
|
|
3532
3620
|
scored.sort((a, b2) => b2.score - a.score);
|
|
3533
3621
|
return scored;
|
|
3534
3622
|
}
|
|
3535
3623
|
|
|
3536
|
-
// ../chitragupta/packages/smriti/
|
|
3624
|
+
// ../chitragupta/packages/smriti/dist/smaran.js
|
|
3537
3625
|
var DEFAULT_CONFIG3 = {
|
|
3538
3626
|
maxEntries: 1e3,
|
|
3539
3627
|
defaultDecayDays: 90,
|
|
@@ -3553,14 +3641,8 @@ var SmaranStore = class {
|
|
|
3553
3641
|
this.config = {
|
|
3554
3642
|
...DEFAULT_CONFIG3,
|
|
3555
3643
|
...config,
|
|
3556
|
-
maxEntries: Math.min(
|
|
3557
|
-
|
|
3558
|
-
SMARAN_HARD_CEILINGS.maxEntries
|
|
3559
|
-
),
|
|
3560
|
-
recallLimit: Math.min(
|
|
3561
|
-
config?.recallLimit ?? DEFAULT_CONFIG3.recallLimit,
|
|
3562
|
-
SMARAN_HARD_CEILINGS.recallLimit
|
|
3563
|
-
)
|
|
3644
|
+
maxEntries: Math.min(config?.maxEntries ?? DEFAULT_CONFIG3.maxEntries, SMARAN_HARD_CEILINGS.maxEntries),
|
|
3645
|
+
recallLimit: Math.min(config?.recallLimit ?? DEFAULT_CONFIG3.recallLimit, SMARAN_HARD_CEILINGS.recallLimit)
|
|
3564
3646
|
};
|
|
3565
3647
|
this.storagePath = this.config.storagePath ?? path7.join(getChitraguptaHome(), "smaran");
|
|
3566
3648
|
}
|
|
@@ -3603,7 +3685,8 @@ var SmaranStore = class {
|
|
|
3603
3685
|
/** Delete a memory by ID. Returns true if deleted. */
|
|
3604
3686
|
forget(id) {
|
|
3605
3687
|
this.ensureLoaded();
|
|
3606
|
-
if (!this.entries.has(id))
|
|
3688
|
+
if (!this.entries.has(id))
|
|
3689
|
+
return false;
|
|
3607
3690
|
this.entries.delete(id);
|
|
3608
3691
|
deleteSmaranFile(this.storagePath, id);
|
|
3609
3692
|
return true;
|
|
@@ -3614,7 +3697,8 @@ var SmaranStore = class {
|
|
|
3614
3697
|
const lower = query.toLowerCase();
|
|
3615
3698
|
const toDelete = [];
|
|
3616
3699
|
for (const [id, entry] of this.entries) {
|
|
3617
|
-
if (entry.content.toLowerCase().includes(lower))
|
|
3700
|
+
if (entry.content.toLowerCase().includes(lower))
|
|
3701
|
+
toDelete.push(id);
|
|
3618
3702
|
}
|
|
3619
3703
|
for (const id of toDelete) {
|
|
3620
3704
|
this.entries.delete(id);
|
|
@@ -3626,11 +3710,16 @@ var SmaranStore = class {
|
|
|
3626
3710
|
update(id, updates) {
|
|
3627
3711
|
this.ensureLoaded();
|
|
3628
3712
|
const entry = this.entries.get(id);
|
|
3629
|
-
if (!entry)
|
|
3630
|
-
|
|
3631
|
-
if (updates.
|
|
3632
|
-
|
|
3633
|
-
if (updates.
|
|
3713
|
+
if (!entry)
|
|
3714
|
+
return null;
|
|
3715
|
+
if (updates.content !== void 0)
|
|
3716
|
+
entry.content = updates.content;
|
|
3717
|
+
if (updates.category !== void 0)
|
|
3718
|
+
entry.category = updates.category;
|
|
3719
|
+
if (updates.tags !== void 0)
|
|
3720
|
+
entry.tags = updates.tags;
|
|
3721
|
+
if (updates.confidence !== void 0)
|
|
3722
|
+
entry.confidence = updates.confidence;
|
|
3634
3723
|
entry.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
3635
3724
|
saveSmaranEntry(this.storagePath, entry);
|
|
3636
3725
|
return entry;
|
|
@@ -3644,7 +3733,8 @@ var SmaranStore = class {
|
|
|
3644
3733
|
/** Recall memories relevant to a query using BM25-like scoring. */
|
|
3645
3734
|
recall(query, limit) {
|
|
3646
3735
|
this.ensureLoaded();
|
|
3647
|
-
if (this.entries.size === 0)
|
|
3736
|
+
if (this.entries.size === 0)
|
|
3737
|
+
return [];
|
|
3648
3738
|
const maxResults = limit ?? this.config.recallLimit;
|
|
3649
3739
|
const scored = scoreBM25Recall(this.entries.values(), query, this.config.recallThreshold);
|
|
3650
3740
|
return scored.slice(0, maxResults).map((s) => s.entry);
|
|
@@ -3654,16 +3744,15 @@ var SmaranStore = class {
|
|
|
3654
3744
|
this.ensureLoaded();
|
|
3655
3745
|
const results = [];
|
|
3656
3746
|
for (const entry of this.entries.values()) {
|
|
3657
|
-
if (entry.category === category)
|
|
3747
|
+
if (entry.category === category)
|
|
3748
|
+
results.push(entry);
|
|
3658
3749
|
}
|
|
3659
3750
|
return results.sort((a, b) => b.confidence - a.confidence);
|
|
3660
3751
|
}
|
|
3661
3752
|
/** List all entries. */
|
|
3662
3753
|
listAll() {
|
|
3663
3754
|
this.ensureLoaded();
|
|
3664
|
-
return [...this.entries.values()].sort(
|
|
3665
|
-
(a, b) => new Date(b.updatedAt).getTime() - new Date(a.updatedAt).getTime()
|
|
3666
|
-
);
|
|
3755
|
+
return [...this.entries.values()].sort((a, b) => new Date(b.updatedAt).getTime() - new Date(a.updatedAt).getTime());
|
|
3667
3756
|
}
|
|
3668
3757
|
/** Get total count of stored memories. */
|
|
3669
3758
|
get size() {
|
|
@@ -3678,9 +3767,11 @@ var SmaranStore = class {
|
|
|
3678
3767
|
*/
|
|
3679
3768
|
buildContextSection(query, maxTokens = 2e3) {
|
|
3680
3769
|
this.ensureLoaded();
|
|
3681
|
-
if (this.entries.size === 0)
|
|
3770
|
+
if (this.entries.size === 0)
|
|
3771
|
+
return "";
|
|
3682
3772
|
const entries = query ? this.recall(query, 15) : this.listAll().slice(0, 20);
|
|
3683
|
-
if (entries.length === 0)
|
|
3773
|
+
if (entries.length === 0)
|
|
3774
|
+
return "";
|
|
3684
3775
|
const sections = ["## User Memory (Smaran)", ""];
|
|
3685
3776
|
const grouped = /* @__PURE__ */ new Map();
|
|
3686
3777
|
for (const entry of entries) {
|
|
@@ -3697,10 +3788,12 @@ var SmaranStore = class {
|
|
|
3697
3788
|
};
|
|
3698
3789
|
let totalLen = 0;
|
|
3699
3790
|
for (const [category, catEntries] of grouped) {
|
|
3700
|
-
if (totalLen >= maxTokens)
|
|
3791
|
+
if (totalLen >= maxTokens)
|
|
3792
|
+
break;
|
|
3701
3793
|
sections.push(`### ${labels[category]}`);
|
|
3702
3794
|
for (const entry of catEntries) {
|
|
3703
|
-
if (totalLen >= maxTokens)
|
|
3795
|
+
if (totalLen >= maxTokens)
|
|
3796
|
+
break;
|
|
3704
3797
|
const conf = entry.source === "explicit" ? "" : ` (confidence: ${entry.confidence.toFixed(1)})`;
|
|
3705
3798
|
const line = `- ${entry.content}${conf}`;
|
|
3706
3799
|
sections.push(line);
|
|
@@ -3717,7 +3810,8 @@ var SmaranStore = class {
|
|
|
3717
3810
|
const now = Date.now();
|
|
3718
3811
|
let modified = false;
|
|
3719
3812
|
for (const entry of this.entries.values()) {
|
|
3720
|
-
if (entry.decayHalfLifeDays <= 0)
|
|
3813
|
+
if (entry.decayHalfLifeDays <= 0)
|
|
3814
|
+
continue;
|
|
3721
3815
|
const ageMs = now - new Date(entry.updatedAt).getTime();
|
|
3722
3816
|
const ageDays = ageMs / (1e3 * 60 * 60 * 24);
|
|
3723
3817
|
const decay = Math.exp(-Math.LN2 * ageDays / entry.decayHalfLifeDays);
|
|
@@ -3749,7 +3843,8 @@ var SmaranStore = class {
|
|
|
3749
3843
|
}
|
|
3750
3844
|
// ─── Internal ─────────────────────────────────────────────────────────
|
|
3751
3845
|
ensureLoaded() {
|
|
3752
|
-
if (this.loaded)
|
|
3846
|
+
if (this.loaded)
|
|
3847
|
+
return;
|
|
3753
3848
|
this.entries = loadSmaranEntries(this.storagePath);
|
|
3754
3849
|
this.loaded = true;
|
|
3755
3850
|
}
|
|
@@ -3763,7 +3858,7 @@ var SmaranStore = class {
|
|
|
3763
3858
|
}
|
|
3764
3859
|
};
|
|
3765
3860
|
|
|
3766
|
-
// ../chitragupta/packages/smriti/
|
|
3861
|
+
// ../chitragupta/packages/smriti/dist/memory-nlu.js
|
|
3767
3862
|
var REMEMBER_PATTERNS = [
|
|
3768
3863
|
{ pattern: /\bremember\s+that\s+(.+)/i, contentGroup: 1 },
|
|
3769
3864
|
{ pattern: /\bremember\s*:\s*(.+)/i, contentGroup: 1 },
|
|
@@ -3816,7 +3911,8 @@ var CATEGORY_PATTERNS = [
|
|
|
3816
3911
|
];
|
|
3817
3912
|
function detectMemoryIntent(text) {
|
|
3818
3913
|
const trimmed = text.trim();
|
|
3819
|
-
if (!trimmed)
|
|
3914
|
+
if (!trimmed)
|
|
3915
|
+
return null;
|
|
3820
3916
|
for (const pattern of FORGET_PATTERNS) {
|
|
3821
3917
|
const match = trimmed.match(pattern);
|
|
3822
3918
|
if (match) {
|
|
@@ -3848,7 +3944,8 @@ function detectMemoryIntent(text) {
|
|
|
3848
3944
|
const match = trimmed.match(pattern);
|
|
3849
3945
|
if (match) {
|
|
3850
3946
|
const content = contentGroup === 0 ? trimmed : (match[contentGroup] ?? "").trim();
|
|
3851
|
-
if (!content)
|
|
3947
|
+
if (!content)
|
|
3948
|
+
continue;
|
|
3852
3949
|
return {
|
|
3853
3950
|
action: "remember",
|
|
3854
3951
|
content: cleanContent(content),
|
|
@@ -3860,7 +3957,8 @@ function detectMemoryIntent(text) {
|
|
|
3860
3957
|
}
|
|
3861
3958
|
function detectCategory(content) {
|
|
3862
3959
|
for (const { pattern, category } of CATEGORY_PATTERNS) {
|
|
3863
|
-
if (pattern.test(content))
|
|
3960
|
+
if (pattern.test(content))
|
|
3961
|
+
return category;
|
|
3864
3962
|
}
|
|
3865
3963
|
return "fact";
|
|
3866
3964
|
}
|
|
@@ -3868,7 +3966,7 @@ function cleanContent(content) {
|
|
|
3868
3966
|
return content.replace(/[.!?]+$/, "").replace(/\s+/g, " ").trim();
|
|
3869
3967
|
}
|
|
3870
3968
|
|
|
3871
|
-
// ../chitragupta/packages/smriti/
|
|
3969
|
+
// ../chitragupta/packages/smriti/dist/identity-context.js
|
|
3872
3970
|
import fs7 from "fs";
|
|
3873
3971
|
import path8 from "path";
|
|
3874
3972
|
import os2 from "os";
|
|
@@ -3894,7 +3992,8 @@ var IdentityContext = class {
|
|
|
3894
3992
|
*/
|
|
3895
3993
|
load() {
|
|
3896
3994
|
const files = this.loadFiles();
|
|
3897
|
-
if (files.length === 0)
|
|
3995
|
+
if (files.length === 0)
|
|
3996
|
+
return "";
|
|
3898
3997
|
const sections = [];
|
|
3899
3998
|
sections.push("## Identity & Values");
|
|
3900
3999
|
sections.push("");
|
|
@@ -3918,7 +4017,8 @@ var IdentityContext = class {
|
|
|
3918
4017
|
loadUserPreferences() {
|
|
3919
4018
|
const files = this.loadFiles();
|
|
3920
4019
|
const userFile = files.find((f) => f.type === "user");
|
|
3921
|
-
if (!userFile)
|
|
4020
|
+
if (!userFile)
|
|
4021
|
+
return "";
|
|
3922
4022
|
const content = stripFrontmatter(userFile.content);
|
|
3923
4023
|
const prefSections = [];
|
|
3924
4024
|
const sectionPattern = /^##\s+(.+)$/gm;
|
|
@@ -3957,7 +4057,8 @@ var IdentityContext = class {
|
|
|
3957
4057
|
}
|
|
3958
4058
|
// ─── Internal ─────────────────────────────────────────────────────────
|
|
3959
4059
|
loadFiles() {
|
|
3960
|
-
if (this.cachedFiles)
|
|
4060
|
+
if (this.cachedFiles)
|
|
4061
|
+
return this.cachedFiles;
|
|
3961
4062
|
const include = this.config.include ?? DEFAULT_INCLUDE;
|
|
3962
4063
|
const files = [];
|
|
3963
4064
|
for (const type of include) {
|
|
@@ -3973,7 +4074,8 @@ var IdentityContext = class {
|
|
|
3973
4074
|
const explicitPath = this.config.paths?.[type];
|
|
3974
4075
|
if (explicitPath) {
|
|
3975
4076
|
const content = readFileSafe(explicitPath);
|
|
3976
|
-
if (content)
|
|
4077
|
+
if (content)
|
|
4078
|
+
return { type, path: explicitPath, content };
|
|
3977
4079
|
}
|
|
3978
4080
|
const searchDirs = this.getSearchDirs();
|
|
3979
4081
|
const fileNames = FILE_NAMES[type];
|
|
@@ -3981,7 +4083,8 @@ var IdentityContext = class {
|
|
|
3981
4083
|
for (const name of fileNames) {
|
|
3982
4084
|
const filePath = path8.join(dir, name);
|
|
3983
4085
|
const content = readFileSafe(filePath);
|
|
3984
|
-
if (content)
|
|
4086
|
+
if (content)
|
|
4087
|
+
return { type, path: filePath, content };
|
|
3985
4088
|
}
|
|
3986
4089
|
}
|
|
3987
4090
|
return null;
|
|
@@ -3993,7 +4096,8 @@ var IdentityContext = class {
|
|
|
3993
4096
|
let current = this.config.projectPath;
|
|
3994
4097
|
for (let i = 0; i < 3; i++) {
|
|
3995
4098
|
const parent = path8.dirname(current);
|
|
3996
|
-
if (parent === current)
|
|
4099
|
+
if (parent === current)
|
|
4100
|
+
break;
|
|
3997
4101
|
dirs.push(parent);
|
|
3998
4102
|
current = parent;
|
|
3999
4103
|
}
|
|
@@ -4020,7 +4124,8 @@ function readFileSafe(filePath) {
|
|
|
4020
4124
|
try {
|
|
4021
4125
|
if (fs7.existsSync(filePath)) {
|
|
4022
4126
|
const content = fs7.readFileSync(filePath, "utf-8");
|
|
4023
|
-
if (content.trim().length > 0)
|
|
4127
|
+
if (content.trim().length > 0)
|
|
4128
|
+
return content;
|
|
4024
4129
|
}
|
|
4025
4130
|
} catch {
|
|
4026
4131
|
}
|
|
@@ -4031,7 +4136,7 @@ function stripFrontmatter(content) {
|
|
|
4031
4136
|
return fmMatch ? content.slice(fmMatch[0].length) : content;
|
|
4032
4137
|
}
|
|
4033
4138
|
|
|
4034
|
-
// ../chitragupta/packages/smriti/
|
|
4139
|
+
// ../chitragupta/packages/smriti/dist/svapna-extraction.js
|
|
4035
4140
|
var FNV_OFFSET2 = 2166136261;
|
|
4036
4141
|
var FNV_PRIME2 = 16777619;
|
|
4037
4142
|
function fnv1a3(input) {
|
|
@@ -4043,7 +4148,8 @@ function fnv1a3(input) {
|
|
|
4043
4148
|
return hash.toString(16).padStart(8, "0");
|
|
4044
4149
|
}
|
|
4045
4150
|
function parseToolCalls(json) {
|
|
4046
|
-
if (!json)
|
|
4151
|
+
if (!json)
|
|
4152
|
+
return [];
|
|
4047
4153
|
try {
|
|
4048
4154
|
const parsed = JSON.parse(json);
|
|
4049
4155
|
return Array.isArray(parsed) ? parsed : [];
|
|
@@ -4056,20 +4162,24 @@ function toolNames(calls) {
|
|
|
4056
4162
|
}
|
|
4057
4163
|
function buildToolFingerprint(names) {
|
|
4058
4164
|
const fp = /* @__PURE__ */ new Set();
|
|
4059
|
-
if (names.length === 0)
|
|
4060
|
-
|
|
4165
|
+
if (names.length === 0)
|
|
4166
|
+
return fp;
|
|
4167
|
+
for (const name of names)
|
|
4168
|
+
fp.add(fnv1a3(`u:${name}`));
|
|
4061
4169
|
for (let i = 0; i < names.length - 1; i++) {
|
|
4062
4170
|
fp.add(fnv1a3(`b:${names[i]}:${names[i + 1]}`));
|
|
4063
4171
|
}
|
|
4064
4172
|
return fp;
|
|
4065
4173
|
}
|
|
4066
4174
|
function jaccardSimilarity(a, b) {
|
|
4067
|
-
if (a.size === 0 && b.size === 0)
|
|
4175
|
+
if (a.size === 0 && b.size === 0)
|
|
4176
|
+
return 0;
|
|
4068
4177
|
let intersection = 0;
|
|
4069
4178
|
const smaller = a.size <= b.size ? a : b;
|
|
4070
4179
|
const larger = a.size <= b.size ? b : a;
|
|
4071
4180
|
for (const elem of smaller) {
|
|
4072
|
-
if (larger.has(elem))
|
|
4181
|
+
if (larger.has(elem))
|
|
4182
|
+
intersection++;
|
|
4073
4183
|
}
|
|
4074
4184
|
const union = a.size + b.size - intersection;
|
|
4075
4185
|
return union > 0 ? intersection / union : 0;
|
|
@@ -4077,21 +4187,26 @@ function jaccardSimilarity(a, b) {
|
|
|
4077
4187
|
async function svapnaReplay(db, config) {
|
|
4078
4188
|
const start = performance.now();
|
|
4079
4189
|
const agentDb = db.get("agent");
|
|
4080
|
-
const sessions = agentDb.prepare(
|
|
4081
|
-
`SELECT id FROM sessions WHERE project = ? ORDER BY updated_at DESC LIMIT ?`
|
|
4082
|
-
).all(config.project, config.maxSessionsPerCycle);
|
|
4190
|
+
const sessions = agentDb.prepare(`SELECT id FROM sessions WHERE project = ? ORDER BY updated_at DESC LIMIT ?`).all(config.project, config.maxSessionsPerCycle);
|
|
4083
4191
|
if (sessions.length === 0) {
|
|
4084
4192
|
return { allTurns: [], highSurpriseTurns: [], turnsScored: 0, highSurprise: 0, durationMs: performance.now() - start };
|
|
4085
4193
|
}
|
|
4086
4194
|
const sessionIds = sessions.map((s) => s.id);
|
|
4087
4195
|
const placeholders = sessionIds.map(() => "?").join(",");
|
|
4088
|
-
const turns = agentDb.prepare(
|
|
4089
|
-
|
|
4090
|
-
|
|
4091
|
-
|
|
4196
|
+
const turns = agentDb.prepare(`SELECT id, session_id, turn_number, role, content, tool_calls, created_at
|
|
4197
|
+
FROM turns WHERE session_id IN (${placeholders}) ORDER BY created_at ASC`).all(...sessionIds);
|
|
4198
|
+
const realTurns = turns.filter((t) => {
|
|
4199
|
+
if (t.content.startsWith("[system:context]"))
|
|
4200
|
+
return false;
|
|
4201
|
+
if (t.content.startsWith("[compressed] [system:context]"))
|
|
4202
|
+
return false;
|
|
4203
|
+
if (/^\[tool:chitragupta_record_conversation\] recorded \d+/.test(t.content))
|
|
4204
|
+
return false;
|
|
4205
|
+
return true;
|
|
4206
|
+
});
|
|
4092
4207
|
const patternCounts = /* @__PURE__ */ new Map();
|
|
4093
4208
|
let totalPatterns = 0;
|
|
4094
|
-
for (const turn of
|
|
4209
|
+
for (const turn of realTurns) {
|
|
4095
4210
|
const calls = parseToolCalls(turn.tool_calls);
|
|
4096
4211
|
for (const tc of calls) {
|
|
4097
4212
|
const key = `${tc.name}:${tc.isError ? "err" : "ok"}`;
|
|
@@ -4100,7 +4215,7 @@ async function svapnaReplay(db, config) {
|
|
|
4100
4215
|
}
|
|
4101
4216
|
}
|
|
4102
4217
|
const scoredTurns = [];
|
|
4103
|
-
for (const turn of
|
|
4218
|
+
for (const turn of realTurns) {
|
|
4104
4219
|
const calls = parseToolCalls(turn.tool_calls);
|
|
4105
4220
|
let surprise = 0;
|
|
4106
4221
|
if (calls.length > 0) {
|
|
@@ -4131,7 +4246,9 @@ async function svapnaReplay(db, config) {
|
|
|
4131
4246
|
}
|
|
4132
4247
|
if (scoredTurns.length > 0) {
|
|
4133
4248
|
let maxSurprise = 0;
|
|
4134
|
-
for (const st of scoredTurns)
|
|
4249
|
+
for (const st of scoredTurns)
|
|
4250
|
+
if (st.surprise > maxSurprise)
|
|
4251
|
+
maxSurprise = st.surprise;
|
|
4135
4252
|
if (maxSurprise > 0) {
|
|
4136
4253
|
for (const st of scoredTurns) {
|
|
4137
4254
|
st.surprise /= maxSurprise;
|
|
@@ -4139,9 +4256,7 @@ async function svapnaReplay(db, config) {
|
|
|
4139
4256
|
}
|
|
4140
4257
|
}
|
|
4141
4258
|
}
|
|
4142
|
-
const highSurpriseTurns = scoredTurns.filter(
|
|
4143
|
-
(st) => st.surprise >= config.surpriseThreshold
|
|
4144
|
-
);
|
|
4259
|
+
const highSurpriseTurns = scoredTurns.filter((st) => st.surprise >= config.surpriseThreshold);
|
|
4145
4260
|
return {
|
|
4146
4261
|
allTurns: scoredTurns,
|
|
4147
4262
|
highSurpriseTurns,
|
|
@@ -4159,13 +4274,12 @@ async function svapnaRecombine(db, config, highSurpriseTurns) {
|
|
|
4159
4274
|
const sessionFingerprints = /* @__PURE__ */ new Map();
|
|
4160
4275
|
const sessions = agentDb.prepare(`SELECT id FROM sessions WHERE project = ? ORDER BY updated_at DESC LIMIT ?`).all(config.project, config.maxSessionsPerCycle);
|
|
4161
4276
|
for (const session of sessions) {
|
|
4162
|
-
const turns = agentDb.prepare(
|
|
4163
|
-
`SELECT tool_calls FROM turns
|
|
4277
|
+
const turns = agentDb.prepare(`SELECT tool_calls FROM turns
|
|
4164
4278
|
WHERE session_id = ? AND tool_calls IS NOT NULL
|
|
4165
|
-
ORDER BY turn_number ASC`
|
|
4166
|
-
).all(session.id);
|
|
4279
|
+
ORDER BY turn_number ASC`).all(session.id);
|
|
4167
4280
|
const allNames = [];
|
|
4168
|
-
for (const turn of turns)
|
|
4281
|
+
for (const turn of turns)
|
|
4282
|
+
allNames.push(...toolNames(parseToolCalls(turn.tool_calls)));
|
|
4169
4283
|
if (allNames.length > 0) {
|
|
4170
4284
|
const fp = buildToolFingerprint(allNames);
|
|
4171
4285
|
sessionFingerprints.set(session.id, {
|
|
@@ -4179,11 +4293,13 @@ async function svapnaRecombine(db, config, highSurpriseTurns) {
|
|
|
4179
4293
|
const MIN_SIMILARITY = 0.15;
|
|
4180
4294
|
for (const st of highSurpriseTurns) {
|
|
4181
4295
|
const turnToolNames = toolNames(st.toolCalls);
|
|
4182
|
-
if (turnToolNames.length === 0)
|
|
4296
|
+
if (turnToolNames.length === 0)
|
|
4297
|
+
continue;
|
|
4183
4298
|
const turnFp = buildToolFingerprint(turnToolNames);
|
|
4184
4299
|
const turnFpStr = [...turnFp].sort().join(",");
|
|
4185
4300
|
for (const [sessionId, sessionFp] of sessionFingerprints) {
|
|
4186
|
-
if (sessionId === st.sessionId)
|
|
4301
|
+
if (sessionId === st.sessionId)
|
|
4302
|
+
continue;
|
|
4187
4303
|
const sim = jaccardSimilarity(turnFp, sessionFp.fingerprint);
|
|
4188
4304
|
if (sim >= MIN_SIMILARITY) {
|
|
4189
4305
|
associations.push({
|
|
@@ -4202,7 +4318,7 @@ async function svapnaRecombine(db, config, highSurpriseTurns) {
|
|
|
4202
4318
|
return { associations, crossSessions: crossSessionPairs.size, durationMs: performance.now() - start };
|
|
4203
4319
|
}
|
|
4204
4320
|
|
|
4205
|
-
// ../chitragupta/packages/smriti/
|
|
4321
|
+
// ../chitragupta/packages/smriti/dist/svapna-rules.js
|
|
4206
4322
|
var FNV_OFFSET3 = 2166136261;
|
|
4207
4323
|
var FNV_PRIME3 = 16777619;
|
|
4208
4324
|
function fnv1a4(input) {
|
|
@@ -4217,8 +4333,10 @@ function textSimilarity2(a, b) {
|
|
|
4217
4333
|
const normalize = (s) => s.toLowerCase().trim().replace(/\s+/g, " ");
|
|
4218
4334
|
const na = normalize(a);
|
|
4219
4335
|
const nb = normalize(b);
|
|
4220
|
-
if (na === nb)
|
|
4221
|
-
|
|
4336
|
+
if (na === nb)
|
|
4337
|
+
return 1;
|
|
4338
|
+
if (na.length < 2 || nb.length < 2)
|
|
4339
|
+
return 0;
|
|
4222
4340
|
const bigrams = (s) => {
|
|
4223
4341
|
const map = /* @__PURE__ */ new Map();
|
|
4224
4342
|
for (let i = 0; i < s.length - 1; i++) {
|
|
@@ -4243,15 +4361,13 @@ async function svapnaCrystallize(db, config) {
|
|
|
4243
4361
|
const agentDb = db.get("agent");
|
|
4244
4362
|
let vasanasCreated = 0;
|
|
4245
4363
|
let vasanasReinforced = 0;
|
|
4246
|
-
const samskaras = agentDb.prepare(
|
|
4247
|
-
`SELECT id, session_id, pattern_type, pattern_content,
|
|
4364
|
+
const samskaras = agentDb.prepare(`SELECT id, session_id, pattern_type, pattern_content,
|
|
4248
4365
|
observation_count, confidence, pramana_type, project
|
|
4249
4366
|
FROM samskaras
|
|
4250
4367
|
WHERE (project = ? OR project IS NULL)
|
|
4251
4368
|
AND observation_count >= ?
|
|
4252
4369
|
AND confidence > 0.5
|
|
4253
|
-
ORDER BY confidence DESC`
|
|
4254
|
-
).all(config.project, config.minPatternFrequency);
|
|
4370
|
+
ORDER BY confidence DESC`).all(config.project, config.minPatternFrequency);
|
|
4255
4371
|
if (samskaras.length === 0) {
|
|
4256
4372
|
return { vasanasCreated: 0, vasanasReinforced: 0, durationMs: performance.now() - start };
|
|
4257
4373
|
}
|
|
@@ -4281,47 +4397,33 @@ async function svapnaCrystallize(db, config) {
|
|
|
4281
4397
|
}
|
|
4282
4398
|
const now = Date.now();
|
|
4283
4399
|
for (const cluster of clusters) {
|
|
4284
|
-
if (cluster.sessionIds.size < 2)
|
|
4400
|
+
if (cluster.sessionIds.size < 2)
|
|
4401
|
+
continue;
|
|
4285
4402
|
const tendency = slugify(cluster.representative);
|
|
4286
4403
|
const vasanaId = fnv1a4(`${tendency}:${config.project}`);
|
|
4287
4404
|
const existing = agentDb.prepare("SELECT id, strength, activation_count FROM vasanas WHERE name = ? AND (project = ? OR project IS NULL)").get(tendency, config.project);
|
|
4288
4405
|
if (existing) {
|
|
4289
4406
|
const newStrength = Math.min(1, existing.strength + 0.1);
|
|
4290
|
-
agentDb.prepare(
|
|
4291
|
-
|
|
4292
|
-
WHERE id = ?`
|
|
4293
|
-
).run(newStrength, now, existing.activation_count + 1, now, JSON.stringify(cluster.samskaraIds), existing.id);
|
|
4407
|
+
agentDb.prepare(`UPDATE vasanas SET strength = ?, last_activated = ?, activation_count = ?, updated_at = ?, source_samskaras = ?
|
|
4408
|
+
WHERE id = ?`).run(newStrength, now, existing.activation_count + 1, now, JSON.stringify(cluster.samskaraIds), existing.id);
|
|
4294
4409
|
vasanasReinforced++;
|
|
4295
4410
|
} else {
|
|
4296
4411
|
let valence = "neutral";
|
|
4297
|
-
if (cluster.patternType === "correction")
|
|
4412
|
+
if (cluster.patternType === "correction")
|
|
4413
|
+
valence = "negative";
|
|
4298
4414
|
else if (cluster.patternType === "preference" || cluster.patternType === "convention") {
|
|
4299
4415
|
valence = "positive";
|
|
4300
4416
|
}
|
|
4301
|
-
agentDb.prepare(
|
|
4302
|
-
`INSERT INTO vasanas (name, description, valence, strength, stability,
|
|
4417
|
+
agentDb.prepare(`INSERT INTO vasanas (name, description, valence, strength, stability,
|
|
4303
4418
|
source_samskaras, project, created_at, updated_at, last_activated, activation_count)
|
|
4304
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`
|
|
4305
|
-
).run(
|
|
4306
|
-
tendency,
|
|
4307
|
-
cluster.representative,
|
|
4308
|
-
valence,
|
|
4309
|
-
Math.min(1, cluster.maxConfidence),
|
|
4310
|
-
cluster.sessionIds.size / config.maxSessionsPerCycle,
|
|
4311
|
-
JSON.stringify(cluster.samskaraIds),
|
|
4312
|
-
config.project,
|
|
4313
|
-
now,
|
|
4314
|
-
now,
|
|
4315
|
-
now,
|
|
4316
|
-
1
|
|
4317
|
-
);
|
|
4419
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(tendency, cluster.representative, valence, Math.min(1, cluster.maxConfidence), cluster.sessionIds.size / config.maxSessionsPerCycle, JSON.stringify(cluster.samskaraIds), config.project, now, now, now, 1);
|
|
4318
4420
|
vasanasCreated++;
|
|
4319
4421
|
}
|
|
4320
4422
|
}
|
|
4321
4423
|
return { vasanasCreated, vasanasReinforced, durationMs: performance.now() - start };
|
|
4322
4424
|
}
|
|
4323
4425
|
|
|
4324
|
-
// ../chitragupta/packages/smriti/
|
|
4426
|
+
// ../chitragupta/packages/smriti/dist/svapna-vidhi.js
|
|
4325
4427
|
var FNV_OFFSET4 = 2166136261;
|
|
4326
4428
|
var FNV_PRIME4 = 16777619;
|
|
4327
4429
|
function fnv1a5(input) {
|
|
@@ -4344,12 +4446,14 @@ function extractNgrams(sequence, minN, maxN) {
|
|
|
4344
4446
|
return counts;
|
|
4345
4447
|
}
|
|
4346
4448
|
function antiUnify(argSets) {
|
|
4347
|
-
if (argSets.length === 0)
|
|
4449
|
+
if (argSets.length === 0)
|
|
4450
|
+
return { template: {}, params: {} };
|
|
4348
4451
|
const template = {};
|
|
4349
4452
|
const params = {};
|
|
4350
4453
|
const allKeys = /* @__PURE__ */ new Set();
|
|
4351
4454
|
for (const args of argSets) {
|
|
4352
|
-
for (const key of Object.keys(args))
|
|
4455
|
+
for (const key of Object.keys(args))
|
|
4456
|
+
allKeys.add(key);
|
|
4353
4457
|
}
|
|
4354
4458
|
for (const key of allKeys) {
|
|
4355
4459
|
const values = argSets.filter((a) => key in a).map((a) => a[key]);
|
|
@@ -4364,9 +4468,12 @@ function antiUnify(argSets) {
|
|
|
4364
4468
|
let inferredType = "string";
|
|
4365
4469
|
if (types.size === 1) {
|
|
4366
4470
|
const t = [...types][0];
|
|
4367
|
-
if (t === "number")
|
|
4368
|
-
|
|
4369
|
-
else if (t === "
|
|
4471
|
+
if (t === "number")
|
|
4472
|
+
inferredType = "number";
|
|
4473
|
+
else if (t === "boolean")
|
|
4474
|
+
inferredType = "boolean";
|
|
4475
|
+
else if (t === "object")
|
|
4476
|
+
inferredType = Array.isArray(values[0]) ? "array" : "object";
|
|
4370
4477
|
}
|
|
4371
4478
|
params[paramName] = {
|
|
4372
4479
|
name: paramName,
|
|
@@ -4380,14 +4487,15 @@ function antiUnify(argSets) {
|
|
|
4380
4487
|
return { template, params };
|
|
4381
4488
|
}
|
|
4382
4489
|
function findSubsequenceStart(sequence, sub) {
|
|
4383
|
-
if (sub.length > sequence.length)
|
|
4384
|
-
|
|
4385
|
-
|
|
4386
|
-
|
|
4387
|
-
|
|
4388
|
-
|
|
4389
|
-
return i;
|
|
4490
|
+
if (sub.length > sequence.length)
|
|
4491
|
+
return -1;
|
|
4492
|
+
outer: for (let i = 0; i <= sequence.length - sub.length; i++) {
|
|
4493
|
+
for (let j = 0; j < sub.length; j++) {
|
|
4494
|
+
if (sequence[i + j] !== sub[j])
|
|
4495
|
+
continue outer;
|
|
4390
4496
|
}
|
|
4497
|
+
return i;
|
|
4498
|
+
}
|
|
4391
4499
|
return -1;
|
|
4392
4500
|
}
|
|
4393
4501
|
function generateTriggers(tools) {
|
|
@@ -4423,10 +4531,8 @@ async function svapnaProceduralize(db, config) {
|
|
|
4423
4531
|
}
|
|
4424
4532
|
const sessionToolData = [];
|
|
4425
4533
|
for (const session of sessions) {
|
|
4426
|
-
const turns = agentDb.prepare(
|
|
4427
|
-
|
|
4428
|
-
WHERE session_id = ? AND tool_calls IS NOT NULL ORDER BY turn_number ASC`
|
|
4429
|
-
).all(session.id);
|
|
4534
|
+
const turns = agentDb.prepare(`SELECT tool_calls FROM turns
|
|
4535
|
+
WHERE session_id = ? AND tool_calls IS NOT NULL ORDER BY turn_number ASC`).all(session.id);
|
|
4430
4536
|
const names = [];
|
|
4431
4537
|
const calls = [];
|
|
4432
4538
|
let totalCalls = 0;
|
|
@@ -4437,7 +4543,8 @@ async function svapnaProceduralize(db, config) {
|
|
|
4437
4543
|
names.push(tc.name);
|
|
4438
4544
|
calls.push([tc]);
|
|
4439
4545
|
totalCalls++;
|
|
4440
|
-
if (tc.isError)
|
|
4546
|
+
if (tc.isError)
|
|
4547
|
+
errorCalls++;
|
|
4441
4548
|
}
|
|
4442
4549
|
}
|
|
4443
4550
|
if (names.length >= config.minSequenceLength) {
|
|
@@ -4470,7 +4577,8 @@ async function svapnaProceduralize(db, config) {
|
|
|
4470
4577
|
if (startIdx >= 0) {
|
|
4471
4578
|
const args = [];
|
|
4472
4579
|
for (let i = 0; i < ngramToolNames.length; i++) {
|
|
4473
|
-
if (startIdx + i >= sd.calls.length)
|
|
4580
|
+
if (startIdx + i >= sd.calls.length)
|
|
4581
|
+
break;
|
|
4474
4582
|
const callGroup = sd.calls[startIdx + i];
|
|
4475
4583
|
if (callGroup && callGroup.length > 0) {
|
|
4476
4584
|
try {
|
|
@@ -4489,15 +4597,18 @@ async function svapnaProceduralize(db, config) {
|
|
|
4489
4597
|
}
|
|
4490
4598
|
const now = Date.now();
|
|
4491
4599
|
for (const [ngramKey, entry] of ngramIndex) {
|
|
4492
|
-
if (entry.sessionIds.size < 3)
|
|
4600
|
+
if (entry.sessionIds.size < 3)
|
|
4601
|
+
continue;
|
|
4493
4602
|
const avgSuccess = entry.successRates.reduce((s, r) => s + r, 0) / entry.successRates.length;
|
|
4494
|
-
if (avgSuccess < config.minSuccessRate)
|
|
4603
|
+
if (avgSuccess < config.minSuccessRate)
|
|
4604
|
+
continue;
|
|
4495
4605
|
const steps = [];
|
|
4496
4606
|
const allParams = {};
|
|
4497
4607
|
for (let pos = 0; pos < entry.toolNames.length; pos++) {
|
|
4498
4608
|
const posArgs = [];
|
|
4499
4609
|
for (const argSet of entry.argSets) {
|
|
4500
|
-
if (argSet[pos])
|
|
4610
|
+
if (argSet[pos])
|
|
4611
|
+
posArgs.push(argSet[pos]);
|
|
4501
4612
|
}
|
|
4502
4613
|
const { template, params } = antiUnify(posArgs);
|
|
4503
4614
|
for (const [pName, pDef] of Object.entries(params)) {
|
|
@@ -4506,7 +4617,8 @@ async function svapnaProceduralize(db, config) {
|
|
|
4506
4617
|
const oldRef = `\${${pName}}`;
|
|
4507
4618
|
const newRef = `\${${qualifiedName}}`;
|
|
4508
4619
|
for (const key of Object.keys(template)) {
|
|
4509
|
-
if (template[key] === oldRef)
|
|
4620
|
+
if (template[key] === oldRef)
|
|
4621
|
+
template[key] = newRef;
|
|
4510
4622
|
}
|
|
4511
4623
|
}
|
|
4512
4624
|
steps.push({
|
|
@@ -4520,7 +4632,8 @@ async function svapnaProceduralize(db, config) {
|
|
|
4520
4632
|
const vidhiName = slugify(ngramKey.replace(/ -> /g, "-then-"));
|
|
4521
4633
|
const vidhiId = fnv1a5(`${vidhiName}:${config.project}`);
|
|
4522
4634
|
const existing = agentDb.prepare("SELECT id FROM vidhis WHERE id = ?").get(vidhiId);
|
|
4523
|
-
if (existing)
|
|
4635
|
+
if (existing)
|
|
4636
|
+
continue;
|
|
4524
4637
|
const vidhi = {
|
|
4525
4638
|
id: vidhiId,
|
|
4526
4639
|
project: config.project,
|
|
@@ -4536,33 +4649,17 @@ async function svapnaProceduralize(db, config) {
|
|
|
4536
4649
|
createdAt: now,
|
|
4537
4650
|
updatedAt: now
|
|
4538
4651
|
};
|
|
4539
|
-
agentDb.prepare(
|
|
4540
|
-
`INSERT OR IGNORE INTO vidhis
|
|
4652
|
+
agentDb.prepare(`INSERT OR IGNORE INTO vidhis
|
|
4541
4653
|
(id, project, name, learned_from, confidence, steps, triggers,
|
|
4542
4654
|
success_rate, success_count, failure_count, parameter_schema,
|
|
4543
4655
|
created_at, updated_at)
|
|
4544
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`
|
|
4545
|
-
).run(
|
|
4546
|
-
vidhi.id,
|
|
4547
|
-
vidhi.project,
|
|
4548
|
-
vidhi.name,
|
|
4549
|
-
JSON.stringify(vidhi.learnedFrom),
|
|
4550
|
-
vidhi.confidence,
|
|
4551
|
-
JSON.stringify(vidhi.steps),
|
|
4552
|
-
JSON.stringify(vidhi.triggers),
|
|
4553
|
-
vidhi.successRate,
|
|
4554
|
-
vidhi.successCount,
|
|
4555
|
-
vidhi.failureCount,
|
|
4556
|
-
JSON.stringify(vidhi.parameterSchema),
|
|
4557
|
-
vidhi.createdAt,
|
|
4558
|
-
vidhi.updatedAt
|
|
4559
|
-
);
|
|
4656
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(vidhi.id, vidhi.project, vidhi.name, JSON.stringify(vidhi.learnedFrom), vidhi.confidence, JSON.stringify(vidhi.steps), JSON.stringify(vidhi.triggers), vidhi.successRate, vidhi.successCount, vidhi.failureCount, JSON.stringify(vidhi.parameterSchema), vidhi.createdAt, vidhi.updatedAt);
|
|
4560
4657
|
createdVidhis.push(vidhi);
|
|
4561
4658
|
}
|
|
4562
4659
|
return { vidhisCreated: createdVidhis.length, vidhis: createdVidhis, durationMs: performance.now() - start };
|
|
4563
4660
|
}
|
|
4564
4661
|
|
|
4565
|
-
// ../chitragupta/packages/smriti/
|
|
4662
|
+
// ../chitragupta/packages/smriti/dist/svapna-types.js
|
|
4566
4663
|
var DEFAULT_CONFIG4 = {
|
|
4567
4664
|
maxSessionsPerCycle: 50,
|
|
4568
4665
|
surpriseThreshold: 0.7,
|
|
@@ -4579,6 +4676,8 @@ var PRAMANA_PRESERVATION = {
|
|
|
4579
4676
|
arthapatti: 0.4,
|
|
4580
4677
|
anupalabdhi: 0.25
|
|
4581
4678
|
};
|
|
4679
|
+
|
|
4680
|
+
// ../chitragupta/packages/smriti/dist/svapna-consolidation.js
|
|
4582
4681
|
var SvapnaConsolidation = class {
|
|
4583
4682
|
config;
|
|
4584
4683
|
db;
|
|
@@ -4606,54 +4705,41 @@ var SvapnaConsolidation = class {
|
|
|
4606
4705
|
const report = onProgress ?? (() => {
|
|
4607
4706
|
});
|
|
4608
4707
|
this.logCycle("running");
|
|
4609
|
-
|
|
4610
|
-
|
|
4611
|
-
|
|
4612
|
-
|
|
4613
|
-
|
|
4614
|
-
|
|
4615
|
-
|
|
4616
|
-
|
|
4617
|
-
|
|
4618
|
-
|
|
4619
|
-
|
|
4620
|
-
|
|
4621
|
-
|
|
4622
|
-
|
|
4623
|
-
|
|
4624
|
-
|
|
4625
|
-
|
|
4626
|
-
|
|
4627
|
-
|
|
4628
|
-
turnsScored: replayResult.turnsScored,
|
|
4629
|
-
|
|
4630
|
-
durationMs:
|
|
4631
|
-
|
|
4632
|
-
|
|
4633
|
-
associations: recombineResult.associations.length,
|
|
4634
|
-
crossSessions: recombineResult.crossSessions,
|
|
4635
|
-
durationMs: recombineResult.durationMs
|
|
4636
|
-
},
|
|
4637
|
-
crystallize: {
|
|
4638
|
-
vasanasCreated: crystallizeResult.vasanasCreated,
|
|
4639
|
-
vasanasReinforced: crystallizeResult.vasanasReinforced,
|
|
4640
|
-
durationMs: crystallizeResult.durationMs
|
|
4641
|
-
},
|
|
4642
|
-
proceduralize: {
|
|
4643
|
-
vidhisCreated: proceduralizeResult.vidhisCreated,
|
|
4644
|
-
durationMs: proceduralizeResult.durationMs
|
|
4708
|
+
try {
|
|
4709
|
+
report("REPLAY", 0);
|
|
4710
|
+
const replayResult = await this.replay();
|
|
4711
|
+
report("REPLAY", 1);
|
|
4712
|
+
report("RECOMBINE", 0);
|
|
4713
|
+
const recombineResult = await this.recombine(replayResult.highSurpriseTurns);
|
|
4714
|
+
report("RECOMBINE", 1);
|
|
4715
|
+
report("CRYSTALLIZE", 0);
|
|
4716
|
+
const crystallizeResult = await this.crystallize();
|
|
4717
|
+
report("CRYSTALLIZE", 1);
|
|
4718
|
+
report("PROCEDURALIZE", 0);
|
|
4719
|
+
const proceduralizeResult = await this.proceduralize();
|
|
4720
|
+
report("PROCEDURALIZE", 1);
|
|
4721
|
+
report("COMPRESS", 0);
|
|
4722
|
+
const compressResult = await this.compress();
|
|
4723
|
+
report("COMPRESS", 1);
|
|
4724
|
+
const totalDurationMs = performance.now() - cycleStart;
|
|
4725
|
+
const result = {
|
|
4726
|
+
phases: {
|
|
4727
|
+
replay: { turnsScored: replayResult.turnsScored, highSurprise: replayResult.highSurprise, durationMs: replayResult.durationMs },
|
|
4728
|
+
recombine: { associations: recombineResult.associations.length, crossSessions: recombineResult.crossSessions, durationMs: recombineResult.durationMs },
|
|
4729
|
+
crystallize: { vasanasCreated: crystallizeResult.vasanasCreated, vasanasReinforced: crystallizeResult.vasanasReinforced, durationMs: crystallizeResult.durationMs },
|
|
4730
|
+
proceduralize: { vidhisCreated: proceduralizeResult.vidhisCreated, durationMs: proceduralizeResult.durationMs },
|
|
4731
|
+
compress: { tokensCompressed: compressResult.tokensCompressed, compressionRatio: compressResult.compressionRatio, durationMs: compressResult.durationMs }
|
|
4645
4732
|
},
|
|
4646
|
-
|
|
4647
|
-
|
|
4648
|
-
|
|
4649
|
-
|
|
4650
|
-
|
|
4651
|
-
|
|
4652
|
-
|
|
4653
|
-
|
|
4654
|
-
|
|
4655
|
-
|
|
4656
|
-
return result;
|
|
4733
|
+
totalDurationMs,
|
|
4734
|
+
cycleId: this.cycleId
|
|
4735
|
+
};
|
|
4736
|
+
this.logCycle("success", result);
|
|
4737
|
+
return result;
|
|
4738
|
+
} catch (err) {
|
|
4739
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
4740
|
+
this.logCycle("failed");
|
|
4741
|
+
throw new Error(`Svapna cycle ${this.cycleId} failed: ${msg}`, { cause: err });
|
|
4742
|
+
}
|
|
4657
4743
|
}
|
|
4658
4744
|
// ── Phase Delegates ─────────────────────────────────────────────────
|
|
4659
4745
|
/** Phase 1: Hippocampal replay — score turns by surprise. */
|
|
@@ -4687,10 +4773,8 @@ var SvapnaConsolidation = class {
|
|
|
4687
4773
|
}
|
|
4688
4774
|
const sessionIds = sessions.map((s) => s.id);
|
|
4689
4775
|
const placeholders = sessionIds.map(() => "?").join(",");
|
|
4690
|
-
const turns = agentDb.prepare(
|
|
4691
|
-
|
|
4692
|
-
FROM turns WHERE session_id IN (${placeholders}) ORDER BY created_at ASC`
|
|
4693
|
-
).all(...sessionIds);
|
|
4776
|
+
const turns = agentDb.prepare(`SELECT id, session_id, content, tool_calls, created_at
|
|
4777
|
+
FROM turns WHERE session_id IN (${placeholders}) ORDER BY created_at ASC`).all(...sessionIds);
|
|
4694
4778
|
if (turns.length === 0) {
|
|
4695
4779
|
return { tokensCompressed: 0, compressionRatio: 1, durationMs: performance.now() - start };
|
|
4696
4780
|
}
|
|
@@ -4699,6 +4783,8 @@ var SvapnaConsolidation = class {
|
|
|
4699
4783
|
const maxAge = 30 * 24 * 60 * 60 * 1e3;
|
|
4700
4784
|
let totalOriginalTokens = 0;
|
|
4701
4785
|
for (const turn of turns) {
|
|
4786
|
+
if (this.isNoiseTurn(turn.content))
|
|
4787
|
+
continue;
|
|
4702
4788
|
const tokens = estimateTokens(turn.content);
|
|
4703
4789
|
totalOriginalTokens += tokens;
|
|
4704
4790
|
const calls = parseToolCalls(turn.tool_calls);
|
|
@@ -4717,6 +4803,13 @@ var SvapnaConsolidation = class {
|
|
|
4717
4803
|
if (chunks.length < 2) {
|
|
4718
4804
|
return { tokensCompressed: totalOriginalTokens, compressionRatio: 1, durationMs: performance.now() - start };
|
|
4719
4805
|
}
|
|
4806
|
+
const { compressedTotal } = this.applyCompression(chunks, turns, totalOriginalTokens);
|
|
4807
|
+
const compressionRatio = totalOriginalTokens > 0 ? compressedTotal / totalOriginalTokens : 1;
|
|
4808
|
+
return { tokensCompressed: totalOriginalTokens, compressionRatio, durationMs: performance.now() - start };
|
|
4809
|
+
}
|
|
4810
|
+
// ─── Private Helpers ──────────────────────────────────────────────────
|
|
4811
|
+
/** Build affinity matrix, run Sinkhorn, compute budgets, and write compressed content. */
|
|
4812
|
+
applyCompression(chunks, turns, totalOriginalTokens) {
|
|
4720
4813
|
const n = chunks.length;
|
|
4721
4814
|
const affinity = [];
|
|
4722
4815
|
for (let i = 0; i < n; i++) {
|
|
@@ -4734,69 +4827,123 @@ var SvapnaConsolidation = class {
|
|
|
4734
4827
|
const rawBudgets = new Array(n);
|
|
4735
4828
|
for (let i = 0; i < n; i++) {
|
|
4736
4829
|
let rowSum = 0;
|
|
4737
|
-
for (let j = 0; j < n; j++)
|
|
4830
|
+
for (let j = 0; j < n; j++)
|
|
4831
|
+
rowSum += dsMatrix[i][j];
|
|
4738
4832
|
rawBudgets[i] = rowSum * chunks[i].relevance;
|
|
4739
4833
|
budgetTotal += rawBudgets[i];
|
|
4740
4834
|
}
|
|
4741
4835
|
const targetTokens = Math.floor(totalOriginalTokens * 0.7);
|
|
4742
4836
|
let compressedTotal = 0;
|
|
4743
|
-
|
|
4837
|
+
const agentDb = this.db.get("agent");
|
|
4838
|
+
const updateStmt = agentDb.prepare(`UPDATE turns SET content = ? WHERE id = ?`);
|
|
4839
|
+
const insertRuleStmt = agentDb.prepare(`INSERT INTO consolidation_rules
|
|
4840
|
+
(project, category, rule_text, source_sessions, confidence, created_at, updated_at)
|
|
4841
|
+
VALUES (?, 'abstraction', ?, ?, ?, ?, ?)`);
|
|
4842
|
+
const compressBatch = agentDb.transaction(() => {
|
|
4744
4843
|
for (let i = 0; i < n; i++) {
|
|
4745
|
-
const budget = Math.floor(rawBudgets[i] / budgetTotal * targetTokens);
|
|
4746
|
-
|
|
4844
|
+
const budget = budgetTotal > 0 ? Math.floor(rawBudgets[i] / budgetTotal * targetTokens) : Math.floor(targetTokens / n);
|
|
4845
|
+
const turnTokens = chunks[i].tokenCount;
|
|
4846
|
+
const allocated = Math.min(budget, turnTokens);
|
|
4847
|
+
compressedTotal += allocated;
|
|
4848
|
+
if (turnTokens > 20 && allocated < turnTokens * 0.6) {
|
|
4849
|
+
const turn = turns[i];
|
|
4850
|
+
const gist = this.generateGist(turn.content, allocated);
|
|
4851
|
+
const cueAnchors = this.extractCueAnchors(turn.content);
|
|
4852
|
+
updateStmt.run(gist, turn.id);
|
|
4853
|
+
insertRuleStmt.run(this.config.project, gist, JSON.stringify([turn.session_id]), chunks[i].relevance, Date.now(), Date.now());
|
|
4854
|
+
if (cueAnchors.length > 0) {
|
|
4855
|
+
try {
|
|
4856
|
+
const graphDb = this.db.get("graph");
|
|
4857
|
+
const upsertNode = graphDb.prepare(`INSERT OR REPLACE INTO nodes (id, type, label, content, metadata) VALUES (?, 'concept', ?, ?, ?)`);
|
|
4858
|
+
for (const cue of cueAnchors) {
|
|
4859
|
+
upsertNode.run(`cue-${turn.id}-${cue.slice(0, 20)}`, cue, gist.slice(0, 200), JSON.stringify({ source: `turn:${turn.id}`, cycle: this.cycleId }));
|
|
4860
|
+
}
|
|
4861
|
+
} catch {
|
|
4862
|
+
}
|
|
4863
|
+
}
|
|
4864
|
+
}
|
|
4747
4865
|
}
|
|
4748
|
-
}
|
|
4749
|
-
|
|
4866
|
+
});
|
|
4867
|
+
try {
|
|
4868
|
+
compressBatch();
|
|
4869
|
+
} catch {
|
|
4750
4870
|
}
|
|
4751
|
-
|
|
4752
|
-
|
|
4871
|
+
return { compressedTotal };
|
|
4872
|
+
}
|
|
4873
|
+
/** Generate a compressed gist (abstraction) of turn content. */
|
|
4874
|
+
generateGist(content, tokenBudget) {
|
|
4875
|
+
const sentences = content.split(/(?<=[.!?\n])\s+/).filter((s) => s.trim().length > 0);
|
|
4876
|
+
if (sentences.length <= 2)
|
|
4877
|
+
return content;
|
|
4878
|
+
const kept = [sentences[0]];
|
|
4879
|
+
const signalPattern = /\b(error|decided|created|modified|fixed|found|returned|result|output)\b/i;
|
|
4880
|
+
for (let i = 1; i < sentences.length - 1; i++) {
|
|
4881
|
+
if (signalPattern.test(sentences[i]))
|
|
4882
|
+
kept.push(sentences[i]);
|
|
4883
|
+
}
|
|
4884
|
+
kept.push(sentences[sentences.length - 1]);
|
|
4885
|
+
let gist = kept.join(" ");
|
|
4886
|
+
const words = gist.split(/\s+/);
|
|
4887
|
+
const wordBudget = Math.max(5, Math.floor(tokenBudget * 0.75));
|
|
4888
|
+
if (words.length > wordBudget)
|
|
4889
|
+
gist = words.slice(0, wordBudget).join(" ") + "...";
|
|
4890
|
+
return `[compressed] ${gist}`;
|
|
4891
|
+
}
|
|
4892
|
+
/** Extract cue anchors (trigger phrases) from turn content. */
|
|
4893
|
+
extractCueAnchors(content) {
|
|
4894
|
+
const anchors = [];
|
|
4895
|
+
const lower = content.toLowerCase();
|
|
4896
|
+
const voPattern = /\b(create|fix|refactor|implement|add|remove|update|debug|test|deploy|configure)\s+(\w+(?:\s+\w+)?)\b/gi;
|
|
4897
|
+
let match;
|
|
4898
|
+
while ((match = voPattern.exec(lower)) !== null)
|
|
4899
|
+
anchors.push(match[0].trim());
|
|
4900
|
+
const pathPattern = /[\w\-]+\.(?:ts|js|py|rs|go|java|tsx|jsx|json|yaml|toml)\b/gi;
|
|
4901
|
+
while ((match = pathPattern.exec(content)) !== null)
|
|
4902
|
+
anchors.push(match[0]);
|
|
4903
|
+
return [...new Set(anchors)].slice(0, 5);
|
|
4904
|
+
}
|
|
4905
|
+
/**
|
|
4906
|
+
* Detect noise turns that should be excluded from consolidation.
|
|
4907
|
+
* System context, compressed prompts, and meta-turns produce garbage rules.
|
|
4908
|
+
*/
|
|
4909
|
+
isNoiseTurn(content) {
|
|
4910
|
+
if (content.startsWith("[system:context]"))
|
|
4911
|
+
return true;
|
|
4912
|
+
if (content.startsWith("[compressed] [system:context]"))
|
|
4913
|
+
return true;
|
|
4914
|
+
if (/^\[tool:chitragupta_record_conversation\] recorded \d+/.test(content))
|
|
4915
|
+
return true;
|
|
4916
|
+
return false;
|
|
4753
4917
|
}
|
|
4754
|
-
// ── Private Helpers ──────────────────────────────────────────────────
|
|
4755
4918
|
/** Classify epistemological source (Pramana) of a turn's content. */
|
|
4756
4919
|
classifyPramana(content, calls) {
|
|
4757
|
-
if (calls.length > 0 && calls.some((tc) => !tc.isError && tc.result.length > 0))
|
|
4920
|
+
if (calls.length > 0 && calls.some((tc) => !tc.isError && tc.result.length > 0))
|
|
4758
4921
|
return "pratyaksha";
|
|
4759
|
-
}
|
|
4760
4922
|
const lower = content.toLowerCase();
|
|
4761
|
-
if (/\b(?:maybe|possibly|might|perhaps|could be|not sure|unsure)\b/.test(lower))
|
|
4762
|
-
|
|
4763
|
-
if (/\b(?:
|
|
4764
|
-
|
|
4923
|
+
if (/\b(?:maybe|possibly|might|perhaps|could be|not sure|unsure)\b/.test(lower))
|
|
4924
|
+
return "anupalabdhi";
|
|
4925
|
+
if (/\b(?:must be|likely|probably|implies|therefore)\b/.test(lower))
|
|
4926
|
+
return "arthapatti";
|
|
4927
|
+
if (/\b(?:similar to|like|analogous|compared to|just as)\b/.test(lower))
|
|
4928
|
+
return "upamana";
|
|
4929
|
+
if (/\b(?:according to|documentation|docs say|reference|specification)\b/.test(lower))
|
|
4930
|
+
return "shabda";
|
|
4765
4931
|
return "anumana";
|
|
4766
4932
|
}
|
|
4767
4933
|
/** Write an entry to the consolidation_log table for audit trail. */
|
|
4768
4934
|
logCycle(status, result) {
|
|
4769
4935
|
const agentDb = this.db.get("agent");
|
|
4770
|
-
agentDb.prepare(
|
|
4771
|
-
`INSERT INTO consolidation_log
|
|
4936
|
+
agentDb.prepare(`INSERT INTO consolidation_log
|
|
4772
4937
|
(project, cycle_type, cycle_id, phase, phase_duration_ms,
|
|
4773
4938
|
vasanas_created, vidhis_created, samskaras_processed,
|
|
4774
4939
|
sessions_processed, status, created_at)
|
|
4775
|
-
VALUES (?, 'svapna', ?, ?, ?, ?, ?, ?, ?, ?, ?)`
|
|
4776
|
-
|
|
4777
|
-
|
|
4778
|
-
this.cycleId,
|
|
4779
|
-
result ? "ALL" : null,
|
|
4780
|
-
result?.totalDurationMs ?? null,
|
|
4781
|
-
result?.phases.crystallize.vasanasCreated ?? 0,
|
|
4782
|
-
result?.phases.proceduralize.vidhisCreated ?? 0,
|
|
4783
|
-
0,
|
|
4784
|
-
result?.phases.replay.turnsScored ?? 0,
|
|
4785
|
-
status,
|
|
4786
|
-
Date.now()
|
|
4787
|
-
);
|
|
4788
|
-
agentDb.prepare(
|
|
4789
|
-
`UPDATE nidra_state SET consolidation_phase = ?, consolidation_progress = ?, updated_at = ?
|
|
4790
|
-
WHERE id = 1`
|
|
4791
|
-
).run(
|
|
4792
|
-
status === "running" ? "REPLAY" : null,
|
|
4793
|
-
status === "success" ? 1 : 0,
|
|
4794
|
-
Date.now()
|
|
4795
|
-
);
|
|
4940
|
+
VALUES (?, 'svapna', ?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(this.config.project, this.cycleId, result ? "ALL" : null, result?.totalDurationMs ?? null, result?.phases.crystallize.vasanasCreated ?? 0, result?.phases.proceduralize.vidhisCreated ?? 0, 0, result?.phases.replay.turnsScored ?? 0, status, Date.now());
|
|
4941
|
+
agentDb.prepare(`UPDATE nidra_state SET consolidation_phase = ?, consolidation_progress = ?, updated_at = ?
|
|
4942
|
+
WHERE id = 1`).run(status === "running" ? "REPLAY" : null, status === "success" ? 1 : 0, Date.now());
|
|
4796
4943
|
}
|
|
4797
4944
|
};
|
|
4798
4945
|
|
|
4799
|
-
// ../chitragupta/packages/smriti/
|
|
4946
|
+
// ../chitragupta/packages/smriti/dist/vidhi-matching.js
|
|
4800
4947
|
var ACTION_VERBS = /* @__PURE__ */ new Set([
|
|
4801
4948
|
"add",
|
|
4802
4949
|
"create",
|
|
@@ -4973,7 +5120,7 @@ var STOPWORDS = /* @__PURE__ */ new Set([
|
|
|
4973
5120
|
"want",
|
|
4974
5121
|
"like"
|
|
4975
5122
|
]);
|
|
4976
|
-
function
|
|
5123
|
+
function tokenize2(text) {
|
|
4977
5124
|
const words = text.toLowerCase().replace(/[^a-z0-9\s-]/g, " ").split(/\s+/).filter((w) => w.length > 1 && !STOPWORDS.has(w));
|
|
4978
5125
|
return new Set(words);
|
|
4979
5126
|
}
|
|
@@ -4981,7 +5128,8 @@ function extractVerbObjectPhrases(message) {
|
|
|
4981
5128
|
const words = message.toLowerCase().replace(/[^a-z0-9\s-]/g, " ").split(/\s+/).filter((w) => w.length > 1);
|
|
4982
5129
|
const phrases = [];
|
|
4983
5130
|
for (let i = 0; i < words.length; i++) {
|
|
4984
|
-
if (!ACTION_VERBS.has(words[i]))
|
|
5131
|
+
if (!ACTION_VERBS.has(words[i]))
|
|
5132
|
+
continue;
|
|
4985
5133
|
if (i + 1 < words.length) {
|
|
4986
5134
|
phrases.push(`${words[i]} ${words[i + 1]}`);
|
|
4987
5135
|
}
|
|
@@ -4995,7 +5143,8 @@ function extractTriggers(instances) {
|
|
|
4995
5143
|
const phraseCounts = /* @__PURE__ */ new Map();
|
|
4996
5144
|
for (const instance of instances) {
|
|
4997
5145
|
const msg = instance.precedingUserMessage;
|
|
4998
|
-
if (!msg || msg.trim().length === 0)
|
|
5146
|
+
if (!msg || msg.trim().length === 0)
|
|
5147
|
+
continue;
|
|
4999
5148
|
const phrases = extractVerbObjectPhrases(msg);
|
|
5000
5149
|
for (const phrase of phrases) {
|
|
5001
5150
|
phraseCounts.set(phrase, (phraseCounts.get(phrase) ?? 0) + 1);
|
|
@@ -5025,35 +5174,42 @@ function sampleGamma2(shape) {
|
|
|
5025
5174
|
} while (v <= 0);
|
|
5026
5175
|
v = v * v * v;
|
|
5027
5176
|
const u = Math.random();
|
|
5028
|
-
if (u < 1 - 0.0331 * (x * x) * (x * x))
|
|
5029
|
-
|
|
5177
|
+
if (u < 1 - 0.0331 * (x * x) * (x * x))
|
|
5178
|
+
return d * v;
|
|
5179
|
+
if (Math.log(u) < 0.5 * x * x + d * (1 - v + Math.log(v)))
|
|
5180
|
+
return d * v;
|
|
5030
5181
|
}
|
|
5031
5182
|
}
|
|
5032
5183
|
function sampleBeta2(alpha, beta) {
|
|
5033
5184
|
const x = sampleGamma2(alpha);
|
|
5034
5185
|
const y = sampleGamma2(beta);
|
|
5035
5186
|
const sum = x + y;
|
|
5036
|
-
if (sum < 1e-300 || !isFinite(sum))
|
|
5187
|
+
if (sum < 1e-300 || !isFinite(sum))
|
|
5188
|
+
return 0.5;
|
|
5037
5189
|
return x / sum;
|
|
5038
5190
|
}
|
|
5039
5191
|
function matchVidhi(vidhis, query) {
|
|
5040
|
-
if (vidhis.length === 0)
|
|
5041
|
-
|
|
5042
|
-
|
|
5192
|
+
if (vidhis.length === 0)
|
|
5193
|
+
return null;
|
|
5194
|
+
const queryTokens = tokenize2(query);
|
|
5195
|
+
if (queryTokens.size === 0)
|
|
5196
|
+
return null;
|
|
5043
5197
|
let bestVidhi = null;
|
|
5044
5198
|
let bestScore = 0;
|
|
5045
5199
|
for (const vidhi of vidhis) {
|
|
5046
5200
|
const triggerTokens = /* @__PURE__ */ new Set();
|
|
5047
5201
|
for (const trigger of vidhi.triggers) {
|
|
5048
|
-
for (const tok of
|
|
5202
|
+
for (const tok of tokenize2(trigger)) {
|
|
5049
5203
|
triggerTokens.add(tok);
|
|
5050
5204
|
}
|
|
5051
5205
|
}
|
|
5052
|
-
if (triggerTokens.size === 0)
|
|
5206
|
+
if (triggerTokens.size === 0)
|
|
5207
|
+
continue;
|
|
5053
5208
|
const intersection = new Set([...queryTokens].filter((t) => triggerTokens.has(t)));
|
|
5054
5209
|
const union = /* @__PURE__ */ new Set([...queryTokens, ...triggerTokens]);
|
|
5055
5210
|
const jaccard = intersection.size / union.size;
|
|
5056
|
-
if (jaccard < 0.15)
|
|
5211
|
+
if (jaccard < 0.15)
|
|
5212
|
+
continue;
|
|
5057
5213
|
const alpha = vidhi.successCount + 1;
|
|
5058
5214
|
const beta = vidhi.failureCount + 1;
|
|
5059
5215
|
const thompsonSample = sampleBeta2(alpha, beta);
|
|
@@ -5066,7 +5222,7 @@ function matchVidhi(vidhis, query) {
|
|
|
5066
5222
|
return bestVidhi;
|
|
5067
5223
|
}
|
|
5068
5224
|
|
|
5069
|
-
// ../chitragupta/packages/smriti/
|
|
5225
|
+
// ../chitragupta/packages/smriti/dist/vidhi-extraction.js
|
|
5070
5226
|
var FNV_OFFSET5 = 2166136261;
|
|
5071
5227
|
var FNV_PRIME5 = 16777619;
|
|
5072
5228
|
function fnv1a6(str) {
|
|
@@ -5079,11 +5235,10 @@ function fnv1a6(str) {
|
|
|
5079
5235
|
}
|
|
5080
5236
|
function loadSessionSequences(config) {
|
|
5081
5237
|
const db = DatabaseManager.instance().get("agent");
|
|
5082
|
-
const sessionRows = db.prepare(
|
|
5083
|
-
"SELECT id FROM sessions WHERE project = ?"
|
|
5084
|
-
).all(config.project);
|
|
5238
|
+
const sessionRows = db.prepare("SELECT id FROM sessions WHERE project = ?").all(config.project);
|
|
5085
5239
|
const sessionIds = new Set(sessionRows.map((r) => r.id));
|
|
5086
|
-
if (sessionIds.size === 0)
|
|
5240
|
+
if (sessionIds.size === 0)
|
|
5241
|
+
return /* @__PURE__ */ new Map();
|
|
5087
5242
|
const turnRows = db.prepare(`
|
|
5088
5243
|
SELECT session_id, turn_number, role, content, tool_calls
|
|
5089
5244
|
FROM turns
|
|
@@ -5097,14 +5252,16 @@ function loadSessionSequences(config) {
|
|
|
5097
5252
|
lastUserMessage = row.content;
|
|
5098
5253
|
continue;
|
|
5099
5254
|
}
|
|
5100
|
-
if (row.role !== "assistant" || !row.tool_calls)
|
|
5255
|
+
if (row.role !== "assistant" || !row.tool_calls)
|
|
5256
|
+
continue;
|
|
5101
5257
|
let toolCalls;
|
|
5102
5258
|
try {
|
|
5103
5259
|
toolCalls = JSON.parse(row.tool_calls);
|
|
5104
5260
|
} catch {
|
|
5105
5261
|
continue;
|
|
5106
5262
|
}
|
|
5107
|
-
if (!Array.isArray(toolCalls) || toolCalls.length === 0)
|
|
5263
|
+
if (!Array.isArray(toolCalls) || toolCalls.length === 0)
|
|
5264
|
+
continue;
|
|
5108
5265
|
if (!result.has(row.session_id)) {
|
|
5109
5266
|
result.set(row.session_id, []);
|
|
5110
5267
|
}
|
|
@@ -5122,12 +5279,14 @@ function loadSessionSequences(config) {
|
|
|
5122
5279
|
function extractAndAggregate(sessionSequences, config) {
|
|
5123
5280
|
const ngramMap = /* @__PURE__ */ new Map();
|
|
5124
5281
|
for (const [sessionId, sequence] of sessionSequences) {
|
|
5125
|
-
if (sequence.length < config.minSequenceLength)
|
|
5282
|
+
if (sequence.length < config.minSequenceLength)
|
|
5283
|
+
continue;
|
|
5126
5284
|
for (let n = config.minSequenceLength; n <= Math.min(config.maxSequenceLength, sequence.length); n++) {
|
|
5127
5285
|
for (let i = 0; i <= sequence.length - n; i++) {
|
|
5128
5286
|
const window = sequence.slice(i, i + n);
|
|
5129
5287
|
const hasError = window.some((w) => w.toolCall.isError === true);
|
|
5130
|
-
if (hasError)
|
|
5288
|
+
if (hasError)
|
|
5289
|
+
continue;
|
|
5131
5290
|
const key = window.map((w) => w.toolCall.name).join("|");
|
|
5132
5291
|
if (!ngramMap.has(key)) {
|
|
5133
5292
|
ngramMap.set(key, /* @__PURE__ */ new Map());
|
|
@@ -5145,14 +5304,14 @@ function extractAndAggregate(sessionSequences, config) {
|
|
|
5145
5304
|
}
|
|
5146
5305
|
const aggregates = [];
|
|
5147
5306
|
for (const [key, sessionMap] of ngramMap) {
|
|
5148
|
-
if (sessionMap.size < config.minSessions)
|
|
5307
|
+
if (sessionMap.size < config.minSessions)
|
|
5308
|
+
continue;
|
|
5149
5309
|
const instances = [...sessionMap.values()];
|
|
5150
5310
|
const toolNames2 = key.split("|");
|
|
5151
|
-
const successfulInstances = instances.filter(
|
|
5152
|
-
(inst) => inst.toolCalls.every((tc) => !tc.isError)
|
|
5153
|
-
);
|
|
5311
|
+
const successfulInstances = instances.filter((inst) => inst.toolCalls.every((tc) => !tc.isError));
|
|
5154
5312
|
const successRate = instances.length > 0 ? successfulInstances.length / instances.length : 0;
|
|
5155
|
-
if (successRate < config.minSuccessRate)
|
|
5313
|
+
if (successRate < config.minSuccessRate)
|
|
5314
|
+
continue;
|
|
5156
5315
|
aggregates.push({
|
|
5157
5316
|
key,
|
|
5158
5317
|
toolNames: toolNames2,
|
|
@@ -5266,36 +5425,45 @@ function generateName(toolNames2) {
|
|
|
5266
5425
|
function inferType(values) {
|
|
5267
5426
|
const types = /* @__PURE__ */ new Set();
|
|
5268
5427
|
for (const v of values) {
|
|
5269
|
-
if (v === null || v === void 0)
|
|
5270
|
-
|
|
5271
|
-
|
|
5272
|
-
|
|
5273
|
-
else if (
|
|
5274
|
-
|
|
5275
|
-
|
|
5276
|
-
|
|
5277
|
-
|
|
5428
|
+
if (v === null || v === void 0)
|
|
5429
|
+
continue;
|
|
5430
|
+
if (typeof v === "string")
|
|
5431
|
+
types.add("string");
|
|
5432
|
+
else if (typeof v === "number")
|
|
5433
|
+
types.add("number");
|
|
5434
|
+
else if (typeof v === "boolean")
|
|
5435
|
+
types.add("boolean");
|
|
5436
|
+
else if (Array.isArray(v))
|
|
5437
|
+
types.add("array");
|
|
5438
|
+
else if (typeof v === "object")
|
|
5439
|
+
types.add("object");
|
|
5440
|
+
}
|
|
5441
|
+
if (types.size === 0)
|
|
5442
|
+
return "string";
|
|
5443
|
+
if (types.size === 1)
|
|
5444
|
+
return [...types][0];
|
|
5278
5445
|
return "string";
|
|
5279
5446
|
}
|
|
5280
5447
|
function deepEqual(a, b) {
|
|
5281
|
-
if (a === b)
|
|
5282
|
-
|
|
5283
|
-
if (
|
|
5448
|
+
if (a === b)
|
|
5449
|
+
return true;
|
|
5450
|
+
if (a === null || b === null)
|
|
5451
|
+
return false;
|
|
5452
|
+
if (typeof a !== typeof b)
|
|
5453
|
+
return false;
|
|
5284
5454
|
if (typeof a === "object") {
|
|
5285
5455
|
if (Array.isArray(a) && Array.isArray(b)) {
|
|
5286
|
-
if (a.length !== b.length)
|
|
5456
|
+
if (a.length !== b.length)
|
|
5457
|
+
return false;
|
|
5287
5458
|
return a.every((val, idx) => deepEqual(val, b[idx]));
|
|
5288
5459
|
}
|
|
5289
|
-
if (Array.isArray(a) !== Array.isArray(b))
|
|
5460
|
+
if (Array.isArray(a) !== Array.isArray(b))
|
|
5461
|
+
return false;
|
|
5290
5462
|
const keysA = Object.keys(a);
|
|
5291
5463
|
const keysB = Object.keys(b);
|
|
5292
|
-
if (keysA.length !== keysB.length)
|
|
5293
|
-
|
|
5294
|
-
|
|
5295
|
-
a[k],
|
|
5296
|
-
b[k]
|
|
5297
|
-
)
|
|
5298
|
-
);
|
|
5464
|
+
if (keysA.length !== keysB.length)
|
|
5465
|
+
return false;
|
|
5466
|
+
return keysA.every((k) => deepEqual(a[k], b[k]));
|
|
5299
5467
|
}
|
|
5300
5468
|
return false;
|
|
5301
5469
|
}
|
|
@@ -5304,15 +5472,17 @@ function uniqueExamples(values, max) {
|
|
|
5304
5472
|
const examples = [];
|
|
5305
5473
|
for (const v of values) {
|
|
5306
5474
|
const key = JSON.stringify(v);
|
|
5307
|
-
if (seen.has(key))
|
|
5475
|
+
if (seen.has(key))
|
|
5476
|
+
continue;
|
|
5308
5477
|
seen.add(key);
|
|
5309
5478
|
examples.push(v);
|
|
5310
|
-
if (examples.length >= max)
|
|
5479
|
+
if (examples.length >= max)
|
|
5480
|
+
break;
|
|
5311
5481
|
}
|
|
5312
5482
|
return examples;
|
|
5313
5483
|
}
|
|
5314
5484
|
|
|
5315
|
-
// ../chitragupta/packages/smriti/
|
|
5485
|
+
// ../chitragupta/packages/smriti/dist/vidhi-engine.js
|
|
5316
5486
|
var DEFAULT_CONFIG5 = {
|
|
5317
5487
|
minSessions: 3,
|
|
5318
5488
|
minSuccessRate: 0.8,
|
|
@@ -5320,7 +5490,8 @@ var DEFAULT_CONFIG5 = {
|
|
|
5320
5490
|
maxSequenceLength: 5
|
|
5321
5491
|
};
|
|
5322
5492
|
function safeParse(json, fallback) {
|
|
5323
|
-
if (!json)
|
|
5493
|
+
if (!json)
|
|
5494
|
+
return fallback;
|
|
5324
5495
|
try {
|
|
5325
5496
|
return JSON.parse(json);
|
|
5326
5497
|
} catch {
|
|
@@ -5359,15 +5530,13 @@ var VidhiEngine = class {
|
|
|
5359
5530
|
for (const agg of aggregates) {
|
|
5360
5531
|
const existingVidhi = existingByKey.get(agg.key);
|
|
5361
5532
|
if (existingVidhi) {
|
|
5533
|
+
const oldSize = existingVidhi.learnedFrom.length;
|
|
5362
5534
|
const mergedSessions = /* @__PURE__ */ new Set([
|
|
5363
5535
|
...existingVidhi.learnedFrom,
|
|
5364
5536
|
...agg.instances.map((i) => i.sessionId)
|
|
5365
5537
|
]);
|
|
5366
5538
|
existingVidhi.learnedFrom = [...mergedSessions];
|
|
5367
|
-
existingVidhi.confidence = Math.min(
|
|
5368
|
-
1,
|
|
5369
|
-
existingVidhi.confidence + 0.05 * (mergedSessions.size - existingVidhi.learnedFrom.length)
|
|
5370
|
-
);
|
|
5539
|
+
existingVidhi.confidence = Math.min(1, existingVidhi.confidence + 0.05 * (mergedSessions.size - oldSize));
|
|
5371
5540
|
existingVidhi.updatedAt = Date.now();
|
|
5372
5541
|
this.persist(existingVidhi);
|
|
5373
5542
|
reinforced.push(existingVidhi);
|
|
@@ -5408,7 +5577,8 @@ var VidhiEngine = class {
|
|
|
5408
5577
|
*/
|
|
5409
5578
|
recordOutcome(vidhiId, success) {
|
|
5410
5579
|
const vidhi = this.getVidhi(vidhiId);
|
|
5411
|
-
if (!vidhi)
|
|
5580
|
+
if (!vidhi)
|
|
5581
|
+
return;
|
|
5412
5582
|
if (success) {
|
|
5413
5583
|
vidhi.successCount += 1;
|
|
5414
5584
|
} else {
|
|
@@ -5461,21 +5631,7 @@ var VidhiEngine = class {
|
|
|
5461
5631
|
success_rate, success_count, failure_count, parameter_schema,
|
|
5462
5632
|
created_at, updated_at)
|
|
5463
5633
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
5464
|
-
`).run(
|
|
5465
|
-
vidhi.id,
|
|
5466
|
-
vidhi.project,
|
|
5467
|
-
vidhi.name,
|
|
5468
|
-
JSON.stringify(vidhi.learnedFrom),
|
|
5469
|
-
vidhi.confidence,
|
|
5470
|
-
JSON.stringify(vidhi.steps),
|
|
5471
|
-
JSON.stringify(vidhi.triggers),
|
|
5472
|
-
vidhi.successRate,
|
|
5473
|
-
vidhi.successCount,
|
|
5474
|
-
vidhi.failureCount,
|
|
5475
|
-
JSON.stringify(vidhi.parameterSchema),
|
|
5476
|
-
vidhi.createdAt,
|
|
5477
|
-
vidhi.updatedAt
|
|
5478
|
-
);
|
|
5634
|
+
`).run(vidhi.id, vidhi.project, vidhi.name, JSON.stringify(vidhi.learnedFrom), vidhi.confidence, JSON.stringify(vidhi.steps), JSON.stringify(vidhi.triggers), vidhi.successRate, vidhi.successCount, vidhi.failureCount, JSON.stringify(vidhi.parameterSchema), vidhi.createdAt, vidhi.updatedAt);
|
|
5479
5635
|
}
|
|
5480
5636
|
/**
|
|
5481
5637
|
* Load all Vidhis for a project from SQLite.
|
|
@@ -5485,9 +5641,7 @@ var VidhiEngine = class {
|
|
|
5485
5641
|
*/
|
|
5486
5642
|
loadAll(project) {
|
|
5487
5643
|
const db = DatabaseManager.instance().get("agent");
|
|
5488
|
-
const rows = db.prepare(
|
|
5489
|
-
"SELECT * FROM vidhis WHERE project = ? ORDER BY success_rate DESC"
|
|
5490
|
-
).all(project);
|
|
5644
|
+
const rows = db.prepare("SELECT * FROM vidhis WHERE project = ? ORDER BY success_rate DESC").all(project);
|
|
5491
5645
|
return rows.map((r) => this._rowToVidhi(r));
|
|
5492
5646
|
}
|
|
5493
5647
|
// ─── Private ──────────────────────────────────────────────────────
|
|
@@ -5509,534 +5663,14 @@ var VidhiEngine = class {
|
|
|
5509
5663
|
successRate: row.success_rate,
|
|
5510
5664
|
successCount: row.success_count,
|
|
5511
5665
|
failureCount: row.failure_count,
|
|
5512
|
-
parameterSchema: safeParse(
|
|
5513
|
-
row.parameter_schema,
|
|
5514
|
-
{}
|
|
5515
|
-
),
|
|
5666
|
+
parameterSchema: safeParse(row.parameter_schema, {}),
|
|
5516
5667
|
createdAt: row.created_at,
|
|
5517
5668
|
updatedAt: row.updated_at
|
|
5518
5669
|
};
|
|
5519
5670
|
}
|
|
5520
5671
|
};
|
|
5521
5672
|
|
|
5522
|
-
// ../chitragupta/packages/smriti/
|
|
5523
|
-
var CREATE_TABLE_SQL = `
|
|
5524
|
-
CREATE TABLE IF NOT EXISTS akasha_traces (
|
|
5525
|
-
id TEXT PRIMARY KEY,
|
|
5526
|
-
agent_id TEXT NOT NULL,
|
|
5527
|
-
trace_type TEXT NOT NULL,
|
|
5528
|
-
topic TEXT NOT NULL,
|
|
5529
|
-
content TEXT NOT NULL,
|
|
5530
|
-
strength REAL NOT NULL,
|
|
5531
|
-
reinforcements INTEGER NOT NULL DEFAULT 0,
|
|
5532
|
-
metadata TEXT,
|
|
5533
|
-
created_at INTEGER NOT NULL,
|
|
5534
|
-
last_reinforced_at INTEGER NOT NULL
|
|
5535
|
-
);
|
|
5536
|
-
CREATE INDEX IF NOT EXISTS idx_akasha_topic ON akasha_traces(topic);
|
|
5537
|
-
CREATE INDEX IF NOT EXISTS idx_akasha_strength ON akasha_traces(strength DESC);
|
|
5538
|
-
`;
|
|
5539
|
-
var UPSERT_SQL = `
|
|
5540
|
-
INSERT OR REPLACE INTO akasha_traces
|
|
5541
|
-
(id, agent_id, trace_type, topic, content, strength,
|
|
5542
|
-
reinforcements, metadata, created_at, last_reinforced_at)
|
|
5543
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
5544
|
-
`;
|
|
5545
|
-
var ENSURE_TABLE_SQL = `
|
|
5546
|
-
CREATE TABLE IF NOT EXISTS akasha_traces (
|
|
5547
|
-
id TEXT PRIMARY KEY,
|
|
5548
|
-
agent_id TEXT NOT NULL,
|
|
5549
|
-
trace_type TEXT NOT NULL,
|
|
5550
|
-
topic TEXT NOT NULL,
|
|
5551
|
-
content TEXT NOT NULL,
|
|
5552
|
-
strength REAL NOT NULL,
|
|
5553
|
-
reinforcements INTEGER NOT NULL DEFAULT 0,
|
|
5554
|
-
metadata TEXT,
|
|
5555
|
-
created_at INTEGER NOT NULL,
|
|
5556
|
-
last_reinforced_at INTEGER NOT NULL
|
|
5557
|
-
);
|
|
5558
|
-
`;
|
|
5559
|
-
function safeParseJson(raw) {
|
|
5560
|
-
if (!raw) return {};
|
|
5561
|
-
try {
|
|
5562
|
-
const parsed = JSON.parse(raw);
|
|
5563
|
-
return typeof parsed === "object" && parsed !== null ? parsed : {};
|
|
5564
|
-
} catch {
|
|
5565
|
-
return {};
|
|
5566
|
-
}
|
|
5567
|
-
}
|
|
5568
|
-
function persistTraces(traces, db) {
|
|
5569
|
-
db.exec(CREATE_TABLE_SQL);
|
|
5570
|
-
const upsert = db.prepare(UPSERT_SQL);
|
|
5571
|
-
for (const trace of traces.values()) {
|
|
5572
|
-
upsert.run(
|
|
5573
|
-
trace.id,
|
|
5574
|
-
trace.agentId,
|
|
5575
|
-
trace.traceType,
|
|
5576
|
-
trace.topic,
|
|
5577
|
-
trace.content,
|
|
5578
|
-
trace.strength,
|
|
5579
|
-
trace.reinforcements,
|
|
5580
|
-
JSON.stringify(trace.metadata),
|
|
5581
|
-
trace.createdAt,
|
|
5582
|
-
trace.lastReinforcedAt
|
|
5583
|
-
);
|
|
5584
|
-
}
|
|
5585
|
-
}
|
|
5586
|
-
function restoreTraces(db, config) {
|
|
5587
|
-
db.exec(ENSURE_TABLE_SQL);
|
|
5588
|
-
const rows = db.prepare("SELECT * FROM akasha_traces").all();
|
|
5589
|
-
const traces = /* @__PURE__ */ new Map();
|
|
5590
|
-
const reinforcedBy = /* @__PURE__ */ new Map();
|
|
5591
|
-
for (const row of rows) {
|
|
5592
|
-
if (row.strength < config.minStrength) continue;
|
|
5593
|
-
const trace = {
|
|
5594
|
-
id: row.id,
|
|
5595
|
-
agentId: row.agent_id,
|
|
5596
|
-
traceType: row.trace_type,
|
|
5597
|
-
topic: row.topic,
|
|
5598
|
-
content: row.content,
|
|
5599
|
-
strength: row.strength,
|
|
5600
|
-
reinforcements: row.reinforcements,
|
|
5601
|
-
metadata: safeParseJson(row.metadata),
|
|
5602
|
-
createdAt: row.created_at,
|
|
5603
|
-
lastReinforcedAt: row.last_reinforced_at
|
|
5604
|
-
};
|
|
5605
|
-
traces.set(trace.id, trace);
|
|
5606
|
-
reinforcedBy.set(trace.id, /* @__PURE__ */ new Set([trace.agentId]));
|
|
5607
|
-
}
|
|
5608
|
-
return { traces, reinforcedBy };
|
|
5609
|
-
}
|
|
5610
|
-
function tracesToGraphNodes(traces, minStrength) {
|
|
5611
|
-
const nodes = [];
|
|
5612
|
-
for (const trace of traces.values()) {
|
|
5613
|
-
if (trace.strength < minStrength) continue;
|
|
5614
|
-
nodes.push({
|
|
5615
|
-
id: trace.id,
|
|
5616
|
-
label: `[${trace.traceType}] ${trace.topic}`,
|
|
5617
|
-
content: trace.content,
|
|
5618
|
-
type: "akasha",
|
|
5619
|
-
weight: trace.strength
|
|
5620
|
-
});
|
|
5621
|
-
}
|
|
5622
|
-
return nodes;
|
|
5623
|
-
}
|
|
5624
|
-
function boostResultsWithTraces(traces, config, results, query) {
|
|
5625
|
-
const queryTokens = new Set(tokenize4(query));
|
|
5626
|
-
const matchingTraces = [];
|
|
5627
|
-
if (queryTokens.size > 0) {
|
|
5628
|
-
for (const trace of traces.values()) {
|
|
5629
|
-
if (trace.strength < config.minStrength) continue;
|
|
5630
|
-
const traceTokens = /* @__PURE__ */ new Set([
|
|
5631
|
-
...tokenize4(trace.topic),
|
|
5632
|
-
...tokenize4(trace.content)
|
|
5633
|
-
]);
|
|
5634
|
-
const sim = jaccardSimilarity2(queryTokens, traceTokens);
|
|
5635
|
-
if (sim > 0) {
|
|
5636
|
-
matchingTraces.push({ trace, similarity: sim });
|
|
5637
|
-
}
|
|
5638
|
-
}
|
|
5639
|
-
matchingTraces.sort((a, b) => b.similarity - a.similarity);
|
|
5640
|
-
}
|
|
5641
|
-
return results.map((result) => {
|
|
5642
|
-
let traceBoost = 0;
|
|
5643
|
-
if (queryTokens.size > 0 && matchingTraces.length > 0) {
|
|
5644
|
-
const resultTokens = result.content ? new Set(tokenize4(result.content)) : /* @__PURE__ */ new Set();
|
|
5645
|
-
let bestBoost = 0;
|
|
5646
|
-
for (const { trace, similarity } of matchingTraces) {
|
|
5647
|
-
if (result.id === trace.id) {
|
|
5648
|
-
bestBoost = Math.max(bestBoost, trace.strength);
|
|
5649
|
-
break;
|
|
5650
|
-
}
|
|
5651
|
-
if (resultTokens.size > 0) {
|
|
5652
|
-
const traceTokens = /* @__PURE__ */ new Set([
|
|
5653
|
-
...tokenize4(trace.topic),
|
|
5654
|
-
...tokenize4(trace.content)
|
|
5655
|
-
]);
|
|
5656
|
-
const resultSim = jaccardSimilarity2(resultTokens, traceTokens);
|
|
5657
|
-
if (resultSim > 0.1) {
|
|
5658
|
-
bestBoost = Math.max(bestBoost, similarity * trace.strength);
|
|
5659
|
-
}
|
|
5660
|
-
} else {
|
|
5661
|
-
bestBoost = Math.max(bestBoost, similarity * trace.strength);
|
|
5662
|
-
}
|
|
5663
|
-
}
|
|
5664
|
-
traceBoost = bestBoost * config.traceBoostFactor;
|
|
5665
|
-
}
|
|
5666
|
-
return {
|
|
5667
|
-
...result,
|
|
5668
|
-
score: result.score * (1 + traceBoost),
|
|
5669
|
-
traceBoost
|
|
5670
|
-
};
|
|
5671
|
-
});
|
|
5672
|
-
}
|
|
5673
|
-
|
|
5674
|
-
// ../chitragupta/packages/smriti/src/akasha.ts
|
|
5675
|
-
var STOP_WORDS = /* @__PURE__ */ new Set([
|
|
5676
|
-
"a",
|
|
5677
|
-
"an",
|
|
5678
|
-
"the",
|
|
5679
|
-
"and",
|
|
5680
|
-
"or",
|
|
5681
|
-
"but",
|
|
5682
|
-
"in",
|
|
5683
|
-
"on",
|
|
5684
|
-
"at",
|
|
5685
|
-
"to",
|
|
5686
|
-
"for",
|
|
5687
|
-
"of",
|
|
5688
|
-
"with",
|
|
5689
|
-
"by",
|
|
5690
|
-
"from",
|
|
5691
|
-
"is",
|
|
5692
|
-
"it",
|
|
5693
|
-
"its",
|
|
5694
|
-
"this",
|
|
5695
|
-
"that",
|
|
5696
|
-
"was",
|
|
5697
|
-
"are",
|
|
5698
|
-
"be",
|
|
5699
|
-
"been",
|
|
5700
|
-
"being",
|
|
5701
|
-
"have",
|
|
5702
|
-
"has",
|
|
5703
|
-
"had",
|
|
5704
|
-
"do",
|
|
5705
|
-
"does",
|
|
5706
|
-
"did",
|
|
5707
|
-
"will",
|
|
5708
|
-
"would",
|
|
5709
|
-
"could",
|
|
5710
|
-
"should",
|
|
5711
|
-
"not",
|
|
5712
|
-
"no",
|
|
5713
|
-
"so",
|
|
5714
|
-
"if",
|
|
5715
|
-
"then",
|
|
5716
|
-
"than",
|
|
5717
|
-
"too",
|
|
5718
|
-
"very",
|
|
5719
|
-
"can",
|
|
5720
|
-
"just",
|
|
5721
|
-
"about",
|
|
5722
|
-
"into",
|
|
5723
|
-
"over",
|
|
5724
|
-
"after"
|
|
5725
|
-
]);
|
|
5726
|
-
var FNV_OFFSET6 = 2166136261;
|
|
5727
|
-
var FNV_PRIME6 = 16777619;
|
|
5728
|
-
function fnv1a7(input) {
|
|
5729
|
-
let hash = FNV_OFFSET6;
|
|
5730
|
-
for (let i = 0; i < input.length; i++) {
|
|
5731
|
-
hash ^= input.charCodeAt(i);
|
|
5732
|
-
hash = Math.imul(hash, FNV_PRIME6) >>> 0;
|
|
5733
|
-
}
|
|
5734
|
-
return hash.toString(16).padStart(8, "0");
|
|
5735
|
-
}
|
|
5736
|
-
function tokenize4(text) {
|
|
5737
|
-
return text.toLowerCase().replace(/[^a-z0-9\s]/g, " ").split(/\s+/).filter((t) => t.length >= 2 && !STOP_WORDS.has(t));
|
|
5738
|
-
}
|
|
5739
|
-
function jaccardSimilarity2(a, b) {
|
|
5740
|
-
if (a.size === 0 && b.size === 0) return 1;
|
|
5741
|
-
let intersection = 0;
|
|
5742
|
-
for (const token of a) {
|
|
5743
|
-
if (b.has(token)) intersection++;
|
|
5744
|
-
}
|
|
5745
|
-
const union = a.size + b.size - intersection;
|
|
5746
|
-
return union === 0 ? 0 : intersection / union;
|
|
5747
|
-
}
|
|
5748
|
-
var DAY_MS = 864e5;
|
|
5749
|
-
var DEFAULT_CONFIG6 = {
|
|
5750
|
-
decayHalfLife: 7 * DAY_MS,
|
|
5751
|
-
minStrength: 0.01,
|
|
5752
|
-
maxTraces: 5e3,
|
|
5753
|
-
reinforcementBoost: 0.15,
|
|
5754
|
-
initialStrength: 0.5,
|
|
5755
|
-
topKRetrieval: 10,
|
|
5756
|
-
traceBoostFactor: 0.3,
|
|
5757
|
-
diminishingAlpha: 0.3,
|
|
5758
|
-
frequencyDecayBeta: 0.5
|
|
5759
|
-
};
|
|
5760
|
-
var HARD_CEILINGS = {
|
|
5761
|
-
maxTraces: 5e4,
|
|
5762
|
-
minDecayHalfLife: 36e5,
|
|
5763
|
-
maxContentSize: 1e4
|
|
5764
|
-
};
|
|
5765
|
-
var AkashaField = class {
|
|
5766
|
-
config;
|
|
5767
|
-
traces = /* @__PURE__ */ new Map();
|
|
5768
|
-
/** Tracks which agents reinforced which traces (prevents self/duplicate). */
|
|
5769
|
-
reinforcedBy = /* @__PURE__ */ new Map();
|
|
5770
|
-
constructor(config) {
|
|
5771
|
-
this.config = {
|
|
5772
|
-
...DEFAULT_CONFIG6,
|
|
5773
|
-
...config,
|
|
5774
|
-
maxTraces: Math.min(
|
|
5775
|
-
config?.maxTraces ?? DEFAULT_CONFIG6.maxTraces,
|
|
5776
|
-
HARD_CEILINGS.maxTraces
|
|
5777
|
-
),
|
|
5778
|
-
decayHalfLife: Math.max(
|
|
5779
|
-
config?.decayHalfLife ?? DEFAULT_CONFIG6.decayHalfLife,
|
|
5780
|
-
HARD_CEILINGS.minDecayHalfLife
|
|
5781
|
-
)
|
|
5782
|
-
};
|
|
5783
|
-
}
|
|
5784
|
-
// ─── Leaving Traces ─────────────────────────────────────────────────
|
|
5785
|
-
/**
|
|
5786
|
-
* Agent leaves a stigmergic trace after solving or discovering something.
|
|
5787
|
-
*
|
|
5788
|
-
* @param agentId - Which agent is leaving this trace.
|
|
5789
|
-
* @param type - The category of knowledge.
|
|
5790
|
-
* @param topic - What the trace is about (used for matching).
|
|
5791
|
-
* @param content - The actual knowledge or solution.
|
|
5792
|
-
* @param metadata - Optional metadata for the trace.
|
|
5793
|
-
* @returns The created StigmergicTrace.
|
|
5794
|
-
*/
|
|
5795
|
-
leave(agentId, type, topic, content, metadata) {
|
|
5796
|
-
const truncatedContent = content.length > HARD_CEILINGS.maxContentSize ? content.slice(0, HARD_CEILINGS.maxContentSize) : content;
|
|
5797
|
-
const id = `aks-${fnv1a7(agentId + ":" + type + ":" + topic + ":" + truncatedContent)}`;
|
|
5798
|
-
const now = Date.now();
|
|
5799
|
-
const trace = {
|
|
5800
|
-
id,
|
|
5801
|
-
agentId,
|
|
5802
|
-
traceType: type,
|
|
5803
|
-
topic,
|
|
5804
|
-
content: truncatedContent,
|
|
5805
|
-
strength: this.config.initialStrength,
|
|
5806
|
-
reinforcements: 0,
|
|
5807
|
-
metadata: metadata ?? {},
|
|
5808
|
-
createdAt: now,
|
|
5809
|
-
lastReinforcedAt: now
|
|
5810
|
-
};
|
|
5811
|
-
this.traces.set(id, trace);
|
|
5812
|
-
this.reinforcedBy.set(id, /* @__PURE__ */ new Set([agentId]));
|
|
5813
|
-
if (this.traces.size > this.config.maxTraces) this.evictWeakest();
|
|
5814
|
-
return trace;
|
|
5815
|
-
}
|
|
5816
|
-
/**
|
|
5817
|
-
* Reinforce an existing trace -- another agent found it useful.
|
|
5818
|
-
*
|
|
5819
|
-
* @param traceId - The trace to reinforce.
|
|
5820
|
-
* @param agentId - The agent reinforcing it.
|
|
5821
|
-
* @returns The updated trace, or null if not found / already reinforced.
|
|
5822
|
-
*/
|
|
5823
|
-
reinforce(traceId, agentId) {
|
|
5824
|
-
const trace = this.traces.get(traceId);
|
|
5825
|
-
if (!trace) return null;
|
|
5826
|
-
const agents = this.reinforcedBy.get(traceId);
|
|
5827
|
-
if (agents?.has(agentId)) return null;
|
|
5828
|
-
const alpha = this.config.diminishingAlpha;
|
|
5829
|
-
const effectiveBoost = this.config.reinforcementBoost / (1 + alpha * trace.reinforcements);
|
|
5830
|
-
trace.strength = Math.min(1, trace.strength + effectiveBoost);
|
|
5831
|
-
trace.reinforcements++;
|
|
5832
|
-
trace.lastReinforcedAt = Date.now();
|
|
5833
|
-
if (!agents) {
|
|
5834
|
-
this.reinforcedBy.set(traceId, /* @__PURE__ */ new Set([agentId]));
|
|
5835
|
-
} else {
|
|
5836
|
-
agents.add(agentId);
|
|
5837
|
-
}
|
|
5838
|
-
return trace;
|
|
5839
|
-
}
|
|
5840
|
-
// ─── Following Traces ────────────────────────────────────────────────
|
|
5841
|
-
/**
|
|
5842
|
-
* Find relevant traces by Jaccard similarity on topic/content tokens.
|
|
5843
|
-
*
|
|
5844
|
-
* @param topic - The query to match against trace topics and content.
|
|
5845
|
-
* @param opts - Optional filters: type, minStrength, limit.
|
|
5846
|
-
* @returns Matching traces sorted by relevance score.
|
|
5847
|
-
*/
|
|
5848
|
-
query(topic, opts) {
|
|
5849
|
-
const queryTokens = new Set(tokenize4(topic));
|
|
5850
|
-
if (queryTokens.size === 0) return [];
|
|
5851
|
-
const minStr = opts?.minStrength ?? this.config.minStrength;
|
|
5852
|
-
const limit = opts?.limit ?? this.config.topKRetrieval;
|
|
5853
|
-
const scored = [];
|
|
5854
|
-
for (const trace of this.traces.values()) {
|
|
5855
|
-
if (trace.strength < minStr) continue;
|
|
5856
|
-
if (opts?.type && trace.traceType !== opts.type) continue;
|
|
5857
|
-
const traceTokens = /* @__PURE__ */ new Set([...tokenize4(trace.topic), ...tokenize4(trace.content)]);
|
|
5858
|
-
const similarity = jaccardSimilarity2(queryTokens, traceTokens);
|
|
5859
|
-
if (similarity <= 0) continue;
|
|
5860
|
-
scored.push({ trace, score: similarity * trace.strength });
|
|
5861
|
-
}
|
|
5862
|
-
scored.sort((a, b) => b.score - a.score);
|
|
5863
|
-
return scored.slice(0, limit).map((s) => s.trace);
|
|
5864
|
-
}
|
|
5865
|
-
/**
|
|
5866
|
-
* Get the strongest traces overall -- the "highways" of collective knowledge.
|
|
5867
|
-
*
|
|
5868
|
-
* @param limit - Maximum number of traces to return.
|
|
5869
|
-
* @returns Traces sorted by strength descending.
|
|
5870
|
-
*/
|
|
5871
|
-
strongest(limit) {
|
|
5872
|
-
const all = [...this.traces.values()];
|
|
5873
|
-
all.sort((a, b) => b.strength - a.strength);
|
|
5874
|
-
return all.slice(0, limit ?? this.config.topKRetrieval);
|
|
5875
|
-
}
|
|
5876
|
-
/**
|
|
5877
|
-
* Get traces left by a specific agent.
|
|
5878
|
-
*
|
|
5879
|
-
* @param agentId - The agent whose traces to retrieve.
|
|
5880
|
-
* @param limit - Maximum results.
|
|
5881
|
-
* @returns Traces by the agent, sorted by creation time descending.
|
|
5882
|
-
*/
|
|
5883
|
-
byAgent(agentId, limit) {
|
|
5884
|
-
const results = [];
|
|
5885
|
-
for (const trace of this.traces.values()) {
|
|
5886
|
-
if (trace.agentId === agentId) results.push(trace);
|
|
5887
|
-
}
|
|
5888
|
-
results.sort((a, b) => b.createdAt - a.createdAt);
|
|
5889
|
-
return results.slice(0, limit ?? this.config.topKRetrieval);
|
|
5890
|
-
}
|
|
5891
|
-
// ─── Decay & Maintenance ─────────────────────────────────────────────
|
|
5892
|
-
/**
|
|
5893
|
-
* Apply temporal decay to all traces. Traces that fall below `minStrength`
|
|
5894
|
-
* after decay are pruned automatically.
|
|
5895
|
-
*
|
|
5896
|
-
* @returns Counts of decayed and pruned traces.
|
|
5897
|
-
*/
|
|
5898
|
-
decay() {
|
|
5899
|
-
const now = Date.now();
|
|
5900
|
-
const baseHalfLife = this.config.decayHalfLife;
|
|
5901
|
-
const beta = this.config.frequencyDecayBeta;
|
|
5902
|
-
let decayed = 0;
|
|
5903
|
-
const toPrune = [];
|
|
5904
|
-
for (const [id, trace] of this.traces) {
|
|
5905
|
-
const elapsed = now - trace.lastReinforcedAt;
|
|
5906
|
-
if (elapsed <= 0) continue;
|
|
5907
|
-
const effectiveHalfLife = baseHalfLife * (1 + beta * Math.log(1 + trace.reinforcements));
|
|
5908
|
-
const factor = Math.exp(-Math.LN2 * elapsed / effectiveHalfLife);
|
|
5909
|
-
const newStrength = trace.strength * factor;
|
|
5910
|
-
if (Math.abs(newStrength - trace.strength) > 1e-10) {
|
|
5911
|
-
trace.strength = newStrength;
|
|
5912
|
-
decayed++;
|
|
5913
|
-
}
|
|
5914
|
-
if (trace.strength < this.config.minStrength) toPrune.push(id);
|
|
5915
|
-
}
|
|
5916
|
-
for (const id of toPrune) {
|
|
5917
|
-
this.traces.delete(id);
|
|
5918
|
-
this.reinforcedBy.delete(id);
|
|
5919
|
-
}
|
|
5920
|
-
return { decayed, pruned: toPrune.length };
|
|
5921
|
-
}
|
|
5922
|
-
/**
|
|
5923
|
-
* Remove traces below the minStrength threshold.
|
|
5924
|
-
*
|
|
5925
|
-
* @returns The number of traces pruned.
|
|
5926
|
-
*/
|
|
5927
|
-
prune() {
|
|
5928
|
-
const toPrune = [];
|
|
5929
|
-
for (const [id, trace] of this.traces) {
|
|
5930
|
-
if (trace.strength < this.config.minStrength) toPrune.push(id);
|
|
5931
|
-
}
|
|
5932
|
-
for (const id of toPrune) {
|
|
5933
|
-
this.traces.delete(id);
|
|
5934
|
-
this.reinforcedBy.delete(id);
|
|
5935
|
-
}
|
|
5936
|
-
return toPrune.length;
|
|
5937
|
-
}
|
|
5938
|
-
// ─── Persistence (delegated to akasha-integration) ───────────────────
|
|
5939
|
-
/**
|
|
5940
|
-
* Persist all traces to a SQLite database.
|
|
5941
|
-
*
|
|
5942
|
-
* @param db - A duck-typed database handle with prepare/exec methods.
|
|
5943
|
-
*/
|
|
5944
|
-
persist(db) {
|
|
5945
|
-
persistTraces(this.traces, db);
|
|
5946
|
-
}
|
|
5947
|
-
/**
|
|
5948
|
-
* Restore traces from a SQLite database.
|
|
5949
|
-
*
|
|
5950
|
-
* @param db - A duck-typed database handle with prepare/exec methods.
|
|
5951
|
-
*/
|
|
5952
|
-
restore(db) {
|
|
5953
|
-
const result = restoreTraces(db, this.config);
|
|
5954
|
-
this.traces.clear();
|
|
5955
|
-
this.reinforcedBy.clear();
|
|
5956
|
-
for (const [k, v] of result.traces) this.traces.set(k, v);
|
|
5957
|
-
for (const [k, v] of result.reinforcedBy) this.reinforcedBy.set(k, v);
|
|
5958
|
-
}
|
|
5959
|
-
// ─── GraphRAG (delegated to akasha-integration) ──────────────────────
|
|
5960
|
-
/**
|
|
5961
|
-
* Register traces as graph nodes suitable for GraphRAG retrieval.
|
|
5962
|
-
*
|
|
5963
|
-
* @returns An array of graph-compatible node objects.
|
|
5964
|
-
*/
|
|
5965
|
-
toGraphNodes() {
|
|
5966
|
-
return tracesToGraphNodes(this.traces, this.config.minStrength);
|
|
5967
|
-
}
|
|
5968
|
-
/**
|
|
5969
|
-
* Boost graph search results that have matching stigmergic traces.
|
|
5970
|
-
*
|
|
5971
|
-
* @param results - The original search results with id and score.
|
|
5972
|
-
* @param query - The search query used for topic matching.
|
|
5973
|
-
* @returns Results with boosted scores and traceBoost metadata.
|
|
5974
|
-
*/
|
|
5975
|
-
boostResults(results, query) {
|
|
5976
|
-
return boostResultsWithTraces(this.traces, this.config, results, query);
|
|
5977
|
-
}
|
|
5978
|
-
// ─── Stats ───────────────────────────────────────────────────────────
|
|
5979
|
-
/**
|
|
5980
|
-
* Return statistics about the current state of the Akasha field.
|
|
5981
|
-
*
|
|
5982
|
-
* @returns Total/active counts, per-type breakdown, average strength,
|
|
5983
|
-
* strongest topic, and total reinforcements.
|
|
5984
|
-
*/
|
|
5985
|
-
stats() {
|
|
5986
|
-
const byType = {
|
|
5987
|
-
solution: 0,
|
|
5988
|
-
warning: 0,
|
|
5989
|
-
shortcut: 0,
|
|
5990
|
-
pattern: 0,
|
|
5991
|
-
correction: 0,
|
|
5992
|
-
preference: 0
|
|
5993
|
-
};
|
|
5994
|
-
let totalStrength = 0;
|
|
5995
|
-
let activeCount = 0;
|
|
5996
|
-
let totalReinforcements = 0;
|
|
5997
|
-
let strongestTrace = null;
|
|
5998
|
-
for (const trace of this.traces.values()) {
|
|
5999
|
-
byType[trace.traceType]++;
|
|
6000
|
-
totalStrength += trace.strength;
|
|
6001
|
-
totalReinforcements += trace.reinforcements;
|
|
6002
|
-
if (trace.strength >= this.config.minStrength) activeCount++;
|
|
6003
|
-
if (!strongestTrace || trace.strength > strongestTrace.strength) {
|
|
6004
|
-
strongestTrace = trace;
|
|
6005
|
-
}
|
|
6006
|
-
}
|
|
6007
|
-
return {
|
|
6008
|
-
totalTraces: this.traces.size,
|
|
6009
|
-
activeTraces: activeCount,
|
|
6010
|
-
byType,
|
|
6011
|
-
avgStrength: this.traces.size > 0 ? totalStrength / this.traces.size : 0,
|
|
6012
|
-
strongestTopic: strongestTrace?.topic ?? null,
|
|
6013
|
-
totalReinforcements
|
|
6014
|
-
};
|
|
6015
|
-
}
|
|
6016
|
-
// ─── Internal Helpers ────────────────────────────────────────────────
|
|
6017
|
-
/** Evict the weakest trace. Ties broken by oldest createdAt. */
|
|
6018
|
-
evictWeakest() {
|
|
6019
|
-
let weakestId = null;
|
|
6020
|
-
let weakestStrength = Infinity;
|
|
6021
|
-
let weakestCreatedAt = Infinity;
|
|
6022
|
-
for (const [id, trace] of this.traces) {
|
|
6023
|
-
if (trace.strength < weakestStrength || trace.strength === weakestStrength && trace.createdAt < weakestCreatedAt) {
|
|
6024
|
-
weakestId = id;
|
|
6025
|
-
weakestStrength = trace.strength;
|
|
6026
|
-
weakestCreatedAt = trace.createdAt;
|
|
6027
|
-
}
|
|
6028
|
-
}
|
|
6029
|
-
if (!weakestId && this.traces.size > 0) {
|
|
6030
|
-
weakestId = this.traces.keys().next().value;
|
|
6031
|
-
}
|
|
6032
|
-
if (weakestId) {
|
|
6033
|
-
this.traces.delete(weakestId);
|
|
6034
|
-
this.reinforcedBy.delete(weakestId);
|
|
6035
|
-
}
|
|
6036
|
-
}
|
|
6037
|
-
};
|
|
6038
|
-
|
|
6039
|
-
// ../chitragupta/packages/smriti/src/temporal-context.ts
|
|
5673
|
+
// ../chitragupta/packages/smriti/dist/temporal-context.js
|
|
6040
5674
|
var MINUTE = 6e4;
|
|
6041
5675
|
var HOUR = 36e5;
|
|
6042
5676
|
var DAY = 864e5;
|
|
@@ -6065,7 +5699,7 @@ var DEFAULT_SCALE_WEIGHTS = {
|
|
|
6065
5699
|
quarter: 0.08,
|
|
6066
5700
|
year: 0.07
|
|
6067
5701
|
};
|
|
6068
|
-
var
|
|
5702
|
+
var HARD_CEILINGS = {
|
|
6069
5703
|
/** Minimum half-life: 1 second. Anything faster is meaningless. */
|
|
6070
5704
|
minDecayRate: 1e3,
|
|
6071
5705
|
/** Maximum half-life: 10 years. Beyond this, nothing decays. */
|
|
@@ -6230,7 +5864,7 @@ function buildTemporalContext(state, db, now) {
|
|
|
6230
5864
|
};
|
|
6231
5865
|
}
|
|
6232
5866
|
|
|
6233
|
-
// ../chitragupta/packages/smriti/
|
|
5867
|
+
// ../chitragupta/packages/smriti/dist/kala-chakra.js
|
|
6234
5868
|
var TEMPORAL_SCALES = [
|
|
6235
5869
|
"turn",
|
|
6236
5870
|
"session",
|
|
@@ -6250,22 +5884,14 @@ var KalaChakra = class {
|
|
|
6250
5884
|
if (config?.decayRates) {
|
|
6251
5885
|
for (const scale of TEMPORAL_SCALES) {
|
|
6252
5886
|
if (config.decayRates[scale] !== void 0) {
|
|
6253
|
-
this._decayRates[scale] = clamp(
|
|
6254
|
-
config.decayRates[scale],
|
|
6255
|
-
HARD_CEILINGS2.minDecayRate,
|
|
6256
|
-
HARD_CEILINGS2.maxDecayRate
|
|
6257
|
-
);
|
|
5887
|
+
this._decayRates[scale] = clamp(config.decayRates[scale], HARD_CEILINGS.minDecayRate, HARD_CEILINGS.maxDecayRate);
|
|
6258
5888
|
}
|
|
6259
5889
|
}
|
|
6260
5890
|
}
|
|
6261
5891
|
if (config?.scaleWeights) {
|
|
6262
5892
|
for (const scale of TEMPORAL_SCALES) {
|
|
6263
5893
|
if (config.scaleWeights[scale] !== void 0) {
|
|
6264
|
-
this._scaleWeights[scale] = clamp(
|
|
6265
|
-
config.scaleWeights[scale],
|
|
6266
|
-
HARD_CEILINGS2.minWeight,
|
|
6267
|
-
HARD_CEILINGS2.maxWeight
|
|
6268
|
-
);
|
|
5894
|
+
this._scaleWeights[scale] = clamp(config.scaleWeights[scale], HARD_CEILINGS.minWeight, HARD_CEILINGS.maxWeight);
|
|
6269
5895
|
}
|
|
6270
5896
|
}
|
|
6271
5897
|
}
|
|
@@ -6346,7 +5972,8 @@ var KalaChakra = class {
|
|
|
6346
5972
|
dominantScale(elapsedMs) {
|
|
6347
5973
|
const abs = Math.abs(elapsedMs);
|
|
6348
5974
|
for (const [threshold, scale] of SCALE_BOUNDARIES) {
|
|
6349
|
-
if (abs < threshold)
|
|
5975
|
+
if (abs < threshold)
|
|
5976
|
+
return scale;
|
|
6350
5977
|
}
|
|
6351
5978
|
return "year";
|
|
6352
5979
|
}
|
|
@@ -6402,26 +6029,19 @@ var KalaChakra = class {
|
|
|
6402
6029
|
* @param data - Previously serialized state from `serialize()`.
|
|
6403
6030
|
*/
|
|
6404
6031
|
restore(data) {
|
|
6405
|
-
if (!data || typeof data !== "object")
|
|
6032
|
+
if (!data || typeof data !== "object")
|
|
6033
|
+
return;
|
|
6406
6034
|
if (data.decayRates && typeof data.decayRates === "object") {
|
|
6407
6035
|
for (const scale of TEMPORAL_SCALES) {
|
|
6408
6036
|
if (typeof data.decayRates[scale] === "number") {
|
|
6409
|
-
this._decayRates[scale] = clamp(
|
|
6410
|
-
data.decayRates[scale],
|
|
6411
|
-
HARD_CEILINGS2.minDecayRate,
|
|
6412
|
-
HARD_CEILINGS2.maxDecayRate
|
|
6413
|
-
);
|
|
6037
|
+
this._decayRates[scale] = clamp(data.decayRates[scale], HARD_CEILINGS.minDecayRate, HARD_CEILINGS.maxDecayRate);
|
|
6414
6038
|
}
|
|
6415
6039
|
}
|
|
6416
6040
|
}
|
|
6417
6041
|
if (data.scaleWeights && typeof data.scaleWeights === "object") {
|
|
6418
6042
|
for (const scale of TEMPORAL_SCALES) {
|
|
6419
6043
|
if (typeof data.scaleWeights[scale] === "number") {
|
|
6420
|
-
this._scaleWeights[scale] = clamp(
|
|
6421
|
-
data.scaleWeights[scale],
|
|
6422
|
-
HARD_CEILINGS2.minWeight,
|
|
6423
|
-
HARD_CEILINGS2.maxWeight
|
|
6424
|
-
);
|
|
6044
|
+
this._scaleWeights[scale] = clamp(data.scaleWeights[scale], HARD_CEILINGS.minWeight, HARD_CEILINGS.maxWeight);
|
|
6425
6045
|
}
|
|
6426
6046
|
}
|
|
6427
6047
|
}
|
|
@@ -6439,7 +6059,8 @@ var KalaChakra = class {
|
|
|
6439
6059
|
/** Compute exponential decay for a given elapsed time and scale. */
|
|
6440
6060
|
_decayForScale(elapsedMs, scale) {
|
|
6441
6061
|
const halfLife = this._decayRates[scale];
|
|
6442
|
-
if (halfLife <= 0)
|
|
6062
|
+
if (halfLife <= 0)
|
|
6063
|
+
return 0;
|
|
6443
6064
|
return Math.exp(-LN2 * elapsedMs / halfLife);
|
|
6444
6065
|
}
|
|
6445
6066
|
};
|
|
@@ -6447,14 +6068,14 @@ function clamp(value, min, max) {
|
|
|
6447
6068
|
return Math.max(min, Math.min(max, value));
|
|
6448
6069
|
}
|
|
6449
6070
|
|
|
6450
|
-
// ../chitragupta/packages/smriti/
|
|
6451
|
-
var
|
|
6452
|
-
var
|
|
6453
|
-
function
|
|
6454
|
-
let hash =
|
|
6071
|
+
// ../chitragupta/packages/smriti/dist/pancha-vritti-patterns.js
|
|
6072
|
+
var FNV_OFFSET6 = 2166136261;
|
|
6073
|
+
var FNV_PRIME6 = 16777619;
|
|
6074
|
+
function fnv1a7(input) {
|
|
6075
|
+
let hash = FNV_OFFSET6;
|
|
6455
6076
|
for (let i = 0; i < input.length; i++) {
|
|
6456
6077
|
hash ^= input.charCodeAt(i);
|
|
6457
|
-
hash = Math.imul(hash,
|
|
6078
|
+
hash = Math.imul(hash, FNV_PRIME6);
|
|
6458
6079
|
}
|
|
6459
6080
|
return (hash >>> 0).toString(16).padStart(8, "0");
|
|
6460
6081
|
}
|
|
@@ -6580,7 +6201,7 @@ var SMRITI_TOOLS = /* @__PURE__ */ new Set([
|
|
|
6580
6201
|
"chitragupta_memory_search"
|
|
6581
6202
|
]);
|
|
6582
6203
|
|
|
6583
|
-
// ../chitragupta/packages/smriti/
|
|
6204
|
+
// ../chitragupta/packages/smriti/dist/pancha-vritti.js
|
|
6584
6205
|
var VRITTI_TYPES = [
|
|
6585
6206
|
"pramana",
|
|
6586
6207
|
"viparyaya",
|
|
@@ -6595,13 +6216,13 @@ var VRITTI_CONFIDENCE_WEIGHTS = {
|
|
|
6595
6216
|
vikalpa: 0.5,
|
|
6596
6217
|
viparyaya: 0.3
|
|
6597
6218
|
};
|
|
6598
|
-
var
|
|
6219
|
+
var DEFAULT_CONFIG6 = {
|
|
6599
6220
|
maxClassifications: 5e3,
|
|
6600
6221
|
minConfidence: 0.4,
|
|
6601
6222
|
snippetMaxLength: 200,
|
|
6602
6223
|
confidenceWeights: { ...VRITTI_CONFIDENCE_WEIGHTS }
|
|
6603
6224
|
};
|
|
6604
|
-
var
|
|
6225
|
+
var HARD_CEILINGS2 = {
|
|
6605
6226
|
maxClassifications: 5e4,
|
|
6606
6227
|
snippetMaxLength: 1e3
|
|
6607
6228
|
};
|
|
@@ -6612,24 +6233,18 @@ var PanchaVritti = class {
|
|
|
6612
6233
|
totalReclassified = 0;
|
|
6613
6234
|
constructor(config) {
|
|
6614
6235
|
const merged = {
|
|
6615
|
-
...
|
|
6236
|
+
...DEFAULT_CONFIG6,
|
|
6616
6237
|
...config,
|
|
6617
6238
|
confidenceWeights: {
|
|
6618
|
-
...
|
|
6239
|
+
...DEFAULT_CONFIG6.confidenceWeights,
|
|
6619
6240
|
...config?.confidenceWeights
|
|
6620
6241
|
}
|
|
6621
6242
|
};
|
|
6622
|
-
if (typeof
|
|
6623
|
-
merged.maxClassifications = Math.min(
|
|
6624
|
-
|
|
6625
|
-
|
|
6626
|
-
);
|
|
6627
|
-
}
|
|
6628
|
-
if (typeof HARD_CEILINGS3.snippetMaxLength === "number") {
|
|
6629
|
-
merged.snippetMaxLength = Math.min(
|
|
6630
|
-
merged.snippetMaxLength,
|
|
6631
|
-
HARD_CEILINGS3.snippetMaxLength
|
|
6632
|
-
);
|
|
6243
|
+
if (typeof HARD_CEILINGS2.maxClassifications === "number") {
|
|
6244
|
+
merged.maxClassifications = Math.min(merged.maxClassifications, HARD_CEILINGS2.maxClassifications);
|
|
6245
|
+
}
|
|
6246
|
+
if (typeof HARD_CEILINGS2.snippetMaxLength === "number") {
|
|
6247
|
+
merged.snippetMaxLength = Math.min(merged.snippetMaxLength, HARD_CEILINGS2.snippetMaxLength);
|
|
6633
6248
|
}
|
|
6634
6249
|
this.cfg = merged;
|
|
6635
6250
|
}
|
|
@@ -6658,7 +6273,7 @@ var PanchaVritti = class {
|
|
|
6658
6273
|
prePatterns.push("context:error-flag");
|
|
6659
6274
|
}
|
|
6660
6275
|
if (content.trim().length === 0) {
|
|
6661
|
-
const id2 =
|
|
6276
|
+
const id2 = fnv1a7("nidra:" + now.toString());
|
|
6662
6277
|
const classification2 = {
|
|
6663
6278
|
id: id2,
|
|
6664
6279
|
type: "nidra",
|
|
@@ -6682,7 +6297,7 @@ var PanchaVritti = class {
|
|
|
6682
6297
|
if (winnerConfidence < this.cfg.minConfidence) {
|
|
6683
6298
|
allPatterns.push("low-confidence");
|
|
6684
6299
|
}
|
|
6685
|
-
const id =
|
|
6300
|
+
const id = fnv1a7(winnerType + ":" + content.slice(0, 100) + ":" + now.toString());
|
|
6686
6301
|
const classification = {
|
|
6687
6302
|
id,
|
|
6688
6303
|
type: winnerType,
|
|
@@ -6711,9 +6326,11 @@ var PanchaVritti = class {
|
|
|
6711
6326
|
*/
|
|
6712
6327
|
reclassify(id, newType, reason) {
|
|
6713
6328
|
const existing = this.classifications.get(id);
|
|
6714
|
-
if (!existing)
|
|
6329
|
+
if (!existing)
|
|
6330
|
+
throw new Error(`Classification not found: ${id}`);
|
|
6715
6331
|
const oldType = existing.type;
|
|
6716
|
-
if (oldType === newType)
|
|
6332
|
+
if (oldType === newType)
|
|
6333
|
+
return;
|
|
6717
6334
|
existing.history.push({ from: oldType, to: newType, reason, at: Date.now() });
|
|
6718
6335
|
existing.type = newType;
|
|
6719
6336
|
this.totalReclassified++;
|
|
@@ -6731,7 +6348,8 @@ var PanchaVritti = class {
|
|
|
6731
6348
|
getByType(type) {
|
|
6732
6349
|
const result = [];
|
|
6733
6350
|
for (const c of this.classifications.values()) {
|
|
6734
|
-
if (c.type === type)
|
|
6351
|
+
if (c.type === type)
|
|
6352
|
+
result.push(c);
|
|
6735
6353
|
}
|
|
6736
6354
|
return result;
|
|
6737
6355
|
}
|
|
@@ -6790,7 +6408,8 @@ var PanchaVritti = class {
|
|
|
6790
6408
|
/** Restore state from a serialized snapshot. */
|
|
6791
6409
|
deserialize(state) {
|
|
6792
6410
|
this.classifications.clear();
|
|
6793
|
-
for (const c of state.classifications)
|
|
6411
|
+
for (const c of state.classifications)
|
|
6412
|
+
this.classifications.set(c.id, c);
|
|
6794
6413
|
this.totalClassified = state.totalClassified;
|
|
6795
6414
|
this.totalReclassified = state.totalReclassified;
|
|
6796
6415
|
}
|
|
@@ -6852,21 +6471,23 @@ var PanchaVritti = class {
|
|
|
6852
6471
|
oldestId = id;
|
|
6853
6472
|
}
|
|
6854
6473
|
}
|
|
6855
|
-
if (oldestId)
|
|
6474
|
+
if (oldestId)
|
|
6475
|
+
this.classifications.delete(oldestId);
|
|
6856
6476
|
}
|
|
6857
6477
|
}
|
|
6858
6478
|
};
|
|
6859
6479
|
|
|
6860
|
-
// ../chitragupta/packages/smriti/
|
|
6480
|
+
// ../chitragupta/packages/smriti/dist/unified-recall.js
|
|
6861
6481
|
async function recall(query, options) {
|
|
6862
6482
|
const limit = options?.limit ?? 5;
|
|
6863
6483
|
const answers = [];
|
|
6864
|
-
const [hybridResults, turnFallbackResults, memoryResults, dayFileResults] = await Promise.allSettled([
|
|
6484
|
+
const [hybridResults, turnFallbackResults, memoryResults, dayFileResults, akashaResults] = await Promise.allSettled([
|
|
6865
6485
|
searchHybrid(query, options?.project, limit),
|
|
6866
6486
|
// FTS5 fallback runs in parallel — used only if hybrid fails
|
|
6867
6487
|
searchTurns(query, options?.project),
|
|
6868
6488
|
options?.includeMemory !== false ? searchMemoryLayer(query) : Promise.resolve([]),
|
|
6869
|
-
options?.includeDayFiles !== false ? searchDayFileLayer(query, limit) : Promise.resolve([])
|
|
6489
|
+
options?.includeDayFiles !== false ? searchDayFileLayer(query, limit) : Promise.resolve([]),
|
|
6490
|
+
options?.includeAkasha !== false ? searchAkashaLayer(query, limit) : Promise.resolve([])
|
|
6870
6491
|
]);
|
|
6871
6492
|
let usedHybrid = false;
|
|
6872
6493
|
if (hybridResults.status === "fulfilled" && hybridResults.value.length > 0) {
|
|
@@ -6899,43 +6520,46 @@ async function recall(query, options) {
|
|
|
6899
6520
|
answers.push(result);
|
|
6900
6521
|
}
|
|
6901
6522
|
}
|
|
6523
|
+
if (akashaResults.status === "fulfilled") {
|
|
6524
|
+
for (const result of akashaResults.value.slice(0, limit)) {
|
|
6525
|
+
answers.push(result);
|
|
6526
|
+
}
|
|
6527
|
+
}
|
|
6902
6528
|
const ranked = deduplicateAnswers(answers);
|
|
6903
6529
|
ranked.sort((a, b) => b.score - a.score);
|
|
6904
6530
|
return ranked.slice(0, limit);
|
|
6905
6531
|
}
|
|
6906
6532
|
async function searchHybrid(query, project, limit) {
|
|
6907
6533
|
try {
|
|
6908
|
-
const { HybridSearchEngine: HybridSearchEngine2 } = await import("./hybrid-search-
|
|
6534
|
+
const { HybridSearchEngine: HybridSearchEngine2 } = await import("./hybrid-search-OD756RDV.js");
|
|
6909
6535
|
let recallEngine = null;
|
|
6910
6536
|
let graphEngine = null;
|
|
6911
6537
|
try {
|
|
6912
|
-
const { RecallEngine: RecallEngine2 } = await import("./recall-
|
|
6538
|
+
const { RecallEngine: RecallEngine2 } = await import("./recall-64RROTUC.js");
|
|
6913
6539
|
recallEngine = new RecallEngine2();
|
|
6914
6540
|
} catch {
|
|
6915
6541
|
}
|
|
6916
6542
|
try {
|
|
6917
|
-
const { GraphRAGEngine: GraphRAGEngine2 } = await import("./graphrag-
|
|
6543
|
+
const { GraphRAGEngine: GraphRAGEngine2 } = await import("./graphrag-73XA7LBX.js");
|
|
6918
6544
|
graphEngine = new GraphRAGEngine2();
|
|
6919
6545
|
} catch {
|
|
6920
6546
|
}
|
|
6921
|
-
const hybrid = new HybridSearchEngine2(
|
|
6922
|
-
|
|
6923
|
-
|
|
6924
|
-
|
|
6925
|
-
|
|
6926
|
-
|
|
6927
|
-
|
|
6928
|
-
|
|
6929
|
-
},
|
|
6930
|
-
recallEngine ?? void 0,
|
|
6931
|
-
graphEngine ?? void 0
|
|
6932
|
-
);
|
|
6547
|
+
const hybrid = new HybridSearchEngine2({
|
|
6548
|
+
project,
|
|
6549
|
+
topK: limit ?? 10,
|
|
6550
|
+
enableBM25: true,
|
|
6551
|
+
enableVector: recallEngine !== null,
|
|
6552
|
+
enableGraphRAG: graphEngine !== null,
|
|
6553
|
+
enablePramana: true
|
|
6554
|
+
}, recallEngine ?? void 0, graphEngine ?? void 0);
|
|
6933
6555
|
const results = await hybrid.search(query);
|
|
6934
6556
|
return results.map((r) => {
|
|
6935
6557
|
let primarySource = "hybrid";
|
|
6936
6558
|
if (r.sources.length === 1) {
|
|
6937
|
-
if (r.sources[0] === "bm25")
|
|
6938
|
-
|
|
6559
|
+
if (r.sources[0] === "bm25")
|
|
6560
|
+
primarySource = "turns";
|
|
6561
|
+
else if (r.sources[0] === "graphrag")
|
|
6562
|
+
primarySource = "graph";
|
|
6939
6563
|
}
|
|
6940
6564
|
const normalizedScore = Math.min(r.score / (r.score + 0.5), 1);
|
|
6941
6565
|
return {
|
|
@@ -6952,8 +6576,8 @@ async function searchHybrid(query, project, limit) {
|
|
|
6952
6576
|
}
|
|
6953
6577
|
async function searchTurns(query, project) {
|
|
6954
6578
|
try {
|
|
6955
|
-
const { searchSessions: searchSessions2 } = await import("./search-
|
|
6956
|
-
const { loadSession: loadSession2 } = await import("./session-store-
|
|
6579
|
+
const { searchSessions: searchSessions2 } = await import("./search-JVCDNTAJ.js");
|
|
6580
|
+
const { loadSession: loadSession2 } = await import("./session-store-3EDQZEDS.js");
|
|
6957
6581
|
const metas = searchSessions2(query, project);
|
|
6958
6582
|
const results = [];
|
|
6959
6583
|
for (const meta of metas.slice(0, 10)) {
|
|
@@ -6966,7 +6590,8 @@ async function searchTurns(query, project) {
|
|
|
6966
6590
|
const content = turn.content.toLowerCase();
|
|
6967
6591
|
let termHits = 0;
|
|
6968
6592
|
for (const term of queryTerms) {
|
|
6969
|
-
if (term.length > 2 && content.includes(term))
|
|
6593
|
+
if (term.length > 2 && content.includes(term))
|
|
6594
|
+
termHits++;
|
|
6970
6595
|
}
|
|
6971
6596
|
const score = queryTerms.length > 0 ? termHits / queryTerms.length : 0;
|
|
6972
6597
|
if (score > bestScore) {
|
|
@@ -6999,9 +6624,9 @@ async function searchTurns(query, project) {
|
|
|
6999
6624
|
}
|
|
7000
6625
|
async function searchMemoryLayer(query) {
|
|
7001
6626
|
try {
|
|
7002
|
-
const { searchMemory: searchMemory2 } = await import("./search-
|
|
6627
|
+
const { searchMemory: searchMemory2 } = await import("./search-JVCDNTAJ.js");
|
|
7003
6628
|
const results = searchMemory2(query);
|
|
7004
|
-
return results.slice(0, 5).map((r) => ({
|
|
6629
|
+
return results.slice(0, 5).filter((r) => !isLowValueMemoryEntry(r.content)).map((r) => ({
|
|
7005
6630
|
score: Math.min((r.relevance ?? 0.5) + 0.1, 1),
|
|
7006
6631
|
answer: `From memory: ${r.content.slice(0, 300)}`,
|
|
7007
6632
|
primarySource: "memory",
|
|
@@ -7011,9 +6636,20 @@ async function searchMemoryLayer(query) {
|
|
|
7011
6636
|
return [];
|
|
7012
6637
|
}
|
|
7013
6638
|
}
|
|
6639
|
+
function isLowValueMemoryEntry(content) {
|
|
6640
|
+
const trimmed = content.trim();
|
|
6641
|
+
if (/^\[(?:action|tool)\].*file\(s\)/i.test(trimmed))
|
|
6642
|
+
return true;
|
|
6643
|
+
if (/^(?:File|Created|Modified|Edited|Deleted)[:\s]+\S+\.\w+$/i.test(trimmed))
|
|
6644
|
+
return true;
|
|
6645
|
+
const bracketMatch = trimmed.match(/^\[\w+\]\s*(.*)/);
|
|
6646
|
+
if (bracketMatch && bracketMatch[1].length < 10)
|
|
6647
|
+
return true;
|
|
6648
|
+
return false;
|
|
6649
|
+
}
|
|
7014
6650
|
async function searchDayFileLayer(query, limit) {
|
|
7015
6651
|
try {
|
|
7016
|
-
const { hierarchicalTemporalSearch: hierarchicalTemporalSearch2 } = await import("./hierarchical-temporal-search-
|
|
6652
|
+
const { hierarchicalTemporalSearch: hierarchicalTemporalSearch2 } = await import("./hierarchical-temporal-search-GHKVKNZ6.js");
|
|
7017
6653
|
const results = await hierarchicalTemporalSearch2(query, { limit });
|
|
7018
6654
|
if (results.length > 0) {
|
|
7019
6655
|
return results.map((r) => ({
|
|
@@ -7028,7 +6664,7 @@ async function searchDayFileLayer(query, limit) {
|
|
|
7028
6664
|
} catch {
|
|
7029
6665
|
}
|
|
7030
6666
|
try {
|
|
7031
|
-
const { searchDayFiles: searchDayFiles2 } = await import("./day-consolidation-
|
|
6667
|
+
const { searchDayFiles: searchDayFiles2 } = await import("./day-consolidation-CR3TJFAL.js");
|
|
7032
6668
|
const results = searchDayFiles2(query, { limit });
|
|
7033
6669
|
return results.map((r) => ({
|
|
7034
6670
|
score: 0.5,
|
|
@@ -7041,17 +6677,50 @@ async function searchDayFileLayer(query, limit) {
|
|
|
7041
6677
|
return [];
|
|
7042
6678
|
}
|
|
7043
6679
|
}
|
|
6680
|
+
async function searchAkashaLayer(query, limit) {
|
|
6681
|
+
try {
|
|
6682
|
+
const { AkashaField: AkashaField2 } = await import("./akasha-5C5Q6NMP.js");
|
|
6683
|
+
const akasha = new AkashaField2();
|
|
6684
|
+
try {
|
|
6685
|
+
const { DatabaseManager: DatabaseManager2 } = await import("./database-BX3LVYXS.js");
|
|
6686
|
+
const dbm = DatabaseManager2.instance();
|
|
6687
|
+
const db = dbm.get("agent");
|
|
6688
|
+
if (db) {
|
|
6689
|
+
akasha.restore(db);
|
|
6690
|
+
}
|
|
6691
|
+
} catch {
|
|
6692
|
+
}
|
|
6693
|
+
const traces = akasha.query(query, { limit });
|
|
6694
|
+
if (traces.length === 0)
|
|
6695
|
+
return [];
|
|
6696
|
+
return traces.map((trace) => {
|
|
6697
|
+
const score = Math.min(trace.strength * 0.8 + 0.2, 1);
|
|
6698
|
+
const typeLabel = trace.traceType.toUpperCase();
|
|
6699
|
+
const snippet = trace.content.slice(0, 300);
|
|
6700
|
+
const answer = `[Akasha ${typeLabel}] ${trace.topic}: ${snippet}`;
|
|
6701
|
+
return {
|
|
6702
|
+
score,
|
|
6703
|
+
answer,
|
|
6704
|
+
primarySource: "akasha",
|
|
6705
|
+
snippet
|
|
6706
|
+
};
|
|
6707
|
+
});
|
|
6708
|
+
} catch {
|
|
6709
|
+
return [];
|
|
6710
|
+
}
|
|
6711
|
+
}
|
|
7044
6712
|
function deduplicateAnswers(answers) {
|
|
7045
6713
|
const seen = /* @__PURE__ */ new Set();
|
|
7046
6714
|
return answers.filter((a) => {
|
|
7047
6715
|
const key = a.sessionId ? `session:${a.sessionId}` : `${a.primarySource}:${a.snippet.slice(0, 50).toLowerCase()}`;
|
|
7048
|
-
if (seen.has(key))
|
|
6716
|
+
if (seen.has(key))
|
|
6717
|
+
return false;
|
|
7049
6718
|
seen.add(key);
|
|
7050
6719
|
return true;
|
|
7051
6720
|
});
|
|
7052
6721
|
}
|
|
7053
6722
|
|
|
7054
|
-
// ../chitragupta/packages/smriti/
|
|
6723
|
+
// ../chitragupta/packages/smriti/dist/provider-bridge.js
|
|
7055
6724
|
async function loadProviderContext(project, options) {
|
|
7056
6725
|
const maxLen = options?.maxContextLength ?? 4e3;
|
|
7057
6726
|
const recentLimit = options?.recentSessionLimit ?? 3;
|
|
@@ -7059,7 +6728,7 @@ async function loadProviderContext(project, options) {
|
|
|
7059
6728
|
let projectMemory = "";
|
|
7060
6729
|
let recentContext = "";
|
|
7061
6730
|
try {
|
|
7062
|
-
const { getMemory: getMemory2 } = await import("./memory-store-
|
|
6731
|
+
const { getMemory: getMemory2 } = await import("./memory-store-4GCBR2DZ.js");
|
|
7063
6732
|
globalFacts = getMemory2({ type: "global" });
|
|
7064
6733
|
if (globalFacts.length > maxLen / 3) {
|
|
7065
6734
|
globalFacts = globalFacts.slice(0, maxLen / 3) + "\n...(truncated)";
|
|
@@ -7068,7 +6737,7 @@ async function loadProviderContext(project, options) {
|
|
|
7068
6737
|
}
|
|
7069
6738
|
if (project) {
|
|
7070
6739
|
try {
|
|
7071
|
-
const { getMemory: getMemory2 } = await import("./memory-store-
|
|
6740
|
+
const { getMemory: getMemory2 } = await import("./memory-store-4GCBR2DZ.js");
|
|
7072
6741
|
projectMemory = getMemory2({ type: "project", path: project });
|
|
7073
6742
|
if (projectMemory.length > maxLen / 3) {
|
|
7074
6743
|
projectMemory = projectMemory.slice(0, maxLen / 3) + "\n...(truncated)";
|
|
@@ -7078,18 +6747,16 @@ async function loadProviderContext(project, options) {
|
|
|
7078
6747
|
}
|
|
7079
6748
|
let vasanaContext = "";
|
|
7080
6749
|
try {
|
|
7081
|
-
const { VasanaEngine: VasanaEngine2 } = await import("./vasana-engine-
|
|
6750
|
+
const { VasanaEngine: VasanaEngine2 } = await import("./vasana-engine-W4PYWT5H.js");
|
|
7082
6751
|
const engine = new VasanaEngine2();
|
|
7083
6752
|
const vasanas = engine.getVasanas(project ?? "__global__", 5);
|
|
7084
6753
|
if (vasanas.length > 0) {
|
|
7085
|
-
vasanaContext = vasanas.map(
|
|
7086
|
-
(v) => `- ${v.tendency} (strength: ${(v.strength * 100).toFixed(0)}%): ${v.description}`
|
|
7087
|
-
).join("\n");
|
|
6754
|
+
vasanaContext = vasanas.map((v) => `- ${v.tendency} (strength: ${(v.strength * 100).toFixed(0)}%): ${v.description}`).join("\n");
|
|
7088
6755
|
}
|
|
7089
6756
|
} catch {
|
|
7090
6757
|
}
|
|
7091
6758
|
try {
|
|
7092
|
-
const { listSessions: listSessions2, loadSession: loadSession2 } = await import("./session-store-
|
|
6759
|
+
const { listSessions: listSessions2, loadSession: loadSession2 } = await import("./session-store-3EDQZEDS.js");
|
|
7093
6760
|
const sessions = project ? listSessions2(project).slice(0, recentLimit) : listSessions2().slice(0, recentLimit);
|
|
7094
6761
|
const summaries = [];
|
|
7095
6762
|
for (const meta of sessions) {
|
|
@@ -7137,6 +6804,595 @@ async function loadProviderContext(project, options) {
|
|
|
7137
6804
|
};
|
|
7138
6805
|
}
|
|
7139
6806
|
|
|
6807
|
+
// ../chitragupta/packages/smriti/dist/critique-store.js
|
|
6808
|
+
init_session_db();
|
|
6809
|
+
import crypto3 from "crypto";
|
|
6810
|
+
var HARD_CEILINGS3 = {
|
|
6811
|
+
maxPerTask: 500,
|
|
6812
|
+
retentionDays: 365,
|
|
6813
|
+
dedupeWindow: 6e5
|
|
6814
|
+
// 10 min max
|
|
6815
|
+
};
|
|
6816
|
+
var DEFAULTS = {
|
|
6817
|
+
maxPerTask: 50,
|
|
6818
|
+
retentionDays: 90,
|
|
6819
|
+
dedupeWindow: 6e4
|
|
6820
|
+
};
|
|
6821
|
+
function tokenize3(text) {
|
|
6822
|
+
return text.toLowerCase().replace(/[^\w\s]/g, " ").split(/\s+/).filter((t) => t.length > 1);
|
|
6823
|
+
}
|
|
6824
|
+
var CritiqueStore = class {
|
|
6825
|
+
config;
|
|
6826
|
+
schemaReady = false;
|
|
6827
|
+
constructor(config) {
|
|
6828
|
+
this.config = {
|
|
6829
|
+
maxPerTask: Math.min(config?.maxPerTask ?? DEFAULTS.maxPerTask, HARD_CEILINGS3.maxPerTask),
|
|
6830
|
+
retentionDays: Math.min(config?.retentionDays ?? DEFAULTS.retentionDays, HARD_CEILINGS3.retentionDays),
|
|
6831
|
+
dedupeWindow: Math.min(config?.dedupeWindow ?? DEFAULTS.dedupeWindow, HARD_CEILINGS3.dedupeWindow)
|
|
6832
|
+
};
|
|
6833
|
+
}
|
|
6834
|
+
// ─── Schema Bootstrap ────────────────────────────────────────────────
|
|
6835
|
+
/** Ensure the critiques table and indices exist. */
|
|
6836
|
+
ensureSchema() {
|
|
6837
|
+
const db = getAgentDb();
|
|
6838
|
+
if (!this.schemaReady) {
|
|
6839
|
+
db.exec(`
|
|
6840
|
+
CREATE TABLE IF NOT EXISTS critiques (
|
|
6841
|
+
id TEXT PRIMARY KEY,
|
|
6842
|
+
task_hash TEXT NOT NULL,
|
|
6843
|
+
severity TEXT NOT NULL,
|
|
6844
|
+
category TEXT NOT NULL,
|
|
6845
|
+
message TEXT NOT NULL,
|
|
6846
|
+
file TEXT,
|
|
6847
|
+
line INTEGER,
|
|
6848
|
+
metadata TEXT,
|
|
6849
|
+
session_id TEXT,
|
|
6850
|
+
created_at INTEGER NOT NULL
|
|
6851
|
+
);
|
|
6852
|
+
CREATE INDEX IF NOT EXISTS idx_critiques_task ON critiques(task_hash);
|
|
6853
|
+
CREATE INDEX IF NOT EXISTS idx_critiques_created ON critiques(created_at);
|
|
6854
|
+
`);
|
|
6855
|
+
this.schemaReady = true;
|
|
6856
|
+
}
|
|
6857
|
+
return db;
|
|
6858
|
+
}
|
|
6859
|
+
// ─── Core Operations ─────────────────────────────────────────────────
|
|
6860
|
+
/**
|
|
6861
|
+
* Store a critique finding with deduplication.
|
|
6862
|
+
*
|
|
6863
|
+
* Before inserting, checks whether an identical (taskHash + category + message)
|
|
6864
|
+
* finding exists within the configured dedupeWindow. If so, the insert is
|
|
6865
|
+
* suppressed and the existing finding is returned.
|
|
6866
|
+
*
|
|
6867
|
+
* When the per-task limit is reached, the oldest findings are pruned.
|
|
6868
|
+
*
|
|
6869
|
+
* @param taskHash - Hash of the task being critiqued.
|
|
6870
|
+
* @param finding - The finding to store (id and createdAt are auto-generated).
|
|
6871
|
+
* @returns The stored (or existing duplicate) CritiqueFinding.
|
|
6872
|
+
*/
|
|
6873
|
+
storeCritique(taskHash, finding) {
|
|
6874
|
+
const db = this.ensureSchema();
|
|
6875
|
+
const now = Date.now();
|
|
6876
|
+
const cutoff = now - this.config.dedupeWindow;
|
|
6877
|
+
const existing = db.prepare(`
|
|
6878
|
+
SELECT id, task_hash, severity, category, message, file, line, metadata, session_id, created_at
|
|
6879
|
+
FROM critiques
|
|
6880
|
+
WHERE task_hash = ? AND category = ? AND message = ? AND created_at > ?
|
|
6881
|
+
ORDER BY created_at DESC LIMIT 1
|
|
6882
|
+
`).get(taskHash, finding.category, finding.message, cutoff);
|
|
6883
|
+
if (existing) {
|
|
6884
|
+
return this.rowToFinding(existing);
|
|
6885
|
+
}
|
|
6886
|
+
const id = crypto3.randomUUID();
|
|
6887
|
+
const metaJson = finding.metadata ? JSON.stringify(finding.metadata) : null;
|
|
6888
|
+
db.prepare(`
|
|
6889
|
+
INSERT INTO critiques (id, task_hash, severity, category, message, file, line, metadata, session_id, created_at)
|
|
6890
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
6891
|
+
`).run(id, taskHash, finding.severity, finding.category, finding.message, finding.file ?? null, finding.line ?? null, metaJson, finding.sessionId ?? null, now);
|
|
6892
|
+
this.enforceTaskLimit(db, taskHash);
|
|
6893
|
+
return {
|
|
6894
|
+
id,
|
|
6895
|
+
taskHash,
|
|
6896
|
+
severity: finding.severity,
|
|
6897
|
+
category: finding.category,
|
|
6898
|
+
message: finding.message,
|
|
6899
|
+
file: finding.file,
|
|
6900
|
+
line: finding.line,
|
|
6901
|
+
metadata: finding.metadata,
|
|
6902
|
+
sessionId: finding.sessionId,
|
|
6903
|
+
createdAt: now
|
|
6904
|
+
};
|
|
6905
|
+
}
|
|
6906
|
+
/**
|
|
6907
|
+
* Retrieve critique findings for a specific task hash.
|
|
6908
|
+
*
|
|
6909
|
+
* Results are ordered by creation time descending (most recent first).
|
|
6910
|
+
*
|
|
6911
|
+
* @param taskHash - The task hash to query.
|
|
6912
|
+
* @param k - Maximum number of results. Default: 10.
|
|
6913
|
+
* @returns Array of CritiqueFinding ordered by recency.
|
|
6914
|
+
*/
|
|
6915
|
+
retrieveCritiques(taskHash, k = 10) {
|
|
6916
|
+
const db = this.ensureSchema();
|
|
6917
|
+
const rows = db.prepare(`
|
|
6918
|
+
SELECT id, task_hash, severity, category, message, file, line, metadata, session_id, created_at
|
|
6919
|
+
FROM critiques
|
|
6920
|
+
WHERE task_hash = ?
|
|
6921
|
+
ORDER BY created_at DESC
|
|
6922
|
+
LIMIT ?
|
|
6923
|
+
`).all(taskHash, k);
|
|
6924
|
+
return rows.map((r) => this.rowToFinding(r));
|
|
6925
|
+
}
|
|
6926
|
+
/**
|
|
6927
|
+
* BM25 text search across all critique findings.
|
|
6928
|
+
*
|
|
6929
|
+
* Searches the concatenation of category + message + file for each finding.
|
|
6930
|
+
*
|
|
6931
|
+
* @param query - Free-text search query.
|
|
6932
|
+
* @param limit - Maximum results. Default: 10.
|
|
6933
|
+
* @returns Array of CritiqueFinding sorted by BM25 relevance.
|
|
6934
|
+
*/
|
|
6935
|
+
searchCritiques(query, limit = 10) {
|
|
6936
|
+
const db = this.ensureSchema();
|
|
6937
|
+
const queryTerms = tokenize3(query);
|
|
6938
|
+
if (queryTerms.length === 0)
|
|
6939
|
+
return [];
|
|
6940
|
+
const rows = db.prepare(`
|
|
6941
|
+
SELECT id, task_hash, severity, category, message, file, line, metadata, session_id, created_at
|
|
6942
|
+
FROM critiques
|
|
6943
|
+
`).all();
|
|
6944
|
+
if (rows.length === 0)
|
|
6945
|
+
return [];
|
|
6946
|
+
const df = /* @__PURE__ */ new Map();
|
|
6947
|
+
const docs = [];
|
|
6948
|
+
for (const row of rows) {
|
|
6949
|
+
const finding = this.rowToFinding(row);
|
|
6950
|
+
const text = `${finding.category} ${finding.message} ${finding.file ?? ""}`;
|
|
6951
|
+
const terms = tokenize3(text);
|
|
6952
|
+
docs.push({ finding, terms });
|
|
6953
|
+
const uniqueTerms = new Set(terms);
|
|
6954
|
+
for (const t of uniqueTerms) {
|
|
6955
|
+
df.set(t, (df.get(t) ?? 0) + 1);
|
|
6956
|
+
}
|
|
6957
|
+
}
|
|
6958
|
+
const N = docs.length;
|
|
6959
|
+
const k1 = 1.5;
|
|
6960
|
+
const b = 0.75;
|
|
6961
|
+
const avgLen = 15;
|
|
6962
|
+
const queryLower = query.toLowerCase();
|
|
6963
|
+
const scored = [];
|
|
6964
|
+
for (const doc of docs) {
|
|
6965
|
+
let bm25 = 0;
|
|
6966
|
+
for (const qt of queryTerms) {
|
|
6967
|
+
const termFreq = doc.terms.filter((t) => t === qt).length;
|
|
6968
|
+
if (termFreq === 0)
|
|
6969
|
+
continue;
|
|
6970
|
+
const docFreq = df.get(qt) ?? 0;
|
|
6971
|
+
const idf = Math.log((N - docFreq + 0.5) / (docFreq + 0.5) + 1);
|
|
6972
|
+
const tf = termFreq * (k1 + 1) / (termFreq + k1 * (1 - b + b * doc.terms.length / avgLen));
|
|
6973
|
+
bm25 += idf * tf;
|
|
6974
|
+
}
|
|
6975
|
+
const docText = `${doc.finding.category} ${doc.finding.message}`.toLowerCase();
|
|
6976
|
+
if (docText.includes(queryLower))
|
|
6977
|
+
bm25 *= 1.5;
|
|
6978
|
+
if (bm25 > 0)
|
|
6979
|
+
scored.push({ finding: doc.finding, score: bm25 });
|
|
6980
|
+
}
|
|
6981
|
+
scored.sort((a, b2) => b2.score - a.score);
|
|
6982
|
+
return scored.slice(0, limit).map((s) => s.finding);
|
|
6983
|
+
}
|
|
6984
|
+
/**
|
|
6985
|
+
* Get aggregate statistics across all stored critique findings.
|
|
6986
|
+
*
|
|
6987
|
+
* @returns Total count, unique task count, and breakdown by severity.
|
|
6988
|
+
*/
|
|
6989
|
+
getStats() {
|
|
6990
|
+
const db = this.ensureSchema();
|
|
6991
|
+
const total = db.prepare("SELECT COUNT(*) as cnt FROM critiques").get();
|
|
6992
|
+
const tasks = db.prepare("SELECT COUNT(DISTINCT task_hash) as cnt FROM critiques").get();
|
|
6993
|
+
const severityRows = db.prepare("SELECT severity, COUNT(*) as cnt FROM critiques GROUP BY severity").all();
|
|
6994
|
+
const bySeverity = {};
|
|
6995
|
+
for (const row of severityRows) {
|
|
6996
|
+
bySeverity[row.severity] = row.cnt;
|
|
6997
|
+
}
|
|
6998
|
+
return {
|
|
6999
|
+
totalCritiques: total.cnt,
|
|
7000
|
+
uniqueTasks: tasks.cnt,
|
|
7001
|
+
bySeverity
|
|
7002
|
+
};
|
|
7003
|
+
}
|
|
7004
|
+
/**
|
|
7005
|
+
* Remove findings older than the configured retentionDays.
|
|
7006
|
+
*
|
|
7007
|
+
* @returns Number of expired findings removed.
|
|
7008
|
+
*/
|
|
7009
|
+
purgeExpired() {
|
|
7010
|
+
const db = this.ensureSchema();
|
|
7011
|
+
const cutoff = Date.now() - this.config.retentionDays * 24 * 60 * 60 * 1e3;
|
|
7012
|
+
const result = db.prepare("DELETE FROM critiques WHERE created_at < ?").run(cutoff);
|
|
7013
|
+
return result.changes;
|
|
7014
|
+
}
|
|
7015
|
+
/**
|
|
7016
|
+
* Clear all findings, or only findings for a specific task hash.
|
|
7017
|
+
*
|
|
7018
|
+
* @param taskHash - If provided, only clear findings for this task. Otherwise clear all.
|
|
7019
|
+
*/
|
|
7020
|
+
clear(taskHash) {
|
|
7021
|
+
const db = this.ensureSchema();
|
|
7022
|
+
if (taskHash) {
|
|
7023
|
+
db.prepare("DELETE FROM critiques WHERE task_hash = ?").run(taskHash);
|
|
7024
|
+
} else {
|
|
7025
|
+
db.prepare("DELETE FROM critiques").run();
|
|
7026
|
+
}
|
|
7027
|
+
}
|
|
7028
|
+
// ─── Internal Helpers ────────────────────────────────────────────────
|
|
7029
|
+
/**
|
|
7030
|
+
* Enforce the maxPerTask cardinality limit by pruning the oldest entries.
|
|
7031
|
+
*
|
|
7032
|
+
* @param db - The database connection.
|
|
7033
|
+
* @param taskHash - The task hash to enforce the limit for.
|
|
7034
|
+
*/
|
|
7035
|
+
enforceTaskLimit(db, taskHash) {
|
|
7036
|
+
const count = db.prepare("SELECT COUNT(*) as cnt FROM critiques WHERE task_hash = ?").get(taskHash);
|
|
7037
|
+
if (count.cnt > this.config.maxPerTask) {
|
|
7038
|
+
const excess = count.cnt - this.config.maxPerTask;
|
|
7039
|
+
db.prepare(`
|
|
7040
|
+
DELETE FROM critiques WHERE id IN (
|
|
7041
|
+
SELECT id FROM critiques WHERE task_hash = ? ORDER BY created_at ASC LIMIT ?
|
|
7042
|
+
)
|
|
7043
|
+
`).run(taskHash, excess);
|
|
7044
|
+
}
|
|
7045
|
+
}
|
|
7046
|
+
/**
|
|
7047
|
+
* Convert a raw SQLite row into a typed CritiqueFinding.
|
|
7048
|
+
*
|
|
7049
|
+
* @param row - A record from the critiques table.
|
|
7050
|
+
* @returns A fully typed CritiqueFinding.
|
|
7051
|
+
*/
|
|
7052
|
+
rowToFinding(row) {
|
|
7053
|
+
let metadata;
|
|
7054
|
+
try {
|
|
7055
|
+
metadata = row.metadata ? JSON.parse(row.metadata) : void 0;
|
|
7056
|
+
} catch {
|
|
7057
|
+
metadata = void 0;
|
|
7058
|
+
}
|
|
7059
|
+
return {
|
|
7060
|
+
id: row.id,
|
|
7061
|
+
taskHash: row.task_hash,
|
|
7062
|
+
severity: row.severity,
|
|
7063
|
+
category: row.category,
|
|
7064
|
+
message: row.message,
|
|
7065
|
+
file: row.file ?? void 0,
|
|
7066
|
+
line: row.line ?? void 0,
|
|
7067
|
+
metadata,
|
|
7068
|
+
sessionId: row.session_id ?? void 0,
|
|
7069
|
+
createdAt: row.created_at
|
|
7070
|
+
};
|
|
7071
|
+
}
|
|
7072
|
+
};
|
|
7073
|
+
|
|
7074
|
+
// ../chitragupta/packages/smriti/dist/orchestrator-checkpoint.js
|
|
7075
|
+
init_session_db();
|
|
7076
|
+
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
7077
|
+
var DEFAULT_MAX_PER_TYPE = 100;
|
|
7078
|
+
var DEFAULT_RETENTION_DAYS = 30;
|
|
7079
|
+
var MS_PER_DAY = 864e5;
|
|
7080
|
+
var CREATE_JOBS_TABLE = `
|
|
7081
|
+
CREATE TABLE IF NOT EXISTS orchestrator_jobs (
|
|
7082
|
+
job_id TEXT PRIMARY KEY,
|
|
7083
|
+
job_type TEXT NOT NULL,
|
|
7084
|
+
status TEXT NOT NULL,
|
|
7085
|
+
current_step_index INTEGER NOT NULL DEFAULT 0,
|
|
7086
|
+
metadata TEXT,
|
|
7087
|
+
idempotency_key TEXT NOT NULL UNIQUE,
|
|
7088
|
+
created_at INTEGER NOT NULL,
|
|
7089
|
+
updated_at INTEGER NOT NULL
|
|
7090
|
+
)`;
|
|
7091
|
+
var CREATE_STEPS_TABLE = `
|
|
7092
|
+
CREATE TABLE IF NOT EXISTS orchestrator_steps (
|
|
7093
|
+
job_id TEXT NOT NULL,
|
|
7094
|
+
step_id TEXT NOT NULL,
|
|
7095
|
+
step_index INTEGER NOT NULL,
|
|
7096
|
+
status TEXT NOT NULL DEFAULT 'pending',
|
|
7097
|
+
input TEXT,
|
|
7098
|
+
output TEXT,
|
|
7099
|
+
error TEXT,
|
|
7100
|
+
started_at INTEGER,
|
|
7101
|
+
completed_at INTEGER,
|
|
7102
|
+
retry_count INTEGER NOT NULL DEFAULT 0,
|
|
7103
|
+
PRIMARY KEY (job_id, step_id),
|
|
7104
|
+
FOREIGN KEY (job_id) REFERENCES orchestrator_jobs(job_id) ON DELETE CASCADE
|
|
7105
|
+
)`;
|
|
7106
|
+
var CREATE_JOBS_TYPE_IDX = `CREATE INDEX IF NOT EXISTS idx_orch_jobs_type ON orchestrator_jobs(job_type)`;
|
|
7107
|
+
var CREATE_JOBS_STATUS_IDX = `CREATE INDEX IF NOT EXISTS idx_orch_jobs_status ON orchestrator_jobs(status)`;
|
|
7108
|
+
var CREATE_STEPS_JOB_IDX = `CREATE INDEX IF NOT EXISTS idx_orch_steps_job ON orchestrator_steps(job_id)`;
|
|
7109
|
+
function rowToStep(row) {
|
|
7110
|
+
return {
|
|
7111
|
+
stepId: row.step_id,
|
|
7112
|
+
status: row.status,
|
|
7113
|
+
input: row.input ? JSON.parse(row.input) : void 0,
|
|
7114
|
+
output: row.output ? JSON.parse(row.output) : void 0,
|
|
7115
|
+
error: row.error ?? void 0,
|
|
7116
|
+
startedAt: row.started_at ?? void 0,
|
|
7117
|
+
completedAt: row.completed_at ?? void 0,
|
|
7118
|
+
retryCount: row.retry_count ?? 0
|
|
7119
|
+
};
|
|
7120
|
+
}
|
|
7121
|
+
function assembleJob(jobRow, stepRows) {
|
|
7122
|
+
const steps = stepRows.sort((a, b) => a.step_index - b.step_index).map(rowToStep);
|
|
7123
|
+
return {
|
|
7124
|
+
jobId: jobRow.job_id,
|
|
7125
|
+
jobType: jobRow.job_type,
|
|
7126
|
+
status: jobRow.status,
|
|
7127
|
+
steps,
|
|
7128
|
+
currentStepIndex: jobRow.current_step_index,
|
|
7129
|
+
metadata: jobRow.metadata ? JSON.parse(jobRow.metadata) : {},
|
|
7130
|
+
createdAt: jobRow.created_at,
|
|
7131
|
+
updatedAt: jobRow.updated_at,
|
|
7132
|
+
idempotencyKey: jobRow.idempotency_key
|
|
7133
|
+
};
|
|
7134
|
+
}
|
|
7135
|
+
var OrchestratorCheckpoint = class {
|
|
7136
|
+
db;
|
|
7137
|
+
maxPerType;
|
|
7138
|
+
retentionDays;
|
|
7139
|
+
initialized = false;
|
|
7140
|
+
constructor(config) {
|
|
7141
|
+
this.db = getAgentDb();
|
|
7142
|
+
this.maxPerType = config?.maxPerType ?? DEFAULT_MAX_PER_TYPE;
|
|
7143
|
+
this.retentionDays = config?.retentionDays ?? DEFAULT_RETENTION_DAYS;
|
|
7144
|
+
this.ensureSchema();
|
|
7145
|
+
}
|
|
7146
|
+
/**
|
|
7147
|
+
* Create a new orchestration job with the given steps.
|
|
7148
|
+
*
|
|
7149
|
+
* Idempotency: throws if a job with the same key exists in a non-terminal state.
|
|
7150
|
+
* If the key exists but the prior job is completed or failed, allows re-creation.
|
|
7151
|
+
*
|
|
7152
|
+
* @param jobType - Category of this job (e.g. "code-review", "deploy").
|
|
7153
|
+
* @param steps - Ordered step definitions for the job.
|
|
7154
|
+
* @param idempotencyKey - Unique key to prevent duplicate execution.
|
|
7155
|
+
* @param metadata - Optional metadata to attach to the job.
|
|
7156
|
+
* @returns The newly created job checkpoint.
|
|
7157
|
+
*/
|
|
7158
|
+
createJob(jobType, steps, idempotencyKey, metadata) {
|
|
7159
|
+
const existing = this.db.prepare("SELECT job_id, status FROM orchestrator_jobs WHERE idempotency_key = ?").get(idempotencyKey);
|
|
7160
|
+
if (existing && existing.status !== "completed" && existing.status !== "failed") {
|
|
7161
|
+
throw new Error(`Duplicate idempotency key "${idempotencyKey}": job ${existing.job_id} is still ${existing.status}`);
|
|
7162
|
+
}
|
|
7163
|
+
if (existing) {
|
|
7164
|
+
this.deleteJob(existing.job_id);
|
|
7165
|
+
}
|
|
7166
|
+
const jobId = `job-${randomUUID2().slice(0, 12)}`;
|
|
7167
|
+
const now = Date.now();
|
|
7168
|
+
const txn = this.db.transaction(() => {
|
|
7169
|
+
this.db.prepare(`
|
|
7170
|
+
INSERT INTO orchestrator_jobs (job_id, job_type, status, current_step_index, metadata, idempotency_key, created_at, updated_at)
|
|
7171
|
+
VALUES (?, ?, 'running', 0, ?, ?, ?, ?)
|
|
7172
|
+
`).run(jobId, jobType, metadata ? JSON.stringify(metadata) : null, idempotencyKey, now, now);
|
|
7173
|
+
for (let i = 0; i < steps.length; i++) {
|
|
7174
|
+
const step = steps[i];
|
|
7175
|
+
const status = i === 0 ? "running" : "pending";
|
|
7176
|
+
const startedAt = i === 0 ? now : null;
|
|
7177
|
+
this.db.prepare(`
|
|
7178
|
+
INSERT INTO orchestrator_steps (job_id, step_id, step_index, status, input, retry_count, started_at)
|
|
7179
|
+
VALUES (?, ?, ?, ?, ?, 0, ?)
|
|
7180
|
+
`).run(jobId, step.stepId, i, status, step.input ? JSON.stringify(step.input) : null, startedAt);
|
|
7181
|
+
}
|
|
7182
|
+
});
|
|
7183
|
+
txn();
|
|
7184
|
+
this.enforceMaxPerType(jobType);
|
|
7185
|
+
return this.loadJob(jobId);
|
|
7186
|
+
}
|
|
7187
|
+
/**
|
|
7188
|
+
* Load a job checkpoint by ID.
|
|
7189
|
+
* @returns The job checkpoint, or null if not found.
|
|
7190
|
+
*/
|
|
7191
|
+
loadJob(jobId) {
|
|
7192
|
+
const jobRow = this.db.prepare("SELECT * FROM orchestrator_jobs WHERE job_id = ?").get(jobId);
|
|
7193
|
+
if (!jobRow)
|
|
7194
|
+
return null;
|
|
7195
|
+
const stepRows = this.db.prepare("SELECT * FROM orchestrator_steps WHERE job_id = ? ORDER BY step_index").all(jobId);
|
|
7196
|
+
return assembleJob(jobRow, stepRows);
|
|
7197
|
+
}
|
|
7198
|
+
/**
|
|
7199
|
+
* Mark the current step as completed and advance to the next step.
|
|
7200
|
+
* @returns The completed step checkpoint.
|
|
7201
|
+
*/
|
|
7202
|
+
advanceStep(jobId, output) {
|
|
7203
|
+
const job = this.requireJob(jobId);
|
|
7204
|
+
const currentStep = job.steps[job.currentStepIndex];
|
|
7205
|
+
if (!currentStep)
|
|
7206
|
+
throw new Error(`No current step at index ${job.currentStepIndex}`);
|
|
7207
|
+
const now = Date.now();
|
|
7208
|
+
const txn = this.db.transaction(() => {
|
|
7209
|
+
this.db.prepare(`
|
|
7210
|
+
UPDATE orchestrator_steps SET status = 'completed', output = ?, completed_at = ?
|
|
7211
|
+
WHERE job_id = ? AND step_id = ?
|
|
7212
|
+
`).run(output ? JSON.stringify(output) : null, now, jobId, currentStep.stepId);
|
|
7213
|
+
const nextIndex = job.currentStepIndex + 1;
|
|
7214
|
+
if (nextIndex < job.steps.length) {
|
|
7215
|
+
const nextStep = job.steps[nextIndex];
|
|
7216
|
+
this.db.prepare(`
|
|
7217
|
+
UPDATE orchestrator_steps SET status = 'running', started_at = ?
|
|
7218
|
+
WHERE job_id = ? AND step_id = ?
|
|
7219
|
+
`).run(now, jobId, nextStep.stepId);
|
|
7220
|
+
this.db.prepare("UPDATE orchestrator_jobs SET current_step_index = ?, updated_at = ? WHERE job_id = ?").run(nextIndex, now, jobId);
|
|
7221
|
+
} else {
|
|
7222
|
+
this.db.prepare("UPDATE orchestrator_jobs SET updated_at = ? WHERE job_id = ?").run(now, jobId);
|
|
7223
|
+
}
|
|
7224
|
+
});
|
|
7225
|
+
txn();
|
|
7226
|
+
return { ...currentStep, status: "completed", output, completedAt: now };
|
|
7227
|
+
}
|
|
7228
|
+
/**
|
|
7229
|
+
* Mark the current step as failed and increment its retry count.
|
|
7230
|
+
* @returns The failed step checkpoint.
|
|
7231
|
+
*/
|
|
7232
|
+
failStep(jobId, error) {
|
|
7233
|
+
const job = this.requireJob(jobId);
|
|
7234
|
+
const currentStep = job.steps[job.currentStepIndex];
|
|
7235
|
+
if (!currentStep)
|
|
7236
|
+
throw new Error(`No current step at index ${job.currentStepIndex}`);
|
|
7237
|
+
const now = Date.now();
|
|
7238
|
+
const newRetry = currentStep.retryCount + 1;
|
|
7239
|
+
this.db.prepare(`
|
|
7240
|
+
UPDATE orchestrator_steps SET status = 'failed', error = ?, retry_count = ?
|
|
7241
|
+
WHERE job_id = ? AND step_id = ?
|
|
7242
|
+
`).run(error, newRetry, jobId, currentStep.stepId);
|
|
7243
|
+
this.db.prepare("UPDATE orchestrator_jobs SET updated_at = ? WHERE job_id = ?").run(now, jobId);
|
|
7244
|
+
return { ...currentStep, status: "failed", error, retryCount: newRetry };
|
|
7245
|
+
}
|
|
7246
|
+
/**
|
|
7247
|
+
* Retry the current failed step (reset to running).
|
|
7248
|
+
* @throws If the current step is not in "failed" status.
|
|
7249
|
+
*/
|
|
7250
|
+
retryStep(jobId) {
|
|
7251
|
+
const job = this.requireJob(jobId);
|
|
7252
|
+
const currentStep = job.steps[job.currentStepIndex];
|
|
7253
|
+
if (!currentStep)
|
|
7254
|
+
throw new Error(`No current step at index ${job.currentStepIndex}`);
|
|
7255
|
+
if (currentStep.status !== "failed") {
|
|
7256
|
+
throw new Error(`Cannot retry step "${currentStep.stepId}" \u2014 status is "${currentStep.status}", not "failed"`);
|
|
7257
|
+
}
|
|
7258
|
+
const now = Date.now();
|
|
7259
|
+
this.db.prepare(`
|
|
7260
|
+
UPDATE orchestrator_steps SET status = 'running', error = NULL, started_at = ?
|
|
7261
|
+
WHERE job_id = ? AND step_id = ?
|
|
7262
|
+
`).run(now, jobId, currentStep.stepId);
|
|
7263
|
+
this.db.prepare("UPDATE orchestrator_jobs SET status = 'running', updated_at = ? WHERE job_id = ?").run(now, jobId);
|
|
7264
|
+
return { ...currentStep, status: "running", error: void 0, startedAt: now };
|
|
7265
|
+
}
|
|
7266
|
+
/** Mark the entire job as completed. */
|
|
7267
|
+
completeJob(jobId) {
|
|
7268
|
+
this.requireJob(jobId);
|
|
7269
|
+
const now = Date.now();
|
|
7270
|
+
this.db.prepare("UPDATE orchestrator_jobs SET status = 'completed', updated_at = ? WHERE job_id = ?").run(now, jobId);
|
|
7271
|
+
return this.loadJob(jobId);
|
|
7272
|
+
}
|
|
7273
|
+
/** Mark the entire job as failed with an error message stored in metadata. */
|
|
7274
|
+
failJob(jobId, error) {
|
|
7275
|
+
const job = this.requireJob(jobId);
|
|
7276
|
+
const now = Date.now();
|
|
7277
|
+
const meta = { ...job.metadata, failureError: error };
|
|
7278
|
+
this.db.prepare("UPDATE orchestrator_jobs SET status = 'failed', metadata = ?, updated_at = ? WHERE job_id = ?").run(JSON.stringify(meta), now, jobId);
|
|
7279
|
+
return this.loadJob(jobId);
|
|
7280
|
+
}
|
|
7281
|
+
/**
|
|
7282
|
+
* Resume a paused or failed job from the last incomplete step.
|
|
7283
|
+
* @throws If the job is already completed.
|
|
7284
|
+
*/
|
|
7285
|
+
resumeJob(jobId) {
|
|
7286
|
+
const job = this.requireJob(jobId);
|
|
7287
|
+
if (job.status === "completed") {
|
|
7288
|
+
throw new Error(`Cannot resume job ${jobId} \u2014 already completed`);
|
|
7289
|
+
}
|
|
7290
|
+
const now = Date.now();
|
|
7291
|
+
let resumeIndex = -1;
|
|
7292
|
+
for (let i = 0; i < job.steps.length; i++) {
|
|
7293
|
+
if (job.steps[i].status !== "completed" && job.steps[i].status !== "skipped") {
|
|
7294
|
+
resumeIndex = i;
|
|
7295
|
+
break;
|
|
7296
|
+
}
|
|
7297
|
+
}
|
|
7298
|
+
if (resumeIndex === -1) {
|
|
7299
|
+
this.db.prepare("UPDATE orchestrator_jobs SET status = 'running', updated_at = ? WHERE job_id = ?").run(now, jobId);
|
|
7300
|
+
return this.loadJob(jobId);
|
|
7301
|
+
}
|
|
7302
|
+
const txn = this.db.transaction(() => {
|
|
7303
|
+
const step = job.steps[resumeIndex];
|
|
7304
|
+
this.db.prepare(`
|
|
7305
|
+
UPDATE orchestrator_steps SET status = 'running', error = NULL, started_at = ?
|
|
7306
|
+
WHERE job_id = ? AND step_id = ?
|
|
7307
|
+
`).run(now, jobId, step.stepId);
|
|
7308
|
+
this.db.prepare(`
|
|
7309
|
+
UPDATE orchestrator_jobs SET status = 'running', current_step_index = ?, updated_at = ?
|
|
7310
|
+
WHERE job_id = ?
|
|
7311
|
+
`).run(resumeIndex, now, jobId);
|
|
7312
|
+
});
|
|
7313
|
+
txn();
|
|
7314
|
+
return this.loadJob(jobId);
|
|
7315
|
+
}
|
|
7316
|
+
/** List jobs with optional type and status filters. */
|
|
7317
|
+
listJobs(filter) {
|
|
7318
|
+
let sql = "SELECT * FROM orchestrator_jobs WHERE 1=1";
|
|
7319
|
+
const params = [];
|
|
7320
|
+
if (filter?.jobType) {
|
|
7321
|
+
sql += " AND job_type = ?";
|
|
7322
|
+
params.push(filter.jobType);
|
|
7323
|
+
}
|
|
7324
|
+
if (filter?.status) {
|
|
7325
|
+
sql += " AND status = ?";
|
|
7326
|
+
params.push(filter.status);
|
|
7327
|
+
}
|
|
7328
|
+
sql += " ORDER BY updated_at DESC";
|
|
7329
|
+
const jobRows = this.db.prepare(sql).all(...params);
|
|
7330
|
+
return jobRows.map((row) => {
|
|
7331
|
+
const stepRows = this.db.prepare("SELECT * FROM orchestrator_steps WHERE job_id = ? ORDER BY step_index").all(row.job_id);
|
|
7332
|
+
return assembleJob(row, stepRows);
|
|
7333
|
+
});
|
|
7334
|
+
}
|
|
7335
|
+
/**
|
|
7336
|
+
* Purge completed/failed jobs older than retentionDays.
|
|
7337
|
+
* @returns Number of jobs removed.
|
|
7338
|
+
*/
|
|
7339
|
+
purgeOld() {
|
|
7340
|
+
const cutoff = Date.now() - this.retentionDays * MS_PER_DAY;
|
|
7341
|
+
const rows = this.db.prepare(`
|
|
7342
|
+
SELECT job_id FROM orchestrator_jobs
|
|
7343
|
+
WHERE status IN ('completed', 'failed') AND updated_at < ?
|
|
7344
|
+
`).all(cutoff);
|
|
7345
|
+
if (rows.length === 0)
|
|
7346
|
+
return 0;
|
|
7347
|
+
const txn = this.db.transaction(() => {
|
|
7348
|
+
for (const row of rows) {
|
|
7349
|
+
this.deleteJob(row.job_id);
|
|
7350
|
+
}
|
|
7351
|
+
});
|
|
7352
|
+
txn();
|
|
7353
|
+
return rows.length;
|
|
7354
|
+
}
|
|
7355
|
+
// ─── Private ──────────────────────────────────────────────────────────────
|
|
7356
|
+
/** Create tables if they don't exist. Idempotent. */
|
|
7357
|
+
ensureSchema() {
|
|
7358
|
+
if (this.initialized)
|
|
7359
|
+
return;
|
|
7360
|
+
this.db.exec(CREATE_JOBS_TABLE);
|
|
7361
|
+
this.db.exec(CREATE_STEPS_TABLE);
|
|
7362
|
+
this.db.exec(CREATE_JOBS_TYPE_IDX);
|
|
7363
|
+
this.db.exec(CREATE_JOBS_STATUS_IDX);
|
|
7364
|
+
this.db.exec(CREATE_STEPS_JOB_IDX);
|
|
7365
|
+
this.initialized = true;
|
|
7366
|
+
}
|
|
7367
|
+
/** Load a job or throw if not found. */
|
|
7368
|
+
requireJob(jobId) {
|
|
7369
|
+
const job = this.loadJob(jobId);
|
|
7370
|
+
if (!job)
|
|
7371
|
+
throw new Error(`Job not found: ${jobId}`);
|
|
7372
|
+
return job;
|
|
7373
|
+
}
|
|
7374
|
+
/** Delete a job and all its steps. */
|
|
7375
|
+
deleteJob(jobId) {
|
|
7376
|
+
this.db.prepare("DELETE FROM orchestrator_steps WHERE job_id = ?").run(jobId);
|
|
7377
|
+
this.db.prepare("DELETE FROM orchestrator_jobs WHERE job_id = ?").run(jobId);
|
|
7378
|
+
}
|
|
7379
|
+
/** Evict oldest completed/failed jobs when exceeding maxPerType. */
|
|
7380
|
+
enforceMaxPerType(jobType) {
|
|
7381
|
+
const count = this.db.prepare("SELECT COUNT(*) as cnt FROM orchestrator_jobs WHERE job_type = ?").get(jobType);
|
|
7382
|
+
if (count.cnt <= this.maxPerType)
|
|
7383
|
+
return;
|
|
7384
|
+
const excess = count.cnt - this.maxPerType;
|
|
7385
|
+
const toRemove = this.db.prepare(`
|
|
7386
|
+
SELECT job_id FROM orchestrator_jobs
|
|
7387
|
+
WHERE job_type = ? AND status IN ('completed', 'failed')
|
|
7388
|
+
ORDER BY updated_at ASC LIMIT ?
|
|
7389
|
+
`).all(jobType, excess);
|
|
7390
|
+
for (const row of toRemove) {
|
|
7391
|
+
this.deleteJob(row.job_id);
|
|
7392
|
+
}
|
|
7393
|
+
}
|
|
7394
|
+
};
|
|
7395
|
+
|
|
7140
7396
|
export {
|
|
7141
7397
|
exportSessionToJson,
|
|
7142
7398
|
exportSessionToMarkdown,
|
|
@@ -7172,13 +7428,14 @@ export {
|
|
|
7172
7428
|
IdentityContext,
|
|
7173
7429
|
SvapnaConsolidation,
|
|
7174
7430
|
VidhiEngine,
|
|
7175
|
-
AkashaField,
|
|
7176
7431
|
TEMPORAL_SCALES,
|
|
7177
7432
|
KalaChakra,
|
|
7178
7433
|
VRITTI_TYPES,
|
|
7179
7434
|
VRITTI_CONFIDENCE_WEIGHTS,
|
|
7180
7435
|
PanchaVritti,
|
|
7181
7436
|
recall,
|
|
7182
|
-
loadProviderContext
|
|
7437
|
+
loadProviderContext,
|
|
7438
|
+
CritiqueStore,
|
|
7439
|
+
OrchestratorCheckpoint
|
|
7183
7440
|
};
|
|
7184
|
-
//# sourceMappingURL=chunk-
|
|
7441
|
+
//# sourceMappingURL=chunk-TSOQ2CT3.js.map
|