@yugenlab/vaayu 0.1.11 → 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-O3NUV7KG.js → agentic-tool-loop-NQESOBLC.js} +2 -2
- package/chunks/akasha-5C5Q6NMP.js +12 -0
- package/chunks/{chunk-7XV5ISV7.js → chunk-26K6DS6N.js} +2 -2
- package/chunks/chunk-5E3ZS5SW.js +529 -0
- package/chunks/{chunk-D46QTN3G.js → chunk-ARZCIITZ.js} +47 -18
- package/chunks/{chunk-ZYY6N3SP.js → chunk-FEDPZOZ5.js} +548 -389
- package/chunks/{chunk-3AYSJ7WB.js → chunk-GWYC7R2L.js} +13 -7
- package/chunks/chunk-H46F2Y6R.js +134 -0
- package/chunks/{chunk-QV4GPIPT.js → chunk-HXHDP2PZ.js} +8 -4
- package/chunks/chunk-KVQH4LE7.js +396 -0
- package/chunks/{chunk-Z576WVLG.js → chunk-LJCT7UYP.js} +17 -7
- package/chunks/{chunk-LJUEMPLG.js → chunk-M2RLX5LU.js} +32 -14
- package/chunks/{chunk-IGKYKEKT.js → chunk-NAQKA54E.js} +8 -2
- package/chunks/{chunk-F6RNEGFX.js → chunk-PZ4AQ22L.js} +78 -13
- package/chunks/{chunk-G2QREGXK.js → chunk-R273KC7J.js} +275 -2
- package/chunks/{chunk-A3HOZBC5.js → chunk-RVKTGKFD.js} +2 -2
- package/chunks/{chunk-VCUJES75.js → chunk-TSOQ2CT3.js} +763 -620
- package/chunks/{chunk-V2ZIKDN4.js → chunk-VEZ2DI2M.js} +16 -5
- package/chunks/{chunk-W4PVGBUH.js → chunk-XP3NIH5F.js} +7 -3
- package/chunks/{chunk-7AYYXHYZ.js → chunk-Y6IZH6FT.js} +19 -4
- package/chunks/{chunk-JZTFJE7M.js → chunk-YRTGGYJU.js} +14 -10
- package/chunks/{consolidation-indexer-VIWOP6VO.js → consolidation-indexer-KPXORCJ4.js} +9 -9
- package/chunks/database-BX3LVYXS.js +11 -0
- package/chunks/{day-consolidation-HMHSXIOM.js → day-consolidation-CR3TJFAL.js} +5 -5
- package/chunks/{dist-CY5NX2IK.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-LEERUQGL.js → memory-store-4GCBR2DZ.js} +4 -4
- package/chunks/periodic-consolidation-IINCHP6L.js +11 -0
- package/chunks/{postgres-7GZDDX77.js → postgres-YLCUNVPQ.js} +2 -2
- package/chunks/recall-64RROTUC.js +21 -0
- package/chunks/search-JVCDNTAJ.js +19 -0
- package/chunks/{session-store-O3TS7DUY.js → session-store-3EDQZEDS.js} +12 -6
- package/chunks/{sqlite-7BC4DJTN.js → sqlite-4N7YH2KK.js} +2 -2
- 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-BJFHJVGM.js → vasana-engine-W4PYWT5H.js} +5 -5
- package/gateway.js +2358 -768
- package/package.json +1 -1
- package/pair-cli.js +2 -2
- package/chunks/chunk-2OBLQJYJ.js +0 -198
- package/chunks/chunk-67DXWEKG.js +0 -123
- package/chunks/graphrag-T2QWNX57.js +0 -14
- package/chunks/hierarchical-temporal-search-U6DG74IR.js +0 -8
- package/chunks/hybrid-search-BYTXCOXP.js +0 -20
- package/chunks/periodic-consolidation-D6SSKZ7H.js +0 -11
- package/chunks/recall-LNRQVATQ.js +0 -21
- package/chunks/search-BIODUW2P.js +0 -19
|
@@ -1,30 +1,41 @@
|
|
|
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";
|
|
34
|
+
|
|
35
|
+
// ../chitragupta/packages/smriti/dist/index.js
|
|
36
|
+
init_markdown_parser();
|
|
37
|
+
init_markdown_writer();
|
|
38
|
+
init_session_store();
|
|
28
39
|
|
|
29
40
|
// ../chitragupta/packages/smriti/dist/session-export.js
|
|
30
41
|
function exportSessionToJson(session) {
|
|
@@ -235,12 +246,14 @@ function validateExportedSession(data) {
|
|
|
235
246
|
}
|
|
236
247
|
|
|
237
248
|
// ../chitragupta/packages/smriti/dist/cross-machine-sync.js
|
|
249
|
+
init_dist();
|
|
238
250
|
import fs2 from "node:fs";
|
|
239
251
|
import os from "node:os";
|
|
240
252
|
import path2 from "node:path";
|
|
241
253
|
import crypto2 from "node:crypto";
|
|
242
254
|
|
|
243
255
|
// ../chitragupta/packages/smriti/dist/sync-import.js
|
|
256
|
+
init_dist();
|
|
244
257
|
import fs from "node:fs";
|
|
245
258
|
import path from "node:path";
|
|
246
259
|
import crypto from "node:crypto";
|
|
@@ -655,6 +668,8 @@ function getCrossMachineSyncStatus() {
|
|
|
655
668
|
}
|
|
656
669
|
|
|
657
670
|
// ../chitragupta/packages/smriti/dist/branch.js
|
|
671
|
+
init_dist();
|
|
672
|
+
init_session_store();
|
|
658
673
|
function branchSession(sessionId, project, branchName, fromTurn) {
|
|
659
674
|
const original = loadSession(sessionId, project);
|
|
660
675
|
let turnsToKeep = original.turns;
|
|
@@ -1174,6 +1189,7 @@ function writeDeltaMarkdown(delta) {
|
|
|
1174
1189
|
}
|
|
1175
1190
|
|
|
1176
1191
|
// ../chitragupta/packages/smriti/dist/compactor.js
|
|
1192
|
+
init_dist();
|
|
1177
1193
|
import fs3 from "fs";
|
|
1178
1194
|
import path3 from "path";
|
|
1179
1195
|
function getCompactionDir() {
|
|
@@ -1369,7 +1385,9 @@ var SessionCompactor = class {
|
|
|
1369
1385
|
const filePath = path3.join(dir, `${delta.sessionId}.md`);
|
|
1370
1386
|
const markdown = writeDeltaMarkdown(delta);
|
|
1371
1387
|
fs3.writeFileSync(filePath, markdown, "utf-8");
|
|
1372
|
-
} catch {
|
|
1388
|
+
} catch (err) {
|
|
1389
|
+
process.stderr.write(`[smriti:compactor] delta save failed: ${err instanceof Error ? err.message : String(err)}
|
|
1390
|
+
`);
|
|
1373
1391
|
}
|
|
1374
1392
|
}
|
|
1375
1393
|
saveMixingMatrix(sessionId, mixingMatrix, signals) {
|
|
@@ -1396,7 +1414,9 @@ var SessionCompactor = class {
|
|
|
1396
1414
|
};
|
|
1397
1415
|
const filePath = path3.join(dir, `${sessionId}.json`);
|
|
1398
1416
|
fs3.writeFileSync(filePath, JSON.stringify(data, null, " "), "utf-8");
|
|
1399
|
-
} catch {
|
|
1417
|
+
} catch (err) {
|
|
1418
|
+
process.stderr.write(`[smriti:compactor] mixing matrix save failed: ${err instanceof Error ? err.message : String(err)}
|
|
1419
|
+
`);
|
|
1400
1420
|
}
|
|
1401
1421
|
}
|
|
1402
1422
|
};
|
|
@@ -2235,6 +2255,7 @@ var CheckpointManager = class {
|
|
|
2235
2255
|
};
|
|
2236
2256
|
|
|
2237
2257
|
// ../chitragupta/packages/smriti/dist/consolidation.js
|
|
2258
|
+
init_dist();
|
|
2238
2259
|
import fs5 from "fs";
|
|
2239
2260
|
import path5 from "path";
|
|
2240
2261
|
|
|
@@ -2634,7 +2655,7 @@ function enforceMaxRules(rules, maxRules) {
|
|
|
2634
2655
|
}
|
|
2635
2656
|
}
|
|
2636
2657
|
|
|
2637
|
-
// ../chitragupta/packages/smriti/dist/consolidation.js
|
|
2658
|
+
// ../chitragupta/packages/smriti/dist/consolidation-types.js
|
|
2638
2659
|
var DEFAULT_CONFIG = {
|
|
2639
2660
|
minObservations: 2,
|
|
2640
2661
|
decayRatePerDay: 0.01,
|
|
@@ -2652,6 +2673,8 @@ var ALL_CATEGORIES = [
|
|
|
2652
2673
|
"domain-knowledge",
|
|
2653
2674
|
"relationship"
|
|
2654
2675
|
];
|
|
2676
|
+
|
|
2677
|
+
// ../chitragupta/packages/smriti/dist/consolidation.js
|
|
2655
2678
|
var ConsolidationEngine = class {
|
|
2656
2679
|
config;
|
|
2657
2680
|
rules = /* @__PURE__ */ new Map();
|
|
@@ -3389,6 +3412,7 @@ var AnveshanaEngine = class {
|
|
|
3389
3412
|
};
|
|
3390
3413
|
|
|
3391
3414
|
// ../chitragupta/packages/smriti/dist/smaran.js
|
|
3415
|
+
init_dist();
|
|
3392
3416
|
import path7 from "path";
|
|
3393
3417
|
|
|
3394
3418
|
// ../chitragupta/packages/smriti/dist/smaran-store.js
|
|
@@ -4171,9 +4195,18 @@ async function svapnaReplay(db, config) {
|
|
|
4171
4195
|
const placeholders = sessionIds.map(() => "?").join(",");
|
|
4172
4196
|
const turns = agentDb.prepare(`SELECT id, session_id, turn_number, role, content, tool_calls, created_at
|
|
4173
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
|
+
});
|
|
4174
4207
|
const patternCounts = /* @__PURE__ */ new Map();
|
|
4175
4208
|
let totalPatterns = 0;
|
|
4176
|
-
for (const turn of
|
|
4209
|
+
for (const turn of realTurns) {
|
|
4177
4210
|
const calls = parseToolCalls(turn.tool_calls);
|
|
4178
4211
|
for (const tc of calls) {
|
|
4179
4212
|
const key = `${tc.name}:${tc.isError ? "err" : "ok"}`;
|
|
@@ -4182,7 +4215,7 @@ async function svapnaReplay(db, config) {
|
|
|
4182
4215
|
}
|
|
4183
4216
|
}
|
|
4184
4217
|
const scoredTurns = [];
|
|
4185
|
-
for (const turn of
|
|
4218
|
+
for (const turn of realTurns) {
|
|
4186
4219
|
const calls = parseToolCalls(turn.tool_calls);
|
|
4187
4220
|
let surprise = 0;
|
|
4188
4221
|
if (calls.length > 0) {
|
|
@@ -4626,7 +4659,7 @@ async function svapnaProceduralize(db, config) {
|
|
|
4626
4659
|
return { vidhisCreated: createdVidhis.length, vidhis: createdVidhis, durationMs: performance.now() - start };
|
|
4627
4660
|
}
|
|
4628
4661
|
|
|
4629
|
-
// ../chitragupta/packages/smriti/dist/svapna-
|
|
4662
|
+
// ../chitragupta/packages/smriti/dist/svapna-types.js
|
|
4630
4663
|
var DEFAULT_CONFIG4 = {
|
|
4631
4664
|
maxSessionsPerCycle: 50,
|
|
4632
4665
|
surpriseThreshold: 0.7,
|
|
@@ -4643,6 +4676,8 @@ var PRAMANA_PRESERVATION = {
|
|
|
4643
4676
|
arthapatti: 0.4,
|
|
4644
4677
|
anupalabdhi: 0.25
|
|
4645
4678
|
};
|
|
4679
|
+
|
|
4680
|
+
// ../chitragupta/packages/smriti/dist/svapna-consolidation.js
|
|
4646
4681
|
var SvapnaConsolidation = class {
|
|
4647
4682
|
config;
|
|
4648
4683
|
db;
|
|
@@ -4689,30 +4724,11 @@ var SvapnaConsolidation = class {
|
|
|
4689
4724
|
const totalDurationMs = performance.now() - cycleStart;
|
|
4690
4725
|
const result = {
|
|
4691
4726
|
phases: {
|
|
4692
|
-
replay: {
|
|
4693
|
-
|
|
4694
|
-
|
|
4695
|
-
|
|
4696
|
-
}
|
|
4697
|
-
recombine: {
|
|
4698
|
-
associations: recombineResult.associations.length,
|
|
4699
|
-
crossSessions: recombineResult.crossSessions,
|
|
4700
|
-
durationMs: recombineResult.durationMs
|
|
4701
|
-
},
|
|
4702
|
-
crystallize: {
|
|
4703
|
-
vasanasCreated: crystallizeResult.vasanasCreated,
|
|
4704
|
-
vasanasReinforced: crystallizeResult.vasanasReinforced,
|
|
4705
|
-
durationMs: crystallizeResult.durationMs
|
|
4706
|
-
},
|
|
4707
|
-
proceduralize: {
|
|
4708
|
-
vidhisCreated: proceduralizeResult.vidhisCreated,
|
|
4709
|
-
durationMs: proceduralizeResult.durationMs
|
|
4710
|
-
},
|
|
4711
|
-
compress: {
|
|
4712
|
-
tokensCompressed: compressResult.tokensCompressed,
|
|
4713
|
-
compressionRatio: compressResult.compressionRatio,
|
|
4714
|
-
durationMs: compressResult.durationMs
|
|
4715
|
-
}
|
|
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 }
|
|
4716
4732
|
},
|
|
4717
4733
|
totalDurationMs,
|
|
4718
4734
|
cycleId: this.cycleId
|
|
@@ -4767,6 +4783,8 @@ var SvapnaConsolidation = class {
|
|
|
4767
4783
|
const maxAge = 30 * 24 * 60 * 60 * 1e3;
|
|
4768
4784
|
let totalOriginalTokens = 0;
|
|
4769
4785
|
for (const turn of turns) {
|
|
4786
|
+
if (this.isNoiseTurn(turn.content))
|
|
4787
|
+
continue;
|
|
4770
4788
|
const tokens = estimateTokens(turn.content);
|
|
4771
4789
|
totalOriginalTokens += tokens;
|
|
4772
4790
|
const calls = parseToolCalls(turn.tool_calls);
|
|
@@ -4785,6 +4803,13 @@ var SvapnaConsolidation = class {
|
|
|
4785
4803
|
if (chunks.length < 2) {
|
|
4786
4804
|
return { tokensCompressed: totalOriginalTokens, compressionRatio: 1, durationMs: performance.now() - start };
|
|
4787
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) {
|
|
4788
4813
|
const n = chunks.length;
|
|
4789
4814
|
const affinity = [];
|
|
4790
4815
|
for (let i = 0; i < n; i++) {
|
|
@@ -4809,6 +4834,7 @@ var SvapnaConsolidation = class {
|
|
|
4809
4834
|
}
|
|
4810
4835
|
const targetTokens = Math.floor(totalOriginalTokens * 0.7);
|
|
4811
4836
|
let compressedTotal = 0;
|
|
4837
|
+
const agentDb = this.db.get("agent");
|
|
4812
4838
|
const updateStmt = agentDb.prepare(`UPDATE turns SET content = ? WHERE id = ?`);
|
|
4813
4839
|
const insertRuleStmt = agentDb.prepare(`INSERT INTO consolidation_rules
|
|
4814
4840
|
(project, category, rule_text, source_sessions, confidence, created_at, updated_at)
|
|
@@ -4828,8 +4854,7 @@ var SvapnaConsolidation = class {
|
|
|
4828
4854
|
if (cueAnchors.length > 0) {
|
|
4829
4855
|
try {
|
|
4830
4856
|
const graphDb = this.db.get("graph");
|
|
4831
|
-
const upsertNode = graphDb.prepare(`INSERT OR REPLACE INTO nodes (id, type, label, content, metadata)
|
|
4832
|
-
VALUES (?, 'concept', ?, ?, ?)`);
|
|
4857
|
+
const upsertNode = graphDb.prepare(`INSERT OR REPLACE INTO nodes (id, type, label, content, metadata) VALUES (?, 'concept', ?, ?, ?)`);
|
|
4833
4858
|
for (const cue of cueAnchors) {
|
|
4834
4859
|
upsertNode.run(`cue-${turn.id}-${cue.slice(0, 20)}`, cue, gist.slice(0, 200), JSON.stringify({ source: `turn:${turn.id}`, cycle: this.cycleId }));
|
|
4835
4860
|
}
|
|
@@ -4843,15 +4868,9 @@ var SvapnaConsolidation = class {
|
|
|
4843
4868
|
compressBatch();
|
|
4844
4869
|
} catch {
|
|
4845
4870
|
}
|
|
4846
|
-
|
|
4847
|
-
return { tokensCompressed: totalOriginalTokens, compressionRatio, durationMs: performance.now() - start };
|
|
4871
|
+
return { compressedTotal };
|
|
4848
4872
|
}
|
|
4849
|
-
|
|
4850
|
-
/**
|
|
4851
|
-
* Generate a compressed gist (abstraction) of turn content.
|
|
4852
|
-
* Uses extractive summarization: keeps the first and last sentences,
|
|
4853
|
-
* plus any sentences containing tool calls or decisions.
|
|
4854
|
-
*/
|
|
4873
|
+
/** Generate a compressed gist (abstraction) of turn content. */
|
|
4855
4874
|
generateGist(content, tokenBudget) {
|
|
4856
4875
|
const sentences = content.split(/(?<=[.!?\n])\s+/).filter((s) => s.trim().length > 0);
|
|
4857
4876
|
if (sentences.length <= 2)
|
|
@@ -4859,42 +4878,47 @@ var SvapnaConsolidation = class {
|
|
|
4859
4878
|
const kept = [sentences[0]];
|
|
4860
4879
|
const signalPattern = /\b(error|decided|created|modified|fixed|found|returned|result|output)\b/i;
|
|
4861
4880
|
for (let i = 1; i < sentences.length - 1; i++) {
|
|
4862
|
-
if (signalPattern.test(sentences[i]))
|
|
4881
|
+
if (signalPattern.test(sentences[i]))
|
|
4863
4882
|
kept.push(sentences[i]);
|
|
4864
|
-
}
|
|
4865
4883
|
}
|
|
4866
4884
|
kept.push(sentences[sentences.length - 1]);
|
|
4867
4885
|
let gist = kept.join(" ");
|
|
4868
4886
|
const words = gist.split(/\s+/);
|
|
4869
4887
|
const wordBudget = Math.max(5, Math.floor(tokenBudget * 0.75));
|
|
4870
|
-
if (words.length > wordBudget)
|
|
4871
|
-
gist = words.slice(0, wordBudget).join(" ") + "
|
|
4872
|
-
}
|
|
4888
|
+
if (words.length > wordBudget)
|
|
4889
|
+
gist = words.slice(0, wordBudget).join(" ") + "...";
|
|
4873
4890
|
return `[compressed] ${gist}`;
|
|
4874
4891
|
}
|
|
4875
|
-
/**
|
|
4876
|
-
* Extract cue anchors (trigger phrases) from turn content.
|
|
4877
|
-
* These serve as retrieval hooks in GraphRAG for finding compressed turns.
|
|
4878
|
-
*/
|
|
4892
|
+
/** Extract cue anchors (trigger phrases) from turn content. */
|
|
4879
4893
|
extractCueAnchors(content) {
|
|
4880
4894
|
const anchors = [];
|
|
4881
4895
|
const lower = content.toLowerCase();
|
|
4882
4896
|
const voPattern = /\b(create|fix|refactor|implement|add|remove|update|debug|test|deploy|configure)\s+(\w+(?:\s+\w+)?)\b/gi;
|
|
4883
4897
|
let match;
|
|
4884
|
-
while ((match = voPattern.exec(lower)) !== null)
|
|
4898
|
+
while ((match = voPattern.exec(lower)) !== null)
|
|
4885
4899
|
anchors.push(match[0].trim());
|
|
4886
|
-
}
|
|
4887
4900
|
const pathPattern = /[\w\-]+\.(?:ts|js|py|rs|go|java|tsx|jsx|json|yaml|toml)\b/gi;
|
|
4888
|
-
while ((match = pathPattern.exec(content)) !== null)
|
|
4901
|
+
while ((match = pathPattern.exec(content)) !== null)
|
|
4889
4902
|
anchors.push(match[0]);
|
|
4890
|
-
}
|
|
4891
4903
|
return [...new Set(anchors)].slice(0, 5);
|
|
4892
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;
|
|
4917
|
+
}
|
|
4893
4918
|
/** Classify epistemological source (Pramana) of a turn's content. */
|
|
4894
4919
|
classifyPramana(content, calls) {
|
|
4895
|
-
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))
|
|
4896
4921
|
return "pratyaksha";
|
|
4897
|
-
}
|
|
4898
4922
|
const lower = content.toLowerCase();
|
|
4899
4923
|
if (/\b(?:maybe|possibly|might|perhaps|could be|not sure|unsure)\b/.test(lower))
|
|
4900
4924
|
return "anupalabdhi";
|
|
@@ -5646,526 +5670,6 @@ var VidhiEngine = class {
|
|
|
5646
5670
|
}
|
|
5647
5671
|
};
|
|
5648
5672
|
|
|
5649
|
-
// ../chitragupta/packages/smriti/dist/akasha-integration.js
|
|
5650
|
-
var CREATE_TABLE_SQL = `
|
|
5651
|
-
CREATE TABLE IF NOT EXISTS akasha_traces (
|
|
5652
|
-
id TEXT PRIMARY KEY,
|
|
5653
|
-
agent_id TEXT NOT NULL,
|
|
5654
|
-
trace_type TEXT NOT NULL,
|
|
5655
|
-
topic TEXT NOT NULL,
|
|
5656
|
-
content TEXT NOT NULL,
|
|
5657
|
-
strength REAL NOT NULL,
|
|
5658
|
-
reinforcements INTEGER NOT NULL DEFAULT 0,
|
|
5659
|
-
metadata TEXT,
|
|
5660
|
-
created_at INTEGER NOT NULL,
|
|
5661
|
-
last_reinforced_at INTEGER NOT NULL
|
|
5662
|
-
);
|
|
5663
|
-
CREATE INDEX IF NOT EXISTS idx_akasha_topic ON akasha_traces(topic);
|
|
5664
|
-
CREATE INDEX IF NOT EXISTS idx_akasha_strength ON akasha_traces(strength DESC);
|
|
5665
|
-
`;
|
|
5666
|
-
var UPSERT_SQL = `
|
|
5667
|
-
INSERT OR REPLACE INTO akasha_traces
|
|
5668
|
-
(id, agent_id, trace_type, topic, content, strength,
|
|
5669
|
-
reinforcements, metadata, created_at, last_reinforced_at)
|
|
5670
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
5671
|
-
`;
|
|
5672
|
-
var ENSURE_TABLE_SQL = `
|
|
5673
|
-
CREATE TABLE IF NOT EXISTS akasha_traces (
|
|
5674
|
-
id TEXT PRIMARY KEY,
|
|
5675
|
-
agent_id TEXT NOT NULL,
|
|
5676
|
-
trace_type TEXT NOT NULL,
|
|
5677
|
-
topic TEXT NOT NULL,
|
|
5678
|
-
content TEXT NOT NULL,
|
|
5679
|
-
strength REAL NOT NULL,
|
|
5680
|
-
reinforcements INTEGER NOT NULL DEFAULT 0,
|
|
5681
|
-
metadata TEXT,
|
|
5682
|
-
created_at INTEGER NOT NULL,
|
|
5683
|
-
last_reinforced_at INTEGER NOT NULL
|
|
5684
|
-
);
|
|
5685
|
-
`;
|
|
5686
|
-
function safeParseJson(raw) {
|
|
5687
|
-
if (!raw)
|
|
5688
|
-
return {};
|
|
5689
|
-
try {
|
|
5690
|
-
const parsed = JSON.parse(raw);
|
|
5691
|
-
return typeof parsed === "object" && parsed !== null ? parsed : {};
|
|
5692
|
-
} catch {
|
|
5693
|
-
return {};
|
|
5694
|
-
}
|
|
5695
|
-
}
|
|
5696
|
-
function persistTraces(traces, db) {
|
|
5697
|
-
db.exec(CREATE_TABLE_SQL);
|
|
5698
|
-
const upsert = db.prepare(UPSERT_SQL);
|
|
5699
|
-
for (const trace of traces.values()) {
|
|
5700
|
-
upsert.run(trace.id, trace.agentId, trace.traceType, trace.topic, trace.content, trace.strength, trace.reinforcements, JSON.stringify(trace.metadata), trace.createdAt, trace.lastReinforcedAt);
|
|
5701
|
-
}
|
|
5702
|
-
}
|
|
5703
|
-
function restoreTraces(db, config) {
|
|
5704
|
-
db.exec(ENSURE_TABLE_SQL);
|
|
5705
|
-
const rows = db.prepare("SELECT * FROM akasha_traces").all();
|
|
5706
|
-
const traces = /* @__PURE__ */ new Map();
|
|
5707
|
-
const reinforcedBy = /* @__PURE__ */ new Map();
|
|
5708
|
-
for (const row of rows) {
|
|
5709
|
-
if (row.strength < config.minStrength)
|
|
5710
|
-
continue;
|
|
5711
|
-
const trace = {
|
|
5712
|
-
id: row.id,
|
|
5713
|
-
agentId: row.agent_id,
|
|
5714
|
-
traceType: row.trace_type,
|
|
5715
|
-
topic: row.topic,
|
|
5716
|
-
content: row.content,
|
|
5717
|
-
strength: row.strength,
|
|
5718
|
-
reinforcements: row.reinforcements,
|
|
5719
|
-
metadata: safeParseJson(row.metadata),
|
|
5720
|
-
createdAt: row.created_at,
|
|
5721
|
-
lastReinforcedAt: row.last_reinforced_at
|
|
5722
|
-
};
|
|
5723
|
-
traces.set(trace.id, trace);
|
|
5724
|
-
reinforcedBy.set(trace.id, /* @__PURE__ */ new Set([trace.agentId]));
|
|
5725
|
-
}
|
|
5726
|
-
return { traces, reinforcedBy };
|
|
5727
|
-
}
|
|
5728
|
-
function tracesToGraphNodes(traces, minStrength) {
|
|
5729
|
-
const nodes = [];
|
|
5730
|
-
for (const trace of traces.values()) {
|
|
5731
|
-
if (trace.strength < minStrength)
|
|
5732
|
-
continue;
|
|
5733
|
-
nodes.push({
|
|
5734
|
-
id: trace.id,
|
|
5735
|
-
label: `[${trace.traceType}] ${trace.topic}`,
|
|
5736
|
-
content: trace.content,
|
|
5737
|
-
type: "akasha",
|
|
5738
|
-
weight: trace.strength
|
|
5739
|
-
});
|
|
5740
|
-
}
|
|
5741
|
-
return nodes;
|
|
5742
|
-
}
|
|
5743
|
-
function boostResultsWithTraces(traces, config, results, query) {
|
|
5744
|
-
const queryTokens = new Set(tokenize3(query));
|
|
5745
|
-
const matchingTraces = [];
|
|
5746
|
-
if (queryTokens.size > 0) {
|
|
5747
|
-
for (const trace of traces.values()) {
|
|
5748
|
-
if (trace.strength < config.minStrength)
|
|
5749
|
-
continue;
|
|
5750
|
-
const traceTokens = /* @__PURE__ */ new Set([
|
|
5751
|
-
...tokenize3(trace.topic),
|
|
5752
|
-
...tokenize3(trace.content)
|
|
5753
|
-
]);
|
|
5754
|
-
const sim = jaccardSimilarity2(queryTokens, traceTokens);
|
|
5755
|
-
if (sim > 0) {
|
|
5756
|
-
matchingTraces.push({ trace, similarity: sim });
|
|
5757
|
-
}
|
|
5758
|
-
}
|
|
5759
|
-
matchingTraces.sort((a, b) => b.similarity - a.similarity);
|
|
5760
|
-
}
|
|
5761
|
-
return results.map((result) => {
|
|
5762
|
-
let traceBoost = 0;
|
|
5763
|
-
if (queryTokens.size > 0 && matchingTraces.length > 0) {
|
|
5764
|
-
const resultTokens = result.content ? new Set(tokenize3(result.content)) : /* @__PURE__ */ new Set();
|
|
5765
|
-
let bestBoost = 0;
|
|
5766
|
-
for (const { trace, similarity } of matchingTraces) {
|
|
5767
|
-
if (result.id === trace.id) {
|
|
5768
|
-
bestBoost = Math.max(bestBoost, trace.strength);
|
|
5769
|
-
break;
|
|
5770
|
-
}
|
|
5771
|
-
if (resultTokens.size > 0) {
|
|
5772
|
-
const traceTokens = /* @__PURE__ */ new Set([
|
|
5773
|
-
...tokenize3(trace.topic),
|
|
5774
|
-
...tokenize3(trace.content)
|
|
5775
|
-
]);
|
|
5776
|
-
const resultSim = jaccardSimilarity2(resultTokens, traceTokens);
|
|
5777
|
-
if (resultSim > 0.1) {
|
|
5778
|
-
bestBoost = Math.max(bestBoost, similarity * trace.strength);
|
|
5779
|
-
}
|
|
5780
|
-
} else {
|
|
5781
|
-
bestBoost = Math.max(bestBoost, similarity * trace.strength);
|
|
5782
|
-
}
|
|
5783
|
-
}
|
|
5784
|
-
traceBoost = bestBoost * config.traceBoostFactor;
|
|
5785
|
-
}
|
|
5786
|
-
return {
|
|
5787
|
-
...result,
|
|
5788
|
-
score: result.score * (1 + traceBoost),
|
|
5789
|
-
traceBoost
|
|
5790
|
-
};
|
|
5791
|
-
});
|
|
5792
|
-
}
|
|
5793
|
-
|
|
5794
|
-
// ../chitragupta/packages/smriti/dist/akasha.js
|
|
5795
|
-
var STOP_WORDS = /* @__PURE__ */ new Set([
|
|
5796
|
-
"a",
|
|
5797
|
-
"an",
|
|
5798
|
-
"the",
|
|
5799
|
-
"and",
|
|
5800
|
-
"or",
|
|
5801
|
-
"but",
|
|
5802
|
-
"in",
|
|
5803
|
-
"on",
|
|
5804
|
-
"at",
|
|
5805
|
-
"to",
|
|
5806
|
-
"for",
|
|
5807
|
-
"of",
|
|
5808
|
-
"with",
|
|
5809
|
-
"by",
|
|
5810
|
-
"from",
|
|
5811
|
-
"is",
|
|
5812
|
-
"it",
|
|
5813
|
-
"its",
|
|
5814
|
-
"this",
|
|
5815
|
-
"that",
|
|
5816
|
-
"was",
|
|
5817
|
-
"are",
|
|
5818
|
-
"be",
|
|
5819
|
-
"been",
|
|
5820
|
-
"being",
|
|
5821
|
-
"have",
|
|
5822
|
-
"has",
|
|
5823
|
-
"had",
|
|
5824
|
-
"do",
|
|
5825
|
-
"does",
|
|
5826
|
-
"did",
|
|
5827
|
-
"will",
|
|
5828
|
-
"would",
|
|
5829
|
-
"could",
|
|
5830
|
-
"should",
|
|
5831
|
-
"not",
|
|
5832
|
-
"no",
|
|
5833
|
-
"so",
|
|
5834
|
-
"if",
|
|
5835
|
-
"then",
|
|
5836
|
-
"than",
|
|
5837
|
-
"too",
|
|
5838
|
-
"very",
|
|
5839
|
-
"can",
|
|
5840
|
-
"just",
|
|
5841
|
-
"about",
|
|
5842
|
-
"into",
|
|
5843
|
-
"over",
|
|
5844
|
-
"after"
|
|
5845
|
-
]);
|
|
5846
|
-
var FNV_OFFSET6 = 2166136261;
|
|
5847
|
-
var FNV_PRIME6 = 16777619;
|
|
5848
|
-
function fnv1a7(input) {
|
|
5849
|
-
let hash = FNV_OFFSET6;
|
|
5850
|
-
for (let i = 0; i < input.length; i++) {
|
|
5851
|
-
hash ^= input.charCodeAt(i);
|
|
5852
|
-
hash = Math.imul(hash, FNV_PRIME6) >>> 0;
|
|
5853
|
-
}
|
|
5854
|
-
return hash.toString(16).padStart(8, "0");
|
|
5855
|
-
}
|
|
5856
|
-
function tokenize3(text) {
|
|
5857
|
-
return text.toLowerCase().replace(/[^a-z0-9\s]/g, " ").split(/\s+/).filter((t) => t.length >= 2 && !STOP_WORDS.has(t));
|
|
5858
|
-
}
|
|
5859
|
-
function jaccardSimilarity2(a, b) {
|
|
5860
|
-
if (a.size === 0 && b.size === 0)
|
|
5861
|
-
return 1;
|
|
5862
|
-
let intersection = 0;
|
|
5863
|
-
for (const token of a) {
|
|
5864
|
-
if (b.has(token))
|
|
5865
|
-
intersection++;
|
|
5866
|
-
}
|
|
5867
|
-
const union = a.size + b.size - intersection;
|
|
5868
|
-
return union === 0 ? 0 : intersection / union;
|
|
5869
|
-
}
|
|
5870
|
-
var DAY_MS = 864e5;
|
|
5871
|
-
var DEFAULT_CONFIG6 = {
|
|
5872
|
-
decayHalfLife: 7 * DAY_MS,
|
|
5873
|
-
minStrength: 0.01,
|
|
5874
|
-
maxTraces: 5e3,
|
|
5875
|
-
reinforcementBoost: 0.15,
|
|
5876
|
-
initialStrength: 0.5,
|
|
5877
|
-
topKRetrieval: 10,
|
|
5878
|
-
traceBoostFactor: 0.3,
|
|
5879
|
-
diminishingAlpha: 0.3,
|
|
5880
|
-
frequencyDecayBeta: 0.5
|
|
5881
|
-
};
|
|
5882
|
-
var HARD_CEILINGS = {
|
|
5883
|
-
maxTraces: 5e4,
|
|
5884
|
-
minDecayHalfLife: 36e5,
|
|
5885
|
-
maxContentSize: 1e4
|
|
5886
|
-
};
|
|
5887
|
-
var AkashaField = class {
|
|
5888
|
-
config;
|
|
5889
|
-
traces = /* @__PURE__ */ new Map();
|
|
5890
|
-
/** Tracks which agents reinforced which traces (prevents self/duplicate). */
|
|
5891
|
-
reinforcedBy = /* @__PURE__ */ new Map();
|
|
5892
|
-
constructor(config) {
|
|
5893
|
-
this.config = {
|
|
5894
|
-
...DEFAULT_CONFIG6,
|
|
5895
|
-
...config,
|
|
5896
|
-
maxTraces: Math.min(config?.maxTraces ?? DEFAULT_CONFIG6.maxTraces, HARD_CEILINGS.maxTraces),
|
|
5897
|
-
decayHalfLife: Math.max(config?.decayHalfLife ?? DEFAULT_CONFIG6.decayHalfLife, HARD_CEILINGS.minDecayHalfLife)
|
|
5898
|
-
};
|
|
5899
|
-
}
|
|
5900
|
-
// ─── Leaving Traces ─────────────────────────────────────────────────
|
|
5901
|
-
/**
|
|
5902
|
-
* Agent leaves a stigmergic trace after solving or discovering something.
|
|
5903
|
-
*
|
|
5904
|
-
* @param agentId - Which agent is leaving this trace.
|
|
5905
|
-
* @param type - The category of knowledge.
|
|
5906
|
-
* @param topic - What the trace is about (used for matching).
|
|
5907
|
-
* @param content - The actual knowledge or solution.
|
|
5908
|
-
* @param metadata - Optional metadata for the trace.
|
|
5909
|
-
* @returns The created StigmergicTrace.
|
|
5910
|
-
*/
|
|
5911
|
-
leave(agentId, type, topic, content, metadata) {
|
|
5912
|
-
const truncatedContent = content.length > HARD_CEILINGS.maxContentSize ? content.slice(0, HARD_CEILINGS.maxContentSize) : content;
|
|
5913
|
-
const id = `aks-${fnv1a7(agentId + ":" + type + ":" + topic + ":" + truncatedContent)}`;
|
|
5914
|
-
const now = Date.now();
|
|
5915
|
-
const trace = {
|
|
5916
|
-
id,
|
|
5917
|
-
agentId,
|
|
5918
|
-
traceType: type,
|
|
5919
|
-
topic,
|
|
5920
|
-
content: truncatedContent,
|
|
5921
|
-
strength: this.config.initialStrength,
|
|
5922
|
-
reinforcements: 0,
|
|
5923
|
-
metadata: metadata ?? {},
|
|
5924
|
-
createdAt: now,
|
|
5925
|
-
lastReinforcedAt: now
|
|
5926
|
-
};
|
|
5927
|
-
this.traces.set(id, trace);
|
|
5928
|
-
this.reinforcedBy.set(id, /* @__PURE__ */ new Set([agentId]));
|
|
5929
|
-
if (this.traces.size > this.config.maxTraces)
|
|
5930
|
-
this.evictWeakest();
|
|
5931
|
-
return trace;
|
|
5932
|
-
}
|
|
5933
|
-
/**
|
|
5934
|
-
* Reinforce an existing trace -- another agent found it useful.
|
|
5935
|
-
*
|
|
5936
|
-
* @param traceId - The trace to reinforce.
|
|
5937
|
-
* @param agentId - The agent reinforcing it.
|
|
5938
|
-
* @returns The updated trace, or null if not found / already reinforced.
|
|
5939
|
-
*/
|
|
5940
|
-
reinforce(traceId, agentId) {
|
|
5941
|
-
const trace = this.traces.get(traceId);
|
|
5942
|
-
if (!trace)
|
|
5943
|
-
return null;
|
|
5944
|
-
const agents = this.reinforcedBy.get(traceId);
|
|
5945
|
-
if (agents?.has(agentId))
|
|
5946
|
-
return null;
|
|
5947
|
-
const alpha = this.config.diminishingAlpha;
|
|
5948
|
-
const effectiveBoost = this.config.reinforcementBoost / (1 + alpha * trace.reinforcements);
|
|
5949
|
-
trace.strength = Math.min(1, trace.strength + effectiveBoost);
|
|
5950
|
-
trace.reinforcements++;
|
|
5951
|
-
trace.lastReinforcedAt = Date.now();
|
|
5952
|
-
if (!agents) {
|
|
5953
|
-
this.reinforcedBy.set(traceId, /* @__PURE__ */ new Set([agentId]));
|
|
5954
|
-
} else {
|
|
5955
|
-
agents.add(agentId);
|
|
5956
|
-
}
|
|
5957
|
-
return trace;
|
|
5958
|
-
}
|
|
5959
|
-
// ─── Following Traces ────────────────────────────────────────────────
|
|
5960
|
-
/**
|
|
5961
|
-
* Find relevant traces by Jaccard similarity on topic/content tokens.
|
|
5962
|
-
*
|
|
5963
|
-
* @param topic - The query to match against trace topics and content.
|
|
5964
|
-
* @param opts - Optional filters: type, minStrength, limit.
|
|
5965
|
-
* @returns Matching traces sorted by relevance score.
|
|
5966
|
-
*/
|
|
5967
|
-
query(topic, opts) {
|
|
5968
|
-
const queryTokens = new Set(tokenize3(topic));
|
|
5969
|
-
if (queryTokens.size === 0)
|
|
5970
|
-
return [];
|
|
5971
|
-
const minStr = opts?.minStrength ?? this.config.minStrength;
|
|
5972
|
-
const limit = opts?.limit ?? this.config.topKRetrieval;
|
|
5973
|
-
const scored = [];
|
|
5974
|
-
for (const trace of this.traces.values()) {
|
|
5975
|
-
if (trace.strength < minStr)
|
|
5976
|
-
continue;
|
|
5977
|
-
if (opts?.type && trace.traceType !== opts.type)
|
|
5978
|
-
continue;
|
|
5979
|
-
const traceTokens = /* @__PURE__ */ new Set([...tokenize3(trace.topic), ...tokenize3(trace.content)]);
|
|
5980
|
-
const similarity = jaccardSimilarity2(queryTokens, traceTokens);
|
|
5981
|
-
if (similarity <= 0)
|
|
5982
|
-
continue;
|
|
5983
|
-
scored.push({ trace, score: similarity * trace.strength });
|
|
5984
|
-
}
|
|
5985
|
-
scored.sort((a, b) => b.score - a.score);
|
|
5986
|
-
return scored.slice(0, limit).map((s) => s.trace);
|
|
5987
|
-
}
|
|
5988
|
-
/**
|
|
5989
|
-
* Get the strongest traces overall -- the "highways" of collective knowledge.
|
|
5990
|
-
*
|
|
5991
|
-
* @param limit - Maximum number of traces to return.
|
|
5992
|
-
* @returns Traces sorted by strength descending.
|
|
5993
|
-
*/
|
|
5994
|
-
strongest(limit) {
|
|
5995
|
-
const all = [...this.traces.values()];
|
|
5996
|
-
all.sort((a, b) => b.strength - a.strength);
|
|
5997
|
-
return all.slice(0, limit ?? this.config.topKRetrieval);
|
|
5998
|
-
}
|
|
5999
|
-
/**
|
|
6000
|
-
* Get traces left by a specific agent.
|
|
6001
|
-
*
|
|
6002
|
-
* @param agentId - The agent whose traces to retrieve.
|
|
6003
|
-
* @param limit - Maximum results.
|
|
6004
|
-
* @returns Traces by the agent, sorted by creation time descending.
|
|
6005
|
-
*/
|
|
6006
|
-
byAgent(agentId, limit) {
|
|
6007
|
-
const results = [];
|
|
6008
|
-
for (const trace of this.traces.values()) {
|
|
6009
|
-
if (trace.agentId === agentId)
|
|
6010
|
-
results.push(trace);
|
|
6011
|
-
}
|
|
6012
|
-
results.sort((a, b) => b.createdAt - a.createdAt);
|
|
6013
|
-
return results.slice(0, limit ?? this.config.topKRetrieval);
|
|
6014
|
-
}
|
|
6015
|
-
// ─── Decay & Maintenance ─────────────────────────────────────────────
|
|
6016
|
-
/**
|
|
6017
|
-
* Apply temporal decay to all traces. Traces that fall below `minStrength`
|
|
6018
|
-
* after decay are pruned automatically.
|
|
6019
|
-
*
|
|
6020
|
-
* @returns Counts of decayed and pruned traces.
|
|
6021
|
-
*/
|
|
6022
|
-
decay() {
|
|
6023
|
-
const now = Date.now();
|
|
6024
|
-
const baseHalfLife = this.config.decayHalfLife;
|
|
6025
|
-
const beta = this.config.frequencyDecayBeta;
|
|
6026
|
-
let decayed = 0;
|
|
6027
|
-
const toPrune = [];
|
|
6028
|
-
for (const [id, trace] of this.traces) {
|
|
6029
|
-
const elapsed = now - trace.lastReinforcedAt;
|
|
6030
|
-
if (elapsed <= 0)
|
|
6031
|
-
continue;
|
|
6032
|
-
const effectiveHalfLife = baseHalfLife * (1 + beta * Math.log(1 + trace.reinforcements));
|
|
6033
|
-
const factor = Math.exp(-Math.LN2 * elapsed / effectiveHalfLife);
|
|
6034
|
-
const newStrength = trace.strength * factor;
|
|
6035
|
-
if (Math.abs(newStrength - trace.strength) > 1e-10) {
|
|
6036
|
-
trace.strength = newStrength;
|
|
6037
|
-
decayed++;
|
|
6038
|
-
}
|
|
6039
|
-
if (trace.strength < this.config.minStrength)
|
|
6040
|
-
toPrune.push(id);
|
|
6041
|
-
}
|
|
6042
|
-
for (const id of toPrune) {
|
|
6043
|
-
this.traces.delete(id);
|
|
6044
|
-
this.reinforcedBy.delete(id);
|
|
6045
|
-
}
|
|
6046
|
-
return { decayed, pruned: toPrune.length };
|
|
6047
|
-
}
|
|
6048
|
-
/**
|
|
6049
|
-
* Remove traces below the minStrength threshold.
|
|
6050
|
-
*
|
|
6051
|
-
* @returns The number of traces pruned.
|
|
6052
|
-
*/
|
|
6053
|
-
prune() {
|
|
6054
|
-
const toPrune = [];
|
|
6055
|
-
for (const [id, trace] of this.traces) {
|
|
6056
|
-
if (trace.strength < this.config.minStrength)
|
|
6057
|
-
toPrune.push(id);
|
|
6058
|
-
}
|
|
6059
|
-
for (const id of toPrune) {
|
|
6060
|
-
this.traces.delete(id);
|
|
6061
|
-
this.reinforcedBy.delete(id);
|
|
6062
|
-
}
|
|
6063
|
-
return toPrune.length;
|
|
6064
|
-
}
|
|
6065
|
-
// ─── Persistence (delegated to akasha-integration) ───────────────────
|
|
6066
|
-
/**
|
|
6067
|
-
* Persist all traces to a SQLite database.
|
|
6068
|
-
*
|
|
6069
|
-
* @param db - A duck-typed database handle with prepare/exec methods.
|
|
6070
|
-
*/
|
|
6071
|
-
persist(db) {
|
|
6072
|
-
persistTraces(this.traces, db);
|
|
6073
|
-
}
|
|
6074
|
-
/**
|
|
6075
|
-
* Restore traces from a SQLite database.
|
|
6076
|
-
*
|
|
6077
|
-
* @param db - A duck-typed database handle with prepare/exec methods.
|
|
6078
|
-
*/
|
|
6079
|
-
restore(db) {
|
|
6080
|
-
const result = restoreTraces(db, this.config);
|
|
6081
|
-
this.traces.clear();
|
|
6082
|
-
this.reinforcedBy.clear();
|
|
6083
|
-
for (const [k, v] of result.traces)
|
|
6084
|
-
this.traces.set(k, v);
|
|
6085
|
-
for (const [k, v] of result.reinforcedBy)
|
|
6086
|
-
this.reinforcedBy.set(k, v);
|
|
6087
|
-
}
|
|
6088
|
-
// ─── GraphRAG (delegated to akasha-integration) ──────────────────────
|
|
6089
|
-
/**
|
|
6090
|
-
* Register traces as graph nodes suitable for GraphRAG retrieval.
|
|
6091
|
-
*
|
|
6092
|
-
* @returns An array of graph-compatible node objects.
|
|
6093
|
-
*/
|
|
6094
|
-
toGraphNodes() {
|
|
6095
|
-
return tracesToGraphNodes(this.traces, this.config.minStrength);
|
|
6096
|
-
}
|
|
6097
|
-
/**
|
|
6098
|
-
* Boost graph search results that have matching stigmergic traces.
|
|
6099
|
-
*
|
|
6100
|
-
* @param results - The original search results with id and score.
|
|
6101
|
-
* @param query - The search query used for topic matching.
|
|
6102
|
-
* @returns Results with boosted scores and traceBoost metadata.
|
|
6103
|
-
*/
|
|
6104
|
-
boostResults(results, query) {
|
|
6105
|
-
return boostResultsWithTraces(this.traces, this.config, results, query);
|
|
6106
|
-
}
|
|
6107
|
-
// ─── Stats ───────────────────────────────────────────────────────────
|
|
6108
|
-
/**
|
|
6109
|
-
* Return statistics about the current state of the Akasha field.
|
|
6110
|
-
*
|
|
6111
|
-
* @returns Total/active counts, per-type breakdown, average strength,
|
|
6112
|
-
* strongest topic, and total reinforcements.
|
|
6113
|
-
*/
|
|
6114
|
-
stats() {
|
|
6115
|
-
const byType = {
|
|
6116
|
-
solution: 0,
|
|
6117
|
-
warning: 0,
|
|
6118
|
-
shortcut: 0,
|
|
6119
|
-
pattern: 0,
|
|
6120
|
-
correction: 0,
|
|
6121
|
-
preference: 0
|
|
6122
|
-
};
|
|
6123
|
-
let totalStrength = 0;
|
|
6124
|
-
let activeCount = 0;
|
|
6125
|
-
let totalReinforcements = 0;
|
|
6126
|
-
let strongestTrace = null;
|
|
6127
|
-
for (const trace of this.traces.values()) {
|
|
6128
|
-
byType[trace.traceType]++;
|
|
6129
|
-
totalStrength += trace.strength;
|
|
6130
|
-
totalReinforcements += trace.reinforcements;
|
|
6131
|
-
if (trace.strength >= this.config.minStrength)
|
|
6132
|
-
activeCount++;
|
|
6133
|
-
if (!strongestTrace || trace.strength > strongestTrace.strength) {
|
|
6134
|
-
strongestTrace = trace;
|
|
6135
|
-
}
|
|
6136
|
-
}
|
|
6137
|
-
return {
|
|
6138
|
-
totalTraces: this.traces.size,
|
|
6139
|
-
activeTraces: activeCount,
|
|
6140
|
-
byType,
|
|
6141
|
-
avgStrength: this.traces.size > 0 ? totalStrength / this.traces.size : 0,
|
|
6142
|
-
strongestTopic: strongestTrace?.topic ?? null,
|
|
6143
|
-
totalReinforcements
|
|
6144
|
-
};
|
|
6145
|
-
}
|
|
6146
|
-
// ─── Internal Helpers ────────────────────────────────────────────────
|
|
6147
|
-
/** Evict the weakest trace. Ties broken by oldest createdAt. */
|
|
6148
|
-
evictWeakest() {
|
|
6149
|
-
let weakestId = null;
|
|
6150
|
-
let weakestStrength = Infinity;
|
|
6151
|
-
let weakestCreatedAt = Infinity;
|
|
6152
|
-
for (const [id, trace] of this.traces) {
|
|
6153
|
-
if (trace.strength < weakestStrength || trace.strength === weakestStrength && trace.createdAt < weakestCreatedAt) {
|
|
6154
|
-
weakestId = id;
|
|
6155
|
-
weakestStrength = trace.strength;
|
|
6156
|
-
weakestCreatedAt = trace.createdAt;
|
|
6157
|
-
}
|
|
6158
|
-
}
|
|
6159
|
-
if (!weakestId && this.traces.size > 0) {
|
|
6160
|
-
weakestId = this.traces.keys().next().value;
|
|
6161
|
-
}
|
|
6162
|
-
if (weakestId) {
|
|
6163
|
-
this.traces.delete(weakestId);
|
|
6164
|
-
this.reinforcedBy.delete(weakestId);
|
|
6165
|
-
}
|
|
6166
|
-
}
|
|
6167
|
-
};
|
|
6168
|
-
|
|
6169
5673
|
// ../chitragupta/packages/smriti/dist/temporal-context.js
|
|
6170
5674
|
var MINUTE = 6e4;
|
|
6171
5675
|
var HOUR = 36e5;
|
|
@@ -6195,7 +5699,7 @@ var DEFAULT_SCALE_WEIGHTS = {
|
|
|
6195
5699
|
quarter: 0.08,
|
|
6196
5700
|
year: 0.07
|
|
6197
5701
|
};
|
|
6198
|
-
var
|
|
5702
|
+
var HARD_CEILINGS = {
|
|
6199
5703
|
/** Minimum half-life: 1 second. Anything faster is meaningless. */
|
|
6200
5704
|
minDecayRate: 1e3,
|
|
6201
5705
|
/** Maximum half-life: 10 years. Beyond this, nothing decays. */
|
|
@@ -6380,14 +5884,14 @@ var KalaChakra = class {
|
|
|
6380
5884
|
if (config?.decayRates) {
|
|
6381
5885
|
for (const scale of TEMPORAL_SCALES) {
|
|
6382
5886
|
if (config.decayRates[scale] !== void 0) {
|
|
6383
|
-
this._decayRates[scale] = clamp(config.decayRates[scale],
|
|
5887
|
+
this._decayRates[scale] = clamp(config.decayRates[scale], HARD_CEILINGS.minDecayRate, HARD_CEILINGS.maxDecayRate);
|
|
6384
5888
|
}
|
|
6385
5889
|
}
|
|
6386
5890
|
}
|
|
6387
5891
|
if (config?.scaleWeights) {
|
|
6388
5892
|
for (const scale of TEMPORAL_SCALES) {
|
|
6389
5893
|
if (config.scaleWeights[scale] !== void 0) {
|
|
6390
|
-
this._scaleWeights[scale] = clamp(config.scaleWeights[scale],
|
|
5894
|
+
this._scaleWeights[scale] = clamp(config.scaleWeights[scale], HARD_CEILINGS.minWeight, HARD_CEILINGS.maxWeight);
|
|
6391
5895
|
}
|
|
6392
5896
|
}
|
|
6393
5897
|
}
|
|
@@ -6530,14 +6034,14 @@ var KalaChakra = class {
|
|
|
6530
6034
|
if (data.decayRates && typeof data.decayRates === "object") {
|
|
6531
6035
|
for (const scale of TEMPORAL_SCALES) {
|
|
6532
6036
|
if (typeof data.decayRates[scale] === "number") {
|
|
6533
|
-
this._decayRates[scale] = clamp(data.decayRates[scale],
|
|
6037
|
+
this._decayRates[scale] = clamp(data.decayRates[scale], HARD_CEILINGS.minDecayRate, HARD_CEILINGS.maxDecayRate);
|
|
6534
6038
|
}
|
|
6535
6039
|
}
|
|
6536
6040
|
}
|
|
6537
6041
|
if (data.scaleWeights && typeof data.scaleWeights === "object") {
|
|
6538
6042
|
for (const scale of TEMPORAL_SCALES) {
|
|
6539
6043
|
if (typeof data.scaleWeights[scale] === "number") {
|
|
6540
|
-
this._scaleWeights[scale] = clamp(data.scaleWeights[scale],
|
|
6044
|
+
this._scaleWeights[scale] = clamp(data.scaleWeights[scale], HARD_CEILINGS.minWeight, HARD_CEILINGS.maxWeight);
|
|
6541
6045
|
}
|
|
6542
6046
|
}
|
|
6543
6047
|
}
|
|
@@ -6565,13 +6069,13 @@ function clamp(value, min, max) {
|
|
|
6565
6069
|
}
|
|
6566
6070
|
|
|
6567
6071
|
// ../chitragupta/packages/smriti/dist/pancha-vritti-patterns.js
|
|
6568
|
-
var
|
|
6569
|
-
var
|
|
6570
|
-
function
|
|
6571
|
-
let hash =
|
|
6072
|
+
var FNV_OFFSET6 = 2166136261;
|
|
6073
|
+
var FNV_PRIME6 = 16777619;
|
|
6074
|
+
function fnv1a7(input) {
|
|
6075
|
+
let hash = FNV_OFFSET6;
|
|
6572
6076
|
for (let i = 0; i < input.length; i++) {
|
|
6573
6077
|
hash ^= input.charCodeAt(i);
|
|
6574
|
-
hash = Math.imul(hash,
|
|
6078
|
+
hash = Math.imul(hash, FNV_PRIME6);
|
|
6575
6079
|
}
|
|
6576
6080
|
return (hash >>> 0).toString(16).padStart(8, "0");
|
|
6577
6081
|
}
|
|
@@ -6712,13 +6216,13 @@ var VRITTI_CONFIDENCE_WEIGHTS = {
|
|
|
6712
6216
|
vikalpa: 0.5,
|
|
6713
6217
|
viparyaya: 0.3
|
|
6714
6218
|
};
|
|
6715
|
-
var
|
|
6219
|
+
var DEFAULT_CONFIG6 = {
|
|
6716
6220
|
maxClassifications: 5e3,
|
|
6717
6221
|
minConfidence: 0.4,
|
|
6718
6222
|
snippetMaxLength: 200,
|
|
6719
6223
|
confidenceWeights: { ...VRITTI_CONFIDENCE_WEIGHTS }
|
|
6720
6224
|
};
|
|
6721
|
-
var
|
|
6225
|
+
var HARD_CEILINGS2 = {
|
|
6722
6226
|
maxClassifications: 5e4,
|
|
6723
6227
|
snippetMaxLength: 1e3
|
|
6724
6228
|
};
|
|
@@ -6729,18 +6233,18 @@ var PanchaVritti = class {
|
|
|
6729
6233
|
totalReclassified = 0;
|
|
6730
6234
|
constructor(config) {
|
|
6731
6235
|
const merged = {
|
|
6732
|
-
...
|
|
6236
|
+
...DEFAULT_CONFIG6,
|
|
6733
6237
|
...config,
|
|
6734
6238
|
confidenceWeights: {
|
|
6735
|
-
...
|
|
6239
|
+
...DEFAULT_CONFIG6.confidenceWeights,
|
|
6736
6240
|
...config?.confidenceWeights
|
|
6737
6241
|
}
|
|
6738
6242
|
};
|
|
6739
|
-
if (typeof
|
|
6740
|
-
merged.maxClassifications = Math.min(merged.maxClassifications,
|
|
6243
|
+
if (typeof HARD_CEILINGS2.maxClassifications === "number") {
|
|
6244
|
+
merged.maxClassifications = Math.min(merged.maxClassifications, HARD_CEILINGS2.maxClassifications);
|
|
6741
6245
|
}
|
|
6742
|
-
if (typeof
|
|
6743
|
-
merged.snippetMaxLength = Math.min(merged.snippetMaxLength,
|
|
6246
|
+
if (typeof HARD_CEILINGS2.snippetMaxLength === "number") {
|
|
6247
|
+
merged.snippetMaxLength = Math.min(merged.snippetMaxLength, HARD_CEILINGS2.snippetMaxLength);
|
|
6744
6248
|
}
|
|
6745
6249
|
this.cfg = merged;
|
|
6746
6250
|
}
|
|
@@ -6769,7 +6273,7 @@ var PanchaVritti = class {
|
|
|
6769
6273
|
prePatterns.push("context:error-flag");
|
|
6770
6274
|
}
|
|
6771
6275
|
if (content.trim().length === 0) {
|
|
6772
|
-
const id2 =
|
|
6276
|
+
const id2 = fnv1a7("nidra:" + now.toString());
|
|
6773
6277
|
const classification2 = {
|
|
6774
6278
|
id: id2,
|
|
6775
6279
|
type: "nidra",
|
|
@@ -6793,7 +6297,7 @@ var PanchaVritti = class {
|
|
|
6793
6297
|
if (winnerConfidence < this.cfg.minConfidence) {
|
|
6794
6298
|
allPatterns.push("low-confidence");
|
|
6795
6299
|
}
|
|
6796
|
-
const id =
|
|
6300
|
+
const id = fnv1a7(winnerType + ":" + content.slice(0, 100) + ":" + now.toString());
|
|
6797
6301
|
const classification = {
|
|
6798
6302
|
id,
|
|
6799
6303
|
type: winnerType,
|
|
@@ -6977,12 +6481,13 @@ var PanchaVritti = class {
|
|
|
6977
6481
|
async function recall(query, options) {
|
|
6978
6482
|
const limit = options?.limit ?? 5;
|
|
6979
6483
|
const answers = [];
|
|
6980
|
-
const [hybridResults, turnFallbackResults, memoryResults, dayFileResults] = await Promise.allSettled([
|
|
6484
|
+
const [hybridResults, turnFallbackResults, memoryResults, dayFileResults, akashaResults] = await Promise.allSettled([
|
|
6981
6485
|
searchHybrid(query, options?.project, limit),
|
|
6982
6486
|
// FTS5 fallback runs in parallel — used only if hybrid fails
|
|
6983
6487
|
searchTurns(query, options?.project),
|
|
6984
6488
|
options?.includeMemory !== false ? searchMemoryLayer(query) : Promise.resolve([]),
|
|
6985
|
-
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([])
|
|
6986
6491
|
]);
|
|
6987
6492
|
let usedHybrid = false;
|
|
6988
6493
|
if (hybridResults.status === "fulfilled" && hybridResults.value.length > 0) {
|
|
@@ -7015,22 +6520,27 @@ async function recall(query, options) {
|
|
|
7015
6520
|
answers.push(result);
|
|
7016
6521
|
}
|
|
7017
6522
|
}
|
|
6523
|
+
if (akashaResults.status === "fulfilled") {
|
|
6524
|
+
for (const result of akashaResults.value.slice(0, limit)) {
|
|
6525
|
+
answers.push(result);
|
|
6526
|
+
}
|
|
6527
|
+
}
|
|
7018
6528
|
const ranked = deduplicateAnswers(answers);
|
|
7019
6529
|
ranked.sort((a, b) => b.score - a.score);
|
|
7020
6530
|
return ranked.slice(0, limit);
|
|
7021
6531
|
}
|
|
7022
6532
|
async function searchHybrid(query, project, limit) {
|
|
7023
6533
|
try {
|
|
7024
|
-
const { HybridSearchEngine: HybridSearchEngine2 } = await import("./hybrid-search-
|
|
6534
|
+
const { HybridSearchEngine: HybridSearchEngine2 } = await import("./hybrid-search-OD756RDV.js");
|
|
7025
6535
|
let recallEngine = null;
|
|
7026
6536
|
let graphEngine = null;
|
|
7027
6537
|
try {
|
|
7028
|
-
const { RecallEngine: RecallEngine2 } = await import("./recall-
|
|
6538
|
+
const { RecallEngine: RecallEngine2 } = await import("./recall-64RROTUC.js");
|
|
7029
6539
|
recallEngine = new RecallEngine2();
|
|
7030
6540
|
} catch {
|
|
7031
6541
|
}
|
|
7032
6542
|
try {
|
|
7033
|
-
const { GraphRAGEngine: GraphRAGEngine2 } = await import("./graphrag-
|
|
6543
|
+
const { GraphRAGEngine: GraphRAGEngine2 } = await import("./graphrag-73XA7LBX.js");
|
|
7034
6544
|
graphEngine = new GraphRAGEngine2();
|
|
7035
6545
|
} catch {
|
|
7036
6546
|
}
|
|
@@ -7066,8 +6576,8 @@ async function searchHybrid(query, project, limit) {
|
|
|
7066
6576
|
}
|
|
7067
6577
|
async function searchTurns(query, project) {
|
|
7068
6578
|
try {
|
|
7069
|
-
const { searchSessions: searchSessions2 } = await import("./search-
|
|
7070
|
-
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");
|
|
7071
6581
|
const metas = searchSessions2(query, project);
|
|
7072
6582
|
const results = [];
|
|
7073
6583
|
for (const meta of metas.slice(0, 10)) {
|
|
@@ -7114,9 +6624,9 @@ async function searchTurns(query, project) {
|
|
|
7114
6624
|
}
|
|
7115
6625
|
async function searchMemoryLayer(query) {
|
|
7116
6626
|
try {
|
|
7117
|
-
const { searchMemory: searchMemory2 } = await import("./search-
|
|
6627
|
+
const { searchMemory: searchMemory2 } = await import("./search-JVCDNTAJ.js");
|
|
7118
6628
|
const results = searchMemory2(query);
|
|
7119
|
-
return results.slice(0, 5).map((r) => ({
|
|
6629
|
+
return results.slice(0, 5).filter((r) => !isLowValueMemoryEntry(r.content)).map((r) => ({
|
|
7120
6630
|
score: Math.min((r.relevance ?? 0.5) + 0.1, 1),
|
|
7121
6631
|
answer: `From memory: ${r.content.slice(0, 300)}`,
|
|
7122
6632
|
primarySource: "memory",
|
|
@@ -7126,9 +6636,20 @@ async function searchMemoryLayer(query) {
|
|
|
7126
6636
|
return [];
|
|
7127
6637
|
}
|
|
7128
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
|
+
}
|
|
7129
6650
|
async function searchDayFileLayer(query, limit) {
|
|
7130
6651
|
try {
|
|
7131
|
-
const { hierarchicalTemporalSearch: hierarchicalTemporalSearch2 } = await import("./hierarchical-temporal-search-
|
|
6652
|
+
const { hierarchicalTemporalSearch: hierarchicalTemporalSearch2 } = await import("./hierarchical-temporal-search-GHKVKNZ6.js");
|
|
7132
6653
|
const results = await hierarchicalTemporalSearch2(query, { limit });
|
|
7133
6654
|
if (results.length > 0) {
|
|
7134
6655
|
return results.map((r) => ({
|
|
@@ -7143,7 +6664,7 @@ async function searchDayFileLayer(query, limit) {
|
|
|
7143
6664
|
} catch {
|
|
7144
6665
|
}
|
|
7145
6666
|
try {
|
|
7146
|
-
const { searchDayFiles: searchDayFiles2 } = await import("./day-consolidation-
|
|
6667
|
+
const { searchDayFiles: searchDayFiles2 } = await import("./day-consolidation-CR3TJFAL.js");
|
|
7147
6668
|
const results = searchDayFiles2(query, { limit });
|
|
7148
6669
|
return results.map((r) => ({
|
|
7149
6670
|
score: 0.5,
|
|
@@ -7156,6 +6677,38 @@ async function searchDayFileLayer(query, limit) {
|
|
|
7156
6677
|
return [];
|
|
7157
6678
|
}
|
|
7158
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
|
+
}
|
|
7159
6712
|
function deduplicateAnswers(answers) {
|
|
7160
6713
|
const seen = /* @__PURE__ */ new Set();
|
|
7161
6714
|
return answers.filter((a) => {
|
|
@@ -7175,7 +6728,7 @@ async function loadProviderContext(project, options) {
|
|
|
7175
6728
|
let projectMemory = "";
|
|
7176
6729
|
let recentContext = "";
|
|
7177
6730
|
try {
|
|
7178
|
-
const { getMemory: getMemory2 } = await import("./memory-store-
|
|
6731
|
+
const { getMemory: getMemory2 } = await import("./memory-store-4GCBR2DZ.js");
|
|
7179
6732
|
globalFacts = getMemory2({ type: "global" });
|
|
7180
6733
|
if (globalFacts.length > maxLen / 3) {
|
|
7181
6734
|
globalFacts = globalFacts.slice(0, maxLen / 3) + "\n...(truncated)";
|
|
@@ -7184,7 +6737,7 @@ async function loadProviderContext(project, options) {
|
|
|
7184
6737
|
}
|
|
7185
6738
|
if (project) {
|
|
7186
6739
|
try {
|
|
7187
|
-
const { getMemory: getMemory2 } = await import("./memory-store-
|
|
6740
|
+
const { getMemory: getMemory2 } = await import("./memory-store-4GCBR2DZ.js");
|
|
7188
6741
|
projectMemory = getMemory2({ type: "project", path: project });
|
|
7189
6742
|
if (projectMemory.length > maxLen / 3) {
|
|
7190
6743
|
projectMemory = projectMemory.slice(0, maxLen / 3) + "\n...(truncated)";
|
|
@@ -7194,7 +6747,7 @@ async function loadProviderContext(project, options) {
|
|
|
7194
6747
|
}
|
|
7195
6748
|
let vasanaContext = "";
|
|
7196
6749
|
try {
|
|
7197
|
-
const { VasanaEngine: VasanaEngine2 } = await import("./vasana-engine-
|
|
6750
|
+
const { VasanaEngine: VasanaEngine2 } = await import("./vasana-engine-W4PYWT5H.js");
|
|
7198
6751
|
const engine = new VasanaEngine2();
|
|
7199
6752
|
const vasanas = engine.getVasanas(project ?? "__global__", 5);
|
|
7200
6753
|
if (vasanas.length > 0) {
|
|
@@ -7203,7 +6756,7 @@ async function loadProviderContext(project, options) {
|
|
|
7203
6756
|
} catch {
|
|
7204
6757
|
}
|
|
7205
6758
|
try {
|
|
7206
|
-
const { listSessions: listSessions2, loadSession: loadSession2 } = await import("./session-store-
|
|
6759
|
+
const { listSessions: listSessions2, loadSession: loadSession2 } = await import("./session-store-3EDQZEDS.js");
|
|
7207
6760
|
const sessions = project ? listSessions2(project).slice(0, recentLimit) : listSessions2().slice(0, recentLimit);
|
|
7208
6761
|
const summaries = [];
|
|
7209
6762
|
for (const meta of sessions) {
|
|
@@ -7251,6 +6804,595 @@ async function loadProviderContext(project, options) {
|
|
|
7251
6804
|
};
|
|
7252
6805
|
}
|
|
7253
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
|
+
|
|
7254
7396
|
export {
|
|
7255
7397
|
exportSessionToJson,
|
|
7256
7398
|
exportSessionToMarkdown,
|
|
@@ -7286,13 +7428,14 @@ export {
|
|
|
7286
7428
|
IdentityContext,
|
|
7287
7429
|
SvapnaConsolidation,
|
|
7288
7430
|
VidhiEngine,
|
|
7289
|
-
AkashaField,
|
|
7290
7431
|
TEMPORAL_SCALES,
|
|
7291
7432
|
KalaChakra,
|
|
7292
7433
|
VRITTI_TYPES,
|
|
7293
7434
|
VRITTI_CONFIDENCE_WEIGHTS,
|
|
7294
7435
|
PanchaVritti,
|
|
7295
7436
|
recall,
|
|
7296
|
-
loadProviderContext
|
|
7437
|
+
loadProviderContext,
|
|
7438
|
+
CritiqueStore,
|
|
7439
|
+
OrchestratorCheckpoint
|
|
7297
7440
|
};
|
|
7298
|
-
//# sourceMappingURL=chunk-
|
|
7441
|
+
//# sourceMappingURL=chunk-TSOQ2CT3.js.map
|