@linxiraos/pi-mnemopi 1.1.6 → 1.1.8

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 CHANGED
@@ -2,6 +2,14 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [1.1.8] - 2026-09-04
6
+
7
+ - OMP sync v18.1.2–v18.1.5: memory-backend plumbing aligned with the upstream mnemopi updates.
8
+
9
+ ## [1.1.7] - 2026-09-01
10
+
11
+ - 同步上游 OMP v18.0.11(`b8ce33a58911c26bed1d84f0db9a5e2e727c49a2`)。
12
+
5
13
  ## [1.1.6] - 2026-08-30
6
14
 
7
15
  - 同步上游 OMP v18.0.9(`cc14e04f075d`)。
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "type": "module",
3
3
  "name": "@linxiraos/pi-mnemopi",
4
- "version": "1.1.6",
4
+ "version": "1.1.8",
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.6",
43
- "@linxiraos/pi-catalog": "1.1.6",
44
- "@linxiraos/pi-natives": "1.1.6",
45
- "@linxiraos/pi-utils": "1.1.6"
42
+ "@linxiraos/pi-ai": "1.1.8",
43
+ "@linxiraos/pi-catalog": "1.1.8",
44
+ "@linxiraos/pi-natives": "1.1.8",
45
+ "@linxiraos/pi-utils": "1.1.8"
46
46
  },
47
47
  "peerDependencies": {
48
48
  "fastembed": "2.1.0",
@@ -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 superseded_by IS NULL AND (${conditions}) LIMIT ?`)
274
- .all(...cjkChars.map(ch => `%${ch}%`), k * 5) as Record<string, unknown>[];
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 ?? "");
@@ -298,9 +299,10 @@ export function ftsSearch(db: Database, query: string, k = 20): FtsRankResult[]
298
299
  const rows = db
299
300
  .query(`SELECT f.rowid, f.rank FROM fts_episodes f
300
301
  WHERE f.fts_episodes MATCH ?
301
- AND EXISTS (SELECT 1 FROM episodic_memory e WHERE e.rowid = f.rowid AND e.superseded_by IS NULL)
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 > ?))
302
304
  ORDER BY f.rank, f.rowid LIMIT ?`)
303
- .all(ftsQuery, k) as Record<string, unknown>[];
305
+ .all(ftsQuery, new Date().toISOString(), k) as Record<string, unknown>[];
304
306
  if (rows.length === 0 && hasCjk(query)) return cjkLikeSearch(db, query, k, false) as FtsRankResult[];
305
307
  return rows.map(row => ({ rowid: Number(row.rowid), rank: Number(row.rank) }));
306
308
  } catch {
@@ -315,9 +317,10 @@ export function ftsSearchWorking(db: Database, query: string, k = 20): WorkingFt
315
317
  const rows = db
316
318
  .query(`SELECT f.id, f.rank FROM fts_working f
317
319
  WHERE f.fts_working MATCH ?
318
- AND EXISTS (SELECT 1 FROM working_memory w WHERE w.id = f.id AND w.superseded_by IS NULL)
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 > ?))
319
322
  ORDER BY f.rank, f.id LIMIT ?`)
320
- .all(ftsQuery, k) as Record<string, unknown>[];
323
+ .all(ftsQuery, new Date().toISOString(), k) as Record<string, unknown>[];
321
324
  if (rows.length === 0 && hasCjk(query)) return cjkLikeSearch(db, query, k, true) as WorkingFtsRankResult[];
322
325
  return rows.map(row => ({ id: String(row.id), rank: Number(row.rank) }));
323
326
  } catch {
@@ -201,7 +201,7 @@ export class BeamMemory implements BeamMemoryState {
201
201
 
202
202
  async flushExtractions(): Promise<void> {
203
203
  while (this.pendingExtractions.size > 0) {
204
- await Promise.allSettled([...this.pendingExtractions]);
204
+ await Promise.allSettled(this.pendingExtractions);
205
205
  }
206
206
  }
207
207
 
@@ -442,6 +442,7 @@ function ftsQuery(query: string, useSynonyms = true): string {
442
442
  }
443
443
 
444
444
  function placeholders(count: number): string {
445
+ // [suppressed] length preallocation
445
446
  return new Array<string>(count).fill("?").join(",");
446
447
  }
447
448
 
@@ -556,18 +557,20 @@ function ftsRows(
556
557
  // 0.042ms. EXISTS probes the primary key only for rows MATCH actually produced.
557
558
  `SELECT f.id, f.rank FROM fts_working f
