claude-memory-layer 1.0.44 → 1.0.46
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 +1 -0
- package/dist/cli/index.js +801 -1421
- package/dist/cli/index.js.map +2 -2
- package/dist/core/index.js +1319 -1501
- package/dist/core/index.js.map +4 -4
- package/dist/hooks/post-tool-use.js +465 -756
- package/dist/hooks/post-tool-use.js.map +2 -2
- package/dist/hooks/semantic-daemon.js +454 -734
- package/dist/hooks/semantic-daemon.js.map +2 -2
- package/dist/hooks/session-end.js +450 -726
- package/dist/hooks/session-end.js.map +2 -2
- package/dist/hooks/session-start.js +451 -728
- package/dist/hooks/session-start.js.map +2 -2
- package/dist/hooks/stop.js +458 -742
- package/dist/hooks/stop.js.map +2 -2
- package/dist/hooks/user-prompt-submit.js +494 -814
- package/dist/hooks/user-prompt-submit.js.map +2 -2
- package/dist/index.js +1397 -1615
- package/dist/index.js.map +4 -4
- package/dist/mcp/index.js +1587 -1655
- package/dist/mcp/index.js.map +4 -4
- package/dist/server/api/index.js +484 -792
- package/dist/server/api/index.js.map +2 -2
- package/dist/server/index.js +492 -808
- package/dist/server/index.js.map +2 -2
- package/dist/services/memory-service.js +450 -726
- package/dist/services/memory-service.js.map +2 -2
- package/package.json +15 -3
|
@@ -57,6 +57,7 @@ var DefaultEmbeddingMaintenanceService = class {
|
|
|
57
57
|
this.options = options;
|
|
58
58
|
this.fileSystem = options.fileSystem ?? defaultFileSystem;
|
|
59
59
|
}
|
|
60
|
+
options;
|
|
60
61
|
fileSystem;
|
|
61
62
|
getEmbeddingModelName() {
|
|
62
63
|
return this.options.getEmbeddingModelName();
|
|
@@ -91,8 +92,7 @@ var DefaultEmbeddingMaintenanceService = class {
|
|
|
91
92
|
}
|
|
92
93
|
const worker = this.options.getVectorWorker();
|
|
93
94
|
const wasRunning = worker?.isRunning() || false;
|
|
94
|
-
if (wasRunning)
|
|
95
|
-
worker?.stop();
|
|
95
|
+
if (wasRunning) worker?.stop();
|
|
96
96
|
await this.options.vectorStore.clearAll();
|
|
97
97
|
await this.options.eventStore.clearEmbeddingOutbox();
|
|
98
98
|
const enqueued = await this.reenqueueAllEvents();
|
|
@@ -109,8 +109,7 @@ var DefaultEmbeddingMaintenanceService = class {
|
|
|
109
109
|
2
|
|
110
110
|
)
|
|
111
111
|
);
|
|
112
|
-
if (wasRunning)
|
|
113
|
-
worker?.start();
|
|
112
|
+
if (wasRunning) worker?.start();
|
|
114
113
|
return {
|
|
115
114
|
changed: true,
|
|
116
115
|
previousModel,
|
|
@@ -135,15 +134,13 @@ var DefaultEmbeddingMaintenanceService = class {
|
|
|
135
134
|
let enqueued = 0;
|
|
136
135
|
while (true) {
|
|
137
136
|
const page = await this.options.eventStore.getEventsPage(DEFAULT_PAGE_SIZE, offset);
|
|
138
|
-
if (page.length === 0)
|
|
139
|
-
break;
|
|
137
|
+
if (page.length === 0) break;
|
|
140
138
|
for (const event of page) {
|
|
141
139
|
await this.options.eventStore.enqueueForEmbedding(event.id, event.content);
|
|
142
140
|
enqueued += 1;
|
|
143
141
|
}
|
|
144
142
|
offset += page.length;
|
|
145
|
-
if (page.length < DEFAULT_PAGE_SIZE)
|
|
146
|
-
break;
|
|
143
|
+
if (page.length < DEFAULT_PAGE_SIZE) break;
|
|
147
144
|
}
|
|
148
145
|
return enqueued;
|
|
149
146
|
}
|
|
@@ -161,12 +158,9 @@ import { randomUUID } from "crypto";
|
|
|
161
158
|
// src/core/db-wrapper.ts
|
|
162
159
|
import BetterSqlite3 from "better-sqlite3";
|
|
163
160
|
function toDate(value) {
|
|
164
|
-
if (value instanceof Date)
|
|
165
|
-
|
|
166
|
-
if (typeof value === "
|
|
167
|
-
return new Date(value);
|
|
168
|
-
if (typeof value === "number")
|
|
169
|
-
return new Date(value);
|
|
161
|
+
if (value instanceof Date) return value;
|
|
162
|
+
if (typeof value === "string") return new Date(value);
|
|
163
|
+
if (typeof value === "number") return new Date(value);
|
|
170
164
|
return new Date(String(value));
|
|
171
165
|
}
|
|
172
166
|
function createDatabase(dbPath, options) {
|
|
@@ -190,6 +184,8 @@ var WorkingSetStore = class {
|
|
|
190
184
|
this.eventStore = eventStore;
|
|
191
185
|
this.config = config;
|
|
192
186
|
}
|
|
187
|
+
eventStore;
|
|
188
|
+
config;
|
|
193
189
|
get db() {
|
|
194
190
|
return this.eventStore.getDatabase();
|
|
195
191
|
}
|
|
@@ -275,8 +271,7 @@ var WorkingSetStore = class {
|
|
|
275
271
|
* Prune specific events from working set (after consolidation)
|
|
276
272
|
*/
|
|
277
273
|
async prune(eventIds) {
|
|
278
|
-
if (eventIds.length === 0)
|
|
279
|
-
return;
|
|
274
|
+
if (eventIds.length === 0) return;
|
|
280
275
|
const placeholders = eventIds.map(() => "?").join(",");
|
|
281
276
|
await dbRun(
|
|
282
277
|
this.db,
|
|
@@ -346,8 +341,7 @@ var WorkingSetStore = class {
|
|
|
346
341
|
LIMIT ?`,
|
|
347
342
|
[maxEvents]
|
|
348
343
|
);
|
|
349
|
-
if (keepIds.length === 0)
|
|
350
|
-
return;
|
|
344
|
+
if (keepIds.length === 0) return;
|
|
351
345
|
const keepIdList = keepIds.map((r) => r.id);
|
|
352
346
|
const placeholders = keepIdList.map(() => "?").join(",");
|
|
353
347
|
await dbRun(
|
|
@@ -394,6 +388,7 @@ var ConsolidatedStore = class {
|
|
|
394
388
|
constructor(eventStore) {
|
|
395
389
|
this.eventStore = eventStore;
|
|
396
390
|
}
|
|
391
|
+
eventStore;
|
|
397
392
|
get db() {
|
|
398
393
|
return this.eventStore.getDatabase();
|
|
399
394
|
}
|
|
@@ -426,8 +421,7 @@ var ConsolidatedStore = class {
|
|
|
426
421
|
`SELECT * FROM consolidated_memories WHERE memory_id = ?`,
|
|
427
422
|
[memoryId]
|
|
428
423
|
);
|
|
429
|
-
if (rows.length === 0)
|
|
430
|
-
return null;
|
|
424
|
+
if (rows.length === 0) return null;
|
|
431
425
|
return this.rowToMemory(rows[0]);
|
|
432
426
|
}
|
|
433
427
|
/**
|
|
@@ -645,8 +639,7 @@ var ConsolidatedStore = class {
|
|
|
645
639
|
WHERE source_events LIKE ?`,
|
|
646
640
|
[`%"${eventId}"%`]
|
|
647
641
|
);
|
|
648
|
-
if ((result[0]?.count || 0) > 0)
|
|
649
|
-
return true;
|
|
642
|
+
if ((result[0]?.count || 0) > 0) return true;
|
|
650
643
|
}
|
|
651
644
|
return false;
|
|
652
645
|
}
|
|
@@ -660,8 +653,7 @@ var ConsolidatedStore = class {
|
|
|
660
653
|
ORDER BY created_at DESC
|
|
661
654
|
LIMIT 1`
|
|
662
655
|
);
|
|
663
|
-
if (result.length === 0)
|
|
664
|
-
return null;
|
|
656
|
+
if (result.length === 0) return null;
|
|
665
657
|
return new Date(result[0].created_at);
|
|
666
658
|
}
|
|
667
659
|
/**
|
|
@@ -691,6 +683,9 @@ var ConsolidationWorker = class {
|
|
|
691
683
|
this.consolidatedStore = consolidatedStore;
|
|
692
684
|
this.config = config;
|
|
693
685
|
}
|
|
686
|
+
workingSetStore;
|
|
687
|
+
consolidatedStore;
|
|
688
|
+
config;
|
|
694
689
|
running = false;
|
|
695
690
|
timeout = null;
|
|
696
691
|
lastActivity = /* @__PURE__ */ new Date();
|
|
@@ -698,8 +693,7 @@ var ConsolidationWorker = class {
|
|
|
698
693
|
* Start the consolidation worker
|
|
699
694
|
*/
|
|
700
695
|
start() {
|
|
701
|
-
if (this.running)
|
|
702
|
-
return;
|
|
696
|
+
if (this.running) return;
|
|
703
697
|
this.running = true;
|
|
704
698
|
this.scheduleNext();
|
|
705
699
|
}
|
|
@@ -742,8 +736,7 @@ var ConsolidationWorker = class {
|
|
|
742
736
|
* Schedule the next consolidation check
|
|
743
737
|
*/
|
|
744
738
|
scheduleNext() {
|
|
745
|
-
if (!this.running)
|
|
746
|
-
return;
|
|
739
|
+
if (!this.running) return;
|
|
747
740
|
this.timeout = setTimeout(
|
|
748
741
|
() => this.run(),
|
|
749
742
|
this.config.consolidation.triggerIntervalMs
|
|
@@ -753,8 +746,7 @@ var ConsolidationWorker = class {
|
|
|
753
746
|
* Run consolidation check
|
|
754
747
|
*/
|
|
755
748
|
async run() {
|
|
756
|
-
if (!this.running)
|
|
757
|
-
return;
|
|
749
|
+
if (!this.running) return;
|
|
758
750
|
try {
|
|
759
751
|
await this.checkAndConsolidate();
|
|
760
752
|
} catch (error) {
|
|
@@ -792,12 +784,10 @@ var ConsolidationWorker = class {
|
|
|
792
784
|
let consolidatedCount = 0;
|
|
793
785
|
const createdMemoryIds = [];
|
|
794
786
|
for (const group of groups) {
|
|
795
|
-
if (group.events.length < 3)
|
|
796
|
-
continue;
|
|
787
|
+
if (group.events.length < 3) continue;
|
|
797
788
|
const eventIds = group.events.map((e) => e.id);
|
|
798
789
|
const alreadyConsolidated = await this.consolidatedStore.isAlreadyConsolidated(eventIds);
|
|
799
|
-
if (alreadyConsolidated)
|
|
800
|
-
continue;
|
|
790
|
+
if (alreadyConsolidated) continue;
|
|
801
791
|
const summary = await this.summarize(group);
|
|
802
792
|
const memoryId = await this.consolidatedStore.create({
|
|
803
793
|
summary,
|
|
@@ -813,8 +803,7 @@ var ConsolidationWorker = class {
|
|
|
813
803
|
const consolidatedEventIds = groups.filter((g) => g.events.length >= 3).flatMap((g) => g.events.map((e) => e.id));
|
|
814
804
|
const oldEventIds = consolidatedEventIds.filter((id) => {
|
|
815
805
|
const event = workingSet.recentEvents.find((e) => e.id === id);
|
|
816
|
-
if (!event)
|
|
817
|
-
return false;
|
|
806
|
+
if (!event) return false;
|
|
818
807
|
const ageHours = (Date.now() - event.timestamp.getTime()) / (1e3 * 60 * 60);
|
|
819
808
|
return ageHours > this.config.workingSet.timeWindowHours / 2;
|
|
820
809
|
});
|
|
@@ -829,18 +818,13 @@ var ConsolidationWorker = class {
|
|
|
829
818
|
let promoted = 0;
|
|
830
819
|
for (const memoryId of memoryIds) {
|
|
831
820
|
const memory = await this.consolidatedStore.get(memoryId);
|
|
832
|
-
if (!memory)
|
|
833
|
-
|
|
834
|
-
if (memory.
|
|
835
|
-
continue;
|
|
836
|
-
if (memory.sourceEvents.length < 4)
|
|
837
|
-
continue;
|
|
821
|
+
if (!memory) continue;
|
|
822
|
+
if (memory.confidence < 0.55) continue;
|
|
823
|
+
if (memory.sourceEvents.length < 4) continue;
|
|
838
824
|
const exists = await this.consolidatedStore.hasRuleForSourceMemory(memoryId);
|
|
839
|
-
if (exists)
|
|
840
|
-
continue;
|
|
825
|
+
if (exists) continue;
|
|
841
826
|
const rule = this.buildRuleFromSummary(memory.summary, memory.topics);
|
|
842
|
-
if (!rule)
|
|
843
|
-
continue;
|
|
827
|
+
if (!rule) continue;
|
|
844
828
|
await this.consolidatedStore.createRule({
|
|
845
829
|
rule,
|
|
846
830
|
topics: memory.topics,
|
|
@@ -856,8 +840,7 @@ var ConsolidationWorker = class {
|
|
|
856
840
|
const lines = summary.split(/\r?\n/).map((l) => l.trim()).filter(Boolean).filter((l) => !l.toLowerCase().startsWith("topics:"));
|
|
857
841
|
const bullet = lines.find((l) => l.startsWith("- "))?.replace(/^-\s*/, "");
|
|
858
842
|
const seed = bullet || lines[0];
|
|
859
|
-
if (!seed || seed.length < 8)
|
|
860
|
-
return null;
|
|
843
|
+
if (!seed || seed.length < 8) return null;
|
|
861
844
|
const topicPrefix = topics.length > 0 ? `[${topics.slice(0, 2).join(", ")}] ` : "";
|
|
862
845
|
return `${topicPrefix}${seed}`;
|
|
863
846
|
}
|
|
@@ -1018,8 +1001,7 @@ var ConsolidationWorker = class {
|
|
|
1018
1001
|
*/
|
|
1019
1002
|
extractKeyPoint(content) {
|
|
1020
1003
|
const sentences = content.split(/[.!?\n]+/).filter((s) => s.trim().length > 10);
|
|
1021
|
-
if (sentences.length === 0)
|
|
1022
|
-
return null;
|
|
1004
|
+
if (sentences.length === 0) return null;
|
|
1023
1005
|
const firstSentence = sentences[0].trim();
|
|
1024
1006
|
if (firstSentence.length > 100) {
|
|
1025
1007
|
return firstSentence.slice(0, 100) + "...";
|
|
@@ -1039,8 +1021,7 @@ var ConsolidationWorker = class {
|
|
|
1039
1021
|
* Calculate time proximity score
|
|
1040
1022
|
*/
|
|
1041
1023
|
calculateTimeProximity(events) {
|
|
1042
|
-
if (events.length < 2)
|
|
1043
|
-
return 1;
|
|
1024
|
+
if (events.length < 2) return 1;
|
|
1044
1025
|
const timestamps = events.map((e) => e.timestamp.getTime()).sort((a, b) => a - b);
|
|
1045
1026
|
const timeSpan = timestamps[timestamps.length - 1] - timestamps[0];
|
|
1046
1027
|
const avgGap = timeSpan / (events.length - 1);
|
|
@@ -1059,6 +1040,8 @@ var ContinuityManager = class {
|
|
|
1059
1040
|
this.eventStore = eventStore;
|
|
1060
1041
|
this.config = config;
|
|
1061
1042
|
}
|
|
1043
|
+
eventStore;
|
|
1044
|
+
config;
|
|
1062
1045
|
lastContext = null;
|
|
1063
1046
|
get db() {
|
|
1064
1047
|
return this.eventStore.getDatabase();
|
|
@@ -1178,8 +1161,7 @@ var ContinuityManager = class {
|
|
|
1178
1161
|
* Calculate overlap between two arrays
|
|
1179
1162
|
*/
|
|
1180
1163
|
calculateOverlap(a, b) {
|
|
1181
|
-
if (a.length === 0 || b.length === 0)
|
|
1182
|
-
return 0;
|
|
1164
|
+
if (a.length === 0 || b.length === 0) return 0;
|
|
1183
1165
|
const setA = new Set(a.map((s) => s.toLowerCase()));
|
|
1184
1166
|
const setB = new Set(b.map((s) => s.toLowerCase()));
|
|
1185
1167
|
const intersection = [...setA].filter((x) => setB.has(x));
|
|
@@ -1352,6 +1334,7 @@ var DefaultEndlessMemoryServices = class {
|
|
|
1352
1334
|
this.options = options;
|
|
1353
1335
|
this.factories = options.factories ? { ...options.factories, randomUUID: options.factories.randomUUID ?? randomUUID4 } : defaultFactories;
|
|
1354
1336
|
}
|
|
1337
|
+
options;
|
|
1355
1338
|
factories;
|
|
1356
1339
|
workingSetStore = null;
|
|
1357
1340
|
consolidatedStore = null;
|
|
@@ -1366,8 +1349,7 @@ var DefaultEndlessMemoryServices = class {
|
|
|
1366
1349
|
}
|
|
1367
1350
|
}
|
|
1368
1351
|
async initializeEndlessMode() {
|
|
1369
|
-
if (this.consolidationWorker)
|
|
1370
|
-
return;
|
|
1352
|
+
if (this.consolidationWorker) return;
|
|
1371
1353
|
const config = await this.getEndlessConfig();
|
|
1372
1354
|
const workingSetStore = this.factories.createWorkingSetStore(this.options.eventStore, config);
|
|
1373
1355
|
const consolidatedStore = this.factories.createConsolidatedStore(this.options.eventStore);
|
|
@@ -1399,8 +1381,7 @@ var DefaultEndlessMemoryServices = class {
|
|
|
1399
1381
|
}
|
|
1400
1382
|
async setMode(mode) {
|
|
1401
1383
|
await this.options.initialize();
|
|
1402
|
-
if (mode === this.mode)
|
|
1403
|
-
return;
|
|
1384
|
+
if (mode === this.mode) return;
|
|
1404
1385
|
this.mode = mode;
|
|
1405
1386
|
await this.options.configStore.setEndlessConfig("mode", mode);
|
|
1406
1387
|
if (mode === "endless") {
|
|
@@ -1416,33 +1397,27 @@ var DefaultEndlessMemoryServices = class {
|
|
|
1416
1397
|
return this.mode === "endless";
|
|
1417
1398
|
}
|
|
1418
1399
|
async addToWorkingSet(eventId, relevanceScore) {
|
|
1419
|
-
if (!this.workingSetStore)
|
|
1420
|
-
return;
|
|
1400
|
+
if (!this.workingSetStore) return;
|
|
1421
1401
|
await this.workingSetStore.add(eventId, relevanceScore);
|
|
1422
1402
|
}
|
|
1423
1403
|
async getWorkingSet() {
|
|
1424
|
-
if (!this.workingSetStore)
|
|
1425
|
-
return null;
|
|
1404
|
+
if (!this.workingSetStore) return null;
|
|
1426
1405
|
return this.workingSetStore.get();
|
|
1427
1406
|
}
|
|
1428
1407
|
async searchConsolidated(query, options) {
|
|
1429
|
-
if (!this.consolidatedStore)
|
|
1430
|
-
return [];
|
|
1408
|
+
if (!this.consolidatedStore) return [];
|
|
1431
1409
|
return this.consolidatedStore.search(query, options);
|
|
1432
1410
|
}
|
|
1433
1411
|
async getConsolidatedMemories(limit) {
|
|
1434
|
-
if (!this.consolidatedStore)
|
|
1435
|
-
return [];
|
|
1412
|
+
if (!this.consolidatedStore) return [];
|
|
1436
1413
|
return this.consolidatedStore.getAll({ limit });
|
|
1437
1414
|
}
|
|
1438
1415
|
async markMemoryAccessed(memoryId) {
|
|
1439
|
-
if (!this.consolidatedStore)
|
|
1440
|
-
return;
|
|
1416
|
+
if (!this.consolidatedStore) return;
|
|
1441
1417
|
await this.consolidatedStore.markAccessed(memoryId);
|
|
1442
1418
|
}
|
|
1443
1419
|
async calculateContinuity(content, metadata) {
|
|
1444
|
-
if (!this.continuityManager)
|
|
1445
|
-
return null;
|
|
1420
|
+
if (!this.continuityManager) return null;
|
|
1446
1421
|
const snapshot = this.continuityManager.createSnapshot(
|
|
1447
1422
|
this.factories.randomUUID(),
|
|
1448
1423
|
content,
|
|
@@ -1454,8 +1429,7 @@ var DefaultEndlessMemoryServices = class {
|
|
|
1454
1429
|
this.consolidationWorker?.recordActivity();
|
|
1455
1430
|
}
|
|
1456
1431
|
async forceConsolidation() {
|
|
1457
|
-
if (!this.consolidationWorker)
|
|
1458
|
-
return 0;
|
|
1432
|
+
if (!this.consolidationWorker) return 0;
|
|
1459
1433
|
return this.consolidationWorker.forceRun();
|
|
1460
1434
|
}
|
|
1461
1435
|
async getEndlessModeStatus() {
|
|
@@ -1547,8 +1521,7 @@ var Embedder = class _Embedder {
|
|
|
1547
1521
|
* Initialize the embedding pipeline
|
|
1548
1522
|
*/
|
|
1549
1523
|
async initialize() {
|
|
1550
|
-
if (this.initialized)
|
|
1551
|
-
return;
|
|
1524
|
+
if (this.initialized) return;
|
|
1552
1525
|
const pipeline = await withSuppressedKnownTransformersWarnings(async () => {
|
|
1553
1526
|
try {
|
|
1554
1527
|
return await loadTransformersPipeline();
|
|
@@ -1665,8 +1638,7 @@ async function withSuppressedKnownTransformersWarnings(fn) {
|
|
|
1665
1638
|
originalConsoleWarn = console.warn;
|
|
1666
1639
|
console.warn = (...args) => {
|
|
1667
1640
|
const message = args.map(String).join(" ");
|
|
1668
|
-
if (isKnownBenignTransformersWarning(message))
|
|
1669
|
-
return;
|
|
1641
|
+
if (isKnownBenignTransformersWarning(message)) return;
|
|
1670
1642
|
(originalConsoleWarn ?? console.warn)(...args);
|
|
1671
1643
|
};
|
|
1672
1644
|
}
|
|
@@ -1948,8 +1920,7 @@ var GraduationPipeline = class {
|
|
|
1948
1920
|
const preferenceKeywords = ["prefer", "like", "want", "always", "never", "favorite"];
|
|
1949
1921
|
const preferences = [];
|
|
1950
1922
|
for (const event of events) {
|
|
1951
|
-
if (event.eventType !== "user_prompt")
|
|
1952
|
-
continue;
|
|
1923
|
+
if (event.eventType !== "user_prompt") continue;
|
|
1953
1924
|
const lowerContent = event.content.toLowerCase();
|
|
1954
1925
|
for (const keyword of preferenceKeywords) {
|
|
1955
1926
|
if (lowerContent.includes(keyword)) {
|
|
@@ -2115,11 +2086,9 @@ function sanitizeSegment(input, fallback) {
|
|
|
2115
2086
|
return v || fallback;
|
|
2116
2087
|
}
|
|
2117
2088
|
function getAtPath(obj, dotted) {
|
|
2118
|
-
if (!obj)
|
|
2119
|
-
return void 0;
|
|
2089
|
+
if (!obj) return void 0;
|
|
2120
2090
|
return dotted.split(".").reduce((acc, key) => {
|
|
2121
|
-
if (!acc || typeof acc !== "object")
|
|
2122
|
-
return void 0;
|
|
2091
|
+
if (!acc || typeof acc !== "object") return void 0;
|
|
2123
2092
|
return acc[key];
|
|
2124
2093
|
}, obj);
|
|
2125
2094
|
}
|
|
@@ -2139,6 +2108,7 @@ var MarkdownMirror = class {
|
|
|
2139
2108
|
constructor(rootDir) {
|
|
2140
2109
|
this.rootDir = rootDir;
|
|
2141
2110
|
}
|
|
2111
|
+
rootDir;
|
|
2142
2112
|
async append(event, eventId) {
|
|
2143
2113
|
const out = buildMirrorPath(this.rootDir, event);
|
|
2144
2114
|
fs2.mkdirSync(path2.dirname(out), { recursive: true });
|
|
@@ -2270,10 +2240,8 @@ function sqliteClose(db) {
|
|
|
2270
2240
|
db.close();
|
|
2271
2241
|
}
|
|
2272
2242
|
function toDateFromSQLite(value) {
|
|
2273
|
-
if (value instanceof Date)
|
|
2274
|
-
|
|
2275
|
-
if (typeof value === "number")
|
|
2276
|
-
return new Date(value);
|
|
2243
|
+
if (value instanceof Date) return value;
|
|
2244
|
+
if (typeof value === "number") return new Date(value);
|
|
2277
2245
|
if (typeof value === "string") {
|
|
2278
2246
|
const trimmed = value.trim();
|
|
2279
2247
|
if (/^\d{4}-\d{2}-\d{2}[ T]\d{2}:\d{2}:\d{2}(?:\.\d+)?$/.test(trimmed)) {
|
|
@@ -2295,8 +2263,7 @@ var DEFAULT_CATEGORY = "uncategorized";
|
|
|
2295
2263
|
function sanitizeSegment2(input, fallback) {
|
|
2296
2264
|
const raw = String(input ?? "").trim().toLowerCase();
|
|
2297
2265
|
const safe = raw.normalize("NFKD").replace(/[^a-z0-9_-]+/g, "-").replace(/^-+|-+$/g, "");
|
|
2298
|
-
if (!safe || safe === "." || safe === "..")
|
|
2299
|
-
return fallback;
|
|
2266
|
+
if (!safe || safe === "." || safe === "..") return fallback;
|
|
2300
2267
|
return safe;
|
|
2301
2268
|
}
|
|
2302
2269
|
function getCategorySegments(metadata, eventType) {
|
|
@@ -2337,6 +2304,7 @@ var MarkdownMirror2 = class {
|
|
|
2337
2304
|
constructor(rootDir) {
|
|
2338
2305
|
this.rootDir = rootDir;
|
|
2339
2306
|
}
|
|
2307
|
+
rootDir;
|
|
2340
2308
|
async append(event) {
|
|
2341
2309
|
const outPath = buildMirrorPath2(this.rootDir, event);
|
|
2342
2310
|
await fs5.mkdir(path4.dirname(outPath), { recursive: true });
|
|
@@ -2359,6 +2327,7 @@ var VectorOutbox = class {
|
|
|
2359
2327
|
this.db = db;
|
|
2360
2328
|
this.config = { ...DEFAULT_CONFIG2, ...config };
|
|
2361
2329
|
}
|
|
2330
|
+
db;
|
|
2362
2331
|
config;
|
|
2363
2332
|
/**
|
|
2364
2333
|
* Enqueue item for vectorization (idempotent).
|
|
@@ -2455,8 +2424,7 @@ var VectorOutbox = class {
|
|
|
2455
2424
|
`SELECT retry_count FROM vector_outbox WHERE job_id = ?`,
|
|
2456
2425
|
[jobId]
|
|
2457
2426
|
);
|
|
2458
|
-
if (rows.length === 0)
|
|
2459
|
-
return;
|
|
2427
|
+
if (rows.length === 0) return;
|
|
2460
2428
|
const retryCount = rows[0].retry_count;
|
|
2461
2429
|
const newStatus = retryCount >= this.config.maxRetries - 1 ? "failed" : "pending";
|
|
2462
2430
|
await dbRun(
|
|
@@ -2476,8 +2444,7 @@ var VectorOutbox = class {
|
|
|
2476
2444
|
`SELECT * FROM vector_outbox WHERE job_id = ?`,
|
|
2477
2445
|
[jobId]
|
|
2478
2446
|
);
|
|
2479
|
-
if (rows.length === 0)
|
|
2480
|
-
return null;
|
|
2447
|
+
if (rows.length === 0) return null;
|
|
2481
2448
|
return this.rowToJob(rows[0]);
|
|
2482
2449
|
}
|
|
2483
2450
|
/**
|
|
@@ -2611,30 +2578,24 @@ function isRetrievalDebugLaneName(value) {
|
|
|
2611
2578
|
return typeof value === "string" && RETRIEVAL_DEBUG_LANE_NAME_SET.has(value);
|
|
2612
2579
|
}
|
|
2613
2580
|
function normalizeRetrievalDebugLanes(value, maxItems = 6) {
|
|
2614
|
-
if (!Array.isArray(value) || maxItems <= 0)
|
|
2615
|
-
return [];
|
|
2581
|
+
if (!Array.isArray(value) || maxItems <= 0) return [];
|
|
2616
2582
|
const normalized = [];
|
|
2617
2583
|
const seen = /* @__PURE__ */ new Set();
|
|
2618
2584
|
for (const item of value) {
|
|
2619
2585
|
const lane = normalizeRetrievalDebugLane(item);
|
|
2620
|
-
if (!lane)
|
|
2621
|
-
continue;
|
|
2586
|
+
if (!lane) continue;
|
|
2622
2587
|
const key = [lane.lane, lane.reason, lane.score ?? ""].join("\0");
|
|
2623
|
-
if (seen.has(key))
|
|
2624
|
-
continue;
|
|
2588
|
+
if (seen.has(key)) continue;
|
|
2625
2589
|
seen.add(key);
|
|
2626
2590
|
normalized.push(lane);
|
|
2627
|
-
if (normalized.length >= maxItems)
|
|
2628
|
-
break;
|
|
2591
|
+
if (normalized.length >= maxItems) break;
|
|
2629
2592
|
}
|
|
2630
2593
|
return normalized;
|
|
2631
2594
|
}
|
|
2632
2595
|
function normalizeRetrievalDebugLane(value) {
|
|
2633
|
-
if (!value || typeof value !== "object")
|
|
2634
|
-
return null;
|
|
2596
|
+
if (!value || typeof value !== "object") return null;
|
|
2635
2597
|
const raw = value;
|
|
2636
|
-
if (!isRetrievalDebugLaneName(raw.lane))
|
|
2637
|
-
return null;
|
|
2598
|
+
if (!isRetrievalDebugLaneName(raw.lane)) return null;
|
|
2638
2599
|
const reason = sanitizeRetrievalLaneReason(typeof raw.reason === "string" ? raw.reason : "") || "unspecified";
|
|
2639
2600
|
const score = typeof raw.score === "number" && Number.isFinite(raw.score) ? Math.max(0, Math.min(1, raw.score)) : void 0;
|
|
2640
2601
|
return score === void 0 ? { lane: raw.lane, reason } : { lane: raw.lane, reason, score };
|
|
@@ -2657,27 +2618,21 @@ function normalizeRetrievalTraceDetails(details) {
|
|
|
2657
2618
|
eventId: detail.eventId,
|
|
2658
2619
|
score: detail.score
|
|
2659
2620
|
};
|
|
2660
|
-
if (detail.semanticScore !== void 0)
|
|
2661
|
-
|
|
2662
|
-
if (detail.
|
|
2663
|
-
|
|
2664
|
-
if (detail.recencyScore !== void 0)
|
|
2665
|
-
normalized.recencyScore = detail.recencyScore;
|
|
2666
|
-
if (lanes.length > 0)
|
|
2667
|
-
normalized.lanes = lanes;
|
|
2621
|
+
if (detail.semanticScore !== void 0) normalized.semanticScore = detail.semanticScore;
|
|
2622
|
+
if (detail.lexicalScore !== void 0) normalized.lexicalScore = detail.lexicalScore;
|
|
2623
|
+
if (detail.recencyScore !== void 0) normalized.recencyScore = detail.recencyScore;
|
|
2624
|
+
if (lanes.length > 0) normalized.lanes = lanes;
|
|
2668
2625
|
return normalized;
|
|
2669
2626
|
});
|
|
2670
2627
|
}
|
|
2671
2628
|
function parseRetrievalTraceDetails(value) {
|
|
2672
|
-
if (typeof value !== "string" || value.length === 0)
|
|
2673
|
-
return [];
|
|
2629
|
+
if (typeof value !== "string" || value.length === 0) return [];
|
|
2674
2630
|
const parsed = JSON.parse(value);
|
|
2675
2631
|
return Array.isArray(parsed) ? normalizeRetrievalTraceDetails(parsed) : [];
|
|
2676
2632
|
}
|
|
2677
2633
|
function normalizeQueryRewriteKind(value) {
|
|
2678
2634
|
const normalized = (value || "").trim().toLowerCase();
|
|
2679
|
-
if (normalized === "follow-up-context" || normalized === "intent-rewrite")
|
|
2680
|
-
return normalized;
|
|
2635
|
+
if (normalized === "follow-up-context" || normalized === "intent-rewrite") return normalized;
|
|
2681
2636
|
return "none";
|
|
2682
2637
|
}
|
|
2683
2638
|
var REWRITTEN_QUERY_REWRITE_KIND_SQL = `LOWER(TRIM(COALESCE(query_rewrite_kind, 'none'))) IN ('follow-up-context', 'intent-rewrite')`;
|
|
@@ -2695,8 +2650,7 @@ function isRecord(value) {
|
|
|
2695
2650
|
function getNestedRecord(root, path14) {
|
|
2696
2651
|
let cursor = root;
|
|
2697
2652
|
for (const key of path14) {
|
|
2698
|
-
if (!isRecord(cursor))
|
|
2699
|
-
return void 0;
|
|
2653
|
+
if (!isRecord(cursor)) return void 0;
|
|
2700
2654
|
cursor = cursor[key];
|
|
2701
2655
|
}
|
|
2702
2656
|
return isRecord(cursor) ? cursor : void 0;
|
|
@@ -2704,8 +2658,7 @@ function getNestedRecord(root, path14) {
|
|
|
2704
2658
|
function getNestedString(root, path14) {
|
|
2705
2659
|
let cursor = root;
|
|
2706
2660
|
for (const key of path14) {
|
|
2707
|
-
if (!isRecord(cursor))
|
|
2708
|
-
return void 0;
|
|
2661
|
+
if (!isRecord(cursor)) return void 0;
|
|
2709
2662
|
cursor = cursor[key];
|
|
2710
2663
|
}
|
|
2711
2664
|
return typeof cursor === "string" && cursor.length > 0 ? cursor : void 0;
|
|
@@ -2721,8 +2674,7 @@ function metadataProjectPaths(metadata) {
|
|
|
2721
2674
|
];
|
|
2722
2675
|
const paths = [];
|
|
2723
2676
|
for (const value of candidates) {
|
|
2724
|
-
if (value && !paths.includes(value))
|
|
2725
|
-
paths.push(value);
|
|
2677
|
+
if (value && !paths.includes(value)) paths.push(value);
|
|
2726
2678
|
}
|
|
2727
2679
|
return paths;
|
|
2728
2680
|
}
|
|
@@ -2743,12 +2695,9 @@ function maybeQuarantinePredicate(options, column = "metadata") {
|
|
|
2743
2695
|
return options?.includeQuarantined ? "1=1" : notActiveQuarantinedSql(column);
|
|
2744
2696
|
}
|
|
2745
2697
|
function safeParseMetadataValue(value) {
|
|
2746
|
-
if (!value)
|
|
2747
|
-
|
|
2748
|
-
if (typeof value
|
|
2749
|
-
return isRecord(value) ? value : void 0;
|
|
2750
|
-
if (typeof value !== "string")
|
|
2751
|
-
return void 0;
|
|
2698
|
+
if (!value) return void 0;
|
|
2699
|
+
if (typeof value === "object") return isRecord(value) ? value : void 0;
|
|
2700
|
+
if (typeof value !== "string") return void 0;
|
|
2752
2701
|
try {
|
|
2753
2702
|
const parsed = JSON.parse(value);
|
|
2754
2703
|
return isRecord(parsed) ? parsed : void 0;
|
|
@@ -2757,16 +2706,14 @@ function safeParseMetadataValue(value) {
|
|
|
2757
2706
|
}
|
|
2758
2707
|
}
|
|
2759
2708
|
function isImportedOrLegacyScopedMetadata(metadata) {
|
|
2760
|
-
if (!metadata)
|
|
2761
|
-
return false;
|
|
2709
|
+
if (!metadata) return false;
|
|
2762
2710
|
return Boolean(
|
|
2763
2711
|
metadata.importedFrom || metadata.sourceSessionId || metadata.sourceSessionHash || metadata.hermesSource || metadata.projectPath || metadata.sourceProjectPath || metadata.source === "hermes" || metadata.source === "claude" || metadata.source === "codex"
|
|
2764
2712
|
);
|
|
2765
2713
|
}
|
|
2766
2714
|
function addMetadataTag(metadata, tag) {
|
|
2767
2715
|
const current = Array.isArray(metadata.tags) ? metadata.tags.filter((value) => typeof value === "string") : [];
|
|
2768
|
-
if (!current.includes(tag))
|
|
2769
|
-
metadata.tags = [...current, tag];
|
|
2716
|
+
if (!current.includes(tag)) metadata.tags = [...current, tag];
|
|
2770
2717
|
}
|
|
2771
2718
|
function buildRepairResult(projectHash, dryRun) {
|
|
2772
2719
|
return {
|
|
@@ -2784,8 +2731,7 @@ function normalizeRepoName(value) {
|
|
|
2784
2731
|
return value.replace(/\.git$/i, "").trim().toLowerCase();
|
|
2785
2732
|
}
|
|
2786
2733
|
function projectBasename(projectPath) {
|
|
2787
|
-
if (!projectPath)
|
|
2788
|
-
return void 0;
|
|
2734
|
+
if (!projectPath) return void 0;
|
|
2789
2735
|
const trimmed = projectPath.replace(/[\\/]+$/, "");
|
|
2790
2736
|
const basename2 = nodePath2.basename(trimmed);
|
|
2791
2737
|
return basename2 ? normalizeRepoName(basename2) : void 0;
|
|
@@ -2798,23 +2744,19 @@ function isProjectScopeRepairExplanation(content) {
|
|
|
2798
2744
|
}
|
|
2799
2745
|
function hasConflictingContentProjectHint(content, projectPath) {
|
|
2800
2746
|
const currentName = projectBasename(projectPath);
|
|
2801
|
-
if (!currentName)
|
|
2802
|
-
|
|
2803
|
-
if (isProjectScopeRepairExplanation(content))
|
|
2804
|
-
return false;
|
|
2747
|
+
if (!currentName) return false;
|
|
2748
|
+
if (isProjectScopeRepairExplanation(content)) return false;
|
|
2805
2749
|
const githubRepoPattern = /github\.com[:/]([^/\s`'"#)]+)\/([^/\s`'"#)]+)(?:\.git)?/gi;
|
|
2806
2750
|
let githubMatch;
|
|
2807
2751
|
while ((githubMatch = githubRepoPattern.exec(content)) !== null) {
|
|
2808
2752
|
const repo = normalizeRepoName(githubMatch[2] || "");
|
|
2809
|
-
if (repo && repo !== currentName)
|
|
2810
|
-
return true;
|
|
2753
|
+
if (repo && repo !== currentName) return true;
|
|
2811
2754
|
}
|
|
2812
2755
|
const workspacePathPattern = /\/workspace\/([^/\s`'"#)]+)/gi;
|
|
2813
2756
|
let workspaceMatch;
|
|
2814
2757
|
while ((workspaceMatch = workspacePathPattern.exec(content)) !== null) {
|
|
2815
2758
|
const repo = normalizeRepoName(workspaceMatch[1] || "");
|
|
2816
|
-
if (repo && repo !== currentName)
|
|
2817
|
-
return true;
|
|
2759
|
+
if (repo && repo !== currentName) return true;
|
|
2818
2760
|
}
|
|
2819
2761
|
return false;
|
|
2820
2762
|
}
|
|
@@ -2834,15 +2776,12 @@ var SQLiteEventStore = class {
|
|
|
2834
2776
|
this.vectorOutbox = this.createVectorOutbox(options?.vectorOutbox);
|
|
2835
2777
|
}
|
|
2836
2778
|
createVectorOutbox(option) {
|
|
2837
|
-
if (this.readOnly || option === false)
|
|
2838
|
-
|
|
2839
|
-
if (option instanceof VectorOutbox)
|
|
2840
|
-
return option;
|
|
2779
|
+
if (this.readOnly || option === false) return null;
|
|
2780
|
+
if (option instanceof VectorOutbox) return option;
|
|
2841
2781
|
return new VectorOutbox(this.db, option ?? {});
|
|
2842
2782
|
}
|
|
2843
2783
|
enqueueVectorOutboxEventSync(eventId) {
|
|
2844
|
-
if (!this.vectorOutbox)
|
|
2845
|
-
return;
|
|
2784
|
+
if (!this.vectorOutbox) return;
|
|
2846
2785
|
this.vectorOutbox.enqueueSync("event", eventId);
|
|
2847
2786
|
}
|
|
2848
2787
|
async enqueueVectorOutboxEvent(eventId) {
|
|
@@ -2852,8 +2791,7 @@ var SQLiteEventStore = class {
|
|
|
2852
2791
|
* Initialize database schema
|
|
2853
2792
|
*/
|
|
2854
2793
|
async initialize() {
|
|
2855
|
-
if (this.initialized)
|
|
2856
|
-
return;
|
|
2794
|
+
if (this.initialized) return;
|
|
2857
2795
|
if (this.readOnly) {
|
|
2858
2796
|
this.initialized = true;
|
|
2859
2797
|
return;
|
|
@@ -3411,10 +3349,8 @@ var SQLiteEventStore = class {
|
|
|
3411
3349
|
try {
|
|
3412
3350
|
const edgeIndexes = sqliteAll(this.db, `PRAGMA index_list(memory_action_edges)`, []);
|
|
3413
3351
|
const hasSourceAwareUnique = edgeIndexes.some((index) => {
|
|
3414
|
-
if (Number(index.unique) !== 1)
|
|
3415
|
-
|
|
3416
|
-
if (!/^[A-Za-z0-9_]+$/.test(index.name))
|
|
3417
|
-
return false;
|
|
3352
|
+
if (Number(index.unique) !== 1) return false;
|
|
3353
|
+
if (!/^[A-Za-z0-9_]+$/.test(index.name)) return false;
|
|
3418
3354
|
const escapedName = index.name.replace(/"/g, '""');
|
|
3419
3355
|
const columns = sqliteAll(this.db, 'PRAGMA index_info("' + escapedName + '")', []).map((column) => column.name);
|
|
3420
3356
|
return columns.length === 5 && columns[0] === "src_action_id" && columns[1] === "rel_type" && columns[2] === "dst_type" && columns[3] === "dst_id" && columns[4] === "source";
|
|
@@ -3654,8 +3590,7 @@ var SQLiteEventStore = class {
|
|
|
3654
3590
|
`SELECT * FROM events WHERE id = ? AND ${maybeQuarantinePredicate(options)}`,
|
|
3655
3591
|
[id]
|
|
3656
3592
|
);
|
|
3657
|
-
if (!row)
|
|
3658
|
-
return null;
|
|
3593
|
+
if (!row) return null;
|
|
3659
3594
|
return this.rowToEvent(row);
|
|
3660
3595
|
}
|
|
3661
3596
|
/**
|
|
@@ -3693,10 +3628,8 @@ var SQLiteEventStore = class {
|
|
|
3693
3628
|
* NOTE: This bypasses the append() id generation to preserve stable IDs.
|
|
3694
3629
|
*/
|
|
3695
3630
|
async importEvents(events) {
|
|
3696
|
-
if (events.length === 0)
|
|
3697
|
-
|
|
3698
|
-
if (this.readOnly)
|
|
3699
|
-
return { inserted: 0, skipped: events.length };
|
|
3631
|
+
if (events.length === 0) return { inserted: 0, skipped: 0 };
|
|
3632
|
+
if (this.readOnly) return { inserted: 0, skipped: events.length };
|
|
3700
3633
|
await this.initialize();
|
|
3701
3634
|
const getById = this.db.prepare(`SELECT id FROM events WHERE id = ?`);
|
|
3702
3635
|
const getByDedupe = this.db.prepare(`SELECT event_id FROM event_dedup WHERE dedupe_key = ?`);
|
|
@@ -3814,8 +3747,7 @@ var SQLiteEventStore = class {
|
|
|
3814
3747
|
`SELECT * FROM sessions WHERE id = ?`,
|
|
3815
3748
|
[id]
|
|
3816
3749
|
);
|
|
3817
|
-
if (!row)
|
|
3818
|
-
return null;
|
|
3750
|
+
if (!row) return null;
|
|
3819
3751
|
return {
|
|
3820
3752
|
id: row.id,
|
|
3821
3753
|
startedAt: toDateFromSQLite(row.started_at),
|
|
@@ -3870,8 +3802,7 @@ var SQLiteEventStore = class {
|
|
|
3870
3802
|
LIMIT ?`,
|
|
3871
3803
|
[limit]
|
|
3872
3804
|
);
|
|
3873
|
-
if (pending.length === 0)
|
|
3874
|
-
return [];
|
|
3805
|
+
if (pending.length === 0) return [];
|
|
3875
3806
|
const ids = pending.map((r) => r.id);
|
|
3876
3807
|
const placeholders = ids.map(() => "?").join(",");
|
|
3877
3808
|
sqliteRun(
|
|
@@ -3895,8 +3826,7 @@ var SQLiteEventStore = class {
|
|
|
3895
3826
|
* Mark outbox items as done
|
|
3896
3827
|
*/
|
|
3897
3828
|
async completeOutboxItems(ids) {
|
|
3898
|
-
if (ids.length === 0)
|
|
3899
|
-
return;
|
|
3829
|
+
if (ids.length === 0) return;
|
|
3900
3830
|
const placeholders = ids.map(() => "?").join(",");
|
|
3901
3831
|
sqliteRun(
|
|
3902
3832
|
this.db,
|
|
@@ -3935,8 +3865,7 @@ var SQLiteEventStore = class {
|
|
|
3935
3865
|
* Mark outbox items as failed
|
|
3936
3866
|
*/
|
|
3937
3867
|
async failOutboxItems(ids, error) {
|
|
3938
|
-
if (ids.length === 0)
|
|
3939
|
-
return;
|
|
3868
|
+
if (ids.length === 0) return;
|
|
3940
3869
|
const placeholders = ids.map(() => "?").join(",");
|
|
3941
3870
|
sqliteRun(
|
|
3942
3871
|
this.db,
|
|
@@ -4063,8 +3992,7 @@ var SQLiteEventStore = class {
|
|
|
4063
3992
|
[]
|
|
4064
3993
|
);
|
|
4065
3994
|
const sample = (entry) => {
|
|
4066
|
-
if (result.samples.length < 20)
|
|
4067
|
-
result.samples.push(entry);
|
|
3995
|
+
if (result.samples.length < 20) result.samples.push(entry);
|
|
4068
3996
|
};
|
|
4069
3997
|
for (const row of rows) {
|
|
4070
3998
|
result.scanned++;
|
|
@@ -4191,12 +4119,10 @@ var SQLiteEventStore = class {
|
|
|
4191
4119
|
`SELECT status, COUNT(*) as count FROM vector_outbox GROUP BY status`
|
|
4192
4120
|
);
|
|
4193
4121
|
const processingAgeMs = (value) => {
|
|
4194
|
-
if (value === null || value === void 0)
|
|
4195
|
-
return null;
|
|
4122
|
+
if (value === null || value === void 0) return null;
|
|
4196
4123
|
const date = toDateFromSQLite(value);
|
|
4197
4124
|
const time = date.getTime();
|
|
4198
|
-
if (!Number.isFinite(time))
|
|
4199
|
-
return null;
|
|
4125
|
+
if (!Number.isFinite(time)) return null;
|
|
4200
4126
|
return Math.max(0, now.getTime() - time);
|
|
4201
4127
|
};
|
|
4202
4128
|
const fromRows = (rows, stuckProcessing, oldestProcessingAgeMs) => {
|
|
@@ -4345,8 +4271,7 @@ var SQLiteEventStore = class {
|
|
|
4345
4271
|
`SELECT value FROM endless_config WHERE key = ?`,
|
|
4346
4272
|
[key]
|
|
4347
4273
|
);
|
|
4348
|
-
if (!row)
|
|
4349
|
-
return null;
|
|
4274
|
+
if (!row) return null;
|
|
4350
4275
|
return JSON.parse(row.value);
|
|
4351
4276
|
}
|
|
4352
4277
|
/**
|
|
@@ -4365,8 +4290,7 @@ var SQLiteEventStore = class {
|
|
|
4365
4290
|
* Increment access count for events
|
|
4366
4291
|
*/
|
|
4367
4292
|
async incrementAccessCount(eventIds) {
|
|
4368
|
-
if (eventIds.length === 0 || this.readOnly)
|
|
4369
|
-
return;
|
|
4293
|
+
if (eventIds.length === 0 || this.readOnly) return;
|
|
4370
4294
|
await this.initialize();
|
|
4371
4295
|
const placeholders = eventIds.map(() => "?").join(",");
|
|
4372
4296
|
const currentTime = toSQLiteTimestamp(/* @__PURE__ */ new Date());
|
|
@@ -4409,8 +4333,7 @@ var SQLiteEventStore = class {
|
|
|
4409
4333
|
* Record a memory retrieval for helpfulness tracking
|
|
4410
4334
|
*/
|
|
4411
4335
|
async recordRetrieval(eventId, sessionId, score, query) {
|
|
4412
|
-
if (this.readOnly)
|
|
4413
|
-
return;
|
|
4336
|
+
if (this.readOnly) return;
|
|
4414
4337
|
await this.initialize();
|
|
4415
4338
|
const id = randomUUID6();
|
|
4416
4339
|
sqliteRun(
|
|
@@ -4440,16 +4363,14 @@ var SQLiteEventStore = class {
|
|
|
4440
4363
|
* Called at session end - uses behavioral signals to compute score
|
|
4441
4364
|
*/
|
|
4442
4365
|
async evaluateSessionHelpfulness(sessionId) {
|
|
4443
|
-
if (this.readOnly)
|
|
4444
|
-
return;
|
|
4366
|
+
if (this.readOnly) return;
|
|
4445
4367
|
await this.initialize();
|
|
4446
4368
|
const retrievals = sqliteAll(
|
|
4447
4369
|
this.db,
|
|
4448
4370
|
`SELECT * FROM memory_helpfulness WHERE session_id = ? AND measured_at IS NULL`,
|
|
4449
4371
|
[sessionId]
|
|
4450
4372
|
);
|
|
4451
|
-
if (retrievals.length === 0)
|
|
4452
|
-
return;
|
|
4373
|
+
if (retrievals.length === 0) return;
|
|
4453
4374
|
const sessionEvents = sqliteAll(
|
|
4454
4375
|
this.db,
|
|
4455
4376
|
`SELECT * FROM events WHERE session_id = ? ORDER BY timestamp ASC`,
|
|
@@ -4462,8 +4383,7 @@ var SQLiteEventStore = class {
|
|
|
4462
4383
|
for (const t of toolEvents) {
|
|
4463
4384
|
try {
|
|
4464
4385
|
const content = JSON.parse(t.content);
|
|
4465
|
-
if (content.success !== false)
|
|
4466
|
-
toolSuccessCount++;
|
|
4386
|
+
if (content.success !== false) toolSuccessCount++;
|
|
4467
4387
|
} catch {
|
|
4468
4388
|
toolSuccessCount++;
|
|
4469
4389
|
}
|
|
@@ -4481,8 +4401,7 @@ var SQLiteEventStore = class {
|
|
|
4481
4401
|
const pWords = new Set(p.content.toLowerCase().split(/\s+/).filter((w) => w.length > 2));
|
|
4482
4402
|
let overlap = 0;
|
|
4483
4403
|
for (const w of queryWords) {
|
|
4484
|
-
if (pWords.has(w))
|
|
4485
|
-
overlap++;
|
|
4404
|
+
if (pWords.has(w)) overlap++;
|
|
4486
4405
|
}
|
|
4487
4406
|
if (queryWords.size > 0 && overlap / queryWords.size > 0.5) {
|
|
4488
4407
|
wasReasked = 1;
|
|
@@ -4664,8 +4583,7 @@ var SQLiteEventStore = class {
|
|
|
4664
4583
|
return this.db;
|
|
4665
4584
|
}
|
|
4666
4585
|
hasTableColumn(tableName, columnName2) {
|
|
4667
|
-
if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(tableName))
|
|
4668
|
-
return false;
|
|
4586
|
+
if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(tableName)) return false;
|
|
4669
4587
|
try {
|
|
4670
4588
|
const rows = sqliteAll(this.db, `PRAGMA table_info("${tableName}")`, []);
|
|
4671
4589
|
return rows.some((row) => row.name === columnName2);
|
|
@@ -4732,8 +4650,7 @@ var SQLiteEventStore = class {
|
|
|
4732
4650
|
createdAt: toDateFromSQLite(row.created_at)
|
|
4733
4651
|
}));
|
|
4734
4652
|
} catch (err) {
|
|
4735
|
-
if (err?.message?.includes("no such table"))
|
|
4736
|
-
return [];
|
|
4653
|
+
if (err?.message?.includes("no such table")) return [];
|
|
4737
4654
|
throw err;
|
|
4738
4655
|
}
|
|
4739
4656
|
}
|
|
@@ -4906,8 +4823,7 @@ var SQLiteEventStore = class {
|
|
|
4906
4823
|
`SELECT id FROM events WHERE session_id = ?`,
|
|
4907
4824
|
[sessionId]
|
|
4908
4825
|
);
|
|
4909
|
-
if (events.length === 0)
|
|
4910
|
-
return 0;
|
|
4826
|
+
if (events.length === 0) return 0;
|
|
4911
4827
|
const eventIds = events.map((e) => e.id);
|
|
4912
4828
|
const placeholders = eventIds.map(() => "?").join(",");
|
|
4913
4829
|
const ftsTriggersDropped = [];
|
|
@@ -5119,8 +5035,7 @@ function sanitizeGovernanceAuditValue(value, key) {
|
|
|
5119
5035
|
return value;
|
|
5120
5036
|
}
|
|
5121
5037
|
function sanitizeAuditJson(value) {
|
|
5122
|
-
if (value === void 0)
|
|
5123
|
-
return void 0;
|
|
5038
|
+
if (value === void 0) return void 0;
|
|
5124
5039
|
return sanitizeGovernanceAuditValue(value);
|
|
5125
5040
|
}
|
|
5126
5041
|
function normalizeSourceEventIds(sourceEventIds) {
|
|
@@ -5169,12 +5084,10 @@ async function writeGovernanceAuditEntry(db, input) {
|
|
|
5169
5084
|
|
|
5170
5085
|
// src/core/operations/facet-repository.ts
|
|
5171
5086
|
function parseStringArray(value) {
|
|
5172
|
-
if (typeof value !== "string")
|
|
5173
|
-
return [];
|
|
5087
|
+
if (typeof value !== "string") return [];
|
|
5174
5088
|
try {
|
|
5175
5089
|
const parsed = JSON.parse(value);
|
|
5176
|
-
if (!Array.isArray(parsed))
|
|
5177
|
-
return [];
|
|
5090
|
+
if (!Array.isArray(parsed)) return [];
|
|
5178
5091
|
return parsed.filter((item) => typeof item === "string" && item.length > 0);
|
|
5179
5092
|
} catch {
|
|
5180
5093
|
return [];
|
|
@@ -5218,6 +5131,7 @@ var FacetRepository = class {
|
|
|
5218
5131
|
constructor(db) {
|
|
5219
5132
|
this.db = db;
|
|
5220
5133
|
}
|
|
5134
|
+
db;
|
|
5221
5135
|
async assign(input) {
|
|
5222
5136
|
const assignment = parseFacetAssignmentInput(input);
|
|
5223
5137
|
const existing = this.findByUniqueKey(assignment);
|
|
@@ -5522,19 +5436,14 @@ var RetentionFacetSchema = z5.object({
|
|
|
5522
5436
|
confidence: z5.number().min(0).max(1).default(1)
|
|
5523
5437
|
});
|
|
5524
5438
|
var DateLikeSchema = z5.preprocess((value) => {
|
|
5525
|
-
if (value instanceof Date)
|
|
5526
|
-
|
|
5527
|
-
if (typeof value === "string" || typeof value === "number")
|
|
5528
|
-
return new Date(value);
|
|
5439
|
+
if (value instanceof Date) return value;
|
|
5440
|
+
if (typeof value === "string" || typeof value === "number") return new Date(value);
|
|
5529
5441
|
return value;
|
|
5530
5442
|
}, z5.date());
|
|
5531
5443
|
var NullableDateLikeSchema = z5.preprocess((value) => {
|
|
5532
|
-
if (value === null || value === void 0 || value === "")
|
|
5533
|
-
|
|
5534
|
-
if (value
|
|
5535
|
-
return value;
|
|
5536
|
-
if (typeof value === "string" || typeof value === "number")
|
|
5537
|
-
return new Date(value);
|
|
5444
|
+
if (value === null || value === void 0 || value === "") return null;
|
|
5445
|
+
if (value instanceof Date) return value;
|
|
5446
|
+
if (typeof value === "string" || typeof value === "number") return new Date(value);
|
|
5538
5447
|
return value;
|
|
5539
5448
|
}, z5.date().nullable());
|
|
5540
5449
|
var OptionalTrimmedStringSchema2 = z5.preprocess(
|
|
@@ -5563,10 +5472,8 @@ import { z as z6 } from "zod";
|
|
|
5563
5472
|
var RequiredTrimmedStringSchema = z6.string().trim().min(1);
|
|
5564
5473
|
var OptionalTrimmedStringSchema3 = z6.string().trim().min(1).optional();
|
|
5565
5474
|
var DateLikeSchema2 = z6.preprocess((value) => {
|
|
5566
|
-
if (value instanceof Date)
|
|
5567
|
-
|
|
5568
|
-
if (typeof value === "string" || typeof value === "number")
|
|
5569
|
-
return new Date(value);
|
|
5475
|
+
if (value instanceof Date) return value;
|
|
5476
|
+
if (typeof value === "string" || typeof value === "number") return new Date(value);
|
|
5570
5477
|
return value;
|
|
5571
5478
|
}, z6.date());
|
|
5572
5479
|
var RetentionReasonSchema = z6.object({
|
|
@@ -5755,8 +5662,7 @@ var MemoryOperationsConfigSchema = z7.object({
|
|
|
5755
5662
|
}).default({});
|
|
5756
5663
|
var MemoryLessonNonEmptyStringSchema = z7.string().transform((value) => value.trim()).pipe(z7.string().min(1));
|
|
5757
5664
|
var MemoryLessonStringArraySchema = z7.preprocess((value) => {
|
|
5758
|
-
if (!Array.isArray(value))
|
|
5759
|
-
return value;
|
|
5665
|
+
if (!Array.isArray(value)) return value;
|
|
5760
5666
|
return value.map((item) => typeof item === "string" ? item.trim() : item).filter((item) => typeof item !== "string" || item.length > 0);
|
|
5761
5667
|
}, z7.array(MemoryLessonNonEmptyStringSchema)).default([]);
|
|
5762
5668
|
var MemoryLessonSchema = z7.object({
|
|
@@ -5801,14 +5707,12 @@ var ListMemoryLessonsInputSchema = z7.object({
|
|
|
5801
5707
|
});
|
|
5802
5708
|
var PerspectiveMemoryNonEmptyStringSchema = z7.string().transform((value) => value.trim()).pipe(z7.string().min(1));
|
|
5803
5709
|
var PerspectiveMemoryOptionalStringSchema = z7.preprocess((value) => {
|
|
5804
|
-
if (typeof value !== "string")
|
|
5805
|
-
return value;
|
|
5710
|
+
if (typeof value !== "string") return value;
|
|
5806
5711
|
const normalized = value.trim();
|
|
5807
5712
|
return normalized.length > 0 ? normalized : void 0;
|
|
5808
5713
|
}, PerspectiveMemoryNonEmptyStringSchema.optional());
|
|
5809
5714
|
var PerspectiveMemoryStringArraySchema = z7.preprocess((value) => {
|
|
5810
|
-
if (!Array.isArray(value))
|
|
5811
|
-
return value;
|
|
5715
|
+
if (!Array.isArray(value)) return value;
|
|
5812
5716
|
return value.map((item) => typeof item === "string" ? item.trim() : item).filter((item) => typeof item !== "string" || item.length > 0);
|
|
5813
5717
|
}, z7.array(PerspectiveMemoryNonEmptyStringSchema)).default([]);
|
|
5814
5718
|
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;
|
|
@@ -6466,6 +6370,7 @@ var GraphPathService = class {
|
|
|
6466
6370
|
constructor(db) {
|
|
6467
6371
|
this.db = db;
|
|
6468
6372
|
}
|
|
6373
|
+
db;
|
|
6469
6374
|
expand(input) {
|
|
6470
6375
|
const graph = this.loadGraph(input.direction ?? "both");
|
|
6471
6376
|
const effectiveMaxHops = normalizeMaxHops(input.maxHops);
|
|
@@ -6483,11 +6388,9 @@ var GraphPathService = class {
|
|
|
6483
6388
|
while (queue.length > 0) {
|
|
6484
6389
|
queue.sort((a, b) => a.totalCost - b.totalCost || a.hops - b.hops || a.key.localeCompare(b.key));
|
|
6485
6390
|
const current = queue.shift();
|
|
6486
|
-
if (current.hops >= effectiveMaxHops)
|
|
6487
|
-
continue;
|
|
6391
|
+
if (current.hops >= effectiveMaxHops) continue;
|
|
6488
6392
|
for (const edge of graph.adjacency.get(current.key) ?? []) {
|
|
6489
|
-
if (current.visited.has(edge.toKey))
|
|
6490
|
-
continue;
|
|
6393
|
+
if (current.visited.has(edge.toKey)) continue;
|
|
6491
6394
|
const nextHops = current.hops + 1;
|
|
6492
6395
|
const nextTotalCost = current.totalCost + edge.step.cost;
|
|
6493
6396
|
const nextSteps = [...current.steps, edge.step];
|
|
@@ -6567,17 +6470,13 @@ function addTraversal(adjacency, fromKey, edge) {
|
|
|
6567
6470
|
adjacency.set(fromKey, edges);
|
|
6568
6471
|
}
|
|
6569
6472
|
function normalizeMaxHops(maxHops) {
|
|
6570
|
-
if (maxHops === void 0)
|
|
6571
|
-
|
|
6572
|
-
if (!Number.isFinite(maxHops))
|
|
6573
|
-
return MAX_HOPS;
|
|
6473
|
+
if (maxHops === void 0) return 1;
|
|
6474
|
+
if (!Number.isFinite(maxHops)) return MAX_HOPS;
|
|
6574
6475
|
return Math.min(Math.max(0, Math.trunc(maxHops)), MAX_HOPS);
|
|
6575
6476
|
}
|
|
6576
6477
|
function normalizeMaxResults(maxResults) {
|
|
6577
|
-
if (maxResults === void 0)
|
|
6578
|
-
|
|
6579
|
-
if (!Number.isFinite(maxResults))
|
|
6580
|
-
return DEFAULT_MAX_RESULTS;
|
|
6478
|
+
if (maxResults === void 0) return DEFAULT_MAX_RESULTS;
|
|
6479
|
+
if (!Number.isFinite(maxResults)) return DEFAULT_MAX_RESULTS;
|
|
6581
6480
|
return Math.min(Math.max(0, Math.trunc(maxResults)), MAX_RESULTS);
|
|
6582
6481
|
}
|
|
6583
6482
|
function isBetterPath(totalCost, hops, signature, existing) {
|
|
@@ -6589,18 +6488,15 @@ function pathSignature(steps) {
|
|
|
6589
6488
|
function edgeWeight(metaJson) {
|
|
6590
6489
|
const meta = parseMeta(metaJson);
|
|
6591
6490
|
const raw = meta.weight;
|
|
6592
|
-
if (typeof raw === "number" && Number.isFinite(raw) && raw > 0)
|
|
6593
|
-
return raw;
|
|
6491
|
+
if (typeof raw === "number" && Number.isFinite(raw) && raw > 0) return raw;
|
|
6594
6492
|
if (typeof raw === "string") {
|
|
6595
6493
|
const parsed = Number(raw);
|
|
6596
|
-
if (Number.isFinite(parsed) && parsed > 0)
|
|
6597
|
-
return parsed;
|
|
6494
|
+
if (Number.isFinite(parsed) && parsed > 0) return parsed;
|
|
6598
6495
|
}
|
|
6599
6496
|
return DEFAULT_WEIGHT;
|
|
6600
6497
|
}
|
|
6601
6498
|
function parseMeta(metaJson) {
|
|
6602
|
-
if (!metaJson)
|
|
6603
|
-
return {};
|
|
6499
|
+
if (!metaJson) return {};
|
|
6604
6500
|
try {
|
|
6605
6501
|
const parsed = JSON.parse(metaJson);
|
|
6606
6502
|
return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : {};
|
|
@@ -6613,8 +6509,7 @@ function nodeKey(node) {
|
|
|
6613
6509
|
}
|
|
6614
6510
|
function nodeFromKey(key) {
|
|
6615
6511
|
const index = key.indexOf(":");
|
|
6616
|
-
if (index === -1)
|
|
6617
|
-
return { type: "entity", id: key };
|
|
6512
|
+
if (index === -1) return { type: "entity", id: key };
|
|
6618
6513
|
return { type: key.slice(0, index), id: key.slice(index + 1) };
|
|
6619
6514
|
}
|
|
6620
6515
|
|
|
@@ -6670,6 +6565,7 @@ var QueryEntityExtractor = class {
|
|
|
6670
6565
|
constructor(db) {
|
|
6671
6566
|
this.db = db;
|
|
6672
6567
|
}
|
|
6568
|
+
db;
|
|
6673
6569
|
extract(query, options = {}) {
|
|
6674
6570
|
const maxCandidates = normalizeMaxCandidates(options.maxCandidates);
|
|
6675
6571
|
const candidates = [];
|
|
@@ -6691,8 +6587,7 @@ var QueryEntityExtractor = class {
|
|
|
6691
6587
|
let match;
|
|
6692
6588
|
while ((match = regex.exec(query)) !== null) {
|
|
6693
6589
|
const text = cleanCandidateText(match[2] ?? "");
|
|
6694
|
-
if (!isUsefulCandidate(text))
|
|
6695
|
-
continue;
|
|
6590
|
+
if (!isUsefulCandidate(text)) continue;
|
|
6696
6591
|
const start = match.index + 1;
|
|
6697
6592
|
const end = start + text.length;
|
|
6698
6593
|
ranges.push([match.index, match.index + match[0].length]);
|
|
@@ -6706,8 +6601,7 @@ var QueryEntityExtractor = class {
|
|
|
6706
6601
|
return ranges;
|
|
6707
6602
|
}
|
|
6708
6603
|
extractKnownAliases(query, candidates) {
|
|
6709
|
-
if (!this.db)
|
|
6710
|
-
return;
|
|
6604
|
+
if (!this.db) return;
|
|
6711
6605
|
const rows = sqliteAll(
|
|
6712
6606
|
this.db,
|
|
6713
6607
|
`SELECT
|
|
@@ -6731,11 +6625,9 @@ var QueryEntityExtractor = class {
|
|
|
6731
6625
|
]).filter(isUsefulCandidate);
|
|
6732
6626
|
for (const alias of aliasLabels) {
|
|
6733
6627
|
const normalizedAlias = normalizeForContainment(alias);
|
|
6734
|
-
if (!normalizedAlias || !containsPhrase(normalizedQuery, normalizedAlias))
|
|
6735
|
-
continue;
|
|
6628
|
+
if (!normalizedAlias || !containsPhrase(normalizedQuery, normalizedAlias)) continue;
|
|
6736
6629
|
const aliasKey = `${row.entity_id}:${normalizedAlias}`;
|
|
6737
|
-
if (seenAliases.has(aliasKey))
|
|
6738
|
-
continue;
|
|
6630
|
+
if (seenAliases.has(aliasKey)) continue;
|
|
6739
6631
|
seenAliases.add(aliasKey);
|
|
6740
6632
|
const range = findRange(query, alias);
|
|
6741
6633
|
pushCandidate(candidates, {
|
|
@@ -6756,8 +6648,7 @@ var QueryEntityExtractor = class {
|
|
|
6756
6648
|
let match;
|
|
6757
6649
|
while ((match = regex.exec(query)) !== null) {
|
|
6758
6650
|
const text = cleanCandidateText(match[2] ?? "");
|
|
6759
|
-
if (!isUsefulCandidate(text))
|
|
6760
|
-
continue;
|
|
6651
|
+
if (!isUsefulCandidate(text)) continue;
|
|
6761
6652
|
const start = match.index + (match[1]?.length ?? 0);
|
|
6762
6653
|
pushCandidate(candidates, {
|
|
6763
6654
|
text,
|
|
@@ -6772,8 +6663,7 @@ var QueryEntityExtractor = class {
|
|
|
6772
6663
|
let match;
|
|
6773
6664
|
while ((match = regex.exec(query)) !== null) {
|
|
6774
6665
|
const text = cleanCandidateText(match[2] ?? "");
|
|
6775
|
-
if (!isUsefulCandidate(text) || text.includes("/.") || text.includes("./"))
|
|
6776
|
-
continue;
|
|
6666
|
+
if (!isUsefulCandidate(text) || text.includes("/.") || text.includes("./")) continue;
|
|
6777
6667
|
const start = match.index + (match[1]?.length ?? 0);
|
|
6778
6668
|
pushCandidate(candidates, {
|
|
6779
6669
|
text,
|
|
@@ -6792,21 +6682,17 @@ var QueryEntityExtractor = class {
|
|
|
6792
6682
|
if (previous && query.slice(previous.end, token.start).match(/^\s+$/)) {
|
|
6793
6683
|
current.push(token);
|
|
6794
6684
|
} else {
|
|
6795
|
-
if (current.length > 0)
|
|
6796
|
-
groups.push(current);
|
|
6685
|
+
if (current.length > 0) groups.push(current);
|
|
6797
6686
|
current = [token];
|
|
6798
6687
|
}
|
|
6799
6688
|
}
|
|
6800
|
-
if (current.length > 0)
|
|
6801
|
-
groups.push(current);
|
|
6689
|
+
if (current.length > 0) groups.push(current);
|
|
6802
6690
|
for (const group of groups) {
|
|
6803
|
-
if (group.length === 1 && !isStrongSingleCapitalized(group[0].text))
|
|
6804
|
-
continue;
|
|
6691
|
+
if (group.length === 1 && !isStrongSingleCapitalized(group[0].text)) continue;
|
|
6805
6692
|
const start = group[0].start;
|
|
6806
6693
|
const end = group[group.length - 1].end;
|
|
6807
6694
|
const text = query.slice(start, end);
|
|
6808
|
-
if (!isUsefulCandidate(text))
|
|
6809
|
-
continue;
|
|
6695
|
+
if (!isUsefulCandidate(text)) continue;
|
|
6810
6696
|
pushCandidate(candidates, {
|
|
6811
6697
|
text,
|
|
6812
6698
|
source: "capitalized_term",
|
|
@@ -6827,8 +6713,7 @@ function collectCapitalizedTokens(query) {
|
|
|
6827
6713
|
}
|
|
6828
6714
|
function pushCandidate(candidates, input) {
|
|
6829
6715
|
const text = cleanCandidateText(input.text);
|
|
6830
|
-
if (!isUsefulCandidate(text))
|
|
6831
|
-
return;
|
|
6716
|
+
if (!isUsefulCandidate(text)) return;
|
|
6832
6717
|
const source = input.source;
|
|
6833
6718
|
candidates.push({
|
|
6834
6719
|
...input,
|
|
@@ -6846,15 +6731,13 @@ function dedupeAndSort(candidates) {
|
|
|
6846
6731
|
for (const candidate of sorted) {
|
|
6847
6732
|
if (candidate.source === "entity_alias") {
|
|
6848
6733
|
const aliasKey = `alias:${candidate.entityId ?? ""}:${normalizeCandidate(candidate.matchedAlias ?? candidate.text)}`;
|
|
6849
|
-
if (seenAliasKeys.has(aliasKey))
|
|
6850
|
-
continue;
|
|
6734
|
+
if (seenAliasKeys.has(aliasKey)) continue;
|
|
6851
6735
|
seenAliasKeys.add(aliasKey);
|
|
6852
6736
|
seenNormalized.add(candidate.normalized);
|
|
6853
6737
|
result.push(candidate);
|
|
6854
6738
|
continue;
|
|
6855
6739
|
}
|
|
6856
|
-
if (seenNormalized.has(candidate.normalized))
|
|
6857
|
-
continue;
|
|
6740
|
+
if (seenNormalized.has(candidate.normalized)) continue;
|
|
6858
6741
|
seenNormalized.add(candidate.normalized);
|
|
6859
6742
|
result.push(candidate);
|
|
6860
6743
|
}
|
|
@@ -6864,8 +6747,7 @@ function compareCandidates(a, b) {
|
|
|
6864
6747
|
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 ?? "");
|
|
6865
6748
|
}
|
|
6866
6749
|
function compareStrings(a, b) {
|
|
6867
|
-
if (a === b)
|
|
6868
|
-
return 0;
|
|
6750
|
+
if (a === b) return 0;
|
|
6869
6751
|
return a < b ? -1 : 1;
|
|
6870
6752
|
}
|
|
6871
6753
|
function stripPriority(candidate) {
|
|
@@ -6873,10 +6755,8 @@ function stripPriority(candidate) {
|
|
|
6873
6755
|
return publicCandidate;
|
|
6874
6756
|
}
|
|
6875
6757
|
function normalizeMaxCandidates(maxCandidates) {
|
|
6876
|
-
if (maxCandidates === void 0)
|
|
6877
|
-
|
|
6878
|
-
if (!Number.isFinite(maxCandidates))
|
|
6879
|
-
return DEFAULT_MAX_CANDIDATES;
|
|
6758
|
+
if (maxCandidates === void 0) return DEFAULT_MAX_CANDIDATES;
|
|
6759
|
+
if (!Number.isFinite(maxCandidates)) return DEFAULT_MAX_CANDIDATES;
|
|
6880
6760
|
return Math.min(Math.max(0, Math.trunc(maxCandidates)), MAX_CANDIDATES);
|
|
6881
6761
|
}
|
|
6882
6762
|
function cleanCandidateText(text) {
|
|
@@ -6898,21 +6778,17 @@ function aliasLabelFromCanonicalKey(canonicalKey) {
|
|
|
6898
6778
|
function findRange(query, alias) {
|
|
6899
6779
|
const normalizedAlias = normalizeForContainment(alias);
|
|
6900
6780
|
const directIndex = query.toLowerCase().indexOf(alias.toLowerCase());
|
|
6901
|
-
if (directIndex >= 0)
|
|
6902
|
-
return { start: directIndex, end: directIndex + alias.length };
|
|
6781
|
+
if (directIndex >= 0) return { start: directIndex, end: directIndex + alias.length };
|
|
6903
6782
|
const normalizedQuery = normalizeForContainment(query);
|
|
6904
6783
|
const normalizedIndex = normalizedQuery.indexOf(normalizedAlias);
|
|
6905
|
-
if (normalizedIndex < 0)
|
|
6906
|
-
return { start: 0, end: 0 };
|
|
6784
|
+
if (normalizedIndex < 0) return { start: 0, end: 0 };
|
|
6907
6785
|
const queryLower = query.toLowerCase();
|
|
6908
6786
|
const words = normalizedAlias.split(" ").filter(Boolean);
|
|
6909
|
-
if (words.length === 0)
|
|
6910
|
-
return { start: 0, end: 0 };
|
|
6787
|
+
if (words.length === 0) return { start: 0, end: 0 };
|
|
6911
6788
|
const first = queryLower.indexOf(words[0]);
|
|
6912
6789
|
const lastWord = words[words.length - 1];
|
|
6913
6790
|
const last = queryLower.indexOf(lastWord, first >= 0 ? first : 0);
|
|
6914
|
-
if (first >= 0 && last >= 0)
|
|
6915
|
-
return { start: first, end: last + lastWord.length };
|
|
6791
|
+
if (first >= 0 && last >= 0) return { start: first, end: last + lastWord.length };
|
|
6916
6792
|
return { start: normalizedIndex, end: normalizedIndex + normalizedAlias.length };
|
|
6917
6793
|
}
|
|
6918
6794
|
function isUsefulCandidate(text) {
|
|
@@ -6923,10 +6799,8 @@ function isInsideAnyRange(index, ranges) {
|
|
|
6923
6799
|
return ranges.some(([start, end]) => index >= start && index < end);
|
|
6924
6800
|
}
|
|
6925
6801
|
function isStrongSingleCapitalized(text) {
|
|
6926
|
-
if (/^[A-Z]{2,}[A-Z0-9]*$/.test(text))
|
|
6927
|
-
|
|
6928
|
-
if (/^[A-Z][a-z]+[A-Z][A-Za-z0-9]*$/.test(text))
|
|
6929
|
-
return true;
|
|
6802
|
+
if (/^[A-Z]{2,}[A-Z0-9]*$/.test(text)) return true;
|
|
6803
|
+
if (/^[A-Z][a-z]+[A-Z][A-Za-z0-9]*$/.test(text)) return true;
|
|
6930
6804
|
return text.length >= 4 && !SENTENCE_START_STOPWORDS.has(text);
|
|
6931
6805
|
}
|
|
6932
6806
|
function uniqueStrings(values) {
|
|
@@ -6934,8 +6808,7 @@ function uniqueStrings(values) {
|
|
|
6934
6808
|
const result = [];
|
|
6935
6809
|
for (const value of values) {
|
|
6936
6810
|
const key = normalizeForContainment(value);
|
|
6937
|
-
if (!key || seen.has(key))
|
|
6938
|
-
continue;
|
|
6811
|
+
if (!key || seen.has(key)) continue;
|
|
6939
6812
|
seen.add(key);
|
|
6940
6813
|
result.push(value);
|
|
6941
6814
|
}
|
|
@@ -6957,8 +6830,7 @@ var LessonCandidateInputSchema = z9.object({
|
|
|
6957
6830
|
import { z as z10 } from "zod";
|
|
6958
6831
|
var NonEmptyStringSchema5 = z10.string().transform((value) => value.trim()).pipe(z10.string().min(1));
|
|
6959
6832
|
var PromotionStringArraySchema = z10.preprocess((value) => {
|
|
6960
|
-
if (!Array.isArray(value))
|
|
6961
|
-
return value;
|
|
6833
|
+
if (!Array.isArray(value)) return value;
|
|
6962
6834
|
return value.map((item) => typeof item === "string" ? item.trim() : item).filter((item) => typeof item !== "string" || item.length > 0);
|
|
6963
6835
|
}, z10.array(NonEmptyStringSchema5).max(100));
|
|
6964
6836
|
var ReviewedLessonCandidateSchema = z10.object({
|
|
@@ -7006,8 +6878,7 @@ function projectHashFromStorage(projectHash) {
|
|
|
7006
6878
|
return projectHash.length > 0 ? projectHash : void 0;
|
|
7007
6879
|
}
|
|
7008
6880
|
function parseJsonRecord(value) {
|
|
7009
|
-
if (!value)
|
|
7010
|
-
return void 0;
|
|
6881
|
+
if (!value) return void 0;
|
|
7011
6882
|
try {
|
|
7012
6883
|
const parsed = JSON.parse(value);
|
|
7013
6884
|
return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : void 0;
|
|
@@ -7019,8 +6890,7 @@ function sanitizeString(value) {
|
|
|
7019
6890
|
return String(sanitizeGovernanceAuditValue(value)).trim();
|
|
7020
6891
|
}
|
|
7021
6892
|
function sanitizeMetadata(metadata) {
|
|
7022
|
-
if (!metadata)
|
|
7023
|
-
return void 0;
|
|
6893
|
+
if (!metadata) return void 0;
|
|
7024
6894
|
return sanitizeGovernanceAuditValue(metadata);
|
|
7025
6895
|
}
|
|
7026
6896
|
function slugActorPart(value) {
|
|
@@ -7028,8 +6898,7 @@ function slugActorPart(value) {
|
|
|
7028
6898
|
return slug.length > 0 ? slug : "unknown";
|
|
7029
6899
|
}
|
|
7030
6900
|
function stableActorId(input) {
|
|
7031
|
-
if (input.actorId)
|
|
7032
|
-
return sanitizeString(input.actorId);
|
|
6901
|
+
if (input.actorId) return sanitizeString(input.actorId);
|
|
7033
6902
|
const projectPart = input.projectHash ? `project:${slugActorPart(input.projectHash)}` : "global";
|
|
7034
6903
|
return [
|
|
7035
6904
|
"actor",
|
|
@@ -7052,12 +6921,10 @@ function rowToActor(row) {
|
|
|
7052
6921
|
});
|
|
7053
6922
|
}
|
|
7054
6923
|
function metadataString(metadata, keys) {
|
|
7055
|
-
if (!metadata)
|
|
7056
|
-
return void 0;
|
|
6924
|
+
if (!metadata) return void 0;
|
|
7057
6925
|
for (const key of keys) {
|
|
7058
6926
|
const value = metadata[key];
|
|
7059
|
-
if (typeof value === "string" && value.trim().length > 0)
|
|
7060
|
-
return value.trim();
|
|
6927
|
+
if (typeof value === "string" && value.trim().length > 0) return value.trim();
|
|
7061
6928
|
}
|
|
7062
6929
|
return void 0;
|
|
7063
6930
|
}
|
|
@@ -7107,6 +6974,7 @@ var ActorRepository = class {
|
|
|
7107
6974
|
constructor(db) {
|
|
7108
6975
|
this.db = db;
|
|
7109
6976
|
}
|
|
6977
|
+
db;
|
|
7110
6978
|
async upsert(input) {
|
|
7111
6979
|
const parsed = UpsertMemoryActorInputSchema.parse(input);
|
|
7112
6980
|
const actorId = stableActorId(parsed);
|
|
@@ -7160,8 +7028,7 @@ var ActorRepository = class {
|
|
|
7160
7028
|
}
|
|
7161
7029
|
require(actorId) {
|
|
7162
7030
|
const actor = this.get(actorId);
|
|
7163
|
-
if (!actor)
|
|
7164
|
-
throw new Error(`Memory actor not found: ${actorId}`);
|
|
7031
|
+
if (!actor) throw new Error(`Memory actor not found: ${actorId}`);
|
|
7165
7032
|
return actor;
|
|
7166
7033
|
}
|
|
7167
7034
|
async list(input = {}) {
|
|
@@ -7197,8 +7064,7 @@ function projectHashFromStorage2(projectHash) {
|
|
|
7197
7064
|
return projectHash.length > 0 ? projectHash : void 0;
|
|
7198
7065
|
}
|
|
7199
7066
|
function parseJsonRecord2(value) {
|
|
7200
|
-
if (!value)
|
|
7201
|
-
return void 0;
|
|
7067
|
+
if (!value) return void 0;
|
|
7202
7068
|
try {
|
|
7203
7069
|
const parsed = JSON.parse(value);
|
|
7204
7070
|
return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : void 0;
|
|
@@ -7207,8 +7073,7 @@ function parseJsonRecord2(value) {
|
|
|
7207
7073
|
}
|
|
7208
7074
|
}
|
|
7209
7075
|
function sanitizeMetadata2(metadata) {
|
|
7210
|
-
if (!metadata)
|
|
7211
|
-
return void 0;
|
|
7076
|
+
if (!metadata) return void 0;
|
|
7212
7077
|
return sanitizeGovernanceAuditValue(metadata);
|
|
7213
7078
|
}
|
|
7214
7079
|
function rowToSessionActor(row) {
|
|
@@ -7228,6 +7093,7 @@ var SessionActorRepository = class {
|
|
|
7228
7093
|
constructor(db) {
|
|
7229
7094
|
this.db = db;
|
|
7230
7095
|
}
|
|
7096
|
+
db;
|
|
7231
7097
|
async upsertMembership(input) {
|
|
7232
7098
|
const parsed = UpsertSessionActorInputSchema.parse(input);
|
|
7233
7099
|
const projectHash = projectHashToStorage3(parsed.projectHash);
|
|
@@ -7274,8 +7140,7 @@ var SessionActorRepository = class {
|
|
|
7274
7140
|
);
|
|
7275
7141
|
}
|
|
7276
7142
|
const saved = this.get(projectHash, parsed.sessionId, parsed.actorId);
|
|
7277
|
-
if (!saved)
|
|
7278
|
-
throw new Error("session actor membership was not saved");
|
|
7143
|
+
if (!saved) throw new Error("session actor membership was not saved");
|
|
7279
7144
|
return saved;
|
|
7280
7145
|
}
|
|
7281
7146
|
async listBySession(input) {
|
|
@@ -7311,8 +7176,7 @@ var SessionActorRepository = class {
|
|
|
7311
7176
|
]
|
|
7312
7177
|
);
|
|
7313
7178
|
const saved = this.get(projectHash, parsed.sessionId, parsed.actorId);
|
|
7314
|
-
if (!saved)
|
|
7315
|
-
throw new Error("session actor membership not found after update");
|
|
7179
|
+
if (!saved) throw new Error("session actor membership not found after update");
|
|
7316
7180
|
return saved;
|
|
7317
7181
|
}
|
|
7318
7182
|
get(projectHash, sessionId, actorId) {
|
|
@@ -7334,8 +7198,7 @@ function projectHashFromStorage3(projectHash) {
|
|
|
7334
7198
|
return projectHash.length > 0 ? projectHash : void 0;
|
|
7335
7199
|
}
|
|
7336
7200
|
function parseStringArray2(value) {
|
|
7337
|
-
if (!value)
|
|
7338
|
-
return [];
|
|
7201
|
+
if (!value) return [];
|
|
7339
7202
|
try {
|
|
7340
7203
|
const parsed = JSON.parse(value);
|
|
7341
7204
|
return Array.isArray(parsed) ? parsed.filter((entry) => typeof entry === "string") : [];
|
|
@@ -7344,8 +7207,7 @@ function parseStringArray2(value) {
|
|
|
7344
7207
|
}
|
|
7345
7208
|
}
|
|
7346
7209
|
function parseJsonRecord3(value) {
|
|
7347
|
-
if (!value)
|
|
7348
|
-
return void 0;
|
|
7210
|
+
if (!value) return void 0;
|
|
7349
7211
|
try {
|
|
7350
7212
|
const parsed = JSON.parse(value);
|
|
7351
7213
|
return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : void 0;
|
|
@@ -7361,8 +7223,7 @@ function sanitizeStoredStringArray(values) {
|
|
|
7361
7223
|
return values.map(sanitizeStoredString).filter((value) => value.length > 0);
|
|
7362
7224
|
}
|
|
7363
7225
|
function sanitizeStoredRecord(value) {
|
|
7364
|
-
if (!value)
|
|
7365
|
-
return void 0;
|
|
7226
|
+
if (!value) return void 0;
|
|
7366
7227
|
return sanitizeGovernanceAuditValue(value);
|
|
7367
7228
|
}
|
|
7368
7229
|
function stableHash(value) {
|
|
@@ -7413,8 +7274,7 @@ function sanitizedObservationSnapshot(observation) {
|
|
|
7413
7274
|
});
|
|
7414
7275
|
}
|
|
7415
7276
|
function queryScore(observation, terms) {
|
|
7416
|
-
if (terms.length === 0)
|
|
7417
|
-
return 0;
|
|
7277
|
+
if (terms.length === 0) return 0;
|
|
7418
7278
|
const haystack = [observation.content, observation.level, observation.sessionId ?? ""].join(" ").toLowerCase();
|
|
7419
7279
|
return terms.reduce((score, term) => score + (haystack.includes(term) ? 1 : 0), 0);
|
|
7420
7280
|
}
|
|
@@ -7460,12 +7320,12 @@ var PerspectiveObservationRepository = class {
|
|
|
7460
7320
|
this.vectorOutbox = options.vectorOutbox;
|
|
7461
7321
|
}
|
|
7462
7322
|
}
|
|
7323
|
+
db;
|
|
7463
7324
|
vectorOutbox = null;
|
|
7464
7325
|
vectorOutboxOption;
|
|
7465
7326
|
getVectorOutbox() {
|
|
7466
7327
|
const option = this.vectorOutboxOption;
|
|
7467
|
-
if (option === false)
|
|
7468
|
-
return null;
|
|
7328
|
+
if (option === false) return null;
|
|
7469
7329
|
if (option instanceof VectorOutbox) {
|
|
7470
7330
|
this.vectorOutbox = option;
|
|
7471
7331
|
return option;
|
|
@@ -7477,8 +7337,7 @@ var PerspectiveObservationRepository = class {
|
|
|
7477
7337
|
}
|
|
7478
7338
|
enqueueObservationSync(observationId) {
|
|
7479
7339
|
const outbox = this.getVectorOutbox();
|
|
7480
|
-
if (!outbox)
|
|
7481
|
-
return;
|
|
7340
|
+
if (!outbox) return;
|
|
7482
7341
|
outbox.enqueueSync("perspective_observation", observationId);
|
|
7483
7342
|
}
|
|
7484
7343
|
async create(input) {
|
|
@@ -7540,14 +7399,12 @@ var PerspectiveObservationRepository = class {
|
|
|
7540
7399
|
contentHash,
|
|
7541
7400
|
sourceHash
|
|
7542
7401
|
);
|
|
7543
|
-
if (!saved)
|
|
7544
|
-
throw new Error("perspective observation was not saved");
|
|
7402
|
+
if (!saved) throw new Error("perspective observation was not saved");
|
|
7545
7403
|
this.enqueueObservationSync(saved.observationId);
|
|
7546
7404
|
});
|
|
7547
7405
|
transaction();
|
|
7548
7406
|
const savedObservation = saved;
|
|
7549
|
-
if (!savedObservation)
|
|
7550
|
-
throw new Error("perspective observation was not saved");
|
|
7407
|
+
if (!savedObservation) throw new Error("perspective observation was not saved");
|
|
7551
7408
|
await this.writeCreateAudit({ ...parsed, observerActorId, observedActorId, sessionId, content, sourceEventIds, sourceObservationIds, createdBy, actor, metadata }, savedObservation);
|
|
7552
7409
|
return savedObservation;
|
|
7553
7410
|
}
|
|
@@ -7557,8 +7414,7 @@ var PerspectiveObservationRepository = class {
|
|
|
7557
7414
|
const ftsQuery = buildObservationFtsQuery(parsed.query);
|
|
7558
7415
|
if (ftsQuery) {
|
|
7559
7416
|
const ftsResult = this.queryWithFts(parsed, ftsQuery);
|
|
7560
|
-
if (ftsResult)
|
|
7561
|
-
return ftsResult;
|
|
7417
|
+
if (ftsResult) return ftsResult;
|
|
7562
7418
|
}
|
|
7563
7419
|
}
|
|
7564
7420
|
return this.queryWithPrefetch(parsed);
|
|
@@ -7579,8 +7435,7 @@ var PerspectiveObservationRepository = class {
|
|
|
7579
7435
|
);
|
|
7580
7436
|
return rows.map(rowToObservation);
|
|
7581
7437
|
} catch (error) {
|
|
7582
|
-
if (isFtsUnavailableError(error))
|
|
7583
|
-
return null;
|
|
7438
|
+
if (isFtsUnavailableError(error)) return null;
|
|
7584
7439
|
throw error;
|
|
7585
7440
|
}
|
|
7586
7441
|
}
|
|
@@ -7621,8 +7476,7 @@ var PerspectiveObservationRepository = class {
|
|
|
7621
7476
|
const parsed = DeletePerspectiveObservationInputSchema.parse(input);
|
|
7622
7477
|
const projectHash = projectHashToStorage4(parsed.projectHash);
|
|
7623
7478
|
const before = this.get(projectHash, parsed.observationId);
|
|
7624
|
-
if (!before)
|
|
7625
|
-
throw new Error("perspective observation not found");
|
|
7479
|
+
if (!before) throw new Error("perspective observation not found");
|
|
7626
7480
|
const deletedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
7627
7481
|
sqliteRun(
|
|
7628
7482
|
this.db,
|
|
@@ -7632,8 +7486,7 @@ var PerspectiveObservationRepository = class {
|
|
|
7632
7486
|
[deletedAt, deletedAt, projectHash, parsed.observationId]
|
|
7633
7487
|
);
|
|
7634
7488
|
const after = this.get(projectHash, parsed.observationId);
|
|
7635
|
-
if (!after)
|
|
7636
|
-
throw new Error("perspective observation not found after delete");
|
|
7489
|
+
if (!after) throw new Error("perspective observation not found after delete");
|
|
7637
7490
|
await writeGovernanceAuditEntry(this.db, {
|
|
7638
7491
|
operation: "perspective_observation_delete",
|
|
7639
7492
|
actor: parsed.actor,
|
|
@@ -7689,11 +7542,9 @@ var DEFAULT_CONFIG3 = {
|
|
|
7689
7542
|
var MAX_OBSERVATION_CONTENT_CHARS = 600;
|
|
7690
7543
|
var RuleBasedPerspectiveObservationExtractor = class {
|
|
7691
7544
|
async extract(event) {
|
|
7692
|
-
if (!isSupportedSourceEvent(event))
|
|
7693
|
-
return [];
|
|
7545
|
+
if (!isSupportedSourceEvent(event)) return [];
|
|
7694
7546
|
const content = normalizeObservationContent(event.content);
|
|
7695
|
-
if (!content)
|
|
7696
|
-
return [];
|
|
7547
|
+
if (!content) return [];
|
|
7697
7548
|
return [{
|
|
7698
7549
|
content,
|
|
7699
7550
|
confidence: 0.6,
|
|
@@ -7764,8 +7615,7 @@ var PerspectiveDeriver = class {
|
|
|
7764
7615
|
for (const candidate of candidates) {
|
|
7765
7616
|
const observedActorId = candidate.observedActorId ?? sourceActor.actorId;
|
|
7766
7617
|
const observers = selectObservers(members, observedActorId, this.config.deriver.maxObserversPerSession);
|
|
7767
|
-
if (observers.length === 0)
|
|
7768
|
-
continue;
|
|
7618
|
+
if (observers.length === 0) continue;
|
|
7769
7619
|
for (const observerActorId of observers) {
|
|
7770
7620
|
await this.observations.create({
|
|
7771
7621
|
projectHash,
|
|
@@ -7818,28 +7668,22 @@ function normalizeConfig(config) {
|
|
|
7818
7668
|
};
|
|
7819
7669
|
}
|
|
7820
7670
|
function clampInteger(value, fallback, min, max) {
|
|
7821
|
-
if (!Number.isFinite(value))
|
|
7822
|
-
return fallback;
|
|
7671
|
+
if (!Number.isFinite(value)) return fallback;
|
|
7823
7672
|
return Math.max(min, Math.min(max, Math.trunc(Number(value))));
|
|
7824
7673
|
}
|
|
7825
7674
|
function isSupportedSourceEvent(event) {
|
|
7826
7675
|
return event.eventType === "user_prompt" || event.eventType === "agent_response";
|
|
7827
7676
|
}
|
|
7828
7677
|
function roleForEvent(event) {
|
|
7829
|
-
if (event.eventType === "user_prompt")
|
|
7830
|
-
|
|
7831
|
-
if (event.eventType === "
|
|
7832
|
-
|
|
7833
|
-
if (event.eventType === "tool_observation")
|
|
7834
|
-
return "tool";
|
|
7835
|
-
if (event.eventType === "session_summary")
|
|
7836
|
-
return "system";
|
|
7678
|
+
if (event.eventType === "user_prompt") return "speaker";
|
|
7679
|
+
if (event.eventType === "agent_response") return "assistant";
|
|
7680
|
+
if (event.eventType === "tool_observation") return "tool";
|
|
7681
|
+
if (event.eventType === "session_summary") return "system";
|
|
7837
7682
|
return "unknown";
|
|
7838
7683
|
}
|
|
7839
7684
|
function normalizeCandidate2(candidate) {
|
|
7840
7685
|
const content = normalizeObservationContent(candidate.content);
|
|
7841
|
-
if (!content)
|
|
7842
|
-
return null;
|
|
7686
|
+
if (!content) return null;
|
|
7843
7687
|
return {
|
|
7844
7688
|
content,
|
|
7845
7689
|
confidence: clampNumber(candidate.confidence, 0.6, 0, 1),
|
|
@@ -7851,8 +7695,7 @@ function normalizeCandidate2(candidate) {
|
|
|
7851
7695
|
}
|
|
7852
7696
|
function normalizeObservationContent(content) {
|
|
7853
7697
|
const normalized = content.replace(/\s+/g, " ").trim();
|
|
7854
|
-
if (!normalized)
|
|
7855
|
-
return null;
|
|
7698
|
+
if (!normalized) return null;
|
|
7856
7699
|
return normalized.slice(0, MAX_OBSERVATION_CONTENT_CHARS);
|
|
7857
7700
|
}
|
|
7858
7701
|
function normalizeOptionalString2(value) {
|
|
@@ -7860,13 +7703,11 @@ function normalizeOptionalString2(value) {
|
|
|
7860
7703
|
return normalized.length > 0 ? normalized : void 0;
|
|
7861
7704
|
}
|
|
7862
7705
|
function clampNumber(value, fallback, min, max) {
|
|
7863
|
-
if (!Number.isFinite(value))
|
|
7864
|
-
return fallback;
|
|
7706
|
+
if (!Number.isFinite(value)) return fallback;
|
|
7865
7707
|
return Math.max(min, Math.min(max, Number(value)));
|
|
7866
7708
|
}
|
|
7867
7709
|
function sanitizeCandidateMetadata(metadata) {
|
|
7868
|
-
if (!metadata)
|
|
7869
|
-
return void 0;
|
|
7710
|
+
if (!metadata) return void 0;
|
|
7870
7711
|
const result = {};
|
|
7871
7712
|
for (const [key, value] of Object.entries(metadata)) {
|
|
7872
7713
|
if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
|
|
@@ -7879,12 +7720,9 @@ function selectObservers(members, observedActorId, maxObservers) {
|
|
|
7879
7720
|
const selected = [];
|
|
7880
7721
|
for (const member of members) {
|
|
7881
7722
|
const canObserve = member.actorId === observedActorId ? member.observeSelf : member.observeOthers;
|
|
7882
|
-
if (!canObserve)
|
|
7883
|
-
|
|
7884
|
-
if (
|
|
7885
|
-
selected.push(member.actorId);
|
|
7886
|
-
if (selected.length >= maxObservers)
|
|
7887
|
-
break;
|
|
7723
|
+
if (!canObserve) continue;
|
|
7724
|
+
if (!selected.includes(member.actorId)) selected.push(member.actorId);
|
|
7725
|
+
if (selected.length >= maxObservers) break;
|
|
7888
7726
|
}
|
|
7889
7727
|
return selected;
|
|
7890
7728
|
}
|
|
@@ -7903,6 +7741,7 @@ var VectorStore = class {
|
|
|
7903
7741
|
constructor(dbPath) {
|
|
7904
7742
|
this.dbPath = dbPath;
|
|
7905
7743
|
}
|
|
7744
|
+
dbPath;
|
|
7906
7745
|
db = null;
|
|
7907
7746
|
tableCache = /* @__PURE__ */ new Map();
|
|
7908
7747
|
defaultTableName = "conversations";
|
|
@@ -7914,8 +7753,7 @@ var VectorStore = class {
|
|
|
7914
7753
|
* conversations table.
|
|
7915
7754
|
*/
|
|
7916
7755
|
async initialize() {
|
|
7917
|
-
if (this.db)
|
|
7918
|
-
return;
|
|
7756
|
+
if (this.db) return;
|
|
7919
7757
|
this.db = await lancedb.connect(this.dbPath);
|
|
7920
7758
|
}
|
|
7921
7759
|
/**
|
|
@@ -7929,8 +7767,7 @@ var VectorStore = class {
|
|
|
7929
7767
|
* Add or update multiple vector records in batch, grouped by inferred table.
|
|
7930
7768
|
*/
|
|
7931
7769
|
async upsertBatch(records) {
|
|
7932
|
-
if (records.length === 0)
|
|
7933
|
-
return;
|
|
7770
|
+
if (records.length === 0) return;
|
|
7934
7771
|
await this.initialize();
|
|
7935
7772
|
if (!this.db) {
|
|
7936
7773
|
throw new Error("Database not initialized");
|
|
@@ -7985,8 +7822,7 @@ var VectorStore = class {
|
|
|
7985
7822
|
async delete(eventId) {
|
|
7986
7823
|
await this.initialize();
|
|
7987
7824
|
const table = await this.getExistingTable(this.defaultTableName);
|
|
7988
|
-
if (!table)
|
|
7989
|
-
return;
|
|
7825
|
+
if (!table) return;
|
|
7990
7826
|
await table.delete(`eventId = ${toLanceSqlString(eventId)}`);
|
|
7991
7827
|
}
|
|
7992
7828
|
/**
|
|
@@ -7995,8 +7831,7 @@ var VectorStore = class {
|
|
|
7995
7831
|
async count() {
|
|
7996
7832
|
await this.initialize();
|
|
7997
7833
|
const table = await this.getExistingTable(this.defaultTableName);
|
|
7998
|
-
if (!table)
|
|
7999
|
-
return 0;
|
|
7834
|
+
if (!table) return 0;
|
|
8000
7835
|
const result = await table.countRows();
|
|
8001
7836
|
return result;
|
|
8002
7837
|
}
|
|
@@ -8005,8 +7840,7 @@ var VectorStore = class {
|
|
|
8005
7840
|
*/
|
|
8006
7841
|
async clearAll() {
|
|
8007
7842
|
await this.initialize();
|
|
8008
|
-
if (!this.db)
|
|
8009
|
-
return;
|
|
7843
|
+
if (!this.db) return;
|
|
8010
7844
|
try {
|
|
8011
7845
|
if (typeof this.db.dropTable === "function") {
|
|
8012
7846
|
await this.db.dropTable(this.defaultTableName);
|
|
@@ -8023,8 +7857,7 @@ var VectorStore = class {
|
|
|
8023
7857
|
async exists(eventId) {
|
|
8024
7858
|
await this.initialize();
|
|
8025
7859
|
const table = await this.getExistingTable(this.defaultTableName);
|
|
8026
|
-
if (!table)
|
|
8027
|
-
return false;
|
|
7860
|
+
if (!table) return false;
|
|
8028
7861
|
const results = await table.search([]).where(`eventId = ${toLanceSqlString(eventId)}`).limit(1).toArray();
|
|
8029
7862
|
return results.length > 0;
|
|
8030
7863
|
}
|
|
@@ -8059,8 +7892,7 @@ var VectorStore = class {
|
|
|
8059
7892
|
throw new Error("Database not initialized");
|
|
8060
7893
|
}
|
|
8061
7894
|
const cached = this.tableCache.get(tableName);
|
|
8062
|
-
if (cached)
|
|
8063
|
-
return cached;
|
|
7895
|
+
if (cached) return cached;
|
|
8064
7896
|
const tableNames = await this.db.tableNames();
|
|
8065
7897
|
if (!tableNames.includes(tableName)) {
|
|
8066
7898
|
return null;
|
|
@@ -8139,12 +7971,9 @@ var IngestInterceptorRegistry = class {
|
|
|
8139
7971
|
}
|
|
8140
7972
|
};
|
|
8141
7973
|
function mergeHierarchicalMetadata(base, patch) {
|
|
8142
|
-
if (!base && !patch)
|
|
8143
|
-
|
|
8144
|
-
if (!base
|
|
8145
|
-
return patch;
|
|
8146
|
-
if (!patch)
|
|
8147
|
-
return base;
|
|
7974
|
+
if (!base && !patch) return void 0;
|
|
7975
|
+
if (!base) return patch;
|
|
7976
|
+
if (!patch) return base;
|
|
8148
7977
|
const result = { ...base };
|
|
8149
7978
|
for (const [key, value] of Object.entries(patch)) {
|
|
8150
7979
|
const current = result[key];
|
|
@@ -8174,33 +8003,26 @@ var VALID_TAG_NAMESPACES = new Set(Object.values(TAG_NAMESPACES));
|
|
|
8174
8003
|
function parseTag(tag) {
|
|
8175
8004
|
const value = (tag || "").trim();
|
|
8176
8005
|
const idx = value.indexOf(":");
|
|
8177
|
-
if (idx <= 0)
|
|
8178
|
-
return { value };
|
|
8006
|
+
if (idx <= 0) return { value };
|
|
8179
8007
|
const namespace = `${value.slice(0, idx)}:`;
|
|
8180
8008
|
const tagValue = value.slice(idx + 1);
|
|
8181
|
-
if (!tagValue)
|
|
8182
|
-
return { value };
|
|
8009
|
+
if (!tagValue) return { value };
|
|
8183
8010
|
return { namespace, value: tagValue };
|
|
8184
8011
|
}
|
|
8185
8012
|
function validateTag(tag) {
|
|
8186
8013
|
const normalized = (tag || "").trim();
|
|
8187
|
-
if (!normalized)
|
|
8188
|
-
return false;
|
|
8014
|
+
if (!normalized) return false;
|
|
8189
8015
|
const { namespace } = parseTag(normalized);
|
|
8190
|
-
if (!namespace)
|
|
8191
|
-
return true;
|
|
8016
|
+
if (!namespace) return true;
|
|
8192
8017
|
return VALID_TAG_NAMESPACES.has(namespace);
|
|
8193
8018
|
}
|
|
8194
8019
|
function normalizeTags(tags) {
|
|
8195
|
-
if (!Array.isArray(tags))
|
|
8196
|
-
return [];
|
|
8020
|
+
if (!Array.isArray(tags)) return [];
|
|
8197
8021
|
const dedup = /* @__PURE__ */ new Set();
|
|
8198
8022
|
for (const item of tags) {
|
|
8199
|
-
if (typeof item !== "string")
|
|
8200
|
-
continue;
|
|
8023
|
+
if (typeof item !== "string") continue;
|
|
8201
8024
|
const normalized = item.trim();
|
|
8202
|
-
if (!validateTag(normalized))
|
|
8203
|
-
continue;
|
|
8025
|
+
if (!validateTag(normalized)) continue;
|
|
8204
8026
|
dedup.add(normalized);
|
|
8205
8027
|
}
|
|
8206
8028
|
return [...dedup];
|
|
@@ -8217,10 +8039,8 @@ var SummaryDeriver = class {
|
|
|
8217
8039
|
* orchestration, while this class owns summary text and metadata decisions.
|
|
8218
8040
|
*/
|
|
8219
8041
|
deriveSessionSummary(events) {
|
|
8220
|
-
if (events.length < 3)
|
|
8221
|
-
|
|
8222
|
-
if (events.some((event) => event.eventType === "session_summary"))
|
|
8223
|
-
return null;
|
|
8042
|
+
if (events.length < 3) return null;
|
|
8043
|
+
if (events.some((event) => event.eventType === "session_summary")) return null;
|
|
8224
8044
|
const prompts = events.filter((event) => event.eventType === "user_prompt");
|
|
8225
8045
|
const toolObservations = events.filter((event) => event.eventType === "tool_observation");
|
|
8226
8046
|
const toolNames = Array.from(new Set(
|
|
@@ -8368,8 +8188,7 @@ var MemoryIngestService = class {
|
|
|
8368
8188
|
await this.initialize();
|
|
8369
8189
|
const events = await this.eventStore.getSessionEvents(sessionId);
|
|
8370
8190
|
const summary = this.summaryDeriver.deriveSessionSummary(events);
|
|
8371
|
-
if (!summary)
|
|
8372
|
-
return;
|
|
8191
|
+
if (!summary) return;
|
|
8373
8192
|
await this.storeSessionSummary(sessionId, summary.text, summary.metadata);
|
|
8374
8193
|
}
|
|
8375
8194
|
async storeToolObservation(sessionId, payload) {
|
|
@@ -8437,10 +8256,8 @@ var MemoryIngestService = class {
|
|
|
8437
8256
|
}
|
|
8438
8257
|
}
|
|
8439
8258
|
async runPerspectiveDeriver(input, eventId, operation) {
|
|
8440
|
-
if (!this.perspectiveDeriver)
|
|
8441
|
-
|
|
8442
|
-
if (operation !== "user_prompt" && operation !== "agent_response")
|
|
8443
|
-
return;
|
|
8259
|
+
if (!this.perspectiveDeriver) return;
|
|
8260
|
+
if (operation !== "user_prompt" && operation !== "agent_response") return;
|
|
8444
8261
|
const event = {
|
|
8445
8262
|
id: eventId,
|
|
8446
8263
|
eventType: input.eventType,
|
|
@@ -8510,11 +8327,13 @@ var MemoryQueryService = class {
|
|
|
8510
8327
|
this.queryStore = queryStore;
|
|
8511
8328
|
this.deps = deps;
|
|
8512
8329
|
}
|
|
8330
|
+
initialize;
|
|
8331
|
+
queryStore;
|
|
8332
|
+
deps;
|
|
8513
8333
|
async keywordSearch(query, options) {
|
|
8514
8334
|
await this.initialize();
|
|
8515
8335
|
const results = await this.queryStore.keywordSearch(query, options?.topK ?? 10);
|
|
8516
|
-
if (results.length === 0)
|
|
8517
|
-
return [];
|
|
8336
|
+
if (results.length === 0) return [];
|
|
8518
8337
|
const maxRank = Math.min(...results.map((r) => r.rank), -1e-3);
|
|
8519
8338
|
const minRank = Math.max(...results.map((r) => r.rank), -1e3);
|
|
8520
8339
|
const rankRange = maxRank - minRank || 1;
|
|
@@ -8609,6 +8428,18 @@ var COMMAND_ARTIFACT_PATTERNS = [
|
|
|
8609
8428
|
/<local-command-stdout>[\s\S]*?<\/local-command-stdout>/i,
|
|
8610
8429
|
/<local-command-stderr>[\s\S]*?<\/local-command-stderr>/i
|
|
8611
8430
|
];
|
|
8431
|
+
var LOW_SIGNAL_CONTEXT_PATTERNS = [
|
|
8432
|
+
/<environment_context\b[\s\S]*<\/environment_context>/i,
|
|
8433
|
+
/<turn_aborted>/i,
|
|
8434
|
+
/^#\s*AGENTS\.md\s+instructions\b[\s\S]*<INSTRUCTIONS>/i,
|
|
8435
|
+
/^\s*(?:understood[,\s.]*)?(?:stopping|stopped|pausing|paused)\s+here\b[\s\S]{0,180}\blet\s+me\s+know\s+when\s+you(?:'d|\s+would)?\s+like\s+to\s+continue\b/i,
|
|
8436
|
+
/^\s*\[?CONTEXT\s+COMPACTION\s*[—-]\s*REFERENCE\s+ONLY\]?\b[\s\S]{0,600}\b(?:earlier\s+turns\s+were\s+compacted|handoff\s+from\s+a\s+previous\s+context\s+window|active\s+task)\b/i,
|
|
8437
|
+
/^\s*Summary\s+generation\s+was\s+unavailable\.\s*\d+\s+message\(s\)\s+were\s+removed\s+to\s+free\s+context\s+space\b/i,
|
|
8438
|
+
/^\s*---\s*END\s+OF\s+CONTEXT\s+SUMMARY\b/i,
|
|
8439
|
+
/^\s*\[Your\s+active\s+task\s+list\s+was\s+preserved\s+across\s+context\s+compression\]/i,
|
|
8440
|
+
/^➜\s+\S+\s+git:\([^)]*\)\s+/i,
|
|
8441
|
+
/^\$\s+\S+/i
|
|
8442
|
+
];
|
|
8612
8443
|
var CONTINUATION_QUERY_PATTERNS = [
|
|
8613
8444
|
/^\s*(?:continue|resume|next|what(?:'s| is)? next|next\s+(?:step|task|action)|recommended\s+(?:next\s+)?(?:step|task|action)|what should (?:we|i) do next)\??\s*$/i,
|
|
8614
8445
|
/^\s*(?:응\s*)?(?:이어서(?:\s*진행(?:해줘)?)?|계속(?:\s*해줘)?|다음\s*(?:단계|작업|추천\s*작업|추천|할\s*일)?(?:은|는)?(?:\s*(?:뭐야|진행(?:해줘)?))?\??|남은\s*(?:추가(?:로)?\s*)?(?:(?:할\s*만한\s*)?(?:작업|일)|할\s*일)?(?:은|는)?\s*(?:있어|있나|있나요|뭐야)\??|추천\s*작업(?:은|는)?(?:\s*뭐야)?\??|진행해줘)\s*$/i
|
|
@@ -8620,7 +8451,7 @@ var SHORT_REPAIR_FOLLOW_UP_PATTERNS = [
|
|
|
8620
8451
|
var CURRENT_STATE_QUERY_PATTERNS = [
|
|
8621
8452
|
/\bcurrent\b.*\b(?:state|status|deployment|blocker|pr|pull request)\b/i,
|
|
8622
8453
|
/\b(?:still|as current|current)\b.*\b(?:unresolved|open|pending|not completed)\b/i,
|
|
8623
|
-
/\b(?:old|obsolete|stale|resolved|already resolved)\b.*\b(?:current|still|unresolved|open|
|
|
8454
|
+
/\b(?:old|obsolete|stale|resolved|already resolved)\b.*\b(?:current|still|unresolved|open|status)\b/i,
|
|
8624
8455
|
/(?:현재|아직|이전|오래된|해결된).*(?:상태|미해결|열린|블로커|PR|풀리퀘스트)/i
|
|
8625
8456
|
];
|
|
8626
8457
|
var STALE_CONTENT_PATTERNS = [
|
|
@@ -8760,55 +8591,67 @@ var LOW_INFORMATION_QUERY_TERMS = /* @__PURE__ */ new Set([
|
|
|
8760
8591
|
]);
|
|
8761
8592
|
function isCommandArtifactQuery(query) {
|
|
8762
8593
|
const trimmed = query.trim();
|
|
8763
|
-
if (!trimmed)
|
|
8764
|
-
return false;
|
|
8594
|
+
if (!trimmed) return false;
|
|
8765
8595
|
const normalized = trimmed.toLowerCase();
|
|
8766
|
-
if (normalized.includes("local-command-stdout") || normalized.includes("local-command-stderr"))
|
|
8767
|
-
|
|
8768
|
-
if (normalized.includes("command-name") || normalized.includes("command-message"))
|
|
8769
|
-
return true;
|
|
8596
|
+
if (normalized.includes("local-command-stdout") || normalized.includes("local-command-stderr")) return true;
|
|
8597
|
+
if (normalized.includes("command-name") || normalized.includes("command-message")) return true;
|
|
8770
8598
|
return COMMAND_ARTIFACT_PATTERNS.some((pattern) => pattern.test(trimmed));
|
|
8771
8599
|
}
|
|
8600
|
+
function isCommandArtifactContent(content) {
|
|
8601
|
+
const trimmed = content.trim();
|
|
8602
|
+
if (!trimmed) return false;
|
|
8603
|
+
const normalized = trimmed.toLowerCase();
|
|
8604
|
+
if (normalized.includes("local-command-stdout") || normalized.includes("local-command-stderr")) return true;
|
|
8605
|
+
if (normalized.includes("command-name") || normalized.includes("command-message")) return true;
|
|
8606
|
+
return COMMAND_ARTIFACT_PATTERNS.some((pattern) => pattern.test(trimmed));
|
|
8607
|
+
}
|
|
8608
|
+
function isLowSignalContextContent(content) {
|
|
8609
|
+
const trimmed = content.trim();
|
|
8610
|
+
if (!trimmed) return true;
|
|
8611
|
+
if (isCommandArtifactContent(trimmed)) return true;
|
|
8612
|
+
if (LOW_SIGNAL_CONTEXT_PATTERNS.some((pattern) => pattern.test(trimmed))) return true;
|
|
8613
|
+
return false;
|
|
8614
|
+
}
|
|
8772
8615
|
function isGenericContinuationQuery(query) {
|
|
8773
8616
|
const trimmed = query.trim();
|
|
8774
|
-
if (!trimmed)
|
|
8775
|
-
|
|
8776
|
-
if (
|
|
8777
|
-
return false;
|
|
8778
|
-
if (extractTechnicalQueryTerms(trimmed).length > 0)
|
|
8779
|
-
return false;
|
|
8617
|
+
if (!trimmed) return false;
|
|
8618
|
+
if (!CONTINUATION_QUERY_PATTERNS.some((pattern) => pattern.test(trimmed))) return false;
|
|
8619
|
+
if (extractTechnicalQueryTerms(trimmed).length > 0) return false;
|
|
8780
8620
|
const tokens = trimmed.match(/[A-Za-z0-9가-힣#._/-]+/g) ?? [];
|
|
8781
|
-
if (tokens.length > 10)
|
|
8782
|
-
return false;
|
|
8621
|
+
if (tokens.length > 10) return false;
|
|
8783
8622
|
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);
|
|
8784
8623
|
}
|
|
8785
8624
|
function isShortRepairFollowUpQuery(query) {
|
|
8786
8625
|
const trimmed = query.trim();
|
|
8787
|
-
if (!trimmed)
|
|
8788
|
-
|
|
8789
|
-
if (extractTechnicalQueryTerms(trimmed).length > 0)
|
|
8790
|
-
return false;
|
|
8626
|
+
if (!trimmed) return false;
|
|
8627
|
+
if (extractTechnicalQueryTerms(trimmed).length > 0) return false;
|
|
8791
8628
|
const tokens = trimmed.match(/[A-Za-z0-9가-힣#._/-]+/g) ?? [];
|
|
8792
|
-
if (tokens.length > 8)
|
|
8793
|
-
return false;
|
|
8629
|
+
if (tokens.length > 8) return false;
|
|
8794
8630
|
return SHORT_REPAIR_FOLLOW_UP_PATTERNS.some((pattern) => pattern.test(trimmed));
|
|
8795
8631
|
}
|
|
8632
|
+
function isLowConfidenceContextFallbackQuery(query) {
|
|
8633
|
+
const trimmed = query.trim();
|
|
8634
|
+
if (!trimmed) return false;
|
|
8635
|
+
if (isGenericContinuationQuery(trimmed) || isShortRepairFollowUpQuery(trimmed)) return true;
|
|
8636
|
+
const terms = new Set(tokenizeQualityText(trimmed));
|
|
8637
|
+
if ((terms.has("compacted") || terms.has("compaction")) && terms.has("handoff")) return false;
|
|
8638
|
+
const hasContinuationRecall = /^(?:continue|resume)\b/i.test(trimmed) && (terms.has("work") || terms.has("step") || terms.has("task") || terms.has("last") || terms.has("completed"));
|
|
8639
|
+
const hasValidationGateRecall = terms.has("validation") && (terms.has("gate") || terms.has("check")) && (terms.has("run") || terms.has("before") || terms.has("commit") || terms.has("committing") || terms.has("change"));
|
|
8640
|
+
return hasContinuationRecall || hasValidationGateRecall;
|
|
8641
|
+
}
|
|
8796
8642
|
function isCurrentStateQuery(query) {
|
|
8797
8643
|
const trimmed = query.trim();
|
|
8798
|
-
if (!trimmed)
|
|
8799
|
-
return false;
|
|
8644
|
+
if (!trimmed) return false;
|
|
8800
8645
|
return CURRENT_STATE_QUERY_PATTERNS.some((pattern) => pattern.test(trimmed));
|
|
8801
8646
|
}
|
|
8802
8647
|
function isStaleOrSupersededContent(content) {
|
|
8803
8648
|
const trimmed = content.trim();
|
|
8804
|
-
if (!trimmed)
|
|
8805
|
-
return false;
|
|
8649
|
+
if (!trimmed) return false;
|
|
8806
8650
|
return STALE_CONTENT_PATTERNS.some((pattern) => pattern.test(trimmed));
|
|
8807
8651
|
}
|
|
8808
8652
|
function buildRetrievalQualityQuery(query) {
|
|
8809
8653
|
const trimmed = query.trim();
|
|
8810
|
-
if (!trimmed)
|
|
8811
|
-
return query;
|
|
8654
|
+
if (!trimmed) return query;
|
|
8812
8655
|
if (isRetrievalPrivacyDecisionQuery(trimmed)) {
|
|
8813
8656
|
return `${trimmed} ${RETRIEVAL_PRIVACY_DECISION_EXPANSION}`;
|
|
8814
8657
|
}
|
|
@@ -8822,12 +8665,10 @@ function buildRetrievalQualityQuery(query) {
|
|
|
8822
8665
|
}
|
|
8823
8666
|
function isRetrievalPrivacyDecisionQuery(query) {
|
|
8824
8667
|
const trimmed = query.trim();
|
|
8825
|
-
if (!trimmed)
|
|
8826
|
-
return false;
|
|
8668
|
+
if (!trimmed) return false;
|
|
8827
8669
|
const terms = new Set(tokenizeQualityText(trimmed));
|
|
8828
8670
|
const hasDecisionSignal = hasAnyTerm(terms, DECISION_RECALL_TERMS) || /(?:결정|정책|원칙)/i.test(trimmed);
|
|
8829
|
-
if (!hasDecisionSignal)
|
|
8830
|
-
return false;
|
|
8671
|
+
if (!hasDecisionSignal) return false;
|
|
8831
8672
|
const hasRawQuerySignal = terms.has("raw") && terms.has("query");
|
|
8832
8673
|
const hasPrivacySignal = terms.has("privacy") || terms.has("expose") || terms.has("redacted");
|
|
8833
8674
|
const hasRetrievalSurface = hasAnyTerm(terms, RETRIEVAL_PRIVACY_SURFACE_TERMS) || terms.has("api") && terms.has("query");
|
|
@@ -8840,16 +8681,14 @@ function extractTechnicalQueryTerms(query) {
|
|
|
8840
8681
|
const matches = query.match(/[A-Za-z][A-Za-z0-9_.:-]{2,}/g) ?? [];
|
|
8841
8682
|
const terms = matches.filter((term) => {
|
|
8842
8683
|
const lower = term.toLowerCase();
|
|
8843
|
-
if (GENERIC_TECHNICAL_TERMS.has(lower))
|
|
8844
|
-
return false;
|
|
8684
|
+
if (GENERIC_TECHNICAL_TERMS.has(lower)) return false;
|
|
8845
8685
|
return /[._:-]/.test(term) || /[a-z][A-Z]/.test(term) || /[A-Z]{2,}/.test(term) || /\d/.test(term);
|
|
8846
8686
|
});
|
|
8847
8687
|
return Array.from(new Set(terms.map((term) => term.toLowerCase())));
|
|
8848
8688
|
}
|
|
8849
8689
|
function hasTechnicalTermOverlap(query, content) {
|
|
8850
8690
|
const terms = extractTechnicalQueryTerms(query);
|
|
8851
|
-
if (terms.length === 0)
|
|
8852
|
-
return true;
|
|
8691
|
+
if (terms.length === 0) return true;
|
|
8853
8692
|
const normalizedContent = content.toLowerCase();
|
|
8854
8693
|
return terms.some((term) => normalizedContent.includes(term));
|
|
8855
8694
|
}
|
|
@@ -8865,15 +8704,12 @@ function hasDiscriminativeTermOverlap(query, content) {
|
|
|
8865
8704
|
return topicTerms.some((term) => contentTerms.has(term));
|
|
8866
8705
|
}
|
|
8867
8706
|
}
|
|
8868
|
-
if (queryTerms.length < 3)
|
|
8869
|
-
return true;
|
|
8707
|
+
if (queryTerms.length < 3) return true;
|
|
8870
8708
|
const requiredHits = queryTerms.length >= 3 ? 2 : 1;
|
|
8871
8709
|
let hits = 0;
|
|
8872
8710
|
for (const term of queryTerms) {
|
|
8873
|
-
if (contentTerms.has(term))
|
|
8874
|
-
|
|
8875
|
-
if (hits >= requiredHits)
|
|
8876
|
-
return true;
|
|
8711
|
+
if (contentTerms.has(term)) hits += 1;
|
|
8712
|
+
if (hits >= requiredHits) return true;
|
|
8877
8713
|
}
|
|
8878
8714
|
return false;
|
|
8879
8715
|
}
|
|
@@ -8883,17 +8719,14 @@ function shouldApplyTechnicalGuard(query) {
|
|
|
8883
8719
|
function hasAnyTerm(terms, expectedTerms) {
|
|
8884
8720
|
let found = false;
|
|
8885
8721
|
expectedTerms.forEach((term) => {
|
|
8886
|
-
if (terms.has(term))
|
|
8887
|
-
found = true;
|
|
8722
|
+
if (terms.has(term)) found = true;
|
|
8888
8723
|
});
|
|
8889
8724
|
return found;
|
|
8890
8725
|
}
|
|
8891
8726
|
function shouldRequireDecisionTopicOverlap(query) {
|
|
8892
|
-
if (isRetrievalPrivacyDecisionQuery(query))
|
|
8893
|
-
return false;
|
|
8727
|
+
if (isRetrievalPrivacyDecisionQuery(query)) return false;
|
|
8894
8728
|
const trimmed = query.trim();
|
|
8895
|
-
if (!trimmed)
|
|
8896
|
-
return false;
|
|
8729
|
+
if (!trimmed) return false;
|
|
8897
8730
|
const terms = new Set(tokenizeQualityText(trimmed));
|
|
8898
8731
|
return hasAnyTerm(terms, DECISION_RECALL_TERMS) || /(?:결정|정책|원칙)/i.test(trimmed);
|
|
8899
8732
|
}
|
|
@@ -8901,12 +8734,9 @@ function extractDiscriminativeQueryTerms(query) {
|
|
|
8901
8734
|
const seen = /* @__PURE__ */ new Set();
|
|
8902
8735
|
const terms = [];
|
|
8903
8736
|
for (const token of tokenizeQualityText(query)) {
|
|
8904
|
-
if (LOW_INFORMATION_QUERY_TERMS.has(token))
|
|
8905
|
-
|
|
8906
|
-
if (
|
|
8907
|
-
continue;
|
|
8908
|
-
if (seen.has(token))
|
|
8909
|
-
continue;
|
|
8737
|
+
if (LOW_INFORMATION_QUERY_TERMS.has(token)) continue;
|
|
8738
|
+
if (GENERIC_TECHNICAL_TERMS.has(token)) continue;
|
|
8739
|
+
if (seen.has(token)) continue;
|
|
8910
8740
|
seen.add(token);
|
|
8911
8741
|
terms.push(token);
|
|
8912
8742
|
}
|
|
@@ -8921,14 +8751,10 @@ function tokenizeQualityText(text) {
|
|
|
8921
8751
|
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);
|
|
8922
8752
|
}
|
|
8923
8753
|
function normalizeQualityToken(token) {
|
|
8924
|
-
if (token === "apis")
|
|
8925
|
-
|
|
8926
|
-
if (token
|
|
8927
|
-
|
|
8928
|
-
if (LOW_INFORMATION_QUERY_TERMS.has(token) || GENERIC_TECHNICAL_TERMS.has(token))
|
|
8929
|
-
return token;
|
|
8930
|
-
if (token.length > 4 && token.endsWith("ies"))
|
|
8931
|
-
return `${token.slice(0, -3)}y`;
|
|
8754
|
+
if (token === "apis") return "api";
|
|
8755
|
+
if (token === "ids") return "id";
|
|
8756
|
+
if (LOW_INFORMATION_QUERY_TERMS.has(token) || GENERIC_TECHNICAL_TERMS.has(token)) return token;
|
|
8757
|
+
if (token.length > 4 && token.endsWith("ies")) return `${token.slice(0, -3)}y`;
|
|
8932
8758
|
if (token.length > 3 && token.endsWith("s") && !token.endsWith("ss") && !token.endsWith("us") && !token.endsWith("is")) {
|
|
8933
8759
|
return token.slice(0, -1);
|
|
8934
8760
|
}
|
|
@@ -9080,7 +8906,14 @@ var Retriever = class {
|
|
|
9080
8906
|
};
|
|
9081
8907
|
fallbackTrace.push("fallback:summary");
|
|
9082
8908
|
}
|
|
9083
|
-
const
|
|
8909
|
+
const selectedResults = current.results.slice(0, opts.topK).filter((result) => {
|
|
8910
|
+
if (current.matchResult.confidence !== "none") return true;
|
|
8911
|
+
if (isLowConfidenceContextFallbackQuery(query)) {
|
|
8912
|
+
return (result.semanticScore ?? result.score) >= 0.5 || result.score >= 0.5;
|
|
8913
|
+
}
|
|
8914
|
+
return (result.semanticScore ?? result.score) >= 0.62 || result.score >= 0.62;
|
|
8915
|
+
});
|
|
8916
|
+
const memories = await this.enrichResults(selectedResults, opts, query);
|
|
9084
8917
|
const context = this.buildContext(memories, opts.maxTokens);
|
|
9085
8918
|
return {
|
|
9086
8919
|
memories,
|
|
@@ -9088,7 +8921,7 @@ var Retriever = class {
|
|
|
9088
8921
|
totalTokens: this.estimateTokens(context),
|
|
9089
8922
|
context,
|
|
9090
8923
|
fallbackTrace,
|
|
9091
|
-
selectedDebug:
|
|
8924
|
+
selectedDebug: selectedResults.map((r) => this.debugDetailForResult(r)),
|
|
9092
8925
|
candidateDebug: (current.candidateResults || []).slice(0, Math.max(opts.topK * 3, 20)).map((r) => this.debugDetailForResult(r)),
|
|
9093
8926
|
rawQueryText: current.queryRewriteKind ? query : void 0,
|
|
9094
8927
|
effectiveQueryText: current.effectiveQueryText,
|
|
@@ -9110,8 +8943,7 @@ var Retriever = class {
|
|
|
9110
8943
|
const sharedMemories = [];
|
|
9111
8944
|
for (const result of sharedVectorResults) {
|
|
9112
8945
|
const entry = await this.sharedStore.get(result.entryId);
|
|
9113
|
-
if (!entry)
|
|
9114
|
-
continue;
|
|
8946
|
+
if (!entry) continue;
|
|
9115
8947
|
if (!options.projectHash || entry.sourceProjectHash !== options.projectHash) {
|
|
9116
8948
|
sharedMemories.push(entry);
|
|
9117
8949
|
await this.sharedStore.recordUsage(entry.entryId);
|
|
@@ -9184,6 +9016,7 @@ var Retriever = class {
|
|
|
9184
9016
|
if (isCurrentStateQuery(options.query)) {
|
|
9185
9017
|
filtered = filtered.filter((result) => !isStaleOrSupersededContent(result.content));
|
|
9186
9018
|
}
|
|
9019
|
+
filtered = filtered.filter((result) => !isLowSignalContextContent(result.content));
|
|
9187
9020
|
filtered = filtered.filter(
|
|
9188
9021
|
(result) => this.isGraphPathResult(result) || hasDiscriminativeTermOverlap(options.query, result.content)
|
|
9189
9022
|
);
|
|
@@ -9192,18 +9025,15 @@ var Retriever = class {
|
|
|
9192
9025
|
(result) => this.isGraphPathResult(result) || hasTechnicalTermOverlap(options.query, result.content)
|
|
9193
9026
|
);
|
|
9194
9027
|
}
|
|
9195
|
-
if (filtered.length <= 2)
|
|
9196
|
-
return filtered;
|
|
9028
|
+
if (filtered.length <= 2) return filtered;
|
|
9197
9029
|
const topScore = filtered[0].score;
|
|
9198
|
-
if (topScore < 0.8)
|
|
9199
|
-
return filtered;
|
|
9030
|
+
if (topScore < 0.8) return filtered;
|
|
9200
9031
|
const cliffThreshold = Math.max(options.minScore, topScore - 0.25);
|
|
9201
9032
|
return filtered.filter((result) => result.score >= cliffThreshold);
|
|
9202
9033
|
}
|
|
9203
9034
|
mergeResults(primary, secondary, limit) {
|
|
9204
9035
|
const byId = /* @__PURE__ */ new Map();
|
|
9205
|
-
for (const row of primary)
|
|
9206
|
-
byId.set(row.eventId, row);
|
|
9036
|
+
for (const row of primary) byId.set(row.eventId, row);
|
|
9207
9037
|
for (const row of secondary) {
|
|
9208
9038
|
const prev = byId.get(row.eventId);
|
|
9209
9039
|
if (!prev || row.score > prev.score) {
|
|
@@ -9214,23 +9044,19 @@ var Retriever = class {
|
|
|
9214
9044
|
}
|
|
9215
9045
|
async expandGraphHops(seeds, opts) {
|
|
9216
9046
|
const byId = /* @__PURE__ */ new Map();
|
|
9217
|
-
for (const s of seeds)
|
|
9218
|
-
byId.set(s.eventId, s);
|
|
9047
|
+
for (const s of seeds) byId.set(s.eventId, s);
|
|
9219
9048
|
let frontier = seeds.map((s) => ({ row: s, hop: 0 }));
|
|
9220
9049
|
for (let hop = 1; hop <= opts.maxHops; hop += 1) {
|
|
9221
9050
|
const next = [];
|
|
9222
9051
|
for (const f of frontier) {
|
|
9223
9052
|
const ev = await this.eventStore.getEvent(f.row.eventId);
|
|
9224
|
-
if (!ev)
|
|
9225
|
-
continue;
|
|
9053
|
+
if (!ev) continue;
|
|
9226
9054
|
const rel = ev.metadata?.relatedEventIds ?? [];
|
|
9227
9055
|
const relatedIds = Array.isArray(rel) ? rel.filter((x) => typeof x === "string") : [];
|
|
9228
9056
|
for (const rid of relatedIds) {
|
|
9229
|
-
if (byId.has(rid))
|
|
9230
|
-
continue;
|
|
9057
|
+
if (byId.has(rid)) continue;
|
|
9231
9058
|
const target = await this.eventStore.getEvent(rid);
|
|
9232
|
-
if (!target)
|
|
9233
|
-
continue;
|
|
9059
|
+
if (!target) continue;
|
|
9234
9060
|
const score = Math.max(0, f.row.score - opts.hopPenalty * hop);
|
|
9235
9061
|
const row = {
|
|
9236
9062
|
id: `hop-${hop}-${rid}`,
|
|
@@ -9244,15 +9070,12 @@ var Retriever = class {
|
|
|
9244
9070
|
};
|
|
9245
9071
|
byId.set(row.eventId, row);
|
|
9246
9072
|
next.push({ row, hop });
|
|
9247
|
-
if (byId.size >= opts.limit)
|
|
9248
|
-
break;
|
|
9073
|
+
if (byId.size >= opts.limit) break;
|
|
9249
9074
|
}
|
|
9250
|
-
if (byId.size >= opts.limit)
|
|
9251
|
-
break;
|
|
9075
|
+
if (byId.size >= opts.limit) break;
|
|
9252
9076
|
}
|
|
9253
9077
|
frontier = next;
|
|
9254
|
-
if (frontier.length === 0 || byId.size >= opts.limit)
|
|
9255
|
-
break;
|
|
9078
|
+
if (frontier.length === 0 || byId.size >= opts.limit) break;
|
|
9256
9079
|
}
|
|
9257
9080
|
if (opts.queryGraphEnabled) {
|
|
9258
9081
|
await this.expandQueryGraphPaths(opts.query, byId, opts);
|
|
@@ -9260,8 +9083,7 @@ var Retriever = class {
|
|
|
9260
9083
|
return [...byId.values()].sort((a, b) => b.score - a.score || compareStable(a.eventId, b.eventId)).slice(0, opts.limit);
|
|
9261
9084
|
}
|
|
9262
9085
|
async expandQueryGraphPaths(query, byId, opts) {
|
|
9263
|
-
if (!query.trim() || !this.eventStore.getDatabase)
|
|
9264
|
-
return;
|
|
9086
|
+
if (!query.trim() || !this.eventStore.getDatabase) return;
|
|
9265
9087
|
try {
|
|
9266
9088
|
const db = this.eventStore.getDatabase();
|
|
9267
9089
|
const extraction = new QueryEntityExtractor(db).extract(query, {
|
|
@@ -9270,8 +9092,7 @@ var Retriever = class {
|
|
|
9270
9092
|
});
|
|
9271
9093
|
const startCandidates = extraction.candidates.filter((candidate) => candidate.entityId).slice(0, 8);
|
|
9272
9094
|
const startNodes = uniqueEntityStartNodes(startCandidates);
|
|
9273
|
-
if (startNodes.length === 0)
|
|
9274
|
-
return;
|
|
9095
|
+
if (startNodes.length === 0) return;
|
|
9275
9096
|
const expansion = new GraphPathService(db).expand({
|
|
9276
9097
|
startNodes: startNodes.map((node) => ({ type: "entity", id: node.entityId })),
|
|
9277
9098
|
maxHops: opts.maxHops,
|
|
@@ -9280,11 +9101,9 @@ var Retriever = class {
|
|
|
9280
9101
|
});
|
|
9281
9102
|
const titleByEntityId = new Map(startNodes.map((node) => [node.entityId, node.title]));
|
|
9282
9103
|
for (const path14 of expansion.paths) {
|
|
9283
|
-
if (path14.target.type !== "event")
|
|
9284
|
-
continue;
|
|
9104
|
+
if (path14.target.type !== "event") continue;
|
|
9285
9105
|
const target = await this.eventStore.getEvent(path14.target.id);
|
|
9286
|
-
if (!target)
|
|
9287
|
-
continue;
|
|
9106
|
+
if (!target) continue;
|
|
9288
9107
|
const graphPath = toRetrievalGraphPathDebug(path14, titleByEntityId);
|
|
9289
9108
|
const score = graphPathScore(path14, opts.hopPenalty);
|
|
9290
9109
|
const existing = byId.get(target.id);
|
|
@@ -9310,17 +9129,14 @@ var Retriever = class {
|
|
|
9310
9129
|
lanes: mergeRetrievalLanes(existing?.lanes ?? [], [graphLane])
|
|
9311
9130
|
};
|
|
9312
9131
|
byId.set(row.eventId, row);
|
|
9313
|
-
if (byId.size >= opts.limit)
|
|
9314
|
-
break;
|
|
9132
|
+
if (byId.size >= opts.limit) break;
|
|
9315
9133
|
}
|
|
9316
9134
|
} catch {
|
|
9317
9135
|
}
|
|
9318
9136
|
}
|
|
9319
9137
|
shouldFallback(matchResult, results) {
|
|
9320
|
-
if (results.length === 0)
|
|
9321
|
-
|
|
9322
|
-
if (matchResult.confidence === "none")
|
|
9323
|
-
return true;
|
|
9138
|
+
if (results.length === 0) return true;
|
|
9139
|
+
if (matchResult.confidence === "none") return true;
|
|
9324
9140
|
return false;
|
|
9325
9141
|
}
|
|
9326
9142
|
async buildSummaryFallback(query, topK) {
|
|
@@ -9425,29 +9241,21 @@ var Retriever = class {
|
|
|
9425
9241
|
(value) => typeof value === "string" && value.length > 0
|
|
9426
9242
|
)
|
|
9427
9243
|
);
|
|
9428
|
-
if (!scope && projectScopeMode === "global" && facetFilters === null)
|
|
9429
|
-
return results;
|
|
9244
|
+
if (!scope && projectScopeMode === "global" && facetFilters === null) return results;
|
|
9430
9245
|
const normalizedIncludes = (scope?.contentIncludes || []).map((s) => s.toLowerCase());
|
|
9431
9246
|
const filtered = [];
|
|
9432
9247
|
for (const result of results) {
|
|
9433
|
-
if (scope?.sessionId && result.sessionId !== scope.sessionId)
|
|
9434
|
-
|
|
9435
|
-
if (scope?.
|
|
9436
|
-
continue;
|
|
9437
|
-
if (scope?.eventTypes && scope.eventTypes.length > 0 && !scope.eventTypes.includes(result.eventType))
|
|
9438
|
-
continue;
|
|
9248
|
+
if (scope?.sessionId && result.sessionId !== scope.sessionId) continue;
|
|
9249
|
+
if (scope?.sessionIdPrefix && !result.sessionId.startsWith(scope.sessionIdPrefix)) continue;
|
|
9250
|
+
if (scope?.eventTypes && scope.eventTypes.length > 0 && !scope.eventTypes.includes(result.eventType)) continue;
|
|
9439
9251
|
const event = await this.eventStore.getEvent(result.eventId);
|
|
9440
|
-
if (!event)
|
|
9441
|
-
|
|
9442
|
-
if (scope?.canonicalKeyPrefix && !event.canonicalKey.startsWith(scope.canonicalKeyPrefix))
|
|
9443
|
-
continue;
|
|
9252
|
+
if (!event) continue;
|
|
9253
|
+
if (scope?.canonicalKeyPrefix && !event.canonicalKey.startsWith(scope.canonicalKeyPrefix)) continue;
|
|
9444
9254
|
if (normalizedIncludes.length > 0) {
|
|
9445
9255
|
const lc = event.content.toLowerCase();
|
|
9446
|
-
if (!normalizedIncludes.some((needle) => lc.includes(needle)))
|
|
9447
|
-
continue;
|
|
9256
|
+
if (!normalizedIncludes.some((needle) => lc.includes(needle))) continue;
|
|
9448
9257
|
}
|
|
9449
|
-
if (scope?.metadata && !this.matchesMetadataScope(event.metadata, scope.metadata))
|
|
9450
|
-
continue;
|
|
9258
|
+
if (scope?.metadata && !this.matchesMetadataScope(event.metadata, scope.metadata)) continue;
|
|
9451
9259
|
const projectHash = this.extractProjectHash(event.metadata);
|
|
9452
9260
|
filtered.push({ result, projectHash });
|
|
9453
9261
|
}
|
|
@@ -9464,27 +9272,21 @@ var Retriever = class {
|
|
|
9464
9272
|
});
|
|
9465
9273
|
}
|
|
9466
9274
|
normalizeFacetFilters(facets) {
|
|
9467
|
-
if (!facets || facets.length === 0)
|
|
9468
|
-
return null;
|
|
9275
|
+
if (!facets || facets.length === 0) return null;
|
|
9469
9276
|
const normalized = [];
|
|
9470
9277
|
for (const facet of facets) {
|
|
9471
9278
|
const parsedDimension = FacetDimensionSchema.safeParse(facet.dimension);
|
|
9472
9279
|
const value = typeof facet.value === "string" ? facet.value.trim() : "";
|
|
9473
|
-
if (!parsedDimension.success || !value)
|
|
9474
|
-
return [];
|
|
9280
|
+
if (!parsedDimension.success || !value) return [];
|
|
9475
9281
|
normalized.push({ dimension: parsedDimension.data, value });
|
|
9476
9282
|
}
|
|
9477
9283
|
return normalized;
|
|
9478
9284
|
}
|
|
9479
9285
|
async applyFacetFilters(results, options) {
|
|
9480
|
-
if (options.facets === null)
|
|
9481
|
-
|
|
9482
|
-
if (options.
|
|
9483
|
-
|
|
9484
|
-
if (!options.projectHash)
|
|
9485
|
-
return [];
|
|
9486
|
-
if (!this.eventStore.getDatabase)
|
|
9487
|
-
return [];
|
|
9286
|
+
if (options.facets === null) return results;
|
|
9287
|
+
if (options.facets.length === 0) return [];
|
|
9288
|
+
if (!options.projectHash) return [];
|
|
9289
|
+
if (!this.eventStore.getDatabase) return [];
|
|
9488
9290
|
const repo = new FacetRepository(this.eventStore.getDatabase());
|
|
9489
9291
|
const filtered = [];
|
|
9490
9292
|
for (const result of results) {
|
|
@@ -9541,14 +9343,11 @@ var Retriever = class {
|
|
|
9541
9343
|
return (result.graphPaths || []).length > 0;
|
|
9542
9344
|
}
|
|
9543
9345
|
extractProjectHash(metadata) {
|
|
9544
|
-
if (!metadata || typeof metadata !== "object")
|
|
9545
|
-
return void 0;
|
|
9346
|
+
if (!metadata || typeof metadata !== "object") return void 0;
|
|
9546
9347
|
const scope = metadata.scope;
|
|
9547
|
-
if (!scope || typeof scope !== "object")
|
|
9548
|
-
return void 0;
|
|
9348
|
+
if (!scope || typeof scope !== "object") return void 0;
|
|
9549
9349
|
const project = scope.project;
|
|
9550
|
-
if (!project || typeof project !== "object")
|
|
9551
|
-
return void 0;
|
|
9350
|
+
if (!project || typeof project !== "object") return void 0;
|
|
9552
9351
|
const hash = project.hash;
|
|
9553
9352
|
return typeof hash === "string" && hash.length > 0 ? hash : void 0;
|
|
9554
9353
|
}
|
|
@@ -9558,52 +9357,48 @@ var Retriever = class {
|
|
|
9558
9357
|
async retrieveRecent(limit = 100) {
|
|
9559
9358
|
return this.eventStore.getRecentEvents(limit);
|
|
9560
9359
|
}
|
|
9561
|
-
async enrichResults(results, options) {
|
|
9360
|
+
async enrichResults(results, options, query) {
|
|
9562
9361
|
const memories = [];
|
|
9563
9362
|
for (const result of results) {
|
|
9564
9363
|
const event = await this.eventStore.getEvent(result.eventId);
|
|
9565
|
-
if (!event)
|
|
9566
|
-
continue;
|
|
9364
|
+
if (!event) continue;
|
|
9567
9365
|
if (this.graduation) {
|
|
9568
9366
|
this.graduation.recordAccess(event.id, options.sessionId || "unknown", result.score);
|
|
9569
9367
|
}
|
|
9570
9368
|
let sessionContext;
|
|
9571
9369
|
if (options.includeSessionContext) {
|
|
9572
|
-
sessionContext = await this.getSessionContext(event.sessionId, event.id);
|
|
9370
|
+
sessionContext = await this.getSessionContext(event.sessionId, event.id, query);
|
|
9573
9371
|
}
|
|
9574
9372
|
memories.push({ event, score: result.score, sessionContext });
|
|
9575
9373
|
}
|
|
9576
9374
|
return memories;
|
|
9577
9375
|
}
|
|
9578
|
-
async getSessionContext(sessionId, eventId) {
|
|
9376
|
+
async getSessionContext(sessionId, eventId, query) {
|
|
9579
9377
|
const sessionEvents = await this.eventStore.getSessionEvents(sessionId);
|
|
9580
9378
|
const eventIndex = sessionEvents.findIndex((e) => e.id === eventId);
|
|
9581
|
-
if (eventIndex === -1)
|
|
9582
|
-
return void 0;
|
|
9379
|
+
if (eventIndex === -1) return void 0;
|
|
9583
9380
|
const start = Math.max(0, eventIndex - 1);
|
|
9584
9381
|
const end = Math.min(sessionEvents.length, eventIndex + 2);
|
|
9585
9382
|
const contextEvents = sessionEvents.slice(start, end);
|
|
9586
|
-
if (contextEvents.length <= 1)
|
|
9587
|
-
|
|
9588
|
-
|
|
9383
|
+
if (contextEvents.length <= 1) return void 0;
|
|
9384
|
+
const suppressStaleState = isCurrentStateQuery(query);
|
|
9385
|
+
const contextLines = contextEvents.filter((e) => e.id !== eventId).filter((e) => !isLowSignalContextContent(e.content)).filter((e) => !(suppressStaleState && isStaleOrSupersededContent(e.content))).map((e) => `[${e.eventType}]: ${e.content.slice(0, 200)}...`);
|
|
9386
|
+
return contextLines.length > 0 ? contextLines.join("\n") : void 0;
|
|
9589
9387
|
}
|
|
9590
9388
|
buildUnifiedContext(projectResult, sharedMemories) {
|
|
9591
9389
|
let context = projectResult.context;
|
|
9592
|
-
if (sharedMemories.length === 0)
|
|
9593
|
-
return context;
|
|
9390
|
+
if (sharedMemories.length === 0) return context;
|
|
9594
9391
|
context += "\n\n## Cross-Project Knowledge\n\n";
|
|
9595
9392
|
for (const memory of sharedMemories.slice(0, 3)) {
|
|
9596
9393
|
context += `### ${memory.title}
|
|
9597
9394
|
`;
|
|
9598
|
-
if (memory.symptoms.length > 0)
|
|
9599
|
-
context += `**Symptoms:** ${memory.symptoms.join(", ")}
|
|
9395
|
+
if (memory.symptoms.length > 0) context += `**Symptoms:** ${memory.symptoms.join(", ")}
|
|
9600
9396
|
`;
|
|
9601
9397
|
context += `**Root Cause:** ${memory.rootCause}
|
|
9602
9398
|
`;
|
|
9603
9399
|
context += `**Solution:** ${memory.solution}
|
|
9604
9400
|
`;
|
|
9605
|
-
if (memory.technologies && memory.technologies.length > 0)
|
|
9606
|
-
context += `**Technologies:** ${memory.technologies.join(", ")}
|
|
9401
|
+
if (memory.technologies && memory.technologies.length > 0) context += `**Technologies:** ${memory.technologies.join(", ")}
|
|
9607
9402
|
`;
|
|
9608
9403
|
context += `_Confidence: ${(memory.confidence * 100).toFixed(0)}%_
|
|
9609
9404
|
|
|
@@ -9617,13 +9412,11 @@ var Retriever = class {
|
|
|
9617
9412
|
for (const memory of memories) {
|
|
9618
9413
|
const memoryText = this.formatMemory(memory);
|
|
9619
9414
|
const memoryTokens = this.estimateTokens(memoryText);
|
|
9620
|
-
if (currentTokens + memoryTokens > maxTokens)
|
|
9621
|
-
break;
|
|
9415
|
+
if (currentTokens + memoryTokens > maxTokens) break;
|
|
9622
9416
|
parts.push(memoryText);
|
|
9623
9417
|
currentTokens += memoryTokens;
|
|
9624
9418
|
}
|
|
9625
|
-
if (parts.length === 0)
|
|
9626
|
-
return "";
|
|
9419
|
+
if (parts.length === 0) return "";
|
|
9627
9420
|
return `## Relevant Memories
|
|
9628
9421
|
|
|
9629
9422
|
${parts.join("\n\n---\n\n")}`;
|
|
@@ -9633,19 +9426,16 @@ ${parts.join("\n\n---\n\n")}`;
|
|
|
9633
9426
|
const date = event.timestamp.toISOString().split("T")[0];
|
|
9634
9427
|
let text = `**${event.eventType}** (${date}, score: ${score.toFixed(2)})
|
|
9635
9428
|
${event.content}`;
|
|
9636
|
-
if (sessionContext)
|
|
9637
|
-
text += `
|
|
9429
|
+
if (sessionContext) text += `
|
|
9638
9430
|
|
|
9639
9431
|
_Context:_ ${sessionContext}`;
|
|
9640
9432
|
return text;
|
|
9641
9433
|
}
|
|
9642
9434
|
matchesMetadataScope(metadata, expected) {
|
|
9643
|
-
if (!metadata)
|
|
9644
|
-
return false;
|
|
9435
|
+
if (!metadata) return false;
|
|
9645
9436
|
return Object.entries(expected).every(([path14, value]) => {
|
|
9646
9437
|
const actual = path14.split(".").reduce((acc, key) => {
|
|
9647
|
-
if (typeof acc !== "object" || acc === null)
|
|
9648
|
-
return void 0;
|
|
9438
|
+
if (typeof acc !== "object" || acc === null) return void 0;
|
|
9649
9439
|
return acc[key];
|
|
9650
9440
|
}, metadata);
|
|
9651
9441
|
return actual === value;
|
|
@@ -9655,27 +9445,20 @@ _Context:_ ${sessionContext}`;
|
|
|
9655
9445
|
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);
|
|
9656
9446
|
}
|
|
9657
9447
|
normalizeToken(token) {
|
|
9658
|
-
if (token === "apis")
|
|
9659
|
-
|
|
9660
|
-
if (token === "
|
|
9661
|
-
|
|
9662
|
-
if (token === "does")
|
|
9663
|
-
return token;
|
|
9664
|
-
if (token.length > 4 && token.endsWith("ies"))
|
|
9665
|
-
return `${token.slice(0, -3)}y`;
|
|
9448
|
+
if (token === "apis") return "api";
|
|
9449
|
+
if (token === "ids") return "id";
|
|
9450
|
+
if (token === "does") return token;
|
|
9451
|
+
if (token.length > 4 && token.endsWith("ies")) return `${token.slice(0, -3)}y`;
|
|
9666
9452
|
if (token.length > 3 && token.endsWith("s") && !token.endsWith("ss") && !token.endsWith("us") && !token.endsWith("is") && !token.endsWith("ps")) {
|
|
9667
9453
|
return token.slice(0, -1);
|
|
9668
9454
|
}
|
|
9669
9455
|
return token;
|
|
9670
9456
|
}
|
|
9671
9457
|
keywordOverlap(a, b) {
|
|
9672
|
-
if (a.length === 0 || b.length === 0)
|
|
9673
|
-
return 0;
|
|
9458
|
+
if (a.length === 0 || b.length === 0) return 0;
|
|
9674
9459
|
const bs = new Set(b);
|
|
9675
9460
|
let hit = 0;
|
|
9676
|
-
for (const t of a)
|
|
9677
|
-
if (bs.has(t))
|
|
9678
|
-
hit += 1;
|
|
9461
|
+
for (const t of a) if (bs.has(t)) hit += 1;
|
|
9679
9462
|
return hit / a.length;
|
|
9680
9463
|
}
|
|
9681
9464
|
estimateTokens(text) {
|
|
@@ -9696,8 +9479,7 @@ function uniqueEntityStartNodes(candidates) {
|
|
|
9696
9479
|
const seen = /* @__PURE__ */ new Set();
|
|
9697
9480
|
const nodes = [];
|
|
9698
9481
|
for (const candidate of candidates) {
|
|
9699
|
-
if (!candidate.entityId || seen.has(candidate.entityId))
|
|
9700
|
-
continue;
|
|
9482
|
+
if (!candidate.entityId || seen.has(candidate.entityId)) continue;
|
|
9701
9483
|
seen.add(candidate.entityId);
|
|
9702
9484
|
nodes.push({ entityId: candidate.entityId, title: candidate.text });
|
|
9703
9485
|
}
|
|
@@ -9721,16 +9503,14 @@ function graphPathScore(path14, hopPenalty) {
|
|
|
9721
9503
|
return Math.max(0.05, base - hopPenalty * Math.max(0, path14.hops - 1));
|
|
9722
9504
|
}
|
|
9723
9505
|
function clampGraphHops(maxHops) {
|
|
9724
|
-
if (!Number.isFinite(maxHops))
|
|
9725
|
-
return 2;
|
|
9506
|
+
if (!Number.isFinite(maxHops)) return 2;
|
|
9726
9507
|
return Math.min(Math.max(0, Math.trunc(maxHops)), 2);
|
|
9727
9508
|
}
|
|
9728
9509
|
function mergeGraphPaths(existing, incoming) {
|
|
9729
9510
|
const byKey = /* @__PURE__ */ new Map();
|
|
9730
9511
|
for (const path14 of [...existing, ...incoming]) {
|
|
9731
9512
|
const key = [path14.startEntityId, path14.targetType, path14.targetId, path14.hops, ...path14.relationPath].join("\0");
|
|
9732
|
-
if (!byKey.has(key))
|
|
9733
|
-
byKey.set(key, path14);
|
|
9513
|
+
if (!byKey.has(key)) byKey.set(key, path14);
|
|
9734
9514
|
}
|
|
9735
9515
|
return [...byKey.values()].sort((a, b) => a.hops - b.hops || compareStable(graphPathSignature(a), graphPathSignature(b))).slice(0, 3);
|
|
9736
9516
|
}
|
|
@@ -9738,10 +9518,8 @@ function graphPathSignature(path14) {
|
|
|
9738
9518
|
return [path14.startEntityId, path14.targetType, path14.targetId, path14.hops, ...path14.relationPath].join("|");
|
|
9739
9519
|
}
|
|
9740
9520
|
function compareStable(a, b) {
|
|
9741
|
-
if (a < b)
|
|
9742
|
-
|
|
9743
|
-
if (a > b)
|
|
9744
|
-
return 1;
|
|
9521
|
+
if (a < b) return -1;
|
|
9522
|
+
if (a > b) return 1;
|
|
9745
9523
|
return 0;
|
|
9746
9524
|
}
|
|
9747
9525
|
function createRetriever(eventStore, vectorStore, embedder, matcher, sharedOptions) {
|
|
@@ -9753,6 +9531,7 @@ var RetrievalAnalyticsService = class {
|
|
|
9753
9531
|
constructor(deps) {
|
|
9754
9532
|
this.deps = deps;
|
|
9755
9533
|
}
|
|
9534
|
+
deps;
|
|
9756
9535
|
async getRetrievalTraceStats() {
|
|
9757
9536
|
await this.deps.initialize();
|
|
9758
9537
|
return this.deps.retrievalStore.getRetrievalTraceStats();
|
|
@@ -9830,6 +9609,7 @@ var RetrievalDisclosureService = class {
|
|
|
9830
9609
|
constructor(deps) {
|
|
9831
9610
|
this.deps = deps;
|
|
9832
9611
|
}
|
|
9612
|
+
deps;
|
|
9833
9613
|
async search(query, options) {
|
|
9834
9614
|
const result = await this.deps.retrievalOrchestrator.retrieveMemories(query, options);
|
|
9835
9615
|
const debugByEventId = this.buildDebugIndex(result);
|
|
@@ -9859,8 +9639,7 @@ var RetrievalDisclosureService = class {
|
|
|
9859
9639
|
return this.expandShared(parsedId.entryId);
|
|
9860
9640
|
}
|
|
9861
9641
|
const targetEvent = await this.deps.eventStore.getEvent(parsedId.eventId);
|
|
9862
|
-
if (!targetEvent)
|
|
9863
|
-
return null;
|
|
9642
|
+
if (!targetEvent) return null;
|
|
9864
9643
|
const windowSize = Math.max(0, options?.windowSize ?? 3);
|
|
9865
9644
|
const sessionEvents = (await this.deps.eventStore.getSessionEvents(targetEvent.sessionId)).slice().sort((a, b) => a.timestamp.getTime() - b.timestamp.getTime());
|
|
9866
9645
|
const targetIndex = sessionEvents.findIndex((event) => event.id === targetEvent.id);
|
|
@@ -9884,8 +9663,7 @@ var RetrievalDisclosureService = class {
|
|
|
9884
9663
|
return this.sourceShared(parsedId.entryId);
|
|
9885
9664
|
}
|
|
9886
9665
|
const rawEvent = await this.deps.eventStore.getEvent(parsedId.eventId);
|
|
9887
|
-
if (!rawEvent)
|
|
9888
|
-
return null;
|
|
9666
|
+
if (!rawEvent) return null;
|
|
9889
9667
|
return {
|
|
9890
9668
|
...this.sourceReferenceForEvent(rawEvent),
|
|
9891
9669
|
rawEvents: [rawEvent],
|
|
@@ -9894,8 +9672,7 @@ var RetrievalDisclosureService = class {
|
|
|
9894
9672
|
}
|
|
9895
9673
|
async expandShared(entryId) {
|
|
9896
9674
|
const entry = await this.deps.sharedStore?.get(entryId);
|
|
9897
|
-
if (!entry)
|
|
9898
|
-
return null;
|
|
9675
|
+
if (!entry) return null;
|
|
9899
9676
|
return {
|
|
9900
9677
|
target: this.sharedToEnvelope(entry),
|
|
9901
9678
|
surroundingFacts: [],
|
|
@@ -9906,8 +9683,7 @@ var RetrievalDisclosureService = class {
|
|
|
9906
9683
|
}
|
|
9907
9684
|
async sourceShared(entryId) {
|
|
9908
9685
|
const entry = await this.deps.sharedStore?.get(entryId);
|
|
9909
|
-
if (!entry)
|
|
9910
|
-
return null;
|
|
9686
|
+
if (!entry) return null;
|
|
9911
9687
|
const sourceReference = this.sourceReferenceForShared(entry);
|
|
9912
9688
|
return {
|
|
9913
9689
|
...sourceReference,
|
|
@@ -9993,38 +9769,25 @@ var RetrievalDisclosureService = class {
|
|
|
9993
9769
|
const reasons = /* @__PURE__ */ new Set();
|
|
9994
9770
|
const usedVector = this.usedVector(result);
|
|
9995
9771
|
const usedKeyword = this.usedKeyword(result);
|
|
9996
|
-
if (usedVector && (debug?.semanticScore ?? 0) > 0)
|
|
9997
|
-
|
|
9998
|
-
if ((debug?.
|
|
9999
|
-
|
|
10000
|
-
if ((debug?.
|
|
10001
|
-
|
|
10002
|
-
if (
|
|
10003
|
-
|
|
10004
|
-
if (
|
|
10005
|
-
reasons.add("entity_overlap");
|
|
10006
|
-
if ((result.fallbackTrace || []).some((step) => step === "fallback:summary"))
|
|
10007
|
-
reasons.add("summary_fallback");
|
|
10008
|
-
if (memory.sessionContext)
|
|
10009
|
-
reasons.add("continuity_link");
|
|
10010
|
-
if (memory.event.eventType === "tool_observation")
|
|
10011
|
-
reasons.add("tool_followup");
|
|
10012
|
-
if (reasons.size === 0)
|
|
10013
|
-
reasons.add(usedVector ? "semantic_match" : "keyword_match");
|
|
9772
|
+
if (usedVector && (debug?.semanticScore ?? 0) > 0) reasons.add("semantic_match");
|
|
9773
|
+
if ((debug?.lexicalScore ?? 0) > 0 || usedKeyword) reasons.add("keyword_match");
|
|
9774
|
+
if ((debug?.recencyScore ?? 0) > 0) reasons.add("recent_relevance");
|
|
9775
|
+
if ((debug?.facetMatches || []).length > 0) reasons.add("facet_match");
|
|
9776
|
+
if ((debug?.graphPaths || []).length > 0) reasons.add("entity_overlap");
|
|
9777
|
+
if ((result.fallbackTrace || []).some((step) => step === "fallback:summary")) reasons.add("summary_fallback");
|
|
9778
|
+
if (memory.sessionContext) reasons.add("continuity_link");
|
|
9779
|
+
if (memory.event.eventType === "tool_observation") reasons.add("tool_followup");
|
|
9780
|
+
if (reasons.size === 0) reasons.add(usedVector ? "semantic_match" : "keyword_match");
|
|
10014
9781
|
return Array.from(reasons);
|
|
10015
9782
|
}
|
|
10016
9783
|
reasonsForContextEvent(event) {
|
|
10017
|
-
if (event.eventType === "tool_observation")
|
|
10018
|
-
|
|
10019
|
-
if (event.eventType === "session_summary")
|
|
10020
|
-
return ["summary_fallback"];
|
|
9784
|
+
if (event.eventType === "tool_observation") return ["tool_followup"];
|
|
9785
|
+
if (event.eventType === "session_summary") return ["summary_fallback"];
|
|
10021
9786
|
return ["continuity_link"];
|
|
10022
9787
|
}
|
|
10023
9788
|
resultTypeForEvent(event) {
|
|
10024
|
-
if (event.eventType === "session_summary")
|
|
10025
|
-
|
|
10026
|
-
if (event.eventType === "tool_observation")
|
|
10027
|
-
return "tool_evidence";
|
|
9789
|
+
if (event.eventType === "session_summary") return "summary";
|
|
9790
|
+
if (event.eventType === "tool_observation") return "tool_evidence";
|
|
10028
9791
|
return "source";
|
|
10029
9792
|
}
|
|
10030
9793
|
sourceReferenceForEvent(event) {
|
|
@@ -10048,21 +9811,15 @@ var RetrievalDisclosureService = class {
|
|
|
10048
9811
|
}
|
|
10049
9812
|
sourceTypeForEvent(event) {
|
|
10050
9813
|
const metadata = event.metadata || {};
|
|
10051
|
-
if (event.eventType === "tool_observation")
|
|
10052
|
-
|
|
10053
|
-
if (typeof metadata.
|
|
10054
|
-
return "transcript";
|
|
10055
|
-
if (typeof metadata.importedFrom === "string")
|
|
10056
|
-
return "imported_history";
|
|
9814
|
+
if (event.eventType === "tool_observation") return "tool_output";
|
|
9815
|
+
if (typeof metadata.transcriptPath === "string") return "transcript";
|
|
9816
|
+
if (typeof metadata.importedFrom === "string") return "imported_history";
|
|
10057
9817
|
return "raw_event";
|
|
10058
9818
|
}
|
|
10059
9819
|
titleForEvent(event) {
|
|
10060
|
-
if (event.eventType === "session_summary")
|
|
10061
|
-
|
|
10062
|
-
if (event.eventType === "
|
|
10063
|
-
return "Tool evidence";
|
|
10064
|
-
if (event.eventType === "agent_response")
|
|
10065
|
-
return "Agent response";
|
|
9820
|
+
if (event.eventType === "session_summary") return "Session summary";
|
|
9821
|
+
if (event.eventType === "tool_observation") return "Tool evidence";
|
|
9822
|
+
if (event.eventType === "agent_response") return "Agent response";
|
|
10066
9823
|
return "User prompt";
|
|
10067
9824
|
}
|
|
10068
9825
|
usedVector(result) {
|
|
@@ -10088,8 +9845,7 @@ var RetrievalDisclosureService = class {
|
|
|
10088
9845
|
}
|
|
10089
9846
|
preview(content, maxLength) {
|
|
10090
9847
|
const normalized = content.replace(/\s+/g, " ").trim();
|
|
10091
|
-
if (normalized.length <= maxLength)
|
|
10092
|
-
return normalized;
|
|
9848
|
+
if (normalized.length <= maxLength) return normalized;
|
|
10093
9849
|
return `${normalized.slice(0, Math.max(0, maxLength - 3))}...`;
|
|
10094
9850
|
}
|
|
10095
9851
|
};
|
|
@@ -10118,6 +9874,7 @@ var RetrievalOrchestrator = class {
|
|
|
10118
9874
|
this.deps = deps;
|
|
10119
9875
|
this.deps.retriever.setQueryRewriter((query) => this.rewriteQueryIntent(query));
|
|
10120
9876
|
}
|
|
9877
|
+
deps;
|
|
10121
9878
|
/**
|
|
10122
9879
|
* Retrieve relevant memories for a query.
|
|
10123
9880
|
*/
|
|
@@ -10199,8 +9956,7 @@ var RetrievalOrchestrator = class {
|
|
|
10199
9956
|
* the heavier retrieval/vector initialization path for prompt telemetry.
|
|
10200
9957
|
*/
|
|
10201
9958
|
async incrementMemoryAccess(eventIds) {
|
|
10202
|
-
if (eventIds.length === 0)
|
|
10203
|
-
return;
|
|
9959
|
+
if (eventIds.length === 0) return;
|
|
10204
9960
|
await this.deps.accessStore.incrementAccessCount(eventIds);
|
|
10205
9961
|
}
|
|
10206
9962
|
/**
|
|
@@ -10213,10 +9969,8 @@ var RetrievalOrchestrator = class {
|
|
|
10213
9969
|
resolveGraphHopOptions(callerOptions) {
|
|
10214
9970
|
const graphExpansion = this.deps.memoryOperationsConfig?.graphExpansion;
|
|
10215
9971
|
const durableOptions = graphExpansion?.enabled === true ? { enabled: true, maxHops: graphExpansion.maxHops } : void 0;
|
|
10216
|
-
if (!callerOptions)
|
|
10217
|
-
|
|
10218
|
-
if (!graphExpansion)
|
|
10219
|
-
return callerOptions;
|
|
9972
|
+
if (!callerOptions) return durableOptions;
|
|
9973
|
+
if (!graphExpansion) return callerOptions;
|
|
10220
9974
|
if (graphExpansion.enabled !== true) {
|
|
10221
9975
|
return {
|
|
10222
9976
|
...callerOptions,
|
|
@@ -10276,12 +10030,10 @@ var RetrievalOrchestrator = class {
|
|
|
10276
10030
|
const lexical = Number(process.env.MEMORY_RERANK_WEIGHT_LEXICAL ?? "");
|
|
10277
10031
|
const recency = Number(process.env.MEMORY_RERANK_WEIGHT_RECENCY ?? "");
|
|
10278
10032
|
const allFinite = [semantic, lexical, recency].every((value) => Number.isFinite(value));
|
|
10279
|
-
if (!allFinite)
|
|
10280
|
-
return void 0;
|
|
10033
|
+
if (!allFinite) return void 0;
|
|
10281
10034
|
const nonNegative = [semantic, lexical, recency].every((value) => value >= 0);
|
|
10282
10035
|
const total = semantic + lexical + recency;
|
|
10283
|
-
if (!nonNegative || total <= 0)
|
|
10284
|
-
return void 0;
|
|
10036
|
+
if (!nonNegative || total <= 0) return void 0;
|
|
10285
10037
|
return {
|
|
10286
10038
|
semantic: semantic / total,
|
|
10287
10039
|
lexical: lexical / total,
|
|
@@ -10290,17 +10042,14 @@ var RetrievalOrchestrator = class {
|
|
|
10290
10042
|
}
|
|
10291
10043
|
async getRerankWeights(adaptive) {
|
|
10292
10044
|
const configured = this.getConfiguredRerankWeights();
|
|
10293
|
-
if (configured)
|
|
10294
|
-
|
|
10295
|
-
if (adaptive)
|
|
10296
|
-
return this.getAdaptiveRerankWeights();
|
|
10045
|
+
if (configured) return configured;
|
|
10046
|
+
if (adaptive) return this.getAdaptiveRerankWeights();
|
|
10297
10047
|
return void 0;
|
|
10298
10048
|
}
|
|
10299
10049
|
async getAdaptiveRerankWeights() {
|
|
10300
10050
|
try {
|
|
10301
10051
|
const stats = await this.deps.traceStore.getHelpfulnessStats();
|
|
10302
|
-
if (stats.totalEvaluated < 20)
|
|
10303
|
-
return void 0;
|
|
10052
|
+
if (stats.totalEvaluated < 20) return void 0;
|
|
10304
10053
|
let semantic = 0.7;
|
|
10305
10054
|
let lexical = 0.2;
|
|
10306
10055
|
let recency = 0.1;
|
|
@@ -10322,11 +10071,9 @@ var RetrievalOrchestrator = class {
|
|
|
10322
10071
|
}
|
|
10323
10072
|
}
|
|
10324
10073
|
async rewriteQueryIntent(query) {
|
|
10325
|
-
if (process.env.MEMORY_INTENT_REWRITE_ENABLED !== "1")
|
|
10326
|
-
return null;
|
|
10074
|
+
if (process.env.MEMORY_INTENT_REWRITE_ENABLED !== "1") return null;
|
|
10327
10075
|
const apiUrl = process.env.COMPANY_STOCK_API_URL || process.env.COMPANY_INT_API_URL;
|
|
10328
|
-
if (!apiUrl)
|
|
10329
|
-
return null;
|
|
10076
|
+
if (!apiUrl) return null;
|
|
10330
10077
|
const controller = new AbortController();
|
|
10331
10078
|
const timeoutMs = Number(process.env.MEMORY_INTENT_REWRITE_TIMEOUT_MS || 5e3);
|
|
10332
10079
|
const timeout = setTimeout(() => controller.abort(), timeoutMs);
|
|
@@ -10352,11 +10099,9 @@ var RetrievalOrchestrator = class {
|
|
|
10352
10099
|
signal: controller.signal
|
|
10353
10100
|
});
|
|
10354
10101
|
const text = (await res.text()).trim();
|
|
10355
|
-
if (!text)
|
|
10356
|
-
return null;
|
|
10102
|
+
if (!text) return null;
|
|
10357
10103
|
const oneLine = text.replace(/^data:\s*/gm, "").split(/\r?\n/).map((line) => line.trim()).filter(Boolean).join(" ").slice(0, 240);
|
|
10358
|
-
if (!oneLine || oneLine.toLowerCase() === query.toLowerCase())
|
|
10359
|
-
return null;
|
|
10104
|
+
if (!oneLine || oneLine.toLowerCase() === query.toLowerCase()) return null;
|
|
10360
10105
|
return oneLine;
|
|
10361
10106
|
} catch {
|
|
10362
10107
|
return null;
|
|
@@ -10498,8 +10243,7 @@ function createMemoryEngineServices(options) {
|
|
|
10498
10243
|
};
|
|
10499
10244
|
}
|
|
10500
10245
|
function shouldEnablePerspectiveDeriver(options) {
|
|
10501
|
-
if (options.readOnly)
|
|
10502
|
-
return false;
|
|
10246
|
+
if (options.readOnly) return false;
|
|
10503
10247
|
const perspectiveMemory = options.memoryOperationsConfig?.perspectiveMemory;
|
|
10504
10248
|
return perspectiveMemory?.enabled === true && perspectiveMemory.deriver?.enabled === true;
|
|
10505
10249
|
}
|
|
@@ -10533,6 +10277,9 @@ var GraduationWorker = class {
|
|
|
10533
10277
|
this.graduation = graduation;
|
|
10534
10278
|
this.config = config;
|
|
10535
10279
|
}
|
|
10280
|
+
eventStore;
|
|
10281
|
+
graduation;
|
|
10282
|
+
config;
|
|
10536
10283
|
running = false;
|
|
10537
10284
|
timeout = null;
|
|
10538
10285
|
lastEvaluated = /* @__PURE__ */ new Map();
|
|
@@ -10540,8 +10287,7 @@ var GraduationWorker = class {
|
|
|
10540
10287
|
* Start the graduation worker
|
|
10541
10288
|
*/
|
|
10542
10289
|
start() {
|
|
10543
|
-
if (this.running)
|
|
10544
|
-
return;
|
|
10290
|
+
if (this.running) return;
|
|
10545
10291
|
this.running = true;
|
|
10546
10292
|
this.scheduleNext();
|
|
10547
10293
|
}
|
|
@@ -10571,8 +10317,7 @@ var GraduationWorker = class {
|
|
|
10571
10317
|
* Schedule the next graduation check
|
|
10572
10318
|
*/
|
|
10573
10319
|
scheduleNext() {
|
|
10574
|
-
if (!this.running)
|
|
10575
|
-
return;
|
|
10320
|
+
if (!this.running) return;
|
|
10576
10321
|
this.timeout = setTimeout(
|
|
10577
10322
|
() => this.run(),
|
|
10578
10323
|
this.config.evaluationIntervalMs
|
|
@@ -10582,8 +10327,7 @@ var GraduationWorker = class {
|
|
|
10582
10327
|
* Run graduation evaluation
|
|
10583
10328
|
*/
|
|
10584
10329
|
async run() {
|
|
10585
|
-
if (!this.running)
|
|
10586
|
-
return;
|
|
10330
|
+
if (!this.running) return;
|
|
10587
10331
|
try {
|
|
10588
10332
|
await this.runGraduation();
|
|
10589
10333
|
} catch (error) {
|
|
@@ -10647,10 +10391,8 @@ var DEFAULT_CONFIG5 = {
|
|
|
10647
10391
|
maxRetries: 3
|
|
10648
10392
|
};
|
|
10649
10393
|
function parseJsonArray(value) {
|
|
10650
|
-
if (Array.isArray(value))
|
|
10651
|
-
|
|
10652
|
-
if (typeof value !== "string" || value.trim().length === 0)
|
|
10653
|
-
return [];
|
|
10394
|
+
if (Array.isArray(value)) return value;
|
|
10395
|
+
if (typeof value !== "string" || value.trim().length === 0) return [];
|
|
10654
10396
|
try {
|
|
10655
10397
|
const parsed = JSON.parse(value);
|
|
10656
10398
|
return Array.isArray(parsed) ? parsed : [];
|
|
@@ -10680,8 +10422,7 @@ var VectorWorker = class {
|
|
|
10680
10422
|
* Start the worker polling loop
|
|
10681
10423
|
*/
|
|
10682
10424
|
start() {
|
|
10683
|
-
if (this.running)
|
|
10684
|
-
return;
|
|
10425
|
+
if (this.running) return;
|
|
10685
10426
|
this.running = true;
|
|
10686
10427
|
this.stopping = false;
|
|
10687
10428
|
this.poll();
|
|
@@ -10757,8 +10498,7 @@ var VectorWorker = class {
|
|
|
10757
10498
|
* Poll for new items
|
|
10758
10499
|
*/
|
|
10759
10500
|
async poll() {
|
|
10760
|
-
if (!this.running || this.stopping)
|
|
10761
|
-
return;
|
|
10501
|
+
if (!this.running || this.stopping) return;
|
|
10762
10502
|
try {
|
|
10763
10503
|
await this.processBatch();
|
|
10764
10504
|
} catch (error) {
|
|
@@ -10803,6 +10543,7 @@ var DefaultContentProvider = class {
|
|
|
10803
10543
|
constructor(db) {
|
|
10804
10544
|
this.db = db;
|
|
10805
10545
|
}
|
|
10546
|
+
db;
|
|
10806
10547
|
async getContent(itemKind, itemId) {
|
|
10807
10548
|
switch (itemKind) {
|
|
10808
10549
|
case "entry":
|
|
@@ -10823,8 +10564,7 @@ var DefaultContentProvider = class {
|
|
|
10823
10564
|
`SELECT title, content_json, entry_type FROM entries WHERE entry_id = ?`,
|
|
10824
10565
|
[entryId]
|
|
10825
10566
|
);
|
|
10826
|
-
if (rows.length === 0)
|
|
10827
|
-
return null;
|
|
10567
|
+
if (rows.length === 0) return null;
|
|
10828
10568
|
const row = rows[0];
|
|
10829
10569
|
const contentJson = typeof row.content_json === "string" ? JSON.parse(row.content_json) : row.content_json;
|
|
10830
10570
|
return {
|
|
@@ -10843,8 +10583,7 @@ ${JSON.stringify(contentJson)}`,
|
|
|
10843
10583
|
WHERE entity_id = ? AND entity_type = 'task'`,
|
|
10844
10584
|
[taskId]
|
|
10845
10585
|
);
|
|
10846
|
-
if (rows.length === 0)
|
|
10847
|
-
return null;
|
|
10586
|
+
if (rows.length === 0) return null;
|
|
10848
10587
|
const row = rows[0];
|
|
10849
10588
|
return {
|
|
10850
10589
|
content: row.search_text || row.title,
|
|
@@ -10860,8 +10599,7 @@ ${JSON.stringify(contentJson)}`,
|
|
|
10860
10599
|
`SELECT content, event_type, session_id FROM events WHERE id = ?`,
|
|
10861
10600
|
[eventId]
|
|
10862
10601
|
);
|
|
10863
|
-
if (rows.length === 0)
|
|
10864
|
-
return null;
|
|
10602
|
+
if (rows.length === 0) return null;
|
|
10865
10603
|
const row = rows[0];
|
|
10866
10604
|
return {
|
|
10867
10605
|
content: row.content,
|
|
@@ -10889,8 +10627,7 @@ ${JSON.stringify(contentJson)}`,
|
|
|
10889
10627
|
}
|
|
10890
10628
|
throw error;
|
|
10891
10629
|
}
|
|
10892
|
-
if (rows.length === 0)
|
|
10893
|
-
return null;
|
|
10630
|
+
if (rows.length === 0) return null;
|
|
10894
10631
|
const row = rows[0];
|
|
10895
10632
|
const sourceEventIds = parseJsonArray(row.source_event_ids_json);
|
|
10896
10633
|
const sourceObservationIds = parseJsonArray(row.source_observation_ids_json);
|
|
@@ -10932,8 +10669,7 @@ var VectorWorkerV2 = class {
|
|
|
10932
10669
|
* Start the worker polling loop
|
|
10933
10670
|
*/
|
|
10934
10671
|
start() {
|
|
10935
|
-
if (this.running)
|
|
10936
|
-
return;
|
|
10672
|
+
if (this.running) return;
|
|
10937
10673
|
this.running = true;
|
|
10938
10674
|
this.stopping = false;
|
|
10939
10675
|
this.poll();
|
|
@@ -11003,8 +10739,7 @@ var VectorWorkerV2 = class {
|
|
|
11003
10739
|
* Poll for new jobs
|
|
11004
10740
|
*/
|
|
11005
10741
|
async poll() {
|
|
11006
|
-
if (!this.running || this.stopping)
|
|
11007
|
-
return;
|
|
10742
|
+
if (!this.running || this.stopping) return;
|
|
11008
10743
|
try {
|
|
11009
10744
|
await this.processBatch();
|
|
11010
10745
|
} catch (error) {
|
|
@@ -11071,8 +10806,7 @@ function createMemoryRuntimeService(deps) {
|
|
|
11071
10806
|
let graduationWorker = null;
|
|
11072
10807
|
return {
|
|
11073
10808
|
async initialize() {
|
|
11074
|
-
if (initialized)
|
|
11075
|
-
return;
|
|
10809
|
+
if (initialized) return;
|
|
11076
10810
|
await deps.sqliteStore.initialize();
|
|
11077
10811
|
if (deps.lightweightMode) {
|
|
11078
10812
|
initialized = true;
|
|
@@ -11166,8 +10900,7 @@ var SharedEventStore = class {
|
|
|
11166
10900
|
this.db = createDatabase(dbPath);
|
|
11167
10901
|
}
|
|
11168
10902
|
async initialize() {
|
|
11169
|
-
if (this.initialized)
|
|
11170
|
-
return;
|
|
10903
|
+
if (this.initialized) return;
|
|
11171
10904
|
await dbRun(this.db, `
|
|
11172
10905
|
CREATE TABLE IF NOT EXISTS shared_troubleshooting (
|
|
11173
10906
|
entry_id VARCHAR PRIMARY KEY,
|
|
@@ -11257,6 +10990,10 @@ var SharedPromoter = class {
|
|
|
11257
10990
|
this.embedder = embedder;
|
|
11258
10991
|
this.config = config;
|
|
11259
10992
|
}
|
|
10993
|
+
sharedStore;
|
|
10994
|
+
sharedVectorStore;
|
|
10995
|
+
embedder;
|
|
10996
|
+
config;
|
|
11260
10997
|
/**
|
|
11261
10998
|
* Check if an entry is eligible for promotion
|
|
11262
10999
|
*/
|
|
@@ -11438,6 +11175,7 @@ var SharedStore = class {
|
|
|
11438
11175
|
constructor(sharedEventStore) {
|
|
11439
11176
|
this.sharedEventStore = sharedEventStore;
|
|
11440
11177
|
}
|
|
11178
|
+
sharedEventStore;
|
|
11441
11179
|
get db() {
|
|
11442
11180
|
return this.sharedEventStore.getDatabase();
|
|
11443
11181
|
}
|
|
@@ -11542,8 +11280,7 @@ var SharedStore = class {
|
|
|
11542
11280
|
`SELECT * FROM shared_troubleshooting WHERE entry_id = ?`,
|
|
11543
11281
|
[entryId]
|
|
11544
11282
|
);
|
|
11545
|
-
if (rows.length === 0)
|
|
11546
|
-
return null;
|
|
11283
|
+
if (rows.length === 0) return null;
|
|
11547
11284
|
return this.rowToEntry(rows[0]);
|
|
11548
11285
|
}
|
|
11549
11286
|
/**
|
|
@@ -11556,8 +11293,7 @@ var SharedStore = class {
|
|
|
11556
11293
|
WHERE source_project_hash = ? AND source_entry_id = ?`,
|
|
11557
11294
|
[projectHash, sourceEntryId]
|
|
11558
11295
|
);
|
|
11559
|
-
if (rows.length === 0)
|
|
11560
|
-
return null;
|
|
11296
|
+
if (rows.length === 0) return null;
|
|
11561
11297
|
return this.rowToEntry(rows[0]);
|
|
11562
11298
|
}
|
|
11563
11299
|
/**
|
|
@@ -11667,6 +11403,7 @@ var SharedVectorStore = class {
|
|
|
11667
11403
|
constructor(dbPath) {
|
|
11668
11404
|
this.dbPath = dbPath;
|
|
11669
11405
|
}
|
|
11406
|
+
dbPath;
|
|
11670
11407
|
db = null;
|
|
11671
11408
|
table = null;
|
|
11672
11409
|
tableName = "shared_knowledge";
|
|
@@ -11674,8 +11411,7 @@ var SharedVectorStore = class {
|
|
|
11674
11411
|
* Initialize LanceDB connection
|
|
11675
11412
|
*/
|
|
11676
11413
|
async initialize() {
|
|
11677
|
-
if (this.db)
|
|
11678
|
-
return;
|
|
11414
|
+
if (this.db) return;
|
|
11679
11415
|
this.db = await lancedb2.connect(this.dbPath);
|
|
11680
11416
|
try {
|
|
11681
11417
|
const tables = await this.db.tableNames();
|
|
@@ -11717,8 +11453,7 @@ var SharedVectorStore = class {
|
|
|
11717
11453
|
* Add multiple records in batch
|
|
11718
11454
|
*/
|
|
11719
11455
|
async upsertBatch(records) {
|
|
11720
|
-
if (records.length === 0)
|
|
11721
|
-
return;
|
|
11456
|
+
if (records.length === 0) return;
|
|
11722
11457
|
await this.initialize();
|
|
11723
11458
|
if (!this.db) {
|
|
11724
11459
|
throw new Error("Database not initialized");
|
|
@@ -11779,24 +11514,21 @@ var SharedVectorStore = class {
|
|
|
11779
11514
|
* Delete vector by entry ID
|
|
11780
11515
|
*/
|
|
11781
11516
|
async delete(entryId) {
|
|
11782
|
-
if (!this.table)
|
|
11783
|
-
return;
|
|
11517
|
+
if (!this.table) return;
|
|
11784
11518
|
await this.table.delete(`entryId = '${entryId}'`);
|
|
11785
11519
|
}
|
|
11786
11520
|
/**
|
|
11787
11521
|
* Get total count
|
|
11788
11522
|
*/
|
|
11789
11523
|
async count() {
|
|
11790
|
-
if (!this.table)
|
|
11791
|
-
return 0;
|
|
11524
|
+
if (!this.table) return 0;
|
|
11792
11525
|
return this.table.countRows();
|
|
11793
11526
|
}
|
|
11794
11527
|
/**
|
|
11795
11528
|
* Check if vector exists for entry
|
|
11796
11529
|
*/
|
|
11797
11530
|
async exists(entryId) {
|
|
11798
|
-
if (!this.table)
|
|
11799
|
-
return false;
|
|
11531
|
+
if (!this.table) return false;
|
|
11800
11532
|
try {
|
|
11801
11533
|
const results = await this.table.search([]).where(`entryId = '${entryId}'`).limit(1).toArray();
|
|
11802
11534
|
return results.length > 0;
|
|
@@ -11814,6 +11546,7 @@ var SharedMemoryServices = class {
|
|
|
11814
11546
|
constructor(options) {
|
|
11815
11547
|
this.options = options;
|
|
11816
11548
|
}
|
|
11549
|
+
options;
|
|
11817
11550
|
sharedEventStore = null;
|
|
11818
11551
|
sharedStore = null;
|
|
11819
11552
|
sharedVectorStore = null;
|
|
@@ -11838,8 +11571,7 @@ var SharedMemoryServices = class {
|
|
|
11838
11571
|
return this.options.config?.sharedStoragePath ? this.options.expandPath(this.options.config.sharedStoragePath) : this.options.defaultSharedStoragePath;
|
|
11839
11572
|
}
|
|
11840
11573
|
async initialize() {
|
|
11841
|
-
if (this.options.config?.enabled === false || this.options.readOnly)
|
|
11842
|
-
return;
|
|
11574
|
+
if (this.options.config?.enabled === false || this.options.readOnly) return;
|
|
11843
11575
|
const sharedPath = this.getSharedStoragePath();
|
|
11844
11576
|
this.ensureDirectory(sharedPath, { allowCreate: true });
|
|
11845
11577
|
const store = await this.openStore(sharedPath);
|
|
@@ -11856,14 +11588,11 @@ var SharedMemoryServices = class {
|
|
|
11856
11588
|
this.options.retriever.setSharedStores(store, this.sharedVectorStore);
|
|
11857
11589
|
}
|
|
11858
11590
|
async ensureStoreForRead() {
|
|
11859
|
-
if (this.options.config?.enabled === false)
|
|
11860
|
-
|
|
11861
|
-
if (this.sharedStore)
|
|
11862
|
-
return this.sharedStore;
|
|
11591
|
+
if (this.options.config?.enabled === false) return null;
|
|
11592
|
+
if (this.sharedStore) return this.sharedStore;
|
|
11863
11593
|
const sharedPath = this.getSharedStoragePath();
|
|
11864
11594
|
const directoryReady = this.ensureDirectory(sharedPath, { allowCreate: !this.options.readOnly });
|
|
11865
|
-
if (!directoryReady)
|
|
11866
|
-
return null;
|
|
11595
|
+
if (!directoryReady) return null;
|
|
11867
11596
|
return this.openStore(sharedPath);
|
|
11868
11597
|
}
|
|
11869
11598
|
async getEntryForDisclosure(entryId) {
|
|
@@ -11880,13 +11609,11 @@ var SharedMemoryServices = class {
|
|
|
11880
11609
|
return this.sharedPromoter.promoteEntry(entry, projectHash);
|
|
11881
11610
|
}
|
|
11882
11611
|
async getStats() {
|
|
11883
|
-
if (!this.sharedStore)
|
|
11884
|
-
return null;
|
|
11612
|
+
if (!this.sharedStore) return null;
|
|
11885
11613
|
return this.sharedStore.getStats();
|
|
11886
11614
|
}
|
|
11887
11615
|
async search(query, options) {
|
|
11888
|
-
if (!this.sharedStore)
|
|
11889
|
-
return [];
|
|
11616
|
+
if (!this.sharedStore) return [];
|
|
11890
11617
|
return this.sharedStore.search(query, options);
|
|
11891
11618
|
}
|
|
11892
11619
|
async close() {
|
|
@@ -11903,8 +11630,7 @@ var SharedMemoryServices = class {
|
|
|
11903
11630
|
this.openStorePromise = null;
|
|
11904
11631
|
}
|
|
11905
11632
|
async openStore(sharedPath) {
|
|
11906
|
-
if (this.sharedStore)
|
|
11907
|
-
return this.sharedStore;
|
|
11633
|
+
if (this.sharedStore) return this.sharedStore;
|
|
11908
11634
|
if (!this.openStorePromise) {
|
|
11909
11635
|
this.openStorePromise = this.createOpenStorePromise(sharedPath);
|
|
11910
11636
|
}
|
|
@@ -11928,10 +11654,8 @@ var SharedMemoryServices = class {
|
|
|
11928
11654
|
return this.sharedStore;
|
|
11929
11655
|
}
|
|
11930
11656
|
ensureDirectory(sharedPath, options) {
|
|
11931
|
-
if (this.factories.existsSync(sharedPath))
|
|
11932
|
-
|
|
11933
|
-
if (!options.allowCreate)
|
|
11934
|
-
return false;
|
|
11657
|
+
if (this.factories.existsSync(sharedPath)) return true;
|
|
11658
|
+
if (!options.allowCreate) return false;
|
|
11935
11659
|
this.factories.mkdirSync(sharedPath);
|
|
11936
11660
|
return true;
|
|
11937
11661
|
}
|
|
@@ -12721,13 +12445,10 @@ function getLastResponsePath(sessionId) {
|
|
|
12721
12445
|
function readLastAssistantSnippet(sessionId) {
|
|
12722
12446
|
try {
|
|
12723
12447
|
const filePath = getLastResponsePath(sessionId);
|
|
12724
|
-
if (!fs9.existsSync(filePath))
|
|
12725
|
-
return null;
|
|
12448
|
+
if (!fs9.existsSync(filePath)) return null;
|
|
12726
12449
|
const state = JSON.parse(fs9.readFileSync(filePath, "utf-8"));
|
|
12727
|
-
if (state.sessionId !== sessionId)
|
|
12728
|
-
|
|
12729
|
-
if (Date.now() - new Date(state.createdAt).getTime() > 2 * 60 * 60 * 1e3)
|
|
12730
|
-
return null;
|
|
12450
|
+
if (state.sessionId !== sessionId) return null;
|
|
12451
|
+
if (Date.now() - new Date(state.createdAt).getTime() > 2 * 60 * 60 * 1e3) return null;
|
|
12731
12452
|
return state.snippet || null;
|
|
12732
12453
|
} catch {
|
|
12733
12454
|
return null;
|
|
@@ -12785,8 +12506,7 @@ function requestFromDaemon(payload, timeoutMs) {
|
|
|
12785
12506
|
client.destroy();
|
|
12786
12507
|
}, timeoutMs);
|
|
12787
12508
|
const settle = (error, memories) => {
|
|
12788
|
-
if (settled)
|
|
12789
|
-
return;
|
|
12509
|
+
if (settled) return;
|
|
12790
12510
|
settled = true;
|
|
12791
12511
|
clearTimeout(timer);
|
|
12792
12512
|
if (error) {
|
|
@@ -12867,8 +12587,7 @@ function canConnect() {
|
|
|
12867
12587
|
let settled = false;
|
|
12868
12588
|
const client = net.createConnection(DAEMON_SOCKET_PATH);
|
|
12869
12589
|
const finalize = (ok) => {
|
|
12870
|
-
if (settled)
|
|
12871
|
-
return;
|
|
12590
|
+
if (settled) return;
|
|
12872
12591
|
settled = true;
|
|
12873
12592
|
client.destroy();
|
|
12874
12593
|
resolve2(ok);
|
|
@@ -12914,13 +12633,10 @@ function filterHookInjectableMemories(candidates, policy = getHookInjectionPolic
|
|
|
12914
12633
|
}
|
|
12915
12634
|
function summarizeHookInjectionConfidence(candidates) {
|
|
12916
12635
|
const scores = candidates.map((candidate) => candidate.score).filter((score) => typeof score === "number" && Number.isFinite(score));
|
|
12917
|
-
if (scores.length === 0)
|
|
12918
|
-
return "none";
|
|
12636
|
+
if (scores.length === 0) return "none";
|
|
12919
12637
|
const maxScore = Math.max(...scores);
|
|
12920
|
-
if (maxScore >= 0.8)
|
|
12921
|
-
|
|
12922
|
-
if (maxScore >= 0.65)
|
|
12923
|
-
return "medium";
|
|
12638
|
+
if (maxScore >= 0.8) return "high";
|
|
12639
|
+
if (maxScore >= 0.65) return "medium";
|
|
12924
12640
|
return "none";
|
|
12925
12641
|
}
|
|
12926
12642
|
function isHookInjectableMemory(candidate, policy) {
|
|
@@ -12942,15 +12658,11 @@ function readScoreThreshold(value, fallback) {
|
|
|
12942
12658
|
return readNumber(value, fallback, { min: 0, max: 1 });
|
|
12943
12659
|
}
|
|
12944
12660
|
function readNumber(value, fallback, bounds) {
|
|
12945
|
-
if (value === void 0 || value.trim() === "")
|
|
12946
|
-
return fallback;
|
|
12661
|
+
if (value === void 0 || value.trim() === "") return fallback;
|
|
12947
12662
|
const parsed = Number(value);
|
|
12948
|
-
if (!Number.isFinite(parsed))
|
|
12949
|
-
|
|
12950
|
-
if (bounds?.
|
|
12951
|
-
return fallback;
|
|
12952
|
-
if (bounds?.max !== void 0 && parsed > bounds.max)
|
|
12953
|
-
return fallback;
|
|
12663
|
+
if (!Number.isFinite(parsed)) return fallback;
|
|
12664
|
+
if (bounds?.min !== void 0 && parsed < bounds.min) return fallback;
|
|
12665
|
+
if (bounds?.max !== void 0 && parsed > bounds.max) return fallback;
|
|
12954
12666
|
return parsed;
|
|
12955
12667
|
}
|
|
12956
12668
|
|
|
@@ -12965,25 +12677,19 @@ var ADHERENCE_INTERVAL_TURNS = parseInt(process.env.CLAUDE_MEMORY_ADHERENCE_INTE
|
|
|
12965
12677
|
var ADHERENCE_STATE_DIR = path13.join(os8.homedir(), ".claude-code", "memory");
|
|
12966
12678
|
function shouldStorePrompt(prompt) {
|
|
12967
12679
|
const trimmed = prompt.trim();
|
|
12968
|
-
if (trimmed.startsWith("/"))
|
|
12969
|
-
|
|
12970
|
-
if (trimmed
|
|
12971
|
-
return false;
|
|
12972
|
-
if (!/[a-zA-Z가-힣]{2,}/.test(trimmed))
|
|
12973
|
-
return false;
|
|
12680
|
+
if (trimmed.startsWith("/")) return false;
|
|
12681
|
+
if (trimmed.length < 15) return false;
|
|
12682
|
+
if (!/[a-zA-Z가-힣]{2,}/.test(trimmed)) return false;
|
|
12974
12683
|
return true;
|
|
12975
12684
|
}
|
|
12976
12685
|
function getDynamicMinScore(prompt) {
|
|
12977
12686
|
const len = prompt.trim().length;
|
|
12978
|
-
if (len <= 20)
|
|
12979
|
-
|
|
12980
|
-
if (len >= 80)
|
|
12981
|
-
return Math.max(0.3, BASE_MIN_SCORE - 0.05);
|
|
12687
|
+
if (len <= 20) return Math.min(0.55, BASE_MIN_SCORE + 0.1);
|
|
12688
|
+
if (len >= 80) return Math.max(0.3, BASE_MIN_SCORE - 0.05);
|
|
12982
12689
|
return BASE_MIN_SCORE;
|
|
12983
12690
|
}
|
|
12984
12691
|
function formatMemoryContext(items) {
|
|
12985
|
-
if (items.length === 0)
|
|
12986
|
-
return "";
|
|
12692
|
+
if (items.length === 0) return "";
|
|
12987
12693
|
const lines = items.map((m) => {
|
|
12988
12694
|
const preview = m.content.length > 300 ? m.content.substring(0, 300) + "..." : m.content;
|
|
12989
12695
|
return `- [${m.type}] ${preview}`;
|
|
@@ -13010,8 +12716,7 @@ function readAdherenceState(sessionId) {
|
|
|
13010
12716
|
}
|
|
13011
12717
|
const data = fs11.readFileSync(filePath, "utf8");
|
|
13012
12718
|
const parsed = JSON.parse(data);
|
|
13013
|
-
if (parsed.sessionId !== sessionId)
|
|
13014
|
-
throw new Error("session mismatch");
|
|
12719
|
+
if (parsed.sessionId !== sessionId) throw new Error("session mismatch");
|
|
13015
12720
|
return parsed;
|
|
13016
12721
|
} catch {
|
|
13017
12722
|
return {
|
|
@@ -13054,47 +12759,35 @@ function tokenize(text) {
|
|
|
13054
12759
|
return text.toLowerCase().replace(/[^a-z0-9가-힣\s]/g, " ").split(/\s+/).filter((w) => w.length >= 2 && !stopwords.has(w));
|
|
13055
12760
|
}
|
|
13056
12761
|
function isTopicShift(currentPrompt, lastPrompt) {
|
|
13057
|
-
if (!lastPrompt || lastPrompt.length < 10)
|
|
13058
|
-
return false;
|
|
12762
|
+
if (!lastPrompt || lastPrompt.length < 10) return false;
|
|
13059
12763
|
const a = new Set(tokenize(currentPrompt));
|
|
13060
12764
|
const b = new Set(tokenize(lastPrompt));
|
|
13061
|
-
if (a.size === 0 || b.size === 0)
|
|
13062
|
-
return false;
|
|
12765
|
+
if (a.size === 0 || b.size === 0) return false;
|
|
13063
12766
|
let intersection = 0;
|
|
13064
12767
|
for (const token of a) {
|
|
13065
|
-
if (b.has(token))
|
|
13066
|
-
intersection++;
|
|
12768
|
+
if (b.has(token)) intersection++;
|
|
13067
12769
|
}
|
|
13068
12770
|
const union = a.size + b.size - intersection;
|
|
13069
12771
|
const similarity = union > 0 ? intersection / union : 0;
|
|
13070
12772
|
return similarity < 0.2;
|
|
13071
12773
|
}
|
|
13072
12774
|
function shouldRunAdherenceCheck(turnCount, prompt, state) {
|
|
13073
|
-
if (hasWriteIntent(prompt))
|
|
13074
|
-
|
|
13075
|
-
if (
|
|
13076
|
-
|
|
13077
|
-
if (
|
|
13078
|
-
|
|
13079
|
-
if (
|
|
13080
|
-
return { run: true, reason: "code-signal" };
|
|
13081
|
-
if (turnCount === 1)
|
|
13082
|
-
return { run: true, reason: "first-turn" };
|
|
13083
|
-
if (isTopicShift(prompt, state.lastPrompt))
|
|
13084
|
-
return { run: true, reason: "topic-shift" };
|
|
13085
|
-
if (turnCount - state.lastCheckedTurn >= ADHERENCE_INTERVAL_TURNS)
|
|
13086
|
-
return { run: true, reason: "interval" };
|
|
12775
|
+
if (hasWriteIntent(prompt)) return { run: true, reason: "write-intent" };
|
|
12776
|
+
if (hasContinuationIntent(prompt)) return { run: true, reason: "continuation-intent" };
|
|
12777
|
+
if (hasDecisionRecallIntent(prompt)) return { run: true, reason: "decision-recall" };
|
|
12778
|
+
if (hasProjectCodeSignal(prompt)) return { run: true, reason: "code-signal" };
|
|
12779
|
+
if (turnCount === 1) return { run: true, reason: "first-turn" };
|
|
12780
|
+
if (isTopicShift(prompt, state.lastPrompt)) return { run: true, reason: "topic-shift" };
|
|
12781
|
+
if (turnCount - state.lastCheckedTurn >= ADHERENCE_INTERVAL_TURNS) return { run: true, reason: "interval" };
|
|
13087
12782
|
return { run: false, reason: "skip" };
|
|
13088
12783
|
}
|
|
13089
12784
|
function isSlashCommandPrompt(prompt) {
|
|
13090
12785
|
return /^\/[a-z][\w:-]*(?:\s|$)/i.test(prompt);
|
|
13091
12786
|
}
|
|
13092
12787
|
function shouldRunMemorySearch(prompt, adherenceDecision) {
|
|
13093
|
-
if (!adherenceDecision.run)
|
|
13094
|
-
return false;
|
|
12788
|
+
if (!adherenceDecision.run) return false;
|
|
13095
12789
|
const trimmed = prompt.trim();
|
|
13096
|
-
if (isSlashCommandPrompt(trimmed))
|
|
13097
|
-
return false;
|
|
12790
|
+
if (isSlashCommandPrompt(trimmed)) return false;
|
|
13098
12791
|
const strongIntentReasons = /* @__PURE__ */ new Set([
|
|
13099
12792
|
"write-intent",
|
|
13100
12793
|
"continuation-intent",
|
|
@@ -13106,45 +12799,35 @@ function shouldRunMemorySearch(prompt, adherenceDecision) {
|
|
|
13106
12799
|
var MAX_RETRIEVAL_CONTEXT_CHARS = 500;
|
|
13107
12800
|
function compactRetrievalContext(text) {
|
|
13108
12801
|
const compacted = (text || "").replace(/\s+/g, " ").trim();
|
|
13109
|
-
if (compacted.length <= MAX_RETRIEVAL_CONTEXT_CHARS)
|
|
13110
|
-
return compacted;
|
|
12802
|
+
if (compacted.length <= MAX_RETRIEVAL_CONTEXT_CHARS) return compacted;
|
|
13111
12803
|
return `${compacted.slice(0, MAX_RETRIEVAL_CONTEXT_CHARS)}\u2026`;
|
|
13112
12804
|
}
|
|
13113
12805
|
function shouldEnrichRetrievalQuery(input) {
|
|
13114
|
-
if (input.currentTurn <= 1)
|
|
13115
|
-
|
|
13116
|
-
if (!input.adherenceDecision.run)
|
|
13117
|
-
return false;
|
|
12806
|
+
if (input.currentTurn <= 1) return false;
|
|
12807
|
+
if (!input.adherenceDecision.run) return false;
|
|
13118
12808
|
if (input.adherenceDecision.reason === "topic-shift" || input.adherenceDecision.reason === "first-turn") {
|
|
13119
12809
|
return false;
|
|
13120
12810
|
}
|
|
13121
12811
|
const hasPriorContext = Boolean(compactRetrievalContext(input.previousUserPrompt)) || Boolean(compactRetrievalContext(input.lastAssistantSnippet));
|
|
13122
|
-
if (!hasPriorContext)
|
|
13123
|
-
return false;
|
|
12812
|
+
if (!hasPriorContext) return false;
|
|
13124
12813
|
const reason = input.adherenceDecision.reason;
|
|
13125
|
-
if (reason === "continuation-intent" || reason === "decision-recall")
|
|
13126
|
-
|
|
13127
|
-
if (reason === "write-intent" && input.prompt.trim().length <= 40)
|
|
13128
|
-
return true;
|
|
12814
|
+
if (reason === "continuation-intent" || reason === "decision-recall") return true;
|
|
12815
|
+
if (reason === "write-intent" && input.prompt.trim().length <= 40) return true;
|
|
13129
12816
|
return false;
|
|
13130
12817
|
}
|
|
13131
12818
|
function buildRetrievalQuery(input) {
|
|
13132
12819
|
const currentPrompt = input.prompt.trim();
|
|
13133
|
-
if (!shouldEnrichRetrievalQuery(input))
|
|
13134
|
-
return currentPrompt;
|
|
12820
|
+
if (!shouldEnrichRetrievalQuery(input)) return currentPrompt;
|
|
13135
12821
|
const previousUser = compactRetrievalContext(input.previousUserPrompt);
|
|
13136
12822
|
const previousAssistant = compactRetrievalContext(input.lastAssistantSnippet);
|
|
13137
12823
|
const parts = [];
|
|
13138
|
-
if (previousUser)
|
|
13139
|
-
|
|
13140
|
-
if (previousAssistant)
|
|
13141
|
-
parts.push(`Previous assistant: ${previousAssistant}`);
|
|
12824
|
+
if (previousUser) parts.push(`Previous user: ${previousUser}`);
|
|
12825
|
+
if (previousAssistant) parts.push(`Previous assistant: ${previousAssistant}`);
|
|
13142
12826
|
parts.push(`Current user: ${currentPrompt}`);
|
|
13143
12827
|
return parts.join("\n\n");
|
|
13144
12828
|
}
|
|
13145
12829
|
function logAdherenceDecision(sessionId, turn, run, reason) {
|
|
13146
|
-
if (!process.env.CLAUDE_MEMORY_DEBUG)
|
|
13147
|
-
return;
|
|
12830
|
+
if (!process.env.CLAUDE_MEMORY_DEBUG) return;
|
|
13148
12831
|
const mode = run ? "enforced" : "skipped";
|
|
13149
12832
|
console.error(`[adherence] session=${sessionId} turn=${turn} mode=${mode} reason=${reason}`);
|
|
13150
12833
|
}
|
|
@@ -13228,8 +12911,7 @@ async function main() {
|
|
|
13228
12911
|
}
|
|
13229
12912
|
const existingIds = new Set(mergedMemories.map((m) => m.id).filter(Boolean));
|
|
13230
12913
|
for (const r of results) {
|
|
13231
|
-
if (existingIds.has(r.event.id))
|
|
13232
|
-
continue;
|
|
12914
|
+
if (existingIds.has(r.event.id)) continue;
|
|
13233
12915
|
mergedMemories.push({
|
|
13234
12916
|
type: r.event.eventType,
|
|
13235
12917
|
content: r.event.content,
|
|
@@ -13238,8 +12920,7 @@ async function main() {
|
|
|
13238
12920
|
source: "keyword",
|
|
13239
12921
|
fallback: usedFallbackFloor
|
|
13240
12922
|
});
|
|
13241
|
-
if (mergedMemories.length >= MAX_MEMORIES)
|
|
13242
|
-
break;
|
|
12923
|
+
if (mergedMemories.length >= MAX_MEMORIES) break;
|
|
13243
12924
|
}
|
|
13244
12925
|
}
|
|
13245
12926
|
const injectableMemories = filterHookInjectableMemories(
|
|
@@ -13252,8 +12933,7 @@ async function main() {
|
|
|
13252
12933
|
await memoryService.incrementMemoryAccess(eventIds);
|
|
13253
12934
|
}
|
|
13254
12935
|
for (const m of injectableMemories) {
|
|
13255
|
-
if (!m.id)
|
|
13256
|
-
continue;
|
|
12936
|
+
if (!m.id) continue;
|
|
13257
12937
|
try {
|
|
13258
12938
|
await memoryService.recordRetrieval(
|
|
13259
12939
|
m.id,
|