pi-hermes-memory 0.7.20 → 0.7.22

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-hermes-memory",
3
- "version": "0.7.20",
3
+ "version": "0.7.22",
4
4
  "description": "🧠 Persistent memory + 🔍 session search + 🛡️ secret scanning for Pi. Token-aware policy-only memory by default, SQLite FTS5 search, auto-consolidation, procedural skills. 368 tests. Ported from Hermes agent.",
5
5
  "type": "module",
6
6
  "main": "src/index.ts",
@@ -48,15 +48,15 @@
48
48
  "@earendil-works/pi-coding-agent": ">=0.74.0"
49
49
  },
50
50
  "devDependencies": {
51
- "@earendil-works/pi-ai": "^0.74.0",
52
- "@earendil-works/pi-coding-agent": "^0.74.0",
51
+ "@earendil-works/pi-ai": "^0.80.2",
52
+ "@earendil-works/pi-coding-agent": "^0.80.2",
53
53
  "@types/better-sqlite3": "^7.6.13",
54
54
  "tsx": "^4.21.0",
55
55
  "typebox": "^1.1.33",
56
56
  "typescript": "^6.0.3"
57
57
  },
58
58
  "dependencies": {
59
- "@earendil-works/pi-tui": "^0.74.0",
59
+ "@earendil-works/pi-tui": "^0.80.2",
60
60
  "better-sqlite3": "^12.9.0"
61
61
  }
62
62
  }
@@ -9,7 +9,7 @@ import { DatabaseManager } from '../store/db.js';
9
9
  import { indexAllSessions, getSessionStats } from '../store/session-indexer.js';
10
10
  import { AGENT_ROOT } from '../paths.js';
11
11
 
12
- const SESSIONS_DIR = path.join(AGENT_ROOT, 'sessions');
12
+ const SESSIONS_DIR = process.env.PI_CODING_AGENT_SESSION_DIR || path.join(AGENT_ROOT, 'sessions');
13
13
 
14
14
  export function registerIndexSessionsCommand(pi: ExtensionAPI): void {
15
15
  pi.registerCommand("memory-index-sessions", {
package/src/store/db.ts CHANGED
@@ -245,19 +245,19 @@ export class DatabaseManager {
245
245
  try {
246
246
  db.exec(SCHEMA_SQL);
247
247
  } catch (err) {
248
- if (!this.isLegacyMemoriesCategoryError(err)) {
248
+ if (!this.isLegacySchemaError(err)) {
249
249
  throw err;
250
250
  }
251
251
 
252
- // Legacy DB from pre-v0.6 can have memories table without the category
253
- // and failure metadata columns. Add missing columns, then retry schema.
254
- this.ensureMemoriesColumns(db);
252
+ // Legacy DBs can be missing v0.6 failure-memory columns and/or the project
253
+ // column on sessions/memories. Add missing columns, then retry schema.
254
+ this.ensureLegacySchemaColumns(db);
255
255
  db.exec(SCHEMA_SQL);
256
256
  }
257
257
 
258
- // Extra safety: always ensure legacy memories columns exist, then migrate
259
- // legacy CHECK(target IN ('memory','user')) constraints to include 'failure'.
260
- this.ensureMemoriesColumns(db);
258
+ // Extra safety: always ensure legacy columns exist, then migrate legacy
259
+ // CHECK(target IN ('memory','user')) constraints to include 'failure'.
260
+ this.ensureLegacySchemaColumns(db);
261
261
  this.migrateLegacyMemoriesTargetConstraint(db);
262
262
  this.rebuildMemoryFts(db);
263
263
  }
@@ -590,19 +590,30 @@ export class DatabaseManager {
590
590
  try { db.close(); } catch { /* best effort */ }
591
591
  }
592
592
 
593
- private isLegacyMemoriesCategoryError(err: unknown): boolean {
593
+ private isLegacySchemaError(err: unknown): boolean {
594
594
  if (!(err instanceof Error)) return false;
595
595
  const msg = err.message.toLowerCase();
596
- return msg.includes('no such column: category') || msg.includes('memories(category)');
596
+ return msg.includes('no such column: category')
597
+ || msg.includes('memories(category)')
598
+ || msg.includes('no such column: project')
599
+ || msg.includes('sessions(project)')
600
+ || msg.includes('memories(project)');
601
+ }
602
+
603
+ private ensureLegacySchemaColumns(db: DatabaseLike): void {
604
+ this.ensureMemoriesColumns(db);
605
+ this.ensureSessionsColumns(db);
597
606
  }
598
607
 
599
608
  private ensureMemoriesColumns(db: DatabaseLike): void {
600
609
  const tableExists = db.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name='memories'").get() as { name: string } | undefined;
601
610
  if (!tableExists) return;
602
611
 
603
- const columns = db.prepare('PRAGMA table_info(memories)').all() as { name: string }[];
604
- const names = new Set(columns.map((c) => c.name));
612
+ const names = this.getColumnNames(db, 'memories');
605
613
 
614
+ if (!names.has('project')) {
615
+ db.exec('ALTER TABLE memories ADD COLUMN project TEXT');
616
+ }
606
617
  if (!names.has('category')) {
607
618
  db.exec('ALTER TABLE memories ADD COLUMN category TEXT');
608
619
  }
@@ -617,6 +628,40 @@ export class DatabaseManager {
617
628
  }
618
629
  }
619
630
 
631
+ private ensureSessionsColumns(db: DatabaseLike): void {
632
+ const tableExists = db.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name='sessions'").get() as { name: string } | undefined;
633
+ if (!tableExists) return;
634
+
635
+ const names = this.getColumnNames(db, 'sessions');
636
+ if (!names.has('project')) {
637
+ db.exec('ALTER TABLE sessions ADD COLUMN project TEXT');
638
+ }
639
+
640
+ this.backfillSessionsProject(db);
641
+ }
642
+
643
+ private backfillSessionsProject(db: DatabaseLike): void {
644
+ const names = this.getColumnNames(db, 'sessions');
645
+ if (!names.has('project') || !names.has('cwd') || !names.has('id')) return;
646
+
647
+ const rows = db.prepare('SELECT id, cwd, project FROM sessions').all() as Array<{
648
+ id?: unknown;
649
+ cwd?: unknown;
650
+ project?: unknown;
651
+ }>;
652
+ const update = db.prepare('UPDATE sessions SET project = ? WHERE id = ?');
653
+
654
+ for (const row of rows) {
655
+ if (typeof row.id !== 'string') continue;
656
+ if (typeof row.project === 'string' && row.project.trim()) continue;
657
+
658
+ const project = typeof row.cwd === 'string' && row.cwd.trim()
659
+ ? (path.basename(row.cwd) || 'unknown')
660
+ : 'unknown';
661
+ update.run(project, row.id);
662
+ }
663
+ }
664
+
620
665
  private migrateLegacyMemoriesTargetConstraint(db: DatabaseLike): void {
621
666
  const tableSqlRow = db.prepare("SELECT sql FROM sqlite_master WHERE type='table' AND name='memories'").get() as { sql?: string } | undefined;
622
667
  const tableSql = tableSqlRow?.sql ?? '';