@oh-my-pi/pi-mnemopi 18.2.4 → 18.2.6
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 +6 -0
- package/package.json +5 -5
- package/src/core/beam/helpers.ts +21 -11
- package/src/core/beam/store.ts +15 -11
package/CHANGELOG.md
CHANGED
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"type": "module",
|
|
3
3
|
"name": "@oh-my-pi/pi-mnemopi",
|
|
4
|
-
"version": "18.2.
|
|
4
|
+
"version": "18.2.6",
|
|
5
5
|
"description": "Local SQLite memory engine for Oh My Pi agents",
|
|
6
6
|
"homepage": "https://omp.sh",
|
|
7
7
|
"author": "Stencil Labs, Inc.",
|
|
@@ -39,10 +39,10 @@
|
|
|
39
39
|
"fmt": "oxfmt --no-error-on-unmatched-pattern 'src/**/*.{ts,tsx}' '{test,bench,examples,scripts}/**/*.ts' '*.ts'"
|
|
40
40
|
},
|
|
41
41
|
"dependencies": {
|
|
42
|
-
"@oh-my-pi/pi-ai": "18.2.
|
|
43
|
-
"@oh-my-pi/pi-catalog": "18.2.
|
|
44
|
-
"@oh-my-pi/pi-natives": "18.2.
|
|
45
|
-
"@oh-my-pi/pi-utils": "18.2.
|
|
42
|
+
"@oh-my-pi/pi-ai": "18.2.6",
|
|
43
|
+
"@oh-my-pi/pi-catalog": "18.2.6",
|
|
44
|
+
"@oh-my-pi/pi-natives": "18.2.6",
|
|
45
|
+
"@oh-my-pi/pi-utils": "18.2.6"
|
|
46
46
|
},
|
|
47
47
|
"peerDependencies": {
|
|
48
48
|
"fastembed": "2.1.0",
|
package/src/core/beam/helpers.ts
CHANGED
|
@@ -352,19 +352,29 @@ export function vecAvailable(db: Database): boolean {
|
|
|
352
352
|
return tableExists(db, "vec_episodes");
|
|
353
353
|
}
|
|
354
354
|
|
|
355
|
+
// Per-Database memo for the vec table shape: schema is fixed at open, so
|
|
356
|
+
// probing sqlite_master on every insert/search is pure overhead. WeakMap
|
|
357
|
+
// keeps no Database alive.
|
|
358
|
+
const vecTypeMemo = new WeakMap<Database, "float32" | "int8" | "bit">();
|
|
359
|
+
|
|
355
360
|
export function effectiveVecType(db: Database): "float32" | "int8" | "bit" {
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
361
|
+
const cached = vecTypeMemo.get(db);
|
|
362
|
+
if (cached !== undefined) return cached;
|
|
363
|
+
let resolved: "float32" | "int8" | "bit" = "float32";
|
|
364
|
+
if (vecAvailable(db)) {
|
|
365
|
+
try {
|
|
366
|
+
const row = db.query("SELECT sql FROM sqlite_master WHERE type='table' AND name='vec_episodes'").get() as {
|
|
367
|
+
sql?: string;
|
|
368
|
+
} | null;
|
|
369
|
+
const sql = row?.sql ?? "";
|
|
370
|
+
if (sql.includes("int8")) resolved = "int8";
|
|
371
|
+
else if (sql.includes("bit")) resolved = "bit";
|
|
372
|
+
} catch {
|
|
373
|
+
resolved = "float32";
|
|
374
|
+
}
|
|
366
375
|
}
|
|
367
|
-
|
|
376
|
+
vecTypeMemo.set(db, resolved);
|
|
377
|
+
return resolved;
|
|
368
378
|
}
|
|
369
379
|
|
|
370
380
|
export function vecInsert(db: Database, rowid: number, embedding: readonly number[]): void {
|
package/src/core/beam/store.ts
CHANGED
|
@@ -908,13 +908,20 @@ export function importFromDict(beam: BeamMemoryState, data: Record<string, unkno
|
|
|
908
908
|
const importedAt = toUtcIso();
|
|
909
909
|
const oldToNewRowid = new Map<number, number>();
|
|
910
910
|
|
|
911
|
+
// Hoisted out of the per-row loops: `db.query` is Bun's cached-statement
|
|
912
|
+
// API (no per-row prepare/finalize churn), and the vec availability probe
|
|
913
|
+
// is loop-invariant (schema is fixed at open).
|
|
914
|
+
const workingExists = db.query("SELECT 1 FROM working_memory WHERE id = ?");
|
|
915
|
+
const episodicExists = db.query("SELECT 1 FROM episodic_memory WHERE id = ?");
|
|
916
|
+
const episodicRowid = db.query("SELECT rowid FROM episodic_memory WHERE id = ?");
|
|
917
|
+
const scratchExists = db.query("SELECT 1 FROM scratchpad WHERE id = ?");
|
|
918
|
+
const vecEpisodesAvailable = vecAvailable(db);
|
|
911
919
|
transaction(db, () => {
|
|
912
920
|
for (const raw of Array.isArray(data.working_memory) ? data.working_memory : []) {
|
|
913
921
|
const item = jsonObject(raw);
|
|
914
922
|
const id = String(item.id ?? "");
|
|
915
923
|
if (id.length === 0) continue;
|
|
916
|
-
|
|
917
|
-
const exists = existsStatement.get(id) !== null;
|
|
924
|
+
const exists = workingExists.get(id) !== null;
|
|
918
925
|
if (exists && !force) {
|
|
919
926
|
stats.working_memory.skipped++;
|
|
920
927
|
continue;
|
|
@@ -968,18 +975,16 @@ export function importFromDict(beam: BeamMemoryState, data: Record<string, unkno
|
|
|
968
975
|
const item = jsonObject(raw);
|
|
969
976
|
const id = String(item.id ?? "");
|
|
970
977
|
if (id.length === 0) continue;
|
|
971
|
-
|
|
972
|
-
const exists = existsStatement.get(id) !== null;
|
|
978
|
+
const exists = episodicExists.get(id) !== null;
|
|
973
979
|
if (exists && !force) {
|
|
974
980
|
stats.episodic_memory.skipped++;
|
|
975
981
|
continue;
|
|
976
982
|
}
|
|
977
|
-
using rowidStatement = db.prepare("SELECT rowid FROM episodic_memory WHERE id = ?");
|
|
978
983
|
if (exists) {
|
|
979
|
-
const existingRow =
|
|
984
|
+
const existingRow = episodicRowid.get(id) as {
|
|
980
985
|
rowid: number;
|
|
981
986
|
} | null;
|
|
982
|
-
if (existingRow !== null &&
|
|
987
|
+
if (existingRow !== null && vecEpisodesAvailable) {
|
|
983
988
|
try {
|
|
984
989
|
db.run("DELETE FROM vec_episodes WHERE rowid = ?", [existingRow.rowid]);
|
|
985
990
|
} catch {
|
|
@@ -1027,7 +1032,7 @@ export function importFromDict(beam: BeamMemoryState, data: Record<string, unkno
|
|
|
1027
1032
|
],
|
|
1028
1033
|
);
|
|
1029
1034
|
const oldRowid = Number(item.rowid);
|
|
1030
|
-
const newRow =
|
|
1035
|
+
const newRow = episodicRowid.get(id) as {
|
|
1031
1036
|
rowid: number;
|
|
1032
1037
|
} | null;
|
|
1033
1038
|
if (Number.isFinite(oldRowid) && newRow !== null) oldToNewRowid.set(oldRowid, newRow.rowid);
|
|
@@ -1041,7 +1046,7 @@ export function importFromDict(beam: BeamMemoryState, data: Record<string, unkno
|
|
|
1041
1046
|
if (mappedRowid === undefined || embedding === null || embedding.some(v => !Number.isFinite(v))) {
|
|
1042
1047
|
continue;
|
|
1043
1048
|
}
|
|
1044
|
-
if (!
|
|
1049
|
+
if (!vecEpisodesAvailable) continue;
|
|
1045
1050
|
try {
|
|
1046
1051
|
vecInsert(db, mappedRowid, embedding);
|
|
1047
1052
|
stats.episodic_memory.embeddings_inserted++;
|
|
@@ -1054,8 +1059,7 @@ export function importFromDict(beam: BeamMemoryState, data: Record<string, unkno
|
|
|
1054
1059
|
const item = jsonObject(raw);
|
|
1055
1060
|
const id = String(item.id ?? "");
|
|
1056
1061
|
if (id.length === 0) continue;
|
|
1057
|
-
|
|
1058
|
-
const exists = existsStatement.get(id) !== null;
|
|
1062
|
+
const exists = scratchExists.get(id) !== null;
|
|
1059
1063
|
if (exists) {
|
|
1060
1064
|
db.run("UPDATE scratchpad SET content = ?, session_id = ?, created_at = ?, updated_at = ? WHERE id = ?", [
|
|
1061
1065
|
sqlBinding(item.content, ""),
|