claude-memory-layer 1.0.43 → 1.0.45
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/README.md +4 -1
- package/dist/cli/index.js +940 -1480
- package/dist/cli/index.js.map +4 -4
- package/dist/core/index.js +1191 -1490
- package/dist/core/index.js.map +4 -4
- package/dist/hooks/post-tool-use.js +411 -749
- package/dist/hooks/post-tool-use.js.map +1 -1
- package/dist/hooks/semantic-daemon.js +400 -727
- package/dist/hooks/semantic-daemon.js.map +1 -1
- package/dist/hooks/session-end.js +396 -719
- package/dist/hooks/session-end.js.map +1 -1
- package/dist/hooks/session-start.js +397 -721
- package/dist/hooks/session-start.js.map +1 -1
- package/dist/hooks/stop.js +404 -735
- package/dist/hooks/stop.js.map +1 -1
- package/dist/hooks/user-prompt-submit.js +440 -807
- package/dist/hooks/user-prompt-submit.js.map +1 -1
- package/dist/index.js +1269 -1604
- package/dist/index.js.map +4 -4
- package/dist/mcp/index.js +1443 -1637
- package/dist/mcp/index.js.map +4 -4
- package/dist/server/api/index.js +430 -785
- package/dist/server/api/index.js.map +1 -1
- package/dist/server/index.js +438 -801
- package/dist/server/index.js.map +1 -1
- package/dist/services/memory-service.js +396 -719
- package/dist/services/memory-service.js.map +1 -1
- package/package.json +15 -3
package/dist/server/index.js
CHANGED
|
@@ -68,6 +68,7 @@ var DefaultEmbeddingMaintenanceService = class {
|
|
|
68
68
|
this.options = options;
|
|
69
69
|
this.fileSystem = options.fileSystem ?? defaultFileSystem;
|
|
70
70
|
}
|
|
71
|
+
options;
|
|
71
72
|
fileSystem;
|
|
72
73
|
getEmbeddingModelName() {
|
|
73
74
|
return this.options.getEmbeddingModelName();
|
|
@@ -102,8 +103,7 @@ var DefaultEmbeddingMaintenanceService = class {
|
|
|
102
103
|
}
|
|
103
104
|
const worker = this.options.getVectorWorker();
|
|
104
105
|
const wasRunning = worker?.isRunning() || false;
|
|
105
|
-
if (wasRunning)
|
|
106
|
-
worker?.stop();
|
|
106
|
+
if (wasRunning) worker?.stop();
|
|
107
107
|
await this.options.vectorStore.clearAll();
|
|
108
108
|
await this.options.eventStore.clearEmbeddingOutbox();
|
|
109
109
|
const enqueued = await this.reenqueueAllEvents();
|
|
@@ -120,8 +120,7 @@ var DefaultEmbeddingMaintenanceService = class {
|
|
|
120
120
|
2
|
|
121
121
|
)
|
|
122
122
|
);
|
|
123
|
-
if (wasRunning)
|
|
124
|
-
worker?.start();
|
|
123
|
+
if (wasRunning) worker?.start();
|
|
125
124
|
return {
|
|
126
125
|
changed: true,
|
|
127
126
|
previousModel,
|
|
@@ -146,15 +145,13 @@ var DefaultEmbeddingMaintenanceService = class {
|
|
|
146
145
|
let enqueued = 0;
|
|
147
146
|
while (true) {
|
|
148
147
|
const page = await this.options.eventStore.getEventsPage(DEFAULT_PAGE_SIZE, offset);
|
|
149
|
-
if (page.length === 0)
|
|
150
|
-
break;
|
|
148
|
+
if (page.length === 0) break;
|
|
151
149
|
for (const event of page) {
|
|
152
150
|
await this.options.eventStore.enqueueForEmbedding(event.id, event.content);
|
|
153
151
|
enqueued += 1;
|
|
154
152
|
}
|
|
155
153
|
offset += page.length;
|
|
156
|
-
if (page.length < DEFAULT_PAGE_SIZE)
|
|
157
|
-
break;
|
|
154
|
+
if (page.length < DEFAULT_PAGE_SIZE) break;
|
|
158
155
|
}
|
|
159
156
|
return enqueued;
|
|
160
157
|
}
|
|
@@ -172,12 +169,9 @@ import { randomUUID } from "crypto";
|
|
|
172
169
|
// src/core/db-wrapper.ts
|
|
173
170
|
import BetterSqlite3 from "better-sqlite3";
|
|
174
171
|
function toDate(value) {
|
|
175
|
-
if (value instanceof Date)
|
|
176
|
-
|
|
177
|
-
if (typeof value === "
|
|
178
|
-
return new Date(value);
|
|
179
|
-
if (typeof value === "number")
|
|
180
|
-
return new Date(value);
|
|
172
|
+
if (value instanceof Date) return value;
|
|
173
|
+
if (typeof value === "string") return new Date(value);
|
|
174
|
+
if (typeof value === "number") return new Date(value);
|
|
181
175
|
return new Date(String(value));
|
|
182
176
|
}
|
|
183
177
|
function createDatabase(dbPath, options) {
|
|
@@ -201,6 +195,8 @@ var WorkingSetStore = class {
|
|
|
201
195
|
this.eventStore = eventStore;
|
|
202
196
|
this.config = config;
|
|
203
197
|
}
|
|
198
|
+
eventStore;
|
|
199
|
+
config;
|
|
204
200
|
get db() {
|
|
205
201
|
return this.eventStore.getDatabase();
|
|
206
202
|
}
|
|
@@ -286,8 +282,7 @@ var WorkingSetStore = class {
|
|
|
286
282
|
* Prune specific events from working set (after consolidation)
|
|
287
283
|
*/
|
|
288
284
|
async prune(eventIds) {
|
|
289
|
-
if (eventIds.length === 0)
|
|
290
|
-
return;
|
|
285
|
+
if (eventIds.length === 0) return;
|
|
291
286
|
const placeholders = eventIds.map(() => "?").join(",");
|
|
292
287
|
await dbRun(
|
|
293
288
|
this.db,
|
|
@@ -357,8 +352,7 @@ var WorkingSetStore = class {
|
|
|
357
352
|
LIMIT ?`,
|
|
358
353
|
[maxEvents]
|
|
359
354
|
);
|
|
360
|
-
if (keepIds.length === 0)
|
|
361
|
-
return;
|
|
355
|
+
if (keepIds.length === 0) return;
|
|
362
356
|
const keepIdList = keepIds.map((r) => r.id);
|
|
363
357
|
const placeholders = keepIdList.map(() => "?").join(",");
|
|
364
358
|
await dbRun(
|
|
@@ -405,6 +399,7 @@ var ConsolidatedStore = class {
|
|
|
405
399
|
constructor(eventStore) {
|
|
406
400
|
this.eventStore = eventStore;
|
|
407
401
|
}
|
|
402
|
+
eventStore;
|
|
408
403
|
get db() {
|
|
409
404
|
return this.eventStore.getDatabase();
|
|
410
405
|
}
|
|
@@ -437,8 +432,7 @@ var ConsolidatedStore = class {
|
|
|
437
432
|
`SELECT * FROM consolidated_memories WHERE memory_id = ?`,
|
|
438
433
|
[memoryId]
|
|
439
434
|
);
|
|
440
|
-
if (rows.length === 0)
|
|
441
|
-
return null;
|
|
435
|
+
if (rows.length === 0) return null;
|
|
442
436
|
return this.rowToMemory(rows[0]);
|
|
443
437
|
}
|
|
444
438
|
/**
|
|
@@ -656,8 +650,7 @@ var ConsolidatedStore = class {
|
|
|
656
650
|
WHERE source_events LIKE ?`,
|
|
657
651
|
[`%"${eventId}"%`]
|
|
658
652
|
);
|
|
659
|
-
if ((result[0]?.count || 0) > 0)
|
|
660
|
-
return true;
|
|
653
|
+
if ((result[0]?.count || 0) > 0) return true;
|
|
661
654
|
}
|
|
662
655
|
return false;
|
|
663
656
|
}
|
|
@@ -671,8 +664,7 @@ var ConsolidatedStore = class {
|
|
|
671
664
|
ORDER BY created_at DESC
|
|
672
665
|
LIMIT 1`
|
|
673
666
|
);
|
|
674
|
-
if (result.length === 0)
|
|
675
|
-
return null;
|
|
667
|
+
if (result.length === 0) return null;
|
|
676
668
|
return new Date(result[0].created_at);
|
|
677
669
|
}
|
|
678
670
|
/**
|
|
@@ -702,6 +694,9 @@ var ConsolidationWorker = class {
|
|
|
702
694
|
this.consolidatedStore = consolidatedStore;
|
|
703
695
|
this.config = config;
|
|
704
696
|
}
|
|
697
|
+
workingSetStore;
|
|
698
|
+
consolidatedStore;
|
|
699
|
+
config;
|
|
705
700
|
running = false;
|
|
706
701
|
timeout = null;
|
|
707
702
|
lastActivity = /* @__PURE__ */ new Date();
|
|
@@ -709,8 +704,7 @@ var ConsolidationWorker = class {
|
|
|
709
704
|
* Start the consolidation worker
|
|
710
705
|
*/
|
|
711
706
|
start() {
|
|
712
|
-
if (this.running)
|
|
713
|
-
return;
|
|
707
|
+
if (this.running) return;
|
|
714
708
|
this.running = true;
|
|
715
709
|
this.scheduleNext();
|
|
716
710
|
}
|
|
@@ -753,8 +747,7 @@ var ConsolidationWorker = class {
|
|
|
753
747
|
* Schedule the next consolidation check
|
|
754
748
|
*/
|
|
755
749
|
scheduleNext() {
|
|
756
|
-
if (!this.running)
|
|
757
|
-
return;
|
|
750
|
+
if (!this.running) return;
|
|
758
751
|
this.timeout = setTimeout(
|
|
759
752
|
() => this.run(),
|
|
760
753
|
this.config.consolidation.triggerIntervalMs
|
|
@@ -764,8 +757,7 @@ var ConsolidationWorker = class {
|
|
|
764
757
|
* Run consolidation check
|
|
765
758
|
*/
|
|
766
759
|
async run() {
|
|
767
|
-
if (!this.running)
|
|
768
|
-
return;
|
|
760
|
+
if (!this.running) return;
|
|
769
761
|
try {
|
|
770
762
|
await this.checkAndConsolidate();
|
|
771
763
|
} catch (error) {
|
|
@@ -803,12 +795,10 @@ var ConsolidationWorker = class {
|
|
|
803
795
|
let consolidatedCount = 0;
|
|
804
796
|
const createdMemoryIds = [];
|
|
805
797
|
for (const group of groups) {
|
|
806
|
-
if (group.events.length < 3)
|
|
807
|
-
continue;
|
|
798
|
+
if (group.events.length < 3) continue;
|
|
808
799
|
const eventIds = group.events.map((e) => e.id);
|
|
809
800
|
const alreadyConsolidated = await this.consolidatedStore.isAlreadyConsolidated(eventIds);
|
|
810
|
-
if (alreadyConsolidated)
|
|
811
|
-
continue;
|
|
801
|
+
if (alreadyConsolidated) continue;
|
|
812
802
|
const summary = await this.summarize(group);
|
|
813
803
|
const memoryId = await this.consolidatedStore.create({
|
|
814
804
|
summary,
|
|
@@ -824,8 +814,7 @@ var ConsolidationWorker = class {
|
|
|
824
814
|
const consolidatedEventIds = groups.filter((g) => g.events.length >= 3).flatMap((g) => g.events.map((e) => e.id));
|
|
825
815
|
const oldEventIds = consolidatedEventIds.filter((id) => {
|
|
826
816
|
const event = workingSet.recentEvents.find((e) => e.id === id);
|
|
827
|
-
if (!event)
|
|
828
|
-
return false;
|
|
817
|
+
if (!event) return false;
|
|
829
818
|
const ageHours = (Date.now() - event.timestamp.getTime()) / (1e3 * 60 * 60);
|
|
830
819
|
return ageHours > this.config.workingSet.timeWindowHours / 2;
|
|
831
820
|
});
|
|
@@ -840,18 +829,13 @@ var ConsolidationWorker = class {
|
|
|
840
829
|
let promoted = 0;
|
|
841
830
|
for (const memoryId of memoryIds) {
|
|
842
831
|
const memory = await this.consolidatedStore.get(memoryId);
|
|
843
|
-
if (!memory)
|
|
844
|
-
|
|
845
|
-
if (memory.
|
|
846
|
-
continue;
|
|
847
|
-
if (memory.sourceEvents.length < 4)
|
|
848
|
-
continue;
|
|
832
|
+
if (!memory) continue;
|
|
833
|
+
if (memory.confidence < 0.55) continue;
|
|
834
|
+
if (memory.sourceEvents.length < 4) continue;
|
|
849
835
|
const exists = await this.consolidatedStore.hasRuleForSourceMemory(memoryId);
|
|
850
|
-
if (exists)
|
|
851
|
-
continue;
|
|
836
|
+
if (exists) continue;
|
|
852
837
|
const rule = this.buildRuleFromSummary(memory.summary, memory.topics);
|
|
853
|
-
if (!rule)
|
|
854
|
-
continue;
|
|
838
|
+
if (!rule) continue;
|
|
855
839
|
await this.consolidatedStore.createRule({
|
|
856
840
|
rule,
|
|
857
841
|
topics: memory.topics,
|
|
@@ -867,8 +851,7 @@ var ConsolidationWorker = class {
|
|
|
867
851
|
const lines = summary.split(/\r?\n/).map((l) => l.trim()).filter(Boolean).filter((l) => !l.toLowerCase().startsWith("topics:"));
|
|
868
852
|
const bullet = lines.find((l) => l.startsWith("- "))?.replace(/^-\s*/, "");
|
|
869
853
|
const seed = bullet || lines[0];
|
|
870
|
-
if (!seed || seed.length < 8)
|
|
871
|
-
return null;
|
|
854
|
+
if (!seed || seed.length < 8) return null;
|
|
872
855
|
const topicPrefix = topics.length > 0 ? `[${topics.slice(0, 2).join(", ")}] ` : "";
|
|
873
856
|
return `${topicPrefix}${seed}`;
|
|
874
857
|
}
|
|
@@ -1029,8 +1012,7 @@ var ConsolidationWorker = class {
|
|
|
1029
1012
|
*/
|
|
1030
1013
|
extractKeyPoint(content) {
|
|
1031
1014
|
const sentences = content.split(/[.!?\n]+/).filter((s) => s.trim().length > 10);
|
|
1032
|
-
if (sentences.length === 0)
|
|
1033
|
-
return null;
|
|
1015
|
+
if (sentences.length === 0) return null;
|
|
1034
1016
|
const firstSentence = sentences[0].trim();
|
|
1035
1017
|
if (firstSentence.length > 100) {
|
|
1036
1018
|
return firstSentence.slice(0, 100) + "...";
|
|
@@ -1050,8 +1032,7 @@ var ConsolidationWorker = class {
|
|
|
1050
1032
|
* Calculate time proximity score
|
|
1051
1033
|
*/
|
|
1052
1034
|
calculateTimeProximity(events) {
|
|
1053
|
-
if (events.length < 2)
|
|
1054
|
-
return 1;
|
|
1035
|
+
if (events.length < 2) return 1;
|
|
1055
1036
|
const timestamps = events.map((e) => e.timestamp.getTime()).sort((a, b) => a - b);
|
|
1056
1037
|
const timeSpan = timestamps[timestamps.length - 1] - timestamps[0];
|
|
1057
1038
|
const avgGap = timeSpan / (events.length - 1);
|
|
@@ -1070,6 +1051,8 @@ var ContinuityManager = class {
|
|
|
1070
1051
|
this.eventStore = eventStore;
|
|
1071
1052
|
this.config = config;
|
|
1072
1053
|
}
|
|
1054
|
+
eventStore;
|
|
1055
|
+
config;
|
|
1073
1056
|
lastContext = null;
|
|
1074
1057
|
get db() {
|
|
1075
1058
|
return this.eventStore.getDatabase();
|
|
@@ -1189,8 +1172,7 @@ var ContinuityManager = class {
|
|
|
1189
1172
|
* Calculate overlap between two arrays
|
|
1190
1173
|
*/
|
|
1191
1174
|
calculateOverlap(a, b) {
|
|
1192
|
-
if (a.length === 0 || b.length === 0)
|
|
1193
|
-
return 0;
|
|
1175
|
+
if (a.length === 0 || b.length === 0) return 0;
|
|
1194
1176
|
const setA = new Set(a.map((s) => s.toLowerCase()));
|
|
1195
1177
|
const setB = new Set(b.map((s) => s.toLowerCase()));
|
|
1196
1178
|
const intersection = [...setA].filter((x) => setB.has(x));
|
|
@@ -1363,6 +1345,7 @@ var DefaultEndlessMemoryServices = class {
|
|
|
1363
1345
|
this.options = options;
|
|
1364
1346
|
this.factories = options.factories ? { ...options.factories, randomUUID: options.factories.randomUUID ?? randomUUID4 } : defaultFactories;
|
|
1365
1347
|
}
|
|
1348
|
+
options;
|
|
1366
1349
|
factories;
|
|
1367
1350
|
workingSetStore = null;
|
|
1368
1351
|
consolidatedStore = null;
|
|
@@ -1377,8 +1360,7 @@ var DefaultEndlessMemoryServices = class {
|
|
|
1377
1360
|
}
|
|
1378
1361
|
}
|
|
1379
1362
|
async initializeEndlessMode() {
|
|
1380
|
-
if (this.consolidationWorker)
|
|
1381
|
-
return;
|
|
1363
|
+
if (this.consolidationWorker) return;
|
|
1382
1364
|
const config = await this.getEndlessConfig();
|
|
1383
1365
|
const workingSetStore = this.factories.createWorkingSetStore(this.options.eventStore, config);
|
|
1384
1366
|
const consolidatedStore = this.factories.createConsolidatedStore(this.options.eventStore);
|
|
@@ -1410,8 +1392,7 @@ var DefaultEndlessMemoryServices = class {
|
|
|
1410
1392
|
}
|
|
1411
1393
|
async setMode(mode) {
|
|
1412
1394
|
await this.options.initialize();
|
|
1413
|
-
if (mode === this.mode)
|
|
1414
|
-
return;
|
|
1395
|
+
if (mode === this.mode) return;
|
|
1415
1396
|
this.mode = mode;
|
|
1416
1397
|
await this.options.configStore.setEndlessConfig("mode", mode);
|
|
1417
1398
|
if (mode === "endless") {
|
|
@@ -1427,33 +1408,27 @@ var DefaultEndlessMemoryServices = class {
|
|
|
1427
1408
|
return this.mode === "endless";
|
|
1428
1409
|
}
|
|
1429
1410
|
async addToWorkingSet(eventId, relevanceScore) {
|
|
1430
|
-
if (!this.workingSetStore)
|
|
1431
|
-
return;
|
|
1411
|
+
if (!this.workingSetStore) return;
|
|
1432
1412
|
await this.workingSetStore.add(eventId, relevanceScore);
|
|
1433
1413
|
}
|
|
1434
1414
|
async getWorkingSet() {
|
|
1435
|
-
if (!this.workingSetStore)
|
|
1436
|
-
return null;
|
|
1415
|
+
if (!this.workingSetStore) return null;
|
|
1437
1416
|
return this.workingSetStore.get();
|
|
1438
1417
|
}
|
|
1439
1418
|
async searchConsolidated(query, options) {
|
|
1440
|
-
if (!this.consolidatedStore)
|
|
1441
|
-
return [];
|
|
1419
|
+
if (!this.consolidatedStore) return [];
|
|
1442
1420
|
return this.consolidatedStore.search(query, options);
|
|
1443
1421
|
}
|
|
1444
1422
|
async getConsolidatedMemories(limit) {
|
|
1445
|
-
if (!this.consolidatedStore)
|
|
1446
|
-
return [];
|
|
1423
|
+
if (!this.consolidatedStore) return [];
|
|
1447
1424
|
return this.consolidatedStore.getAll({ limit });
|
|
1448
1425
|
}
|
|
1449
1426
|
async markMemoryAccessed(memoryId) {
|
|
1450
|
-
if (!this.consolidatedStore)
|
|
1451
|
-
return;
|
|
1427
|
+
if (!this.consolidatedStore) return;
|
|
1452
1428
|
await this.consolidatedStore.markAccessed(memoryId);
|
|
1453
1429
|
}
|
|
1454
1430
|
async calculateContinuity(content, metadata) {
|
|
1455
|
-
if (!this.continuityManager)
|
|
1456
|
-
return null;
|
|
1431
|
+
if (!this.continuityManager) return null;
|
|
1457
1432
|
const snapshot = this.continuityManager.createSnapshot(
|
|
1458
1433
|
this.factories.randomUUID(),
|
|
1459
1434
|
content,
|
|
@@ -1465,8 +1440,7 @@ var DefaultEndlessMemoryServices = class {
|
|
|
1465
1440
|
this.consolidationWorker?.recordActivity();
|
|
1466
1441
|
}
|
|
1467
1442
|
async forceConsolidation() {
|
|
1468
|
-
if (!this.consolidationWorker)
|
|
1469
|
-
return 0;
|
|
1443
|
+
if (!this.consolidationWorker) return 0;
|
|
1470
1444
|
return this.consolidationWorker.forceRun();
|
|
1471
1445
|
}
|
|
1472
1446
|
async getEndlessModeStatus() {
|
|
@@ -1558,8 +1532,7 @@ var Embedder = class _Embedder {
|
|
|
1558
1532
|
* Initialize the embedding pipeline
|
|
1559
1533
|
*/
|
|
1560
1534
|
async initialize() {
|
|
1561
|
-
if (this.initialized)
|
|
1562
|
-
return;
|
|
1535
|
+
if (this.initialized) return;
|
|
1563
1536
|
const pipeline = await withSuppressedKnownTransformersWarnings(async () => {
|
|
1564
1537
|
try {
|
|
1565
1538
|
return await loadTransformersPipeline();
|
|
@@ -1676,8 +1649,7 @@ async function withSuppressedKnownTransformersWarnings(fn) {
|
|
|
1676
1649
|
originalConsoleWarn = console.warn;
|
|
1677
1650
|
console.warn = (...args) => {
|
|
1678
1651
|
const message = args.map(String).join(" ");
|
|
1679
|
-
if (isKnownBenignTransformersWarning(message))
|
|
1680
|
-
return;
|
|
1652
|
+
if (isKnownBenignTransformersWarning(message)) return;
|
|
1681
1653
|
(originalConsoleWarn ?? console.warn)(...args);
|
|
1682
1654
|
};
|
|
1683
1655
|
}
|
|
@@ -1959,8 +1931,7 @@ var GraduationPipeline = class {
|
|
|
1959
1931
|
const preferenceKeywords = ["prefer", "like", "want", "always", "never", "favorite"];
|
|
1960
1932
|
const preferences = [];
|
|
1961
1933
|
for (const event of events) {
|
|
1962
|
-
if (event.eventType !== "user_prompt")
|
|
1963
|
-
continue;
|
|
1934
|
+
if (event.eventType !== "user_prompt") continue;
|
|
1964
1935
|
const lowerContent = event.content.toLowerCase();
|
|
1965
1936
|
for (const keyword of preferenceKeywords) {
|
|
1966
1937
|
if (lowerContent.includes(keyword)) {
|
|
@@ -2126,11 +2097,9 @@ function sanitizeSegment(input, fallback) {
|
|
|
2126
2097
|
return v || fallback;
|
|
2127
2098
|
}
|
|
2128
2099
|
function getAtPath(obj, dotted) {
|
|
2129
|
-
if (!obj)
|
|
2130
|
-
return void 0;
|
|
2100
|
+
if (!obj) return void 0;
|
|
2131
2101
|
return dotted.split(".").reduce((acc, key) => {
|
|
2132
|
-
if (!acc || typeof acc !== "object")
|
|
2133
|
-
return void 0;
|
|
2102
|
+
if (!acc || typeof acc !== "object") return void 0;
|
|
2134
2103
|
return acc[key];
|
|
2135
2104
|
}, obj);
|
|
2136
2105
|
}
|
|
@@ -2150,6 +2119,7 @@ var MarkdownMirror = class {
|
|
|
2150
2119
|
constructor(rootDir) {
|
|
2151
2120
|
this.rootDir = rootDir;
|
|
2152
2121
|
}
|
|
2122
|
+
rootDir;
|
|
2153
2123
|
async append(event, eventId) {
|
|
2154
2124
|
const out = buildMirrorPath(this.rootDir, event);
|
|
2155
2125
|
fs2.mkdirSync(path2.dirname(out), { recursive: true });
|
|
@@ -2285,10 +2255,8 @@ function sqliteClose(db) {
|
|
|
2285
2255
|
db.close();
|
|
2286
2256
|
}
|
|
2287
2257
|
function toDateFromSQLite(value) {
|
|
2288
|
-
if (value instanceof Date)
|
|
2289
|
-
|
|
2290
|
-
if (typeof value === "number")
|
|
2291
|
-
return new Date(value);
|
|
2258
|
+
if (value instanceof Date) return value;
|
|
2259
|
+
if (typeof value === "number") return new Date(value);
|
|
2292
2260
|
if (typeof value === "string") {
|
|
2293
2261
|
const trimmed = value.trim();
|
|
2294
2262
|
if (/^\d{4}-\d{2}-\d{2}[ T]\d{2}:\d{2}:\d{2}(?:\.\d+)?$/.test(trimmed)) {
|
|
@@ -2310,8 +2278,7 @@ var DEFAULT_CATEGORY = "uncategorized";
|
|
|
2310
2278
|
function sanitizeSegment2(input, fallback) {
|
|
2311
2279
|
const raw = String(input ?? "").trim().toLowerCase();
|
|
2312
2280
|
const safe = raw.normalize("NFKD").replace(/[^a-z0-9_-]+/g, "-").replace(/^-+|-+$/g, "");
|
|
2313
|
-
if (!safe || safe === "." || safe === "..")
|
|
2314
|
-
return fallback;
|
|
2281
|
+
if (!safe || safe === "." || safe === "..") return fallback;
|
|
2315
2282
|
return safe;
|
|
2316
2283
|
}
|
|
2317
2284
|
function getCategorySegments(metadata, eventType) {
|
|
@@ -2352,6 +2319,7 @@ var MarkdownMirror2 = class {
|
|
|
2352
2319
|
constructor(rootDir) {
|
|
2353
2320
|
this.rootDir = rootDir;
|
|
2354
2321
|
}
|
|
2322
|
+
rootDir;
|
|
2355
2323
|
async append(event) {
|
|
2356
2324
|
const outPath = buildMirrorPath2(this.rootDir, event);
|
|
2357
2325
|
await fs5.mkdir(path4.dirname(outPath), { recursive: true });
|
|
@@ -2374,6 +2342,7 @@ var VectorOutbox = class {
|
|
|
2374
2342
|
this.db = db;
|
|
2375
2343
|
this.config = { ...DEFAULT_CONFIG2, ...config };
|
|
2376
2344
|
}
|
|
2345
|
+
db;
|
|
2377
2346
|
config;
|
|
2378
2347
|
/**
|
|
2379
2348
|
* Enqueue item for vectorization (idempotent).
|
|
@@ -2470,8 +2439,7 @@ var VectorOutbox = class {
|
|
|
2470
2439
|
`SELECT retry_count FROM vector_outbox WHERE job_id = ?`,
|
|
2471
2440
|
[jobId]
|
|
2472
2441
|
);
|
|
2473
|
-
if (rows.length === 0)
|
|
2474
|
-
return;
|
|
2442
|
+
if (rows.length === 0) return;
|
|
2475
2443
|
const retryCount = rows[0].retry_count;
|
|
2476
2444
|
const newStatus = retryCount >= this.config.maxRetries - 1 ? "failed" : "pending";
|
|
2477
2445
|
await dbRun(
|
|
@@ -2491,8 +2459,7 @@ var VectorOutbox = class {
|
|
|
2491
2459
|
`SELECT * FROM vector_outbox WHERE job_id = ?`,
|
|
2492
2460
|
[jobId]
|
|
2493
2461
|
);
|
|
2494
|
-
if (rows.length === 0)
|
|
2495
|
-
return null;
|
|
2462
|
+
if (rows.length === 0) return null;
|
|
2496
2463
|
return this.rowToJob(rows[0]);
|
|
2497
2464
|
}
|
|
2498
2465
|
/**
|
|
@@ -2626,30 +2593,24 @@ function isRetrievalDebugLaneName(value) {
|
|
|
2626
2593
|
return typeof value === "string" && RETRIEVAL_DEBUG_LANE_NAME_SET.has(value);
|
|
2627
2594
|
}
|
|
2628
2595
|
function normalizeRetrievalDebugLanes(value, maxItems = 6) {
|
|
2629
|
-
if (!Array.isArray(value) || maxItems <= 0)
|
|
2630
|
-
return [];
|
|
2596
|
+
if (!Array.isArray(value) || maxItems <= 0) return [];
|
|
2631
2597
|
const normalized = [];
|
|
2632
2598
|
const seen = /* @__PURE__ */ new Set();
|
|
2633
2599
|
for (const item of value) {
|
|
2634
2600
|
const lane = normalizeRetrievalDebugLane(item);
|
|
2635
|
-
if (!lane)
|
|
2636
|
-
continue;
|
|
2601
|
+
if (!lane) continue;
|
|
2637
2602
|
const key = [lane.lane, lane.reason, lane.score ?? ""].join("\0");
|
|
2638
|
-
if (seen.has(key))
|
|
2639
|
-
continue;
|
|
2603
|
+
if (seen.has(key)) continue;
|
|
2640
2604
|
seen.add(key);
|
|
2641
2605
|
normalized.push(lane);
|
|
2642
|
-
if (normalized.length >= maxItems)
|
|
2643
|
-
break;
|
|
2606
|
+
if (normalized.length >= maxItems) break;
|
|
2644
2607
|
}
|
|
2645
2608
|
return normalized;
|
|
2646
2609
|
}
|
|
2647
2610
|
function normalizeRetrievalDebugLane(value) {
|
|
2648
|
-
if (!value || typeof value !== "object")
|
|
2649
|
-
return null;
|
|
2611
|
+
if (!value || typeof value !== "object") return null;
|
|
2650
2612
|
const raw = value;
|
|
2651
|
-
if (!isRetrievalDebugLaneName(raw.lane))
|
|
2652
|
-
return null;
|
|
2613
|
+
if (!isRetrievalDebugLaneName(raw.lane)) return null;
|
|
2653
2614
|
const reason = sanitizeRetrievalLaneReason(typeof raw.reason === "string" ? raw.reason : "") || "unspecified";
|
|
2654
2615
|
const score = typeof raw.score === "number" && Number.isFinite(raw.score) ? Math.max(0, Math.min(1, raw.score)) : void 0;
|
|
2655
2616
|
return score === void 0 ? { lane: raw.lane, reason } : { lane: raw.lane, reason, score };
|
|
@@ -2672,27 +2633,21 @@ function normalizeRetrievalTraceDetails(details) {
|
|
|
2672
2633
|
eventId: detail.eventId,
|
|
2673
2634
|
score: detail.score
|
|
2674
2635
|
};
|
|
2675
|
-
if (detail.semanticScore !== void 0)
|
|
2676
|
-
|
|
2677
|
-
if (detail.
|
|
2678
|
-
|
|
2679
|
-
if (detail.recencyScore !== void 0)
|
|
2680
|
-
normalized.recencyScore = detail.recencyScore;
|
|
2681
|
-
if (lanes.length > 0)
|
|
2682
|
-
normalized.lanes = lanes;
|
|
2636
|
+
if (detail.semanticScore !== void 0) normalized.semanticScore = detail.semanticScore;
|
|
2637
|
+
if (detail.lexicalScore !== void 0) normalized.lexicalScore = detail.lexicalScore;
|
|
2638
|
+
if (detail.recencyScore !== void 0) normalized.recencyScore = detail.recencyScore;
|
|
2639
|
+
if (lanes.length > 0) normalized.lanes = lanes;
|
|
2683
2640
|
return normalized;
|
|
2684
2641
|
});
|
|
2685
2642
|
}
|
|
2686
2643
|
function parseRetrievalTraceDetails(value) {
|
|
2687
|
-
if (typeof value !== "string" || value.length === 0)
|
|
2688
|
-
return [];
|
|
2644
|
+
if (typeof value !== "string" || value.length === 0) return [];
|
|
2689
2645
|
const parsed = JSON.parse(value);
|
|
2690
2646
|
return Array.isArray(parsed) ? normalizeRetrievalTraceDetails(parsed) : [];
|
|
2691
2647
|
}
|
|
2692
2648
|
function normalizeQueryRewriteKind(value) {
|
|
2693
2649
|
const normalized = (value || "").trim().toLowerCase();
|
|
2694
|
-
if (normalized === "follow-up-context" || normalized === "intent-rewrite")
|
|
2695
|
-
return normalized;
|
|
2650
|
+
if (normalized === "follow-up-context" || normalized === "intent-rewrite") return normalized;
|
|
2696
2651
|
return "none";
|
|
2697
2652
|
}
|
|
2698
2653
|
var REWRITTEN_QUERY_REWRITE_KIND_SQL = `LOWER(TRIM(COALESCE(query_rewrite_kind, 'none'))) IN ('follow-up-context', 'intent-rewrite')`;
|
|
@@ -2710,8 +2665,7 @@ function isRecord(value) {
|
|
|
2710
2665
|
function getNestedRecord(root, path14) {
|
|
2711
2666
|
let cursor = root;
|
|
2712
2667
|
for (const key of path14) {
|
|
2713
|
-
if (!isRecord(cursor))
|
|
2714
|
-
return void 0;
|
|
2668
|
+
if (!isRecord(cursor)) return void 0;
|
|
2715
2669
|
cursor = cursor[key];
|
|
2716
2670
|
}
|
|
2717
2671
|
return isRecord(cursor) ? cursor : void 0;
|
|
@@ -2719,8 +2673,7 @@ function getNestedRecord(root, path14) {
|
|
|
2719
2673
|
function getNestedString(root, path14) {
|
|
2720
2674
|
let cursor = root;
|
|
2721
2675
|
for (const key of path14) {
|
|
2722
|
-
if (!isRecord(cursor))
|
|
2723
|
-
return void 0;
|
|
2676
|
+
if (!isRecord(cursor)) return void 0;
|
|
2724
2677
|
cursor = cursor[key];
|
|
2725
2678
|
}
|
|
2726
2679
|
return typeof cursor === "string" && cursor.length > 0 ? cursor : void 0;
|
|
@@ -2736,8 +2689,7 @@ function metadataProjectPaths(metadata) {
|
|
|
2736
2689
|
];
|
|
2737
2690
|
const paths = [];
|
|
2738
2691
|
for (const value of candidates) {
|
|
2739
|
-
if (value && !paths.includes(value))
|
|
2740
|
-
paths.push(value);
|
|
2692
|
+
if (value && !paths.includes(value)) paths.push(value);
|
|
2741
2693
|
}
|
|
2742
2694
|
return paths;
|
|
2743
2695
|
}
|
|
@@ -2758,12 +2710,9 @@ function maybeQuarantinePredicate(options, column = "metadata") {
|
|
|
2758
2710
|
return options?.includeQuarantined ? "1=1" : notActiveQuarantinedSql(column);
|
|
2759
2711
|
}
|
|
2760
2712
|
function safeParseMetadataValue(value) {
|
|
2761
|
-
if (!value)
|
|
2762
|
-
|
|
2763
|
-
if (typeof value
|
|
2764
|
-
return isRecord(value) ? value : void 0;
|
|
2765
|
-
if (typeof value !== "string")
|
|
2766
|
-
return void 0;
|
|
2713
|
+
if (!value) return void 0;
|
|
2714
|
+
if (typeof value === "object") return isRecord(value) ? value : void 0;
|
|
2715
|
+
if (typeof value !== "string") return void 0;
|
|
2767
2716
|
try {
|
|
2768
2717
|
const parsed = JSON.parse(value);
|
|
2769
2718
|
return isRecord(parsed) ? parsed : void 0;
|
|
@@ -2772,16 +2721,14 @@ function safeParseMetadataValue(value) {
|
|
|
2772
2721
|
}
|
|
2773
2722
|
}
|
|
2774
2723
|
function isImportedOrLegacyScopedMetadata(metadata) {
|
|
2775
|
-
if (!metadata)
|
|
2776
|
-
return false;
|
|
2724
|
+
if (!metadata) return false;
|
|
2777
2725
|
return Boolean(
|
|
2778
2726
|
metadata.importedFrom || metadata.sourceSessionId || metadata.sourceSessionHash || metadata.hermesSource || metadata.projectPath || metadata.sourceProjectPath || metadata.source === "hermes" || metadata.source === "claude" || metadata.source === "codex"
|
|
2779
2727
|
);
|
|
2780
2728
|
}
|
|
2781
2729
|
function addMetadataTag(metadata, tag) {
|
|
2782
2730
|
const current = Array.isArray(metadata.tags) ? metadata.tags.filter((value) => typeof value === "string") : [];
|
|
2783
|
-
if (!current.includes(tag))
|
|
2784
|
-
metadata.tags = [...current, tag];
|
|
2731
|
+
if (!current.includes(tag)) metadata.tags = [...current, tag];
|
|
2785
2732
|
}
|
|
2786
2733
|
function buildRepairResult(projectHash, dryRun) {
|
|
2787
2734
|
return {
|
|
@@ -2799,8 +2746,7 @@ function normalizeRepoName(value) {
|
|
|
2799
2746
|
return value.replace(/\.git$/i, "").trim().toLowerCase();
|
|
2800
2747
|
}
|
|
2801
2748
|
function projectBasename(projectPath) {
|
|
2802
|
-
if (!projectPath)
|
|
2803
|
-
return void 0;
|
|
2749
|
+
if (!projectPath) return void 0;
|
|
2804
2750
|
const trimmed = projectPath.replace(/[\\/]+$/, "");
|
|
2805
2751
|
const basename3 = nodePath2.basename(trimmed);
|
|
2806
2752
|
return basename3 ? normalizeRepoName(basename3) : void 0;
|
|
@@ -2813,23 +2759,19 @@ function isProjectScopeRepairExplanation(content) {
|
|
|
2813
2759
|
}
|
|
2814
2760
|
function hasConflictingContentProjectHint(content, projectPath) {
|
|
2815
2761
|
const currentName = projectBasename(projectPath);
|
|
2816
|
-
if (!currentName)
|
|
2817
|
-
|
|
2818
|
-
if (isProjectScopeRepairExplanation(content))
|
|
2819
|
-
return false;
|
|
2762
|
+
if (!currentName) return false;
|
|
2763
|
+
if (isProjectScopeRepairExplanation(content)) return false;
|
|
2820
2764
|
const githubRepoPattern = /github\.com[:/]([^/\s`'"#)]+)\/([^/\s`'"#)]+)(?:\.git)?/gi;
|
|
2821
2765
|
let githubMatch;
|
|
2822
2766
|
while ((githubMatch = githubRepoPattern.exec(content)) !== null) {
|
|
2823
2767
|
const repo = normalizeRepoName(githubMatch[2] || "");
|
|
2824
|
-
if (repo && repo !== currentName)
|
|
2825
|
-
return true;
|
|
2768
|
+
if (repo && repo !== currentName) return true;
|
|
2826
2769
|
}
|
|
2827
2770
|
const workspacePathPattern = /\/workspace\/([^/\s`'"#)]+)/gi;
|
|
2828
2771
|
let workspaceMatch;
|
|
2829
2772
|
while ((workspaceMatch = workspacePathPattern.exec(content)) !== null) {
|
|
2830
2773
|
const repo = normalizeRepoName(workspaceMatch[1] || "");
|
|
2831
|
-
if (repo && repo !== currentName)
|
|
2832
|
-
return true;
|
|
2774
|
+
if (repo && repo !== currentName) return true;
|
|
2833
2775
|
}
|
|
2834
2776
|
return false;
|
|
2835
2777
|
}
|
|
@@ -2849,15 +2791,12 @@ var SQLiteEventStore = class {
|
|
|
2849
2791
|
this.vectorOutbox = this.createVectorOutbox(options?.vectorOutbox);
|
|
2850
2792
|
}
|
|
2851
2793
|
createVectorOutbox(option) {
|
|
2852
|
-
if (this.readOnly || option === false)
|
|
2853
|
-
|
|
2854
|
-
if (option instanceof VectorOutbox)
|
|
2855
|
-
return option;
|
|
2794
|
+
if (this.readOnly || option === false) return null;
|
|
2795
|
+
if (option instanceof VectorOutbox) return option;
|
|
2856
2796
|
return new VectorOutbox(this.db, option ?? {});
|
|
2857
2797
|
}
|
|
2858
2798
|
enqueueVectorOutboxEventSync(eventId) {
|
|
2859
|
-
if (!this.vectorOutbox)
|
|
2860
|
-
return;
|
|
2799
|
+
if (!this.vectorOutbox) return;
|
|
2861
2800
|
this.vectorOutbox.enqueueSync("event", eventId);
|
|
2862
2801
|
}
|
|
2863
2802
|
async enqueueVectorOutboxEvent(eventId) {
|
|
@@ -2867,8 +2806,7 @@ var SQLiteEventStore = class {
|
|
|
2867
2806
|
* Initialize database schema
|
|
2868
2807
|
*/
|
|
2869
2808
|
async initialize() {
|
|
2870
|
-
if (this.initialized)
|
|
2871
|
-
return;
|
|
2809
|
+
if (this.initialized) return;
|
|
2872
2810
|
if (this.readOnly) {
|
|
2873
2811
|
this.initialized = true;
|
|
2874
2812
|
return;
|
|
@@ -3426,10 +3364,8 @@ var SQLiteEventStore = class {
|
|
|
3426
3364
|
try {
|
|
3427
3365
|
const edgeIndexes = sqliteAll(this.db, `PRAGMA index_list(memory_action_edges)`, []);
|
|
3428
3366
|
const hasSourceAwareUnique = edgeIndexes.some((index) => {
|
|
3429
|
-
if (Number(index.unique) !== 1)
|
|
3430
|
-
|
|
3431
|
-
if (!/^[A-Za-z0-9_]+$/.test(index.name))
|
|
3432
|
-
return false;
|
|
3367
|
+
if (Number(index.unique) !== 1) return false;
|
|
3368
|
+
if (!/^[A-Za-z0-9_]+$/.test(index.name)) return false;
|
|
3433
3369
|
const escapedName = index.name.replace(/"/g, '""');
|
|
3434
3370
|
const columns = sqliteAll(this.db, 'PRAGMA index_info("' + escapedName + '")', []).map((column) => column.name);
|
|
3435
3371
|
return columns.length === 5 && columns[0] === "src_action_id" && columns[1] === "rel_type" && columns[2] === "dst_type" && columns[3] === "dst_id" && columns[4] === "source";
|
|
@@ -3669,8 +3605,7 @@ var SQLiteEventStore = class {
|
|
|
3669
3605
|
`SELECT * FROM events WHERE id = ? AND ${maybeQuarantinePredicate(options)}`,
|
|
3670
3606
|
[id]
|
|
3671
3607
|
);
|
|
3672
|
-
if (!row)
|
|
3673
|
-
return null;
|
|
3608
|
+
if (!row) return null;
|
|
3674
3609
|
return this.rowToEvent(row);
|
|
3675
3610
|
}
|
|
3676
3611
|
/**
|
|
@@ -3708,10 +3643,8 @@ var SQLiteEventStore = class {
|
|
|
3708
3643
|
* NOTE: This bypasses the append() id generation to preserve stable IDs.
|
|
3709
3644
|
*/
|
|
3710
3645
|
async importEvents(events) {
|
|
3711
|
-
if (events.length === 0)
|
|
3712
|
-
|
|
3713
|
-
if (this.readOnly)
|
|
3714
|
-
return { inserted: 0, skipped: events.length };
|
|
3646
|
+
if (events.length === 0) return { inserted: 0, skipped: 0 };
|
|
3647
|
+
if (this.readOnly) return { inserted: 0, skipped: events.length };
|
|
3715
3648
|
await this.initialize();
|
|
3716
3649
|
const getById = this.db.prepare(`SELECT id FROM events WHERE id = ?`);
|
|
3717
3650
|
const getByDedupe = this.db.prepare(`SELECT event_id FROM event_dedup WHERE dedupe_key = ?`);
|
|
@@ -3829,8 +3762,7 @@ var SQLiteEventStore = class {
|
|
|
3829
3762
|
`SELECT * FROM sessions WHERE id = ?`,
|
|
3830
3763
|
[id]
|
|
3831
3764
|
);
|
|
3832
|
-
if (!row)
|
|
3833
|
-
return null;
|
|
3765
|
+
if (!row) return null;
|
|
3834
3766
|
return {
|
|
3835
3767
|
id: row.id,
|
|
3836
3768
|
startedAt: toDateFromSQLite(row.started_at),
|
|
@@ -3885,8 +3817,7 @@ var SQLiteEventStore = class {
|
|
|
3885
3817
|
LIMIT ?`,
|
|
3886
3818
|
[limit]
|
|
3887
3819
|
);
|
|
3888
|
-
if (pending.length === 0)
|
|
3889
|
-
return [];
|
|
3820
|
+
if (pending.length === 0) return [];
|
|
3890
3821
|
const ids = pending.map((r) => r.id);
|
|
3891
3822
|
const placeholders = ids.map(() => "?").join(",");
|
|
3892
3823
|
sqliteRun(
|
|
@@ -3910,8 +3841,7 @@ var SQLiteEventStore = class {
|
|
|
3910
3841
|
* Mark outbox items as done
|
|
3911
3842
|
*/
|
|
3912
3843
|
async completeOutboxItems(ids) {
|
|
3913
|
-
if (ids.length === 0)
|
|
3914
|
-
return;
|
|
3844
|
+
if (ids.length === 0) return;
|
|
3915
3845
|
const placeholders = ids.map(() => "?").join(",");
|
|
3916
3846
|
sqliteRun(
|
|
3917
3847
|
this.db,
|
|
@@ -3950,8 +3880,7 @@ var SQLiteEventStore = class {
|
|
|
3950
3880
|
* Mark outbox items as failed
|
|
3951
3881
|
*/
|
|
3952
3882
|
async failOutboxItems(ids, error) {
|
|
3953
|
-
if (ids.length === 0)
|
|
3954
|
-
return;
|
|
3883
|
+
if (ids.length === 0) return;
|
|
3955
3884
|
const placeholders = ids.map(() => "?").join(",");
|
|
3956
3885
|
sqliteRun(
|
|
3957
3886
|
this.db,
|
|
@@ -4078,8 +4007,7 @@ var SQLiteEventStore = class {
|
|
|
4078
4007
|
[]
|
|
4079
4008
|
);
|
|
4080
4009
|
const sample = (entry) => {
|
|
4081
|
-
if (result.samples.length < 20)
|
|
4082
|
-
result.samples.push(entry);
|
|
4010
|
+
if (result.samples.length < 20) result.samples.push(entry);
|
|
4083
4011
|
};
|
|
4084
4012
|
for (const row of rows) {
|
|
4085
4013
|
result.scanned++;
|
|
@@ -4206,12 +4134,10 @@ var SQLiteEventStore = class {
|
|
|
4206
4134
|
`SELECT status, COUNT(*) as count FROM vector_outbox GROUP BY status`
|
|
4207
4135
|
);
|
|
4208
4136
|
const processingAgeMs = (value) => {
|
|
4209
|
-
if (value === null || value === void 0)
|
|
4210
|
-
return null;
|
|
4137
|
+
if (value === null || value === void 0) return null;
|
|
4211
4138
|
const date = toDateFromSQLite(value);
|
|
4212
4139
|
const time = date.getTime();
|
|
4213
|
-
if (!Number.isFinite(time))
|
|
4214
|
-
return null;
|
|
4140
|
+
if (!Number.isFinite(time)) return null;
|
|
4215
4141
|
return Math.max(0, now.getTime() - time);
|
|
4216
4142
|
};
|
|
4217
4143
|
const fromRows = (rows, stuckProcessing, oldestProcessingAgeMs) => {
|
|
@@ -4360,8 +4286,7 @@ var SQLiteEventStore = class {
|
|
|
4360
4286
|
`SELECT value FROM endless_config WHERE key = ?`,
|
|
4361
4287
|
[key]
|
|
4362
4288
|
);
|
|
4363
|
-
if (!row)
|
|
4364
|
-
return null;
|
|
4289
|
+
if (!row) return null;
|
|
4365
4290
|
return JSON.parse(row.value);
|
|
4366
4291
|
}
|
|
4367
4292
|
/**
|
|
@@ -4380,8 +4305,7 @@ var SQLiteEventStore = class {
|
|
|
4380
4305
|
* Increment access count for events
|
|
4381
4306
|
*/
|
|
4382
4307
|
async incrementAccessCount(eventIds) {
|
|
4383
|
-
if (eventIds.length === 0 || this.readOnly)
|
|
4384
|
-
return;
|
|
4308
|
+
if (eventIds.length === 0 || this.readOnly) return;
|
|
4385
4309
|
await this.initialize();
|
|
4386
4310
|
const placeholders = eventIds.map(() => "?").join(",");
|
|
4387
4311
|
const currentTime = toSQLiteTimestamp(/* @__PURE__ */ new Date());
|
|
@@ -4424,8 +4348,7 @@ var SQLiteEventStore = class {
|
|
|
4424
4348
|
* Record a memory retrieval for helpfulness tracking
|
|
4425
4349
|
*/
|
|
4426
4350
|
async recordRetrieval(eventId, sessionId, score, query) {
|
|
4427
|
-
if (this.readOnly)
|
|
4428
|
-
return;
|
|
4351
|
+
if (this.readOnly) return;
|
|
4429
4352
|
await this.initialize();
|
|
4430
4353
|
const id = randomUUID6();
|
|
4431
4354
|
sqliteRun(
|
|
@@ -4455,16 +4378,14 @@ var SQLiteEventStore = class {
|
|
|
4455
4378
|
* Called at session end - uses behavioral signals to compute score
|
|
4456
4379
|
*/
|
|
4457
4380
|
async evaluateSessionHelpfulness(sessionId) {
|
|
4458
|
-
if (this.readOnly)
|
|
4459
|
-
return;
|
|
4381
|
+
if (this.readOnly) return;
|
|
4460
4382
|
await this.initialize();
|
|
4461
4383
|
const retrievals = sqliteAll(
|
|
4462
4384
|
this.db,
|
|
4463
4385
|
`SELECT * FROM memory_helpfulness WHERE session_id = ? AND measured_at IS NULL`,
|
|
4464
4386
|
[sessionId]
|
|
4465
4387
|
);
|
|
4466
|
-
if (retrievals.length === 0)
|
|
4467
|
-
return;
|
|
4388
|
+
if (retrievals.length === 0) return;
|
|
4468
4389
|
const sessionEvents = sqliteAll(
|
|
4469
4390
|
this.db,
|
|
4470
4391
|
`SELECT * FROM events WHERE session_id = ? ORDER BY timestamp ASC`,
|
|
@@ -4477,8 +4398,7 @@ var SQLiteEventStore = class {
|
|
|
4477
4398
|
for (const t of toolEvents) {
|
|
4478
4399
|
try {
|
|
4479
4400
|
const content = JSON.parse(t.content);
|
|
4480
|
-
if (content.success !== false)
|
|
4481
|
-
toolSuccessCount++;
|
|
4401
|
+
if (content.success !== false) toolSuccessCount++;
|
|
4482
4402
|
} catch {
|
|
4483
4403
|
toolSuccessCount++;
|
|
4484
4404
|
}
|
|
@@ -4496,8 +4416,7 @@ var SQLiteEventStore = class {
|
|
|
4496
4416
|
const pWords = new Set(p.content.toLowerCase().split(/\s+/).filter((w) => w.length > 2));
|
|
4497
4417
|
let overlap = 0;
|
|
4498
4418
|
for (const w of queryWords) {
|
|
4499
|
-
if (pWords.has(w))
|
|
4500
|
-
overlap++;
|
|
4419
|
+
if (pWords.has(w)) overlap++;
|
|
4501
4420
|
}
|
|
4502
4421
|
if (queryWords.size > 0 && overlap / queryWords.size > 0.5) {
|
|
4503
4422
|
wasReasked = 1;
|
|
@@ -4679,8 +4598,7 @@ var SQLiteEventStore = class {
|
|
|
4679
4598
|
return this.db;
|
|
4680
4599
|
}
|
|
4681
4600
|
hasTableColumn(tableName, columnName2) {
|
|
4682
|
-
if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(tableName))
|
|
4683
|
-
return false;
|
|
4601
|
+
if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(tableName)) return false;
|
|
4684
4602
|
try {
|
|
4685
4603
|
const rows = sqliteAll(this.db, `PRAGMA table_info("${tableName}")`, []);
|
|
4686
4604
|
return rows.some((row) => row.name === columnName2);
|
|
@@ -4747,8 +4665,7 @@ var SQLiteEventStore = class {
|
|
|
4747
4665
|
createdAt: toDateFromSQLite(row.created_at)
|
|
4748
4666
|
}));
|
|
4749
4667
|
} catch (err) {
|
|
4750
|
-
if (err?.message?.includes("no such table"))
|
|
4751
|
-
return [];
|
|
4668
|
+
if (err?.message?.includes("no such table")) return [];
|
|
4752
4669
|
throw err;
|
|
4753
4670
|
}
|
|
4754
4671
|
}
|
|
@@ -4921,8 +4838,7 @@ var SQLiteEventStore = class {
|
|
|
4921
4838
|
`SELECT id FROM events WHERE session_id = ?`,
|
|
4922
4839
|
[sessionId]
|
|
4923
4840
|
);
|
|
4924
|
-
if (events.length === 0)
|
|
4925
|
-
return 0;
|
|
4841
|
+
if (events.length === 0) return 0;
|
|
4926
4842
|
const eventIds = events.map((e) => e.id);
|
|
4927
4843
|
const placeholders = eventIds.map(() => "?").join(",");
|
|
4928
4844
|
const ftsTriggersDropped = [];
|
|
@@ -5134,8 +5050,7 @@ function sanitizeGovernanceAuditValue(value, key) {
|
|
|
5134
5050
|
return value;
|
|
5135
5051
|
}
|
|
5136
5052
|
function sanitizeAuditJson(value) {
|
|
5137
|
-
if (value === void 0)
|
|
5138
|
-
return void 0;
|
|
5053
|
+
if (value === void 0) return void 0;
|
|
5139
5054
|
return sanitizeGovernanceAuditValue(value);
|
|
5140
5055
|
}
|
|
5141
5056
|
function normalizeSourceEventIds(sourceEventIds) {
|
|
@@ -5184,12 +5099,10 @@ async function writeGovernanceAuditEntry(db, input) {
|
|
|
5184
5099
|
|
|
5185
5100
|
// src/core/operations/facet-repository.ts
|
|
5186
5101
|
function parseStringArray(value) {
|
|
5187
|
-
if (typeof value !== "string")
|
|
5188
|
-
return [];
|
|
5102
|
+
if (typeof value !== "string") return [];
|
|
5189
5103
|
try {
|
|
5190
5104
|
const parsed = JSON.parse(value);
|
|
5191
|
-
if (!Array.isArray(parsed))
|
|
5192
|
-
return [];
|
|
5105
|
+
if (!Array.isArray(parsed)) return [];
|
|
5193
5106
|
return parsed.filter((item) => typeof item === "string" && item.length > 0);
|
|
5194
5107
|
} catch {
|
|
5195
5108
|
return [];
|
|
@@ -5233,6 +5146,7 @@ var FacetRepository = class {
|
|
|
5233
5146
|
constructor(db) {
|
|
5234
5147
|
this.db = db;
|
|
5235
5148
|
}
|
|
5149
|
+
db;
|
|
5236
5150
|
async assign(input) {
|
|
5237
5151
|
const assignment = parseFacetAssignmentInput(input);
|
|
5238
5152
|
const existing = this.findByUniqueKey(assignment);
|
|
@@ -5537,19 +5451,14 @@ var RetentionFacetSchema = z5.object({
|
|
|
5537
5451
|
confidence: z5.number().min(0).max(1).default(1)
|
|
5538
5452
|
});
|
|
5539
5453
|
var DateLikeSchema = z5.preprocess((value) => {
|
|
5540
|
-
if (value instanceof Date)
|
|
5541
|
-
|
|
5542
|
-
if (typeof value === "string" || typeof value === "number")
|
|
5543
|
-
return new Date(value);
|
|
5454
|
+
if (value instanceof Date) return value;
|
|
5455
|
+
if (typeof value === "string" || typeof value === "number") return new Date(value);
|
|
5544
5456
|
return value;
|
|
5545
5457
|
}, z5.date());
|
|
5546
5458
|
var NullableDateLikeSchema = z5.preprocess((value) => {
|
|
5547
|
-
if (value === null || value === void 0 || value === "")
|
|
5548
|
-
|
|
5549
|
-
if (value
|
|
5550
|
-
return value;
|
|
5551
|
-
if (typeof value === "string" || typeof value === "number")
|
|
5552
|
-
return new Date(value);
|
|
5459
|
+
if (value === null || value === void 0 || value === "") return null;
|
|
5460
|
+
if (value instanceof Date) return value;
|
|
5461
|
+
if (typeof value === "string" || typeof value === "number") return new Date(value);
|
|
5553
5462
|
return value;
|
|
5554
5463
|
}, z5.date().nullable());
|
|
5555
5464
|
var OptionalTrimmedStringSchema2 = z5.preprocess(
|
|
@@ -5578,10 +5487,8 @@ import { z as z6 } from "zod";
|
|
|
5578
5487
|
var RequiredTrimmedStringSchema = z6.string().trim().min(1);
|
|
5579
5488
|
var OptionalTrimmedStringSchema3 = z6.string().trim().min(1).optional();
|
|
5580
5489
|
var DateLikeSchema2 = z6.preprocess((value) => {
|
|
5581
|
-
if (value instanceof Date)
|
|
5582
|
-
|
|
5583
|
-
if (typeof value === "string" || typeof value === "number")
|
|
5584
|
-
return new Date(value);
|
|
5490
|
+
if (value instanceof Date) return value;
|
|
5491
|
+
if (typeof value === "string" || typeof value === "number") return new Date(value);
|
|
5585
5492
|
return value;
|
|
5586
5493
|
}, z6.date());
|
|
5587
5494
|
var RetentionReasonSchema = z6.object({
|
|
@@ -5770,8 +5677,7 @@ var MemoryOperationsConfigSchema = z7.object({
|
|
|
5770
5677
|
}).default({});
|
|
5771
5678
|
var MemoryLessonNonEmptyStringSchema = z7.string().transform((value) => value.trim()).pipe(z7.string().min(1));
|
|
5772
5679
|
var MemoryLessonStringArraySchema = z7.preprocess((value) => {
|
|
5773
|
-
if (!Array.isArray(value))
|
|
5774
|
-
return value;
|
|
5680
|
+
if (!Array.isArray(value)) return value;
|
|
5775
5681
|
return value.map((item) => typeof item === "string" ? item.trim() : item).filter((item) => typeof item !== "string" || item.length > 0);
|
|
5776
5682
|
}, z7.array(MemoryLessonNonEmptyStringSchema)).default([]);
|
|
5777
5683
|
var MemoryLessonSchema = z7.object({
|
|
@@ -5816,14 +5722,12 @@ var ListMemoryLessonsInputSchema = z7.object({
|
|
|
5816
5722
|
});
|
|
5817
5723
|
var PerspectiveMemoryNonEmptyStringSchema = z7.string().transform((value) => value.trim()).pipe(z7.string().min(1));
|
|
5818
5724
|
var PerspectiveMemoryOptionalStringSchema = z7.preprocess((value) => {
|
|
5819
|
-
if (typeof value !== "string")
|
|
5820
|
-
return value;
|
|
5725
|
+
if (typeof value !== "string") return value;
|
|
5821
5726
|
const normalized = value.trim();
|
|
5822
5727
|
return normalized.length > 0 ? normalized : void 0;
|
|
5823
5728
|
}, PerspectiveMemoryNonEmptyStringSchema.optional());
|
|
5824
5729
|
var PerspectiveMemoryStringArraySchema = z7.preprocess((value) => {
|
|
5825
|
-
if (!Array.isArray(value))
|
|
5826
|
-
return value;
|
|
5730
|
+
if (!Array.isArray(value)) return value;
|
|
5827
5731
|
return value.map((item) => typeof item === "string" ? item.trim() : item).filter((item) => typeof item !== "string" || item.length > 0);
|
|
5828
5732
|
}, z7.array(PerspectiveMemoryNonEmptyStringSchema)).default([]);
|
|
5829
5733
|
var ActorCardSensitivePattern = /(?:\b(?:api[_-]?key|secret|password|passwd|token|access[_-]?token|client[_-]?secret|bearer)\b\s*[:=])|(?:\b(?:api[_-]?key|secret|password|passwd|token|access[_-]?token|client[_-]?secret|bearer)=)|(?:^|\s)(?:\/[A-Za-z0-9._-][^\s`'\"]*)/i;
|
|
@@ -6481,6 +6385,7 @@ var GraphPathService = class {
|
|
|
6481
6385
|
constructor(db) {
|
|
6482
6386
|
this.db = db;
|
|
6483
6387
|
}
|
|
6388
|
+
db;
|
|
6484
6389
|
expand(input) {
|
|
6485
6390
|
const graph = this.loadGraph(input.direction ?? "both");
|
|
6486
6391
|
const effectiveMaxHops = normalizeMaxHops(input.maxHops);
|
|
@@ -6498,11 +6403,9 @@ var GraphPathService = class {
|
|
|
6498
6403
|
while (queue.length > 0) {
|
|
6499
6404
|
queue.sort((a, b) => a.totalCost - b.totalCost || a.hops - b.hops || a.key.localeCompare(b.key));
|
|
6500
6405
|
const current = queue.shift();
|
|
6501
|
-
if (current.hops >= effectiveMaxHops)
|
|
6502
|
-
continue;
|
|
6406
|
+
if (current.hops >= effectiveMaxHops) continue;
|
|
6503
6407
|
for (const edge of graph.adjacency.get(current.key) ?? []) {
|
|
6504
|
-
if (current.visited.has(edge.toKey))
|
|
6505
|
-
continue;
|
|
6408
|
+
if (current.visited.has(edge.toKey)) continue;
|
|
6506
6409
|
const nextHops = current.hops + 1;
|
|
6507
6410
|
const nextTotalCost = current.totalCost + edge.step.cost;
|
|
6508
6411
|
const nextSteps = [...current.steps, edge.step];
|
|
@@ -6582,17 +6485,13 @@ function addTraversal(adjacency, fromKey, edge) {
|
|
|
6582
6485
|
adjacency.set(fromKey, edges);
|
|
6583
6486
|
}
|
|
6584
6487
|
function normalizeMaxHops(maxHops) {
|
|
6585
|
-
if (maxHops === void 0)
|
|
6586
|
-
|
|
6587
|
-
if (!Number.isFinite(maxHops))
|
|
6588
|
-
return MAX_HOPS;
|
|
6488
|
+
if (maxHops === void 0) return 1;
|
|
6489
|
+
if (!Number.isFinite(maxHops)) return MAX_HOPS;
|
|
6589
6490
|
return Math.min(Math.max(0, Math.trunc(maxHops)), MAX_HOPS);
|
|
6590
6491
|
}
|
|
6591
6492
|
function normalizeMaxResults(maxResults) {
|
|
6592
|
-
if (maxResults === void 0)
|
|
6593
|
-
|
|
6594
|
-
if (!Number.isFinite(maxResults))
|
|
6595
|
-
return DEFAULT_MAX_RESULTS;
|
|
6493
|
+
if (maxResults === void 0) return DEFAULT_MAX_RESULTS;
|
|
6494
|
+
if (!Number.isFinite(maxResults)) return DEFAULT_MAX_RESULTS;
|
|
6596
6495
|
return Math.min(Math.max(0, Math.trunc(maxResults)), MAX_RESULTS);
|
|
6597
6496
|
}
|
|
6598
6497
|
function isBetterPath(totalCost, hops, signature, existing) {
|
|
@@ -6604,18 +6503,15 @@ function pathSignature(steps) {
|
|
|
6604
6503
|
function edgeWeight(metaJson) {
|
|
6605
6504
|
const meta = parseMeta(metaJson);
|
|
6606
6505
|
const raw = meta.weight;
|
|
6607
|
-
if (typeof raw === "number" && Number.isFinite(raw) && raw > 0)
|
|
6608
|
-
return raw;
|
|
6506
|
+
if (typeof raw === "number" && Number.isFinite(raw) && raw > 0) return raw;
|
|
6609
6507
|
if (typeof raw === "string") {
|
|
6610
6508
|
const parsed = Number(raw);
|
|
6611
|
-
if (Number.isFinite(parsed) && parsed > 0)
|
|
6612
|
-
return parsed;
|
|
6509
|
+
if (Number.isFinite(parsed) && parsed > 0) return parsed;
|
|
6613
6510
|
}
|
|
6614
6511
|
return DEFAULT_WEIGHT;
|
|
6615
6512
|
}
|
|
6616
6513
|
function parseMeta(metaJson) {
|
|
6617
|
-
if (!metaJson)
|
|
6618
|
-
return {};
|
|
6514
|
+
if (!metaJson) return {};
|
|
6619
6515
|
try {
|
|
6620
6516
|
const parsed = JSON.parse(metaJson);
|
|
6621
6517
|
return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : {};
|
|
@@ -6628,8 +6524,7 @@ function nodeKey(node) {
|
|
|
6628
6524
|
}
|
|
6629
6525
|
function nodeFromKey(key) {
|
|
6630
6526
|
const index = key.indexOf(":");
|
|
6631
|
-
if (index === -1)
|
|
6632
|
-
return { type: "entity", id: key };
|
|
6527
|
+
if (index === -1) return { type: "entity", id: key };
|
|
6633
6528
|
return { type: key.slice(0, index), id: key.slice(index + 1) };
|
|
6634
6529
|
}
|
|
6635
6530
|
|
|
@@ -6685,6 +6580,7 @@ var QueryEntityExtractor = class {
|
|
|
6685
6580
|
constructor(db) {
|
|
6686
6581
|
this.db = db;
|
|
6687
6582
|
}
|
|
6583
|
+
db;
|
|
6688
6584
|
extract(query, options = {}) {
|
|
6689
6585
|
const maxCandidates = normalizeMaxCandidates(options.maxCandidates);
|
|
6690
6586
|
const candidates = [];
|
|
@@ -6706,8 +6602,7 @@ var QueryEntityExtractor = class {
|
|
|
6706
6602
|
let match;
|
|
6707
6603
|
while ((match = regex.exec(query)) !== null) {
|
|
6708
6604
|
const text = cleanCandidateText(match[2] ?? "");
|
|
6709
|
-
if (!isUsefulCandidate(text))
|
|
6710
|
-
continue;
|
|
6605
|
+
if (!isUsefulCandidate(text)) continue;
|
|
6711
6606
|
const start = match.index + 1;
|
|
6712
6607
|
const end = start + text.length;
|
|
6713
6608
|
ranges.push([match.index, match.index + match[0].length]);
|
|
@@ -6721,8 +6616,7 @@ var QueryEntityExtractor = class {
|
|
|
6721
6616
|
return ranges;
|
|
6722
6617
|
}
|
|
6723
6618
|
extractKnownAliases(query, candidates) {
|
|
6724
|
-
if (!this.db)
|
|
6725
|
-
return;
|
|
6619
|
+
if (!this.db) return;
|
|
6726
6620
|
const rows = sqliteAll(
|
|
6727
6621
|
this.db,
|
|
6728
6622
|
`SELECT
|
|
@@ -6746,11 +6640,9 @@ var QueryEntityExtractor = class {
|
|
|
6746
6640
|
]).filter(isUsefulCandidate);
|
|
6747
6641
|
for (const alias of aliasLabels) {
|
|
6748
6642
|
const normalizedAlias = normalizeForContainment(alias);
|
|
6749
|
-
if (!normalizedAlias || !containsPhrase(normalizedQuery, normalizedAlias))
|
|
6750
|
-
continue;
|
|
6643
|
+
if (!normalizedAlias || !containsPhrase(normalizedQuery, normalizedAlias)) continue;
|
|
6751
6644
|
const aliasKey = `${row.entity_id}:${normalizedAlias}`;
|
|
6752
|
-
if (seenAliases.has(aliasKey))
|
|
6753
|
-
continue;
|
|
6645
|
+
if (seenAliases.has(aliasKey)) continue;
|
|
6754
6646
|
seenAliases.add(aliasKey);
|
|
6755
6647
|
const range = findRange(query, alias);
|
|
6756
6648
|
pushCandidate(candidates, {
|
|
@@ -6771,8 +6663,7 @@ var QueryEntityExtractor = class {
|
|
|
6771
6663
|
let match;
|
|
6772
6664
|
while ((match = regex.exec(query)) !== null) {
|
|
6773
6665
|
const text = cleanCandidateText(match[2] ?? "");
|
|
6774
|
-
if (!isUsefulCandidate(text))
|
|
6775
|
-
continue;
|
|
6666
|
+
if (!isUsefulCandidate(text)) continue;
|
|
6776
6667
|
const start = match.index + (match[1]?.length ?? 0);
|
|
6777
6668
|
pushCandidate(candidates, {
|
|
6778
6669
|
text,
|
|
@@ -6787,8 +6678,7 @@ var QueryEntityExtractor = class {
|
|
|
6787
6678
|
let match;
|
|
6788
6679
|
while ((match = regex.exec(query)) !== null) {
|
|
6789
6680
|
const text = cleanCandidateText(match[2] ?? "");
|
|
6790
|
-
if (!isUsefulCandidate(text) || text.includes("/.") || text.includes("./"))
|
|
6791
|
-
continue;
|
|
6681
|
+
if (!isUsefulCandidate(text) || text.includes("/.") || text.includes("./")) continue;
|
|
6792
6682
|
const start = match.index + (match[1]?.length ?? 0);
|
|
6793
6683
|
pushCandidate(candidates, {
|
|
6794
6684
|
text,
|
|
@@ -6807,21 +6697,17 @@ var QueryEntityExtractor = class {
|
|
|
6807
6697
|
if (previous && query.slice(previous.end, token.start).match(/^\s+$/)) {
|
|
6808
6698
|
current.push(token);
|
|
6809
6699
|
} else {
|
|
6810
|
-
if (current.length > 0)
|
|
6811
|
-
groups.push(current);
|
|
6700
|
+
if (current.length > 0) groups.push(current);
|
|
6812
6701
|
current = [token];
|
|
6813
6702
|
}
|
|
6814
6703
|
}
|
|
6815
|
-
if (current.length > 0)
|
|
6816
|
-
groups.push(current);
|
|
6704
|
+
if (current.length > 0) groups.push(current);
|
|
6817
6705
|
for (const group of groups) {
|
|
6818
|
-
if (group.length === 1 && !isStrongSingleCapitalized(group[0].text))
|
|
6819
|
-
continue;
|
|
6706
|
+
if (group.length === 1 && !isStrongSingleCapitalized(group[0].text)) continue;
|
|
6820
6707
|
const start = group[0].start;
|
|
6821
6708
|
const end = group[group.length - 1].end;
|
|
6822
6709
|
const text = query.slice(start, end);
|
|
6823
|
-
if (!isUsefulCandidate(text))
|
|
6824
|
-
continue;
|
|
6710
|
+
if (!isUsefulCandidate(text)) continue;
|
|
6825
6711
|
pushCandidate(candidates, {
|
|
6826
6712
|
text,
|
|
6827
6713
|
source: "capitalized_term",
|
|
@@ -6842,8 +6728,7 @@ function collectCapitalizedTokens(query) {
|
|
|
6842
6728
|
}
|
|
6843
6729
|
function pushCandidate(candidates, input) {
|
|
6844
6730
|
const text = cleanCandidateText(input.text);
|
|
6845
|
-
if (!isUsefulCandidate(text))
|
|
6846
|
-
return;
|
|
6731
|
+
if (!isUsefulCandidate(text)) return;
|
|
6847
6732
|
const source = input.source;
|
|
6848
6733
|
candidates.push({
|
|
6849
6734
|
...input,
|
|
@@ -6861,15 +6746,13 @@ function dedupeAndSort(candidates) {
|
|
|
6861
6746
|
for (const candidate of sorted) {
|
|
6862
6747
|
if (candidate.source === "entity_alias") {
|
|
6863
6748
|
const aliasKey = `alias:${candidate.entityId ?? ""}:${normalizeCandidate(candidate.matchedAlias ?? candidate.text)}`;
|
|
6864
|
-
if (seenAliasKeys.has(aliasKey))
|
|
6865
|
-
continue;
|
|
6749
|
+
if (seenAliasKeys.has(aliasKey)) continue;
|
|
6866
6750
|
seenAliasKeys.add(aliasKey);
|
|
6867
6751
|
seenNormalized.add(candidate.normalized);
|
|
6868
6752
|
result.push(candidate);
|
|
6869
6753
|
continue;
|
|
6870
6754
|
}
|
|
6871
|
-
if (seenNormalized.has(candidate.normalized))
|
|
6872
|
-
continue;
|
|
6755
|
+
if (seenNormalized.has(candidate.normalized)) continue;
|
|
6873
6756
|
seenNormalized.add(candidate.normalized);
|
|
6874
6757
|
result.push(candidate);
|
|
6875
6758
|
}
|
|
@@ -6879,8 +6762,7 @@ function compareCandidates(a, b) {
|
|
|
6879
6762
|
return a.priority - b.priority || a.start - b.start || a.end - b.end || compareStrings(a.text, b.text) || compareStrings(a.entityId ?? "", b.entityId ?? "") || compareStrings(a.matchedAlias ?? "", b.matchedAlias ?? "");
|
|
6880
6763
|
}
|
|
6881
6764
|
function compareStrings(a, b) {
|
|
6882
|
-
if (a === b)
|
|
6883
|
-
return 0;
|
|
6765
|
+
if (a === b) return 0;
|
|
6884
6766
|
return a < b ? -1 : 1;
|
|
6885
6767
|
}
|
|
6886
6768
|
function stripPriority(candidate) {
|
|
@@ -6888,10 +6770,8 @@ function stripPriority(candidate) {
|
|
|
6888
6770
|
return publicCandidate;
|
|
6889
6771
|
}
|
|
6890
6772
|
function normalizeMaxCandidates(maxCandidates) {
|
|
6891
|
-
if (maxCandidates === void 0)
|
|
6892
|
-
|
|
6893
|
-
if (!Number.isFinite(maxCandidates))
|
|
6894
|
-
return DEFAULT_MAX_CANDIDATES;
|
|
6773
|
+
if (maxCandidates === void 0) return DEFAULT_MAX_CANDIDATES;
|
|
6774
|
+
if (!Number.isFinite(maxCandidates)) return DEFAULT_MAX_CANDIDATES;
|
|
6895
6775
|
return Math.min(Math.max(0, Math.trunc(maxCandidates)), MAX_CANDIDATES);
|
|
6896
6776
|
}
|
|
6897
6777
|
function cleanCandidateText(text) {
|
|
@@ -6913,21 +6793,17 @@ function aliasLabelFromCanonicalKey(canonicalKey) {
|
|
|
6913
6793
|
function findRange(query, alias) {
|
|
6914
6794
|
const normalizedAlias = normalizeForContainment(alias);
|
|
6915
6795
|
const directIndex = query.toLowerCase().indexOf(alias.toLowerCase());
|
|
6916
|
-
if (directIndex >= 0)
|
|
6917
|
-
return { start: directIndex, end: directIndex + alias.length };
|
|
6796
|
+
if (directIndex >= 0) return { start: directIndex, end: directIndex + alias.length };
|
|
6918
6797
|
const normalizedQuery = normalizeForContainment(query);
|
|
6919
6798
|
const normalizedIndex = normalizedQuery.indexOf(normalizedAlias);
|
|
6920
|
-
if (normalizedIndex < 0)
|
|
6921
|
-
return { start: 0, end: 0 };
|
|
6799
|
+
if (normalizedIndex < 0) return { start: 0, end: 0 };
|
|
6922
6800
|
const queryLower = query.toLowerCase();
|
|
6923
6801
|
const words = normalizedAlias.split(" ").filter(Boolean);
|
|
6924
|
-
if (words.length === 0)
|
|
6925
|
-
return { start: 0, end: 0 };
|
|
6802
|
+
if (words.length === 0) return { start: 0, end: 0 };
|
|
6926
6803
|
const first = queryLower.indexOf(words[0]);
|
|
6927
6804
|
const lastWord = words[words.length - 1];
|
|
6928
6805
|
const last = queryLower.indexOf(lastWord, first >= 0 ? first : 0);
|
|
6929
|
-
if (first >= 0 && last >= 0)
|
|
6930
|
-
return { start: first, end: last + lastWord.length };
|
|
6806
|
+
if (first >= 0 && last >= 0) return { start: first, end: last + lastWord.length };
|
|
6931
6807
|
return { start: normalizedIndex, end: normalizedIndex + normalizedAlias.length };
|
|
6932
6808
|
}
|
|
6933
6809
|
function isUsefulCandidate(text) {
|
|
@@ -6938,10 +6814,8 @@ function isInsideAnyRange(index, ranges) {
|
|
|
6938
6814
|
return ranges.some(([start, end]) => index >= start && index < end);
|
|
6939
6815
|
}
|
|
6940
6816
|
function isStrongSingleCapitalized(text) {
|
|
6941
|
-
if (/^[A-Z]{2,}[A-Z0-9]*$/.test(text))
|
|
6942
|
-
|
|
6943
|
-
if (/^[A-Z][a-z]+[A-Z][A-Za-z0-9]*$/.test(text))
|
|
6944
|
-
return true;
|
|
6817
|
+
if (/^[A-Z]{2,}[A-Z0-9]*$/.test(text)) return true;
|
|
6818
|
+
if (/^[A-Z][a-z]+[A-Z][A-Za-z0-9]*$/.test(text)) return true;
|
|
6945
6819
|
return text.length >= 4 && !SENTENCE_START_STOPWORDS.has(text);
|
|
6946
6820
|
}
|
|
6947
6821
|
function uniqueStrings(values) {
|
|
@@ -6949,8 +6823,7 @@ function uniqueStrings(values) {
|
|
|
6949
6823
|
const result = [];
|
|
6950
6824
|
for (const value of values) {
|
|
6951
6825
|
const key = normalizeForContainment(value);
|
|
6952
|
-
if (!key || seen.has(key))
|
|
6953
|
-
continue;
|
|
6826
|
+
if (!key || seen.has(key)) continue;
|
|
6954
6827
|
seen.add(key);
|
|
6955
6828
|
result.push(value);
|
|
6956
6829
|
}
|
|
@@ -6972,8 +6845,7 @@ var LessonCandidateInputSchema = z9.object({
|
|
|
6972
6845
|
import { z as z10 } from "zod";
|
|
6973
6846
|
var NonEmptyStringSchema5 = z10.string().transform((value) => value.trim()).pipe(z10.string().min(1));
|
|
6974
6847
|
var PromotionStringArraySchema = z10.preprocess((value) => {
|
|
6975
|
-
if (!Array.isArray(value))
|
|
6976
|
-
return value;
|
|
6848
|
+
if (!Array.isArray(value)) return value;
|
|
6977
6849
|
return value.map((item) => typeof item === "string" ? item.trim() : item).filter((item) => typeof item !== "string" || item.length > 0);
|
|
6978
6850
|
}, z10.array(NonEmptyStringSchema5).max(100));
|
|
6979
6851
|
var ReviewedLessonCandidateSchema = z10.object({
|
|
@@ -7021,8 +6893,7 @@ function projectHashFromStorage(projectHash) {
|
|
|
7021
6893
|
return projectHash.length > 0 ? projectHash : void 0;
|
|
7022
6894
|
}
|
|
7023
6895
|
function parseJsonRecord(value) {
|
|
7024
|
-
if (!value)
|
|
7025
|
-
return void 0;
|
|
6896
|
+
if (!value) return void 0;
|
|
7026
6897
|
try {
|
|
7027
6898
|
const parsed = JSON.parse(value);
|
|
7028
6899
|
return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : void 0;
|
|
@@ -7034,8 +6905,7 @@ function sanitizeString(value) {
|
|
|
7034
6905
|
return String(sanitizeGovernanceAuditValue(value)).trim();
|
|
7035
6906
|
}
|
|
7036
6907
|
function sanitizeMetadata(metadata) {
|
|
7037
|
-
if (!metadata)
|
|
7038
|
-
return void 0;
|
|
6908
|
+
if (!metadata) return void 0;
|
|
7039
6909
|
return sanitizeGovernanceAuditValue(metadata);
|
|
7040
6910
|
}
|
|
7041
6911
|
function slugActorPart(value) {
|
|
@@ -7043,8 +6913,7 @@ function slugActorPart(value) {
|
|
|
7043
6913
|
return slug.length > 0 ? slug : "unknown";
|
|
7044
6914
|
}
|
|
7045
6915
|
function stableActorId(input) {
|
|
7046
|
-
if (input.actorId)
|
|
7047
|
-
return sanitizeString(input.actorId);
|
|
6916
|
+
if (input.actorId) return sanitizeString(input.actorId);
|
|
7048
6917
|
const projectPart = input.projectHash ? `project:${slugActorPart(input.projectHash)}` : "global";
|
|
7049
6918
|
return [
|
|
7050
6919
|
"actor",
|
|
@@ -7067,12 +6936,10 @@ function rowToActor(row) {
|
|
|
7067
6936
|
});
|
|
7068
6937
|
}
|
|
7069
6938
|
function metadataString(metadata, keys) {
|
|
7070
|
-
if (!metadata)
|
|
7071
|
-
return void 0;
|
|
6939
|
+
if (!metadata) return void 0;
|
|
7072
6940
|
for (const key of keys) {
|
|
7073
6941
|
const value = metadata[key];
|
|
7074
|
-
if (typeof value === "string" && value.trim().length > 0)
|
|
7075
|
-
return value.trim();
|
|
6942
|
+
if (typeof value === "string" && value.trim().length > 0) return value.trim();
|
|
7076
6943
|
}
|
|
7077
6944
|
return void 0;
|
|
7078
6945
|
}
|
|
@@ -7122,6 +6989,7 @@ var ActorRepository = class {
|
|
|
7122
6989
|
constructor(db) {
|
|
7123
6990
|
this.db = db;
|
|
7124
6991
|
}
|
|
6992
|
+
db;
|
|
7125
6993
|
async upsert(input) {
|
|
7126
6994
|
const parsed = UpsertMemoryActorInputSchema.parse(input);
|
|
7127
6995
|
const actorId = stableActorId(parsed);
|
|
@@ -7175,8 +7043,7 @@ var ActorRepository = class {
|
|
|
7175
7043
|
}
|
|
7176
7044
|
require(actorId) {
|
|
7177
7045
|
const actor = this.get(actorId);
|
|
7178
|
-
if (!actor)
|
|
7179
|
-
throw new Error(`Memory actor not found: ${actorId}`);
|
|
7046
|
+
if (!actor) throw new Error(`Memory actor not found: ${actorId}`);
|
|
7180
7047
|
return actor;
|
|
7181
7048
|
}
|
|
7182
7049
|
async list(input = {}) {
|
|
@@ -7212,8 +7079,7 @@ function projectHashFromStorage2(projectHash) {
|
|
|
7212
7079
|
return projectHash.length > 0 ? projectHash : void 0;
|
|
7213
7080
|
}
|
|
7214
7081
|
function parseJsonRecord2(value) {
|
|
7215
|
-
if (!value)
|
|
7216
|
-
return void 0;
|
|
7082
|
+
if (!value) return void 0;
|
|
7217
7083
|
try {
|
|
7218
7084
|
const parsed = JSON.parse(value);
|
|
7219
7085
|
return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : void 0;
|
|
@@ -7222,8 +7088,7 @@ function parseJsonRecord2(value) {
|
|
|
7222
7088
|
}
|
|
7223
7089
|
}
|
|
7224
7090
|
function sanitizeMetadata2(metadata) {
|
|
7225
|
-
if (!metadata)
|
|
7226
|
-
return void 0;
|
|
7091
|
+
if (!metadata) return void 0;
|
|
7227
7092
|
return sanitizeGovernanceAuditValue(metadata);
|
|
7228
7093
|
}
|
|
7229
7094
|
function rowToSessionActor(row) {
|
|
@@ -7243,6 +7108,7 @@ var SessionActorRepository = class {
|
|
|
7243
7108
|
constructor(db) {
|
|
7244
7109
|
this.db = db;
|
|
7245
7110
|
}
|
|
7111
|
+
db;
|
|
7246
7112
|
async upsertMembership(input) {
|
|
7247
7113
|
const parsed = UpsertSessionActorInputSchema.parse(input);
|
|
7248
7114
|
const projectHash = projectHashToStorage3(parsed.projectHash);
|
|
@@ -7289,8 +7155,7 @@ var SessionActorRepository = class {
|
|
|
7289
7155
|
);
|
|
7290
7156
|
}
|
|
7291
7157
|
const saved = this.get(projectHash, parsed.sessionId, parsed.actorId);
|
|
7292
|
-
if (!saved)
|
|
7293
|
-
throw new Error("session actor membership was not saved");
|
|
7158
|
+
if (!saved) throw new Error("session actor membership was not saved");
|
|
7294
7159
|
return saved;
|
|
7295
7160
|
}
|
|
7296
7161
|
async listBySession(input) {
|
|
@@ -7326,8 +7191,7 @@ var SessionActorRepository = class {
|
|
|
7326
7191
|
]
|
|
7327
7192
|
);
|
|
7328
7193
|
const saved = this.get(projectHash, parsed.sessionId, parsed.actorId);
|
|
7329
|
-
if (!saved)
|
|
7330
|
-
throw new Error("session actor membership not found after update");
|
|
7194
|
+
if (!saved) throw new Error("session actor membership not found after update");
|
|
7331
7195
|
return saved;
|
|
7332
7196
|
}
|
|
7333
7197
|
get(projectHash, sessionId, actorId) {
|
|
@@ -7349,8 +7213,7 @@ function projectHashFromStorage3(projectHash) {
|
|
|
7349
7213
|
return projectHash.length > 0 ? projectHash : void 0;
|
|
7350
7214
|
}
|
|
7351
7215
|
function parseStringArray2(value) {
|
|
7352
|
-
if (!value)
|
|
7353
|
-
return [];
|
|
7216
|
+
if (!value) return [];
|
|
7354
7217
|
try {
|
|
7355
7218
|
const parsed = JSON.parse(value);
|
|
7356
7219
|
return Array.isArray(parsed) ? parsed.filter((entry) => typeof entry === "string") : [];
|
|
@@ -7359,8 +7222,7 @@ function parseStringArray2(value) {
|
|
|
7359
7222
|
}
|
|
7360
7223
|
}
|
|
7361
7224
|
function parseJsonRecord3(value) {
|
|
7362
|
-
if (!value)
|
|
7363
|
-
return void 0;
|
|
7225
|
+
if (!value) return void 0;
|
|
7364
7226
|
try {
|
|
7365
7227
|
const parsed = JSON.parse(value);
|
|
7366
7228
|
return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : void 0;
|
|
@@ -7376,8 +7238,7 @@ function sanitizeStoredStringArray(values) {
|
|
|
7376
7238
|
return values.map(sanitizeStoredString).filter((value) => value.length > 0);
|
|
7377
7239
|
}
|
|
7378
7240
|
function sanitizeStoredRecord(value) {
|
|
7379
|
-
if (!value)
|
|
7380
|
-
return void 0;
|
|
7241
|
+
if (!value) return void 0;
|
|
7381
7242
|
return sanitizeGovernanceAuditValue(value);
|
|
7382
7243
|
}
|
|
7383
7244
|
function stableHash(value) {
|
|
@@ -7428,8 +7289,7 @@ function sanitizedObservationSnapshot(observation) {
|
|
|
7428
7289
|
});
|
|
7429
7290
|
}
|
|
7430
7291
|
function queryScore(observation, terms) {
|
|
7431
|
-
if (terms.length === 0)
|
|
7432
|
-
return 0;
|
|
7292
|
+
if (terms.length === 0) return 0;
|
|
7433
7293
|
const haystack = [observation.content, observation.level, observation.sessionId ?? ""].join(" ").toLowerCase();
|
|
7434
7294
|
return terms.reduce((score, term) => score + (haystack.includes(term) ? 1 : 0), 0);
|
|
7435
7295
|
}
|
|
@@ -7475,12 +7335,12 @@ var PerspectiveObservationRepository = class {
|
|
|
7475
7335
|
this.vectorOutbox = options.vectorOutbox;
|
|
7476
7336
|
}
|
|
7477
7337
|
}
|
|
7338
|
+
db;
|
|
7478
7339
|
vectorOutbox = null;
|
|
7479
7340
|
vectorOutboxOption;
|
|
7480
7341
|
getVectorOutbox() {
|
|
7481
7342
|
const option = this.vectorOutboxOption;
|
|
7482
|
-
if (option === false)
|
|
7483
|
-
return null;
|
|
7343
|
+
if (option === false) return null;
|
|
7484
7344
|
if (option instanceof VectorOutbox) {
|
|
7485
7345
|
this.vectorOutbox = option;
|
|
7486
7346
|
return option;
|
|
@@ -7492,8 +7352,7 @@ var PerspectiveObservationRepository = class {
|
|
|
7492
7352
|
}
|
|
7493
7353
|
enqueueObservationSync(observationId) {
|
|
7494
7354
|
const outbox = this.getVectorOutbox();
|
|
7495
|
-
if (!outbox)
|
|
7496
|
-
return;
|
|
7355
|
+
if (!outbox) return;
|
|
7497
7356
|
outbox.enqueueSync("perspective_observation", observationId);
|
|
7498
7357
|
}
|
|
7499
7358
|
async create(input) {
|
|
@@ -7555,14 +7414,12 @@ var PerspectiveObservationRepository = class {
|
|
|
7555
7414
|
contentHash,
|
|
7556
7415
|
sourceHash
|
|
7557
7416
|
);
|
|
7558
|
-
if (!saved)
|
|
7559
|
-
throw new Error("perspective observation was not saved");
|
|
7417
|
+
if (!saved) throw new Error("perspective observation was not saved");
|
|
7560
7418
|
this.enqueueObservationSync(saved.observationId);
|
|
7561
7419
|
});
|
|
7562
7420
|
transaction();
|
|
7563
7421
|
const savedObservation = saved;
|
|
7564
|
-
if (!savedObservation)
|
|
7565
|
-
throw new Error("perspective observation was not saved");
|
|
7422
|
+
if (!savedObservation) throw new Error("perspective observation was not saved");
|
|
7566
7423
|
await this.writeCreateAudit({ ...parsed, observerActorId, observedActorId, sessionId, content, sourceEventIds, sourceObservationIds, createdBy, actor, metadata }, savedObservation);
|
|
7567
7424
|
return savedObservation;
|
|
7568
7425
|
}
|
|
@@ -7572,8 +7429,7 @@ var PerspectiveObservationRepository = class {
|
|
|
7572
7429
|
const ftsQuery = buildObservationFtsQuery(parsed.query);
|
|
7573
7430
|
if (ftsQuery) {
|
|
7574
7431
|
const ftsResult = this.queryWithFts(parsed, ftsQuery);
|
|
7575
|
-
if (ftsResult)
|
|
7576
|
-
return ftsResult;
|
|
7432
|
+
if (ftsResult) return ftsResult;
|
|
7577
7433
|
}
|
|
7578
7434
|
}
|
|
7579
7435
|
return this.queryWithPrefetch(parsed);
|
|
@@ -7594,8 +7450,7 @@ var PerspectiveObservationRepository = class {
|
|
|
7594
7450
|
);
|
|
7595
7451
|
return rows.map(rowToObservation);
|
|
7596
7452
|
} catch (error) {
|
|
7597
|
-
if (isFtsUnavailableError(error))
|
|
7598
|
-
return null;
|
|
7453
|
+
if (isFtsUnavailableError(error)) return null;
|
|
7599
7454
|
throw error;
|
|
7600
7455
|
}
|
|
7601
7456
|
}
|
|
@@ -7636,8 +7491,7 @@ var PerspectiveObservationRepository = class {
|
|
|
7636
7491
|
const parsed = DeletePerspectiveObservationInputSchema.parse(input);
|
|
7637
7492
|
const projectHash = projectHashToStorage4(parsed.projectHash);
|
|
7638
7493
|
const before = this.get(projectHash, parsed.observationId);
|
|
7639
|
-
if (!before)
|
|
7640
|
-
throw new Error("perspective observation not found");
|
|
7494
|
+
if (!before) throw new Error("perspective observation not found");
|
|
7641
7495
|
const deletedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
7642
7496
|
sqliteRun(
|
|
7643
7497
|
this.db,
|
|
@@ -7647,8 +7501,7 @@ var PerspectiveObservationRepository = class {
|
|
|
7647
7501
|
[deletedAt, deletedAt, projectHash, parsed.observationId]
|
|
7648
7502
|
);
|
|
7649
7503
|
const after = this.get(projectHash, parsed.observationId);
|
|
7650
|
-
if (!after)
|
|
7651
|
-
throw new Error("perspective observation not found after delete");
|
|
7504
|
+
if (!after) throw new Error("perspective observation not found after delete");
|
|
7652
7505
|
await writeGovernanceAuditEntry(this.db, {
|
|
7653
7506
|
operation: "perspective_observation_delete",
|
|
7654
7507
|
actor: parsed.actor,
|
|
@@ -7704,11 +7557,9 @@ var DEFAULT_CONFIG3 = {
|
|
|
7704
7557
|
var MAX_OBSERVATION_CONTENT_CHARS = 600;
|
|
7705
7558
|
var RuleBasedPerspectiveObservationExtractor = class {
|
|
7706
7559
|
async extract(event) {
|
|
7707
|
-
if (!isSupportedSourceEvent(event))
|
|
7708
|
-
return [];
|
|
7560
|
+
if (!isSupportedSourceEvent(event)) return [];
|
|
7709
7561
|
const content = normalizeObservationContent(event.content);
|
|
7710
|
-
if (!content)
|
|
7711
|
-
return [];
|
|
7562
|
+
if (!content) return [];
|
|
7712
7563
|
return [{
|
|
7713
7564
|
content,
|
|
7714
7565
|
confidence: 0.6,
|
|
@@ -7779,8 +7630,7 @@ var PerspectiveDeriver = class {
|
|
|
7779
7630
|
for (const candidate of candidates) {
|
|
7780
7631
|
const observedActorId = candidate.observedActorId ?? sourceActor.actorId;
|
|
7781
7632
|
const observers = selectObservers(members, observedActorId, this.config.deriver.maxObserversPerSession);
|
|
7782
|
-
if (observers.length === 0)
|
|
7783
|
-
continue;
|
|
7633
|
+
if (observers.length === 0) continue;
|
|
7784
7634
|
for (const observerActorId of observers) {
|
|
7785
7635
|
await this.observations.create({
|
|
7786
7636
|
projectHash,
|
|
@@ -7833,28 +7683,22 @@ function normalizeConfig(config) {
|
|
|
7833
7683
|
};
|
|
7834
7684
|
}
|
|
7835
7685
|
function clampInteger(value, fallback, min, max) {
|
|
7836
|
-
if (!Number.isFinite(value))
|
|
7837
|
-
return fallback;
|
|
7686
|
+
if (!Number.isFinite(value)) return fallback;
|
|
7838
7687
|
return Math.max(min, Math.min(max, Math.trunc(Number(value))));
|
|
7839
7688
|
}
|
|
7840
7689
|
function isSupportedSourceEvent(event) {
|
|
7841
7690
|
return event.eventType === "user_prompt" || event.eventType === "agent_response";
|
|
7842
7691
|
}
|
|
7843
7692
|
function roleForEvent(event) {
|
|
7844
|
-
if (event.eventType === "user_prompt")
|
|
7845
|
-
|
|
7846
|
-
if (event.eventType === "
|
|
7847
|
-
|
|
7848
|
-
if (event.eventType === "tool_observation")
|
|
7849
|
-
return "tool";
|
|
7850
|
-
if (event.eventType === "session_summary")
|
|
7851
|
-
return "system";
|
|
7693
|
+
if (event.eventType === "user_prompt") return "speaker";
|
|
7694
|
+
if (event.eventType === "agent_response") return "assistant";
|
|
7695
|
+
if (event.eventType === "tool_observation") return "tool";
|
|
7696
|
+
if (event.eventType === "session_summary") return "system";
|
|
7852
7697
|
return "unknown";
|
|
7853
7698
|
}
|
|
7854
7699
|
function normalizeCandidate2(candidate) {
|
|
7855
7700
|
const content = normalizeObservationContent(candidate.content);
|
|
7856
|
-
if (!content)
|
|
7857
|
-
return null;
|
|
7701
|
+
if (!content) return null;
|
|
7858
7702
|
return {
|
|
7859
7703
|
content,
|
|
7860
7704
|
confidence: clampNumber(candidate.confidence, 0.6, 0, 1),
|
|
@@ -7866,8 +7710,7 @@ function normalizeCandidate2(candidate) {
|
|
|
7866
7710
|
}
|
|
7867
7711
|
function normalizeObservationContent(content) {
|
|
7868
7712
|
const normalized = content.replace(/\s+/g, " ").trim();
|
|
7869
|
-
if (!normalized)
|
|
7870
|
-
return null;
|
|
7713
|
+
if (!normalized) return null;
|
|
7871
7714
|
return normalized.slice(0, MAX_OBSERVATION_CONTENT_CHARS);
|
|
7872
7715
|
}
|
|
7873
7716
|
function normalizeOptionalString2(value) {
|
|
@@ -7875,13 +7718,11 @@ function normalizeOptionalString2(value) {
|
|
|
7875
7718
|
return normalized.length > 0 ? normalized : void 0;
|
|
7876
7719
|
}
|
|
7877
7720
|
function clampNumber(value, fallback, min, max) {
|
|
7878
|
-
if (!Number.isFinite(value))
|
|
7879
|
-
return fallback;
|
|
7721
|
+
if (!Number.isFinite(value)) return fallback;
|
|
7880
7722
|
return Math.max(min, Math.min(max, Number(value)));
|
|
7881
7723
|
}
|
|
7882
7724
|
function sanitizeCandidateMetadata(metadata) {
|
|
7883
|
-
if (!metadata)
|
|
7884
|
-
return void 0;
|
|
7725
|
+
if (!metadata) return void 0;
|
|
7885
7726
|
const result = {};
|
|
7886
7727
|
for (const [key, value] of Object.entries(metadata)) {
|
|
7887
7728
|
if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
|
|
@@ -7894,12 +7735,9 @@ function selectObservers(members, observedActorId, maxObservers) {
|
|
|
7894
7735
|
const selected = [];
|
|
7895
7736
|
for (const member of members) {
|
|
7896
7737
|
const canObserve = member.actorId === observedActorId ? member.observeSelf : member.observeOthers;
|
|
7897
|
-
if (!canObserve)
|
|
7898
|
-
|
|
7899
|
-
if (
|
|
7900
|
-
selected.push(member.actorId);
|
|
7901
|
-
if (selected.length >= maxObservers)
|
|
7902
|
-
break;
|
|
7738
|
+
if (!canObserve) continue;
|
|
7739
|
+
if (!selected.includes(member.actorId)) selected.push(member.actorId);
|
|
7740
|
+
if (selected.length >= maxObservers) break;
|
|
7903
7741
|
}
|
|
7904
7742
|
return selected;
|
|
7905
7743
|
}
|
|
@@ -7935,6 +7773,7 @@ var VectorStore = class {
|
|
|
7935
7773
|
constructor(dbPath) {
|
|
7936
7774
|
this.dbPath = dbPath;
|
|
7937
7775
|
}
|
|
7776
|
+
dbPath;
|
|
7938
7777
|
db = null;
|
|
7939
7778
|
tableCache = /* @__PURE__ */ new Map();
|
|
7940
7779
|
defaultTableName = "conversations";
|
|
@@ -7946,8 +7785,7 @@ var VectorStore = class {
|
|
|
7946
7785
|
* conversations table.
|
|
7947
7786
|
*/
|
|
7948
7787
|
async initialize() {
|
|
7949
|
-
if (this.db)
|
|
7950
|
-
return;
|
|
7788
|
+
if (this.db) return;
|
|
7951
7789
|
this.db = await lancedb.connect(this.dbPath);
|
|
7952
7790
|
}
|
|
7953
7791
|
/**
|
|
@@ -7961,8 +7799,7 @@ var VectorStore = class {
|
|
|
7961
7799
|
* Add or update multiple vector records in batch, grouped by inferred table.
|
|
7962
7800
|
*/
|
|
7963
7801
|
async upsertBatch(records) {
|
|
7964
|
-
if (records.length === 0)
|
|
7965
|
-
return;
|
|
7802
|
+
if (records.length === 0) return;
|
|
7966
7803
|
await this.initialize();
|
|
7967
7804
|
if (!this.db) {
|
|
7968
7805
|
throw new Error("Database not initialized");
|
|
@@ -8017,8 +7854,7 @@ var VectorStore = class {
|
|
|
8017
7854
|
async delete(eventId) {
|
|
8018
7855
|
await this.initialize();
|
|
8019
7856
|
const table = await this.getExistingTable(this.defaultTableName);
|
|
8020
|
-
if (!table)
|
|
8021
|
-
return;
|
|
7857
|
+
if (!table) return;
|
|
8022
7858
|
await table.delete(`eventId = ${toLanceSqlString(eventId)}`);
|
|
8023
7859
|
}
|
|
8024
7860
|
/**
|
|
@@ -8027,8 +7863,7 @@ var VectorStore = class {
|
|
|
8027
7863
|
async count() {
|
|
8028
7864
|
await this.initialize();
|
|
8029
7865
|
const table = await this.getExistingTable(this.defaultTableName);
|
|
8030
|
-
if (!table)
|
|
8031
|
-
return 0;
|
|
7866
|
+
if (!table) return 0;
|
|
8032
7867
|
const result = await table.countRows();
|
|
8033
7868
|
return result;
|
|
8034
7869
|
}
|
|
@@ -8037,8 +7872,7 @@ var VectorStore = class {
|
|
|
8037
7872
|
*/
|
|
8038
7873
|
async clearAll() {
|
|
8039
7874
|
await this.initialize();
|
|
8040
|
-
if (!this.db)
|
|
8041
|
-
return;
|
|
7875
|
+
if (!this.db) return;
|
|
8042
7876
|
try {
|
|
8043
7877
|
if (typeof this.db.dropTable === "function") {
|
|
8044
7878
|
await this.db.dropTable(this.defaultTableName);
|
|
@@ -8055,8 +7889,7 @@ var VectorStore = class {
|
|
|
8055
7889
|
async exists(eventId) {
|
|
8056
7890
|
await this.initialize();
|
|
8057
7891
|
const table = await this.getExistingTable(this.defaultTableName);
|
|
8058
|
-
if (!table)
|
|
8059
|
-
return false;
|
|
7892
|
+
if (!table) return false;
|
|
8060
7893
|
const results = await table.search([]).where(`eventId = ${toLanceSqlString(eventId)}`).limit(1).toArray();
|
|
8061
7894
|
return results.length > 0;
|
|
8062
7895
|
}
|
|
@@ -8091,8 +7924,7 @@ var VectorStore = class {
|
|
|
8091
7924
|
throw new Error("Database not initialized");
|
|
8092
7925
|
}
|
|
8093
7926
|
const cached = this.tableCache.get(tableName);
|
|
8094
|
-
if (cached)
|
|
8095
|
-
return cached;
|
|
7927
|
+
if (cached) return cached;
|
|
8096
7928
|
const tableNames = await this.db.tableNames();
|
|
8097
7929
|
if (!tableNames.includes(tableName)) {
|
|
8098
7930
|
return null;
|
|
@@ -8171,12 +8003,9 @@ var IngestInterceptorRegistry = class {
|
|
|
8171
8003
|
}
|
|
8172
8004
|
};
|
|
8173
8005
|
function mergeHierarchicalMetadata(base, patch) {
|
|
8174
|
-
if (!base && !patch)
|
|
8175
|
-
|
|
8176
|
-
if (!base
|
|
8177
|
-
return patch;
|
|
8178
|
-
if (!patch)
|
|
8179
|
-
return base;
|
|
8006
|
+
if (!base && !patch) return void 0;
|
|
8007
|
+
if (!base) return patch;
|
|
8008
|
+
if (!patch) return base;
|
|
8180
8009
|
const result = { ...base };
|
|
8181
8010
|
for (const [key, value] of Object.entries(patch)) {
|
|
8182
8011
|
const current = result[key];
|
|
@@ -8206,33 +8035,26 @@ var VALID_TAG_NAMESPACES = new Set(Object.values(TAG_NAMESPACES));
|
|
|
8206
8035
|
function parseTag(tag) {
|
|
8207
8036
|
const value = (tag || "").trim();
|
|
8208
8037
|
const idx = value.indexOf(":");
|
|
8209
|
-
if (idx <= 0)
|
|
8210
|
-
return { value };
|
|
8038
|
+
if (idx <= 0) return { value };
|
|
8211
8039
|
const namespace = `${value.slice(0, idx)}:`;
|
|
8212
8040
|
const tagValue = value.slice(idx + 1);
|
|
8213
|
-
if (!tagValue)
|
|
8214
|
-
return { value };
|
|
8041
|
+
if (!tagValue) return { value };
|
|
8215
8042
|
return { namespace, value: tagValue };
|
|
8216
8043
|
}
|
|
8217
8044
|
function validateTag(tag) {
|
|
8218
8045
|
const normalized = (tag || "").trim();
|
|
8219
|
-
if (!normalized)
|
|
8220
|
-
return false;
|
|
8046
|
+
if (!normalized) return false;
|
|
8221
8047
|
const { namespace } = parseTag(normalized);
|
|
8222
|
-
if (!namespace)
|
|
8223
|
-
return true;
|
|
8048
|
+
if (!namespace) return true;
|
|
8224
8049
|
return VALID_TAG_NAMESPACES.has(namespace);
|
|
8225
8050
|
}
|
|
8226
8051
|
function normalizeTags(tags) {
|
|
8227
|
-
if (!Array.isArray(tags))
|
|
8228
|
-
return [];
|
|
8052
|
+
if (!Array.isArray(tags)) return [];
|
|
8229
8053
|
const dedup = /* @__PURE__ */ new Set();
|
|
8230
8054
|
for (const item of tags) {
|
|
8231
|
-
if (typeof item !== "string")
|
|
8232
|
-
continue;
|
|
8055
|
+
if (typeof item !== "string") continue;
|
|
8233
8056
|
const normalized = item.trim();
|
|
8234
|
-
if (!validateTag(normalized))
|
|
8235
|
-
continue;
|
|
8057
|
+
if (!validateTag(normalized)) continue;
|
|
8236
8058
|
dedup.add(normalized);
|
|
8237
8059
|
}
|
|
8238
8060
|
return [...dedup];
|
|
@@ -8249,10 +8071,8 @@ var SummaryDeriver = class {
|
|
|
8249
8071
|
* orchestration, while this class owns summary text and metadata decisions.
|
|
8250
8072
|
*/
|
|
8251
8073
|
deriveSessionSummary(events) {
|
|
8252
|
-
if (events.length < 3)
|
|
8253
|
-
|
|
8254
|
-
if (events.some((event) => event.eventType === "session_summary"))
|
|
8255
|
-
return null;
|
|
8074
|
+
if (events.length < 3) return null;
|
|
8075
|
+
if (events.some((event) => event.eventType === "session_summary")) return null;
|
|
8256
8076
|
const prompts = events.filter((event) => event.eventType === "user_prompt");
|
|
8257
8077
|
const toolObservations = events.filter((event) => event.eventType === "tool_observation");
|
|
8258
8078
|
const toolNames = Array.from(new Set(
|
|
@@ -8400,8 +8220,7 @@ var MemoryIngestService = class {
|
|
|
8400
8220
|
await this.initialize();
|
|
8401
8221
|
const events = await this.eventStore.getSessionEvents(sessionId);
|
|
8402
8222
|
const summary = this.summaryDeriver.deriveSessionSummary(events);
|
|
8403
|
-
if (!summary)
|
|
8404
|
-
return;
|
|
8223
|
+
if (!summary) return;
|
|
8405
8224
|
await this.storeSessionSummary(sessionId, summary.text, summary.metadata);
|
|
8406
8225
|
}
|
|
8407
8226
|
async storeToolObservation(sessionId, payload) {
|
|
@@ -8469,10 +8288,8 @@ var MemoryIngestService = class {
|
|
|
8469
8288
|
}
|
|
8470
8289
|
}
|
|
8471
8290
|
async runPerspectiveDeriver(input, eventId, operation) {
|
|
8472
|
-
if (!this.perspectiveDeriver)
|
|
8473
|
-
|
|
8474
|
-
if (operation !== "user_prompt" && operation !== "agent_response")
|
|
8475
|
-
return;
|
|
8291
|
+
if (!this.perspectiveDeriver) return;
|
|
8292
|
+
if (operation !== "user_prompt" && operation !== "agent_response") return;
|
|
8476
8293
|
const event = {
|
|
8477
8294
|
id: eventId,
|
|
8478
8295
|
eventType: input.eventType,
|
|
@@ -8542,11 +8359,13 @@ var MemoryQueryService = class {
|
|
|
8542
8359
|
this.queryStore = queryStore;
|
|
8543
8360
|
this.deps = deps;
|
|
8544
8361
|
}
|
|
8362
|
+
initialize;
|
|
8363
|
+
queryStore;
|
|
8364
|
+
deps;
|
|
8545
8365
|
async keywordSearch(query, options) {
|
|
8546
8366
|
await this.initialize();
|
|
8547
8367
|
const results = await this.queryStore.keywordSearch(query, options?.topK ?? 10);
|
|
8548
|
-
if (results.length === 0)
|
|
8549
|
-
return [];
|
|
8368
|
+
if (results.length === 0) return [];
|
|
8550
8369
|
const maxRank = Math.min(...results.map((r) => r.rank), -1e-3);
|
|
8551
8370
|
const minRank = Math.max(...results.map((r) => r.rank), -1e3);
|
|
8552
8371
|
const rankRange = maxRank - minRank || 1;
|
|
@@ -8792,55 +8611,42 @@ var LOW_INFORMATION_QUERY_TERMS = /* @__PURE__ */ new Set([
|
|
|
8792
8611
|
]);
|
|
8793
8612
|
function isCommandArtifactQuery(query) {
|
|
8794
8613
|
const trimmed = query.trim();
|
|
8795
|
-
if (!trimmed)
|
|
8796
|
-
return false;
|
|
8614
|
+
if (!trimmed) return false;
|
|
8797
8615
|
const normalized = trimmed.toLowerCase();
|
|
8798
|
-
if (normalized.includes("local-command-stdout") || normalized.includes("local-command-stderr"))
|
|
8799
|
-
|
|
8800
|
-
if (normalized.includes("command-name") || normalized.includes("command-message"))
|
|
8801
|
-
return true;
|
|
8616
|
+
if (normalized.includes("local-command-stdout") || normalized.includes("local-command-stderr")) return true;
|
|
8617
|
+
if (normalized.includes("command-name") || normalized.includes("command-message")) return true;
|
|
8802
8618
|
return COMMAND_ARTIFACT_PATTERNS.some((pattern) => pattern.test(trimmed));
|
|
8803
8619
|
}
|
|
8804
8620
|
function isGenericContinuationQuery(query) {
|
|
8805
8621
|
const trimmed = query.trim();
|
|
8806
|
-
if (!trimmed)
|
|
8807
|
-
|
|
8808
|
-
if (
|
|
8809
|
-
return false;
|
|
8810
|
-
if (extractTechnicalQueryTerms(trimmed).length > 0)
|
|
8811
|
-
return false;
|
|
8622
|
+
if (!trimmed) return false;
|
|
8623
|
+
if (!CONTINUATION_QUERY_PATTERNS.some((pattern) => pattern.test(trimmed))) return false;
|
|
8624
|
+
if (extractTechnicalQueryTerms(trimmed).length > 0) return false;
|
|
8812
8625
|
const tokens = trimmed.match(/[A-Za-z0-9가-힣#._/-]+/g) ?? [];
|
|
8813
|
-
if (tokens.length > 10)
|
|
8814
|
-
return false;
|
|
8626
|
+
if (tokens.length > 10) return false;
|
|
8815
8627
|
return !/[A-Za-z0-9_-]+\.[A-Za-z0-9]+/.test(trimmed) && !/(?:^|\s)(?:feat|fix|chore|refactor|docs)\/[A-Za-z0-9._-]+/.test(trimmed) && !/[A-Za-z]:?[\\/]|\/Users\/|\.\/|\.\.\//.test(trimmed);
|
|
8816
8628
|
}
|
|
8817
8629
|
function isShortRepairFollowUpQuery(query) {
|
|
8818
8630
|
const trimmed = query.trim();
|
|
8819
|
-
if (!trimmed)
|
|
8820
|
-
|
|
8821
|
-
if (extractTechnicalQueryTerms(trimmed).length > 0)
|
|
8822
|
-
return false;
|
|
8631
|
+
if (!trimmed) return false;
|
|
8632
|
+
if (extractTechnicalQueryTerms(trimmed).length > 0) return false;
|
|
8823
8633
|
const tokens = trimmed.match(/[A-Za-z0-9가-힣#._/-]+/g) ?? [];
|
|
8824
|
-
if (tokens.length > 8)
|
|
8825
|
-
return false;
|
|
8634
|
+
if (tokens.length > 8) return false;
|
|
8826
8635
|
return SHORT_REPAIR_FOLLOW_UP_PATTERNS.some((pattern) => pattern.test(trimmed));
|
|
8827
8636
|
}
|
|
8828
8637
|
function isCurrentStateQuery(query) {
|
|
8829
8638
|
const trimmed = query.trim();
|
|
8830
|
-
if (!trimmed)
|
|
8831
|
-
return false;
|
|
8639
|
+
if (!trimmed) return false;
|
|
8832
8640
|
return CURRENT_STATE_QUERY_PATTERNS.some((pattern) => pattern.test(trimmed));
|
|
8833
8641
|
}
|
|
8834
8642
|
function isStaleOrSupersededContent(content) {
|
|
8835
8643
|
const trimmed = content.trim();
|
|
8836
|
-
if (!trimmed)
|
|
8837
|
-
return false;
|
|
8644
|
+
if (!trimmed) return false;
|
|
8838
8645
|
return STALE_CONTENT_PATTERNS.some((pattern) => pattern.test(trimmed));
|
|
8839
8646
|
}
|
|
8840
8647
|
function buildRetrievalQualityQuery(query) {
|
|
8841
8648
|
const trimmed = query.trim();
|
|
8842
|
-
if (!trimmed)
|
|
8843
|
-
return query;
|
|
8649
|
+
if (!trimmed) return query;
|
|
8844
8650
|
if (isRetrievalPrivacyDecisionQuery(trimmed)) {
|
|
8845
8651
|
return `${trimmed} ${RETRIEVAL_PRIVACY_DECISION_EXPANSION}`;
|
|
8846
8652
|
}
|
|
@@ -8854,12 +8660,10 @@ function buildRetrievalQualityQuery(query) {
|
|
|
8854
8660
|
}
|
|
8855
8661
|
function isRetrievalPrivacyDecisionQuery(query) {
|
|
8856
8662
|
const trimmed = query.trim();
|
|
8857
|
-
if (!trimmed)
|
|
8858
|
-
return false;
|
|
8663
|
+
if (!trimmed) return false;
|
|
8859
8664
|
const terms = new Set(tokenizeQualityText(trimmed));
|
|
8860
8665
|
const hasDecisionSignal = hasAnyTerm(terms, DECISION_RECALL_TERMS) || /(?:결정|정책|원칙)/i.test(trimmed);
|
|
8861
|
-
if (!hasDecisionSignal)
|
|
8862
|
-
return false;
|
|
8666
|
+
if (!hasDecisionSignal) return false;
|
|
8863
8667
|
const hasRawQuerySignal = terms.has("raw") && terms.has("query");
|
|
8864
8668
|
const hasPrivacySignal = terms.has("privacy") || terms.has("expose") || terms.has("redacted");
|
|
8865
8669
|
const hasRetrievalSurface = hasAnyTerm(terms, RETRIEVAL_PRIVACY_SURFACE_TERMS) || terms.has("api") && terms.has("query");
|
|
@@ -8872,16 +8676,14 @@ function extractTechnicalQueryTerms(query) {
|
|
|
8872
8676
|
const matches = query.match(/[A-Za-z][A-Za-z0-9_.:-]{2,}/g) ?? [];
|
|
8873
8677
|
const terms = matches.filter((term) => {
|
|
8874
8678
|
const lower = term.toLowerCase();
|
|
8875
|
-
if (GENERIC_TECHNICAL_TERMS.has(lower))
|
|
8876
|
-
return false;
|
|
8679
|
+
if (GENERIC_TECHNICAL_TERMS.has(lower)) return false;
|
|
8877
8680
|
return /[._:-]/.test(term) || /[a-z][A-Z]/.test(term) || /[A-Z]{2,}/.test(term) || /\d/.test(term);
|
|
8878
8681
|
});
|
|
8879
8682
|
return Array.from(new Set(terms.map((term) => term.toLowerCase())));
|
|
8880
8683
|
}
|
|
8881
8684
|
function hasTechnicalTermOverlap(query, content) {
|
|
8882
8685
|
const terms = extractTechnicalQueryTerms(query);
|
|
8883
|
-
if (terms.length === 0)
|
|
8884
|
-
return true;
|
|
8686
|
+
if (terms.length === 0) return true;
|
|
8885
8687
|
const normalizedContent = content.toLowerCase();
|
|
8886
8688
|
return terms.some((term) => normalizedContent.includes(term));
|
|
8887
8689
|
}
|
|
@@ -8897,15 +8699,12 @@ function hasDiscriminativeTermOverlap(query, content) {
|
|
|
8897
8699
|
return topicTerms.some((term) => contentTerms.has(term));
|
|
8898
8700
|
}
|
|
8899
8701
|
}
|
|
8900
|
-
if (queryTerms.length < 3)
|
|
8901
|
-
return true;
|
|
8702
|
+
if (queryTerms.length < 3) return true;
|
|
8902
8703
|
const requiredHits = queryTerms.length >= 3 ? 2 : 1;
|
|
8903
8704
|
let hits = 0;
|
|
8904
8705
|
for (const term of queryTerms) {
|
|
8905
|
-
if (contentTerms.has(term))
|
|
8906
|
-
|
|
8907
|
-
if (hits >= requiredHits)
|
|
8908
|
-
return true;
|
|
8706
|
+
if (contentTerms.has(term)) hits += 1;
|
|
8707
|
+
if (hits >= requiredHits) return true;
|
|
8909
8708
|
}
|
|
8910
8709
|
return false;
|
|
8911
8710
|
}
|
|
@@ -8915,17 +8714,14 @@ function shouldApplyTechnicalGuard(query) {
|
|
|
8915
8714
|
function hasAnyTerm(terms, expectedTerms) {
|
|
8916
8715
|
let found = false;
|
|
8917
8716
|
expectedTerms.forEach((term) => {
|
|
8918
|
-
if (terms.has(term))
|
|
8919
|
-
found = true;
|
|
8717
|
+
if (terms.has(term)) found = true;
|
|
8920
8718
|
});
|
|
8921
8719
|
return found;
|
|
8922
8720
|
}
|
|
8923
8721
|
function shouldRequireDecisionTopicOverlap(query) {
|
|
8924
|
-
if (isRetrievalPrivacyDecisionQuery(query))
|
|
8925
|
-
return false;
|
|
8722
|
+
if (isRetrievalPrivacyDecisionQuery(query)) return false;
|
|
8926
8723
|
const trimmed = query.trim();
|
|
8927
|
-
if (!trimmed)
|
|
8928
|
-
return false;
|
|
8724
|
+
if (!trimmed) return false;
|
|
8929
8725
|
const terms = new Set(tokenizeQualityText(trimmed));
|
|
8930
8726
|
return hasAnyTerm(terms, DECISION_RECALL_TERMS) || /(?:결정|정책|원칙)/i.test(trimmed);
|
|
8931
8727
|
}
|
|
@@ -8933,12 +8729,9 @@ function extractDiscriminativeQueryTerms(query) {
|
|
|
8933
8729
|
const seen = /* @__PURE__ */ new Set();
|
|
8934
8730
|
const terms = [];
|
|
8935
8731
|
for (const token of tokenizeQualityText(query)) {
|
|
8936
|
-
if (LOW_INFORMATION_QUERY_TERMS.has(token))
|
|
8937
|
-
|
|
8938
|
-
if (
|
|
8939
|
-
continue;
|
|
8940
|
-
if (seen.has(token))
|
|
8941
|
-
continue;
|
|
8732
|
+
if (LOW_INFORMATION_QUERY_TERMS.has(token)) continue;
|
|
8733
|
+
if (GENERIC_TECHNICAL_TERMS.has(token)) continue;
|
|
8734
|
+
if (seen.has(token)) continue;
|
|
8942
8735
|
seen.add(token);
|
|
8943
8736
|
terms.push(token);
|
|
8944
8737
|
}
|
|
@@ -8953,14 +8746,10 @@ function tokenizeQualityText(text) {
|
|
|
8953
8746
|
return text.replace(/([a-z])([A-Z])/g, "$1 $2").toLowerCase().replace(/[^A-Za-z0-9가-힣\s_.:-]/g, " ").split(/\s+/).flatMap((token) => token.split(/(?=[._:-])|(?<=[._:-])/g)).map((token) => normalizeQualityToken(token.replace(/^[._:-]+|[._:-]+$/g, ""))).filter((token) => token.length >= 2);
|
|
8954
8747
|
}
|
|
8955
8748
|
function normalizeQualityToken(token) {
|
|
8956
|
-
if (token === "apis")
|
|
8957
|
-
|
|
8958
|
-
if (token
|
|
8959
|
-
|
|
8960
|
-
if (LOW_INFORMATION_QUERY_TERMS.has(token) || GENERIC_TECHNICAL_TERMS.has(token))
|
|
8961
|
-
return token;
|
|
8962
|
-
if (token.length > 4 && token.endsWith("ies"))
|
|
8963
|
-
return `${token.slice(0, -3)}y`;
|
|
8749
|
+
if (token === "apis") return "api";
|
|
8750
|
+
if (token === "ids") return "id";
|
|
8751
|
+
if (LOW_INFORMATION_QUERY_TERMS.has(token) || GENERIC_TECHNICAL_TERMS.has(token)) return token;
|
|
8752
|
+
if (token.length > 4 && token.endsWith("ies")) return `${token.slice(0, -3)}y`;
|
|
8964
8753
|
if (token.length > 3 && token.endsWith("s") && !token.endsWith("ss") && !token.endsWith("us") && !token.endsWith("is")) {
|
|
8965
8754
|
return token.slice(0, -1);
|
|
8966
8755
|
}
|
|
@@ -9142,8 +8931,7 @@ var Retriever = class {
|
|
|
9142
8931
|
const sharedMemories = [];
|
|
9143
8932
|
for (const result of sharedVectorResults) {
|
|
9144
8933
|
const entry = await this.sharedStore.get(result.entryId);
|
|
9145
|
-
if (!entry)
|
|
9146
|
-
continue;
|
|
8934
|
+
if (!entry) continue;
|
|
9147
8935
|
if (!options.projectHash || entry.sourceProjectHash !== options.projectHash) {
|
|
9148
8936
|
sharedMemories.push(entry);
|
|
9149
8937
|
await this.sharedStore.recordUsage(entry.entryId);
|
|
@@ -9224,18 +9012,15 @@ var Retriever = class {
|
|
|
9224
9012
|
(result) => this.isGraphPathResult(result) || hasTechnicalTermOverlap(options.query, result.content)
|
|
9225
9013
|
);
|
|
9226
9014
|
}
|
|
9227
|
-
if (filtered.length <= 2)
|
|
9228
|
-
return filtered;
|
|
9015
|
+
if (filtered.length <= 2) return filtered;
|
|
9229
9016
|
const topScore = filtered[0].score;
|
|
9230
|
-
if (topScore < 0.8)
|
|
9231
|
-
return filtered;
|
|
9017
|
+
if (topScore < 0.8) return filtered;
|
|
9232
9018
|
const cliffThreshold = Math.max(options.minScore, topScore - 0.25);
|
|
9233
9019
|
return filtered.filter((result) => result.score >= cliffThreshold);
|
|
9234
9020
|
}
|
|
9235
9021
|
mergeResults(primary, secondary, limit) {
|
|
9236
9022
|
const byId = /* @__PURE__ */ new Map();
|
|
9237
|
-
for (const row of primary)
|
|
9238
|
-
byId.set(row.eventId, row);
|
|
9023
|
+
for (const row of primary) byId.set(row.eventId, row);
|
|
9239
9024
|
for (const row of secondary) {
|
|
9240
9025
|
const prev = byId.get(row.eventId);
|
|
9241
9026
|
if (!prev || row.score > prev.score) {
|
|
@@ -9246,23 +9031,19 @@ var Retriever = class {
|
|
|
9246
9031
|
}
|
|
9247
9032
|
async expandGraphHops(seeds, opts) {
|
|
9248
9033
|
const byId = /* @__PURE__ */ new Map();
|
|
9249
|
-
for (const s of seeds)
|
|
9250
|
-
byId.set(s.eventId, s);
|
|
9034
|
+
for (const s of seeds) byId.set(s.eventId, s);
|
|
9251
9035
|
let frontier = seeds.map((s) => ({ row: s, hop: 0 }));
|
|
9252
9036
|
for (let hop = 1; hop <= opts.maxHops; hop += 1) {
|
|
9253
9037
|
const next = [];
|
|
9254
9038
|
for (const f of frontier) {
|
|
9255
9039
|
const ev = await this.eventStore.getEvent(f.row.eventId);
|
|
9256
|
-
if (!ev)
|
|
9257
|
-
continue;
|
|
9040
|
+
if (!ev) continue;
|
|
9258
9041
|
const rel = ev.metadata?.relatedEventIds ?? [];
|
|
9259
9042
|
const relatedIds = Array.isArray(rel) ? rel.filter((x) => typeof x === "string") : [];
|
|
9260
9043
|
for (const rid of relatedIds) {
|
|
9261
|
-
if (byId.has(rid))
|
|
9262
|
-
continue;
|
|
9044
|
+
if (byId.has(rid)) continue;
|
|
9263
9045
|
const target = await this.eventStore.getEvent(rid);
|
|
9264
|
-
if (!target)
|
|
9265
|
-
continue;
|
|
9046
|
+
if (!target) continue;
|
|
9266
9047
|
const score = Math.max(0, f.row.score - opts.hopPenalty * hop);
|
|
9267
9048
|
const row = {
|
|
9268
9049
|
id: `hop-${hop}-${rid}`,
|
|
@@ -9276,15 +9057,12 @@ var Retriever = class {
|
|
|
9276
9057
|
};
|
|
9277
9058
|
byId.set(row.eventId, row);
|
|
9278
9059
|
next.push({ row, hop });
|
|
9279
|
-
if (byId.size >= opts.limit)
|
|
9280
|
-
break;
|
|
9060
|
+
if (byId.size >= opts.limit) break;
|
|
9281
9061
|
}
|
|
9282
|
-
if (byId.size >= opts.limit)
|
|
9283
|
-
break;
|
|
9062
|
+
if (byId.size >= opts.limit) break;
|
|
9284
9063
|
}
|
|
9285
9064
|
frontier = next;
|
|
9286
|
-
if (frontier.length === 0 || byId.size >= opts.limit)
|
|
9287
|
-
break;
|
|
9065
|
+
if (frontier.length === 0 || byId.size >= opts.limit) break;
|
|
9288
9066
|
}
|
|
9289
9067
|
if (opts.queryGraphEnabled) {
|
|
9290
9068
|
await this.expandQueryGraphPaths(opts.query, byId, opts);
|
|
@@ -9292,8 +9070,7 @@ var Retriever = class {
|
|
|
9292
9070
|
return [...byId.values()].sort((a, b) => b.score - a.score || compareStable(a.eventId, b.eventId)).slice(0, opts.limit);
|
|
9293
9071
|
}
|
|
9294
9072
|
async expandQueryGraphPaths(query, byId, opts) {
|
|
9295
|
-
if (!query.trim() || !this.eventStore.getDatabase)
|
|
9296
|
-
return;
|
|
9073
|
+
if (!query.trim() || !this.eventStore.getDatabase) return;
|
|
9297
9074
|
try {
|
|
9298
9075
|
const db = this.eventStore.getDatabase();
|
|
9299
9076
|
const extraction = new QueryEntityExtractor(db).extract(query, {
|
|
@@ -9302,8 +9079,7 @@ var Retriever = class {
|
|
|
9302
9079
|
});
|
|
9303
9080
|
const startCandidates = extraction.candidates.filter((candidate) => candidate.entityId).slice(0, 8);
|
|
9304
9081
|
const startNodes = uniqueEntityStartNodes(startCandidates);
|
|
9305
|
-
if (startNodes.length === 0)
|
|
9306
|
-
return;
|
|
9082
|
+
if (startNodes.length === 0) return;
|
|
9307
9083
|
const expansion = new GraphPathService(db).expand({
|
|
9308
9084
|
startNodes: startNodes.map((node) => ({ type: "entity", id: node.entityId })),
|
|
9309
9085
|
maxHops: opts.maxHops,
|
|
@@ -9312,11 +9088,9 @@ var Retriever = class {
|
|
|
9312
9088
|
});
|
|
9313
9089
|
const titleByEntityId = new Map(startNodes.map((node) => [node.entityId, node.title]));
|
|
9314
9090
|
for (const path14 of expansion.paths) {
|
|
9315
|
-
if (path14.target.type !== "event")
|
|
9316
|
-
continue;
|
|
9091
|
+
if (path14.target.type !== "event") continue;
|
|
9317
9092
|
const target = await this.eventStore.getEvent(path14.target.id);
|
|
9318
|
-
if (!target)
|
|
9319
|
-
continue;
|
|
9093
|
+
if (!target) continue;
|
|
9320
9094
|
const graphPath = toRetrievalGraphPathDebug(path14, titleByEntityId);
|
|
9321
9095
|
const score = graphPathScore(path14, opts.hopPenalty);
|
|
9322
9096
|
const existing = byId.get(target.id);
|
|
@@ -9342,17 +9116,14 @@ var Retriever = class {
|
|
|
9342
9116
|
lanes: mergeRetrievalLanes(existing?.lanes ?? [], [graphLane])
|
|
9343
9117
|
};
|
|
9344
9118
|
byId.set(row.eventId, row);
|
|
9345
|
-
if (byId.size >= opts.limit)
|
|
9346
|
-
break;
|
|
9119
|
+
if (byId.size >= opts.limit) break;
|
|
9347
9120
|
}
|
|
9348
9121
|
} catch {
|
|
9349
9122
|
}
|
|
9350
9123
|
}
|
|
9351
9124
|
shouldFallback(matchResult, results) {
|
|
9352
|
-
if (results.length === 0)
|
|
9353
|
-
|
|
9354
|
-
if (matchResult.confidence === "none")
|
|
9355
|
-
return true;
|
|
9125
|
+
if (results.length === 0) return true;
|
|
9126
|
+
if (matchResult.confidence === "none") return true;
|
|
9356
9127
|
return false;
|
|
9357
9128
|
}
|
|
9358
9129
|
async buildSummaryFallback(query, topK) {
|
|
@@ -9457,29 +9228,21 @@ var Retriever = class {
|
|
|
9457
9228
|
(value) => typeof value === "string" && value.length > 0
|
|
9458
9229
|
)
|
|
9459
9230
|
);
|
|
9460
|
-
if (!scope && projectScopeMode === "global" && facetFilters === null)
|
|
9461
|
-
return results;
|
|
9231
|
+
if (!scope && projectScopeMode === "global" && facetFilters === null) return results;
|
|
9462
9232
|
const normalizedIncludes = (scope?.contentIncludes || []).map((s) => s.toLowerCase());
|
|
9463
9233
|
const filtered = [];
|
|
9464
9234
|
for (const result of results) {
|
|
9465
|
-
if (scope?.sessionId && result.sessionId !== scope.sessionId)
|
|
9466
|
-
|
|
9467
|
-
if (scope?.
|
|
9468
|
-
continue;
|
|
9469
|
-
if (scope?.eventTypes && scope.eventTypes.length > 0 && !scope.eventTypes.includes(result.eventType))
|
|
9470
|
-
continue;
|
|
9235
|
+
if (scope?.sessionId && result.sessionId !== scope.sessionId) continue;
|
|
9236
|
+
if (scope?.sessionIdPrefix && !result.sessionId.startsWith(scope.sessionIdPrefix)) continue;
|
|
9237
|
+
if (scope?.eventTypes && scope.eventTypes.length > 0 && !scope.eventTypes.includes(result.eventType)) continue;
|
|
9471
9238
|
const event = await this.eventStore.getEvent(result.eventId);
|
|
9472
|
-
if (!event)
|
|
9473
|
-
|
|
9474
|
-
if (scope?.canonicalKeyPrefix && !event.canonicalKey.startsWith(scope.canonicalKeyPrefix))
|
|
9475
|
-
continue;
|
|
9239
|
+
if (!event) continue;
|
|
9240
|
+
if (scope?.canonicalKeyPrefix && !event.canonicalKey.startsWith(scope.canonicalKeyPrefix)) continue;
|
|
9476
9241
|
if (normalizedIncludes.length > 0) {
|
|
9477
9242
|
const lc = event.content.toLowerCase();
|
|
9478
|
-
if (!normalizedIncludes.some((needle) => lc.includes(needle)))
|
|
9479
|
-
continue;
|
|
9243
|
+
if (!normalizedIncludes.some((needle) => lc.includes(needle))) continue;
|
|
9480
9244
|
}
|
|
9481
|
-
if (scope?.metadata && !this.matchesMetadataScope(event.metadata, scope.metadata))
|
|
9482
|
-
continue;
|
|
9245
|
+
if (scope?.metadata && !this.matchesMetadataScope(event.metadata, scope.metadata)) continue;
|
|
9483
9246
|
const projectHash = this.extractProjectHash(event.metadata);
|
|
9484
9247
|
filtered.push({ result, projectHash });
|
|
9485
9248
|
}
|
|
@@ -9496,27 +9259,21 @@ var Retriever = class {
|
|
|
9496
9259
|
});
|
|
9497
9260
|
}
|
|
9498
9261
|
normalizeFacetFilters(facets) {
|
|
9499
|
-
if (!facets || facets.length === 0)
|
|
9500
|
-
return null;
|
|
9262
|
+
if (!facets || facets.length === 0) return null;
|
|
9501
9263
|
const normalized = [];
|
|
9502
9264
|
for (const facet of facets) {
|
|
9503
9265
|
const parsedDimension = FacetDimensionSchema.safeParse(facet.dimension);
|
|
9504
9266
|
const value = typeof facet.value === "string" ? facet.value.trim() : "";
|
|
9505
|
-
if (!parsedDimension.success || !value)
|
|
9506
|
-
return [];
|
|
9267
|
+
if (!parsedDimension.success || !value) return [];
|
|
9507
9268
|
normalized.push({ dimension: parsedDimension.data, value });
|
|
9508
9269
|
}
|
|
9509
9270
|
return normalized;
|
|
9510
9271
|
}
|
|
9511
9272
|
async applyFacetFilters(results, options) {
|
|
9512
|
-
if (options.facets === null)
|
|
9513
|
-
|
|
9514
|
-
if (options.
|
|
9515
|
-
|
|
9516
|
-
if (!options.projectHash)
|
|
9517
|
-
return [];
|
|
9518
|
-
if (!this.eventStore.getDatabase)
|
|
9519
|
-
return [];
|
|
9273
|
+
if (options.facets === null) return results;
|
|
9274
|
+
if (options.facets.length === 0) return [];
|
|
9275
|
+
if (!options.projectHash) return [];
|
|
9276
|
+
if (!this.eventStore.getDatabase) return [];
|
|
9520
9277
|
const repo = new FacetRepository(this.eventStore.getDatabase());
|
|
9521
9278
|
const filtered = [];
|
|
9522
9279
|
for (const result of results) {
|
|
@@ -9573,14 +9330,11 @@ var Retriever = class {
|
|
|
9573
9330
|
return (result.graphPaths || []).length > 0;
|
|
9574
9331
|
}
|
|
9575
9332
|
extractProjectHash(metadata) {
|
|
9576
|
-
if (!metadata || typeof metadata !== "object")
|
|
9577
|
-
return void 0;
|
|
9333
|
+
if (!metadata || typeof metadata !== "object") return void 0;
|
|
9578
9334
|
const scope = metadata.scope;
|
|
9579
|
-
if (!scope || typeof scope !== "object")
|
|
9580
|
-
return void 0;
|
|
9335
|
+
if (!scope || typeof scope !== "object") return void 0;
|
|
9581
9336
|
const project = scope.project;
|
|
9582
|
-
if (!project || typeof project !== "object")
|
|
9583
|
-
return void 0;
|
|
9337
|
+
if (!project || typeof project !== "object") return void 0;
|
|
9584
9338
|
const hash = project.hash;
|
|
9585
9339
|
return typeof hash === "string" && hash.length > 0 ? hash : void 0;
|
|
9586
9340
|
}
|
|
@@ -9594,8 +9348,7 @@ var Retriever = class {
|
|
|
9594
9348
|
const memories = [];
|
|
9595
9349
|
for (const result of results) {
|
|
9596
9350
|
const event = await this.eventStore.getEvent(result.eventId);
|
|
9597
|
-
if (!event)
|
|
9598
|
-
continue;
|
|
9351
|
+
if (!event) continue;
|
|
9599
9352
|
if (this.graduation) {
|
|
9600
9353
|
this.graduation.recordAccess(event.id, options.sessionId || "unknown", result.score);
|
|
9601
9354
|
}
|
|
@@ -9610,32 +9363,27 @@ var Retriever = class {
|
|
|
9610
9363
|
async getSessionContext(sessionId, eventId) {
|
|
9611
9364
|
const sessionEvents = await this.eventStore.getSessionEvents(sessionId);
|
|
9612
9365
|
const eventIndex = sessionEvents.findIndex((e) => e.id === eventId);
|
|
9613
|
-
if (eventIndex === -1)
|
|
9614
|
-
return void 0;
|
|
9366
|
+
if (eventIndex === -1) return void 0;
|
|
9615
9367
|
const start = Math.max(0, eventIndex - 1);
|
|
9616
9368
|
const end = Math.min(sessionEvents.length, eventIndex + 2);
|
|
9617
9369
|
const contextEvents = sessionEvents.slice(start, end);
|
|
9618
|
-
if (contextEvents.length <= 1)
|
|
9619
|
-
return void 0;
|
|
9370
|
+
if (contextEvents.length <= 1) return void 0;
|
|
9620
9371
|
return contextEvents.filter((e) => e.id !== eventId).map((e) => `[${e.eventType}]: ${e.content.slice(0, 200)}...`).join("\n");
|
|
9621
9372
|
}
|
|
9622
9373
|
buildUnifiedContext(projectResult, sharedMemories) {
|
|
9623
9374
|
let context = projectResult.context;
|
|
9624
|
-
if (sharedMemories.length === 0)
|
|
9625
|
-
return context;
|
|
9375
|
+
if (sharedMemories.length === 0) return context;
|
|
9626
9376
|
context += "\n\n## Cross-Project Knowledge\n\n";
|
|
9627
9377
|
for (const memory of sharedMemories.slice(0, 3)) {
|
|
9628
9378
|
context += `### ${memory.title}
|
|
9629
9379
|
`;
|
|
9630
|
-
if (memory.symptoms.length > 0)
|
|
9631
|
-
context += `**Symptoms:** ${memory.symptoms.join(", ")}
|
|
9380
|
+
if (memory.symptoms.length > 0) context += `**Symptoms:** ${memory.symptoms.join(", ")}
|
|
9632
9381
|
`;
|
|
9633
9382
|
context += `**Root Cause:** ${memory.rootCause}
|
|
9634
9383
|
`;
|
|
9635
9384
|
context += `**Solution:** ${memory.solution}
|
|
9636
9385
|
`;
|
|
9637
|
-
if (memory.technologies && memory.technologies.length > 0)
|
|
9638
|
-
context += `**Technologies:** ${memory.technologies.join(", ")}
|
|
9386
|
+
if (memory.technologies && memory.technologies.length > 0) context += `**Technologies:** ${memory.technologies.join(", ")}
|
|
9639
9387
|
`;
|
|
9640
9388
|
context += `_Confidence: ${(memory.confidence * 100).toFixed(0)}%_
|
|
9641
9389
|
|
|
@@ -9649,13 +9397,11 @@ var Retriever = class {
|
|
|
9649
9397
|
for (const memory of memories) {
|
|
9650
9398
|
const memoryText = this.formatMemory(memory);
|
|
9651
9399
|
const memoryTokens = this.estimateTokens(memoryText);
|
|
9652
|
-
if (currentTokens + memoryTokens > maxTokens)
|
|
9653
|
-
break;
|
|
9400
|
+
if (currentTokens + memoryTokens > maxTokens) break;
|
|
9654
9401
|
parts.push(memoryText);
|
|
9655
9402
|
currentTokens += memoryTokens;
|
|
9656
9403
|
}
|
|
9657
|
-
if (parts.length === 0)
|
|
9658
|
-
return "";
|
|
9404
|
+
if (parts.length === 0) return "";
|
|
9659
9405
|
return `## Relevant Memories
|
|
9660
9406
|
|
|
9661
9407
|
${parts.join("\n\n---\n\n")}`;
|
|
@@ -9665,19 +9411,16 @@ ${parts.join("\n\n---\n\n")}`;
|
|
|
9665
9411
|
const date = event.timestamp.toISOString().split("T")[0];
|
|
9666
9412
|
let text = `**${event.eventType}** (${date}, score: ${score.toFixed(2)})
|
|
9667
9413
|
${event.content}`;
|
|
9668
|
-
if (sessionContext)
|
|
9669
|
-
text += `
|
|
9414
|
+
if (sessionContext) text += `
|
|
9670
9415
|
|
|
9671
9416
|
_Context:_ ${sessionContext}`;
|
|
9672
9417
|
return text;
|
|
9673
9418
|
}
|
|
9674
9419
|
matchesMetadataScope(metadata, expected) {
|
|
9675
|
-
if (!metadata)
|
|
9676
|
-
return false;
|
|
9420
|
+
if (!metadata) return false;
|
|
9677
9421
|
return Object.entries(expected).every(([path14, value]) => {
|
|
9678
9422
|
const actual = path14.split(".").reduce((acc, key) => {
|
|
9679
|
-
if (typeof acc !== "object" || acc === null)
|
|
9680
|
-
return void 0;
|
|
9423
|
+
if (typeof acc !== "object" || acc === null) return void 0;
|
|
9681
9424
|
return acc[key];
|
|
9682
9425
|
}, metadata);
|
|
9683
9426
|
return actual === value;
|
|
@@ -9687,27 +9430,20 @@ _Context:_ ${sessionContext}`;
|
|
|
9687
9430
|
return text.replace(/([a-z])([A-Z])/g, "$1 $2").toLowerCase().replace(/[^\p{L}\p{N}\s]/gu, " ").split(/\s+/).map((token) => this.normalizeToken(token)).filter((t) => t.length >= 2).slice(0, 64);
|
|
9688
9431
|
}
|
|
9689
9432
|
normalizeToken(token) {
|
|
9690
|
-
if (token === "apis")
|
|
9691
|
-
|
|
9692
|
-
if (token === "
|
|
9693
|
-
|
|
9694
|
-
if (token === "does")
|
|
9695
|
-
return token;
|
|
9696
|
-
if (token.length > 4 && token.endsWith("ies"))
|
|
9697
|
-
return `${token.slice(0, -3)}y`;
|
|
9433
|
+
if (token === "apis") return "api";
|
|
9434
|
+
if (token === "ids") return "id";
|
|
9435
|
+
if (token === "does") return token;
|
|
9436
|
+
if (token.length > 4 && token.endsWith("ies")) return `${token.slice(0, -3)}y`;
|
|
9698
9437
|
if (token.length > 3 && token.endsWith("s") && !token.endsWith("ss") && !token.endsWith("us") && !token.endsWith("is") && !token.endsWith("ps")) {
|
|
9699
9438
|
return token.slice(0, -1);
|
|
9700
9439
|
}
|
|
9701
9440
|
return token;
|
|
9702
9441
|
}
|
|
9703
9442
|
keywordOverlap(a, b) {
|
|
9704
|
-
if (a.length === 0 || b.length === 0)
|
|
9705
|
-
return 0;
|
|
9443
|
+
if (a.length === 0 || b.length === 0) return 0;
|
|
9706
9444
|
const bs = new Set(b);
|
|
9707
9445
|
let hit = 0;
|
|
9708
|
-
for (const t of a)
|
|
9709
|
-
if (bs.has(t))
|
|
9710
|
-
hit += 1;
|
|
9446
|
+
for (const t of a) if (bs.has(t)) hit += 1;
|
|
9711
9447
|
return hit / a.length;
|
|
9712
9448
|
}
|
|
9713
9449
|
estimateTokens(text) {
|
|
@@ -9728,8 +9464,7 @@ function uniqueEntityStartNodes(candidates) {
|
|
|
9728
9464
|
const seen = /* @__PURE__ */ new Set();
|
|
9729
9465
|
const nodes = [];
|
|
9730
9466
|
for (const candidate of candidates) {
|
|
9731
|
-
if (!candidate.entityId || seen.has(candidate.entityId))
|
|
9732
|
-
continue;
|
|
9467
|
+
if (!candidate.entityId || seen.has(candidate.entityId)) continue;
|
|
9733
9468
|
seen.add(candidate.entityId);
|
|
9734
9469
|
nodes.push({ entityId: candidate.entityId, title: candidate.text });
|
|
9735
9470
|
}
|
|
@@ -9753,16 +9488,14 @@ function graphPathScore(path14, hopPenalty) {
|
|
|
9753
9488
|
return Math.max(0.05, base - hopPenalty * Math.max(0, path14.hops - 1));
|
|
9754
9489
|
}
|
|
9755
9490
|
function clampGraphHops(maxHops) {
|
|
9756
|
-
if (!Number.isFinite(maxHops))
|
|
9757
|
-
return 2;
|
|
9491
|
+
if (!Number.isFinite(maxHops)) return 2;
|
|
9758
9492
|
return Math.min(Math.max(0, Math.trunc(maxHops)), 2);
|
|
9759
9493
|
}
|
|
9760
9494
|
function mergeGraphPaths(existing, incoming) {
|
|
9761
9495
|
const byKey = /* @__PURE__ */ new Map();
|
|
9762
9496
|
for (const path14 of [...existing, ...incoming]) {
|
|
9763
9497
|
const key = [path14.startEntityId, path14.targetType, path14.targetId, path14.hops, ...path14.relationPath].join("\0");
|
|
9764
|
-
if (!byKey.has(key))
|
|
9765
|
-
byKey.set(key, path14);
|
|
9498
|
+
if (!byKey.has(key)) byKey.set(key, path14);
|
|
9766
9499
|
}
|
|
9767
9500
|
return [...byKey.values()].sort((a, b) => a.hops - b.hops || compareStable(graphPathSignature(a), graphPathSignature(b))).slice(0, 3);
|
|
9768
9501
|
}
|
|
@@ -9770,10 +9503,8 @@ function graphPathSignature(path14) {
|
|
|
9770
9503
|
return [path14.startEntityId, path14.targetType, path14.targetId, path14.hops, ...path14.relationPath].join("|");
|
|
9771
9504
|
}
|
|
9772
9505
|
function compareStable(a, b) {
|
|
9773
|
-
if (a < b)
|
|
9774
|
-
|
|
9775
|
-
if (a > b)
|
|
9776
|
-
return 1;
|
|
9506
|
+
if (a < b) return -1;
|
|
9507
|
+
if (a > b) return 1;
|
|
9777
9508
|
return 0;
|
|
9778
9509
|
}
|
|
9779
9510
|
function createRetriever(eventStore, vectorStore, embedder, matcher, sharedOptions) {
|
|
@@ -9785,6 +9516,7 @@ var RetrievalAnalyticsService = class {
|
|
|
9785
9516
|
constructor(deps) {
|
|
9786
9517
|
this.deps = deps;
|
|
9787
9518
|
}
|
|
9519
|
+
deps;
|
|
9788
9520
|
async getRetrievalTraceStats() {
|
|
9789
9521
|
await this.deps.initialize();
|
|
9790
9522
|
return this.deps.retrievalStore.getRetrievalTraceStats();
|
|
@@ -9862,6 +9594,7 @@ var RetrievalDisclosureService = class {
|
|
|
9862
9594
|
constructor(deps) {
|
|
9863
9595
|
this.deps = deps;
|
|
9864
9596
|
}
|
|
9597
|
+
deps;
|
|
9865
9598
|
async search(query, options) {
|
|
9866
9599
|
const result = await this.deps.retrievalOrchestrator.retrieveMemories(query, options);
|
|
9867
9600
|
const debugByEventId = this.buildDebugIndex(result);
|
|
@@ -9891,8 +9624,7 @@ var RetrievalDisclosureService = class {
|
|
|
9891
9624
|
return this.expandShared(parsedId.entryId);
|
|
9892
9625
|
}
|
|
9893
9626
|
const targetEvent = await this.deps.eventStore.getEvent(parsedId.eventId);
|
|
9894
|
-
if (!targetEvent)
|
|
9895
|
-
return null;
|
|
9627
|
+
if (!targetEvent) return null;
|
|
9896
9628
|
const windowSize = Math.max(0, options?.windowSize ?? 3);
|
|
9897
9629
|
const sessionEvents = (await this.deps.eventStore.getSessionEvents(targetEvent.sessionId)).slice().sort((a, b) => a.timestamp.getTime() - b.timestamp.getTime());
|
|
9898
9630
|
const targetIndex = sessionEvents.findIndex((event) => event.id === targetEvent.id);
|
|
@@ -9916,8 +9648,7 @@ var RetrievalDisclosureService = class {
|
|
|
9916
9648
|
return this.sourceShared(parsedId.entryId);
|
|
9917
9649
|
}
|
|
9918
9650
|
const rawEvent = await this.deps.eventStore.getEvent(parsedId.eventId);
|
|
9919
|
-
if (!rawEvent)
|
|
9920
|
-
return null;
|
|
9651
|
+
if (!rawEvent) return null;
|
|
9921
9652
|
return {
|
|
9922
9653
|
...this.sourceReferenceForEvent(rawEvent),
|
|
9923
9654
|
rawEvents: [rawEvent],
|
|
@@ -9926,8 +9657,7 @@ var RetrievalDisclosureService = class {
|
|
|
9926
9657
|
}
|
|
9927
9658
|
async expandShared(entryId) {
|
|
9928
9659
|
const entry = await this.deps.sharedStore?.get(entryId);
|
|
9929
|
-
if (!entry)
|
|
9930
|
-
return null;
|
|
9660
|
+
if (!entry) return null;
|
|
9931
9661
|
return {
|
|
9932
9662
|
target: this.sharedToEnvelope(entry),
|
|
9933
9663
|
surroundingFacts: [],
|
|
@@ -9938,8 +9668,7 @@ var RetrievalDisclosureService = class {
|
|
|
9938
9668
|
}
|
|
9939
9669
|
async sourceShared(entryId) {
|
|
9940
9670
|
const entry = await this.deps.sharedStore?.get(entryId);
|
|
9941
|
-
if (!entry)
|
|
9942
|
-
return null;
|
|
9671
|
+
if (!entry) return null;
|
|
9943
9672
|
const sourceReference = this.sourceReferenceForShared(entry);
|
|
9944
9673
|
return {
|
|
9945
9674
|
...sourceReference,
|
|
@@ -10025,38 +9754,25 @@ var RetrievalDisclosureService = class {
|
|
|
10025
9754
|
const reasons = /* @__PURE__ */ new Set();
|
|
10026
9755
|
const usedVector = this.usedVector(result);
|
|
10027
9756
|
const usedKeyword = this.usedKeyword(result);
|
|
10028
|
-
if (usedVector && (debug?.semanticScore ?? 0) > 0)
|
|
10029
|
-
|
|
10030
|
-
if ((debug?.
|
|
10031
|
-
|
|
10032
|
-
if ((debug?.
|
|
10033
|
-
|
|
10034
|
-
if (
|
|
10035
|
-
|
|
10036
|
-
if (
|
|
10037
|
-
reasons.add("entity_overlap");
|
|
10038
|
-
if ((result.fallbackTrace || []).some((step) => step === "fallback:summary"))
|
|
10039
|
-
reasons.add("summary_fallback");
|
|
10040
|
-
if (memory.sessionContext)
|
|
10041
|
-
reasons.add("continuity_link");
|
|
10042
|
-
if (memory.event.eventType === "tool_observation")
|
|
10043
|
-
reasons.add("tool_followup");
|
|
10044
|
-
if (reasons.size === 0)
|
|
10045
|
-
reasons.add(usedVector ? "semantic_match" : "keyword_match");
|
|
9757
|
+
if (usedVector && (debug?.semanticScore ?? 0) > 0) reasons.add("semantic_match");
|
|
9758
|
+
if ((debug?.lexicalScore ?? 0) > 0 || usedKeyword) reasons.add("keyword_match");
|
|
9759
|
+
if ((debug?.recencyScore ?? 0) > 0) reasons.add("recent_relevance");
|
|
9760
|
+
if ((debug?.facetMatches || []).length > 0) reasons.add("facet_match");
|
|
9761
|
+
if ((debug?.graphPaths || []).length > 0) reasons.add("entity_overlap");
|
|
9762
|
+
if ((result.fallbackTrace || []).some((step) => step === "fallback:summary")) reasons.add("summary_fallback");
|
|
9763
|
+
if (memory.sessionContext) reasons.add("continuity_link");
|
|
9764
|
+
if (memory.event.eventType === "tool_observation") reasons.add("tool_followup");
|
|
9765
|
+
if (reasons.size === 0) reasons.add(usedVector ? "semantic_match" : "keyword_match");
|
|
10046
9766
|
return Array.from(reasons);
|
|
10047
9767
|
}
|
|
10048
9768
|
reasonsForContextEvent(event) {
|
|
10049
|
-
if (event.eventType === "tool_observation")
|
|
10050
|
-
|
|
10051
|
-
if (event.eventType === "session_summary")
|
|
10052
|
-
return ["summary_fallback"];
|
|
9769
|
+
if (event.eventType === "tool_observation") return ["tool_followup"];
|
|
9770
|
+
if (event.eventType === "session_summary") return ["summary_fallback"];
|
|
10053
9771
|
return ["continuity_link"];
|
|
10054
9772
|
}
|
|
10055
9773
|
resultTypeForEvent(event) {
|
|
10056
|
-
if (event.eventType === "session_summary")
|
|
10057
|
-
|
|
10058
|
-
if (event.eventType === "tool_observation")
|
|
10059
|
-
return "tool_evidence";
|
|
9774
|
+
if (event.eventType === "session_summary") return "summary";
|
|
9775
|
+
if (event.eventType === "tool_observation") return "tool_evidence";
|
|
10060
9776
|
return "source";
|
|
10061
9777
|
}
|
|
10062
9778
|
sourceReferenceForEvent(event) {
|
|
@@ -10080,21 +9796,15 @@ var RetrievalDisclosureService = class {
|
|
|
10080
9796
|
}
|
|
10081
9797
|
sourceTypeForEvent(event) {
|
|
10082
9798
|
const metadata = event.metadata || {};
|
|
10083
|
-
if (event.eventType === "tool_observation")
|
|
10084
|
-
|
|
10085
|
-
if (typeof metadata.
|
|
10086
|
-
return "transcript";
|
|
10087
|
-
if (typeof metadata.importedFrom === "string")
|
|
10088
|
-
return "imported_history";
|
|
9799
|
+
if (event.eventType === "tool_observation") return "tool_output";
|
|
9800
|
+
if (typeof metadata.transcriptPath === "string") return "transcript";
|
|
9801
|
+
if (typeof metadata.importedFrom === "string") return "imported_history";
|
|
10089
9802
|
return "raw_event";
|
|
10090
9803
|
}
|
|
10091
9804
|
titleForEvent(event) {
|
|
10092
|
-
if (event.eventType === "session_summary")
|
|
10093
|
-
|
|
10094
|
-
if (event.eventType === "
|
|
10095
|
-
return "Tool evidence";
|
|
10096
|
-
if (event.eventType === "agent_response")
|
|
10097
|
-
return "Agent response";
|
|
9805
|
+
if (event.eventType === "session_summary") return "Session summary";
|
|
9806
|
+
if (event.eventType === "tool_observation") return "Tool evidence";
|
|
9807
|
+
if (event.eventType === "agent_response") return "Agent response";
|
|
10098
9808
|
return "User prompt";
|
|
10099
9809
|
}
|
|
10100
9810
|
usedVector(result) {
|
|
@@ -10120,8 +9830,7 @@ var RetrievalDisclosureService = class {
|
|
|
10120
9830
|
}
|
|
10121
9831
|
preview(content, maxLength) {
|
|
10122
9832
|
const normalized = content.replace(/\s+/g, " ").trim();
|
|
10123
|
-
if (normalized.length <= maxLength)
|
|
10124
|
-
return normalized;
|
|
9833
|
+
if (normalized.length <= maxLength) return normalized;
|
|
10125
9834
|
return `${normalized.slice(0, Math.max(0, maxLength - 3))}...`;
|
|
10126
9835
|
}
|
|
10127
9836
|
};
|
|
@@ -10150,6 +9859,7 @@ var RetrievalOrchestrator = class {
|
|
|
10150
9859
|
this.deps = deps;
|
|
10151
9860
|
this.deps.retriever.setQueryRewriter((query) => this.rewriteQueryIntent(query));
|
|
10152
9861
|
}
|
|
9862
|
+
deps;
|
|
10153
9863
|
/**
|
|
10154
9864
|
* Retrieve relevant memories for a query.
|
|
10155
9865
|
*/
|
|
@@ -10231,8 +9941,7 @@ var RetrievalOrchestrator = class {
|
|
|
10231
9941
|
* the heavier retrieval/vector initialization path for prompt telemetry.
|
|
10232
9942
|
*/
|
|
10233
9943
|
async incrementMemoryAccess(eventIds) {
|
|
10234
|
-
if (eventIds.length === 0)
|
|
10235
|
-
return;
|
|
9944
|
+
if (eventIds.length === 0) return;
|
|
10236
9945
|
await this.deps.accessStore.incrementAccessCount(eventIds);
|
|
10237
9946
|
}
|
|
10238
9947
|
/**
|
|
@@ -10245,10 +9954,8 @@ var RetrievalOrchestrator = class {
|
|
|
10245
9954
|
resolveGraphHopOptions(callerOptions) {
|
|
10246
9955
|
const graphExpansion = this.deps.memoryOperationsConfig?.graphExpansion;
|
|
10247
9956
|
const durableOptions = graphExpansion?.enabled === true ? { enabled: true, maxHops: graphExpansion.maxHops } : void 0;
|
|
10248
|
-
if (!callerOptions)
|
|
10249
|
-
|
|
10250
|
-
if (!graphExpansion)
|
|
10251
|
-
return callerOptions;
|
|
9957
|
+
if (!callerOptions) return durableOptions;
|
|
9958
|
+
if (!graphExpansion) return callerOptions;
|
|
10252
9959
|
if (graphExpansion.enabled !== true) {
|
|
10253
9960
|
return {
|
|
10254
9961
|
...callerOptions,
|
|
@@ -10308,12 +10015,10 @@ var RetrievalOrchestrator = class {
|
|
|
10308
10015
|
const lexical = Number(process.env.MEMORY_RERANK_WEIGHT_LEXICAL ?? "");
|
|
10309
10016
|
const recency = Number(process.env.MEMORY_RERANK_WEIGHT_RECENCY ?? "");
|
|
10310
10017
|
const allFinite = [semantic, lexical, recency].every((value) => Number.isFinite(value));
|
|
10311
|
-
if (!allFinite)
|
|
10312
|
-
return void 0;
|
|
10018
|
+
if (!allFinite) return void 0;
|
|
10313
10019
|
const nonNegative = [semantic, lexical, recency].every((value) => value >= 0);
|
|
10314
10020
|
const total = semantic + lexical + recency;
|
|
10315
|
-
if (!nonNegative || total <= 0)
|
|
10316
|
-
return void 0;
|
|
10021
|
+
if (!nonNegative || total <= 0) return void 0;
|
|
10317
10022
|
return {
|
|
10318
10023
|
semantic: semantic / total,
|
|
10319
10024
|
lexical: lexical / total,
|
|
@@ -10322,17 +10027,14 @@ var RetrievalOrchestrator = class {
|
|
|
10322
10027
|
}
|
|
10323
10028
|
async getRerankWeights(adaptive) {
|
|
10324
10029
|
const configured = this.getConfiguredRerankWeights();
|
|
10325
|
-
if (configured)
|
|
10326
|
-
|
|
10327
|
-
if (adaptive)
|
|
10328
|
-
return this.getAdaptiveRerankWeights();
|
|
10030
|
+
if (configured) return configured;
|
|
10031
|
+
if (adaptive) return this.getAdaptiveRerankWeights();
|
|
10329
10032
|
return void 0;
|
|
10330
10033
|
}
|
|
10331
10034
|
async getAdaptiveRerankWeights() {
|
|
10332
10035
|
try {
|
|
10333
10036
|
const stats = await this.deps.traceStore.getHelpfulnessStats();
|
|
10334
|
-
if (stats.totalEvaluated < 20)
|
|
10335
|
-
return void 0;
|
|
10037
|
+
if (stats.totalEvaluated < 20) return void 0;
|
|
10336
10038
|
let semantic = 0.7;
|
|
10337
10039
|
let lexical = 0.2;
|
|
10338
10040
|
let recency = 0.1;
|
|
@@ -10354,11 +10056,9 @@ var RetrievalOrchestrator = class {
|
|
|
10354
10056
|
}
|
|
10355
10057
|
}
|
|
10356
10058
|
async rewriteQueryIntent(query) {
|
|
10357
|
-
if (process.env.MEMORY_INTENT_REWRITE_ENABLED !== "1")
|
|
10358
|
-
return null;
|
|
10059
|
+
if (process.env.MEMORY_INTENT_REWRITE_ENABLED !== "1") return null;
|
|
10359
10060
|
const apiUrl = process.env.COMPANY_STOCK_API_URL || process.env.COMPANY_INT_API_URL;
|
|
10360
|
-
if (!apiUrl)
|
|
10361
|
-
return null;
|
|
10061
|
+
if (!apiUrl) return null;
|
|
10362
10062
|
const controller = new AbortController();
|
|
10363
10063
|
const timeoutMs = Number(process.env.MEMORY_INTENT_REWRITE_TIMEOUT_MS || 5e3);
|
|
10364
10064
|
const timeout = setTimeout(() => controller.abort(), timeoutMs);
|
|
@@ -10384,11 +10084,9 @@ var RetrievalOrchestrator = class {
|
|
|
10384
10084
|
signal: controller.signal
|
|
10385
10085
|
});
|
|
10386
10086
|
const text = (await res.text()).trim();
|
|
10387
|
-
if (!text)
|
|
10388
|
-
return null;
|
|
10087
|
+
if (!text) return null;
|
|
10389
10088
|
const oneLine = text.replace(/^data:\s*/gm, "").split(/\r?\n/).map((line) => line.trim()).filter(Boolean).join(" ").slice(0, 240);
|
|
10390
|
-
if (!oneLine || oneLine.toLowerCase() === query.toLowerCase())
|
|
10391
|
-
return null;
|
|
10089
|
+
if (!oneLine || oneLine.toLowerCase() === query.toLowerCase()) return null;
|
|
10392
10090
|
return oneLine;
|
|
10393
10091
|
} catch {
|
|
10394
10092
|
return null;
|
|
@@ -10530,8 +10228,7 @@ function createMemoryEngineServices(options) {
|
|
|
10530
10228
|
};
|
|
10531
10229
|
}
|
|
10532
10230
|
function shouldEnablePerspectiveDeriver(options) {
|
|
10533
|
-
if (options.readOnly)
|
|
10534
|
-
return false;
|
|
10231
|
+
if (options.readOnly) return false;
|
|
10535
10232
|
const perspectiveMemory = options.memoryOperationsConfig?.perspectiveMemory;
|
|
10536
10233
|
return perspectiveMemory?.enabled === true && perspectiveMemory.deriver?.enabled === true;
|
|
10537
10234
|
}
|
|
@@ -10565,6 +10262,9 @@ var GraduationWorker = class {
|
|
|
10565
10262
|
this.graduation = graduation;
|
|
10566
10263
|
this.config = config;
|
|
10567
10264
|
}
|
|
10265
|
+
eventStore;
|
|
10266
|
+
graduation;
|
|
10267
|
+
config;
|
|
10568
10268
|
running = false;
|
|
10569
10269
|
timeout = null;
|
|
10570
10270
|
lastEvaluated = /* @__PURE__ */ new Map();
|
|
@@ -10572,8 +10272,7 @@ var GraduationWorker = class {
|
|
|
10572
10272
|
* Start the graduation worker
|
|
10573
10273
|
*/
|
|
10574
10274
|
start() {
|
|
10575
|
-
if (this.running)
|
|
10576
|
-
return;
|
|
10275
|
+
if (this.running) return;
|
|
10577
10276
|
this.running = true;
|
|
10578
10277
|
this.scheduleNext();
|
|
10579
10278
|
}
|
|
@@ -10603,8 +10302,7 @@ var GraduationWorker = class {
|
|
|
10603
10302
|
* Schedule the next graduation check
|
|
10604
10303
|
*/
|
|
10605
10304
|
scheduleNext() {
|
|
10606
|
-
if (!this.running)
|
|
10607
|
-
return;
|
|
10305
|
+
if (!this.running) return;
|
|
10608
10306
|
this.timeout = setTimeout(
|
|
10609
10307
|
() => this.run(),
|
|
10610
10308
|
this.config.evaluationIntervalMs
|
|
@@ -10614,8 +10312,7 @@ var GraduationWorker = class {
|
|
|
10614
10312
|
* Run graduation evaluation
|
|
10615
10313
|
*/
|
|
10616
10314
|
async run() {
|
|
10617
|
-
if (!this.running)
|
|
10618
|
-
return;
|
|
10315
|
+
if (!this.running) return;
|
|
10619
10316
|
try {
|
|
10620
10317
|
await this.runGraduation();
|
|
10621
10318
|
} catch (error) {
|
|
@@ -10679,10 +10376,8 @@ var DEFAULT_CONFIG5 = {
|
|
|
10679
10376
|
maxRetries: 3
|
|
10680
10377
|
};
|
|
10681
10378
|
function parseJsonArray(value) {
|
|
10682
|
-
if (Array.isArray(value))
|
|
10683
|
-
|
|
10684
|
-
if (typeof value !== "string" || value.trim().length === 0)
|
|
10685
|
-
return [];
|
|
10379
|
+
if (Array.isArray(value)) return value;
|
|
10380
|
+
if (typeof value !== "string" || value.trim().length === 0) return [];
|
|
10686
10381
|
try {
|
|
10687
10382
|
const parsed = JSON.parse(value);
|
|
10688
10383
|
return Array.isArray(parsed) ? parsed : [];
|
|
@@ -10712,8 +10407,7 @@ var VectorWorker = class {
|
|
|
10712
10407
|
* Start the worker polling loop
|
|
10713
10408
|
*/
|
|
10714
10409
|
start() {
|
|
10715
|
-
if (this.running)
|
|
10716
|
-
return;
|
|
10410
|
+
if (this.running) return;
|
|
10717
10411
|
this.running = true;
|
|
10718
10412
|
this.stopping = false;
|
|
10719
10413
|
this.poll();
|
|
@@ -10789,8 +10483,7 @@ var VectorWorker = class {
|
|
|
10789
10483
|
* Poll for new items
|
|
10790
10484
|
*/
|
|
10791
10485
|
async poll() {
|
|
10792
|
-
if (!this.running || this.stopping)
|
|
10793
|
-
return;
|
|
10486
|
+
if (!this.running || this.stopping) return;
|
|
10794
10487
|
try {
|
|
10795
10488
|
await this.processBatch();
|
|
10796
10489
|
} catch (error) {
|
|
@@ -10835,6 +10528,7 @@ var DefaultContentProvider = class {
|
|
|
10835
10528
|
constructor(db) {
|
|
10836
10529
|
this.db = db;
|
|
10837
10530
|
}
|
|
10531
|
+
db;
|
|
10838
10532
|
async getContent(itemKind, itemId) {
|
|
10839
10533
|
switch (itemKind) {
|
|
10840
10534
|
case "entry":
|
|
@@ -10855,8 +10549,7 @@ var DefaultContentProvider = class {
|
|
|
10855
10549
|
`SELECT title, content_json, entry_type FROM entries WHERE entry_id = ?`,
|
|
10856
10550
|
[entryId]
|
|
10857
10551
|
);
|
|
10858
|
-
if (rows.length === 0)
|
|
10859
|
-
return null;
|
|
10552
|
+
if (rows.length === 0) return null;
|
|
10860
10553
|
const row = rows[0];
|
|
10861
10554
|
const contentJson = typeof row.content_json === "string" ? JSON.parse(row.content_json) : row.content_json;
|
|
10862
10555
|
return {
|
|
@@ -10875,8 +10568,7 @@ ${JSON.stringify(contentJson)}`,
|
|
|
10875
10568
|
WHERE entity_id = ? AND entity_type = 'task'`,
|
|
10876
10569
|
[taskId]
|
|
10877
10570
|
);
|
|
10878
|
-
if (rows.length === 0)
|
|
10879
|
-
return null;
|
|
10571
|
+
if (rows.length === 0) return null;
|
|
10880
10572
|
const row = rows[0];
|
|
10881
10573
|
return {
|
|
10882
10574
|
content: row.search_text || row.title,
|
|
@@ -10892,8 +10584,7 @@ ${JSON.stringify(contentJson)}`,
|
|
|
10892
10584
|
`SELECT content, event_type, session_id FROM events WHERE id = ?`,
|
|
10893
10585
|
[eventId]
|
|
10894
10586
|
);
|
|
10895
|
-
if (rows.length === 0)
|
|
10896
|
-
return null;
|
|
10587
|
+
if (rows.length === 0) return null;
|
|
10897
10588
|
const row = rows[0];
|
|
10898
10589
|
return {
|
|
10899
10590
|
content: row.content,
|
|
@@ -10921,8 +10612,7 @@ ${JSON.stringify(contentJson)}`,
|
|
|
10921
10612
|
}
|
|
10922
10613
|
throw error;
|
|
10923
10614
|
}
|
|
10924
|
-
if (rows.length === 0)
|
|
10925
|
-
return null;
|
|
10615
|
+
if (rows.length === 0) return null;
|
|
10926
10616
|
const row = rows[0];
|
|
10927
10617
|
const sourceEventIds = parseJsonArray(row.source_event_ids_json);
|
|
10928
10618
|
const sourceObservationIds = parseJsonArray(row.source_observation_ids_json);
|
|
@@ -10964,8 +10654,7 @@ var VectorWorkerV2 = class {
|
|
|
10964
10654
|
* Start the worker polling loop
|
|
10965
10655
|
*/
|
|
10966
10656
|
start() {
|
|
10967
|
-
if (this.running)
|
|
10968
|
-
return;
|
|
10657
|
+
if (this.running) return;
|
|
10969
10658
|
this.running = true;
|
|
10970
10659
|
this.stopping = false;
|
|
10971
10660
|
this.poll();
|
|
@@ -11035,8 +10724,7 @@ var VectorWorkerV2 = class {
|
|
|
11035
10724
|
* Poll for new jobs
|
|
11036
10725
|
*/
|
|
11037
10726
|
async poll() {
|
|
11038
|
-
if (!this.running || this.stopping)
|
|
11039
|
-
return;
|
|
10727
|
+
if (!this.running || this.stopping) return;
|
|
11040
10728
|
try {
|
|
11041
10729
|
await this.processBatch();
|
|
11042
10730
|
} catch (error) {
|
|
@@ -11103,8 +10791,7 @@ function createMemoryRuntimeService(deps) {
|
|
|
11103
10791
|
let graduationWorker = null;
|
|
11104
10792
|
return {
|
|
11105
10793
|
async initialize() {
|
|
11106
|
-
if (initialized)
|
|
11107
|
-
return;
|
|
10794
|
+
if (initialized) return;
|
|
11108
10795
|
await deps.sqliteStore.initialize();
|
|
11109
10796
|
if (deps.lightweightMode) {
|
|
11110
10797
|
initialized = true;
|
|
@@ -11198,8 +10885,7 @@ var SharedEventStore = class {
|
|
|
11198
10885
|
this.db = createDatabase(dbPath);
|
|
11199
10886
|
}
|
|
11200
10887
|
async initialize() {
|
|
11201
|
-
if (this.initialized)
|
|
11202
|
-
return;
|
|
10888
|
+
if (this.initialized) return;
|
|
11203
10889
|
await dbRun(this.db, `
|
|
11204
10890
|
CREATE TABLE IF NOT EXISTS shared_troubleshooting (
|
|
11205
10891
|
entry_id VARCHAR PRIMARY KEY,
|
|
@@ -11289,6 +10975,10 @@ var SharedPromoter = class {
|
|
|
11289
10975
|
this.embedder = embedder;
|
|
11290
10976
|
this.config = config;
|
|
11291
10977
|
}
|
|
10978
|
+
sharedStore;
|
|
10979
|
+
sharedVectorStore;
|
|
10980
|
+
embedder;
|
|
10981
|
+
config;
|
|
11292
10982
|
/**
|
|
11293
10983
|
* Check if an entry is eligible for promotion
|
|
11294
10984
|
*/
|
|
@@ -11470,6 +11160,7 @@ var SharedStore = class {
|
|
|
11470
11160
|
constructor(sharedEventStore) {
|
|
11471
11161
|
this.sharedEventStore = sharedEventStore;
|
|
11472
11162
|
}
|
|
11163
|
+
sharedEventStore;
|
|
11473
11164
|
get db() {
|
|
11474
11165
|
return this.sharedEventStore.getDatabase();
|
|
11475
11166
|
}
|
|
@@ -11574,8 +11265,7 @@ var SharedStore = class {
|
|
|
11574
11265
|
`SELECT * FROM shared_troubleshooting WHERE entry_id = ?`,
|
|
11575
11266
|
[entryId]
|
|
11576
11267
|
);
|
|
11577
|
-
if (rows.length === 0)
|
|
11578
|
-
return null;
|
|
11268
|
+
if (rows.length === 0) return null;
|
|
11579
11269
|
return this.rowToEntry(rows[0]);
|
|
11580
11270
|
}
|
|
11581
11271
|
/**
|
|
@@ -11588,8 +11278,7 @@ var SharedStore = class {
|
|
|
11588
11278
|
WHERE source_project_hash = ? AND source_entry_id = ?`,
|
|
11589
11279
|
[projectHash, sourceEntryId]
|
|
11590
11280
|
);
|
|
11591
|
-
if (rows.length === 0)
|
|
11592
|
-
return null;
|
|
11281
|
+
if (rows.length === 0) return null;
|
|
11593
11282
|
return this.rowToEntry(rows[0]);
|
|
11594
11283
|
}
|
|
11595
11284
|
/**
|
|
@@ -11699,6 +11388,7 @@ var SharedVectorStore = class {
|
|
|
11699
11388
|
constructor(dbPath) {
|
|
11700
11389
|
this.dbPath = dbPath;
|
|
11701
11390
|
}
|
|
11391
|
+
dbPath;
|
|
11702
11392
|
db = null;
|
|
11703
11393
|
table = null;
|
|
11704
11394
|
tableName = "shared_knowledge";
|
|
@@ -11706,8 +11396,7 @@ var SharedVectorStore = class {
|
|
|
11706
11396
|
* Initialize LanceDB connection
|
|
11707
11397
|
*/
|
|
11708
11398
|
async initialize() {
|
|
11709
|
-
if (this.db)
|
|
11710
|
-
return;
|
|
11399
|
+
if (this.db) return;
|
|
11711
11400
|
this.db = await lancedb2.connect(this.dbPath);
|
|
11712
11401
|
try {
|
|
11713
11402
|
const tables = await this.db.tableNames();
|
|
@@ -11749,8 +11438,7 @@ var SharedVectorStore = class {
|
|
|
11749
11438
|
* Add multiple records in batch
|
|
11750
11439
|
*/
|
|
11751
11440
|
async upsertBatch(records) {
|
|
11752
|
-
if (records.length === 0)
|
|
11753
|
-
return;
|
|
11441
|
+
if (records.length === 0) return;
|
|
11754
11442
|
await this.initialize();
|
|
11755
11443
|
if (!this.db) {
|
|
11756
11444
|
throw new Error("Database not initialized");
|
|
@@ -11811,24 +11499,21 @@ var SharedVectorStore = class {
|
|
|
11811
11499
|
* Delete vector by entry ID
|
|
11812
11500
|
*/
|
|
11813
11501
|
async delete(entryId) {
|
|
11814
|
-
if (!this.table)
|
|
11815
|
-
return;
|
|
11502
|
+
if (!this.table) return;
|
|
11816
11503
|
await this.table.delete(`entryId = '${entryId}'`);
|
|
11817
11504
|
}
|
|
11818
11505
|
/**
|
|
11819
11506
|
* Get total count
|
|
11820
11507
|
*/
|
|
11821
11508
|
async count() {
|
|
11822
|
-
if (!this.table)
|
|
11823
|
-
return 0;
|
|
11509
|
+
if (!this.table) return 0;
|
|
11824
11510
|
return this.table.countRows();
|
|
11825
11511
|
}
|
|
11826
11512
|
/**
|
|
11827
11513
|
* Check if vector exists for entry
|
|
11828
11514
|
*/
|
|
11829
11515
|
async exists(entryId) {
|
|
11830
|
-
if (!this.table)
|
|
11831
|
-
return false;
|
|
11516
|
+
if (!this.table) return false;
|
|
11832
11517
|
try {
|
|
11833
11518
|
const results = await this.table.search([]).where(`entryId = '${entryId}'`).limit(1).toArray();
|
|
11834
11519
|
return results.length > 0;
|
|
@@ -11846,6 +11531,7 @@ var SharedMemoryServices = class {
|
|
|
11846
11531
|
constructor(options) {
|
|
11847
11532
|
this.options = options;
|
|
11848
11533
|
}
|
|
11534
|
+
options;
|
|
11849
11535
|
sharedEventStore = null;
|
|
11850
11536
|
sharedStore = null;
|
|
11851
11537
|
sharedVectorStore = null;
|
|
@@ -11870,8 +11556,7 @@ var SharedMemoryServices = class {
|
|
|
11870
11556
|
return this.options.config?.sharedStoragePath ? this.options.expandPath(this.options.config.sharedStoragePath) : this.options.defaultSharedStoragePath;
|
|
11871
11557
|
}
|
|
11872
11558
|
async initialize() {
|
|
11873
|
-
if (this.options.config?.enabled === false || this.options.readOnly)
|
|
11874
|
-
return;
|
|
11559
|
+
if (this.options.config?.enabled === false || this.options.readOnly) return;
|
|
11875
11560
|
const sharedPath = this.getSharedStoragePath();
|
|
11876
11561
|
this.ensureDirectory(sharedPath, { allowCreate: true });
|
|
11877
11562
|
const store = await this.openStore(sharedPath);
|
|
@@ -11888,14 +11573,11 @@ var SharedMemoryServices = class {
|
|
|
11888
11573
|
this.options.retriever.setSharedStores(store, this.sharedVectorStore);
|
|
11889
11574
|
}
|
|
11890
11575
|
async ensureStoreForRead() {
|
|
11891
|
-
if (this.options.config?.enabled === false)
|
|
11892
|
-
|
|
11893
|
-
if (this.sharedStore)
|
|
11894
|
-
return this.sharedStore;
|
|
11576
|
+
if (this.options.config?.enabled === false) return null;
|
|
11577
|
+
if (this.sharedStore) return this.sharedStore;
|
|
11895
11578
|
const sharedPath = this.getSharedStoragePath();
|
|
11896
11579
|
const directoryReady = this.ensureDirectory(sharedPath, { allowCreate: !this.options.readOnly });
|
|
11897
|
-
if (!directoryReady)
|
|
11898
|
-
return null;
|
|
11580
|
+
if (!directoryReady) return null;
|
|
11899
11581
|
return this.openStore(sharedPath);
|
|
11900
11582
|
}
|
|
11901
11583
|
async getEntryForDisclosure(entryId) {
|
|
@@ -11912,13 +11594,11 @@ var SharedMemoryServices = class {
|
|
|
11912
11594
|
return this.sharedPromoter.promoteEntry(entry, projectHash);
|
|
11913
11595
|
}
|
|
11914
11596
|
async getStats() {
|
|
11915
|
-
if (!this.sharedStore)
|
|
11916
|
-
return null;
|
|
11597
|
+
if (!this.sharedStore) return null;
|
|
11917
11598
|
return this.sharedStore.getStats();
|
|
11918
11599
|
}
|
|
11919
11600
|
async search(query, options) {
|
|
11920
|
-
if (!this.sharedStore)
|
|
11921
|
-
return [];
|
|
11601
|
+
if (!this.sharedStore) return [];
|
|
11922
11602
|
return this.sharedStore.search(query, options);
|
|
11923
11603
|
}
|
|
11924
11604
|
async close() {
|
|
@@ -11935,8 +11615,7 @@ var SharedMemoryServices = class {
|
|
|
11935
11615
|
this.openStorePromise = null;
|
|
11936
11616
|
}
|
|
11937
11617
|
async openStore(sharedPath) {
|
|
11938
|
-
if (this.sharedStore)
|
|
11939
|
-
return this.sharedStore;
|
|
11618
|
+
if (this.sharedStore) return this.sharedStore;
|
|
11940
11619
|
if (!this.openStorePromise) {
|
|
11941
11620
|
this.openStorePromise = this.createOpenStorePromise(sharedPath);
|
|
11942
11621
|
}
|
|
@@ -11960,10 +11639,8 @@ var SharedMemoryServices = class {
|
|
|
11960
11639
|
return this.sharedStore;
|
|
11961
11640
|
}
|
|
11962
11641
|
ensureDirectory(sharedPath, options) {
|
|
11963
|
-
if (this.factories.existsSync(sharedPath))
|
|
11964
|
-
|
|
11965
|
-
if (!options.allowCreate)
|
|
11966
|
-
return false;
|
|
11642
|
+
if (this.factories.existsSync(sharedPath)) return true;
|
|
11643
|
+
if (!options.allowCreate) return false;
|
|
11967
11644
|
this.factories.mkdirSync(sharedPath);
|
|
11968
11645
|
return true;
|
|
11969
11646
|
}
|
|
@@ -13170,15 +12847,13 @@ function countRowValue(db, sql, params = []) {
|
|
|
13170
12847
|
return Number(row?.count ?? 0);
|
|
13171
12848
|
}
|
|
13172
12849
|
function projectFilter(projectHash, column = "project_hash") {
|
|
13173
|
-
if (!projectHash)
|
|
13174
|
-
return { clause: "", params: [] };
|
|
12850
|
+
if (!projectHash) return { clause: "", params: [] };
|
|
13175
12851
|
return { clause: `WHERE ${column} = ?`, params: [projectHash] };
|
|
13176
12852
|
}
|
|
13177
12853
|
function sanitizeAggregateLabel(value) {
|
|
13178
12854
|
const raw = typeof value === "string" ? value : String(value ?? "unknown");
|
|
13179
12855
|
const sanitized = String(sanitizeGovernanceAuditValue(raw));
|
|
13180
|
-
if (sanitized !== raw || sanitized.includes("[REDACTED]"))
|
|
13181
|
-
return "[REDACTED]";
|
|
12856
|
+
if (sanitized !== raw || sanitized.includes("[REDACTED]")) return "[REDACTED]";
|
|
13182
12857
|
const trimmed = sanitized.trim();
|
|
13183
12858
|
return trimmed.length > 0 ? trimmed.slice(0, 96) : "unknown";
|
|
13184
12859
|
}
|
|
@@ -13522,8 +13197,7 @@ function buildPerspectiveSourceEvidence(db, projectHash) {
|
|
|
13522
13197
|
function sortCountRows(rows, labelKey) {
|
|
13523
13198
|
return [...rows].sort((a, b) => {
|
|
13524
13199
|
const countDiff = Number(b.count ?? 0) - Number(a.count ?? 0);
|
|
13525
|
-
if (countDiff !== 0)
|
|
13526
|
-
return countDiff;
|
|
13200
|
+
if (countDiff !== 0) return countDiff;
|
|
13527
13201
|
return String(a[labelKey] ?? "").localeCompare(String(b[labelKey] ?? ""));
|
|
13528
13202
|
});
|
|
13529
13203
|
}
|
|
@@ -13606,8 +13280,7 @@ var DEFAULT_KPI_THRESHOLDS = {
|
|
|
13606
13280
|
function loadKpiThresholds() {
|
|
13607
13281
|
try {
|
|
13608
13282
|
const filePath = path11.resolve(process.cwd(), "config", "kpi-thresholds.json");
|
|
13609
|
-
if (!fs9.existsSync(filePath))
|
|
13610
|
-
return DEFAULT_KPI_THRESHOLDS;
|
|
13283
|
+
if (!fs9.existsSync(filePath)) return DEFAULT_KPI_THRESHOLDS;
|
|
13611
13284
|
const parsed = JSON.parse(fs9.readFileSync(filePath, "utf-8"));
|
|
13612
13285
|
return {
|
|
13613
13286
|
usefulRecallRateMin: Number(parsed.usefulRecallRateMin ?? DEFAULT_KPI_THRESHOLDS.usefulRecallRateMin),
|
|
@@ -13621,10 +13294,8 @@ function loadKpiThresholds() {
|
|
|
13621
13294
|
}
|
|
13622
13295
|
}
|
|
13623
13296
|
function windowToMs(window) {
|
|
13624
|
-
if (window === "24h")
|
|
13625
|
-
|
|
13626
|
-
if (window === "7d")
|
|
13627
|
-
return 7 * 24 * 60 * 60 * 1e3;
|
|
13297
|
+
if (window === "24h") return 24 * 60 * 60 * 1e3;
|
|
13298
|
+
if (window === "7d") return 7 * 24 * 60 * 60 * 1e3;
|
|
13628
13299
|
return 30 * 24 * 60 * 60 * 1e3;
|
|
13629
13300
|
}
|
|
13630
13301
|
function inWindow(e, now, window) {
|
|
@@ -13634,8 +13305,7 @@ function isEditToolName(name) {
|
|
|
13634
13305
|
return ["Write", "Edit", "MultiEdit", "NotebookEdit"].includes(name);
|
|
13635
13306
|
}
|
|
13636
13307
|
function parseToolPayload(e) {
|
|
13637
|
-
if (e.eventType !== "tool_observation")
|
|
13638
|
-
return null;
|
|
13308
|
+
if (e.eventType !== "tool_observation") return null;
|
|
13639
13309
|
try {
|
|
13640
13310
|
const payload = JSON.parse(e.content);
|
|
13641
13311
|
return {
|
|
@@ -13654,13 +13324,11 @@ function parseToolPayload(e) {
|
|
|
13654
13324
|
}
|
|
13655
13325
|
}
|
|
13656
13326
|
function isTestLikeCommand(command) {
|
|
13657
|
-
if (!command)
|
|
13658
|
-
return false;
|
|
13327
|
+
if (!command) return false;
|
|
13659
13328
|
return /(test|jest|vitest|pytest|go test|cargo test|lint|eslint|build|tsc)/i.test(command);
|
|
13660
13329
|
}
|
|
13661
13330
|
function safeRatio(num, den) {
|
|
13662
|
-
if (!Number.isFinite(num) || !Number.isFinite(den) || den <= 0)
|
|
13663
|
-
return 0;
|
|
13331
|
+
if (!Number.isFinite(num) || !Number.isFinite(den) || den <= 0) return 0;
|
|
13664
13332
|
return num / den;
|
|
13665
13333
|
}
|
|
13666
13334
|
function round(value, digits = 4) {
|
|
@@ -13671,28 +13339,23 @@ function computeSessionTurnCount(sessionEvents) {
|
|
|
13671
13339
|
const turnIds = /* @__PURE__ */ new Set();
|
|
13672
13340
|
for (const e of sessionEvents) {
|
|
13673
13341
|
const turnId = e.metadata?.turnId;
|
|
13674
|
-
if (typeof turnId === "string" && turnId.length > 0)
|
|
13675
|
-
turnIds.add(turnId);
|
|
13342
|
+
if (typeof turnId === "string" && turnId.length > 0) turnIds.add(turnId);
|
|
13676
13343
|
}
|
|
13677
|
-
if (turnIds.size > 0)
|
|
13678
|
-
return turnIds.size;
|
|
13344
|
+
if (turnIds.size > 0) return turnIds.size;
|
|
13679
13345
|
return sessionEvents.filter((e) => e.eventType === "user_prompt").length;
|
|
13680
13346
|
}
|
|
13681
13347
|
function normalizeQueryRewriteKind2(value) {
|
|
13682
13348
|
const normalized = (value || "").trim().toLowerCase();
|
|
13683
|
-
if (normalized === "follow-up-context" || normalized === "intent-rewrite")
|
|
13684
|
-
return normalized;
|
|
13349
|
+
if (normalized === "follow-up-context" || normalized === "intent-rewrite") return normalized;
|
|
13685
13350
|
return "none";
|
|
13686
13351
|
}
|
|
13687
13352
|
function normalizeMetric(value) {
|
|
13688
13353
|
const numberValue = Number(value || 0);
|
|
13689
|
-
if (!Number.isFinite(numberValue))
|
|
13690
|
-
return 0;
|
|
13354
|
+
if (!Number.isFinite(numberValue)) return 0;
|
|
13691
13355
|
return Math.max(0, Math.min(1, numberValue));
|
|
13692
13356
|
}
|
|
13693
13357
|
function getTimestampMs(value) {
|
|
13694
|
-
if (value instanceof Date)
|
|
13695
|
-
return value.getTime();
|
|
13358
|
+
if (value instanceof Date) return value.getTime();
|
|
13696
13359
|
if (typeof value === "string") {
|
|
13697
13360
|
const parsed = new Date(value).getTime();
|
|
13698
13361
|
return Number.isFinite(parsed) ? parsed : 0;
|
|
@@ -13750,8 +13413,7 @@ function makeRetrievalReviewItem(trace) {
|
|
|
13750
13413
|
detail = `${selectedCount} of ${candidateCount} candidates were selected.`;
|
|
13751
13414
|
action = "Inspect score distribution and MMR/diversity settings before lowering thresholds.";
|
|
13752
13415
|
}
|
|
13753
|
-
if (!reason)
|
|
13754
|
-
return null;
|
|
13416
|
+
if (!reason) return null;
|
|
13755
13417
|
return {
|
|
13756
13418
|
traceId: trace.traceId || "unknown-trace",
|
|
13757
13419
|
reason,
|
|
@@ -13800,24 +13462,17 @@ function buildRetrievalReviewQueue(traces, limit) {
|
|
|
13800
13462
|
};
|
|
13801
13463
|
}
|
|
13802
13464
|
function parseStatsLimit(value, fallback, max) {
|
|
13803
|
-
if (!value)
|
|
13804
|
-
|
|
13805
|
-
if (!/^\d+$/.test(value))
|
|
13806
|
-
return fallback;
|
|
13465
|
+
if (!value) return fallback;
|
|
13466
|
+
if (!/^\d+$/.test(value)) return fallback;
|
|
13807
13467
|
const parsed = Number(value);
|
|
13808
|
-
if (!Number.isFinite(parsed) || parsed <= 0)
|
|
13809
|
-
return fallback;
|
|
13468
|
+
if (!Number.isFinite(parsed) || parsed <= 0) return fallback;
|
|
13810
13469
|
return Math.min(parsed, max);
|
|
13811
13470
|
}
|
|
13812
13471
|
function usefulnessScoreLabel(score, confidence) {
|
|
13813
|
-
if (confidence <= 0)
|
|
13814
|
-
|
|
13815
|
-
if (score >=
|
|
13816
|
-
|
|
13817
|
-
if (score >= 60)
|
|
13818
|
-
return "good";
|
|
13819
|
-
if (score >= 40)
|
|
13820
|
-
return "watch";
|
|
13472
|
+
if (confidence <= 0) return "unknown";
|
|
13473
|
+
if (score >= 80) return "excellent";
|
|
13474
|
+
if (score >= 60) return "good";
|
|
13475
|
+
if (score >= 40) return "watch";
|
|
13821
13476
|
return "low";
|
|
13822
13477
|
}
|
|
13823
13478
|
function buildMemoryUsefulnessDiagnostics(input) {
|
|
@@ -14063,8 +13718,7 @@ function computeKpiMetrics(events, usefulRecallRate) {
|
|
|
14063
13718
|
let seenEdit = false;
|
|
14064
13719
|
for (const e of sorted) {
|
|
14065
13720
|
const payload = parseToolPayload(e);
|
|
14066
|
-
if (!payload?.toolName)
|
|
14067
|
-
continue;
|
|
13721
|
+
if (!payload?.toolName) continue;
|
|
14068
13722
|
if (isEditToolName(payload.toolName) && payload.success === true) {
|
|
14069
13723
|
editActions.push({ sessionId, timestamp: e.timestamp.getTime(), filePath: payload.filePath });
|
|
14070
13724
|
seenEdit = true;
|
|
@@ -14072,8 +13726,7 @@ function computeKpiMetrics(events, usefulRecallRate) {
|
|
|
14072
13726
|
}
|
|
14073
13727
|
if (seenEdit && isTestLikeCommand(payload.command)) {
|
|
14074
13728
|
testRunsAfterEdit++;
|
|
14075
|
-
if (payload.success === false)
|
|
14076
|
-
failedTestRunsAfterEdit++;
|
|
13729
|
+
if (payload.success === false) failedTestRunsAfterEdit++;
|
|
14077
13730
|
}
|
|
14078
13731
|
}
|
|
14079
13732
|
}
|
|
@@ -14082,8 +13735,7 @@ function computeKpiMetrics(events, usefulRecallRate) {
|
|
|
14082
13735
|
const bySessionFile = /* @__PURE__ */ new Map();
|
|
14083
13736
|
const sortedEdits = [...editActions].sort((a, b) => a.timestamp - b.timestamp);
|
|
14084
13737
|
for (const edit of sortedEdits) {
|
|
14085
|
-
if (!edit.filePath)
|
|
14086
|
-
continue;
|
|
13738
|
+
if (!edit.filePath) continue;
|
|
14087
13739
|
const key = `${edit.sessionId}::${edit.filePath}`;
|
|
14088
13740
|
const prev = bySessionFile.get(key);
|
|
14089
13741
|
if (typeof prev === "number" && edit.timestamp - prev <= THIRTY_MIN_MS) {
|
|
@@ -14458,12 +14110,9 @@ statsRouter.get("/timeline", async (c) => {
|
|
|
14458
14110
|
acc[day] = { date: day, total: 0, prompts: 0, responses: 0, tools: 0 };
|
|
14459
14111
|
}
|
|
14460
14112
|
acc[day].total++;
|
|
14461
|
-
if (e.eventType === "user_prompt")
|
|
14462
|
-
|
|
14463
|
-
if (e.eventType === "
|
|
14464
|
-
acc[day].responses++;
|
|
14465
|
-
if (e.eventType === "tool_observation")
|
|
14466
|
-
acc[day].tools++;
|
|
14113
|
+
if (e.eventType === "user_prompt") acc[day].prompts++;
|
|
14114
|
+
if (e.eventType === "agent_response") acc[day].responses++;
|
|
14115
|
+
if (e.eventType === "tool_observation") acc[day].tools++;
|
|
14467
14116
|
return acc;
|
|
14468
14117
|
}, {});
|
|
14469
14118
|
return c.json({
|
|
@@ -14674,8 +14323,7 @@ statsRouter.get("/kpi", async (c) => {
|
|
|
14674
14323
|
for (const edit of dayEditActions) {
|
|
14675
14324
|
const key = `${edit.sessionId}::${edit.filePath}`;
|
|
14676
14325
|
const prev = dayBySessionFile.get(key);
|
|
14677
|
-
if (typeof prev === "number" && edit.timestamp - prev <= THIRTY_MIN_MS)
|
|
14678
|
-
dayReworkCount++;
|
|
14326
|
+
if (typeof prev === "number" && edit.timestamp - prev <= THIRTY_MIN_MS) dayReworkCount++;
|
|
14679
14327
|
dayBySessionFile.set(key, edit.timestamp);
|
|
14680
14328
|
}
|
|
14681
14329
|
const dayTests = dayEvents.filter((e) => {
|
|
@@ -15015,8 +14663,7 @@ projectsRouter.get("/", async (c) => {
|
|
|
15015
14663
|
}
|
|
15016
14664
|
});
|
|
15017
14665
|
function formatBytes(bytes) {
|
|
15018
|
-
if (bytes === 0)
|
|
15019
|
-
return "0 B";
|
|
14666
|
+
if (bytes === 0) return "0 B";
|
|
15020
14667
|
const k = 1024;
|
|
15021
14668
|
const sizes = ["B", "KB", "MB", "GB"];
|
|
15022
14669
|
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
@@ -15034,6 +14681,7 @@ var ProviderFailure = class extends Error {
|
|
|
15034
14681
|
this.code = code;
|
|
15035
14682
|
this.name = "ProviderFailure";
|
|
15036
14683
|
}
|
|
14684
|
+
code;
|
|
15037
14685
|
};
|
|
15038
14686
|
var CLAUDE_TIMEOUT_MS = 12e4;
|
|
15039
14687
|
chatRouter.post("/", async (c) => {
|
|
@@ -15110,8 +14758,7 @@ async function collectMemoryContext(memoryService, query) {
|
|
|
15110
14758
|
async function collectStatsContext(memoryService) {
|
|
15111
14759
|
try {
|
|
15112
14760
|
const stats = await memoryService.getStats?.();
|
|
15113
|
-
if (!stats)
|
|
15114
|
-
return "";
|
|
14761
|
+
if (!stats) return "";
|
|
15115
14762
|
const levels = stats.levelStats.map((l) => `${l.level}: ${l.count}`).join(", ");
|
|
15116
14763
|
return [
|
|
15117
14764
|
"## Memory Stats",
|
|
@@ -15124,8 +14771,7 @@ async function collectStatsContext(memoryService) {
|
|
|
15124
14771
|
}
|
|
15125
14772
|
}
|
|
15126
14773
|
function formatMemoryContext(memoryHits) {
|
|
15127
|
-
if (memoryHits.length === 0)
|
|
15128
|
-
return "";
|
|
14774
|
+
if (memoryHits.length === 0) return "";
|
|
15129
14775
|
const parts = ["## Relevant Memories\n"];
|
|
15130
14776
|
for (const m of memoryHits) {
|
|
15131
14777
|
const date = m.event.timestamp ? new Date(m.event.timestamp).toISOString().split("T")[0] : "unknown-date";
|
|
@@ -15247,8 +14893,7 @@ function streamClaudeResponse(prompt, stream) {
|
|
|
15247
14893
|
const lines = buffer.split("\n");
|
|
15248
14894
|
buffer = lines.pop() || "";
|
|
15249
14895
|
for (const line of lines) {
|
|
15250
|
-
if (!line.trim())
|
|
15251
|
-
continue;
|
|
14896
|
+
if (!line.trim()) continue;
|
|
15252
14897
|
try {
|
|
15253
14898
|
const parsed = JSON.parse(line);
|
|
15254
14899
|
if (parsed.type === "assistant" && parsed.message?.content) {
|
|
@@ -15477,21 +15122,17 @@ function timingSafeStringEqual(a, b) {
|
|
|
15477
15122
|
return left.length === right.length && timingSafeEqual(left, right);
|
|
15478
15123
|
}
|
|
15479
15124
|
function verifyDashboardSessionToken(token, password, maxAgeSeconds, now) {
|
|
15480
|
-
if (!token)
|
|
15481
|
-
return false;
|
|
15125
|
+
if (!token) return false;
|
|
15482
15126
|
const [payload, signature, extra] = token.split(".");
|
|
15483
|
-
if (!payload || !signature || extra !== void 0 || !/^\d+$/.test(payload))
|
|
15484
|
-
return false;
|
|
15127
|
+
if (!payload || !signature || extra !== void 0 || !/^\d+$/.test(payload)) return false;
|
|
15485
15128
|
const expectedSignature = signSessionPayload(payload, password);
|
|
15486
|
-
if (!timingSafeStringEqual(signature, expectedSignature))
|
|
15487
|
-
return false;
|
|
15129
|
+
if (!timingSafeStringEqual(signature, expectedSignature)) return false;
|
|
15488
15130
|
const issuedAt = Number.parseInt(payload, 10);
|
|
15489
15131
|
const age = nowSeconds(now) - issuedAt;
|
|
15490
15132
|
return Number.isSafeInteger(issuedAt) && age >= 0 && age <= maxAgeSeconds;
|
|
15491
15133
|
}
|
|
15492
15134
|
function isDashboardAuthenticated(c, options) {
|
|
15493
|
-
if (!options.password)
|
|
15494
|
-
return true;
|
|
15135
|
+
if (!options.password) return true;
|
|
15495
15136
|
return verifyDashboardSessionToken(
|
|
15496
15137
|
getCookie(c, DASHBOARD_SESSION_COOKIE),
|
|
15497
15138
|
options.password,
|
|
@@ -15578,8 +15219,7 @@ function createDashboardApp(options = {}) {
|
|
|
15578
15219
|
}
|
|
15579
15220
|
const submittedPassword = await readSubmittedPassword(c);
|
|
15580
15221
|
if (!timingSafeStringEqual(submittedPassword, authOptions.password)) {
|
|
15581
|
-
if (wantsAuthJson(c))
|
|
15582
|
-
return c.json({ error: "Invalid password" }, 401);
|
|
15222
|
+
if (wantsAuthJson(c)) return c.json({ error: "Invalid password" }, 401);
|
|
15583
15223
|
return c.html(renderLoginPage("Invalid password"), 401);
|
|
15584
15224
|
}
|
|
15585
15225
|
const token = createDashboardSessionToken(authOptions.password, authOptions.now);
|
|
@@ -15590,14 +15230,12 @@ function createDashboardApp(options = {}) {
|
|
|
15590
15230
|
path: "/",
|
|
15591
15231
|
maxAge: authOptions.cookieMaxAgeSeconds
|
|
15592
15232
|
});
|
|
15593
|
-
if (wantsAuthJson(c))
|
|
15594
|
-
return c.json({ authenticated: true });
|
|
15233
|
+
if (wantsAuthJson(c)) return c.json({ authenticated: true });
|
|
15595
15234
|
return c.redirect("/", 303);
|
|
15596
15235
|
});
|
|
15597
15236
|
app2.post("/api/auth/logout", (c) => {
|
|
15598
15237
|
deleteCookie(c, DASHBOARD_SESSION_COOKIE, { path: "/" });
|
|
15599
|
-
if (wantsAuthJson(c))
|
|
15600
|
-
return c.json({ authenticated: false });
|
|
15238
|
+
if (wantsAuthJson(c)) return c.json({ authenticated: false });
|
|
15601
15239
|
return c.redirect("/", 303);
|
|
15602
15240
|
});
|
|
15603
15241
|
if (authOptions.password) {
|
|
@@ -15606,8 +15244,7 @@ function createDashboardApp(options = {}) {
|
|
|
15606
15244
|
await next();
|
|
15607
15245
|
return;
|
|
15608
15246
|
}
|
|
15609
|
-
if (isApiRequest(c))
|
|
15610
|
-
return c.json({ error: "Authentication required" }, 401);
|
|
15247
|
+
if (isApiRequest(c)) return c.json({ error: "Authentication required" }, 401);
|
|
15611
15248
|
return c.html(renderLoginPage(), 401);
|
|
15612
15249
|
});
|
|
15613
15250
|
}
|