@yugenlab/vaayu 0.1.9 → 0.1.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/chunks/{agentic-tool-loop-2FZK72JO.js → agentic-tool-loop-O3NUV7KG.js} +1 -1
- package/chunks/{chunk-UZ6OIVEC.js → chunk-2OBLQJYJ.js} +1 -1
- package/chunks/{chunk-PJEYJQ2C.js → chunk-3AYSJ7WB.js} +30 -18
- package/chunks/{chunk-U62ABYKD.js → chunk-67DXWEKG.js} +3 -3
- package/chunks/{chunk-6556EKOB.js → chunk-7AYYXHYZ.js} +25 -24
- package/chunks/{chunk-IGBRBFXX.js → chunk-7XV5ISV7.js} +7 -5
- package/chunks/{chunk-JAWZ7ANC.js → chunk-A3HOZBC5.js} +11 -7
- package/chunks/{chunk-LVE2EOOH.js → chunk-D46QTN3G.js} +126 -136
- package/chunks/{chunk-PRXQW76U.js → chunk-EG37M4QL.js} +17 -6
- package/chunks/{chunk-7UOXFHEB.js → chunk-F6RNEGFX.js} +480 -432
- package/chunks/{chunk-MJ74G5RB.js → chunk-G2QREGXK.js} +2 -2
- package/chunks/{chunk-DOQMEQ5S.js → chunk-JZTFJE7M.js} +39 -39
- package/chunks/{chunk-S2HDNNC7.js → chunk-LJUEMPLG.js} +638 -679
- package/chunks/{chunk-C76USAC5.js → chunk-QFGAB4XD.js} +13 -5
- package/chunks/{chunk-D3RVJGO7.js → chunk-QV4GPIPT.js} +118 -135
- package/chunks/{chunk-YJRXLRTE.js → chunk-V2ZIKDN4.js} +9 -8
- package/chunks/{chunk-YSC77CKZ.js → chunk-VCUJES75.js} +3276 -3526
- package/chunks/{chunk-OBYBBGHA.js → chunk-W4PVGBUH.js} +190 -189
- package/chunks/chunk-Z576WVLG.js +434 -0
- package/chunks/{chunk-NHRBVSN3.js → chunk-ZYY6N3SP.js} +117 -110
- package/chunks/{consolidation-indexer-CD6DS2HO.js → consolidation-indexer-VIWOP6VO.js} +8 -8
- package/chunks/{day-consolidation-U3X6P4ZG.js → day-consolidation-HMHSXIOM.js} +8 -4
- package/chunks/{src-ZAKUL232.js → dist-CY5NX2IK.js} +17 -17
- package/chunks/graphrag-T2QWNX57.js +14 -0
- package/chunks/{hierarchical-temporal-search-ETXYYJZK.js → hierarchical-temporal-search-U6DG74IR.js} +2 -2
- package/chunks/hybrid-search-BYTXCOXP.js +20 -0
- package/chunks/{memory-store-A6WOWLWC.js → memory-store-LEERUQGL.js} +3 -3
- package/chunks/periodic-consolidation-D6SSKZ7H.js +11 -0
- package/chunks/{postgres-WLH3D5HG.js → postgres-7GZDDX77.js} +2 -2
- package/chunks/{recall-IUPQCBYP.js → recall-LNRQVATQ.js} +7 -7
- package/chunks/search-BIODUW2P.js +19 -0
- package/chunks/{session-store-NDUDYAC7.js → session-store-O3TS7DUY.js} +5 -5
- package/chunks/{sqlite-DHUQGPR5.js → sqlite-7BC4DJTN.js} +2 -2
- package/chunks/vasana-engine-BJFHJVGM.js +30 -0
- package/gateway.js +31671 -24786
- package/package.json +1 -1
- package/pair-cli.js +1 -1
- package/chunks/chunk-TEQKXGIK.js +0 -752
- package/chunks/graphrag-LAZSXLLI.js +0 -14
- package/chunks/hybrid-search-TX6T3KYH.js +0 -20
- package/chunks/periodic-consolidation-4MACZE6S.js +0 -11
- package/chunks/search-HHSVHBXC.js +0 -19
- package/chunks/vasana-engine-G6BPOFX7.js +0 -10
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import {
|
|
2
2
|
DatabaseManager
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-67DXWEKG.js";
|
|
4
4
|
|
|
5
|
-
// ../chitragupta/packages/smriti/
|
|
5
|
+
// ../chitragupta/packages/smriti/dist/vasana-bocpd.js
|
|
6
6
|
var FNV_OFFSET = 2166136261;
|
|
7
7
|
var FNV_PRIME = 16777619;
|
|
8
8
|
function fnv1a(input) {
|
|
@@ -13,7 +13,7 @@ function fnv1a(input) {
|
|
|
13
13
|
}
|
|
14
14
|
return hash.toString(16).padStart(8, "0");
|
|
15
15
|
}
|
|
16
|
-
var
|
|
16
|
+
var DEFAULT_VASANA_CONFIG = {
|
|
17
17
|
lambda: 50,
|
|
18
18
|
changePointThreshold: 0.3,
|
|
19
19
|
stabilityWindow: 5,
|
|
@@ -35,11 +35,14 @@ var HARD_CEILINGS = {
|
|
|
35
35
|
stabilityWindow: 100
|
|
36
36
|
};
|
|
37
37
|
function logsumexp(xs) {
|
|
38
|
-
if (xs.length === 0)
|
|
38
|
+
if (xs.length === 0)
|
|
39
|
+
return -Infinity;
|
|
39
40
|
const m = Math.max(...xs);
|
|
40
|
-
if (m === -Infinity)
|
|
41
|
+
if (m === -Infinity)
|
|
42
|
+
return -Infinity;
|
|
41
43
|
let s = 0;
|
|
42
|
-
for (let i = 0; i < xs.length; i++)
|
|
44
|
+
for (let i = 0; i < xs.length; i++)
|
|
45
|
+
s += Math.exp(xs[i] - m);
|
|
43
46
|
return m + Math.log(s);
|
|
44
47
|
}
|
|
45
48
|
function lgamma(z) {
|
|
@@ -54,10 +57,12 @@ function lgamma(z) {
|
|
|
54
57
|
9984369578019572e-21,
|
|
55
58
|
15056327351493116e-23
|
|
56
59
|
];
|
|
57
|
-
if (z < 0.5)
|
|
60
|
+
if (z < 0.5)
|
|
61
|
+
return Math.log(Math.PI / Math.sin(Math.PI * z)) - lgamma(1 - z);
|
|
58
62
|
z -= 1;
|
|
59
63
|
let x = c[0];
|
|
60
|
-
for (let i = 1; i < 9; i++)
|
|
64
|
+
for (let i = 1; i < 9; i++)
|
|
65
|
+
x += c[i] / (z + i);
|
|
61
66
|
const t = z + 7.5;
|
|
62
67
|
return 0.5 * Math.log(2 * Math.PI) + (z + 0.5) * Math.log(t) - t + Math.log(x);
|
|
63
68
|
}
|
|
@@ -66,13 +71,106 @@ function logStudentT(x, nu, mu, sigma) {
|
|
|
66
71
|
const z = (x - mu) / safeSigma;
|
|
67
72
|
return lgamma((nu + 1) / 2) - lgamma(nu / 2) - 0.5 * Math.log(nu * Math.PI * safeSigma * safeSigma) - (nu + 1) / 2 * Math.log(1 + z * z / nu);
|
|
68
73
|
}
|
|
74
|
+
function initBOCPD(cfg) {
|
|
75
|
+
return {
|
|
76
|
+
logR: [0],
|
|
77
|
+
// P(r=0) = 1
|
|
78
|
+
stats: [{
|
|
79
|
+
mu: cfg.priorMu,
|
|
80
|
+
kappa: cfg.priorKappa,
|
|
81
|
+
alpha: cfg.priorAlpha,
|
|
82
|
+
beta: cfg.priorAlpha
|
|
83
|
+
}],
|
|
84
|
+
stableCount: 0,
|
|
85
|
+
totalObs: 0,
|
|
86
|
+
recentCpProbs: []
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
function updateBOCPD(st, x, cfg) {
|
|
90
|
+
const logH = -Math.log(cfg.lambda);
|
|
91
|
+
const log1H = Math.log(1 - 1 / cfg.lambda);
|
|
92
|
+
const n = st.logR.length;
|
|
93
|
+
const lpp = new Array(n);
|
|
94
|
+
for (let r = 0; r < n; r++) {
|
|
95
|
+
const s = st.stats[r];
|
|
96
|
+
lpp[r] = logStudentT(x, 2 * s.alpha, s.mu, Math.sqrt(s.beta * (s.kappa + 1) / (s.alpha * s.kappa)));
|
|
97
|
+
}
|
|
98
|
+
const cpTerms = new Array(n);
|
|
99
|
+
const newLR = new Array(n + 1);
|
|
100
|
+
for (let r = 0; r < n; r++) {
|
|
101
|
+
newLR[r + 1] = lpp[r] + st.logR[r] + log1H;
|
|
102
|
+
cpTerms[r] = lpp[r] + st.logR[r] + logH;
|
|
103
|
+
}
|
|
104
|
+
newLR[0] = logsumexp(cpTerms);
|
|
105
|
+
const logZ = logsumexp(newLR);
|
|
106
|
+
for (let i = 0; i <= n; i++)
|
|
107
|
+
newLR[i] -= logZ;
|
|
108
|
+
const newS = new Array(n + 1);
|
|
109
|
+
newS[0] = {
|
|
110
|
+
mu: cfg.priorMu,
|
|
111
|
+
kappa: cfg.priorKappa,
|
|
112
|
+
alpha: cfg.priorAlpha,
|
|
113
|
+
beta: cfg.priorAlpha
|
|
114
|
+
};
|
|
115
|
+
for (let r = 0; r < n; r++) {
|
|
116
|
+
const p = st.stats[r];
|
|
117
|
+
const k = p.kappa + 1;
|
|
118
|
+
const dx = x - p.mu;
|
|
119
|
+
newS[r + 1] = {
|
|
120
|
+
mu: (p.kappa * p.mu + x) / k,
|
|
121
|
+
kappa: k,
|
|
122
|
+
alpha: p.alpha + 0.5,
|
|
123
|
+
beta: p.beta + 0.5 * p.kappa * dx * dx / k
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
if (newLR.length > cfg.maxRunLength) {
|
|
127
|
+
const idx = newLR.map((lp, i) => ({ lp, i })).sort((a, b) => b.lp - a.lp);
|
|
128
|
+
const keep = new Set(idx.slice(0, cfg.maxRunLength).map((e) => e.i));
|
|
129
|
+
const pR = [], pS = [];
|
|
130
|
+
for (let i = 0; i <= n; i++)
|
|
131
|
+
if (keep.has(i)) {
|
|
132
|
+
pR.push(newLR[i]);
|
|
133
|
+
pS.push(newS[i]);
|
|
134
|
+
}
|
|
135
|
+
const norm = logsumexp(pR);
|
|
136
|
+
for (let i = 0; i < pR.length; i++)
|
|
137
|
+
pR[i] -= norm;
|
|
138
|
+
st.logR = pR;
|
|
139
|
+
st.stats = pS;
|
|
140
|
+
} else {
|
|
141
|
+
st.logR = newLR;
|
|
142
|
+
st.stats = newS;
|
|
143
|
+
}
|
|
144
|
+
st.totalObs++;
|
|
145
|
+
const cpProb = st.logR.length > 0 ? Math.exp(st.logR[0]) : 0;
|
|
146
|
+
if (!st.recentCpProbs)
|
|
147
|
+
st.recentCpProbs = [];
|
|
148
|
+
st.recentCpProbs.push(cpProb);
|
|
149
|
+
if (st.recentCpProbs.length > cfg.anomalyRevertWindow) {
|
|
150
|
+
st.recentCpProbs.shift();
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
function serializeBOCPD(states, obs) {
|
|
154
|
+
return {
|
|
155
|
+
features: Object.fromEntries(states),
|
|
156
|
+
observations: Object.fromEntries(obs)
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
function deserializeBOCPD(raw) {
|
|
160
|
+
return {
|
|
161
|
+
states: new Map(Object.entries(raw.features)),
|
|
162
|
+
obs: new Map(Object.entries(raw.observations).map(([k, v]) => [k, Array.isArray(v) ? v : []]))
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// ../chitragupta/packages/smriti/dist/vasana-engine.js
|
|
69
167
|
var VasanaEngine = class {
|
|
70
168
|
cfg;
|
|
71
169
|
states = /* @__PURE__ */ new Map();
|
|
72
170
|
obs = /* @__PURE__ */ new Map();
|
|
73
171
|
cache = /* @__PURE__ */ new Map();
|
|
74
172
|
constructor(config) {
|
|
75
|
-
const merged = { ...
|
|
173
|
+
const merged = { ...DEFAULT_VASANA_CONFIG, ...config };
|
|
76
174
|
for (const [k, ceil] of Object.entries(HARD_CEILINGS)) {
|
|
77
175
|
const key = k;
|
|
78
176
|
if (typeof merged[key] === "number" && typeof ceil === "number")
|
|
@@ -84,12 +182,14 @@ var VasanaEngine = class {
|
|
|
84
182
|
/** Observe a samskara: extract features and update BOCPD state per dimension. */
|
|
85
183
|
observe(samskara) {
|
|
86
184
|
for (const [feat, val] of this.extractFeatures(samskara)) {
|
|
87
|
-
if (!this.states.has(feat))
|
|
185
|
+
if (!this.states.has(feat))
|
|
186
|
+
this.states.set(feat, initBOCPD(this.cfg));
|
|
88
187
|
const buf = this.obs.get(feat) ?? [];
|
|
89
188
|
buf.push(val);
|
|
90
|
-
if (buf.length > this.cfg.windowSize)
|
|
189
|
+
if (buf.length > this.cfg.windowSize)
|
|
190
|
+
buf.splice(0, buf.length - this.cfg.windowSize);
|
|
91
191
|
this.obs.set(feat, buf);
|
|
92
|
-
this.
|
|
192
|
+
updateBOCPD(this.states.get(feat), val, this.cfg);
|
|
93
193
|
}
|
|
94
194
|
}
|
|
95
195
|
/** Run crystallization: stability check, holdout validation, vasana upsert. */
|
|
@@ -97,12 +197,10 @@ var VasanaEngine = class {
|
|
|
97
197
|
const now = Date.now();
|
|
98
198
|
const res = { created: [], reinforced: [], pending: [], changePoints: [], anomalies: [], timestamp: now };
|
|
99
199
|
const db = DatabaseManager.instance().get("agent");
|
|
100
|
-
const rows = db.prepare(
|
|
101
|
-
`SELECT id, session_id, pattern_type, pattern_content, observation_count,
|
|
200
|
+
const rows = db.prepare(`SELECT id, session_id, pattern_type, pattern_content, observation_count,
|
|
102
201
|
confidence, pramana_type, project, created_at, updated_at
|
|
103
202
|
FROM samskaras WHERE project = ? OR project IS NULL
|
|
104
|
-
ORDER BY updated_at DESC LIMIT ?`
|
|
105
|
-
).all(project, this.cfg.windowSize * 10);
|
|
203
|
+
ORDER BY updated_at DESC LIMIT ?`).all(project, this.cfg.windowSize * 10);
|
|
106
204
|
for (const [key, ids] of this.clusterSamskaras(rows)) {
|
|
107
205
|
const feat = `cluster:${key}`;
|
|
108
206
|
const st = this.states.get(feat);
|
|
@@ -174,7 +272,8 @@ var VasanaEngine = class {
|
|
|
174
272
|
/** Reinforce with diminishing returns: delta = 0.1 / (1 + ln(1 + count)). */
|
|
175
273
|
reinforce(vasanaId) {
|
|
176
274
|
const v = this.loadVasana(vasanaId);
|
|
177
|
-
if (!v)
|
|
275
|
+
if (!v)
|
|
276
|
+
return;
|
|
178
277
|
v.strength = Math.min(1, v.strength + 0.1 / (1 + Math.log(1 + v.reinforcementCount)));
|
|
179
278
|
v.reinforcementCount++;
|
|
180
279
|
v.lastActivated = v.updatedAt = Date.now();
|
|
@@ -183,19 +282,18 @@ var VasanaEngine = class {
|
|
|
183
282
|
/** Weaken by fixed decrement. */
|
|
184
283
|
weaken(vasanaId) {
|
|
185
284
|
const v = this.loadVasana(vasanaId);
|
|
186
|
-
if (!v)
|
|
285
|
+
if (!v)
|
|
286
|
+
return;
|
|
187
287
|
v.strength = Math.max(0, v.strength - 0.15);
|
|
188
288
|
v.updatedAt = Date.now();
|
|
189
289
|
this.saveVasana(v);
|
|
190
290
|
}
|
|
191
291
|
/** Get vasanas for a project (includes global), sorted by strength desc. */
|
|
192
292
|
getVasanas(project, topK = 20) {
|
|
193
|
-
const rows = DatabaseManager.instance().get("agent").prepare(
|
|
194
|
-
`SELECT id,name,description,valence,strength,stability,source_samskaras,
|
|
293
|
+
const rows = DatabaseManager.instance().get("agent").prepare(`SELECT id,name,description,valence,strength,stability,source_samskaras,
|
|
195
294
|
project,created_at,updated_at,last_activated,activation_count
|
|
196
295
|
FROM vasanas WHERE project=? OR project IS NULL OR project='__global__'
|
|
197
|
-
ORDER BY strength DESC LIMIT ?`
|
|
198
|
-
).all(project, topK);
|
|
296
|
+
ORDER BY strength DESC LIMIT ?`).all(project, topK);
|
|
199
297
|
return rows.map((r) => this.toVasana(r));
|
|
200
298
|
}
|
|
201
299
|
/** Promote project vasanas to global when found in >= promotionMinProjects. */
|
|
@@ -203,12 +301,10 @@ var VasanaEngine = class {
|
|
|
203
301
|
const now = Date.now();
|
|
204
302
|
const res = { promoted: [], projectSources: {}, timestamp: now };
|
|
205
303
|
const db = DatabaseManager.instance().get("agent");
|
|
206
|
-
const rows = db.prepare(
|
|
207
|
-
`SELECT id,name,description,valence,strength,stability,source_samskaras,
|
|
304
|
+
const rows = db.prepare(`SELECT id,name,description,valence,strength,stability,source_samskaras,
|
|
208
305
|
project,created_at,updated_at,last_activated,activation_count
|
|
209
306
|
FROM vasanas WHERE project IS NOT NULL AND project!='__global__' AND strength>=0.4
|
|
210
|
-
ORDER BY name`
|
|
211
|
-
).all();
|
|
307
|
+
ORDER BY name`).all();
|
|
212
308
|
const byName = /* @__PURE__ */ new Map();
|
|
213
309
|
for (const r of rows) {
|
|
214
310
|
const k = r.name.toLowerCase();
|
|
@@ -216,12 +312,16 @@ var VasanaEngine = class {
|
|
|
216
312
|
}
|
|
217
313
|
for (const [tendency, group] of byName) {
|
|
218
314
|
const projects = new Set(group.map((r) => r.project));
|
|
219
|
-
if (projects.size < this.cfg.promotionMinProjects)
|
|
220
|
-
|
|
315
|
+
if (projects.size < this.cfg.promotionMinProjects)
|
|
316
|
+
continue;
|
|
317
|
+
if (db.prepare(`SELECT 1 FROM vasanas WHERE name=? AND (project IS NULL OR project='__global__')`).get(tendency))
|
|
318
|
+
continue;
|
|
221
319
|
const allSrc = [];
|
|
222
|
-
for (const r of group)
|
|
320
|
+
for (const r of group)
|
|
321
|
+
allSrc.push(...jsonArr(r.source_samskaras));
|
|
223
322
|
const votes = { positive: 0, negative: 0, neutral: 0 };
|
|
224
|
-
for (const r of group)
|
|
323
|
+
for (const r of group)
|
|
324
|
+
votes[r.valence]++;
|
|
225
325
|
const valence = ["positive", "negative", "neutral"].reduce((a, b) => votes[a] >= votes[b] ? a : b);
|
|
226
326
|
const gv = {
|
|
227
327
|
id: fnv1a(tendency + ":__global__"),
|
|
@@ -253,39 +353,36 @@ var VasanaEngine = class {
|
|
|
253
353
|
let deleted = 0;
|
|
254
354
|
for (const r of rows) {
|
|
255
355
|
const elapsed = now - (r.last_activated ?? now);
|
|
256
|
-
if (elapsed <= 0)
|
|
356
|
+
if (elapsed <= 0)
|
|
357
|
+
continue;
|
|
257
358
|
const s = r.strength * Math.exp(-Math.LN2 * elapsed / hl);
|
|
258
359
|
if (s < 0.01) {
|
|
259
360
|
db.prepare(`DELETE FROM vasanas WHERE id=?`).run(r.id);
|
|
260
361
|
deleted++;
|
|
261
|
-
} else
|
|
362
|
+
} else
|
|
363
|
+
db.prepare(`UPDATE vasanas SET strength=?,updated_at=? WHERE id=?`).run(s, now, r.id);
|
|
262
364
|
}
|
|
263
365
|
return deleted;
|
|
264
366
|
}
|
|
265
367
|
/** Persist BOCPD state (run-length distributions + observations) to SQLite. */
|
|
266
368
|
persist() {
|
|
267
|
-
const json = JSON.stringify(
|
|
268
|
-
|
|
269
|
-
observations: Object.fromEntries(this.obs)
|
|
270
|
-
});
|
|
271
|
-
DatabaseManager.instance().get("agent").prepare(
|
|
272
|
-
`INSERT OR REPLACE INTO consolidation_rules
|
|
369
|
+
const json = JSON.stringify(serializeBOCPD(this.states, this.obs));
|
|
370
|
+
DatabaseManager.instance().get("agent").prepare(`INSERT OR REPLACE INTO consolidation_rules
|
|
273
371
|
(id, category, rule_text, confidence, source_sessions, created_at, updated_at, hit_count, project)
|
|
274
372
|
VALUES ((SELECT id FROM consolidation_rules WHERE category='bocpd_state' AND project='__vasana_engine__'),
|
|
275
|
-
'bocpd_state',?,1.0,NULL,?,?,1,'__vasana_engine__')`
|
|
276
|
-
).run(json, Date.now(), Date.now());
|
|
373
|
+
'bocpd_state',?,1.0,NULL,?,?,1,'__vasana_engine__')`).run(json, Date.now(), Date.now());
|
|
277
374
|
}
|
|
278
375
|
/** Restore BOCPD state from SQLite. No-op if nothing persisted. */
|
|
279
376
|
restore() {
|
|
280
|
-
const row = DatabaseManager.instance().get("agent").prepare(
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
if (!row) return;
|
|
377
|
+
const row = DatabaseManager.instance().get("agent").prepare(`SELECT rule_text FROM consolidation_rules
|
|
378
|
+
WHERE category='bocpd_state' AND project='__vasana_engine__' LIMIT 1`).get();
|
|
379
|
+
if (!row)
|
|
380
|
+
return;
|
|
285
381
|
try {
|
|
286
|
-
const
|
|
287
|
-
|
|
288
|
-
this.
|
|
382
|
+
const raw = JSON.parse(row.rule_text);
|
|
383
|
+
const { states, obs } = deserializeBOCPD(raw);
|
|
384
|
+
this.states = states;
|
|
385
|
+
this.obs = obs;
|
|
289
386
|
} catch (err) {
|
|
290
387
|
process.stderr.write(`[vasana-engine] restore() failed to parse BOCPD state: ${err instanceof Error ? err.message : err}
|
|
291
388
|
`);
|
|
@@ -293,103 +390,21 @@ var VasanaEngine = class {
|
|
|
293
390
|
this.obs.clear();
|
|
294
391
|
}
|
|
295
392
|
}
|
|
296
|
-
// ──
|
|
297
|
-
initState() {
|
|
298
|
-
return {
|
|
299
|
-
logR: [0],
|
|
300
|
-
// P(r=0) = 1
|
|
301
|
-
stats: [{
|
|
302
|
-
mu: this.cfg.priorMu,
|
|
303
|
-
kappa: this.cfg.priorKappa,
|
|
304
|
-
alpha: this.cfg.priorAlpha,
|
|
305
|
-
beta: this.cfg.priorAlpha
|
|
306
|
-
}],
|
|
307
|
-
stableCount: 0,
|
|
308
|
-
totalObs: 0,
|
|
309
|
-
recentCpProbs: []
|
|
310
|
-
};
|
|
311
|
-
}
|
|
312
|
-
/**
|
|
313
|
-
* Online BOCPD update for one observation on one feature dimension.
|
|
314
|
-
*
|
|
315
|
-
* 1. Predictive P(x_t | r) via Student-t with Normal-Gamma sufficient stats
|
|
316
|
-
* 2. Growth: P(r_t=r+1) = P(x|r) * P(r) * (1-H)
|
|
317
|
-
* 3. Change-point: P(r_t=0) = sum_r P(x|r) * P(r) * H
|
|
318
|
-
* 4. Normalize, update sufficient stats, prune low-probability tails
|
|
319
|
-
*/
|
|
320
|
-
updateBOCPD(feat, x) {
|
|
321
|
-
const st = this.states.get(feat);
|
|
322
|
-
const logH = -Math.log(this.cfg.lambda);
|
|
323
|
-
const log1H = Math.log(1 - 1 / this.cfg.lambda);
|
|
324
|
-
const n = st.logR.length;
|
|
325
|
-
const lpp = new Array(n);
|
|
326
|
-
for (let r = 0; r < n; r++) {
|
|
327
|
-
const s = st.stats[r];
|
|
328
|
-
lpp[r] = logStudentT(x, 2 * s.alpha, s.mu, Math.sqrt(s.beta * (s.kappa + 1) / (s.alpha * s.kappa)));
|
|
329
|
-
}
|
|
330
|
-
const cpTerms = new Array(n);
|
|
331
|
-
const newLR = new Array(n + 1);
|
|
332
|
-
for (let r = 0; r < n; r++) {
|
|
333
|
-
newLR[r + 1] = lpp[r] + st.logR[r] + log1H;
|
|
334
|
-
cpTerms[r] = lpp[r] + st.logR[r] + logH;
|
|
335
|
-
}
|
|
336
|
-
newLR[0] = logsumexp(cpTerms);
|
|
337
|
-
const logZ = logsumexp(newLR);
|
|
338
|
-
for (let i = 0; i <= n; i++) newLR[i] -= logZ;
|
|
339
|
-
const newS = new Array(n + 1);
|
|
340
|
-
newS[0] = {
|
|
341
|
-
mu: this.cfg.priorMu,
|
|
342
|
-
kappa: this.cfg.priorKappa,
|
|
343
|
-
alpha: this.cfg.priorAlpha,
|
|
344
|
-
beta: this.cfg.priorAlpha
|
|
345
|
-
};
|
|
346
|
-
for (let r = 0; r < n; r++) {
|
|
347
|
-
const p = st.stats[r];
|
|
348
|
-
const k = p.kappa + 1;
|
|
349
|
-
const dx = x - p.mu;
|
|
350
|
-
newS[r + 1] = {
|
|
351
|
-
mu: (p.kappa * p.mu + x) / k,
|
|
352
|
-
kappa: k,
|
|
353
|
-
alpha: p.alpha + 0.5,
|
|
354
|
-
beta: p.beta + 0.5 * p.kappa * dx * dx / k
|
|
355
|
-
};
|
|
356
|
-
}
|
|
357
|
-
if (newLR.length > this.cfg.maxRunLength) {
|
|
358
|
-
const idx = newLR.map((lp, i) => ({ lp, i })).sort((a, b) => b.lp - a.lp);
|
|
359
|
-
const keep = new Set(idx.slice(0, this.cfg.maxRunLength).map((e) => e.i));
|
|
360
|
-
const pR = [], pS = [];
|
|
361
|
-
for (let i = 0; i <= n; i++) if (keep.has(i)) {
|
|
362
|
-
pR.push(newLR[i]);
|
|
363
|
-
pS.push(newS[i]);
|
|
364
|
-
}
|
|
365
|
-
const norm = logsumexp(pR);
|
|
366
|
-
for (let i = 0; i < pR.length; i++) pR[i] -= norm;
|
|
367
|
-
st.logR = pR;
|
|
368
|
-
st.stats = pS;
|
|
369
|
-
} else {
|
|
370
|
-
st.logR = newLR;
|
|
371
|
-
st.stats = newS;
|
|
372
|
-
}
|
|
373
|
-
st.totalObs++;
|
|
374
|
-
const cpProb = st.logR.length > 0 ? Math.exp(st.logR[0]) : 0;
|
|
375
|
-
if (!st.recentCpProbs) st.recentCpProbs = [];
|
|
376
|
-
st.recentCpProbs.push(cpProb);
|
|
377
|
-
if (st.recentCpProbs.length > this.cfg.anomalyRevertWindow) {
|
|
378
|
-
st.recentCpProbs.shift();
|
|
379
|
-
}
|
|
380
|
-
}
|
|
393
|
+
// ── Deviation Classification ─────────────────────────────────────────
|
|
381
394
|
/**
|
|
382
395
|
* Classify a deviation as change-point, anomaly, or stable.
|
|
383
396
|
*
|
|
384
397
|
* Joint anomaly/change-point discrimination (arxiv 2508.06385):
|
|
385
|
-
* - If P(r=0) > threshold and persists across the revert window
|
|
386
|
-
* - If P(r=0) > threshold but reverts within the window
|
|
387
|
-
* - Otherwise
|
|
398
|
+
* - If P(r=0) > threshold and persists across the revert window -> change-point
|
|
399
|
+
* - If P(r=0) > threshold but reverts within the window -> anomaly (one-off)
|
|
400
|
+
* - Otherwise -> stable
|
|
388
401
|
*/
|
|
389
402
|
classifyDeviation(st) {
|
|
390
|
-
if (st.logR.length === 0)
|
|
403
|
+
if (st.logR.length === 0)
|
|
404
|
+
return "stable";
|
|
391
405
|
const cpProb = Math.exp(st.logR[0]);
|
|
392
|
-
if (cpProb <= this.cfg.changePointThreshold)
|
|
406
|
+
if (cpProb <= this.cfg.changePointThreshold)
|
|
407
|
+
return "stable";
|
|
393
408
|
const recent = st.recentCpProbs ?? [cpProb];
|
|
394
409
|
const exceedCount = recent.filter((p) => p > this.cfg.changePointThreshold).length;
|
|
395
410
|
const ratio = exceedCount / Math.max(1, recent.length);
|
|
@@ -398,11 +413,9 @@ var VasanaEngine = class {
|
|
|
398
413
|
}
|
|
399
414
|
return "anomaly";
|
|
400
415
|
}
|
|
401
|
-
isChangePoint(st) {
|
|
402
|
-
return this.classifyDeviation(st) === "change-point";
|
|
403
|
-
}
|
|
404
416
|
stabilityScore(st) {
|
|
405
|
-
if (st.logR.length === 0)
|
|
417
|
+
if (st.logR.length === 0)
|
|
418
|
+
return 0;
|
|
406
419
|
return Math.max(0, Math.min(1, 1 - Math.exp(st.logR[0])));
|
|
407
420
|
}
|
|
408
421
|
// ── Feature Extraction & Validation ──────────────────────────────────
|
|
@@ -424,25 +437,31 @@ var VasanaEngine = class {
|
|
|
424
437
|
}
|
|
425
438
|
/** 70/30 holdout: fraction of test points within 1.5 sigma of train mean. */
|
|
426
439
|
holdoutValidation(obs) {
|
|
427
|
-
if (obs.length < 4)
|
|
440
|
+
if (obs.length < 4)
|
|
441
|
+
return 0;
|
|
428
442
|
const si = Math.floor(obs.length * this.cfg.holdoutTrainRatio);
|
|
429
443
|
const train = obs.slice(0, si), test = obs.slice(si);
|
|
430
|
-
if (!train.length || !test.length)
|
|
444
|
+
if (!train.length || !test.length)
|
|
445
|
+
return 0;
|
|
431
446
|
const mu = train.reduce((a, b) => a + b, 0) / train.length;
|
|
432
447
|
const std = Math.sqrt(train.reduce((a, v) => a + (v - mu) ** 2, 0) / train.length + 1e-10);
|
|
433
448
|
let ok = 0;
|
|
434
|
-
for (const v of test)
|
|
449
|
+
for (const v of test)
|
|
450
|
+
if (Math.abs(v - mu) <= 1.5 * std)
|
|
451
|
+
ok++;
|
|
435
452
|
return ok / test.length;
|
|
436
453
|
}
|
|
437
454
|
assignValence(rows) {
|
|
438
455
|
let pos = 0, neg = 0;
|
|
439
456
|
for (const r of rows) {
|
|
440
|
-
if (r.pattern_type === "correction")
|
|
457
|
+
if (r.pattern_type === "correction")
|
|
458
|
+
neg += r.confidence;
|
|
441
459
|
else if (r.pattern_type !== "tool-sequence" || r.confidence > 0.6)
|
|
442
460
|
pos += r.confidence * (r.pattern_type === "tool-sequence" ? 0.5 : 1);
|
|
443
461
|
}
|
|
444
462
|
const tot = pos + neg;
|
|
445
|
-
if (tot < 0.1)
|
|
463
|
+
if (tot < 0.1)
|
|
464
|
+
return "neutral";
|
|
446
465
|
return pos / tot > 0.6 ? "positive" : neg / tot > 0.6 ? "negative" : "neutral";
|
|
447
466
|
}
|
|
448
467
|
clusterSamskaras(rows) {
|
|
@@ -456,54 +475,25 @@ var VasanaEngine = class {
|
|
|
456
475
|
return m;
|
|
457
476
|
}
|
|
458
477
|
// ── SQLite Helpers ───────────────────────────────────────────────────
|
|
459
|
-
// Schema mapping: Vasana.tendency
|
|
460
|
-
// reinforcementCount
|
|
478
|
+
// Schema mapping: Vasana.tendency->name, sourceSamskaras->source_samskaras(JSON),
|
|
479
|
+
// reinforcementCount->activation_count, lastActivated->last_activated
|
|
461
480
|
saveVasana(v) {
|
|
462
481
|
const db = DatabaseManager.instance().get("agent");
|
|
463
|
-
const existing = db.prepare(
|
|
464
|
-
`SELECT id FROM vasanas WHERE name=? AND (project=? OR (project IS NULL AND ?='__global__'))`
|
|
465
|
-
).get(v.tendency, v.project, v.project);
|
|
482
|
+
const existing = db.prepare(`SELECT id FROM vasanas WHERE name=? AND (project=? OR (project IS NULL AND ?='__global__'))`).get(v.tendency, v.project, v.project);
|
|
466
483
|
if (existing) {
|
|
467
|
-
db.prepare(
|
|
468
|
-
|
|
469
|
-
source_samskaras=?,updated_at=?,last_activated=?,activation_count=? WHERE id=?`
|
|
470
|
-
).run(
|
|
471
|
-
v.description,
|
|
472
|
-
v.valence,
|
|
473
|
-
v.strength,
|
|
474
|
-
v.stability,
|
|
475
|
-
JSON.stringify(v.sourceSamskaras),
|
|
476
|
-
v.updatedAt,
|
|
477
|
-
v.lastActivated,
|
|
478
|
-
v.reinforcementCount,
|
|
479
|
-
existing.id
|
|
480
|
-
);
|
|
484
|
+
db.prepare(`UPDATE vasanas SET description=?,valence=?,strength=?,stability=?,
|
|
485
|
+
source_samskaras=?,updated_at=?,last_activated=?,activation_count=? WHERE id=?`).run(v.description, v.valence, v.strength, v.stability, JSON.stringify(v.sourceSamskaras), v.updatedAt, v.lastActivated, v.reinforcementCount, existing.id);
|
|
481
486
|
} else {
|
|
482
|
-
db.prepare(
|
|
483
|
-
|
|
484
|
-
project,created_at,updated_at,last_activated,activation_count) VALUES (?,?,?,?,?,?,?,?,?,?,?)`
|
|
485
|
-
).run(
|
|
486
|
-
v.tendency,
|
|
487
|
-
v.description,
|
|
488
|
-
v.valence,
|
|
489
|
-
v.strength,
|
|
490
|
-
v.stability,
|
|
491
|
-
JSON.stringify(v.sourceSamskaras),
|
|
492
|
-
v.project === "__global__" ? null : v.project,
|
|
493
|
-
v.createdAt,
|
|
494
|
-
v.updatedAt,
|
|
495
|
-
v.lastActivated,
|
|
496
|
-
v.reinforcementCount
|
|
497
|
-
);
|
|
487
|
+
db.prepare(`INSERT INTO vasanas (name,description,valence,strength,stability,source_samskaras,
|
|
488
|
+
project,created_at,updated_at,last_activated,activation_count) VALUES (?,?,?,?,?,?,?,?,?,?,?)`).run(v.tendency, v.description, v.valence, v.strength, v.stability, JSON.stringify(v.sourceSamskaras), v.project === "__global__" ? null : v.project, v.createdAt, v.updatedAt, v.lastActivated, v.reinforcementCount);
|
|
498
489
|
}
|
|
499
490
|
this.cache.set(v.id, v);
|
|
500
491
|
}
|
|
501
492
|
loadVasana(vid) {
|
|
502
|
-
if (this.cache.has(vid))
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
project,created_at,updated_at,last_activated,activation_count FROM vasanas`
|
|
506
|
-
).all();
|
|
493
|
+
if (this.cache.has(vid))
|
|
494
|
+
return this.cache.get(vid);
|
|
495
|
+
const rows = DatabaseManager.instance().get("agent").prepare(`SELECT id,name,description,valence,strength,stability,source_samskaras,
|
|
496
|
+
project,created_at,updated_at,last_activated,activation_count FROM vasanas`).all();
|
|
507
497
|
for (const r of rows) {
|
|
508
498
|
const v = this.toVasana(r);
|
|
509
499
|
this.cache.set(v.id, v);
|
|
@@ -530,7 +520,8 @@ var VasanaEngine = class {
|
|
|
530
520
|
}
|
|
531
521
|
};
|
|
532
522
|
function jsonArr(s) {
|
|
533
|
-
if (!s)
|
|
523
|
+
if (!s)
|
|
524
|
+
return [];
|
|
534
525
|
try {
|
|
535
526
|
const p = JSON.parse(s);
|
|
536
527
|
return Array.isArray(p) ? p : [];
|
|
@@ -540,6 +531,16 @@ function jsonArr(s) {
|
|
|
540
531
|
}
|
|
541
532
|
|
|
542
533
|
export {
|
|
534
|
+
fnv1a,
|
|
535
|
+
DEFAULT_VASANA_CONFIG,
|
|
536
|
+
HARD_CEILINGS,
|
|
537
|
+
logsumexp,
|
|
538
|
+
lgamma,
|
|
539
|
+
logStudentT,
|
|
540
|
+
initBOCPD,
|
|
541
|
+
updateBOCPD,
|
|
542
|
+
serializeBOCPD,
|
|
543
|
+
deserializeBOCPD,
|
|
543
544
|
VasanaEngine
|
|
544
545
|
};
|
|
545
|
-
//# sourceMappingURL=chunk-
|
|
546
|
+
//# sourceMappingURL=chunk-W4PVGBUH.js.map
|