@yugenlab/vaayu 0.1.8 → 0.1.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (29) hide show
  1. package/README.md +1 -1
  2. package/chunks/{chunk-7UOXFHEB.js → chunk-77725AR7.js} +416 -397
  3. package/chunks/{chunk-YSC77CKZ.js → chunk-AGK3A7R7.js} +2844 -3208
  4. package/chunks/{chunk-DOQMEQ5S.js → chunk-AS3DJFY3.js} +5 -5
  5. package/chunks/{chunk-NHRBVSN3.js → chunk-HIYHTWFW.js} +44 -9
  6. package/chunks/{chunk-IGBRBFXX.js → chunk-JGI4SDWS.js} +2 -2
  7. package/chunks/{chunk-D3RVJGO7.js → chunk-M7THR63C.js} +48 -74
  8. package/chunks/{chunk-OBYBBGHA.js → chunk-N22M7D4P.js} +118 -106
  9. package/chunks/{chunk-PJEYJQ2C.js → chunk-O4KV7TFP.js} +2 -2
  10. package/chunks/{chunk-S2HDNNC7.js → chunk-OT4G2L46.js} +552 -641
  11. package/chunks/chunk-TND3MU4Z.js +426 -0
  12. package/chunks/{chunk-LVE2EOOH.js → chunk-VJHNE47S.js} +84 -75
  13. package/chunks/{consolidation-indexer-CD6DS2HO.js → consolidation-indexer-VKQ6DNU3.js} +4 -4
  14. package/chunks/{day-consolidation-U3X6P4ZG.js → day-consolidation-BH3QU2SZ.js} +6 -2
  15. package/chunks/{graphrag-LAZSXLLI.js → graphrag-D7OXWAWD.js} +2 -2
  16. package/chunks/{hierarchical-temporal-search-ETXYYJZK.js → hierarchical-temporal-search-PVHVA3NZ.js} +2 -2
  17. package/chunks/{hybrid-search-TX6T3KYH.js → hybrid-search-G2NAJKJ7.js} +4 -4
  18. package/chunks/{periodic-consolidation-4MACZE6S.js → periodic-consolidation-LMYMNS4Q.js} +2 -2
  19. package/chunks/{recall-IUPQCBYP.js → recall-ZNL4DJ2L.js} +3 -3
  20. package/chunks/{search-HHSVHBXC.js → search-35JMSGUT.js} +3 -3
  21. package/chunks/{session-store-NDUDYAC7.js → session-store-3BRPGC6P.js} +2 -2
  22. package/chunks/{src-ZAKUL232.js → src-Y3TGMINC.js} +12 -12
  23. package/chunks/vasana-engine-MU25OQ23.js +30 -0
  24. package/gateway.js +492 -226
  25. package/package.json +1 -1
  26. package/vaayu-mark-npm.png +0 -0
  27. package/chunks/chunk-TEQKXGIK.js +0 -752
  28. package/chunks/vasana-engine-G6BPOFX7.js +0 -10
  29. package/vaayu-mark.png +0 -0
