@linxiraos/pi-mnemopi 1.1.5 → 1.1.7
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/CHANGELOG.md +8 -0
- package/package.json +5 -5
- package/src/core/beam/helpers.ts +15 -6
- package/src/core/beam/recall.ts +21 -6
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,14 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [1.1.7] - 2026-09-01
|
|
6
|
+
|
|
7
|
+
- 同步上游 OMP v18.0.11(`b8ce33a58911c26bed1d84f0db9a5e2e727c49a2`)。
|
|
8
|
+
|
|
9
|
+
## [1.1.6] - 2026-08-30
|
|
10
|
+
|
|
11
|
+
- 同步上游 OMP v18.0.9(`cc14e04f075d`)。
|
|
12
|
+
|
|
5
13
|
## [1.1.5] - 2026-08-26
|
|
6
14
|
|
|
7
15
|
- 随 1.1.5 版本线对齐发布:OMP v18.0.6 同步未触及本包,无独立功能变更。
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"type": "module",
|
|
3
3
|
"name": "@linxiraos/pi-mnemopi",
|
|
4
|
-
"version": "1.1.
|
|
4
|
+
"version": "1.1.7",
|
|
5
5
|
"description": "Local SQLite memory engine for Oh My Pi agents",
|
|
6
6
|
"homepage": "https://linxira-os.github.io/zeta/",
|
|
7
7
|
"author": "Can Boluk",
|
|
@@ -39,10 +39,10 @@
|
|
|
39
39
|
"fmt": "biome format --write ."
|
|
40
40
|
},
|
|
41
41
|
"dependencies": {
|
|
42
|
-
"@linxiraos/pi-ai": "1.1.
|
|
43
|
-
"@linxiraos/pi-catalog": "1.1.
|
|
44
|
-
"@linxiraos/pi-natives": "1.1.
|
|
45
|
-
"@linxiraos/pi-utils": "1.1.
|
|
42
|
+
"@linxiraos/pi-ai": "1.1.7",
|
|
43
|
+
"@linxiraos/pi-catalog": "1.1.7",
|
|
44
|
+
"@linxiraos/pi-natives": "1.1.7",
|
|
45
|
+
"@linxiraos/pi-utils": "1.1.7"
|
|
46
46
|
},
|
|
47
47
|
"peerDependencies": {
|
|
48
48
|
"fastembed": "2.1.0",
|
package/src/core/beam/helpers.ts
CHANGED
|
@@ -270,8 +270,9 @@ export function cjkLikeSearch(
|
|
|
270
270
|
const conditions = cjkChars.map(() => "content LIKE ? ESCAPE '\\'").join(" OR ");
|
|
271
271
|
try {
|
|
272
272
|
const rows = db
|
|
273
|
-
.query(`SELECT ${idColumn}, content FROM ${table} WHERE
|
|
274
|
-
|
|
273
|
+
.query(`SELECT ${idColumn}, content FROM ${table} WHERE superseded_by IS NULL AND (valid_until IS NULL OR valid_until > ?)
|
|
274
|
+
AND (${conditions}) LIMIT ?`)
|
|
275
|
+
.all(new Date().toISOString(), ...cjkChars.map(ch => `%${ch}%`), k * 5) as Record<string, unknown>[];
|
|
275
276
|
const scored: Array<{ id: string | number; score: number }> = [];
|
|
276
277
|
for (const row of rows) {
|
|
277
278
|
const content = String(row.content ?? "");
|
|
@@ -296,8 +297,12 @@ export function ftsSearch(db: Database, query: string, k = 20): FtsRankResult[]
|
|
|
296
297
|
if (!ftsQuery) return hasCjk(query) ? (cjkLikeSearch(db, query, k, false) as FtsRankResult[]) : [];
|
|
297
298
|
try {
|
|
298
299
|
const rows = db
|
|
299
|
-
.query(
|
|
300
|
-
|
|
300
|
+
.query(`SELECT f.rowid, f.rank FROM fts_episodes f
|
|
301
|
+
WHERE f.fts_episodes MATCH ?
|
|
302
|
+
AND EXISTS (SELECT 1 FROM episodic_memory e WHERE e.rowid = f.rowid AND e.superseded_by IS NULL
|
|
303
|
+
AND (e.valid_until IS NULL OR e.valid_until > ?))
|
|
304
|
+
ORDER BY f.rank, f.rowid LIMIT ?`)
|
|
305
|
+
.all(ftsQuery, new Date().toISOString(), k) as Record<string, unknown>[];
|
|
301
306
|
if (rows.length === 0 && hasCjk(query)) return cjkLikeSearch(db, query, k, false) as FtsRankResult[];
|
|
302
307
|
return rows.map(row => ({ rowid: Number(row.rowid), rank: Number(row.rank) }));
|
|
303
308
|
} catch {
|
|
@@ -310,8 +315,12 @@ export function ftsSearchWorking(db: Database, query: string, k = 20): WorkingFt
|
|
|
310
315
|
if (!ftsQuery) return hasCjk(query) ? (cjkLikeSearch(db, query, k, true) as WorkingFtsRankResult[]) : [];
|
|
311
316
|
try {
|
|
312
317
|
const rows = db
|
|
313
|
-
.query(
|
|
314
|
-
|
|
318
|
+
.query(`SELECT f.id, f.rank FROM fts_working f
|
|
319
|
+
WHERE f.fts_working MATCH ?
|
|
320
|
+
AND EXISTS (SELECT 1 FROM working_memory w WHERE w.id = f.id AND w.superseded_by IS NULL
|
|
321
|
+
AND (w.valid_until IS NULL OR w.valid_until > ?))
|
|
322
|
+
ORDER BY f.rank, f.id LIMIT ?`)
|
|
323
|
+
.all(ftsQuery, new Date().toISOString(), k) as Record<string, unknown>[];
|
|
315
324
|
if (rows.length === 0 && hasCjk(query)) return cjkLikeSearch(db, query, k, true) as WorkingFtsRankResult[];
|
|
316
325
|
return rows.map(row => ({ id: String(row.id), rank: Number(row.rank) }));
|
|
317
326
|
} catch {
|
package/src/core/beam/recall.ts
CHANGED
|
@@ -545,16 +545,31 @@ function ftsRows(
|
|
|
545
545
|
): Row[] {
|
|
546
546
|
if (!tableExists(beam, table)) return [];
|
|
547
547
|
try {
|
|
548
|
+
// Superseded rows stay in the FTS mirrors (their content never changed) but must not
|
|
549
|
+
// occupy LIMIT slots — visibility filtering would drop them AFTER they displaced live rows.
|
|
548
550
|
if (table === "fts_working") {
|
|
549
|
-
return queryAll(
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
551
|
+
return queryAll(
|
|
552
|
+
beam,
|
|
553
|
+
// Correlated EXISTS, never `id IN (SELECT ...)`: the IN form makes SQLite build a
|
|
554
|
+
// LIST SUBQUERY over the whole live table on every lexical recall, before the small
|
|
555
|
+
// LIMIT applies. Measured on a 40k-row bank with a selective query: 9.19ms vs
|
|
556
|
+
// 0.042ms. EXISTS probes the primary key only for rows MATCH actually produced.
|
|
557
|
+
`SELECT f.id, f.rank FROM fts_working f
|
|
558
|
+
WHERE f.fts_working MATCH ?
|
|
559
|
+
AND EXISTS (SELECT 1 FROM working_memory w WHERE w.id = f.id AND w.superseded_by IS NULL
|
|
560
|
+
AND (w.valid_until IS NULL OR w.valid_until > ?))
|
|
561
|
+
ORDER BY f.rank, f.id LIMIT ?`,
|
|
562
|
+
[ftsQuery(query, useSynonyms), nowIso(), limit],
|
|
563
|
+
);
|
|
553
564
|
}
|
|
554
565
|
return queryAll(
|
|
555
566
|
beam,
|
|
556
|
-
|
|
557
|
-
|
|
567
|
+
`SELECT f.rowid, f.rank FROM fts_episodes f
|
|
568
|
+
WHERE f.fts_episodes MATCH ?
|
|
569
|
+
AND EXISTS (SELECT 1 FROM episodic_memory e WHERE e.rowid = f.rowid AND e.superseded_by IS NULL
|
|
570
|
+
AND (e.valid_until IS NULL OR e.valid_until > ?))
|
|
571
|
+
ORDER BY f.rank, f.rowid LIMIT ?`,
|
|
572
|
+
[ftsQuery(query, useSynonyms), nowIso(), limit],
|
|
558
573
|
);
|
|
559
574
|
} catch {
|
|
560
575
|
return [];
|