558
559
  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 EXISTS (SELECT 1 FROM working_memory w WHERE w.id = f.id AND w.superseded_by IS NULL
561
+ AND (w.valid_until IS NULL OR w.valid_until > ?))
560
562
  ORDER BY f.rank, f.id LIMIT ?`,
561
- [ftsQuery(query, useSynonyms), limit],
563
+ [ftsQuery(query, useSynonyms), nowIso(), limit],
562
564
  );
563
565
  }
564
566
  return queryAll(
565
567
  beam,
566
568
  `SELECT f.rowid, f.rank FROM fts_episodes f
567
569
  WHERE f.fts_episodes MATCH ?
568
- AND EXISTS (SELECT 1 FROM episodic_memory e WHERE e.rowid = f.rowid AND e.superseded_by IS NULL)
570
+ AND EXISTS (SELECT 1 FROM episodic_memory e WHERE e.rowid = f.rowid AND e.superseded_by IS NULL
571
+ AND (e.valid_until IS NULL OR e.valid_until > ?))
569
572
  ORDER BY f.rank, f.rowid LIMIT ?`,
570
- [ftsQuery(query, useSynonyms), limit],
573
+ [ftsQuery(query, useSynonyms), nowIso(), limit],
571
574
  );
572
575
  } catch {
573
576
  return [];
@@ -598,6 +601,7 @@ function parseEmbedding(raw: unknown): number[] | null {
598
601
  try {
599
602
  const parsed = JSON.parse(raw) as unknown;
600
603
  if (!Array.isArray(parsed)) return null;
604
+ // [suppressed] length preallocation
601
605
  const vector = new Array<number>(parsed.length);
602
606
  for (let i = 0; i < parsed.length; i += 1) {
603
607
  const value = Number(parsed[i]);
@@ -144,7 +144,9 @@ export function levenshteinDistance(s1: string, s2: string): number {
144
144
  }
145
145
  if (right.length === 0) return left.length;
146
146
 
147
+ // [suppressed] length preallocation
147
148
  let previousRow = new Array<number>(right.length + 1);
149
+ // [suppressed] length preallocation
148
150
  let currentRow = new Array<number>(right.length + 1).fill(0);
149
151
  for (let i = 0; i <= right.length; i++) previousRow[i] = i;
150
152
 
@@ -203,7 +203,7 @@ export class DetectedPattern {
203
203
  this.description = init.description;
204
204
  this.confidence = init.confidence;
205
205
  this.samples = [...(init.samples ?? [])];
206
- this.metadata = { ...(init.metadata ?? {}) };
206
+ this.metadata = { ...init.metadata };
207
207
  }
208
208
 
209
209
  toDict(): Record<string, unknown> {
package/src/mcp-tools.ts CHANGED
@@ -759,7 +759,7 @@ async function handleSharedRemember(args: ToolArguments): Promise<ToolResult> {
759
759
  const memoryId = beam.remember(labelled, {
760
760
  source: "surface_manual",
761
761
  importance: Math.max(0, Math.min(1, numberArg(args, "importance", 0.8))),
762
- metadata: { ...(metadataArg(args) ?? {}), shared_memory: true, surface_kind: kind },
762
+ metadata: { ...metadataArg(args), shared_memory: true, surface_kind: kind },
763
763
  veracity: stringArg(args, "veracity", "unknown"),
764
764
  scope: "global",
765
765
  });