@@ -0,0 +1,426 @@
1
+ import {
2
+ DatabaseManager
3
+ } from "./chunk-U62ABYKD.js";
4
+ import {
5
+ getChitraguptaHome
6
+ } from "./chunk-UZ6OIVEC.js";
7
+
8
+ // ../chitragupta/packages/smriti/src/periodic-consolidation.ts
9
+ import fs2 from "node:fs";
10
+ import path from "node:path";
11
+
12
+ // ../chitragupta/packages/smriti/src/periodic-monthly.ts
13
+ function esc(s) {
14
+ return s.replace(/\|/g, "\\|").replace(/\n/g, " ");
15
+ }
16
+ function truncate(s, max) {
17
+ return s.length <= max ? s : s.slice(0, max - 3) + "...";
18
+ }
19
+ function countJsonArray(json) {
20
+ if (!json) return 0;
21
+ try {
22
+ const arr = JSON.parse(json);
23
+ return Array.isArray(arr) ? arr.length : 0;
24
+ } catch {
25
+ return 0;
26
+ }
27
+ }
28
+ function generateRecommendations(stats, vasanas, vidhis, samskaras, tools) {
29
+ const recs = [];
30
+ if (stats.sessions > 0 && stats.cost > 0) {
31
+ const cps = stats.cost / stats.sessions;
32
+ if (cps > 1) recs.push(`Average cost per session is $${cps.toFixed(2)} \u2014 consider using lighter models for routine tasks.`);
33
+ }
34
+ if (stats.turns > 0 && stats.tokens > 0) {
35
+ const tpt = Math.round(stats.tokens / stats.turns);
36
+ if (tpt > 5e3) recs.push(`High token usage per turn (${tpt.toLocaleString()} avg) \u2014 review context window usage and compaction settings.`);
37
+ }
38
+ const negVas = vasanas.filter((v) => v.valence === "negative");
39
+ if (negVas.length > 0) recs.push(`${negVas.length} negative vasana(s) detected: ${negVas.map((v) => v.name).join(", ")}. Investigate root causes.`);
40
+ const weakVidhis = vidhis.filter((v) => v.success_rate < 0.5);
41
+ if (weakVidhis.length > 0) recs.push(`${weakVidhis.length} vidhi(s) with sub-50% success rate \u2014 consider refining or deprecating: ${weakVidhis.map((v) => v.name).join(", ")}.`);
42
+ const strongSam = samskaras.filter((s) => s.confidence > 0.8 && s.observation_count >= 5);
43
+ if (strongSam.length > 0) recs.push(`${strongSam.length} high-confidence samskara(s) may be ready for vasana crystallization.`);
44
+ if (tools.size > 0 && stats.sessions >= 5) {
45
+ if (tools.size / stats.sessions < 1.5) recs.push("Low tool diversity \u2014 explore additional tools to improve efficiency.");
46
+ }
47
+ if (recs.length === 0) recs.push("All metrics within healthy ranges. Keep up the momentum.");
48
+ return recs;
49
+ }
50
+ function buildMonthlyMarkdown(project, period, stats, vasanas, vidhis, samskaras, tools, newNodes, newEdges, recommendations) {
51
+ const lines = [];
52
+ lines.push(`# Monthly Consolidation \u2014 ${project} \u2014 ${period}`, `> Generated: ${(/* @__PURE__ */ new Date()).toISOString()}`, "");
53
+ lines.push("## Summary");
54
+ lines.push(`- **Sessions**: ${stats.sessions}`, `- **Turns**: ${stats.turns}`);
55
+ lines.push(`- **Tools Used**: ${tools.size > 0 ? [...tools].sort().join(", ") : "none"}`);
56
+ lines.push(`- **Total Tokens**: ${stats.tokens.toLocaleString()}`, `- **Estimated Cost**: $${stats.cost.toFixed(4)}`, "");
57
+ lines.push("## Vasanas Crystallized");
58
+ if (vasanas.length === 0) {
59
+ lines.push("_No vasanas crystallized this month._");
60
+ } else {
61
+ lines.push("| Tendency | Strength | Valence | Stability |", "|----------|----------|---------|-----------|");
62
+ for (const v of vasanas) lines.push(`| ${esc(v.name)} | ${v.strength.toFixed(2)} | ${v.valence} | ${v.stability.toFixed(2)} |`);
63
+ }
64
+ lines.push("");
65
+ lines.push("## Vidhis Extracted");
66
+ if (vidhis.length === 0) {
67
+ lines.push("_No vidhis extracted this month._");
68
+ } else {
69
+ lines.push("| Procedure | Steps | Success Rate | Sessions |", "|-----------|-------|--------------|----------|");
70
+ for (const v of vidhis) lines.push(`| ${esc(v.name)} | ${countJsonArray(v.steps)} | ${v.success_rate.toFixed(2)} | ${countJsonArray(v.learned_from)} |`);
71
+ }
72
+ lines.push("");
73
+ lines.push("## Top Samskaras");
74
+ if (samskaras.length === 0) {
75
+ lines.push("_No active samskaras this month._");
76
+ } else {
77
+ lines.push("| Pattern | Type | Confidence | Observations |", "|---------|------|------------|--------------|");
78
+ for (const s of samskaras) lines.push(`| ${esc(truncate(s.pattern_content, 60))} | ${s.pattern_type} | ${s.confidence.toFixed(2)} | ${s.observation_count} |`);
79
+ }
80
+ lines.push("");
81
+ lines.push("## Knowledge Graph Growth", `- New nodes: ${newNodes}`, `- New edges: ${newEdges}`, "");
82
+ lines.push("## Recommendations");
83
+ for (const rec of recommendations) lines.push(`- ${rec}`);
84
+ lines.push("");
85
+ return lines.join("\n");
86
+ }
87
+ async function buildMonthlyReport(project, home, baseDir, year, month, writeReport, indexIntoFts, logConsolidation, getReportPath) {
88
+ const t0 = Date.now();
89
+ const period = `${year}-${String(month).padStart(2, "0")}`;
90
+ const start = new Date(Date.UTC(year, month - 1, 1));
91
+ const end = new Date(Date.UTC(year, month, 1));
92
+ const startMs = start.getTime();
93
+ const endMs = end.getTime();
94
+ const dbm = DatabaseManager.instance(home);
95
+ const agentDb = dbm.get("agent");
96
+ const graphDb = dbm.get("graph");
97
+ const sessions = agentDb.prepare(`SELECT id, title, turn_count, cost, tokens, created_at FROM sessions WHERE project = ? AND created_at >= ? AND created_at < ? ORDER BY created_at ASC`).all(project, startMs, endMs);
98
+ const sessionIds = sessions.map((s) => s.id);
99
+ const totalTurns = sessions.reduce((sum, s) => sum + s.turn_count, 0);
100
+ const totalTokens = sessions.reduce((sum, s) => sum + (s.tokens ?? 0), 0);
101
+ const totalCost = sessions.reduce((sum, s) => sum + (s.cost ?? 0), 0);
102
+ const toolSet = /* @__PURE__ */ new Set();
103
+ if (sessionIds.length > 0) {
104
+ const ph = sessionIds.map(() => "?").join(",");
105
+ const turns = agentDb.prepare(`SELECT tool_calls FROM turns WHERE session_id IN (${ph}) AND tool_calls IS NOT NULL`).all(...sessionIds);
106
+ for (const turn of turns) {
107
+ if (!turn.tool_calls) continue;
108
+ try {
109
+ for (const c of JSON.parse(turn.tool_calls)) {
110
+ if (c.name) toolSet.add(c.name);
111
+ }
112
+ } catch {
113
+ }
114
+ }
115
+ }
116
+ const vasanas = agentDb.prepare(`SELECT name, description, strength, valence, stability FROM vasanas WHERE (project = ? OR project IS NULL) AND created_at >= ? AND created_at < ? ORDER BY strength DESC`).all(project, startMs, endMs);
117
+ const vidhis = agentDb.prepare(`SELECT name, steps, success_rate, learned_from FROM vidhis WHERE project = ? AND created_at >= ? AND created_at < ? ORDER BY success_rate DESC`).all(project, startMs, endMs);
118
+ const samskaras = agentDb.prepare(`SELECT id, pattern_type, pattern_content, confidence, observation_count FROM samskaras WHERE (project = ? OR project IS NULL) AND updated_at >= ? AND updated_at < ? ORDER BY confidence DESC LIMIT 20`).all(project, startMs, endMs);
119
+ const newNodes = graphDb.prepare(`SELECT COUNT(*) AS cnt FROM nodes WHERE created_at >= ? AND created_at < ?`).get(startMs, endMs)?.cnt ?? 0;
120
+ const newEdges = graphDb.prepare(`SELECT COUNT(*) AS cnt FROM edges WHERE recorded_at >= ? AND recorded_at < ?`).get(startMs, endMs)?.cnt ?? 0;
121
+ const stats = { sessions: sessions.length, turns: totalTurns, tokens: totalTokens, cost: totalCost, vasanasCreated: vasanas.length, vidhisCreated: vidhis.length, samskarasActive: samskaras.length };
122
+ const recommendations = generateRecommendations(stats, vasanas, vidhis, samskaras, toolSet);
123
+ const markdown = buildMonthlyMarkdown(project, period, stats, vasanas, vidhis, samskaras, toolSet, newNodes, newEdges, recommendations);
124
+ const filePath = getReportPath("monthly", period);
125
+ writeReport(filePath, markdown);
126
+ try {
127
+ const { indexConsolidationSummary } = await import("./consolidation-indexer-VKQ6DNU3.js");
128
+ await indexConsolidationSummary("monthly", period, markdown, project);
129
+ } catch {
130
+ }
131
+ indexIntoFts(agentDb, markdown);
132
+ const durationMs = Date.now() - t0;
133
+ logConsolidation(agentDb, { project, cycleType: "monthly", cycleId: `monthly-${period}`, vasanasCreated: vasanas.length, vidhisCreated: vidhis.length, samskarasProcessed: samskaras.length, sessionsProcessed: sessions.length, status: "success", createdAt: Date.now() });
134
+ return { type: "monthly", period, project, filePath, markdown, stats, durationMs };
135
+ }
136
+
137
+ // ../chitragupta/packages/smriti/src/periodic-yearly.ts
138
+ import fs from "node:fs";
139
+ function esc2(s) {
140
+ return s.replace(/\|/g, "\\|").replace(/\n/g, " ");
141
+ }
142
+ function truncate2(s, max) {
143
+ return s.length <= max ? s : s.slice(0, max - 3) + "...";
144
+ }
145
+ function countJsonArray2(json) {
146
+ if (!json) return 0;
147
+ try {
148
+ const arr = JSON.parse(json);
149
+ return Array.isArray(arr) ? arr.length : 0;
150
+ } catch {
151
+ return 0;
152
+ }
153
+ }
154
+ function analyzeTrends(reports) {
155
+ const trends = [];
156
+ if (reports.length < 2) return trends;
157
+ const sessionCounts = reports.map((r) => r.stats.sessions);
158
+ const half = Math.floor(sessionCounts.length / 2);
159
+ const avgFirst = sessionCounts.slice(0, half).reduce((a, b) => a + b, 0) / (half || 1);
160
+ const avgSecond = sessionCounts.slice(half).reduce((a, b) => a + b, 0) / (sessionCounts.length - half || 1);
161
+ if (avgSecond > avgFirst * 1.3) trends.push("Session volume increased significantly in the second half of the year.");
162
+ else if (avgSecond < avgFirst * 0.7) trends.push("Session volume decreased notably in the second half of the year.");
163
+ const costs = reports.map((r) => r.stats.cost);
164
+ const costFirst = costs.slice(0, half).reduce((a, b) => a + b, 0);
165
+ const costSecond = costs.slice(half).reduce((a, b) => a + b, 0);
166
+ if (costSecond > 0 && costFirst > 0) {
167
+ if (costSecond < costFirst * 0.8) trends.push("Cost efficiency improved over the year \u2014 spending decreased while activity continued.");
168
+ else if (costSecond > costFirst * 1.5) trends.push("Spending increased substantially \u2014 review model selection and caching strategies.");
169
+ }
170
+ const totalVasanas = reports.reduce((s, r) => s + r.stats.vasanasCreated, 0);
171
+ const totalVidhis = reports.reduce((s, r) => s + r.stats.vidhisCreated, 0);
172
+ if (totalVasanas > 10) trends.push(`Strong behavioral crystallization: ${totalVasanas} vasanas formed across the year.`);
173
+ if (totalVidhis > 5) trends.push(`Active procedural learning: ${totalVidhis} vidhis extracted from repeated patterns.`);
174
+ if (trends.length === 0) trends.push("Steady, consistent usage throughout the year with no significant inflection points.");
175
+ return trends;
176
+ }
177
+ function buildYearlyMarkdown(project, period, stats, vasanas, vidhis, samskaras, yearNodes, yearEdges, monthlyReports, trends, prevYearStats) {
178
+ const lines = [];
179
+ lines.push(`# Yearly Consolidation \u2014 ${project} \u2014 ${period}`, `> Generated: ${(/* @__PURE__ */ new Date()).toISOString()}`, "");
180
+ lines.push("## Annual Summary");
181
+ lines.push(`- **Sessions**: ${stats.sessions}`, `- **Turns**: ${stats.turns}`);
182
+ lines.push(`- **Total Tokens**: ${stats.tokens.toLocaleString()}`, `- **Estimated Cost**: $${stats.cost.toFixed(4)}`);
183
+ lines.push(`- **Vasanas Crystallized**: ${stats.vasanasCreated}`, `- **Vidhis Extracted**: ${stats.vidhisCreated}`);
184
+ lines.push(`- **Samskaras Active**: ${stats.samskarasActive}`, "");
185
+ if (prevYearStats) {
186
+ lines.push("## Year-over-Year Comparison");
187
+ lines.push("| Metric | Previous Year | This Year | Change |", "|--------|---------------|-----------|--------|");
188
+ const yoy = (label, prev, curr) => {
189
+ const d = curr - prev;
190
+ const pct = prev > 0 ? (d / prev * 100).toFixed(1) : "N/A";
191
+ return `| ${label} | ${prev} | ${curr} | ${d >= 0 ? "+" : ""}${pct !== "N/A" ? pct + "%" : pct} |`;
192
+ };
193
+ lines.push(yoy("Sessions", prevYearStats.sessions, stats.sessions));
194
+ lines.push(yoy("Turns", prevYearStats.turns, stats.turns));
195
+ lines.push(yoy("Tokens", prevYearStats.tokens, stats.tokens));
196
+ lines.push(yoy("Vasanas", prevYearStats.vasanasCreated, stats.vasanasCreated));
197
+ lines.push(yoy("Vidhis", prevYearStats.vidhisCreated, stats.vidhisCreated));
198
+ lines.push("");
199
+ }
200
+ if (monthlyReports.length > 0) {
201
+ lines.push("## Monthly Breakdown");
202
+ lines.push("| Month | Sessions | Turns | Tokens | Cost |", "|-------|----------|-------|--------|------|");
203
+ for (const r of monthlyReports) lines.push(`| ${r.period} | ${r.stats.sessions} | ${r.stats.turns} | ${r.stats.tokens.toLocaleString()} | $${r.stats.cost.toFixed(4)} |`);
204
+ lines.push("");
205
+ }
206
+ lines.push("## Trends");
207
+ for (const t of trends) lines.push(`- ${t}`);
208
+ lines.push("");
209
+ lines.push("## Top Vasanas of the Year");
210
+ if (vasanas.length === 0) {
211
+ lines.push("_No vasanas crystallized this year._");
212
+ } else {
213
+ lines.push("| Tendency | Strength | Valence | Stability |", "|----------|----------|---------|-----------|");
214
+ for (const v of vasanas.slice(0, 15)) lines.push(`| ${esc2(v.name)} | ${v.strength.toFixed(2)} | ${v.valence} | ${v.stability.toFixed(2)} |`);
215
+ }
216
+ lines.push("");
217
+ lines.push("## Top Vidhis of the Year");
218
+ if (vidhis.length === 0) {
219
+ lines.push("_No vidhis extracted this year._");
220
+ } else {
221
+ lines.push("| Procedure | Steps | Success Rate | Sessions |", "|-----------|-------|--------------|----------|");
222
+ for (const v of vidhis.slice(0, 15)) lines.push(`| ${esc2(v.name)} | ${countJsonArray2(v.steps)} | ${v.success_rate.toFixed(2)} | ${countJsonArray2(v.learned_from)} |`);
223
+ }
224
+ lines.push("");
225
+ lines.push("## Top Samskaras of the Year");
226
+ if (samskaras.length === 0) {
227
+ lines.push("_No active samskaras this year._");
228
+ } else {
229
+ lines.push("| Pattern | Type | Confidence | Observations |", "|---------|------|------------|--------------|");
230
+ for (const s of samskaras.slice(0, 20)) lines.push(`| ${esc2(truncate2(s.pattern_content, 60))} | ${s.pattern_type} | ${s.confidence.toFixed(2)} | ${s.observation_count} |`);
231
+ }
232
+ lines.push("");
233
+ lines.push("## Knowledge Graph Growth", `- New nodes: ${yearNodes}`, `- New edges: ${yearEdges}`, "");
234
+ lines.push("## Database Maintenance", "- VACUUM executed on agent.db, graph.db, vectors.db", "");
235
+ return lines.join("\n");
236
+ }
237
+ async function buildYearlyReport(project, home, baseDir, year, monthlyFn, extractStatsFromMarkdown, writeReport, indexIntoFts, logConsolidation, getReportPath) {
238
+ const t0 = Date.now();
239
+ const period = String(year);
240
+ const startMs = new Date(Date.UTC(year, 0, 1)).getTime();
241
+ const endMs = new Date(Date.UTC(year + 1, 0, 1)).getTime();
242
+ const dbm = DatabaseManager.instance(home);
243
+ const agentDb = dbm.get("agent");
244
+ const graphDb = dbm.get("graph");
245
+ const monthlyReports = [];
246
+ for (let m = 1; m <= 12; m++) {
247
+ const mp = `${year}-${String(m).padStart(2, "0")}`;
248
+ const mPath = getReportPath("monthly", mp);
249
+ if (!fs.existsSync(mPath)) {
250
+ const ms = new Date(Date.UTC(year, m - 1, 1)).getTime();
251
+ const me = new Date(Date.UTC(year, m, 1)).getTime();
252
+ if (me <= Date.now()) {
253
+ const cnt = agentDb.prepare(`SELECT COUNT(*) AS cnt FROM sessions WHERE project = ? AND created_at >= ? AND created_at < ?`).get(project, ms, me)?.cnt ?? 0;
254
+ if (cnt > 0) {
255
+ monthlyReports.push(await monthlyFn(year, m));
256
+ continue;
257
+ }
258
+ }
259
+ } else {
260
+ const content = fs.readFileSync(mPath, "utf-8");
261
+ monthlyReports.push({ type: "monthly", period: mp, project, filePath: mPath, markdown: content, stats: extractStatsFromMarkdown(content), durationMs: 0 });
262
+ }
263
+ }
264
+ const annualStats = { sessions: 0, turns: 0, tokens: 0, cost: 0, vasanasCreated: 0, vidhisCreated: 0, samskarasActive: 0 };
265
+ for (const r of monthlyReports) {
266
+ annualStats.sessions += r.stats.sessions;
267
+ annualStats.turns += r.stats.turns;
268
+ annualStats.tokens += r.stats.tokens;
269
+ annualStats.cost += r.stats.cost;
270
+ annualStats.vasanasCreated += r.stats.vasanasCreated;
271
+ annualStats.vidhisCreated += r.stats.vidhisCreated;
272
+ annualStats.samskarasActive += r.stats.samskarasActive;
273
+ }
274
+ const allVasanas = agentDb.prepare(`SELECT name, description, strength, valence, stability FROM vasanas WHERE (project = ? OR project IS NULL) AND created_at >= ? AND created_at < ? ORDER BY strength DESC`).all(project, startMs, endMs);
275
+ const allVidhis = agentDb.prepare(`SELECT name, steps, success_rate, learned_from FROM vidhis WHERE project = ? AND created_at >= ? AND created_at < ? ORDER BY success_rate DESC`).all(project, startMs, endMs);
276
+ const allSamskaras = agentDb.prepare(`SELECT id, pattern_type, pattern_content, confidence, observation_count FROM samskaras WHERE (project = ? OR project IS NULL) AND updated_at >= ? AND updated_at < ? ORDER BY confidence DESC LIMIT 30`).all(project, startMs, endMs);
277
+ const yearNodes = graphDb.prepare(`SELECT COUNT(*) AS cnt FROM nodes WHERE created_at >= ? AND created_at < ?`).get(startMs, endMs)?.cnt ?? 0;
278
+ const yearEdges = graphDb.prepare(`SELECT COUNT(*) AS cnt FROM edges WHERE recorded_at >= ? AND recorded_at < ?`).get(startMs, endMs)?.cnt ?? 0;
279
+ let prevYearStats = null;
280
+ const prevPath = getReportPath("yearly", String(year - 1));
281
+ if (fs.existsSync(prevPath)) prevYearStats = extractStatsFromMarkdown(fs.readFileSync(prevPath, "utf-8"));
282
+ const trends = analyzeTrends(monthlyReports);
283
+ const markdown = buildYearlyMarkdown(project, period, annualStats, allVasanas, allVidhis, allSamskaras, yearNodes, yearEdges, monthlyReports, trends, prevYearStats);
284
+ const filePath = getReportPath("yearly", period);
285
+ writeReport(filePath, markdown);
286
+ try {
287
+ const { indexConsolidationSummary } = await import("./consolidation-indexer-VKQ6DNU3.js");
288
+ await indexConsolidationSummary("yearly", period, markdown, project);
289
+ } catch {
290
+ }
291
+ indexIntoFts(agentDb, markdown);
292
+ dbm.vacuum("agent");
293
+ dbm.vacuum("graph");
294
+ dbm.vacuum("vectors");
295
+ const durationMs = Date.now() - t0;
296
+ logConsolidation(agentDb, { project, cycleType: "yearly", cycleId: `yearly-${period}`, vasanasCreated: allVasanas.length, vidhisCreated: allVidhis.length, samskarasProcessed: allSamskaras.length, sessionsProcessed: annualStats.sessions, status: "success", createdAt: Date.now() });
297
+ return { type: "yearly", period, project, filePath, markdown, stats: annualStats, durationMs };
298
+ }
299
+
300
+ // ../chitragupta/packages/smriti/src/periodic-consolidation.ts
301
+ function projectHash(project) {
302
+ let h = 2166136261;
303
+ for (let i = 0; i < project.length; i++) {
304
+ h ^= project.charCodeAt(i);
305
+ h = h * 16777619 >>> 0;
306
+ }
307
+ return (h >>> 0).toString(16).slice(0, 4);
308
+ }
309
+ var PeriodicConsolidation = class {
310
+ _project;
311
+ _home;
312
+ _hash;
313
+ _baseDir;
314
+ constructor(config) {
315
+ this._project = config.project;
316
+ this._home = config.chitraguptaHome ?? getChitraguptaHome();
317
+ this._hash = projectHash(this._project);
318
+ this._baseDir = path.join(this._home, "consolidated", this._hash);
319
+ }
320
+ // ── Public API ────────────────────────────────────────────────────────
321
+ /** Run monthly consolidation for a specific calendar month. */
322
+ async monthly(year, month) {
323
+ return buildMonthlyReport(
324
+ this._project,
325
+ this._home,
326
+ this._baseDir,
327
+ year,
328
+ month,
329
+ this._writeReport.bind(this),
330
+ this._indexIntoFts.bind(this),
331
+ this._logConsolidation.bind(this),
332
+ this.getReportPath.bind(this)
333
+ );
334
+ }
335
+ /** Run yearly consolidation for a specific calendar year. */
336
+ async yearly(year) {
337
+ return buildYearlyReport(
338
+ this._project,
339
+ this._home,
340
+ this._baseDir,
341
+ year,
342
+ this.monthly.bind(this),
343
+ this._extractStatsFromMarkdown.bind(this),
344
+ this._writeReport.bind(this),
345
+ this._indexIntoFts.bind(this),
346
+ this._logConsolidation.bind(this),
347
+ this.getReportPath.bind(this)
348
+ );
349
+ }
350
+ /** Check whether a monthly report exists on disk. */
351
+ hasMonthlyReport(year, month) {
352
+ const period = `${year}-${String(month).padStart(2, "0")}`;
353
+ return fs2.existsSync(this.getReportPath("monthly", period));
354
+ }
355
+ /** Check whether a yearly report exists on disk. */
356
+ hasYearlyReport(year) {
357
+ return fs2.existsSync(this.getReportPath("yearly", String(year)));
358
+ }
359
+ /** Get the absolute file path for a report. */
360
+ getReportPath(type, period) {
361
+ return path.join(this._baseDir, type, `${period}.md`);
362
+ }
363
+ /** List all existing reports for this project. */
364
+ listReports() {
365
+ const reports = [];
366
+ for (const type of ["monthly", "yearly"]) {
367
+ const dir = path.join(this._baseDir, type);
368
+ if (!fs2.existsSync(dir)) continue;
369
+ const files = fs2.readdirSync(dir).filter((f) => f.endsWith(".md")).sort();
370
+ for (const file of files) {
371
+ reports.push({ type, period: file.replace(/\.md$/, ""), path: path.join(dir, file) });
372
+ }
373
+ }
374
+ return reports;
375
+ }
376
+ // ── Private Helpers ───────────────────────────────────────────────────
377
+ /** Write a Markdown report to disk, creating parent dirs as needed. */
378
+ _writeReport(filePath, content) {
379
+ fs2.mkdirSync(path.dirname(filePath), { recursive: true });
380
+ fs2.writeFileSync(filePath, content, "utf-8");
381
+ fs2.chmodSync(filePath, 384);
382
+ }
383
+ /** Index report text into FTS5 for full-text search. */
384
+ _indexIntoFts(agentDb, content) {
385
+ try {
386
+ agentDb.prepare("INSERT INTO turns_fts(content) VALUES (?)").run(content);
387
+ } catch {
388
+ }
389
+ }
390
+ /** Log a consolidation run to the consolidation_log table. */
391
+ _logConsolidation(agentDb, entry) {
392
+ try {
393
+ agentDb.prepare(
394
+ `INSERT INTO consolidation_log (project, cycle_type, cycle_id, vasanas_created, vidhis_created, samskaras_processed, sessions_processed, status, created_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`
395
+ ).run(entry.project, entry.cycleType, entry.cycleId, entry.vasanasCreated, entry.vidhisCreated, entry.samskarasProcessed, entry.sessionsProcessed, entry.status, entry.createdAt);
396
+ } catch {
397
+ }
398
+ }
399
+ /** Extract stats from a previously generated Markdown report. */
400
+ _extractStatsFromMarkdown(md) {
401
+ const stats = { sessions: 0, turns: 0, tokens: 0, cost: 0, vasanasCreated: 0, vidhisCreated: 0, samskarasActive: 0 };
402
+ const num = (pattern) => {
403
+ const match = md.match(pattern);
404
+ return match ? parseFloat(match[1].replace(/,/g, "")) || 0 : 0;
405
+ };
406
+ stats.sessions = num(/\*\*Sessions\*\*:\s*([\d,]+)/);
407
+ stats.turns = num(/\*\*Turns\*\*:\s*([\d,]+)/);
408
+ stats.tokens = num(/\*\*Total Tokens\*\*:\s*([\d,]+)/);
409
+ stats.cost = num(/\*\*Estimated Cost\*\*:\s*\$?([\d,.]+)/);
410
+ const countTableRows = (sectionName) => {
411
+ const section = md.match(new RegExp(`## ${sectionName}\\n[\\s\\S]*?(?=\\n##|$)`));
412
+ if (!section) return 0;
413
+ const rows = (section[0].match(/^\|(?!\s*-)[^|]+\|/gm) || []).length - 1;
414
+ return rows < 0 ? 0 : rows;
415
+ };
416
+ stats.vasanasCreated = countTableRows("Vasanas Crystallized");
417
+ stats.vidhisCreated = countTableRows("Vidhis Extracted");
418
+ stats.samskarasActive = countTableRows("Top Samskaras");
419
+ return stats;
420
+ }
421
+ };
422
+
423
+ export {
424
+ PeriodicConsolidation
425
+ };
426
+ //# sourceMappingURL=chunk-TND3MU4Z.js.map
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  listSessions,
3
3
  loadSession
