From 2b6358860476ed67e420353aef376ffb0f8530a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9B=B7=E7=94=B5=E8=8A=BD=E8=A1=A3?= Date: Fri, 17 Apr 2026 01:28:20 -0400 Subject: [PATCH] feat(db): wire sessionEntries + credentialsTable and add migration 32 - Expose buildSessionEntryMethods and buildCredentialMethods on AppDatabaseBase as public readonly members so agent-runtime and credential-store can access them via db.sessionEntries / db.credentialsTable - Add idempotent schema migration v32 creating session_entries and credentials tables plus supporting indexes; uses CREATE TABLE IF NOT EXISTS so existing profile DBs upgrade safely without destructive ops --- src/main/database-base.ts | 6 ++++++ src/main/database/schema.ts | 42 +++++++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+) diff --git a/src/main/database-base.ts b/src/main/database-base.ts index 5cfcab4c..5ec788d7 100644 --- a/src/main/database-base.ts +++ b/src/main/database-base.ts @@ -22,6 +22,8 @@ import { buildAutomationMethods } from "./database/automation"; import { buildKnowledgeMethods } from "./database/knowledge"; import { buildWakeupMethods } from "./database/wakeup"; import { buildBackupMethods } from "./database/backup"; +import { buildSessionEntryMethods } from "./database/session-entries"; +import { buildCredentialMethods } from "./database/credentials"; import { initializeDatabase } from "./database/schema"; import { SecretVault } from "./vault"; import type { AgentStatus, ConnectorId, ProfileSnapshot, RunStatus } from "@shared/types"; @@ -64,6 +66,8 @@ export class AppDatabaseBase { public readonly knowledgeMod: ReturnType; public readonly wakeup: ReturnType; public readonly backupMod: ReturnType; + public readonly sessionEntries: ReturnType; + public readonly credentialsTable: ReturnType; constructor(rootDir: string) { this.profileDir = rootDir; @@ -134,6 +138,8 @@ export class AppDatabaseBase { }); this.knowledgeMod = buildKnowledgeMethods(getDb, ra); this.wakeup = buildWakeupMethods(getDb, ra, tx); + this.sessionEntries = buildSessionEntryMethods(getDb, ra, tx); + this.credentialsTable = buildCredentialMethods(getDb, ra, tx); this.backupMod = buildBackupMethods({ getDb, setDb: (db) => { this.db = db; }, openConnection: () => this.openConnection(), diff --git a/src/main/database/schema.ts b/src/main/database/schema.ts index 316a14db..013e4f72 100644 --- a/src/main/database/schema.ts +++ b/src/main/database/schema.ts @@ -433,6 +433,48 @@ export function runMigrations( sql: `CREATE INDEX IF NOT EXISTS idx_approvals_company_state_type ON approvals(company_id, state, type); CREATE INDEX IF NOT EXISTS idx_approvals_related_task ON approvals(related_task_id)`, }, + { + // Typed seniority enum replaces English keyword substring matching for + // leadership detection. Free-text `role` stays UI-editable; `role_level` + // is inferred once on insert/update via inferRoleLevel(). + version: 31, name: "add_agents_role_level", + fn: () => { + if (!columnExists(db, "agents", "role_level")) { + db.prepare("ALTER TABLE agents ADD COLUMN role_level TEXT NOT NULL DEFAULT 'ic'").run(); + } + }, + }, + { + // pi-mono session transcripts + credential vault. Idempotent; safe to + // re-apply on fresh DBs or DBs that already have the tables. + version: 32, name: "create_pi_mono_session_and_credentials_tables", + sql: `CREATE TABLE IF NOT EXISTS session_entries ( + id TEXT PRIMARY KEY, + task_session_id TEXT NOT NULL, + sequence INTEGER NOT NULL, + kind TEXT NOT NULL, + role TEXT, + payload_json TEXT NOT NULL, + is_superseded INTEGER NOT NULL DEFAULT 0, + created_at TEXT NOT NULL + ); + CREATE INDEX IF NOT EXISTS idx_session_entries_session ON session_entries(task_session_id, sequence); + CREATE INDEX IF NOT EXISTS idx_session_entries_active ON session_entries(task_session_id, is_superseded, sequence); + CREATE TABLE IF NOT EXISTS credentials ( + connector_id TEXT PRIMARY KEY, + kind TEXT NOT NULL, + backend TEXT NOT NULL, + ciphertext BLOB NOT NULL, + display_hint TEXT NOT NULL DEFAULT '', + status TEXT NOT NULL DEFAULT 'active', + expires_at TEXT, + last_refreshed_at TEXT, + last_error TEXT, + created_at TEXT NOT NULL, + updated_at TEXT NOT NULL + ); + CREATE INDEX IF NOT EXISTS idx_credentials_status ON credentials(status)`, + }, ]; for (const migration of migrations) {