4
- } from "./chunk-NHRBVSN3.js";
4
+ } from "./chunk-HIYHTWFW.js";
5
5
  import {
6
6
  EmbeddingService,
7
7
  cosineSimilarity,
@@ -18,8 +18,7 @@ import {
18
18
  } from "./chunk-UZ6OIVEC.js";
19
19
 
20
20
  // ../chitragupta/packages/smriti/src/recall.ts
21
- import fs2 from "fs";
22
- import path2 from "path";
21
+ import fs3 from "fs";
23
22
 
24
23
  // ../chitragupta/packages/smriti/src/streams.ts
25
24
  import fs from "fs";
@@ -368,7 +367,9 @@ function resetOllamaAvailability() {
368
367
  _embeddingService.resetAvailability();
369
368
  }
370
369
 
371
- // ../chitragupta/packages/smriti/src/recall.ts
370
+ // ../chitragupta/packages/smriti/src/recall-storage.ts
371
+ import fs2 from "fs";
372
+ import path2 from "path";
372
373
  var DEFAULT_TOP_K = 10;
373
374
  var DEFAULT_THRESHOLD = 0.3;
374
375
  function getIndexDir() {
@@ -389,6 +390,72 @@ function blobToVector(blob) {
389
390
  );
390
391
  return Array.from(float32);
391
392
  }
393
+ function migrateEmbeddingsJson() {
394
+ const jsonPath = getEmbeddingsPath();
395
+ if (!fs2.existsSync(jsonPath)) {
396
+ return { migrated: 0, skipped: 0 };
397
+ }
398
+ let entries;
399
+ try {
400
+ const raw = fs2.readFileSync(jsonPath, "utf-8");
401
+ entries = JSON.parse(raw);
402
+ } catch {
403
+ return { migrated: 0, skipped: 0 };
404
+ }
405
+ if (!entries || entries.length === 0) {
406
+ return { migrated: 0, skipped: 0 };
407
+ }
408
+ let migrated = 0;
409
+ let skipped = 0;
410
+ try {
411
+ const dbm = DatabaseManager.instance();
412
+ initVectorsSchema(dbm);
413
+ const db = dbm.get("vectors");
414
+ const txn = db.transaction(() => {
415
+ const insert = db.prepare(`
416
+ INSERT OR IGNORE INTO embeddings (id, vector, text, source_type, source_id, dimensions, metadata, created_at)
417
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?)
418
+ `);
419
+ for (const entry of entries) {
420
+ try {
421
+ const result = insert.run(
422
+ entry.id,
423
+ vectorToBlob(entry.vector),
424
+ entry.text,
425
+ entry.source,
426
+ entry.sourceId,
427
+ entry.vector.length,
428
+ JSON.stringify({
429
+ title: entry.title,
430
+ summary: entry.summary,
431
+ tags: entry.tags,
432
+ date: entry.date,
433
+ deviceId: entry.deviceId
434
+ }),
435
+ new Date(entry.date).getTime()
436
+ );
437
+ if (result.changes > 0) {
438
+ migrated++;
439
+ } else {
440
+ skipped++;
441
+ }
442
+ } catch {
443
+ skipped++;
444
+ }
445
+ }
446
+ });
447
+ txn();
448
+ try {
449
+ fs2.renameSync(jsonPath, jsonPath + ".bak");
450
+ } catch {
451
+ }
452
+ } catch {
453
+ return { migrated: 0, skipped: entries.length };
454
+ }
455
+ return { migrated, skipped };
456
+ }
457
+
458
+ // ../chitragupta/packages/smriti/src/recall.ts
392
459
  var _dbInitialized = false;
393
460
  function _resetRecallDbInit() {
394
461
  _dbInitialized = false;
@@ -480,8 +547,8 @@ var RecallEngine = class {
480
547
  loadIndexJson() {
481
548
  try {
482
549
  const indexPath = getEmbeddingsPath();
483
- if (fs2.existsSync(indexPath)) {
484
- const raw = fs2.readFileSync(indexPath, "utf-8");
550
+ if (fs3.existsSync(indexPath)) {
551
+ const raw = fs3.readFileSync(indexPath, "utf-8");
485
552
  this.entries = JSON.parse(raw);
486
553
  }
487
554
  } catch {
@@ -491,8 +558,8 @@ var RecallEngine = class {
491
558
  saveIndexJson() {
492
559
  try {
493
560
  const dir = getIndexDir();
494
- fs2.mkdirSync(dir, { recursive: true });
495
- fs2.writeFileSync(
561
+ fs3.mkdirSync(dir, { recursive: true });
562
+ fs3.writeFileSync(
496
563
  getEmbeddingsPath(),
497
564
  JSON.stringify(this.entries, null, " "),
498
565
  "utf-8"
@@ -501,6 +568,7 @@ var RecallEngine = class {
501
568
  }
502
569
  }
503
570
  // ─── Session Indexing ────────────────────────────────────────────
571
+ /** Index a session's turns into the embedding store. */
504
572
  async indexSession(session) {
505
573
  if (!this.loaded) this.loadIndex();
506
574
  this.entries = this.entries.filter(
@@ -534,6 +602,7 @@ var RecallEngine = class {
534
602
  }
535
603
  this.saveIndex();
536
604
  }
605
+ /** Index a memory stream into the embedding store. */
537
606
  async indexStream(streamType, content, deviceId) {
538
607
  if (!this.loaded) this.loadIndex();
539
608
  const sourceId = deviceId ? `stream-${streamType}-${deviceId}` : `stream-${streamType}`;
@@ -557,6 +626,7 @@ var RecallEngine = class {
557
626
  this.saveIndex();
558
627
  }
559
628
  // ─── Recall (Search) ─────────────────────────────────────────────
629
+ /** Search all indexed embeddings for the given query string. */
560
630
  async recall(query, options) {
561
631
  if (!this.loaded) this.loadIndex();
562
632
  if (this.entries.length === 0) return [];
@@ -600,6 +670,7 @@ var RecallEngine = class {
600
670
  return results;
601
671
  }
602
672
  // ─── Re-index ────────────────────────────────────────────────────
673
+ /** Re-index all sessions and streams from scratch. */
603
674
  async reindexAll() {
604
675
  this.entries = [];
605
676
  const allMetas = listSessions();
@@ -629,77 +700,15 @@ var RecallEngine = class {
629
700
  }
630
701
  this.saveIndex();
631
702
  }
703
+ /** Return the number of entries in the in-memory index. */
632
704
  getIndexSize() {
633
705
  return this.entries.length;
634
706
  }
707
+ /** Reset the embedding provider availability cache. */
635
708
  resetOllamaAvailability() {
636
709
  resetOllamaAvailability();
637
710
  }
638
711
  };
639
- function migrateEmbeddingsJson() {
640
- const jsonPath = getEmbeddingsPath();
641
- if (!fs2.existsSync(jsonPath)) {
642
- return { migrated: 0, skipped: 0 };
643
- }
644
- let entries;
645
- try {
646
- const raw = fs2.readFileSync(jsonPath, "utf-8");
647
- entries = JSON.parse(raw);
648
- } catch {
649
- return { migrated: 0, skipped: 0 };
650
- }
651
- if (!entries || entries.length === 0) {
652
- return { migrated: 0, skipped: 0 };
653
- }
654
- let migrated = 0;
655
- let skipped = 0;
656
- try {
657
- const dbm = DatabaseManager.instance();
658
- initVectorsSchema(dbm);
659
- const db = dbm.get("vectors");
660
- const txn = db.transaction(() => {
661
- const insert = db.prepare(`
662
- INSERT OR IGNORE INTO embeddings (id, vector, text, source_type, source_id, dimensions, metadata, created_at)
663
- VALUES (?, ?, ?, ?, ?, ?, ?, ?)
664
- `);
665
- for (const entry of entries) {
666
- try {
667
- const result = insert.run(
668
- entry.id,
669
- vectorToBlob(entry.vector),
670
- entry.text,
671
- entry.source,
672
- entry.sourceId,
673
- entry.vector.length,
674
- JSON.stringify({
675
- title: entry.title,
676
- summary: entry.summary,
677
- tags: entry.tags,
678
- date: entry.date,
679
- deviceId: entry.deviceId
680
- }),
681
- new Date(entry.date).getTime()
682
- );
683
- if (result.changes > 0) {
684
- migrated++;
685
- } else {
686
- skipped++;
687
- }
688
- } catch {
689
- skipped++;
690
- }
691
- }
692
- });
693
- txn();
694
- try {
695
- fs2.renameSync(jsonPath, jsonPath + ".bak");
696
- } catch {
697
- }
698
- } catch {
699
- return { migrated: 0, skipped: entries.length };
700
- }
701
- return { migrated, skipped };
702
- }
703
712
 
704
713
  export {
705
714
  STREAM_CONFIGS,
@@ -709,8 +718,8 @@ export {
709
718
  configureRecallScoring,
710
719
  vectorToBlob,
711
720
  blobToVector,
721
+ migrateEmbeddingsJson,
712
722
  _resetRecallDbInit,
713
- RecallEngine,
714
- migrateEmbeddingsJson
723
+ RecallEngine
715
724
  };
716
- //# sourceMappingURL=chunk-LVE2EOOH.js.map
725
+ //# sourceMappingURL=chunk-VJHNE47S.js.map