@c3-oss/prosa-core 0.8.0 → 0.8.1
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/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/core/bundle.ts","../src/core/db.ts","../src/core/schema/sql/001_init.ts","../src/core/schema/sql/002_search_index_status.ts","../src/core/schema/sql/003_analytics_views.ts","../src/core/schema/sql/004_tantivy_checkpoint.ts","../src/core/schema/sql/005_object_transport_hash.ts","../src/core/schema/migrate.ts","../package.json","../src/core/version.ts","../src/core/domain/types.ts","../src/core/cas/index.ts","../src/core/cas/compress.ts","../src/core/cas/hash.ts","../src/core/domain/ids.ts","../src/core/ingest/batch.ts","../src/core/ingest/idempotency.ts","../src/core/limits.ts","../src/services/sessions.ts","../src/services/search.ts","../src/core/errors.ts","../src/services/indexing.ts","../src/services/compile.ts","../src/importers/claude/index.ts","../src/core/domain/status.ts","../src/importers/claude/discover.ts","../src/importers/codex/index.ts","../src/importers/codex/discover.ts","../src/importers/cursor/index.ts","../src/importers/cursor/discover.ts","../src/importers/gemini/index.ts","../src/importers/gemini/discover.ts","../src/importers/hermes/index.ts","../src/importers/hermes/discover.ts","../src/services/export/parquet.ts","../src/services/analytics.ts","../src/services/doctor.ts","../src/services/tool_calls.ts","../src/services/transcript.ts","../src/services/export/markdown.ts","../src/services/transcript-format-text.ts","../src/mcp/guidance.ts","../src/mcp/server.ts","../src/mcp/tools.ts"],"sourcesContent":["import { constants as fsConstants } from 'node:fs'\nimport { access, mkdir, readFile, stat, writeFile } from 'node:fs/promises'\nimport os from 'node:os'\nimport path from 'node:path'\nimport { type Db, closeDb, openDb } from './db.js'\nimport { currentSchemaVersion, runMigrations } from './schema/migrate.js'\nimport { PROSA_PARSER_VERSION, PROSA_SCHEMA_VERSION } from './version.js'\n\n/**\n * Durable metadata written to `manifest.json` at the root of a bundle.\n *\n * The manifest records the store format and the parser/schema versions that\n * last opened the bundle. SQLite remains the authoritative schema source after\n * migrations; `openBundle` refreshes the version stamps when they drift.\n */\nexport interface BundleManifest {\n /** Manifest file format version. */\n version: 1\n /** Parser version that last initialized or opened the bundle. */\n parser_version: string\n /** SQLite schema version expected by the last opener. */\n schema_version: number\n /** ISO timestamp for bundle creation. */\n created_at: string\n /** Hash algorithm used for content-addressed object IDs. */\n hash_alg: 'blake3'\n /** Default compression used for stored CAS payloads. */\n default_compression: 'zstd'\n}\n\n/**\n * Open bundle handle shared by core services.\n *\n * `path` is the resolved bundle root. `paths` contains all managed locations\n * under that root, including SQLite, CAS/object storage, raw source copies,\n * search indexes, and generated exports.\n */\nexport interface Bundle {\n /** Absolute bundle root path. */\n path: string\n /** Open better-sqlite3 database handle for `prosa.sqlite`. */\n db: Db\n /** Parsed bundle manifest metadata. */\n manifest: BundleManifest\n /** Canonical absolute paths for bundle-managed files and directories. */\n paths: {\n /** SQLite database file. */\n db: string\n /** Manifest JSON file. */\n manifest: string\n /** Main CAS fanout directory. */\n objects: string\n /** Raw preserved source-file directory. */\n rawSources: string\n /** Search-related sidecar root. */\n search: string\n /** Tantivy index directory. */\n tantivy: string\n /** Generated export root. */\n exports: string\n /** Default Parquet export directory. */\n parquet: string\n /** Reserved lock-file path for future single-writer coordination. */\n lock: string\n }\n}\n\n/** Store path exists or was requested, but no initialized bundle is available. */\nexport class BundleNotInitializedError extends Error {\n constructor(\n readonly bundlePath: string,\n readonly reason: 'missing-directory' | 'missing-manifest',\n ) {\n super(reason === 'missing-directory' ? `bundle path not found: ${bundlePath}` : `no manifest.json in ${bundlePath}`)\n this.name = 'BundleNotInitializedError'\n }\n}\n\n/**\n * Resolve the default bundle root.\n *\n * `PROSA_STORE` wins when set; otherwise the local-first store lives in\n * `~/.prosa`. The return value is absolute in both cases.\n */\nexport function defaultBundlePath(): string {\n const env = process.env.PROSA_STORE\n if (env && env.length > 0) return path.resolve(env)\n return path.join(os.homedir(), '.prosa')\n}\n\n/**\n * Derive every managed filesystem path for a bundle without touching disk.\n */\nfunction bundlePaths(rootPath: string): Bundle['paths'] {\n return {\n db: path.join(rootPath, 'prosa.sqlite'),\n manifest: path.join(rootPath, 'manifest.json'),\n objects: path.join(rootPath, 'objects'),\n rawSources: path.join(rootPath, 'raw', 'sources'),\n search: path.join(rootPath, 'search'),\n tantivy: path.join(rootPath, 'search', 'tantivy'),\n exports: path.join(rootPath, 'exports'),\n parquet: path.join(rootPath, 'parquet'),\n lock: path.join(rootPath, 'prosa.lock'),\n }\n}\n\nasync function exists(p: string): Promise<boolean> {\n try {\n await access(p, fsConstants.F_OK)\n return true\n } catch {\n return false\n }\n}\n\n/**\n * Create a fresh bundle at `rootPath`. Fails if the directory already contains\n * a manifest (use openBundle for that case).\n *\n * Side effects: creates the bundle directory tree, writes `manifest.json`,\n * opens `prosa.sqlite`, and applies all schema migrations. The caller owns the\n * returned database handle and must close it via `closeBundle`.\n */\nexport async function initBundle(rootPath: string): Promise<Bundle> {\n const resolved = path.resolve(rootPath)\n const paths = bundlePaths(resolved)\n\n await mkdir(resolved, { recursive: true })\n\n if (await exists(paths.manifest)) {\n throw new Error(`bundle already exists at ${resolved} (found manifest.json) — use openBundle instead`)\n }\n\n await mkdir(paths.objects, { recursive: true })\n await mkdir(paths.rawSources, { recursive: true })\n await mkdir(paths.search, { recursive: true })\n await mkdir(paths.tantivy, { recursive: true })\n await mkdir(paths.exports, { recursive: true })\n await mkdir(paths.parquet, { recursive: true })\n\n const manifest: BundleManifest = {\n version: 1,\n parser_version: PROSA_PARSER_VERSION,\n schema_version: PROSA_SCHEMA_VERSION,\n created_at: new Date().toISOString(),\n hash_alg: 'blake3',\n default_compression: 'zstd',\n }\n\n await writeFile(paths.manifest, `${JSON.stringify(manifest, null, 2)}\\n`, 'utf8')\n\n const db = openDb(paths.db)\n runMigrations(db)\n\n return { path: resolved, db, manifest, paths }\n}\n\n/**\n * Open an existing bundle. Applies pending migrations if the schema is older\n * than the current code expects.\n *\n * Fails when the root is missing, lacks a manifest, or the migrated database\n * version still does not match the code-time schema version. On success it may\n * rewrite only manifest version metadata.\n */\nexport async function openBundle(rootPath: string): Promise<Bundle> {\n const resolved = path.resolve(rootPath)\n const paths = bundlePaths(resolved)\n\n const dirStat = await stat(resolved).catch(() => null)\n if (!dirStat) {\n throw new BundleNotInitializedError(resolved, 'missing-directory')\n }\n if (!dirStat.isDirectory()) {\n throw new Error(`bundle path not found or not a directory: ${resolved}`)\n }\n if (!(await exists(paths.manifest))) {\n throw new BundleNotInitializedError(resolved, 'missing-manifest')\n }\n\n const manifest = JSON.parse(await readFile(paths.manifest, 'utf8')) as BundleManifest\n await mkdir(paths.search, { recursive: true })\n await mkdir(paths.tantivy, { recursive: true })\n const db = openDb(paths.db)\n runMigrations(db)\n\n const currentVersion = currentSchemaVersion(db)\n if (currentVersion !== PROSA_SCHEMA_VERSION) {\n closeDb(db)\n throw new Error(`schema version mismatch (db=${currentVersion}, code=${PROSA_SCHEMA_VERSION})`)\n }\n\n // Refresh manifest's parser_version and schema_version stamps on every open.\n // schema_version drifts after migrations apply to an older bundle; rewriting\n // the manifest keeps it in sync with the actual db state and avoids a stale\n // metadata warning from `prosa doctor`.\n let manifestDirty = false\n if (manifest.parser_version !== PROSA_PARSER_VERSION) {\n manifest.parser_version = PROSA_PARSER_VERSION\n manifestDirty = true\n }\n if (manifest.schema_version !== currentVersion) {\n manifest.schema_version = currentVersion\n manifestDirty = true\n }\n if (manifestDirty) {\n await writeFile(paths.manifest, `${JSON.stringify(manifest, null, 2)}\\n`, 'utf8')\n }\n\n return { path: resolved, db, manifest, paths }\n}\n\n/**\n * Open an existing bundle or transparently initialize one if the store path is\n * missing or has not been initialized yet.\n *\n * Fails when `rootPath` exists but is not a directory. This is the CLI-friendly\n * entrypoint for commands that should create the store on first use.\n */\nexport async function openOrInitBundle(rootPath: string): Promise<Bundle> {\n const resolved = path.resolve(rootPath)\n const paths = bundlePaths(resolved)\n\n const dirStat = await stat(resolved).catch(() => null)\n if (dirStat && !dirStat.isDirectory()) {\n throw new Error(`bundle path not found or not a directory: ${resolved}`)\n }\n\n if (!dirStat || !(await exists(paths.manifest))) {\n return await initBundle(resolved)\n }\n\n return await openBundle(resolved)\n}\n\n/**\n * Close the SQLite handle associated with a bundle.\n */\nexport function closeBundle(bundle: Bundle): void {\n closeDb(bundle.db)\n}\n","import Database, { type Database as DatabaseType, type Statement } from 'better-sqlite3'\n\n/**\n * Synchronous better-sqlite3 database handle used throughout core.\n */\nexport type Db = DatabaseType\n\n/**\n * Open a SQLite database with Prosa's write-heavy import pragmas applied.\n *\n * The function does not run migrations. It configures WAL mode, foreign key\n * enforcement, larger cache/mmap windows, and import-friendly checkpointing\n * before callers create or access schema objects.\n */\nexport function openDb(path: string): Db {\n const db = new Database(path)\n // page_size must be set before any table is created. On an existing DB it\n // is a no-op (changing requires VACUUM). 16 KiB pages cut B-tree depth and\n // pack more rows per page — measurable wins on insert-heavy workloads.\n db.pragma('page_size = 16384')\n db.pragma('journal_mode = WAL')\n db.pragma('foreign_keys = ON')\n db.pragma('synchronous = NORMAL')\n // Reduce contention on long imports.\n db.pragma('busy_timeout = 5000')\n // 256 MiB page cache (default is 2 MiB) — keeps the working set of long\n // imports in memory and avoids re-reading hot index pages from disk.\n db.pragma('cache_size = -262144')\n // 256 MiB mmap window for read-side; cheap on macOS/Linux and lets SQLite\n // skip pread() syscalls when pages are already paged in.\n db.pragma('mmap_size = 268435456')\n // Keep temp btrees (used by FTS5 merges, large IN lists) in RAM.\n db.pragma('temp_store = MEMORY')\n // Default 1000 pages (~4 MiB) causes a WAL checkpoint every few hundred\n // INSERTs during compile; bump to ~80 MiB so checkpoints don't interrupt\n // the steady-state write loop.\n db.pragma('wal_autocheckpoint = 20000')\n return db\n}\n\n/**\n * Close an open SQLite handle.\n */\nexport function closeDb(db: Db): void {\n db.close()\n}\n\n/**\n * Prepared-statement cache keyed by database object and SQL text.\n *\n * WeakMap ownership lets statements become collectible when the corresponding\n * DB handle is no longer referenced.\n */\nconst stmtCache = new WeakMap<Db, Map<string, Statement>>()\n\n/**\n * Cache prepared statements per database. Importers call the same INSERTs\n * thousands of times — preparing once cuts a lot of overhead and the cache\n * vanishes when the Db is garbage-collected.\n *\n * `TParams` defaults to `unknown[]` so callers don't have to type their\n * arguments. When precise typing matters, pass a tuple type as the first\n * generic argument and `Statement<TParams, TRow>` is returned directly.\n */\nexport function prepare<TParams extends unknown[] = unknown[], TRow = unknown>(\n db: Db,\n sql: string,\n): Statement<TParams, TRow> {\n let cache = stmtCache.get(db)\n if (!cache) {\n cache = new Map()\n stmtCache.set(db, cache)\n }\n let stmt = cache.get(sql)\n if (!stmt) {\n stmt = db.prepare(sql)\n cache.set(sql, stmt)\n }\n return stmt as Statement<TParams, TRow>\n}\n\n/**\n * Execute `fn` inside a single synchronous SQLite transaction.\n *\n * Any exception thrown by `fn` rolls back the transaction and is rethrown by\n * better-sqlite3. Async work must happen before or after this helper.\n */\nexport function transactional<T>(db: Db, fn: () => T): T {\n const wrapped = db.transaction(fn)\n return wrapped()\n}\n","// Auto-generated from schema description. Edit the SQL here directly.\n// Loaded at runtime by core/schema/migrate.ts.\n\n/**\n * Initial bundle schema.\n *\n * Defines the raw immutable layer, canonical projection tables, and derived\n * search index tables/triggers. Projection rows are rebuildable from preserved\n * raw records and CAS objects.\n */\nexport const SQL_001_INIT = String.raw`\n-- Schema W v1\n--\n-- Three layers:\n-- 1. raw immutable : raw_records pointing at preserved bytes (objects)\n-- 2. canonical projection: sessions, turns, events, messages, blocks,\n-- tool_calls, tool_results, artifacts, edges\n-- 3. derived indexes : search_docs + FTS5\n--\n-- Projections are regenerable from raw_records. Raw is the source of truth.\n\nCREATE TABLE IF NOT EXISTS objects (\n object_id TEXT PRIMARY KEY,\n hash_alg TEXT NOT NULL,\n hash TEXT NOT NULL,\n size_bytes INTEGER NOT NULL,\n compressed_size_bytes INTEGER,\n compression TEXT NOT NULL DEFAULT 'zstd',\n mime_type TEXT,\n encoding TEXT,\n storage_path TEXT NOT NULL,\n created_at TEXT NOT NULL\n);\n\nCREATE INDEX IF NOT EXISTS objects_hash_idx ON objects(hash_alg, hash);\n\nCREATE TABLE IF NOT EXISTS source_files (\n source_file_id TEXT PRIMARY KEY,\n source_tool TEXT NOT NULL,\n path TEXT NOT NULL,\n file_kind TEXT NOT NULL,\n size_bytes INTEGER NOT NULL,\n mtime TEXT,\n content_hash TEXT NOT NULL,\n object_id TEXT REFERENCES objects(object_id),\n discovered_at TEXT NOT NULL,\n workspace_hint TEXT,\n UNIQUE(source_tool, path, size_bytes, mtime, content_hash)\n);\n\nCREATE INDEX IF NOT EXISTS source_files_tool_idx ON source_files(source_tool);\nCREATE INDEX IF NOT EXISTS source_files_hash_idx ON source_files(content_hash);\n\nCREATE TABLE IF NOT EXISTS import_batches (\n batch_id TEXT PRIMARY KEY,\n parser_version TEXT NOT NULL,\n source_tool TEXT,\n paths TEXT,\n started_at TEXT NOT NULL,\n finished_at TEXT,\n status TEXT NOT NULL DEFAULT 'running',\n counts_json TEXT\n);\n\nCREATE TABLE IF NOT EXISTS raw_records (\n raw_record_id TEXT PRIMARY KEY,\n source_file_id TEXT NOT NULL REFERENCES source_files(source_file_id),\n source_tool TEXT NOT NULL,\n record_kind TEXT NOT NULL,\n ordinal INTEGER,\n line_no INTEGER,\n json_pointer TEXT,\n native_id TEXT,\n raw_object_id TEXT NOT NULL REFERENCES objects(object_id),\n decoded_json_object_id TEXT REFERENCES objects(object_id),\n parser_status TEXT NOT NULL,\n confidence TEXT NOT NULL DEFAULT 'high',\n import_batch_id TEXT NOT NULL REFERENCES import_batches(batch_id),\n UNIQUE(source_file_id, ordinal, raw_object_id)\n);\n\nCREATE INDEX IF NOT EXISTS raw_records_file_idx ON raw_records(source_file_id);\nCREATE INDEX IF NOT EXISTS raw_records_native_idx ON raw_records(source_tool, native_id);\n\nCREATE TABLE IF NOT EXISTS import_errors (\n error_id INTEGER PRIMARY KEY AUTOINCREMENT,\n batch_id TEXT NOT NULL REFERENCES import_batches(batch_id),\n source_file_id TEXT,\n raw_record_id TEXT,\n kind TEXT NOT NULL,\n message TEXT NOT NULL,\n payload_object_id TEXT REFERENCES objects(object_id),\n occurred_at TEXT NOT NULL\n);\n\nCREATE TABLE IF NOT EXISTS uncertainties (\n uncertainty_id INTEGER PRIMARY KEY AUTOINCREMENT,\n entity_type TEXT NOT NULL,\n entity_id TEXT NOT NULL,\n reason TEXT NOT NULL,\n metadata_object_id TEXT REFERENCES objects(object_id)\n);\n\nCREATE TABLE IF NOT EXISTS projects (\n project_id TEXT PRIMARY KEY,\n canonical_path TEXT,\n path_hash TEXT,\n source_tool TEXT,\n source_project_id TEXT,\n display_name TEXT,\n created_at TEXT NOT NULL,\n UNIQUE(source_tool, source_project_id)\n);\n\nCREATE TABLE IF NOT EXISTS sessions (\n session_id TEXT PRIMARY KEY,\n source_tool TEXT NOT NULL,\n source_session_id TEXT NOT NULL,\n project_id TEXT REFERENCES projects(project_id),\n parent_session_id TEXT REFERENCES sessions(session_id),\n is_subagent INTEGER NOT NULL DEFAULT 0,\n agent_role TEXT,\n agent_nickname TEXT,\n title TEXT,\n summary TEXT,\n start_ts TEXT,\n end_ts TEXT,\n cwd_initial TEXT,\n git_branch_initial TEXT,\n model_first TEXT,\n model_last TEXT,\n status TEXT,\n timeline_confidence TEXT NOT NULL DEFAULT 'high'\n CHECK (timeline_confidence IN ('high','medium','low')),\n raw_record_id TEXT REFERENCES raw_records(raw_record_id),\n UNIQUE(source_tool, source_session_id)\n);\n\nCREATE INDEX IF NOT EXISTS sessions_source_idx ON sessions(source_tool);\nCREATE INDEX IF NOT EXISTS sessions_start_idx ON sessions(start_ts);\nCREATE INDEX IF NOT EXISTS sessions_project_idx ON sessions(project_id);\nCREATE INDEX IF NOT EXISTS sessions_parent_idx ON sessions(parent_session_id);\n\nCREATE TABLE IF NOT EXISTS turns (\n turn_id TEXT PRIMARY KEY,\n session_id TEXT NOT NULL REFERENCES sessions(session_id),\n source_turn_id TEXT,\n ordinal INTEGER NOT NULL,\n start_ts TEXT,\n end_ts TEXT,\n model TEXT,\n cwd TEXT,\n git_branch TEXT,\n approval_policy TEXT,\n sandbox_policy TEXT,\n effort TEXT,\n raw_record_id TEXT REFERENCES raw_records(raw_record_id)\n);\n\nCREATE INDEX IF NOT EXISTS turns_session_idx ON turns(session_id, ordinal);\n\nCREATE TABLE IF NOT EXISTS events (\n event_id TEXT PRIMARY KEY,\n session_id TEXT NOT NULL REFERENCES sessions(session_id),\n turn_id TEXT REFERENCES turns(turn_id),\n source_event_id TEXT,\n event_type TEXT NOT NULL,\n source_type TEXT,\n subtype TEXT,\n timestamp TEXT,\n ordinal INTEGER NOT NULL,\n actor TEXT,\n payload_object_id TEXT REFERENCES objects(object_id),\n raw_record_id TEXT NOT NULL REFERENCES raw_records(raw_record_id),\n confidence TEXT NOT NULL DEFAULT 'high',\n is_derived INTEGER NOT NULL DEFAULT 0\n);\n\nCREATE INDEX IF NOT EXISTS events_session_idx ON events(session_id, ordinal);\nCREATE INDEX IF NOT EXISTS events_type_idx ON events(event_type, subtype);\n\nCREATE TABLE IF NOT EXISTS messages (\n message_id TEXT PRIMARY KEY,\n session_id TEXT NOT NULL REFERENCES sessions(session_id),\n turn_id TEXT REFERENCES turns(turn_id),\n event_id TEXT REFERENCES events(event_id),\n source_message_id TEXT,\n role TEXT NOT NULL CHECK (role IN (\n 'system_prompt','developer','user','assistant','tool','operational'\n )),\n author_name TEXT,\n model TEXT,\n timestamp TEXT,\n ordinal INTEGER NOT NULL,\n parent_message_id TEXT REFERENCES messages(message_id),\n request_id TEXT,\n status TEXT,\n raw_record_id TEXT NOT NULL REFERENCES raw_records(raw_record_id)\n);\n\nCREATE INDEX IF NOT EXISTS messages_session_idx ON messages(session_id, ordinal);\nCREATE INDEX IF NOT EXISTS messages_role_idx ON messages(role);\n\nCREATE TABLE IF NOT EXISTS content_blocks (\n block_id TEXT PRIMARY KEY,\n message_id TEXT REFERENCES messages(message_id),\n event_id TEXT REFERENCES events(event_id),\n session_id TEXT NOT NULL REFERENCES sessions(session_id),\n ordinal INTEGER NOT NULL,\n block_type TEXT NOT NULL,\n text_object_id TEXT REFERENCES objects(object_id),\n text_inline TEXT,\n mime_type TEXT,\n token_count INTEGER,\n is_error INTEGER NOT NULL DEFAULT 0,\n is_redacted INTEGER NOT NULL DEFAULT 0,\n visibility TEXT NOT NULL DEFAULT 'default'\n CHECK (visibility IN ('default','hidden_by_default','audit_only')),\n raw_record_id TEXT NOT NULL REFERENCES raw_records(raw_record_id)\n);\n\nCREATE INDEX IF NOT EXISTS blocks_session_idx ON content_blocks(session_id, ordinal);\nCREATE INDEX IF NOT EXISTS blocks_message_idx ON content_blocks(message_id);\n\nCREATE TABLE IF NOT EXISTS tool_calls (\n tool_call_id TEXT PRIMARY KEY,\n session_id TEXT NOT NULL REFERENCES sessions(session_id),\n turn_id TEXT REFERENCES turns(turn_id),\n message_id TEXT REFERENCES messages(message_id),\n event_id TEXT REFERENCES events(event_id),\n source_call_id TEXT,\n tool_name TEXT NOT NULL,\n canonical_tool_type TEXT,\n args_object_id TEXT REFERENCES objects(object_id),\n command TEXT,\n cwd TEXT,\n path TEXT,\n query TEXT,\n timestamp_start TEXT,\n timestamp_end TEXT,\n status TEXT,\n raw_record_id TEXT NOT NULL REFERENCES raw_records(raw_record_id)\n);\n\nCREATE INDEX IF NOT EXISTS tool_calls_session_idx ON tool_calls(session_id, timestamp_start);\nCREATE INDEX IF NOT EXISTS tool_calls_name_idx ON tool_calls(tool_name);\nCREATE INDEX IF NOT EXISTS tool_calls_canon_idx ON tool_calls(canonical_tool_type);\nCREATE INDEX IF NOT EXISTS tool_calls_source_call_idx ON tool_calls(session_id, source_call_id);\n\nCREATE TABLE IF NOT EXISTS tool_results (\n tool_result_id TEXT PRIMARY KEY,\n tool_call_id TEXT REFERENCES tool_calls(tool_call_id),\n session_id TEXT NOT NULL REFERENCES sessions(session_id),\n message_id TEXT REFERENCES messages(message_id),\n event_id TEXT REFERENCES events(event_id),\n source_call_id TEXT,\n status TEXT,\n is_error INTEGER NOT NULL DEFAULT 0,\n exit_code INTEGER,\n duration_ms INTEGER,\n stdout_object_id TEXT REFERENCES objects(object_id),\n stderr_object_id TEXT REFERENCES objects(object_id),\n output_object_id TEXT REFERENCES objects(object_id),\n preview TEXT,\n raw_record_id TEXT NOT NULL REFERENCES raw_records(raw_record_id)\n);\n\nCREATE INDEX IF NOT EXISTS tool_results_session_idx ON tool_results(session_id);\nCREATE INDEX IF NOT EXISTS tool_results_call_idx ON tool_results(tool_call_id);\nCREATE INDEX IF NOT EXISTS tool_results_source_call_idx ON tool_results(session_id, source_call_id);\nCREATE INDEX IF NOT EXISTS tool_results_error_idx ON tool_results(is_error);\n\nCREATE TABLE IF NOT EXISTS artifacts (\n artifact_id TEXT PRIMARY KEY,\n session_id TEXT REFERENCES sessions(session_id),\n project_id TEXT REFERENCES projects(project_id),\n source_tool TEXT NOT NULL,\n kind TEXT NOT NULL,\n path TEXT,\n logical_path TEXT,\n object_id TEXT REFERENCES objects(object_id),\n text_object_id TEXT REFERENCES objects(object_id),\n mime_type TEXT,\n size_bytes INTEGER NOT NULL,\n created_ts TEXT,\n raw_record_id TEXT NOT NULL REFERENCES raw_records(raw_record_id)\n);\n\nCREATE INDEX IF NOT EXISTS artifacts_session_idx ON artifacts(session_id);\nCREATE INDEX IF NOT EXISTS artifacts_path_idx ON artifacts(path);\n\nCREATE TABLE IF NOT EXISTS edges (\n edge_id INTEGER PRIMARY KEY AUTOINCREMENT,\n src_type TEXT NOT NULL,\n src_id TEXT NOT NULL,\n dst_type TEXT NOT NULL,\n dst_id TEXT NOT NULL,\n edge_type TEXT NOT NULL,\n confidence TEXT NOT NULL DEFAULT 'high',\n source TEXT NOT NULL DEFAULT 'explicit',\n raw_record_id TEXT REFERENCES raw_records(raw_record_id),\n metadata_object_id TEXT REFERENCES objects(object_id),\n UNIQUE(src_type, src_id, dst_type, dst_id, edge_type)\n);\n\nCREATE INDEX IF NOT EXISTS edges_src_idx ON edges(src_type, src_id);\nCREATE INDEX IF NOT EXISTS edges_dst_idx ON edges(dst_type, dst_id);\nCREATE INDEX IF NOT EXISTS edges_type_idx ON edges(edge_type);\n\nCREATE TABLE IF NOT EXISTS search_docs (\n doc_id TEXT PRIMARY KEY,\n entity_type TEXT NOT NULL,\n entity_id TEXT NOT NULL,\n session_id TEXT,\n project_id TEXT,\n timestamp TEXT,\n role TEXT,\n tool_name TEXT,\n canonical_tool_type TEXT,\n field_kind TEXT NOT NULL,\n text TEXT NOT NULL\n);\n\nCREATE INDEX IF NOT EXISTS search_docs_session_idx ON search_docs(session_id);\nCREATE INDEX IF NOT EXISTS search_docs_entity_idx ON search_docs(entity_type, entity_id);\nCREATE INDEX IF NOT EXISTS search_docs_field_idx ON search_docs(field_kind);\n\nCREATE VIRTUAL TABLE IF NOT EXISTS search_docs_fts USING fts5(\n text,\n role UNINDEXED,\n tool_name UNINDEXED,\n field_kind UNINDEXED,\n content='search_docs',\n content_rowid='rowid',\n tokenize='unicode61 remove_diacritics 2'\n);\n\nCREATE TRIGGER IF NOT EXISTS search_docs_ai AFTER INSERT ON search_docs BEGIN\n INSERT INTO search_docs_fts(rowid, text, role, tool_name, field_kind)\n VALUES (new.rowid, new.text, new.role, new.tool_name, new.field_kind);\nEND;\n\nCREATE TRIGGER IF NOT EXISTS search_docs_ad AFTER DELETE ON search_docs BEGIN\n INSERT INTO search_docs_fts(search_docs_fts, rowid, text, role, tool_name, field_kind)\n VALUES('delete', old.rowid, old.text, old.role, old.tool_name, old.field_kind);\nEND;\n\nCREATE TRIGGER IF NOT EXISTS search_docs_au AFTER UPDATE ON search_docs BEGIN\n INSERT INTO search_docs_fts(search_docs_fts, rowid, text, role, tool_name, field_kind)\n VALUES('delete', old.rowid, old.text, old.role, old.tool_name, old.field_kind);\n INSERT INTO search_docs_fts(rowid, text, role, tool_name, field_kind)\n VALUES (new.rowid, new.text, new.role, new.tool_name, new.field_kind);\nEND;\n`\n","/**\n * Adds durable status tracking for local search index engines.\n *\n * FTS5 starts as ready because it is maintained inside SQLite; Tantivy starts\n * missing until the external index is built.\n */\nexport const SQL_002_SEARCH_INDEX_STATUS = String.raw`\nCREATE TABLE IF NOT EXISTS search_index_status (\n engine TEXT PRIMARY KEY,\n status TEXT NOT NULL CHECK (status IN ('missing','ready','stale','building','failed')),\n source_doc_count INTEGER NOT NULL DEFAULT 0,\n indexed_doc_count INTEGER NOT NULL DEFAULT 0,\n updated_at TEXT NOT NULL,\n error_message TEXT\n);\n\nINSERT OR IGNORE INTO search_index_status (\n engine, status, source_doc_count, indexed_doc_count, updated_at, error_message\n) VALUES\n ('fts5', 'ready', 0, 0, strftime('%Y-%m-%dT%H:%M:%fZ','now'), NULL),\n ('tantivy', 'missing', 0, 0, strftime('%Y-%m-%dT%H:%M:%fZ','now'), NULL);\n`\n","/**\n * Derived analytics views over canonical projection tables.\n *\n * These views are read models only; importers should continue to write source,\n * raw, and canonical tables directly.\n */\nexport const SQL_003_ANALYTICS_VIEWS = String.raw`\nCREATE VIEW IF NOT EXISTS session_facts AS\nWITH turn_counts AS (\n SELECT session_id, count(*) AS turn_count\n FROM turns\n GROUP BY session_id\n),\nmessage_counts AS (\n SELECT session_id,\n count(*) AS message_count,\n sum(CASE WHEN role = 'user' THEN 1 ELSE 0 END) AS user_message_count,\n sum(CASE WHEN role = 'assistant' THEN 1 ELSE 0 END) AS assistant_message_count\n FROM messages\n GROUP BY session_id\n),\ntool_call_counts AS (\n SELECT session_id,\n count(*) AS tool_call_count,\n sum(CASE WHEN status = 'error' THEN 1 ELSE 0 END) AS tool_call_error_count\n FROM tool_calls\n GROUP BY session_id\n),\ntool_result_counts AS (\n SELECT session_id,\n count(*) AS tool_result_count,\n sum(CASE WHEN is_error = 1 OR (exit_code IS NOT NULL AND exit_code <> 0)\n THEN 1 ELSE 0 END) AS tool_result_error_count,\n sum(COALESCE(duration_ms, 0)) AS tool_duration_ms\n FROM tool_results\n GROUP BY session_id\n),\nsearch_doc_counts AS (\n SELECT session_id, count(*) AS search_doc_count\n FROM search_docs\n WHERE session_id IS NOT NULL\n GROUP BY session_id\n)\nSELECT s.session_id,\n s.source_tool,\n s.source_session_id,\n s.project_id,\n p.display_name AS project_name,\n p.canonical_path AS project_path,\n s.parent_session_id,\n s.is_subagent,\n s.agent_role,\n s.agent_nickname,\n s.title,\n s.start_ts,\n s.end_ts,\n CASE\n WHEN s.start_ts IS NOT NULL AND s.end_ts IS NOT NULL\n THEN ROUND((julianday(s.end_ts) - julianday(s.start_ts)) * 86400, 3)\n ELSE NULL\n END AS duration_seconds,\n s.cwd_initial,\n s.git_branch_initial,\n s.model_first,\n s.model_last,\n s.status,\n s.timeline_confidence,\n sf.path AS source_file_path,\n COALESCE(tc.turn_count, 0) AS turn_count,\n COALESCE(mc.message_count, 0) AS message_count,\n COALESCE(mc.user_message_count, 0) AS user_message_count,\n COALESCE(mc.assistant_message_count, 0) AS assistant_message_count,\n COALESCE(tcc.tool_call_count, 0) AS tool_call_count,\n COALESCE(trc.tool_result_count, 0) AS tool_result_count,\n COALESCE(tcc.tool_call_error_count, 0)\n + COALESCE(trc.tool_result_error_count, 0) AS tool_error_count,\n COALESCE(trc.tool_duration_ms, 0) AS tool_duration_ms,\n COALESCE(sdc.search_doc_count, 0) AS search_doc_count\n FROM sessions s\n LEFT JOIN projects p ON p.project_id = s.project_id\n LEFT JOIN raw_records rr ON rr.raw_record_id = s.raw_record_id\n LEFT JOIN source_files sf ON sf.source_file_id = rr.source_file_id\n LEFT JOIN turn_counts tc ON tc.session_id = s.session_id\n LEFT JOIN message_counts mc ON mc.session_id = s.session_id\n LEFT JOIN tool_call_counts tcc ON tcc.session_id = s.session_id\n LEFT JOIN tool_result_counts trc ON trc.session_id = s.session_id\n LEFT JOIN search_doc_counts sdc ON sdc.session_id = s.session_id;\n\nCREATE VIEW IF NOT EXISTS tool_usage_facts AS\nWITH result_rollup AS (\n SELECT tool_call_id,\n session_id,\n count(*) AS tool_result_count,\n max(status) AS result_status,\n max(is_error) AS is_error,\n min(exit_code) AS exit_code,\n sum(COALESCE(duration_ms, 0)) AS duration_ms,\n max(preview) AS preview\n FROM tool_results\n GROUP BY tool_call_id, session_id\n)\nSELECT tc.tool_call_id,\n tc.session_id,\n s.source_tool,\n s.source_session_id,\n s.project_id,\n p.display_name AS project_name,\n p.canonical_path AS project_path,\n tc.turn_id,\n tc.message_id,\n tc.event_id,\n tc.source_call_id,\n tc.tool_name,\n tc.canonical_tool_type,\n tc.command,\n tc.cwd,\n tc.path,\n tc.query,\n tc.timestamp_start,\n tc.timestamp_end,\n CASE\n WHEN tc.timestamp_start IS NOT NULL AND tc.timestamp_end IS NOT NULL\n THEN ROUND((julianday(tc.timestamp_end) - julianday(tc.timestamp_start)) * 86400, 3)\n ELSE NULL\n END AS call_duration_seconds,\n tc.status AS call_status,\n rr.result_status,\n COALESCE(rr.is_error, 0) AS is_error,\n rr.exit_code,\n rr.duration_ms AS result_duration_ms,\n COALESCE(rr.tool_result_count, 0) AS tool_result_count,\n rr.preview,\n tc.raw_record_id\n FROM tool_calls tc\n LEFT JOIN sessions s ON s.session_id = tc.session_id\n LEFT JOIN projects p ON p.project_id = s.project_id\n LEFT JOIN result_rollup rr ON rr.tool_call_id = tc.tool_call_id;\n\nCREATE VIEW IF NOT EXISTS error_facts AS\nSELECT 'tool_result:' || tr.tool_result_id AS error_id,\n 'tool_result' AS error_category,\n s.source_tool,\n s.project_id,\n p.display_name AS project_name,\n tr.session_id,\n COALESCE(tc.timestamp_end, tc.timestamp_start) AS timestamp,\n tc.tool_name,\n tc.canonical_tool_type,\n COALESCE(tr.status, tc.status) AS status,\n tr.exit_code,\n NULL AS message,\n tr.preview,\n NULL AS entity_type,\n NULL AS entity_id,\n tr.raw_record_id\n FROM tool_results tr\n LEFT JOIN tool_calls tc ON tc.tool_call_id = tr.tool_call_id\n LEFT JOIN sessions s ON s.session_id = tr.session_id\n LEFT JOIN projects p ON p.project_id = s.project_id\n WHERE tr.is_error = 1 OR (tr.exit_code IS NOT NULL AND tr.exit_code <> 0)\nUNION ALL\nSELECT 'import_error:' || CAST(ie.error_id AS TEXT) AS error_id,\n 'import_error' AS error_category,\n COALESCE(rr.source_tool, ib.source_tool) AS source_tool,\n NULL AS project_id,\n NULL AS project_name,\n NULL AS session_id,\n ie.occurred_at AS timestamp,\n NULL AS tool_name,\n NULL AS canonical_tool_type,\n ie.kind AS status,\n NULL AS exit_code,\n ie.message,\n NULL AS preview,\n NULL AS entity_type,\n NULL AS entity_id,\n ie.raw_record_id\n FROM import_errors ie\n LEFT JOIN import_batches ib ON ib.batch_id = ie.batch_id\n LEFT JOIN raw_records rr ON rr.raw_record_id = ie.raw_record_id\nUNION ALL\nSELECT 'uncertainty:' || CAST(u.uncertainty_id AS TEXT) AS error_id,\n 'uncertainty' AS error_category,\n NULL AS source_tool,\n NULL AS project_id,\n NULL AS project_name,\n CASE WHEN u.entity_type = 'session' THEN u.entity_id ELSE NULL END AS session_id,\n NULL AS timestamp,\n NULL AS tool_name,\n NULL AS canonical_tool_type,\n u.reason AS status,\n NULL AS exit_code,\n u.reason AS message,\n NULL AS preview,\n u.entity_type,\n u.entity_id,\n NULL AS raw_record_id\n FROM uncertainties u;\n\nCREATE VIEW IF NOT EXISTS model_usage AS\nWITH model_events AS (\n SELECT s.source_tool,\n s.project_id,\n p.display_name AS project_name,\n p.canonical_path AS project_path,\n s.session_id,\n NULL AS turn_id,\n s.model_first AS model,\n s.start_ts AS timestamp,\n 'session_first' AS observation_type\n FROM sessions s\n LEFT JOIN projects p ON p.project_id = s.project_id\n WHERE s.model_first IS NOT NULL\n UNION ALL\n SELECT s.source_tool, s.project_id, p.display_name, p.canonical_path,\n s.session_id, NULL AS turn_id, s.model_last AS model, s.end_ts AS timestamp,\n 'session_last' AS observation_type\n FROM sessions s\n LEFT JOIN projects p ON p.project_id = s.project_id\n WHERE s.model_last IS NOT NULL\n UNION ALL\n SELECT s.source_tool, s.project_id, p.display_name, p.canonical_path,\n t.session_id, t.turn_id, t.model, t.start_ts AS timestamp, 'turn' AS observation_type\n FROM turns t\n LEFT JOIN sessions s ON s.session_id = t.session_id\n LEFT JOIN projects p ON p.project_id = s.project_id\n WHERE t.model IS NOT NULL\n UNION ALL\n SELECT s.source_tool, s.project_id, p.display_name, p.canonical_path,\n m.session_id, m.turn_id, m.model, m.timestamp, 'message' AS observation_type\n FROM messages m\n LEFT JOIN sessions s ON s.session_id = m.session_id\n LEFT JOIN projects p ON p.project_id = s.project_id\n WHERE m.model IS NOT NULL\n)\nSELECT source_tool,\n project_id,\n project_name,\n project_path,\n model,\n count(DISTINCT session_id) AS session_count,\n count(DISTINCT turn_id) AS turn_count,\n count(*) AS observation_count,\n sum(CASE WHEN observation_type = 'message' THEN 1 ELSE 0 END) AS message_count,\n min(timestamp) AS first_seen_ts,\n max(timestamp) AS last_seen_ts\n FROM model_events\n GROUP BY source_tool, project_id, project_name, project_path, model;\n\nCREATE VIEW IF NOT EXISTS project_activity AS\nSELECT s.source_tool,\n s.project_id,\n COALESCE(p.display_name, s.cwd_initial, '(unknown)') AS project_name,\n p.canonical_path AS project_path,\n min(s.start_ts) AS first_session_ts,\n max(COALESCE(s.end_ts, s.start_ts)) AS latest_session_ts,\n count(DISTINCT s.session_id) AS session_count,\n count(DISTINCT CASE WHEN s.timeline_confidence = 'low' THEN s.session_id END)\n AS low_confidence_session_count,\n count(DISTINCT t.turn_id) AS turn_count,\n count(DISTINCT m.message_id) AS message_count,\n count(DISTINCT tc.tool_call_id) AS tool_call_count,\n count(DISTINCT tr.tool_result_id) AS tool_result_count,\n count(DISTINCT CASE\n WHEN tr.is_error = 1 OR (tr.exit_code IS NOT NULL AND tr.exit_code <> 0)\n THEN tr.tool_result_id\n END) AS tool_error_count,\n count(DISTINCT sd.doc_id) AS search_doc_count\n FROM sessions s\n LEFT JOIN projects p ON p.project_id = s.project_id\n LEFT JOIN turns t ON t.session_id = s.session_id\n LEFT JOIN messages m ON m.session_id = s.session_id\n LEFT JOIN tool_calls tc ON tc.session_id = s.session_id\n LEFT JOIN tool_results tr ON tr.session_id = s.session_id\n LEFT JOIN search_docs sd ON sd.session_id = s.session_id\n GROUP BY s.source_tool, s.project_id, p.display_name, s.cwd_initial, p.canonical_path;\n`\n","/**\n * Adds checkpoint columns for incremental Tantivy rebuilds.\n *\n * `last_indexed_rowid` is the highest `search_docs.rowid` already present in\n * Tantivy segments. `schema_fingerprint` lets the rebuild path detect index\n * schema changes and fall back to a full re-index. Both columns are nullable;\n * upgraded v3 bundles therefore default to the safe full-rebuild behavior.\n */\nexport const SQL_004_TANTIVY_CHECKPOINT = String.raw`\nALTER TABLE search_index_status ADD COLUMN last_indexed_rowid INTEGER;\nALTER TABLE search_index_status ADD COLUMN schema_fingerprint TEXT;\n`\n","// Loaded at runtime by core/schema/migrate.ts.\n\n/**\n * Add the optional transport hash cached for object upload bodies.\n *\n * `objects.hash` remains the canonical uncompressed BLAKE3 digest. This column\n * stores the BLAKE3 digest of the bytes sent over sync transport, which may be\n * compressed bytes for zstd-backed objects.\n */\nexport const SQL_005_OBJECT_TRANSPORT_HASH = String.raw`\n-- Schema W v5\n\nALTER TABLE objects ADD COLUMN transport_hash TEXT;\n`\n","import type { Db } from '../db.js'\nimport { SQL_001_INIT } from './sql/001_init.js'\nimport { SQL_002_SEARCH_INDEX_STATUS } from './sql/002_search_index_status.js'\nimport { SQL_003_ANALYTICS_VIEWS } from './sql/003_analytics_views.js'\nimport { SQL_004_TANTIVY_CHECKPOINT } from './sql/004_tantivy_checkpoint.js'\nimport { SQL_005_OBJECT_TRANSPORT_HASH } from './sql/005_object_transport_hash.js'\n\n/**\n * One immutable schema migration entry.\n *\n * The `version` is the durable ordering key stored in `_prosa_migrations`;\n * `sql` may contain multiple DDL/DML statements.\n */\ninterface Migration {\n version: number\n name: string\n sql: string\n}\n\n/**\n * Ordered migration list applied to every opened bundle.\n *\n * Each entry is a self-contained set of DDL statements run inside a single\n * transaction together with its bookkeeping insert.\n */\nconst MIGRATIONS: readonly Migration[] = [\n { version: 1, name: 'init', sql: SQL_001_INIT },\n { version: 2, name: 'search_index_status', sql: SQL_002_SEARCH_INDEX_STATUS },\n { version: 3, name: 'analytics_views', sql: SQL_003_ANALYTICS_VIEWS },\n { version: 4, name: 'tantivy_checkpoint', sql: SQL_004_TANTIVY_CHECKPOINT },\n { version: 5, name: 'object_transport_hash', sql: SQL_005_OBJECT_TRANSPORT_HASH },\n]\n\n/** Result returned after running schema migrations. */\nexport interface MigrationResult {\n /** Migration versions applied during this call. */\n applied: number[]\n}\n\n/**\n * Apply all unapplied schema migrations and return the versions newly applied.\n *\n * The migrations table is created on demand. Each migration either fully\n * applies with its bookkeeping row or rolls back through SQLite's transaction\n * machinery; errors propagate to the caller.\n */\nexport function runMigrations(db: Db): MigrationResult {\n db.exec(`\n CREATE TABLE IF NOT EXISTS _prosa_migrations (\n version INTEGER PRIMARY KEY,\n name TEXT NOT NULL,\n applied_at TEXT NOT NULL\n );\n `)\n\n const applied = new Set<number>(\n db\n .prepare<[], { version: number }>(`SELECT version FROM _prosa_migrations`)\n .all()\n .map((row) => row.version),\n )\n\n const newlyApplied: number[] = []\n\n for (const migration of MIGRATIONS) {\n if (applied.has(migration.version)) continue\n const tx = db.transaction(() => {\n db.exec(migration.sql)\n db.prepare(`INSERT INTO _prosa_migrations(version, name, applied_at) VALUES (?, ?, ?)`).run(\n migration.version,\n migration.name,\n new Date().toISOString(),\n )\n })\n tx()\n newlyApplied.push(migration.version)\n }\n\n return { applied: newlyApplied }\n}\n\n/**\n * Read the highest applied schema version from the database.\n *\n * Returns 0 for an uninitialized database or if migration metadata cannot be\n * queried yet.\n */\nexport function currentSchemaVersion(db: Db): number {\n try {\n const row = db\n .prepare<[], { version: number | null }>(`SELECT MAX(version) AS version FROM _prosa_migrations`)\n .get()\n return row?.version ?? 0\n } catch {\n return 0\n }\n}\n","{\n \"name\": \"@c3-oss/prosa-core\",\n \"version\": \"0.8.0\",\n \"description\": \"Core storage, import, search, export, analytics, and MCP APIs for prosa.\",\n \"author\": \"Caian Ertl <hi@caian.org>\",\n \"license\": \"MIT\",\n \"type\": \"module\",\n \"homepage\": \"https://github.com/c3-oss/prosa#readme\",\n \"bugs\": {\n \"url\": \"https://github.com/c3-oss/prosa/issues\"\n },\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://github.com/c3-oss/prosa.git\",\n \"directory\": \"packages/prosa-core\"\n },\n \"files\": [\"dist\"],\n \"main\": \"./dist/index.js\",\n \"types\": \"./dist/index.d.ts\",\n \"exports\": {\n \".\": {\n \"prosa-dev\": \"./src/index.ts\",\n \"import\": \"./dist/index.js\",\n \"types\": \"./dist/index.d.ts\"\n }\n },\n \"typedocOptions\": {\n \"entryPoints\": [\"src/index.ts\"],\n \"tsconfig\": \"tsconfig.json\"\n },\n \"publishConfig\": {\n \"access\": \"public\",\n \"registry\": \"https://registry.npmjs.org/\"\n },\n \"scripts\": {\n \"build\": \"tsup\",\n \"typecheck\": \"tsc --noEmit\",\n \"test\": \"vitest run\",\n \"test:coverage\": \"vitest run --coverage\",\n \"lint\": \"biome check .\",\n \"lint:fix\": \"biome check --fix .\",\n \"clean\": \"rm -rf dist coverage .turbo\"\n },\n \"dependencies\": {\n \"@duckdb/node-api\": \"1.5.2-r.1\",\n \"@modelcontextprotocol/sdk\": \"^1.29.0\",\n \"@noble/hashes\": \"^1.7.0\",\n \"@oxdev03/node-tantivy-binding\": \"0.2.0\",\n \"better-sqlite3\": \"^12.10.0\",\n \"filtrex\": \"^3.1.0\",\n \"hash-wasm\": \"^4.12.0\",\n \"pino\": \"^10.3.1\",\n \"zod\": \"^3.23.8\",\n \"zstd-napi\": \"^0.0.10\"\n },\n \"devDependencies\": {\n \"@c3-oss/config-biome\": \"^0.3.1\",\n \"@c3-oss/config-tsup\": \"^0.2.0\",\n \"@c3-oss/config-typescript\": \"^0.1.0\",\n \"@c3-oss/config-vitest\": \"^0.3.0\",\n \"@types/better-sqlite3\": \"^7.6.12\"\n },\n \"optionalDependencies\": {\n \"@oxdev03/node-tantivy-binding-darwin-arm64\": \"0.2.0\",\n \"@oxdev03/node-tantivy-binding-darwin-x64\": \"0.2.0\",\n \"@oxdev03/node-tantivy-binding-linux-x64-gnu\": \"0.2.0\",\n \"@oxdev03/node-tantivy-binding-win32-x64-msvc\": \"0.2.0\"\n }\n}\n","import packageJson from '../../package.json' with { type: 'json' }\n\n/**\n * Parser/projection version for normalized importer output.\n *\n * Bump when importer or normalizer semantics change in a way that can make\n * existing canonical rows stale relative to preserved raw records. Stored on\n * every `import_batches` row for future re-projection decisions.\n */\nexport const PROSA_PARSER_VERSION = packageJson.version\n\n/**\n * Current SQLite schema version, matching the highest migration in\n * `src/core/schema`.\n */\nexport const PROSA_SCHEMA_VERSION = 5\n","// Row-shaped TypeScript types matching the SQLite schema. These are the\n// boundary contract between importers and the catalog. Optional fields use\n// `null` (not `undefined`) to mirror SQLite NULL semantics directly.\n\n/**\n * Source tools that have first-class importer support and stable schema\n * semantics.\n */\nexport const SOURCE_TOOLS = ['cursor', 'codex', 'claude', 'gemini', 'hermes'] as const\n\n/**\n * Normalized source-tool discriminator stored on source files, raw records,\n * sessions, and analytics views.\n */\nexport type SourceTool = (typeof SOURCE_TOOLS)[number]\n\n/**\n * Confidence level for inferred timeline positions and recovered relations.\n */\nexport type Confidence = 'high' | 'medium' | 'low'\n\n/**\n * Canonical message role vocabulary used by the `messages.role` CHECK\n * constraint. `operational` is reserved for runtime/system events that are not\n * user-visible system prompts.\n */\nexport type MessageRole = 'system_prompt' | 'developer' | 'user' | 'assistant' | 'tool' | 'operational'\n\n/**\n * Coarse tool categories used for cross-importer aggregation while preserving\n * the native tool name separately.\n */\nexport type CanonicalToolType =\n | 'shell'\n | 'read_file'\n | 'write_file'\n | 'edit_file'\n | 'search_file'\n | 'web_search'\n | 'mcp'\n | 'subagent'\n | 'patch'\n | 'other'\n\n/**\n * Directed graph relationship vocabulary for `edges`, covering conversation\n * lineage, tool call/result links, artifacts, and recovered equivalence.\n */\nexport type EdgeType =\n | 'parent_of'\n | 'calls'\n | 'returns'\n | 'spawned'\n | 'contains'\n | 'produced'\n | 'consumed'\n | 'derived_from'\n | 'summarizes'\n | 'compacts'\n | 'same_as'\n | 'refers_to'\n\n/**\n * Importer-normalized lifecycle state for tool calls when the source format\n * provides enough evidence to distinguish outcomes.\n */\nexport type ToolCallStatus = 'started' | 'success' | 'error' | 'cancelled' | 'unknown'\n\n/**\n * Complete row projection for the `sessions` table.\n *\n * Boolean flags are represented as SQLite integers and absent values are\n * represented as `null` so callers can bind/read rows without conversion.\n */\nexport interface SessionRowFull {\n /** Canonical prosa session identifier. */\n session_id: string\n /** Source tool that produced the session. */\n source_tool: SourceTool\n /** Native session identifier from the source tool. */\n source_session_id: string\n /** Canonical project identifier, when recovered. */\n project_id: string | null\n /** Parent session identifier for subagent sessions. */\n parent_session_id: string | null\n /** SQLite boolean indicating whether this session is a subagent. */\n is_subagent: 0 | 1\n /** Source-specific role for a subagent. */\n agent_role: string | null\n /** Display nickname for a subagent. */\n agent_nickname: string | null\n /** Best recovered session title. */\n title: string | null\n /** Best recovered session summary. */\n summary: string | null\n /** Earliest recovered session timestamp. */\n start_ts: string | null\n /** Latest recovered session timestamp. */\n end_ts: string | null\n /** Initial working directory, when available. */\n cwd_initial: string | null\n /** Initial git branch, when available. */\n git_branch_initial: string | null\n /** First observed model name. */\n model_first: string | null\n /** Last observed model name. */\n model_last: string | null\n /** Source or importer session status. */\n status: string | null\n /** Confidence in recovered timeline ordering. */\n timeline_confidence: Confidence\n /** Raw record that introduced the session, when applicable. */\n raw_record_id: string | null\n}\n","import { mkdir, readFile, writeFile } from 'node:fs/promises'\nimport path from 'node:path'\nimport type { Bundle } from '../bundle.js'\nimport { prepare } from '../db.js'\nimport { type Compression, compressBytes, decompressBytes } from './compress.js'\nimport { blake3Hex, blake3HexAsync, objectIdFromHash, objectStoragePath } from './hash.js'\n\n/**\n * Content-addressed object identifier stored as `blake3:<hex>`.\n */\nexport type ObjectId = string\n\n/**\n * Complete metadata row for one object stored in the CAS.\n *\n * `storage_path` is relative to the bundle root and points at compressed or\n * raw bytes depending on `compression`.\n */\nexport interface ObjectMeta {\n /** Canonical object identifier, formatted as `blake3:<hex>`. */\n object_id: ObjectId\n /** Hash algorithm used to derive `hash` and `object_id`. */\n hash_alg: 'blake3'\n /** Raw BLAKE3 hex digest without the `blake3:` prefix. */\n hash: string\n /** Original uncompressed payload size in bytes. */\n size_bytes: number\n /** Stored compressed payload size, or null when stored uncompressed. */\n compressed_size_bytes: number | null\n /** Compression algorithm used for the stored payload. */\n compression: Compression\n /** Optional media type supplied by the writer. */\n mime_type: string | null\n /** Optional text encoding supplied by the writer. */\n encoding: string | null\n /** Bundle-relative path to the stored bytes. */\n storage_path: string\n /** BLAKE3 hex digest of the bytes stored on disk and uploaded over sync. */\n transport_hash: string | null\n /** ISO timestamp for the metadata row insertion. */\n created_at: string\n}\n\n/**\n * Optional MIME and text-encoding metadata for newly stored CAS objects.\n */\nexport interface PutOptions {\n /** Optional media type to persist on the object metadata row. */\n mimeType?: string\n /** Optional text encoding to persist on the object metadata row. */\n encoding?: string\n}\n\n/**\n * Per-process cache of directories we've already mkdir'd. The CAS fanout\n * creates `objects/blake3/ab/cd/` for 65k possible leaves; calling\n * `mkdir(... { recursive: true })` for every staged object during a large\n * import was a measurable cost. Cache by absolute path.\n */\nconst ensuredDirs = new Set<string>()\n\nexport async function ensureDir(absoluteDir: string): Promise<void> {\n if (ensuredDirs.has(absoluteDir)) return\n await mkdir(absoluteDir, { recursive: true })\n ensuredDirs.add(absoluteDir)\n}\n\n/**\n * Store raw bytes in the CAS. Returns the object_id. Idempotent: if the same\n * content already exists, returns the existing object_id without rewriting.\n *\n * Bytes are compressed with zstd when worth it (see compress.ts threshold).\n * The on-disk path is `<bundle>/objects/blake3/ab/cd/<hash>.zst`.\n */\nexport async function putBytes(bundle: Bundle, bytes: Uint8Array, options: PutOptions = {}): Promise<ObjectId> {\n const hash = await blake3HexAsync(bytes)\n const objectId = objectIdFromHash(hash)\n\n const existing = prepare<[string], ObjectMeta>(\n bundle.db,\n `SELECT object_id, hash_alg, hash, size_bytes, compressed_size_bytes,\n compression, mime_type, encoding, storage_path, transport_hash, created_at\n FROM objects WHERE object_id = ?`,\n ).get(objectId)\n\n if (existing) return objectId\n\n const { bytes: stored, compression } = compressBytes(bytes)\n const storagePath = objectStoragePath(hash, compression)\n const absolutePath = path.join(bundle.path, storagePath)\n\n await ensureDir(path.dirname(absolutePath))\n await writeFile(absolutePath, stored)\n\n prepare(\n bundle.db,\n `INSERT INTO objects (\n object_id, hash_alg, hash, size_bytes, compressed_size_bytes,\n compression, mime_type, encoding, storage_path, transport_hash, created_at\n ) VALUES (?, 'blake3', ?, ?, ?, ?, ?, ?, ?, ?, ?)`,\n ).run(\n objectId,\n hash,\n bytes.byteLength,\n compression === 'zstd' ? stored.byteLength : null,\n compression,\n options.mimeType ?? null,\n options.encoding ?? null,\n storagePath,\n await blake3HexAsync(stored),\n new Date().toISOString(),\n )\n\n return objectId\n}\n\n/**\n * Store UTF-8 text in the CAS with text metadata.\n */\nexport async function putText(bundle: Bundle, text: string, options: { mimeType?: string } = {}): Promise<ObjectId> {\n const buf = Buffer.from(text, 'utf8')\n return putBytes(bundle, buf, {\n mimeType: options.mimeType ?? 'text/plain; charset=utf-8',\n encoding: 'utf-8',\n })\n}\n\n/**\n * Store a JSON-serialized value in the CAS.\n *\n * Serialization is compact but not canonicalized; callers should not rely on\n * object key ordering for cross-process identity unless the input itself is\n * produced deterministically.\n */\nexport async function putJson(bundle: Bundle, value: unknown): Promise<ObjectId> {\n // Compact serialization. Stable enough for the importer's own writes; we\n // don't promise canonical JSON across producers.\n const text = JSON.stringify(value)\n return putBytes(bundle, Buffer.from(text, 'utf8'), {\n mimeType: 'application/json',\n encoding: 'utf-8',\n })\n}\n\n/**\n * Read and decompress object bytes from the CAS.\n *\n * Throws when `objectId` is absent from the `objects` table; filesystem read or\n * decompression errors also propagate because they indicate bundle corruption\n * or inaccessible storage.\n */\nexport async function getBytes(bundle: Bundle, objectId: ObjectId): Promise<Buffer> {\n const meta = prepare<[string], ObjectMeta>(\n bundle.db,\n `SELECT object_id, hash_alg, hash, size_bytes, compressed_size_bytes,\n compression, mime_type, encoding, storage_path, transport_hash, created_at\n FROM objects WHERE object_id = ?`,\n ).get(objectId)\n if (!meta) {\n throw new Error(`object not found: ${objectId}`)\n }\n const buf = await readFile(path.join(bundle.path, meta.storage_path))\n return decompressBytes(buf, meta.compression)\n}\n\n/**\n * Read an object as UTF-8 text.\n */\nexport async function getText(bundle: Bundle, objectId: ObjectId): Promise<string> {\n const buf = await getBytes(bundle, objectId)\n return buf.toString('utf8')\n}\n\n/**\n * Read an object as UTF-8 JSON and parse it as `T`.\n */\nexport async function getJson<T = unknown>(bundle: Bundle, objectId: ObjectId): Promise<T> {\n const text = await getText(bundle, objectId)\n return JSON.parse(text) as T\n}\n\n/**\n * Look up object metadata without reading object bytes.\n */\nexport function getObjectMeta(bundle: Bundle, objectId: ObjectId): ObjectMeta | null {\n return (\n prepare<[string], ObjectMeta>(\n bundle.db,\n `SELECT object_id, hash_alg, hash, size_bytes, compressed_size_bytes,\n compression, mime_type, encoding, storage_path, transport_hash, created_at\n FROM objects WHERE object_id = ?`,\n ).get(objectId) ?? null\n )\n}\n\n// -- Staging API for high-volume importers ---------------------------------\n//\n// Importers parse thousands of records per file and call putBytes/putJson per\n// record. Doing each as its own SQLite auto-commit + mkdir + writeFile is the\n// dominant cost on a fresh import. The staging API splits CAS work into:\n//\n// 1. stageBytes/stageJson/stageText — synchronous; computes the blake3 hash,\n// builds the ObjectId, and accumulates pending bytes in a per-batch Map\n// deduped by ObjectId. Returns the ObjectId immediately so the rest of\n// the importer can reference it.\n// 2. flushPendingObjects — async; runs once per batch. Bulk-checks which\n// ObjectIds already exist, writes the missing files in parallel, then\n// bulk-inserts the new `objects` rows in a single transaction.\n//\n// The shape lets importers keep their existing\n// `transactional(bundle.db, () => flushPending(...))` block as the only\n// SQLite write boundary for the file, with `flushPendingObjects` running just\n// before that (FS writes can't run inside a sync transaction).\n\n/**\n * Object staged for a high-volume importer flush.\n *\n * Bytes are the original uncompressed payload; compression and storage path are\n * decided once during `flushPendingObjects`.\n */\nexport interface StagedObject {\n objectId: ObjectId\n hash: string\n bytes: Buffer\n mimeType: string | null\n encoding: string | null\n}\n\n/**\n * Mutable per-import accumulator of staged CAS objects, deduped by object ID.\n */\nexport interface PendingObjects {\n byId: Map<ObjectId, StagedObject>\n}\n\n/**\n * Create an empty CAS staging accumulator.\n */\nexport function createPendingObjects(): PendingObjects {\n return { byId: new Map() }\n}\n\n/**\n * Stage bytes for later CAS persistence and return their object ID.\n *\n * This is synchronous and idempotent within the pending set; the first staged\n * metadata for a given object ID wins.\n */\nexport function stageBytes(pending: PendingObjects, bytes: Uint8Array, options: PutOptions = {}): ObjectId {\n const buf = Buffer.isBuffer(bytes) ? bytes : Buffer.from(bytes)\n const hash = blake3Hex(buf)\n const objectId = objectIdFromHash(hash)\n if (!pending.byId.has(objectId)) {\n pending.byId.set(objectId, {\n objectId,\n hash,\n bytes: buf,\n mimeType: options.mimeType ?? null,\n encoding: options.encoding ?? null,\n })\n }\n return objectId\n}\n\n/**\n * Stage UTF-8 text for later CAS persistence.\n */\nexport function stageText(pending: PendingObjects, text: string, options: { mimeType?: string } = {}): ObjectId {\n return stageBytes(pending, Buffer.from(text, 'utf8'), {\n mimeType: options.mimeType ?? 'text/plain; charset=utf-8',\n encoding: 'utf-8',\n })\n}\n\n/**\n * Stage a compact JSON representation for later CAS persistence.\n */\nexport function stageJson(pending: PendingObjects, value: unknown): ObjectId {\n return stageBytes(pending, Buffer.from(JSON.stringify(value), 'utf8'), {\n mimeType: 'application/json',\n encoding: 'utf-8',\n })\n}\n\n/**\n * Flush every staged object to disk and to the `objects` table.\n *\n * Writes happen before the caller's domain transaction starts because\n * better-sqlite3 transactions are synchronous and we want to overlap the\n * filesystem writes with each other. The `objects` rows are inserted with\n * INSERT OR IGNORE, so any rows another writer added between our existence\n * check and our insert are tolerated.\n */\nexport async function flushPendingObjects(bundle: Bundle, pending: PendingObjects): Promise<void> {\n if (pending.byId.size === 0) return\n\n const ids = [...pending.byId.keys()]\n const existingIds = queryExistingObjectIds(bundle, ids)\n\n // Compress once. The same buffer + path are reused for the FS write and\n // the `objects` row.\n /**\n * Fully prepared representation used for both filesystem and SQLite writes.\n */\n interface PreparedObject {\n staged: StagedObject\n compression: Compression\n compressedBytes: Buffer\n storagePath: string\n absolutePath: string\n }\n const toWrite: PreparedObject[] = []\n for (const obj of pending.byId.values()) {\n if (existingIds.has(obj.objectId)) continue\n const { bytes: compressedBytes, compression } = compressBytes(obj.bytes)\n const storagePath = objectStoragePath(obj.hash, compression)\n toWrite.push({\n staged: obj,\n compression,\n compressedBytes,\n storagePath,\n absolutePath: path.join(bundle.path, storagePath),\n })\n }\n\n if (toWrite.length > 0) {\n await writeFilesParallel(toWrite)\n }\n\n // Compute transport hashes in parallel using WASM before entering the sync\n // SQLite insert loop. Promise.all lets the WASM calls overlap.\n const transportHashes = await Promise.all(toWrite.map((p) => blake3HexAsync(p.compressedBytes)))\n\n const insertObject = prepare(\n bundle.db,\n `INSERT OR IGNORE INTO objects (\n object_id, hash_alg, hash, size_bytes, compressed_size_bytes,\n compression, mime_type, encoding, storage_path, transport_hash, created_at\n ) VALUES (?, 'blake3', ?, ?, ?, ?, ?, ?, ?, ?, ?)`,\n )\n const now = new Date().toISOString()\n for (const [i, p] of toWrite.entries()) {\n insertObject.run(\n p.staged.objectId,\n p.staged.hash,\n p.staged.bytes.byteLength,\n p.compression === 'zstd' ? p.compressedBytes.byteLength : null,\n p.compression,\n p.staged.mimeType,\n p.staged.encoding,\n p.storagePath,\n transportHashes[i],\n now,\n )\n }\n}\n\n/**\n * Query existing object IDs in chunks to stay below SQLite variable limits.\n */\nfunction queryExistingObjectIds(bundle: Bundle, ids: ObjectId[]): Set<ObjectId> {\n const found = new Set<ObjectId>()\n if (ids.length === 0) return found\n // SQLite's default SQLITE_LIMIT_VARIABLE_NUMBER is 32766; chunk well under\n // that for safety.\n const CHUNK = 500\n for (let start = 0; start < ids.length; start += CHUNK) {\n const slice = ids.slice(start, start + CHUNK)\n const placeholders = slice.map(() => '?').join(',')\n const rows = bundle.db\n .prepare<ObjectId[], { object_id: ObjectId }>(\n `SELECT object_id FROM objects WHERE object_id IN (${placeholders})`,\n )\n .all(...slice)\n for (const row of rows) found.add(row.object_id)\n }\n return found\n}\n\n/**\n * Maximum concurrent filesystem writes during staged CAS flushes.\n */\nconst FS_WRITE_CONCURRENCY = 16\n\n/**\n * Write compressed object payloads with bounded concurrency.\n *\n * Directory creation is cached via `ensureDir`; individual write failures\n * reject the whole flush.\n */\nasync function writeFilesParallel(tasks: { absolutePath: string; compressedBytes: Buffer }[]): Promise<void> {\n let cursor = 0\n const workers: Promise<void>[] = []\n const limit = Math.min(FS_WRITE_CONCURRENCY, tasks.length)\n for (let w = 0; w < limit; w++) {\n workers.push(\n (async () => {\n while (true) {\n const i = cursor++\n if (i >= tasks.length) return\n const task = tasks[i]!\n await ensureDir(path.dirname(task.absolutePath))\n await writeFile(task.absolutePath, task.compressedBytes)\n }\n })(),\n )\n }\n await Promise.all(workers)\n}\n","import { compress as zstdCompress, decompress as zstdDecompress } from 'zstd-napi'\n\n/**\n * Minimum payload size for zstd compression.\n *\n * Below this threshold the zstd frame overhead and CPU cost are not worth the\n * small storage savings.\n */\nconst COMPRESS_THRESHOLD_BYTES = 256\n\n/**\n * Conservative zstd level used for importer throughput.\n */\nconst ZSTD_LEVEL = 3\n\n/**\n * Stored object compression marker persisted in the `objects` table.\n */\nexport type Compression = 'zstd' | 'none'\n\n/**\n * Bytes plus the storage codec needed to recover them.\n */\nexport interface CompressionResult {\n bytes: Buffer\n compression: Compression\n}\n\n/**\n * Compress bytes when they are large enough to benefit.\n *\n * Returns a Buffer regardless of input type. Small payloads are copied and\n * tagged as `none` so reads can skip decompression.\n */\nexport function compressBytes(input: Uint8Array): CompressionResult {\n if (input.byteLength < COMPRESS_THRESHOLD_BYTES) {\n return { bytes: Buffer.from(input), compression: 'none' }\n }\n const out = zstdCompress(Buffer.from(input), { compressionLevel: ZSTD_LEVEL })\n return { bytes: out, compression: 'zstd' }\n}\n\n/**\n * Reverse `compressBytes` according to the persisted compression marker.\n */\nexport function decompressBytes(input: Buffer, compression: Compression): Buffer {\n if (compression === 'none') return input\n return zstdDecompress(input)\n}\n","import { createHash } from 'node:crypto'\nimport { blake3 as nobleBlake3 } from '@noble/hashes/blake3'\nimport { bytesToHex } from '@noble/hashes/utils'\nimport { blake3 as wasmBlake3 } from 'hash-wasm'\n\n/**\n * Hash bytes with BLAKE3 and return lowercase hex.\n *\n * Uses the pure-JS @noble/hashes implementation to remain synchronous.\n * Call sites that are already async should use blake3HexAsync instead for\n * better throughput via the WASM implementation.\n */\nexport function blake3Hex(bytes: Uint8Array): string {\n return bytesToHex(nobleBlake3(bytes))\n}\n\n/**\n * Hash bytes with BLAKE3 and return lowercase hex.\n *\n * Uses the hash-wasm WASM implementation for better throughput on large\n * payloads. Output is byte-identical to blake3Hex for the same input.\n * Prefer this in async call sites (putBytes, flushPendingObjects, etc.).\n */\nexport async function blake3HexAsync(bytes: Uint8Array): Promise<string> {\n return wasmBlake3(bytes)\n}\n\n/**\n * Hash bytes or text with SHA-256 and return lowercase hex.\n */\nexport function sha256Hex(bytes: Uint8Array | string): string {\n return createHash('sha256').update(bytes).digest('hex')\n}\n\n/** \"blake3:<hex>\" — the canonical object_id format in the schema. */\nexport function objectIdFromHash(hashHex: string): string {\n return `blake3:${hashHex}`\n}\n\n/**\n * Storage path under `objects/blake3/`: `ab/cd/<hash>.zst` to avoid one giant\n * directory. Uses the first 4 hex chars (2-level fanout).\n */\nexport function objectStoragePath(hashHex: string, compression: 'zstd' | 'none'): string {\n const ext = compression === 'zstd' ? '.zst' : '.bin'\n const a = hashHex.slice(0, 2)\n const b = hashHex.slice(2, 4)\n return `objects/blake3/${a}/${b}/${hashHex}${ext}`\n}\n","import { sha256Hex } from '../cas/hash.js'\n\n// Deterministic IDs let reimports converge on the same row instead of\n// duplicating. The shape is sha256 of a tuple of natural keys, hex-truncated\n// to 32 chars (128 bits). 128 bits is overkill for collision but makes IDs\n// short enough to grep without losing essentially zero safety.\n\n/**\n * Number of hash bytes retained for deterministic catalog IDs.\n */\nconst ID_PREFIX_BYTES = 16 // 128 bits => 32 hex chars\n\n/**\n * Build a deterministic fixed-width ID from natural-key tuple components.\n *\n * The NUL separator is outside normal path/session identifiers and avoids\n * ambiguous concatenations between differently shaped tuples.\n */\nfunction tupleId(parts: readonly string[]): string {\n // The separator avoids ambiguity between (\"a:b\",\"c\") and (\"a\",\"b:c\").\n return sha256Hex(parts.join('\u0000')).slice(0, ID_PREFIX_BYTES * 2)\n}\n\n/**\n * Deterministic ID for one preserved source-file version.\n *\n * The content hash is part of the key so modified files preserve historical\n * source rows instead of overwriting prior projections.\n */\nexport function sourceFileId(sourceTool: string, absolutePath: string, contentHash: string): string {\n // Includes contentHash so that a modified version of the same file gets a\n // new row instead of clashing with the previous import (which we keep around\n // for history / re-projection).\n return tupleId(['source_file', sourceTool, absolutePath, contentHash])\n}\n\n/**\n * Deterministic ID for a raw record recovered from a source file.\n *\n * `ordinal` may be null for single-record or pointer-addressed formats; it is\n * normalized to `-1` so the tuple remains stable.\n */\nexport function rawRecordId(sourceFileId: string, ordinal: number | null, rawObjectId: string): string {\n return tupleId(['raw_record', sourceFileId, String(ordinal ?? -1), rawObjectId])\n}\n\n/**\n * Deterministic ID for a logical session from a source tool.\n */\nexport function sessionId(sourceTool: string, sourceSessionId: string): string {\n return tupleId(['session', sourceTool, sourceSessionId])\n}\n\n/**\n * Deterministic ID for a turn within a session ordinal stream.\n */\nexport function turnId(sessionId: string, ordinal: number, sourceTurnId?: string | null): string {\n return tupleId(['turn', sessionId, String(ordinal), sourceTurnId ?? ''])\n}\n\n/**\n * Deterministic ID for an event when only session, ordinal, and kind are stable.\n */\nexport function eventId(sessionId: string, ordinal: number, kind: string): string {\n return tupleId(['event', sessionId, String(ordinal), kind])\n}\n\n/**\n * Deterministic ID for a message within a session ordinal stream.\n */\nexport function messageId(sessionId: string, ordinal: number, sourceMsgId?: string | null): string {\n return tupleId(['message', sessionId, String(ordinal), sourceMsgId ?? ''])\n}\n\n/**\n * Deterministic ID for a content block attached to a message or event.\n */\nexport function blockId(messageOrEventId: string, ordinal: number): string {\n return tupleId(['block', messageOrEventId, String(ordinal)])\n}\n\n/**\n * Deterministic ID for a tool call scoped by session and native call ID.\n */\nexport function toolCallId(sessionId: string, sourceCallId: string): string {\n return tupleId(['tool_call', sessionId, sourceCallId])\n}\n\n/**\n * Deterministic ID for a tool result scoped by session and native call ID.\n */\nexport function toolResultId(sessionId: string, sourceCallId: string): string {\n return tupleId(['tool_result', sessionId, sourceCallId])\n}\n\n/**\n * Deterministic ID for an artifact keyed by source tool and source-specific\n * artifact key. `sessionId` may be null for workspace-level artifacts.\n */\nexport function artifactId(sessionId: string | null, sourceTool: string, key: string): string {\n return tupleId(['artifact', sessionId ?? '', sourceTool, key])\n}\n\n/**\n * Deterministic ID for a source-tool project/workspace identity.\n */\nexport function projectId(sourceTool: string, sourceProjectId: string): string {\n return tupleId(['project', sourceTool, sourceProjectId])\n}\n\n/**\n * Import batch IDs are intentionally unique per run, not idempotent.\n *\n * `startedAtIso` keeps IDs sortable-ish while the random component avoids\n * collisions for concurrent or same-millisecond batch starts.\n */\nexport function importBatchId(sourceTool: string, startedAtIso: string): string {\n return tupleId(['import_batch', sourceTool, startedAtIso, String(Math.random())])\n}\n","import type { Bundle } from '../bundle.js'\nimport { type ObjectId, putJson } from '../cas/index.js'\nimport { prepare } from '../db.js'\nimport { importBatchId } from '../domain/ids.js'\nimport type { SourceTool } from '../domain/types.js'\nimport { PROSA_PARSER_VERSION } from '../version.js'\n\n/**\n * In-memory representation of an `import_batches` row while a compile/import\n * run is active.\n *\n * `finished_at` is populated only after `finishBatch` persists terminal status.\n */\nexport interface ImportBatch {\n /** Stable batch identifier derived from source and start time. */\n batch_id: string\n /** Source importer for this batch, or null for multi-source orchestration. */\n source_tool: SourceTool | null\n /** Parser version that produced this batch. */\n parser_version: string\n /** Source roots or files covered by the batch. */\n paths: string[]\n /** ISO timestamp when the batch was created. */\n started_at: string\n /** ISO timestamp set after terminal status is persisted. */\n finished_at?: string\n}\n\n/**\n * Per-batch counters serialized into `import_batches.counts_json`.\n *\n * Counts describe importer work, not necessarily net-new durable rows; skipped\n * source files and idempotent inserts are tracked explicitly.\n */\nexport interface ImportCounts {\n /** Source files discovered by the importer. */\n source_files_seen: number\n /** Source files parsed and imported. */\n source_files_imported: number\n /** Source files skipped by idempotency checks. */\n source_files_skipped: number\n /** Raw source records preserved. */\n raw_records: number\n /** Session rows inserted or updated. */\n sessions: number\n /** Turn rows inserted or updated. */\n turns: number\n /** Timeline event rows inserted or updated. */\n events: number\n /** Message rows inserted or updated. */\n messages: number\n /** Content block rows inserted or updated. */\n content_blocks: number\n /** Tool call rows inserted or updated. */\n tool_calls: number\n /** Tool result rows inserted or updated. */\n tool_results: number\n /** Artifact rows inserted or updated. */\n artifacts: number\n /** Edge rows inserted or updated. */\n edges: number\n /** Import errors recorded for the batch. */\n errors: number\n}\n\n/**\n * Create a zeroed counter object for a new import batch.\n */\nexport function emptyCounts(): ImportCounts {\n return {\n source_files_seen: 0,\n source_files_imported: 0,\n source_files_skipped: 0,\n raw_records: 0,\n sessions: 0,\n turns: 0,\n events: 0,\n messages: 0,\n content_blocks: 0,\n tool_calls: 0,\n tool_results: 0,\n artifacts: 0,\n edges: 0,\n errors: 0,\n }\n}\n\n/**\n * Insert a running import batch and return its process-local handle.\n *\n * Batch IDs are intentionally unique per run so repeated compiles preserve\n * their own audit trail even when all source rows are skipped idempotently.\n */\nexport function startBatch(bundle: Bundle, sourceTool: SourceTool | null, paths: string[]): ImportBatch {\n const startedAt = new Date().toISOString()\n const id = importBatchId(sourceTool ?? 'all', startedAt)\n prepare(\n bundle.db,\n `INSERT INTO import_batches (\n batch_id, parser_version, source_tool, paths, started_at, status\n ) VALUES (?, ?, ?, ?, ?, 'running')`,\n ).run(id, PROSA_PARSER_VERSION, sourceTool, JSON.stringify(paths), startedAt)\n\n return {\n batch_id: id,\n source_tool: sourceTool,\n parser_version: PROSA_PARSER_VERSION,\n paths,\n started_at: startedAt,\n }\n}\n\n/**\n * Mark an import batch completed or failed and persist final counts.\n */\nexport function finishBatch(\n bundle: Bundle,\n batch: ImportBatch,\n counts: ImportCounts,\n status: 'completed' | 'failed',\n): void {\n prepare(\n bundle.db,\n `UPDATE import_batches\n SET finished_at = ?, status = ?, counts_json = ?\n WHERE batch_id = ?`,\n ).run(new Date().toISOString(), status, JSON.stringify(counts), batch.batch_id)\n}\n\n/**\n * Record an importer error tied to an optional source file or raw record.\n *\n * Non-string payloads are preserved in the CAS as JSON and referenced from the\n * error row; this keeps diagnostic detail out of inline SQLite columns while\n * preserving it for later inspection.\n */\nexport async function recordError(\n bundle: Bundle,\n batchId: string,\n args: {\n sourceFileId?: string | null\n rawRecordId?: string | null\n kind: string\n message: string\n payload?: unknown\n },\n): Promise<void> {\n let payloadObjectId: ObjectId | null = null\n if (args.payload !== undefined) {\n payloadObjectId = await putJson(bundle, args.payload)\n }\n prepare(\n bundle.db,\n `INSERT INTO import_errors (\n batch_id, source_file_id, raw_record_id, kind, message,\n payload_object_id, occurred_at\n ) VALUES (?, ?, ?, ?, ?, ?, ?)`,\n ).run(\n batchId,\n args.sourceFileId ?? null,\n args.rawRecordId ?? null,\n args.kind,\n args.message,\n payloadObjectId,\n new Date().toISOString(),\n )\n}\n","import { access, readFile, stat, writeFile } from 'node:fs/promises'\nimport path from 'node:path'\nimport type { Bundle } from '../bundle.js'\nimport { compressBytes } from '../cas/compress.js'\nimport { blake3HexAsync, objectIdFromHash, sha256Hex } from '../cas/hash.js'\nimport { ensureDir } from '../cas/index.js'\nimport { prepare } from '../db.js'\nimport { sourceFileId } from '../domain/ids.js'\nimport type { SourceTool } from '../domain/types.js'\n\n/**\n * Complete `source_files` row used by source discovery and importer idempotency.\n *\n * Paths are absolute source paths. `object_id` points at preserved raw source\n * bytes and may be backfilled for rows created before raw preservation existed.\n */\nexport interface SourceFileRow {\n /** Stable source file identifier. */\n source_file_id: string\n /** Importer that discovered the file. */\n source_tool: SourceTool\n /** Absolute path to the native source file. */\n path: string\n /** Importer-specific file kind. */\n file_kind: string\n /** File size observed during discovery. */\n size_bytes: number\n /** Filesystem modification time as ISO text, when available. */\n mtime: string | null\n /** SHA-256 content hash used for idempotency. */\n content_hash: string\n /** CAS object ID for preserved raw bytes, if available. */\n object_id: string | null\n /** ISO timestamp when the file was first registered. */\n discovered_at: string\n /** Optional project/workspace hint derived during discovery. */\n workspace_hint: string | null\n}\n\n/**\n * Result of source-file registration.\n *\n * `alreadyKnown` means the same path/content tuple was already registered and\n * the caller can usually skip parsing/importing the file.\n */\nexport interface RegisterResult {\n /** Registered source file row. */\n row: SourceFileRow\n /** True when the caller can usually skip parsing the file. */\n alreadyKnown: boolean\n}\n\n/**\n * Idempotent registration of a source file. The natural key is\n * (source_tool, path, size, mtime, content_hash). If a row with the same\n * tuple already exists we return it untouched and the caller can skip\n * re-importing. Otherwise we insert a new row.\n *\n * This is the cheapest form of idempotency: re-running `prosa compile` over\n * the same Codex tree is a no-op (no rehash unless the file changed).\n */\nexport async function registerSourceFile(\n bundle: Bundle,\n args: {\n sourceTool: SourceTool\n absolutePath: string\n fileKind: string\n workspaceHint?: string | null\n },\n): Promise<RegisterResult> {\n const st = await stat(args.absolutePath)\n const size = st.size\n const mtime = st.mtime.toISOString()\n\n // Hash on demand. We could memoize per (path,size,mtime) but the cheap\n // pre-check below already covers the common case.\n const cheap = prepare<[SourceTool, string, number, string], SourceFileRow>(\n bundle.db,\n `SELECT source_file_id, source_tool, path, file_kind, size_bytes, mtime,\n content_hash, object_id, discovered_at, workspace_hint\n FROM source_files\n WHERE source_tool = ? AND path = ? AND size_bytes = ? AND mtime = ?\n LIMIT 1`,\n ).get(args.sourceTool, args.absolutePath, size, mtime)\n\n if (cheap) {\n return {\n row: await ensureSourceFilePreserved(bundle, cheap, args.absolutePath),\n alreadyKnown: true,\n }\n }\n\n const buf = await readFile(args.absolutePath)\n const contentHash = sha256Hex(buf)\n\n // Slow path: same content under same path was perhaps re-saved with new\n // mtime; honor the (tool,path,size,mtime,hash) UNIQUE constraint.\n const exact = prepare<[SourceTool, string, string], SourceFileRow>(\n bundle.db,\n `SELECT source_file_id, source_tool, path, file_kind, size_bytes, mtime,\n content_hash, object_id, discovered_at, workspace_hint\n FROM source_files\n WHERE source_tool = ? AND path = ? AND content_hash = ?\n LIMIT 1`,\n ).get(args.sourceTool, args.absolutePath, contentHash)\n\n if (exact) {\n return {\n row: await ensureSourceFilePreserved(bundle, exact, args.absolutePath, buf),\n alreadyKnown: true,\n }\n }\n\n const objectId = await preserveRawSourceBytes(bundle, buf)\n\n const id = sourceFileId(args.sourceTool, args.absolutePath, contentHash)\n const row: SourceFileRow = {\n source_file_id: id,\n source_tool: args.sourceTool,\n path: args.absolutePath,\n file_kind: args.fileKind,\n size_bytes: size,\n mtime,\n content_hash: contentHash,\n object_id: objectId,\n discovered_at: new Date().toISOString(),\n workspace_hint: args.workspaceHint ?? null,\n }\n\n prepare(\n bundle.db,\n `INSERT INTO source_files (\n source_file_id, source_tool, path, file_kind, size_bytes, mtime,\n content_hash, object_id, discovered_at, workspace_hint\n ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,\n ).run(\n row.source_file_id,\n row.source_tool,\n row.path,\n row.file_kind,\n row.size_bytes,\n row.mtime,\n row.content_hash,\n row.object_id,\n row.discovered_at,\n row.workspace_hint,\n )\n\n return { row, alreadyKnown: false }\n}\n\n/**\n * Backfill raw-byte preservation for an existing `source_files` row.\n *\n * Older rows or cheap-path matches may not have `object_id`; this helper stores\n * the current source bytes and updates the row before returning it.\n */\nasync function ensureSourceFilePreserved(\n bundle: Bundle,\n row: SourceFileRow,\n absolutePath: string,\n bytes?: Buffer,\n): Promise<SourceFileRow> {\n if (row.object_id) return row\n\n const sourceBytes = bytes ?? (await readFile(absolutePath))\n const objectId = await preserveRawSourceBytes(bundle, sourceBytes)\n\n prepare<[string, string]>(bundle.db, `UPDATE source_files SET object_id = ? WHERE source_file_id = ?`).run(\n objectId,\n row.source_file_id,\n )\n\n return { ...row, object_id: objectId }\n}\n\n/**\n * Preserve raw source bytes outside the main CAS fanout and record them in\n * `objects`.\n *\n * The storage path is `raw/sources/<blake3>.<ext>` so original input files are\n * easy to distinguish from normalized payloads under `objects/blake3`. The DB\n * insert is idempotent, and the file write is skipped if the object already\n * exists on disk.\n */\nasync function preserveRawSourceBytes(bundle: Bundle, bytes: Uint8Array): Promise<string> {\n const hash = await blake3HexAsync(bytes)\n const objectId = objectIdFromHash(hash)\n const { bytes: stored, compression } = compressBytes(bytes)\n const storagePath = rawSourceStoragePath(hash, compression)\n const absolutePath = path.join(bundle.path, storagePath)\n\n await ensureDir(path.dirname(absolutePath))\n if (!(await fileExists(absolutePath))) {\n await writeFile(absolutePath, stored)\n }\n\n const existing = prepare<[string], { object_id: string }>(\n bundle.db,\n `SELECT object_id FROM objects WHERE object_id = ?`,\n ).get(objectId)\n\n if (!existing) {\n prepare(\n bundle.db,\n `INSERT INTO objects (\n object_id, hash_alg, hash, size_bytes, compressed_size_bytes,\n compression, mime_type, encoding, storage_path, transport_hash, created_at\n ) VALUES (?, 'blake3', ?, ?, ?, ?, ?, ?, ?, ?, ?)`,\n ).run(\n objectId,\n hash,\n bytes.byteLength,\n compression === 'zstd' ? stored.byteLength : null,\n compression,\n 'application/octet-stream',\n null,\n storagePath,\n await blake3HexAsync(stored),\n new Date().toISOString(),\n )\n }\n\n return objectId\n}\n\n/**\n * Relative bundle path for preserved raw source bytes.\n */\nfunction rawSourceStoragePath(hashHex: string, compression: 'zstd' | 'none'): string {\n const ext = compression === 'zstd' ? '.zst' : '.bin'\n return `raw/sources/${hashHex}${ext}`\n}\n\nasync function fileExists(filePath: string): Promise<boolean> {\n try {\n await access(filePath)\n return true\n } catch {\n return false\n }\n}\n","/**\n * Bounds and default for CLI/API limit values.\n */\nexport interface ClampLimitOptions {\n min?: number\n max: number\n fallback: number\n}\n\n/**\n * Clamp a possibly-missing numeric limit into an inclusive range.\n *\n * Undefined values resolve to `fallback`; omitted `min` defaults to 1 so\n * callers do not accidentally request empty or unbounded result sets.\n */\nexport function clampLimit(value: number | undefined, opts: ClampLimitOptions): number {\n return Math.max(opts.min ?? 1, Math.min(opts.max, value ?? opts.fallback))\n}\n","import type { Bundle } from '../core/bundle.js'\nimport type { Confidence, SourceTool } from '../core/domain/types.js'\nimport { clampLimit } from '../core/limits.js'\n\n/** Filters applied consistently to session list and count queries. */\nexport interface SessionListFilters {\n /** Restrict results to one source tool. */\n sourceTool?: SourceTool\n /** Inclusive lower bound for `start_ts`; unknown timestamps are retained. */\n sinceIso?: string\n /** Exclusive upper bound for `start_ts`; unknown timestamps are retained. */\n untilIso?: string\n /** Maximum rows to return, clamped by service limits. */\n limit?: number\n}\n\n/** Summary row returned by session listing surfaces. */\nexport interface SessionRow {\n /** Canonical prosa session identifier. */\n session_id: string\n /** Source tool that produced the session. */\n source_tool: SourceTool\n /** Native source session identifier. */\n source_session_id: string\n /** Canonical project identifier this session belongs to, when one was recovered. */\n project_id: string | null\n /** Parent session for subagent sessions. */\n parent_session_id: string | null\n /** SQLite boolean indicating whether this is a subagent session. */\n is_subagent: 0 | 1\n /** Best recovered title. */\n title: string | null\n /** Earliest recovered timestamp. */\n start_ts: string | null\n /** Latest recovered timestamp. */\n end_ts: string | null\n /** Initial working directory. */\n cwd_initial: string | null\n /** Initial git branch. */\n git_branch_initial: string | null\n /** First observed model. */\n model_first: string | null\n /** Last observed model. */\n model_last: string | null\n /** Source or importer status. */\n status: string | null\n /** Confidence in recovered timeline ordering. */\n timeline_confidence: Confidence\n /** Number of messages attached to the session. */\n message_count: number\n /** Number of tool calls attached to the session. */\n tool_call_count: number\n}\n\n/** Builds the shared WHERE clause so list and count stay filter-equivalent. */\nfunction sessionFilterWhere(filters: SessionListFilters): { where: string; params: unknown[] } {\n const conds: string[] = []\n const params: unknown[] = []\n\n if (filters.sourceTool) {\n conds.push('s.source_tool = ?')\n params.push(filters.sourceTool)\n }\n if (filters.sinceIso) {\n conds.push('(s.start_ts IS NULL OR s.start_ts >= ?)')\n params.push(filters.sinceIso)\n }\n if (filters.untilIso) {\n conds.push('(s.start_ts IS NULL OR s.start_ts < ?)')\n params.push(filters.untilIso)\n }\n\n return {\n where: conds.length ? `WHERE ${conds.join(' AND ')}` : '',\n params,\n }\n}\n\n/** Lists sessions newest-first, preserving rows with unknown timestamps at the end. */\nexport function listSessions(bundle: Bundle, filters: SessionListFilters = {}): SessionRow[] {\n const { where, params } = sessionFilterWhere(filters)\n const limit = clampLimit(filters.limit, { max: 1000, fallback: 50 })\n\n const sql = `\n SELECT s.session_id,\n s.source_tool,\n s.source_session_id,\n s.project_id,\n s.parent_session_id,\n s.is_subagent,\n s.title,\n s.start_ts,\n s.end_ts,\n s.cwd_initial,\n s.git_branch_initial,\n s.model_first,\n s.model_last,\n s.status,\n s.timeline_confidence,\n (SELECT count(*) FROM messages m WHERE m.session_id = s.session_id) AS message_count,\n (SELECT count(*) FROM tool_calls tc WHERE tc.session_id = s.session_id) AS tool_call_count\n FROM sessions s\n ${where}\n ORDER BY s.start_ts DESC NULLS LAST\n LIMIT ${limit}\n `\n\n return bundle.db.prepare(sql).all(...params) as SessionRow[]\n}\n\n/** Counts sessions using the same filter policy as {@link listSessions}. */\nexport function countSessions(bundle: Bundle, filters: SessionListFilters = {}): number {\n const { where, params } = sessionFilterWhere(filters)\n const row = bundle.db\n .prepare(\n `\n SELECT count(*) AS count\n FROM sessions s\n ${where}\n `,\n )\n .get(...params) as { count: number } | undefined\n\n return row?.count ?? 0\n}\n\n/** Timeline event row used by session detail views. */\nexport interface SessionDetailEvent {\n /** Timeline ordinal within the session. */\n ordinal: number\n /** Event timestamp when known. */\n timestamp: string | null\n /** Canonical event type. */\n event_type: string\n /** Native source event type, when retained. */\n source_type: string | null\n /** Source-specific event subtype. */\n subtype: string | null\n /** Actor associated with the event. */\n actor: string | null\n /** Message row attached to the event. */\n message_id: string | null\n /** Message role attached to the event. */\n role: string | null\n /** Tool name attached to the event. */\n tool_name: string | null\n /** SQLite boolean indicating a failed tool result. */\n is_error: 0 | 1 | null\n /** Human-sized preview for detail rendering. */\n preview: string | null\n}\n\n/** Full session detail with summary metadata and ordered timeline events. */\nexport interface SessionDetail {\n /** Session summary row. */\n session: SessionRow\n /** Ordered timeline events. */\n events: SessionDetailEvent[]\n}\n\n/** Returns a single session with its event timeline, or null when absent. */\nexport function getSession(bundle: Bundle, sessionId: string): SessionDetail | null {\n const rows = listSessions(bundle) // small query reused for shape\n const row = bundle.db\n .prepare<[string], SessionRow>(\n `SELECT s.session_id, s.source_tool, s.source_session_id, s.project_id,\n s.parent_session_id, s.is_subagent, s.title, s.start_ts, s.end_ts,\n s.cwd_initial, s.git_branch_initial, s.model_first, s.model_last,\n s.status, s.timeline_confidence,\n (SELECT count(*) FROM messages m WHERE m.session_id = s.session_id) AS message_count,\n (SELECT count(*) FROM tool_calls tc WHERE tc.session_id = s.session_id) AS tool_call_count\n FROM sessions s\n WHERE s.session_id = ?`,\n )\n .get(sessionId)\n void rows\n if (!row) return null\n\n const events = bundle.db\n .prepare<[string], SessionDetailEvent>(\n `SELECT e.ordinal,\n e.timestamp,\n e.event_type,\n e.source_type,\n e.subtype,\n e.actor,\n m.message_id,\n m.role,\n tc.tool_name,\n tr.is_error,\n tr.preview\n FROM events e\n LEFT JOIN messages m ON m.event_id = e.event_id\n LEFT JOIN tool_calls tc ON tc.event_id = e.event_id\n LEFT JOIN tool_results tr ON tr.event_id = e.event_id\n WHERE e.session_id = ?\n ORDER BY e.ordinal`,\n )\n .all(sessionId)\n\n return { session: row, events }\n}\n","import { existsSync } from 'node:fs'\nimport { createRequire } from 'node:module'\nimport type { Bundle } from '../core/bundle.js'\nimport { getErrorMessage } from '../core/errors.js'\nimport { clampLimit } from '../core/limits.js'\nimport { type SearchEngine, getSearchIndexStatus } from './indexing.js'\n\nconst require = createRequire(import.meta.url)\n\n/** Search result projected from either FTS5 or Tantivy into the common service shape. */\nexport interface SearchHit {\n /** Search document identifier. */\n doc_id: string\n /** Indexed entity kind. */\n entity_type: string\n /** Identifier of the indexed entity. */\n entity_id: string\n /** Session that owns the document, when applicable. */\n session_id: string | null\n /** Timestamp used for result ordering. */\n timestamp: string | null\n /** Message role associated with the document. */\n role: string | null\n /** Tool name associated with the document. */\n tool_name: string | null\n /** Indexed text field category. */\n field_kind: string\n /** Highlighted or truncated result snippet. */\n snippet: string\n}\n\n/** Options for full-text search across indexed conversation and tool evidence. */\nexport interface SearchOptions {\n /** Query text, interpreted by the selected engine. */\n query: string\n /** Maximum hit count, clamped by service limits. */\n limit?: number\n /** Search backend to query; defaults to FTS5. */\n engine?: SearchEngine\n /**\n * When true, pass `query` straight to FTS5 (MATCH expression). When false\n * (default), each whitespace-delimited token is wrapped in double quotes so\n * punctuation like `package.json` doesn't trip the FTS5 parser. Set true if\n * you want to use FTS5 operators like `OR`, `NEAR`, prefixes, etc.\n */\n raw?: boolean\n}\n\n/**\n * Wrap each whitespace-delimited token in double quotes so the FTS5 parser\n * treats them as phrases. This avoids syntax errors on punctuation that the\n * unicode61 tokenizer splits on (dots, slashes, hyphens, etc.) while still\n * AND-matching across tokens.\n */\nfunction escapeFtsQuery(q: string): string {\n return q\n .split(/\\s+/)\n .filter((t) => t.length > 0)\n .map((t) => `\"${t.replace(/\"/g, '\"\"')}\"`)\n .join(' ')\n}\n\n/** Runs full-text search with FTS5 by default, or Tantivy when requested. */\nexport function searchFullText(bundle: Bundle, options: SearchOptions): SearchHit[] {\n if (options.engine === 'tantivy') {\n return searchTantivy(bundle, options)\n }\n\n const limit = clampLimit(options.limit, { max: 500, fallback: 50 })\n const sql = `\n SELECT d.doc_id,\n d.entity_type,\n d.entity_id,\n d.session_id,\n d.timestamp,\n d.role,\n d.tool_name,\n d.field_kind,\n snippet(search_docs_fts, 0, '⟪', '⟫', '…', 12) AS snippet\n FROM search_docs_fts\n JOIN search_docs d ON d.rowid = search_docs_fts.rowid\n WHERE search_docs_fts MATCH ?\n ORDER BY bm25(search_docs_fts), d.timestamp DESC\n LIMIT ${limit}\n `\n const ftsQuery = options.raw ? options.query : escapeFtsQuery(options.query)\n if (!ftsQuery) return []\n return bundle.db.prepare(sql).all(ftsQuery) as SearchHit[]\n}\n\n/** Searches the Tantivy sidecar and maps stored fields back to {@link SearchHit}. */\nfunction searchTantivy(bundle: Bundle, options: SearchOptions): SearchHit[] {\n if (!existsSync(bundle.paths.tantivy)) {\n throw new Error('tantivy index not found; run `prosa index tantivy` first')\n }\n\n const status = getSearchIndexStatus(bundle, 'tantivy')\n if (status?.status !== 'ready') {\n throw new Error(`tantivy index is ${status?.status ?? 'missing'}; run \\`prosa index tantivy\\` first`)\n }\n\n const limit = clampLimit(options.limit, { max: 500, fallback: 50 })\n const queryText = options.query.trim()\n if (!queryText) return []\n\n const tantivy = requireTantivy()\n const index = tantivy.Index.open(bundle.paths.tantivy)\n const searcher = index.searcher()\n const [query] = options.raw\n ? [index.parseQuery(queryText, ['text'])]\n : index.parseQueryLenient(queryText, ['text'], undefined, {\n text: [true, 2, true],\n })\n const result = searcher.search(query, limit, true)\n const snippets = tantivy.SnippetGenerator.create(searcher, query, index.schema, 'text')\n snippets.setMaxNumChars(180)\n\n return result.hits.map((hit: TantivySearchHit) => {\n const doc = searcher.doc(hit.docAddress)\n const snippet = snippets.snippetFromDoc(doc)\n const text = getStoredText(doc, 'text')\n const renderedSnippet = snippet.fragment()\n ? highlightSnippet(snippet.fragment(), snippet.highlighted())\n : text.slice(0, 180)\n return {\n doc_id: getStoredText(doc, 'doc_id'),\n entity_type: getStoredText(doc, 'entity_type'),\n entity_id: getStoredText(doc, 'entity_id'),\n session_id: nullIfEmpty(getStoredText(doc, 'session_id')),\n timestamp: nullIfEmpty(getStoredText(doc, 'timestamp')),\n role: nullIfEmpty(getStoredText(doc, 'role')),\n tool_name: nullIfEmpty(getStoredText(doc, 'tool_name')),\n field_kind: getStoredText(doc, 'field_kind'),\n snippet: renderedSnippet,\n }\n })\n}\n\ntype TantivyModule = typeof import('@oxdev03/node-tantivy-binding')\ntype TantivyDocument = InstanceType<TantivyModule['Document']>\ntype TantivySearchHit = import('@oxdev03/node-tantivy-binding').SearchHit\n\n/** Loads the optional Tantivy binding and normalizes missing-module failures. */\nfunction requireTantivy(): TantivyModule {\n try {\n return require('@oxdev03/node-tantivy-binding') as TantivyModule\n } catch (error) {\n throw new Error(`tantivy engine is unavailable: ${getErrorMessage(error)}`)\n }\n}\n\n/** Reads a stored Tantivy text field across scalar and array binding shapes. */\nfunction getStoredText(doc: TantivyDocument, field: string): string {\n const value = doc.getFirst(field)\n if (typeof value === 'string') return value\n if (Array.isArray(value) && typeof value[0] === 'string') return value[0]\n if (value == null) return ''\n return String(value)\n}\n\n/** Converts Tantivy's empty-string null sentinel back to service-level null. */\nfunction nullIfEmpty(value: string): string | null {\n return value.length > 0 ? value : null\n}\n\n/** Renders Tantivy highlight byte ranges with the same markers used by FTS5 snippets. */\nfunction highlightSnippet(fragment: string, ranges: Array<{ start: number; end: number }>): string {\n if (ranges.length === 0) return fragment\n\n let out = ''\n let cursor = 0\n for (const range of ranges) {\n out += fragment.slice(cursor, range.start)\n out += `⟪${fragment.slice(range.start, range.end)}⟫`\n cursor = range.end\n }\n out += fragment.slice(cursor)\n return out\n}\n","/**\n * Convert unknown caught values into a display/log-safe message string.\n */\nexport const getErrorMessage = (err: unknown): string => (err instanceof Error ? err.message : String(err))\n","import { createHash } from 'node:crypto'\nimport { existsSync } from 'node:fs'\nimport { mkdir, rm, writeFile } from 'node:fs/promises'\nimport path from 'node:path'\nimport type { Bundle } from '../core/bundle.js'\nimport { prepare, transactional } from '../core/db.js'\nimport { getErrorMessage } from '../core/errors.js'\n\n/** Supported search backends tracked by the bundle. */\nexport type SearchEngine = 'fts5' | 'tantivy'\n\n/** Persisted status row for a search index sidecar. */\nexport interface SearchIndexStatus {\n /** Search backend represented by this status row. */\n engine: SearchEngine\n /** Current index lifecycle state. */\n status: 'missing' | 'ready' | 'stale' | 'building' | 'failed'\n /** Number of canonical search_docs rows available to index. */\n source_doc_count: number\n /** Number of documents known to be present in the index. */\n indexed_doc_count: number\n /** ISO timestamp for the last status update. */\n updated_at: string\n /** Last build error message, if the index failed. */\n error_message: string | null\n /** Last indexed SQLite rowid for incremental sidecars. */\n last_indexed_rowid: number | null\n /** Schema fingerprint used to decide whether incremental rebuild is valid. */\n schema_fingerprint: string | null\n}\n\n/** Canonical search document row used to feed external indexes. */\ninterface SearchDocRow {\n rowid: number\n doc_id: string\n entity_type: string\n entity_id: string\n session_id: string | null\n project_id: string | null\n timestamp: string | null\n role: string | null\n tool_name: string | null\n canonical_tool_type: string | null\n field_kind: string\n text: string\n}\n\n/** Shared projection for search index status queries. */\nconst SEARCH_INDEX_STATUS_COLUMNS = `\n engine, status, source_doc_count, indexed_doc_count, updated_at,\n error_message, last_indexed_rowid, schema_fingerprint\n`\n\n/** Triggers that keep the SQLite FTS5 virtual table synchronized with search_docs. */\nconst FTS5_TRIGGER_SQL = `\nCREATE TRIGGER IF NOT EXISTS search_docs_ai AFTER INSERT ON search_docs BEGIN\n INSERT INTO search_docs_fts(rowid, text, role, tool_name, field_kind)\n VALUES (new.rowid, new.text, new.role, new.tool_name, new.field_kind);\nEND;\n\nCREATE TRIGGER IF NOT EXISTS search_docs_ad AFTER DELETE ON search_docs BEGIN\n INSERT INTO search_docs_fts(search_docs_fts, rowid, text, role, tool_name, field_kind)\n VALUES('delete', old.rowid, old.text, old.role, old.tool_name, old.field_kind);\nEND;\n\nCREATE TRIGGER IF NOT EXISTS search_docs_au AFTER UPDATE ON search_docs BEGIN\n INSERT INTO search_docs_fts(search_docs_fts, rowid, text, role, tool_name, field_kind)\n VALUES('delete', old.rowid, old.text, old.role, old.tool_name, old.field_kind);\n INSERT INTO search_docs_fts(rowid, text, role, tool_name, field_kind)\n VALUES (new.rowid, new.text, new.role, new.tool_name, new.field_kind);\nEND;\n`\n\n/** Enables incremental FTS5 maintenance after bulk rebuilds or imports. */\nexport function enableFts5Triggers(bundle: Bundle): void {\n bundle.db.exec(FTS5_TRIGGER_SQL)\n}\n\n/** Disables FTS5 maintenance triggers while import code performs bulk writes. */\nexport function disableFts5Triggers(bundle: Bundle): void {\n bundle.db.exec(`\n DROP TRIGGER IF EXISTS search_docs_ai;\n DROP TRIGGER IF EXISTS search_docs_ad;\n DROP TRIGGER IF EXISTS search_docs_au;\n `)\n}\n\n/** Returns status rows for all known search engines, creating defaults if absent. */\nexport function getSearchIndexStatuses(bundle: Bundle): SearchIndexStatus[] {\n ensureSearchIndexStatusRows(bundle)\n return bundle.db\n .prepare<[], SearchIndexStatus>(\n `SELECT ${SEARCH_INDEX_STATUS_COLUMNS}\n FROM search_index_status\n ORDER BY engine`,\n )\n .all()\n}\n\n/** Returns the status row for one search engine, or null only if initialization failed. */\nexport function getSearchIndexStatus(bundle: Bundle, engine: SearchEngine): SearchIndexStatus | null {\n ensureSearchIndexStatusRows(bundle)\n return (\n bundle.db\n .prepare<[SearchEngine], SearchIndexStatus>(\n `SELECT ${SEARCH_INDEX_STATUS_COLUMNS}\n FROM search_index_status\n WHERE engine = ?`,\n )\n .get(engine) ?? null\n )\n}\n\n/** Marks derived search indexes stale after canonical search_docs changed. */\nexport function markIndexesAfterImport(bundle: Bundle, options: { changed: boolean }): void {\n if (!options.changed) return\n\n const tantivy = getSearchIndexStatus(bundle, 'tantivy')\n if (tantivy?.status === 'ready' || tantivy?.status === 'stale' || tantivy?.status === 'failed') {\n updateSearchIndexStatus(bundle, 'tantivy', {\n status: 'stale',\n sourceDocCount: countSearchDocs(bundle),\n indexedDocCount: tantivy.indexed_doc_count,\n errorMessage: null,\n })\n }\n}\n\n/** Fully rebuilds the SQLite FTS5 index from search_docs and records status. */\nexport function rebuildFts5Index(bundle: Bundle): SearchIndexStatus {\n ensureSearchIndexStatusRows(bundle)\n updateSearchIndexStatus(bundle, 'fts5', {\n status: 'building',\n sourceDocCount: countSearchDocs(bundle),\n indexedDocCount: countFts5Docs(bundle),\n errorMessage: null,\n })\n\n try {\n transactional(bundle.db, () => {\n enableFts5Triggers(bundle)\n bundle.db.exec(`INSERT INTO search_docs_fts(search_docs_fts) VALUES('rebuild')`)\n })\n updateSearchIndexStatus(bundle, 'fts5', {\n status: 'ready',\n sourceDocCount: countSearchDocs(bundle),\n indexedDocCount: countFts5Docs(bundle),\n errorMessage: null,\n })\n } catch (error) {\n updateSearchIndexStatus(bundle, 'fts5', {\n status: 'failed',\n sourceDocCount: countSearchDocs(bundle),\n indexedDocCount: countFts5Docs(bundle),\n errorMessage: getErrorMessage(error),\n })\n throw error\n }\n\n return getSearchIndexStatus(bundle, 'fts5') as SearchIndexStatus\n}\n\n/** Options controlling Tantivy sidecar rebuild behavior. */\nexport interface RebuildTantivyOptions {\n /**\n * Force a full re-index even when an incremental run would be valid.\n * Surfaced by the `--overwrite` flag on `prosa index tantivy` and on\n * `prosa compile`.\n */\n overwrite?: boolean\n}\n\ntype TantivyModule = typeof import('@oxdev03/node-tantivy-binding')\n\n/** Stored Tantivy schema field used for schema fingerprinting and indexing. */\ninterface TantivySchemaField {\n name: string\n tokenizer: string\n}\n\n/**\n * Ordered list of fields stored on every Tantivy document.\n *\n * The order is load-bearing: the schema fingerprint hashes this list verbatim,\n * so changing the order forces a full rebuild on existing bundles.\n */\nconst TANTIVY_SCHEMA_FIELDS: readonly TantivySchemaField[] = [\n { name: 'doc_id', tokenizer: 'raw' },\n { name: 'entity_type', tokenizer: 'raw' },\n { name: 'entity_id', tokenizer: 'raw' },\n { name: 'session_id', tokenizer: 'raw' },\n { name: 'project_id', tokenizer: 'raw' },\n { name: 'timestamp', tokenizer: 'raw' },\n { name: 'role', tokenizer: 'raw' },\n { name: 'tool_name', tokenizer: 'raw' },\n { name: 'canonical_tool_type', tokenizer: 'raw' },\n { name: 'field_kind', tokenizer: 'raw' },\n // The text field uses Tantivy's default tokenizer (en_stem in the binding).\n { name: 'text', tokenizer: 'default' },\n]\n\n/** Builds the Tantivy schema from the fingerprinted field policy. */\nfunction buildTantivySchema(tantivy: TantivyModule): InstanceType<TantivyModule['Schema']> {\n const builder = new tantivy.SchemaBuilder()\n for (const field of TANTIVY_SCHEMA_FIELDS) {\n if (field.tokenizer === 'default') {\n builder.addTextField(field.name, { stored: true })\n } else {\n builder.addTextField(field.name, { stored: true, tokenizerName: field.tokenizer })\n }\n }\n return builder.build()\n}\n\n/** Returns the fingerprint that decides whether Tantivy can rebuild incrementally. */\nexport function getCurrentTantivySchemaFingerprint(): string {\n const canonical = TANTIVY_SCHEMA_FIELDS.map((f) => `${f.name}:${f.tokenizer}:stored`).join('|')\n return createHash('sha256').update(canonical).digest('hex')\n}\n\n/** Checks for Tantivy's metadata file without opening the optional binding. */\nexport function tantivyIndexDirIsValid(dir: string): boolean {\n return existsSync(path.join(dir, 'meta.json'))\n}\n\n/** Maps a canonical search_docs row into one stored Tantivy document. */\nfunction makeTantivyDoc(tantivy: TantivyModule, row: SearchDocRow): InstanceType<TantivyModule['Document']> {\n const doc = new tantivy.Document()\n doc.addText('doc_id', row.doc_id)\n doc.addText('entity_type', row.entity_type)\n doc.addText('entity_id', row.entity_id)\n doc.addText('session_id', row.session_id ?? '')\n doc.addText('project_id', row.project_id ?? '')\n doc.addText('timestamp', row.timestamp ?? '')\n doc.addText('role', row.role ?? '')\n doc.addText('tool_name', row.tool_name ?? '')\n doc.addText('canonical_tool_type', row.canonical_tool_type ?? '')\n doc.addText('field_kind', row.field_kind)\n doc.addText('text', row.text)\n return doc\n}\n\n/** Base projection used by full and incremental Tantivy indexing. */\nconst SEARCH_DOCS_SELECT = `\n SELECT rowid, doc_id, entity_type, entity_id, session_id, project_id, timestamp,\n role, tool_name, canonical_tool_type, field_kind, text\n FROM search_docs\n`\n\n/** Rebuilds the Tantivy sidecar, using an incremental append path when valid. */\nexport async function rebuildTantivyIndex(\n bundle: Bundle,\n options: RebuildTantivyOptions = {},\n): Promise<SearchIndexStatus> {\n ensureSearchIndexStatusRows(bundle)\n const sourceDocCount = countSearchDocs(bundle)\n\n // Read the *previous* status before we mark it 'building' — we rely on it\n // to decide between full and incremental, and on the prior indexed count\n // to project the post-incremental total.\n const prev = getSearchIndexStatus(bundle, 'tantivy')\n const fingerprint = getCurrentTantivySchemaFingerprint()\n const indexDirValid = tantivyIndexDirIsValid(bundle.paths.tantivy)\n const fingerprintMatches = prev?.schema_fingerprint === fingerprint\n const lastIndexedRowid = typeof prev?.last_indexed_rowid === 'number' ? prev.last_indexed_rowid : 0\n const wantFullRebuild = options.overwrite === true || !indexDirValid || !fingerprintMatches || lastIndexedRowid <= 0\n\n updateSearchIndexStatus(bundle, 'tantivy', {\n status: 'building',\n sourceDocCount,\n indexedDocCount: 0,\n errorMessage: null,\n })\n\n try {\n const tantivy = await import('@oxdev03/node-tantivy-binding')\n const schema = buildTantivySchema(tantivy)\n\n let index: InstanceType<TantivyModule['Index']>\n if (wantFullRebuild) {\n await rm(bundle.paths.tantivy, { recursive: true, force: true })\n await mkdir(bundle.paths.tantivy, { recursive: true })\n index = new tantivy.Index(schema, bundle.paths.tantivy, false)\n } else {\n index = tantivy.Index.open(bundle.paths.tantivy)\n }\n\n const writer = index.writer(300_000_000, 4)\n const select = wantFullRebuild\n ? `${SEARCH_DOCS_SELECT} ORDER BY rowid`\n : `${SEARCH_DOCS_SELECT} WHERE rowid > ${lastIndexedRowid} ORDER BY rowid`\n\n let addedDocCount = 0\n let maxRowid = wantFullRebuild ? 0 : lastIndexedRowid\n for (const row of bundle.db.prepare<[], SearchDocRow>(select).iterate()) {\n if (!wantFullRebuild) {\n // Defensive: lets re-imported docs replace the prior copy. The\n // tokenizer for `doc_id` is `raw`, so the stored value maps 1:1\n // to a single deletable term.\n writer.deleteDocumentsByTerm('doc_id', row.doc_id)\n }\n writer.addDocument(makeTantivyDoc(tantivy, row))\n addedDocCount++\n if (row.rowid > maxRowid) maxRowid = row.rowid\n }\n\n writer.commit()\n index.reload()\n // Drop the writer deterministically so the directory lock is released\n // before the next rebuildTantivyIndex call (e.g. consecutive runs in\n // the same process).\n writer.waitMergingThreads()\n\n const indexedDocCount = wantFullRebuild ? addedDocCount : countTantivyDocsBest(prev, addedDocCount)\n\n await writeFile(\n path.join(bundle.paths.tantivy, 'prosa-index.json'),\n `${JSON.stringify(\n {\n engine: 'tantivy',\n source: 'search_docs',\n built_at: new Date().toISOString(),\n mode: wantFullRebuild ? 'full' : 'incremental',\n source_doc_count: sourceDocCount,\n indexed_doc_count: indexedDocCount,\n last_indexed_rowid: maxRowid,\n schema_fingerprint: fingerprint,\n },\n null,\n 2,\n )}\\n`,\n 'utf8',\n )\n\n updateSearchIndexStatus(bundle, 'tantivy', {\n status: 'ready',\n sourceDocCount,\n indexedDocCount,\n errorMessage: null,\n lastIndexedRowid: maxRowid,\n schemaFingerprint: fingerprint,\n })\n } catch (error) {\n updateSearchIndexStatus(bundle, 'tantivy', {\n status: 'failed',\n sourceDocCount,\n indexedDocCount: 0,\n errorMessage: getErrorMessage(error),\n })\n throw error\n }\n\n return getSearchIndexStatus(bundle, 'tantivy') as SearchIndexStatus\n}\n\n/**\n * Estimates Tantivy's post-incremental document count from prior recorded\n * state because the binding does not expose a cheap committed count here.\n */\nfunction countTantivyDocsBest(prev: SearchIndexStatus | null, added: number): number {\n if (prev && typeof prev.indexed_doc_count === 'number') {\n return prev.indexed_doc_count + added\n }\n return added\n}\n\n/** Ensures every supported search engine has a status row before reads/writes. */\nfunction ensureSearchIndexStatusRows(bundle: Bundle): void {\n const now = new Date().toISOString()\n const stmt = prepare(\n bundle.db,\n `INSERT OR IGNORE INTO search_index_status (\n engine, status, source_doc_count, indexed_doc_count, updated_at,\n error_message, last_indexed_rowid, schema_fingerprint\n ) VALUES (?, ?, 0, 0, ?, NULL, NULL, NULL)`,\n )\n stmt.run('fts5', 'ready', now)\n stmt.run('tantivy', 'missing', now)\n}\n\n/** Partial search_index_status update; optional fields leave columns unchanged. */\ninterface UpdateSearchIndexValues {\n status: SearchIndexStatus['status']\n sourceDocCount: number\n indexedDocCount: number\n errorMessage: string | null\n /** undefined leaves the column untouched; null clears it. */\n lastIndexedRowid?: number | null\n /** undefined leaves the column untouched; null clears it. */\n schemaFingerprint?: string | null\n}\n\n/** Writes status metadata while preserving optional columns unless explicitly provided. */\nfunction updateSearchIndexStatus(bundle: Bundle, engine: SearchEngine, values: UpdateSearchIndexValues): void {\n ensureSearchIndexStatusRows(bundle)\n const setClauses = [\n 'status = ?',\n 'source_doc_count = ?',\n 'indexed_doc_count = ?',\n 'updated_at = ?',\n 'error_message = ?',\n ]\n const params: unknown[] = [\n values.status,\n values.sourceDocCount,\n values.indexedDocCount,\n new Date().toISOString(),\n values.errorMessage,\n ]\n if (values.lastIndexedRowid !== undefined) {\n setClauses.push('last_indexed_rowid = ?')\n params.push(values.lastIndexedRowid)\n }\n if (values.schemaFingerprint !== undefined) {\n setClauses.push('schema_fingerprint = ?')\n params.push(values.schemaFingerprint)\n }\n params.push(engine)\n prepare(bundle.db, `UPDATE search_index_status SET ${setClauses.join(', ')} WHERE engine = ?`).run(...params)\n}\n\n/** Counts canonical search_docs rows that derived indexes should cover. */\nexport function countSearchDocs(bundle: Bundle): number {\n return bundle.db.prepare<[], { n: number }>(`SELECT count(*) AS n FROM search_docs`).get()?.n ?? 0\n}\n\n/** Counts rows currently present in the SQLite FTS5 virtual table. */\nexport function countFts5Docs(bundle: Bundle): number {\n return bundle.db.prepare<[], { n: number }>(`SELECT count(*) AS n FROM search_docs_fts`).get()?.n ?? 0\n}\n","import os from 'node:os'\nimport path from 'node:path'\nimport type { Bundle } from '../core/bundle.js'\nimport type { SourceTool } from '../core/domain/types.js'\nimport { getErrorMessage } from '../core/errors.js'\nimport type { ImportBatch, ImportCounts } from '../core/ingest/batch.js'\nimport { compileClaude } from '../importers/claude/index.js'\nimport { compileCodex } from '../importers/codex/index.js'\nimport type { CompileLogger, CompileOptions } from '../importers/compile-options.js'\nimport { compileCursor } from '../importers/cursor/index.js'\nimport { compileGemini } from '../importers/gemini/index.js'\nimport { compileHermes } from '../importers/hermes/index.js'\nimport { exportBundleParquet } from './export/parquet.js'\nimport {\n disableFts5Triggers,\n enableFts5Triggers,\n markIndexesAfterImport,\n rebuildFts5Index,\n rebuildTantivyIndex,\n} from './indexing.js'\n\n/** Importer result shape normalized for compile orchestration. */\nexport interface CompileResult {\n /** Import batch created by the provider. */\n batch: ImportBatch\n /** Final provider import counts. */\n counts: ImportCounts\n}\n\n/** Configures one source-tool importer for the compile service. */\nexport interface CompileProviderConfig {\n /** Source tool handled by this provider. */\n name: SourceTool\n /** Human-readable provider description. */\n description: string\n /** Help text describing the expected root path. */\n pathHelp: string\n /** Default native history location for this provider. */\n defaultSessionsPath: () => string\n /** Provider compile implementation. */\n compile: (bundle: Bundle, root: string, options?: CompileOptions) => Promise<CompileResult>\n}\n\n/** Per-provider summary emitted after an importer finishes. */\nexport interface ProviderCompileSummary {\n /** Source tool that completed. */\n source: SourceTool\n /** Resolved source path compiled by the provider. */\n sourcePath: string\n /** Batch identifier for this provider run. */\n batchId: string\n /** Import batch metadata. */\n batch: ImportBatch\n /** Final import counts. */\n counts: ImportCounts\n}\n\n/** Summary emitted after a Tantivy rebuild completes during compile. */\nexport interface TantivyCompileSummary {\n /** Documents present in the rebuilt Tantivy index. */\n indexedDocCount: number\n}\n\n/** Aggregate result for a compile import run across one or more providers. */\nexport interface CompileImportSummary {\n /** Per-provider summaries in execution order. */\n providers: ProviderCompileSummary[]\n /** True when at least one source file was imported. */\n importedAny: boolean\n /** Tantivy rebuild summary, if it completed. */\n tantivy: TantivyCompileSummary | null\n /** Tantivy rebuild error message, if rebuild failed but compile continued. */\n tantivyError: string | null\n /** FTS5 rebuild error message, if rebuild failed but compile continued. */\n fts5Error: string | null\n}\n\n/** Summary returned after compile-triggered Parquet export. */\nexport interface ParquetCompileSummary {\n /** Directory containing generated Parquet files. */\n outDir: string\n /** Path to the generated export manifest. */\n manifestPath: string\n /** Number of exported canonical tables. */\n tableCount: number\n /** Absolute output file path by table. */\n files: Record<string, string>\n /** Row count by table. */\n counts: Record<string, number>\n}\n\n/** Options for running compile imports across configured providers. */\nexport interface CompileImportOptions {\n /** Open bundle to import into. */\n bundle: Bundle\n /** Providers to run in order. */\n providers: CompileProviderConfig[]\n /** Optional override for every provider's default source path. */\n sessionsPath?: string\n /**\n * Force a full rebuild of derived indexes after import. Tantivy is the\n * only sidecar with an incremental path today, so this currently flips\n * Tantivy to a from-scratch rebuild; FTS5 and Parquet are always\n * full-rewrite. Surfaced by `prosa compile … --overwrite`.\n */\n overwrite?: boolean\n /** Optional structured logger. */\n logger?: CompileLogger\n /** Callback invoked after each provider completes. */\n onProviderComplete?: (summary: ProviderCompileSummary) => void\n /** Callback invoked after Tantivy rebuild completes. */\n onTantivyComplete?: (summary: TantivyCompileSummary) => void\n}\n\n/** Options for compile's Parquet export step. */\nexport interface ExportCompileParquetOptions {\n /** Bundle root whose canonical tables should be exported. */\n storePath: string\n /** Optional structured logger. */\n logger?: CompileLogger\n}\n\n/** Built-in compile providers and their default history locations. */\nexport const COMPILE_PROVIDERS: CompileProviderConfig[] = [\n {\n name: 'codex',\n description: 'Import Codex CLI session histories into the bundle.',\n pathHelp: 'root of Codex CLI sessions',\n defaultSessionsPath: () => path.join(os.homedir(), '.codex', 'sessions'),\n compile: compileCodex,\n },\n {\n name: 'claude',\n description: 'Import Claude Code project histories into the bundle.',\n pathHelp: 'root of Claude Code projects',\n defaultSessionsPath: () => path.join(os.homedir(), '.claude', 'projects'),\n compile: compileClaude,\n },\n {\n name: 'gemini',\n description: 'Import Gemini CLI session histories into the bundle.',\n pathHelp: 'root of Gemini CLI tmp dir',\n defaultSessionsPath: () => path.join(os.homedir(), '.gemini', 'tmp'),\n compile: compileGemini,\n },\n {\n name: 'cursor',\n description: 'Import Cursor agent stores into the bundle.',\n pathHelp: 'root of Cursor agent stores',\n defaultSessionsPath: () => path.join(os.homedir(), '.cursor', 'chats'),\n compile: compileCursor,\n },\n {\n name: 'hermes',\n description: 'Import Hermes session histories into the bundle.',\n pathHelp: 'root of Hermes sessions',\n defaultSessionsPath: () => path.join(os.homedir(), '.hermes', 'sessions'),\n compile: compileHermes,\n },\n]\n\n/** Resolves a compile provider by source tool, throwing for unsupported names. */\nexport function getCompileProvider(source: SourceTool): CompileProviderConfig {\n const provider = COMPILE_PROVIDERS.find((p) => p.name === source)\n if (!provider) {\n throw new Error(`unknown compile source: ${source}`)\n }\n return provider\n}\n\n/** Expands shell-style home paths and resolves compile paths to absolutes. */\nexport function resolveCompilePath(p: string, basePath = process.env.INIT_CWD ?? process.cwd()): string {\n if (p === '~') return os.homedir()\n if (p.startsWith('~/')) return path.join(os.homedir(), p.slice(2))\n if (path.isAbsolute(p)) return path.resolve(p)\n return path.resolve(basePath, p)\n}\n\n/** Runs provider imports and refreshes derived search indexes when data changed. */\nexport async function runCompileImports(options: CompileImportOptions): Promise<CompileImportSummary> {\n const { bundle, providers, logger } = options\n const overwrite = options.overwrite === true\n let importedAny = false\n const summaries: ProviderCompileSummary[] = []\n let tantivy: TantivyCompileSummary | null = null\n let tantivyError: string | null = null\n let fts5Error: string | null = null\n\n try {\n // Sweep any unfinished import_batches left behind by a previous crash so\n // they don't keep tripping `prosa doctor` after every successful compile.\n // SQLite is single-writer; if we're here, no other process owns those rows.\n const sweep = bundle.db\n .prepare(\n `UPDATE import_batches SET status = 'failed', finished_at = datetime('now')\n WHERE finished_at IS NULL`,\n )\n .run()\n if (sweep.changes > 0) {\n logger?.warn({ batches_reaped: sweep.changes }, 'reaped unfinished import_batches from a prior crash')\n }\n\n logger?.info('disabling FTS5 triggers for bulk rebuild')\n disableFts5Triggers(bundle)\n\n for (const provider of providers) {\n const sourcePath = resolveCompilePath(options.sessionsPath ?? provider.defaultSessionsPath())\n const providerLogger = logger?.child({\n source_tool: provider.name,\n source_path: sourcePath,\n })\n providerLogger?.info('starting compile')\n const r = await provider.compile(bundle, sourcePath, { logger: providerLogger })\n importedAny ||= r.counts.source_files_imported > 0\n providerLogger?.info(\n {\n batch_id: r.batch.batch_id,\n counts: r.counts,\n },\n 'compile finished',\n )\n\n const summary = {\n source: provider.name,\n sourcePath,\n batchId: r.batch.batch_id,\n batch: r.batch,\n counts: r.counts,\n }\n summaries.push(summary)\n options.onProviderComplete?.(summary)\n }\n\n const shouldRebuildIndexes = importedAny || overwrite\n if (shouldRebuildIndexes) {\n logger?.info(\n { changed: importedAny, overwrite },\n importedAny ? 'marking indexes' : 'overwrite forces rebuild despite no new imports',\n )\n markIndexesAfterImport(bundle, { changed: true })\n\n try {\n logger?.info('rebuilding fts5 index')\n rebuildFts5Index(bundle)\n } catch (error) {\n fts5Error = getErrorMessage(error)\n logger?.error({ err: error }, 'fts5 rebuild failed; SQLite data is intact')\n }\n\n try {\n logger?.info({ overwrite }, 'rebuilding tantivy index')\n const status = await rebuildTantivyIndex(bundle, { overwrite })\n tantivy = { indexedDocCount: status.indexed_doc_count }\n options.onTantivyComplete?.(tantivy)\n } catch (error) {\n tantivyError = getErrorMessage(error)\n logger?.error({ err: error }, 'tantivy rebuild failed; SQLite data is intact')\n }\n }\n } finally {\n enableFts5Triggers(bundle)\n }\n\n return {\n providers: summaries,\n importedAny,\n tantivy,\n tantivyError,\n fts5Error,\n }\n}\n\n/** Exports the compiled bundle to Parquet using compile command path semantics. */\nexport async function exportCompileParquet(options: ExportCompileParquetOptions): Promise<ParquetCompileSummary> {\n const storePath = resolveCompilePath(options.storePath)\n options.logger?.info({ store_path: storePath }, 'exporting parquet')\n const result = await exportBundleParquet({ bundlePath: storePath })\n return {\n outDir: result.outDir,\n manifestPath: result.manifestPath,\n tableCount: Object.keys(result.files).length,\n files: result.files,\n counts: result.counts,\n }\n}\n","import { readFile } from 'node:fs/promises'\nimport path from 'node:path'\nimport type { Bundle } from '../../core/bundle.js'\nimport {\n type ObjectId,\n type PendingObjects,\n createPendingObjects,\n flushPendingObjects,\n stageBytes,\n stageJson,\n stageText,\n} from '../../core/cas/index.js'\nimport { prepare, transactional } from '../../core/db.js'\nimport {\n artifactId,\n blockId,\n eventId as makeEventId,\n messageId as makeMessageId,\n rawRecordId as makeRawRecordId,\n sessionId as makeSessionId,\n toolCallId as makeToolCallId,\n toolResultId as makeToolResultId,\n} from '../../core/domain/ids.js'\nimport { normalizeToolCallStatus } from '../../core/domain/status.js'\nimport { getErrorMessage } from '../../core/errors.js'\nimport {\n type ImportBatch,\n type ImportCounts,\n emptyCounts,\n finishBatch,\n recordError,\n startBatch,\n} from '../../core/ingest/batch.js'\nimport { registerSourceFile } from '../../core/ingest/idempotency.js'\nimport type { CompileLogger, CompileOptions } from '../compile-options.js'\nimport { type ClaudeFile, discoverClaudeFiles } from './discover.js'\nimport type { ClaudeContentBlock, ClaudeRecord, ClaudeSubagentMeta } from './types.js'\n\n/** Result returned after a Claude compile batch finishes or records a failed batch. */\nexport interface CompileResult {\n /** Import batch created for this Claude run. */\n batch: ImportBatch\n /** Final counts accumulated while importing Claude files. */\n counts: ImportCounts\n}\n\n/** Maximum inline text retained in normalized rows before full content moves to CAS. */\nconst PREVIEW_MAX = 4_000\n\n/** Compile Claude Code JSONL files under `root` into the bundle. */\nexport async function compileClaude(\n bundle: Bundle,\n root: string,\n options: CompileOptions = {},\n): Promise<CompileResult> {\n const logger = options.logger\n const batch = startBatch(bundle, 'claude', [root])\n const counts = emptyCounts()\n logger?.info({ batch_id: batch.batch_id, root }, 'claude batch started')\n\n try {\n for await (const file of discoverClaudeFiles(root)) {\n counts.source_files_seen++\n logger?.debug(\n {\n path: file.filePath,\n project_slug: file.projectSlug,\n is_subagent: file.isSubagent,\n },\n 'claude source file discovered',\n )\n try {\n const fc = await compileClaudeFile(bundle, batch, file, logger)\n addCounts(counts, fc)\n } catch (error) {\n counts.errors++\n logger?.warn(\n {\n err: error,\n path: file.filePath,\n },\n 'claude source file failed',\n )\n await recordError(bundle, batch.batch_id, {\n kind: 'claude_file_failed',\n message: getErrorMessage(error),\n payload: { path: file.filePath },\n })\n }\n }\n linkSubagentParents(bundle)\n logger?.debug({ batch_id: batch.batch_id }, 'claude subagent parent links refreshed')\n finishBatch(bundle, batch, counts, 'completed')\n logger?.info({ batch_id: batch.batch_id, counts }, 'claude batch completed')\n } catch (error) {\n finishBatch(bundle, batch, counts, 'failed')\n logger?.error({ err: error, batch_id: batch.batch_id, counts }, 'claude batch failed')\n throw error\n }\n\n return { batch, counts }\n}\n\n/** Resolve Claude subagent parent links after all files in the batch have been inserted. */\nfunction linkSubagentParents(bundle: Bundle): void {\n bundle.db.exec(`\n UPDATE edges\n SET src_id = (\n SELECT m.message_id\n FROM messages m\n JOIN raw_records r ON r.raw_record_id = m.raw_record_id\n WHERE r.source_tool = 'claude'\n AND r.native_id = edges.src_id\n LIMIT 1\n )\n WHERE src_type = 'message'\n AND edge_type = 'spawned'\n AND source = 'source_tool_assistant_uuid'\n AND EXISTS (\n SELECT 1\n FROM messages m\n JOIN raw_records r ON r.raw_record_id = m.raw_record_id\n WHERE r.source_tool = 'claude'\n AND r.native_id = edges.src_id\n );\n\n UPDATE sessions\n SET parent_session_id = (\n SELECT e.src_id\n FROM edges e\n WHERE e.edge_type = 'spawned'\n AND e.dst_type = 'session'\n AND e.dst_id = sessions.session_id\n AND EXISTS (SELECT 1 FROM sessions p WHERE p.session_id = e.src_id)\n LIMIT 1\n )\n WHERE parent_session_id IS NULL\n AND is_subagent = 1\n AND source_tool = 'claude'\n `)\n}\n\n/** Per-source-file deltas that are merged into the import batch counts. */\ninterface FileCounts {\n source_files_imported: number\n source_files_skipped: number\n raw_records: number\n sessions: number\n turns: number\n events: number\n messages: number\n content_blocks: number\n tool_calls: number\n tool_results: number\n artifacts: number\n edges: number\n errors: number\n}\n\n/** Create zeroed file counters for a Claude file that may still fail or be skipped. */\nfunction emptyFileCounts(): FileCounts {\n return {\n source_files_imported: 0,\n source_files_skipped: 0,\n raw_records: 0,\n sessions: 0,\n turns: 0,\n events: 0,\n messages: 0,\n content_blocks: 0,\n tool_calls: 0,\n tool_results: 0,\n artifacts: 0,\n edges: 0,\n errors: 0,\n }\n}\n\n/** Merge a single Claude file's normalized row counts into batch totals. */\nfunction addCounts(target: ImportCounts, source: FileCounts): void {\n target.source_files_imported += source.source_files_imported\n target.source_files_skipped += source.source_files_skipped\n target.raw_records += source.raw_records\n target.sessions += source.sessions\n target.turns += source.turns\n target.events += source.events\n target.messages += source.messages\n target.content_blocks += source.content_blocks\n target.tool_calls += source.tool_calls\n target.tool_results += source.tool_results\n target.artifacts += source.artifacts\n target.edges += source.edges\n target.errors += source.errors\n}\n\n// -- per file --\n\n/** Raw record row staged from a Claude JSONL line before database insertion. */\ninterface PendingRawRecord {\n raw_record_id: string\n source_file_id: string\n ordinal: number\n line_no: number\n native_id: string | null\n raw_object_id: ObjectId\n decoded_json_object_id: ObjectId | null\n parser_status: 'ok' | 'partial' | 'failed'\n confidence: 'high' | 'medium' | 'low'\n import_batch_id: string\n}\n\n/** Session row staged from the first Claude record with a session id. */\ninterface PendingSession {\n session_id: string\n source_session_id: string\n is_subagent: 0 | 1\n agent_role: string | null\n agent_nickname: string | null\n title: string | null\n start_ts: string | null\n end_ts: string | null\n cwd_initial: string | null\n git_branch_initial: string | null\n raw_record_id: string | null\n /** for subagent files; resolved cross-file in linkSubagentParents */\n parent_session_id_pending: string | null\n}\n\n/** Event row staged from Claude user, assistant, system, or operational records. */\ninterface PendingEvent {\n event_id: string\n ordinal: number\n source_event_id: string | null\n event_type: string\n source_type: string\n subtype: string | null\n timestamp: string | null\n actor: string | null\n payload_object_id: ObjectId | null\n raw_record_id: string\n confidence: 'high' | 'medium' | 'low'\n}\n\n/** Message row staged from Claude user and assistant records. */\ninterface PendingMessage {\n message_id: string\n event_id: string | null\n source_message_id: string | null\n role: 'system_prompt' | 'developer' | 'user' | 'assistant' | 'tool' | 'operational'\n model: string | null\n timestamp: string | null\n ordinal: number\n parent_message_id: string | null\n parent_uuid: string | null // for parent_of edge linking by uuid\n uuid: string | null\n raw_record_id: string\n}\n\n/** Content block row staged from Claude text, thinking, tool, image, or unknown blocks. */\ninterface PendingBlock {\n block_id: string\n message_id: string | null\n event_id: string | null\n ordinal: number\n block_type: string\n text_object_id: ObjectId | null\n text_inline: string | null\n is_error: 0 | 1\n visibility: 'default' | 'hidden_by_default' | 'audit_only'\n raw_record_id: string\n}\n\n/** Tool call row staged from Claude `tool_use` content blocks. */\ninterface PendingToolCall {\n tool_call_id: string\n message_id: string | null\n event_id: string | null\n source_call_id: string\n tool_name: string\n canonical_tool_type: string\n args_object_id: ObjectId | null\n command: string | null\n cwd: string | null\n path: string | null\n query: string | null\n timestamp_start: string | null\n status: string | null\n raw_record_id: string\n}\n\n/** Tool result row staged from Claude `tool_result` content blocks. */\ninterface PendingToolResult {\n tool_result_id: string\n tool_call_id: string | null\n source_call_id: string | null\n message_id: string | null\n event_id: string | null\n status: string | null\n is_error: 0 | 1\n exit_code: number | null\n duration_ms: number | null\n stdout_object_id: ObjectId | null\n stderr_object_id: ObjectId | null\n output_object_id: ObjectId | null\n preview: string | null\n raw_record_id: string\n}\n\n/** Artifact row staged from Claude records that point to external or generated content. */\ninterface PendingArtifact {\n artifact_id: string\n kind: string\n path: string | null\n logical_path: string | null\n object_id: ObjectId | null\n text_object_id: ObjectId | null\n mime_type: string | null\n size_bytes: number\n created_ts: string | null\n raw_record_id: string\n}\n\n/** Graph edge row staged for Claude parent-message and subagent relationships. */\ninterface PendingEdge {\n src_type: string\n src_id: string\n dst_type: string\n dst_id: string\n edge_type: string\n confidence: 'high' | 'medium' | 'low'\n source: string\n raw_record_id: string | null\n}\n\n/** Search index row staged from normalized Claude messages, commands, paths, and previews. */\ninterface PendingSearchDoc {\n doc_id: string\n entity_type: string\n entity_id: string\n timestamp: string | null\n role: string | null\n tool_name: string | null\n canonical_tool_type: string | null\n field_kind: string\n text: string\n}\n\n/** All normalized Claude rows staged for one source file before FK-ordered flush. */\ninterface PendingState {\n rawRecords: PendingRawRecord[]\n session: PendingSession | null\n events: PendingEvent[]\n messages: PendingMessage[]\n blocks: PendingBlock[]\n toolCalls: Map<string, PendingToolCall>\n toolCallsList: PendingToolCall[]\n toolResults: PendingToolResult[]\n artifacts: PendingArtifact[]\n edges: PendingEdge[]\n searchDocs: PendingSearchDoc[]\n /** map uuid → message_id for parent_of edges resolved at flush time. */\n uuidToMessageId: Map<string, string>\n objects: PendingObjects\n}\n\n/** Parse one Claude JSONL file, stage CAS objects, and flush normalized rows. */\nasync function compileClaudeFile(\n bundle: Bundle,\n batch: ImportBatch,\n file: ClaudeFile,\n logger?: CompileLogger,\n): Promise<FileCounts> {\n const counts = emptyFileCounts()\n\n const { row: sourceFile, alreadyKnown } = await registerSourceFile(bundle, {\n sourceTool: 'claude',\n absolutePath: path.resolve(file.filePath),\n fileKind: 'jsonl',\n workspaceHint: file.projectSlug,\n })\n\n if (alreadyKnown) {\n counts.source_files_skipped = 1\n logger?.debug({ path: file.filePath, source_file_id: sourceFile.source_file_id }, 'claude source file skipped')\n return counts\n }\n counts.source_files_imported = 1\n logger?.debug({ path: file.filePath, source_file_id: sourceFile.source_file_id }, 'claude source file registered')\n\n const text = await readFile(file.filePath, 'utf8')\n const rawLines = text.split('\\n')\n const lines = rawLines[rawLines.length - 1] === '' ? rawLines.slice(0, -1) : rawLines\n\n const meta = file.metaPath ? await readMeta(file.metaPath) : null\n\n const pending: PendingState = {\n rawRecords: [],\n session: null,\n events: [],\n messages: [],\n blocks: [],\n toolCalls: new Map(),\n toolCallsList: [],\n toolResults: [],\n artifacts: [],\n edges: [],\n searchDocs: [],\n uuidToMessageId: new Map(),\n objects: createPendingObjects(),\n }\n\n let modelFirst: string | null = null\n let modelLast: string | null = null\n let messageOrdinal = 0\n let sessionStartTs: string | null = null\n let sessionEndTs: string | null = null\n let cwdInitial: string | null = null\n let branchInitial: string | null = null\n\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i]\n if (!line || line.length === 0) continue\n const lineNo = i + 1\n const ordinal = i\n\n const lineBytes = Buffer.from(line, 'utf8')\n const rawObjectId = stageBytes(pending.objects, lineBytes, {\n mimeType: 'application/jsonl-line',\n encoding: 'utf-8',\n })\n\n let parsed: ClaudeRecord | null = null\n let parserStatus: 'ok' | 'partial' | 'failed' = 'ok'\n try {\n parsed = JSON.parse(line) as ClaudeRecord\n } catch {\n parserStatus = 'failed'\n }\n\n // The raw line already IS the JSON for `parserStatus === 'ok'`, so we\n // skip storing a re-serialized copy as `decoded_json_object_id`. Saves\n // ~half the CAS writes per file. Nothing reads it back later.\n const decodedObjectId: ObjectId | null = null\n\n const nativeId = parsed?.uuid ?? null\n const rawRecordId = makeRawRecordId(sourceFile.source_file_id, ordinal, rawObjectId)\n\n pending.rawRecords.push({\n raw_record_id: rawRecordId,\n source_file_id: sourceFile.source_file_id,\n ordinal,\n line_no: lineNo,\n native_id: nativeId,\n raw_object_id: rawObjectId,\n decoded_json_object_id: decodedObjectId,\n parser_status: parserStatus,\n confidence: parserStatus === 'ok' ? 'high' : 'low',\n import_batch_id: batch.batch_id,\n })\n\n if (!parsed) continue\n\n const ts = typeof parsed.timestamp === 'string' ? parsed.timestamp : null\n if (ts) {\n if (!sessionStartTs || ts < sessionStartTs) sessionStartTs = ts\n if (!sessionEndTs || ts > sessionEndTs) sessionEndTs = ts\n }\n if (!cwdInitial && typeof parsed.cwd === 'string') cwdInitial = parsed.cwd\n if (!branchInitial && typeof parsed.gitBranch === 'string') branchInitial = parsed.gitBranch\n\n // Resolve session on first record that carries a sessionId.\n if (!pending.session && typeof parsed.sessionId === 'string') {\n pending.session = createSessionFromFirstRecord(file, parsed, meta, ts, rawRecordId)\n if (file.isSubagent && file.parentSessionId) {\n const parentSid = makeSessionId('claude', file.parentSessionId)\n pending.edges.push({\n src_type: 'session',\n src_id: parentSid,\n dst_type: 'session',\n dst_id: pending.session.session_id,\n edge_type: 'spawned',\n confidence: 'high',\n source: 'path_inferred',\n raw_record_id: rawRecordId,\n })\n pending.session.parent_session_id_pending = parentSid\n }\n }\n\n const sessionId = pending.session?.session_id ?? makeSessionId('claude', `unknown:${path.basename(file.filePath)}`)\n\n const type = typeof parsed.type === 'string' ? parsed.type : null\n\n if (type === 'user' || type === 'assistant') {\n const msgRole: PendingMessage['role'] = type === 'user' ? 'user' : 'assistant'\n const role = inferRoleFromContent(parsed, msgRole)\n const msgOrdinal = messageOrdinal++\n const messageId = makeMessageId(sessionId, msgOrdinal, parsed.message?.id ?? parsed.uuid ?? null)\n const eventId = makeEventId(sessionId, ordinal, 'message')\n\n pending.events.push({\n event_id: eventId,\n ordinal,\n source_event_id: parsed.uuid ?? null,\n event_type: 'message',\n source_type: type,\n subtype: null,\n timestamp: ts,\n actor: msgRole,\n payload_object_id: decodedObjectId,\n raw_record_id: rawRecordId,\n confidence: 'high',\n })\n\n const model = parsed.message?.model ?? null\n if (msgRole === 'assistant' && model) {\n if (!modelFirst) modelFirst = model\n modelLast = model\n }\n\n pending.messages.push({\n message_id: messageId,\n event_id: eventId,\n source_message_id: parsed.message?.id ?? null,\n role,\n model: msgRole === 'assistant' ? model : null,\n timestamp: ts,\n ordinal: msgOrdinal,\n parent_message_id: null,\n parent_uuid: parsed.parentUuid ?? null,\n uuid: parsed.uuid ?? null,\n raw_record_id: rawRecordId,\n })\n if (parsed.uuid) pending.uuidToMessageId.set(parsed.uuid, messageId)\n if (parsed.isSidechain && parsed.sourceToolAssistantUUID) {\n pending.edges.push({\n src_type: 'message',\n src_id: parsed.sourceToolAssistantUUID,\n dst_type: 'session',\n dst_id: sessionId,\n edge_type: 'spawned',\n confidence: 'high',\n source: 'source_tool_assistant_uuid',\n raw_record_id: rawRecordId,\n })\n }\n\n const content = parsed.message?.content\n if (typeof content === 'string') {\n pending.blocks.push({\n block_id: blockId(messageId, 0),\n message_id: messageId,\n event_id: null,\n ordinal: 0,\n block_type: 'text',\n text_object_id: null,\n text_inline: content.slice(0, PREVIEW_MAX),\n is_error: 0,\n visibility: 'default',\n raw_record_id: rawRecordId,\n })\n if (content.length > PREVIEW_MAX) {\n // Big text — also store full body in CAS for later retrieval.\n const fullId = stageText(pending.objects, content)\n const last = pending.blocks[pending.blocks.length - 1]\n if (last) last.text_object_id = fullId\n }\n } else if (Array.isArray(content)) {\n for (let bi = 0; bi < content.length; bi++) {\n const block = content[bi] as ClaudeContentBlock | undefined\n if (!block) continue\n await processContentBlock(bundle, sessionId, messageId, eventId, bi, block, ts, rawRecordId, pending)\n }\n }\n continue\n }\n\n if (type === 'system') {\n // Critical: Claude's `type=system` is OPERATIONAL (hooks, turn duration,\n // local commands, api errors). It's not a system prompt.\n pending.events.push({\n event_id: makeEventId(sessionId, ordinal, 'system_operational'),\n ordinal,\n source_event_id: parsed.uuid ?? null,\n event_type: 'system_operational',\n source_type: 'system',\n subtype: parsed.subtype ?? null,\n timestamp: ts,\n actor: 'system',\n payload_object_id: decodedObjectId,\n raw_record_id: rawRecordId,\n confidence: 'high',\n })\n continue\n }\n\n if (type === 'progress') {\n const progressType = typeof parsed.data?.type === 'string' ? (parsed.data.type as string) : null\n pending.events.push({\n event_id: makeEventId(sessionId, ordinal, `progress.${progressType ?? 'unknown'}`),\n ordinal,\n source_event_id: parsed.uuid ?? null,\n event_type: 'progress',\n source_type: 'progress',\n subtype: progressType,\n timestamp: ts,\n actor: 'system',\n payload_object_id: decodedObjectId,\n raw_record_id: rawRecordId,\n confidence: 'high',\n })\n continue\n }\n\n if (type === 'attachment') {\n pending.events.push({\n event_id: makeEventId(sessionId, ordinal, 'attachment'),\n ordinal,\n source_event_id: parsed.uuid ?? null,\n event_type: 'file_history_snapshot',\n source_type: 'attachment',\n subtype: parsed.attachment?.type ?? null,\n timestamp: ts,\n actor: 'system',\n payload_object_id: decodedObjectId,\n raw_record_id: rawRecordId,\n confidence: 'high',\n })\n continue\n }\n\n if (type === 'file-history-snapshot') {\n pending.events.push({\n event_id: makeEventId(sessionId, ordinal, 'file_history_snapshot'),\n ordinal,\n source_event_id: parsed.uuid ?? null,\n event_type: 'attachment',\n source_type: 'file-history-snapshot',\n subtype: parsed.isSnapshotUpdate ? 'update' : 'snapshot',\n timestamp: ts,\n actor: 'system',\n payload_object_id: decodedObjectId,\n raw_record_id: rawRecordId,\n confidence: 'high',\n })\n pending.artifacts.push({\n artifact_id: artifactId(sessionId, 'claude', `snapshot:${parsed.snapshot?.messageId ?? ordinal}`),\n kind: 'snapshot',\n path: null,\n logical_path: null,\n object_id: null,\n text_object_id: null,\n mime_type: 'application/json',\n size_bytes: line.length,\n created_ts: ts,\n raw_record_id: rawRecordId,\n })\n continue\n }\n\n // permission-mode, last-prompt, queue-operation, agent-name, custom-title,\n // pr-link, etc. — keep as operational events.\n pending.events.push({\n event_id: makeEventId(sessionId, ordinal, `claude.${type ?? 'unknown'}`),\n ordinal,\n source_event_id: parsed.uuid ?? null,\n event_type: 'system_operational',\n source_type: type ?? 'unknown',\n subtype: null,\n timestamp: ts,\n actor: 'system',\n payload_object_id: decodedObjectId,\n raw_record_id: rawRecordId,\n confidence: 'high',\n })\n }\n\n // Resolve parent_of edges by uuid.\n for (const m of pending.messages) {\n if (m.parent_uuid && pending.uuidToMessageId.has(m.parent_uuid)) {\n const parentId = pending.uuidToMessageId.get(m.parent_uuid)!\n m.parent_message_id = parentId\n pending.edges.push({\n src_type: 'message',\n src_id: parentId,\n dst_type: 'message',\n dst_id: m.message_id,\n edge_type: 'parent_of',\n confidence: 'high',\n source: 'explicit',\n raw_record_id: m.raw_record_id,\n })\n }\n }\n\n if (pending.session) {\n pending.session.start_ts ??= sessionStartTs\n pending.session.end_ts ??= sessionEndTs\n pending.session.cwd_initial ??= cwdInitial\n pending.session.git_branch_initial ??= branchInitial\n }\n\n buildSearchDocs(pending)\n\n // Persist staged CAS objects (FS + objects rows) before the domain\n // transaction. better-sqlite3 transactions are sync, so we can't await\n // file writes inside them.\n await flushPendingObjects(bundle, pending.objects)\n\n transactional(bundle.db, () => {\n flushPending(bundle, pending, { modelFirst, modelLast })\n })\n\n counts.raw_records = pending.rawRecords.length\n counts.sessions = pending.session ? 1 : 0\n counts.events = pending.events.length\n counts.messages = pending.messages.length\n counts.content_blocks = pending.blocks.length\n counts.tool_calls = pending.toolCallsList.length\n counts.tool_results = pending.toolResults.length\n counts.artifacts = pending.artifacts.length\n counts.edges = pending.edges.length\n logger?.debug(\n { path: file.filePath, source_file_id: sourceFile.source_file_id, counts },\n 'claude source file imported',\n )\n\n return counts\n}\n\n/** Build the normalized session id, keeping Claude subagents distinct from parent sessions. */\nfunction createSessionFromFirstRecord(\n file: ClaudeFile,\n parsed: ClaudeRecord,\n meta: ClaudeSubagentMeta | null,\n ts: string | null,\n rawRecordId: string,\n): PendingSession {\n const sourceSid = parsed.sessionId as string\n // Subagent and main share the same `sessionId` field. Differentiate by\n // appending the agentId for subagents to keep PKs stable.\n const composite = file.isSubagent && file.agentId ? `${sourceSid}:${file.agentId}` : sourceSid\n return {\n session_id: makeSessionId('claude', composite),\n source_session_id: composite,\n is_subagent: file.isSubagent ? 1 : 0,\n agent_role: meta?.agentType ?? null,\n agent_nickname: parsed.agentName ?? null,\n title: meta?.description ?? null,\n start_ts: ts,\n end_ts: null,\n cwd_initial: parsed.cwd ?? null,\n git_branch_initial: parsed.gitBranch ?? null,\n raw_record_id: rawRecordId,\n parent_session_id_pending: null,\n }\n}\n\n/** Read optional Claude subagent metadata, treating missing or malformed files as absent. */\nasync function readMeta(metaPath: string): Promise<ClaudeSubagentMeta | null> {\n try {\n const text = await readFile(metaPath, 'utf8')\n return JSON.parse(text) as ClaudeSubagentMeta\n } catch {\n return null\n }\n}\n\n/** Reclassify tool-result-only Claude user messages as tool output for search and filters. */\nfunction inferRoleFromContent(parsed: ClaudeRecord, fallback: 'user' | 'assistant'): PendingMessage['role'] {\n // A user-typed message that contains only tool_result blocks is the agent\n // delivering tool output back to itself. Mark as 'tool' role for clarity in\n // search/filters; mixed messages stay as 'user'.\n if (fallback !== 'user') return 'assistant'\n const c = parsed.message?.content\n if (!Array.isArray(c) || c.length === 0) return 'user'\n const allToolResult = c.every((b) => b && typeof b === 'object' && (b as { type?: string }).type === 'tool_result')\n return allToolResult ? 'tool' : 'user'\n}\n\n/** Normalize one Claude content block into blocks, tool calls, tool results, or audit rows. */\nasync function processContentBlock(\n bundle: Bundle,\n sessionId: string,\n messageId: string,\n eventId: string,\n blockOrdinal: number,\n block: ClaudeContentBlock,\n ts: string | null,\n rawRecordId: string,\n pending: PendingState,\n): Promise<void> {\n const blkId = blockId(messageId, blockOrdinal)\n\n if (block.type === 'text') {\n const text = (block as { text?: string }).text ?? ''\n pending.blocks.push({\n block_id: blkId,\n message_id: messageId,\n event_id: null,\n ordinal: blockOrdinal,\n block_type: 'text',\n text_object_id: text.length > PREVIEW_MAX ? stageText(pending.objects, text) : null,\n text_inline: text.slice(0, PREVIEW_MAX),\n is_error: 0,\n visibility: 'default',\n raw_record_id: rawRecordId,\n })\n return\n }\n\n if (block.type === 'thinking') {\n const text = (block as { thinking?: string }).thinking ?? ''\n pending.blocks.push({\n block_id: blkId,\n message_id: messageId,\n event_id: null,\n ordinal: blockOrdinal,\n block_type: 'thinking',\n text_object_id: text.length > PREVIEW_MAX ? stageText(pending.objects, text) : null,\n text_inline: text.slice(0, PREVIEW_MAX),\n is_error: 0,\n visibility: 'hidden_by_default',\n raw_record_id: rawRecordId,\n })\n return\n }\n\n if (block.type === 'tool_use') {\n const tu = block as { id?: string; name?: string; input?: unknown }\n const sourceCallId = tu.id ?? `${blockOrdinal}`\n const toolName = tu.name ?? 'unknown'\n const argsId = tu.input != null ? stageJson(pending.objects, tu.input) : null\n const command = inferCommandFromArgs(toolName, tu.input)\n const filePath = inferPathFromArgs(tu.input)\n const tcId = makeToolCallId(sessionId, sourceCallId)\n\n pending.blocks.push({\n block_id: blkId,\n message_id: messageId,\n event_id: null,\n ordinal: blockOrdinal,\n block_type: 'tool_use',\n text_object_id: null,\n text_inline: null,\n is_error: 0,\n visibility: 'default',\n raw_record_id: rawRecordId,\n })\n\n const call: PendingToolCall = {\n tool_call_id: tcId,\n message_id: messageId,\n event_id: eventId,\n source_call_id: sourceCallId,\n tool_name: toolName,\n canonical_tool_type: canonicalToolType(toolName),\n args_object_id: argsId,\n command,\n cwd: null,\n path: filePath,\n query: null,\n timestamp_start: ts,\n status: 'started',\n raw_record_id: rawRecordId,\n }\n pending.toolCalls.set(sourceCallId, call)\n pending.toolCallsList.push(call)\n return\n }\n\n if (block.type === 'tool_result') {\n const tr = block as { tool_use_id?: string; content?: unknown; is_error?: boolean }\n const sourceCallId = tr.tool_use_id ?? null\n const isError = tr.is_error === true ? 1 : 0\n const text = stringifyOrNull(tr.content) ?? ''\n const overflowId = text.length > PREVIEW_MAX ? stageText(pending.objects, text) : null\n pending.blocks.push({\n block_id: blkId,\n message_id: messageId,\n event_id: null,\n ordinal: blockOrdinal,\n block_type: 'tool_result',\n text_object_id: overflowId,\n text_inline: text.slice(0, PREVIEW_MAX),\n is_error: isError,\n visibility: 'default',\n raw_record_id: rawRecordId,\n })\n\n const matched = sourceCallId ? pending.toolCalls.get(sourceCallId) : undefined\n pending.toolResults.push({\n tool_result_id: makeToolResultId(sessionId, sourceCallId ?? `${messageId}:${blockOrdinal}`),\n tool_call_id: matched?.tool_call_id ?? null,\n source_call_id: sourceCallId,\n message_id: messageId,\n event_id: eventId,\n status: normalizeToolCallStatus('claude', matched ? (isError ? 'error' : 'success') : null),\n is_error: isError,\n exit_code: null,\n duration_ms: null,\n stdout_object_id: null,\n stderr_object_id: null,\n output_object_id: overflowId,\n preview: text.slice(0, PREVIEW_MAX),\n raw_record_id: rawRecordId,\n })\n if (matched) {\n matched.status = isError ? 'error' : 'success'\n }\n return\n }\n\n if (block.type === 'image') {\n pending.blocks.push({\n block_id: blkId,\n message_id: messageId,\n event_id: null,\n ordinal: blockOrdinal,\n block_type: 'image',\n text_object_id: null,\n text_inline: null,\n is_error: 0,\n visibility: 'default',\n raw_record_id: rawRecordId,\n })\n return\n }\n\n // Unknown block type — keep it as raw inline JSON for visibility.\n pending.blocks.push({\n block_id: blkId,\n message_id: messageId,\n event_id: null,\n ordinal: blockOrdinal,\n block_type: (block as { type?: string }).type ?? 'unknown',\n text_object_id: null,\n text_inline: stringifyOrNull(block)?.slice(0, PREVIEW_MAX) ?? null,\n is_error: 0,\n visibility: 'audit_only',\n raw_record_id: rawRecordId,\n })\n}\n\n/** Collapse Claude tool names into broad search/filter tool categories. */\nfunction canonicalToolType(toolName: string): string {\n const lower = toolName.toLowerCase()\n if (lower.startsWith('mcp__')) return 'mcp'\n if (lower === 'bash' || lower === 'shell' || lower === 'run_terminal_cmd') return 'shell'\n if (lower === 'read' || lower === 'readfile' || lower === 'read_file') return 'read_file'\n if (lower === 'write' || lower === 'writefile' || lower === 'write_file') return 'write_file'\n if (\n lower === 'edit' ||\n lower === 'strreplace' ||\n lower === 'str_replace' ||\n lower === 'replace' ||\n lower === 'search_replace'\n ) {\n return 'edit_file'\n }\n if (lower === 'grep' || lower === 'glob' || lower === 'glob_file_search') return 'search_file'\n if (lower === 'websearch' || lower === 'google_web_search') return 'web_search'\n if (lower === 'webfetch') return 'other'\n if (lower === 'agent') return 'subagent'\n if (lower === 'applypatch' || lower === 'apply_patch') return 'patch'\n return 'other'\n}\n\n/** Extract a shell command from Claude tool arguments when the native tool exposes one. */\nfunction inferCommandFromArgs(toolName: string, args: unknown): string | null {\n if (!args || typeof args !== 'object') return null\n const obj = args as Record<string, unknown>\n if (typeof obj.command === 'string') return obj.command\n if (toolName.toLowerCase() === 'bash' && typeof obj.cmd === 'string') return obj.cmd\n return null\n}\n\n/** Extract a file path from Claude tool arguments without treating absence as an error. */\nfunction inferPathFromArgs(args: unknown): string | null {\n if (!args || typeof args !== 'object') return null\n const obj = args as Record<string, unknown>\n if (typeof obj.file_path === 'string') return obj.file_path\n if (typeof obj.path === 'string') return obj.path\n if (typeof obj.absolute_path === 'string') return obj.absolute_path\n return null\n}\n\n/** Convert arbitrary recovered payload values into compact text previews when possible. */\nfunction stringifyOrNull(value: unknown): string | null {\n if (value == null) return null\n if (typeof value === 'string') return value\n try {\n return JSON.stringify(value)\n } catch {\n return null\n }\n}\n\n/** Build searchable Claude documents while excluding hidden thinking from default search. */\nfunction buildSearchDocs(pending: PendingState): void {\n const sessionId = pending.session?.session_id ?? null\n if (!sessionId) return\n\n const blocksByMsg = new Map<string, PendingBlock[]>()\n for (const b of pending.blocks) {\n if (!b.message_id) continue\n if (!b.text_inline) continue\n if (b.block_type !== 'text' && b.block_type !== 'thinking' && b.block_type !== 'tool_result') continue\n const list = blocksByMsg.get(b.message_id) ?? []\n list.push(b)\n blocksByMsg.set(b.message_id, list)\n }\n\n for (const m of pending.messages) {\n const blks = blocksByMsg.get(m.message_id) ?? []\n const text = blks\n .filter((b) => b.block_type !== 'thinking') // hide reasoning from default search\n .map((b) => b.text_inline ?? '')\n .join('\\n')\n .trim()\n if (!text) continue\n pending.searchDocs.push({\n doc_id: `msg:${m.message_id}`,\n entity_type: 'message',\n entity_id: m.message_id,\n timestamp: m.timestamp,\n role: m.role,\n tool_name: null,\n canonical_tool_type: null,\n field_kind: m.role === 'user' ? 'user_prompt' : m.role === 'tool' ? 'tool_result' : 'assistant_text',\n text,\n })\n }\n\n for (const c of pending.toolCallsList) {\n if (c.command) {\n pending.searchDocs.push({\n doc_id: `tc:cmd:${c.tool_call_id}`,\n entity_type: 'tool_call',\n entity_id: c.tool_call_id,\n timestamp: c.timestamp_start,\n role: null,\n tool_name: c.tool_name,\n canonical_tool_type: c.canonical_tool_type,\n field_kind: 'command',\n text: c.command,\n })\n }\n if (c.path) {\n pending.searchDocs.push({\n doc_id: `tc:path:${c.tool_call_id}`,\n entity_type: 'tool_call',\n entity_id: c.tool_call_id,\n timestamp: c.timestamp_start,\n role: null,\n tool_name: c.tool_name,\n canonical_tool_type: c.canonical_tool_type,\n field_kind: 'file_path',\n text: c.path,\n })\n }\n }\n\n for (const r of pending.toolResults) {\n if (!r.preview) continue\n pending.searchDocs.push({\n doc_id: `tr:preview:${r.tool_result_id}`,\n entity_type: 'tool_result',\n entity_id: r.tool_result_id,\n timestamp: null,\n role: null,\n tool_name: null,\n canonical_tool_type: null,\n field_kind: r.is_error ? 'error' : 'tool_result',\n text: r.preview,\n })\n }\n}\n\n/** Insert staged Claude rows in foreign-key order after CAS objects are already durable. */\nfunction flushPending(\n bundle: Bundle,\n pending: PendingState,\n meta: { modelFirst: string | null; modelLast: string | null },\n): void {\n if (!pending.session) return\n\n const insertRaw = prepare(\n bundle.db,\n `INSERT OR IGNORE INTO raw_records (\n raw_record_id, source_file_id, source_tool, record_kind, ordinal,\n line_no, json_pointer, native_id, raw_object_id, decoded_json_object_id,\n parser_status, confidence, import_batch_id\n ) VALUES (?, ?, 'claude', 'jsonl_line', ?, ?, NULL, ?, ?, ?, ?, ?, ?)`,\n )\n for (const r of pending.rawRecords) {\n insertRaw.run(\n r.raw_record_id,\n r.source_file_id,\n r.ordinal,\n r.line_no,\n r.native_id,\n r.raw_object_id,\n r.decoded_json_object_id,\n r.parser_status,\n r.confidence,\n r.import_batch_id,\n )\n }\n\n prepare(\n bundle.db,\n `INSERT OR REPLACE INTO sessions (\n session_id, source_tool, source_session_id, project_id, parent_session_id,\n is_subagent, agent_role, agent_nickname, title, summary,\n start_ts, end_ts, cwd_initial, git_branch_initial,\n model_first, model_last, status, timeline_confidence, raw_record_id\n ) VALUES (?, 'claude', ?, NULL, NULL, ?, ?, ?, ?, NULL, ?, ?, ?, ?, ?, ?, 'completed', 'high', ?)`,\n ).run(\n pending.session.session_id,\n pending.session.source_session_id,\n pending.session.is_subagent,\n pending.session.agent_role,\n pending.session.agent_nickname,\n pending.session.title,\n pending.session.start_ts,\n pending.session.end_ts,\n pending.session.cwd_initial,\n pending.session.git_branch_initial,\n meta.modelFirst,\n meta.modelLast,\n pending.session.raw_record_id,\n )\n\n const insertEvent = prepare(\n bundle.db,\n `INSERT OR REPLACE INTO events (\n event_id, session_id, turn_id, source_event_id, event_type, source_type,\n subtype, timestamp, ordinal, actor, payload_object_id, raw_record_id,\n confidence, is_derived\n ) VALUES (?, ?, NULL, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 0)`,\n )\n for (const e of pending.events) {\n insertEvent.run(\n e.event_id,\n pending.session.session_id,\n e.source_event_id,\n e.event_type,\n e.source_type,\n e.subtype,\n e.timestamp,\n e.ordinal,\n e.actor,\n e.payload_object_id,\n e.raw_record_id,\n e.confidence,\n )\n }\n\n const insertMessage = prepare(\n bundle.db,\n `INSERT OR REPLACE INTO messages (\n message_id, session_id, turn_id, event_id, source_message_id, role,\n author_name, model, timestamp, ordinal, parent_message_id, request_id,\n status, raw_record_id\n ) VALUES (?, ?, NULL, ?, ?, ?, NULL, ?, ?, ?, ?, NULL, NULL, ?)`,\n )\n for (const m of pending.messages) {\n insertMessage.run(\n m.message_id,\n pending.session.session_id,\n m.event_id,\n m.source_message_id,\n m.role,\n m.model,\n m.timestamp,\n m.ordinal,\n m.parent_message_id,\n m.raw_record_id,\n )\n }\n\n const insertBlock = prepare(\n bundle.db,\n `INSERT OR REPLACE INTO content_blocks (\n block_id, message_id, event_id, session_id, ordinal, block_type,\n text_object_id, text_inline, mime_type, token_count, is_error,\n is_redacted, visibility, raw_record_id\n ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, NULL, NULL, ?, 0, ?, ?)`,\n )\n for (const b of pending.blocks) {\n insertBlock.run(\n b.block_id,\n b.message_id,\n b.event_id,\n pending.session.session_id,\n b.ordinal,\n b.block_type,\n b.text_object_id,\n b.text_inline,\n b.is_error,\n b.visibility,\n b.raw_record_id,\n )\n }\n\n const insertToolCall = prepare(\n bundle.db,\n `INSERT OR REPLACE INTO tool_calls (\n tool_call_id, session_id, turn_id, message_id, event_id,\n source_call_id, tool_name, canonical_tool_type, args_object_id,\n command, cwd, path, query, timestamp_start, timestamp_end, status,\n raw_record_id\n ) VALUES (?, ?, NULL, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, NULL, ?, ?)`,\n )\n for (const c of pending.toolCallsList) {\n insertToolCall.run(\n c.tool_call_id,\n pending.session.session_id,\n c.message_id,\n c.event_id,\n c.source_call_id,\n c.tool_name,\n c.canonical_tool_type,\n c.args_object_id,\n c.command,\n c.cwd,\n c.path,\n c.query,\n c.timestamp_start,\n c.status,\n c.raw_record_id,\n )\n }\n\n const insertToolResult = prepare(\n bundle.db,\n `INSERT OR REPLACE INTO tool_results (\n tool_result_id, tool_call_id, session_id, message_id, event_id,\n source_call_id, status, is_error, exit_code, duration_ms,\n stdout_object_id, stderr_object_id, output_object_id, preview, raw_record_id\n ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,\n )\n for (const r of pending.toolResults) {\n insertToolResult.run(\n r.tool_result_id,\n r.tool_call_id,\n pending.session.session_id,\n r.message_id,\n r.event_id,\n r.source_call_id,\n r.status,\n r.is_error,\n r.exit_code,\n r.duration_ms,\n r.stdout_object_id,\n r.stderr_object_id,\n r.output_object_id,\n r.preview,\n r.raw_record_id,\n )\n }\n\n const insertArtifact = prepare(\n bundle.db,\n `INSERT OR REPLACE INTO artifacts (\n artifact_id, session_id, project_id, source_tool, kind, path,\n logical_path, object_id, text_object_id, mime_type, size_bytes,\n created_ts, raw_record_id\n ) VALUES (?, ?, NULL, 'claude', ?, ?, ?, ?, ?, ?, ?, ?, ?)`,\n )\n for (const a of pending.artifacts) {\n insertArtifact.run(\n a.artifact_id,\n pending.session.session_id,\n a.kind,\n a.path,\n a.logical_path,\n a.object_id,\n a.text_object_id,\n a.mime_type,\n a.size_bytes,\n a.created_ts,\n a.raw_record_id,\n )\n }\n\n const insertEdge = prepare(\n bundle.db,\n `INSERT OR IGNORE INTO edges (\n src_type, src_id, dst_type, dst_id, edge_type, confidence, source,\n raw_record_id, metadata_object_id\n ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, NULL)`,\n )\n for (const e of pending.edges) {\n insertEdge.run(e.src_type, e.src_id, e.dst_type, e.dst_id, e.edge_type, e.confidence, e.source, e.raw_record_id)\n }\n\n const insertSearch = prepare(\n bundle.db,\n `INSERT OR REPLACE INTO search_docs (\n doc_id, entity_type, entity_id, session_id, project_id, timestamp,\n role, tool_name, canonical_tool_type, field_kind, text\n ) VALUES (?, ?, ?, ?, NULL, ?, ?, ?, ?, ?, ?)`,\n )\n for (const d of pending.searchDocs) {\n insertSearch.run(\n d.doc_id,\n d.entity_type,\n d.entity_id,\n pending.session.session_id,\n d.timestamp,\n d.role,\n d.tool_name,\n d.canonical_tool_type,\n d.field_kind,\n d.text,\n )\n }\n}\n","import type { SourceTool, ToolCallStatus } from './types.js'\n\nconst CANONICAL_TOOL_CALL_STATUSES = new Set<string>(['started', 'success', 'error', 'cancelled', 'unknown'])\n\n/**\n * Canonical session lifecycle vocabulary used across importers. Sources spell\n * these out in many ways (`stop`, `tool_calls`, `failure`, `cancel`); the\n * normalizer collapses them so the projection stays consistent.\n */\nexport function normalizeSessionStatus(status: string | null | undefined): string | null {\n if (!status) return null\n const normalized = status.trim().toLowerCase()\n if (normalized === 'stop' || normalized === 'completed' || normalized === 'success') return 'completed'\n if (normalized === 'tool_calls') return 'completed'\n if (normalized === 'error' || normalized === 'failed' || normalized === 'failure') return 'error'\n if (normalized === 'cancelled' || normalized === 'canceled' || normalized === 'cancel') return 'cancelled'\n return 'unknown'\n}\n\n/** Normalize source-specific tool lifecycle values into the canonical vocabulary. */\nexport function normalizeToolCallStatus(sourceTool: SourceTool, raw: string | null | undefined): ToolCallStatus {\n const status = raw?.trim()\n if (!status) return 'unknown'\n if (CANONICAL_TOOL_CALL_STATUSES.has(status)) return status as ToolCallStatus\n\n switch (sourceTool) {\n case 'codex':\n if (status === 'completed') return 'success'\n if (status === 'in_progress') return 'started'\n if (status === 'incomplete' || status === 'failed' || status === 'timeout') return 'error'\n if (status === 'canceled') return 'cancelled'\n return 'unknown'\n case 'hermes':\n if (status === 'stop' || status === 'tool_calls') return 'success'\n if (status === 'length' || status === 'content_filter') return 'error'\n return 'unknown'\n case 'gemini':\n case 'claude':\n case 'cursor':\n return 'unknown'\n }\n}\n","import { readdir } from 'node:fs/promises'\nimport path from 'node:path'\n\n/** Discovered Claude Code JSONL file plus path-derived project/subagent context. */\nexport interface ClaudeFile {\n /** Absolute path to a JSONL session file. */\n filePath: string\n /** Project slug (the dashed directory name under projects/). */\n projectSlug: string\n /** Whether the file is a subagent rollout under `<session>/subagents/`. */\n isSubagent: boolean\n /**\n * For main files: the session-id derived from the filename.\n * For subagent files: the session-id from the parent directory; the subagent\n * has the same `sessionId` field internally but a distinct `agentId`.\n */\n parentSessionId: string | null\n /** For subagent files only: agent id parsed from `agent-<id>.jsonl`. */\n agentId: string | null\n /** Path to the companion `.meta.json`, if any (subagents only). */\n metaPath: string | null\n}\n\n/**\n * Walk `<root>` (typically `~/.claude/projects`) and yield every JSONL file\n * under it, classified as main session or subagent. We deliberately ignore\n * `sessions-index.json` (per the recovery report it's incomplete) and skip\n * `tool-results/` and `memory/` for the MVP.\n */\nexport async function* discoverClaudeFiles(root: string): AsyncGenerator<ClaudeFile, void, void> {\n const projectDirs = await readdirSafe(root)\n for (const project of projectDirs) {\n if (!project.isDirectory()) continue\n const projectRoot = path.join(root, project.name)\n yield* walkProject(projectRoot, project.name)\n }\n}\n\n/** Classify project children as top-level session files or subagent rollouts. */\nasync function* walkProject(projectRoot: string, projectSlug: string): AsyncGenerator<ClaudeFile, void, void> {\n const entries = await readdirSafe(projectRoot)\n for (const entry of entries) {\n if (entry.isFile() && entry.name.endsWith('.jsonl')) {\n yield {\n filePath: path.join(projectRoot, entry.name),\n projectSlug,\n isSubagent: false,\n parentSessionId: null,\n agentId: null,\n metaPath: null,\n }\n continue\n }\n if (entry.isDirectory()) {\n // Could be a session-id dir with subagents/ inside; or memory/; or other.\n const subagentsDir = path.join(projectRoot, entry.name, 'subagents')\n const subagentEntries = await readdirSafe(subagentsDir)\n for (const sub of subagentEntries) {\n if (!sub.isFile() || !sub.name.endsWith('.jsonl')) continue\n if (!sub.name.startsWith('agent-')) continue\n const agentId = sub.name.slice('agent-'.length, -'.jsonl'.length)\n const metaCandidate = path.join(subagentsDir, `agent-${agentId}.meta.json`)\n const metaExists = subagentEntries.some((e) => e.isFile() && e.name === `agent-${agentId}.meta.json`)\n yield {\n filePath: path.join(subagentsDir, sub.name),\n projectSlug,\n isSubagent: true,\n parentSessionId: entry.name,\n agentId,\n metaPath: metaExists ? metaCandidate : null,\n }\n }\n }\n }\n}\n\n/** Read a directory as empty when optional Claude folders are absent. */\nasync function readdirSafe(dir: string): Promise<import('node:fs').Dirent[]> {\n try {\n return await readdir(dir, { withFileTypes: true })\n } catch {\n return []\n }\n}\n","import { readFile } from 'node:fs/promises'\nimport path from 'node:path'\nimport type { Bundle } from '../../core/bundle.js'\nimport {\n type ObjectId,\n type PendingObjects,\n createPendingObjects,\n flushPendingObjects,\n stageBytes,\n stageJson,\n stageText,\n} from '../../core/cas/index.js'\nimport { prepare, transactional } from '../../core/db.js'\nimport {\n artifactId,\n blockId,\n eventId as makeEventId,\n messageId as makeMessageId,\n rawRecordId as makeRawRecordId,\n sessionId as makeSessionId,\n toolCallId as makeToolCallId,\n toolResultId as makeToolResultId,\n turnId as makeTurnId,\n} from '../../core/domain/ids.js'\nimport { normalizeToolCallStatus } from '../../core/domain/status.js'\nimport { getErrorMessage } from '../../core/errors.js'\nimport {\n type ImportBatch,\n type ImportCounts,\n emptyCounts,\n finishBatch,\n recordError,\n startBatch,\n} from '../../core/ingest/batch.js'\nimport { registerSourceFile } from '../../core/ingest/idempotency.js'\nimport type { CompileLogger, CompileOptions } from '../compile-options.js'\nimport { discoverCodexSessions } from './discover.js'\nimport type {\n CodexContentItem,\n CodexEnvelope,\n CodexEventMsgPayload,\n CodexResponseItemPayload,\n CodexSessionMetaPayload,\n CodexTurnContextPayload,\n} from './types.js'\n\n/** Result returned after a Codex compile batch finishes or records a failed batch. */\nexport interface CompileResult {\n /** Import batch created for this Codex run. */\n batch: ImportBatch\n /** Final counts accumulated while importing Codex files. */\n counts: ImportCounts\n}\n\n/** Maximum inline text retained in normalized rows before full content moves to CAS. */\nconst PREVIEW_MAX = 4_000\n\n/**\n * Number of Codex files prepared concurrently before each short per-file\n * database transaction. Prepare is I/O-heavy; applying rows stays serial to\n * avoid long write transactions and growing WAL lookup costs.\n */\nconst CODEX_PREPARE_CONCURRENCY = 8\n\n/** Compile Codex JSONL session files under `root` into the bundle. */\nexport async function compileCodex(bundle: Bundle, root: string, options: CompileOptions = {}): Promise<CompileResult> {\n const logger = options.logger\n const batch = startBatch(bundle, 'codex', [root])\n const counts = emptyCounts()\n logger?.info({ batch_id: batch.batch_id, root }, 'codex batch started')\n\n try {\n const files: string[] = []\n for await (const filePath of discoverCodexSessions(root)) {\n files.push(filePath)\n logger?.debug({ path: filePath }, 'codex source file discovered')\n }\n counts.source_files_seen = files.length\n\n for (let i = 0; i < files.length; i += CODEX_PREPARE_CONCURRENCY) {\n const slice = files.slice(i, i + CODEX_PREPARE_CONCURRENCY)\n await processCodexBatch(bundle, batch, slice, counts, logger)\n }\n\n linkSubagentParents(bundle)\n logger?.debug({ batch_id: batch.batch_id }, 'codex subagent parent links refreshed')\n finishBatch(bundle, batch, counts, 'completed')\n logger?.info({ batch_id: batch.batch_id, counts }, 'codex batch completed')\n } catch (error) {\n finishBatch(bundle, batch, counts, 'failed')\n logger?.error({ err: error, batch_id: batch.batch_id, counts }, 'codex batch failed')\n throw error\n }\n\n return { batch, counts }\n}\n\n/** Parsed and CAS-staged Codex file waiting for the short domain insert transaction. */\ninterface CodexPrepared {\n filePath: string\n pending: PendingState\n meta: { sessionEndTs: string | null; modelFirst: string | null; modelLast: string | null }\n}\n\n/** Per-file state tracked while a concurrent Codex prepare slice is applied. */\ninterface CodexBatchItem {\n filePath: string\n prepared: CodexPrepared | null\n fileCounts: FileCounts\n prepareError: Error | null\n applyError: Error | null\n}\n\n/** Prepare a slice concurrently, then apply each prepared file in its own transaction. */\nasync function processCodexBatch(\n bundle: Bundle,\n batch: ImportBatch,\n slice: string[],\n counts: ImportCounts,\n logger?: CompileLogger,\n): Promise<void> {\n // Phase A: parse + CAS flush for the whole slice concurrently. Each file's\n // prepare is independent — registerSourceFile is idempotent and CAS writes\n // are content-addressed — so we can overlap their I/O.\n const items = await Promise.all(\n slice.map(async (filePath): Promise<CodexBatchItem> => {\n try {\n const result = await prepareCodexFile(bundle, batch, filePath, logger)\n return {\n filePath,\n prepared: result.prepared,\n fileCounts: result.counts,\n prepareError: null,\n applyError: null,\n }\n } catch (err) {\n return {\n filePath,\n prepared: null,\n fileCounts: emptyFileCounts(),\n prepareError: err as Error,\n applyError: null,\n }\n }\n }),\n )\n\n // Phase B: domain INSERTs run one file at a time, each in its own short\n // transaction. We tried wrapping the whole slice in one outer transaction\n // with savepoints per file — that turned the steady-state insert loop CPU-\n // bound because INSERT OR IGNORE lookups had to walk the growing WAL inside\n // the long transaction. Per-file commits keep the WAL small.\n for (const item of items) {\n if (item.prepareError || !item.prepared) continue\n try {\n transactional(bundle.db, () => applyCodexFile(bundle, item.prepared as CodexPrepared))\n } catch (err) {\n item.applyError = err as Error\n }\n }\n\n // Phase C: aggregate counts and record per-file errors.\n for (const item of items) {\n const err = item.prepareError ?? item.applyError\n if (err) {\n counts.errors++\n logger?.warn({ err, path: item.filePath }, 'codex source file failed')\n await recordError(bundle, batch.batch_id, {\n kind: 'codex_file_failed',\n message: getErrorMessage(err),\n payload: { path: item.filePath },\n })\n } else {\n addCounts(counts, item.fileCounts)\n }\n }\n}\n\n/**\n * After every file is committed, fill `sessions.parent_session_id` from any\n * `edges(spawned)` whose target session now exists. We deliberately set\n * `parent_session_id=NULL` during per-file inserts because a subagent file may\n * be processed before the parent file; deferring the link to a single UPDATE\n * keeps every per-file transaction self-contained.\n */\nfunction linkSubagentParents(bundle: Bundle): void {\n bundle.db.exec(`\n UPDATE sessions\n SET parent_session_id = (\n SELECT e.src_id\n FROM edges e\n WHERE e.edge_type = 'spawned'\n AND e.dst_type = 'session'\n AND e.dst_id = sessions.session_id\n AND EXISTS (SELECT 1 FROM sessions p WHERE p.session_id = e.src_id)\n LIMIT 1\n )\n WHERE parent_session_id IS NULL\n AND is_subagent = 1\n `)\n}\n\n/** Per-source-file deltas that are merged into the import batch counts. */\ninterface FileCounts {\n source_files_imported: number\n source_files_skipped: number\n raw_records: number\n sessions: number\n turns: number\n events: number\n messages: number\n content_blocks: number\n tool_calls: number\n tool_results: number\n artifacts: number\n edges: number\n errors: number\n}\n\n/** Create zeroed file counters for a Codex file that may still fail or be skipped. */\nfunction emptyFileCounts(): FileCounts {\n return {\n source_files_imported: 0,\n source_files_skipped: 0,\n raw_records: 0,\n sessions: 0,\n turns: 0,\n events: 0,\n messages: 0,\n content_blocks: 0,\n tool_calls: 0,\n tool_results: 0,\n artifacts: 0,\n edges: 0,\n errors: 0,\n }\n}\n\n/** Merge a single Codex file's normalized row counts into batch totals. */\nfunction addCounts(target: ImportCounts, source: FileCounts): void {\n target.source_files_imported += source.source_files_imported\n target.source_files_skipped += source.source_files_skipped\n target.raw_records += source.raw_records\n target.sessions += source.sessions\n target.turns += source.turns\n target.events += source.events\n target.messages += source.messages\n target.content_blocks += source.content_blocks\n target.tool_calls += source.tool_calls\n target.tool_results += source.tool_results\n target.artifacts += source.artifacts\n target.edges += source.edges\n target.errors += source.errors\n}\n\n// ---- per-file pipeline ---------------------------------------------------\n\n/** Raw record row staged from a Codex JSONL line before database insertion. */\ninterface PendingRawRecord {\n raw_record_id: string\n source_file_id: string\n source_tool: 'codex'\n record_kind: 'jsonl_line'\n ordinal: number\n line_no: number\n json_pointer: null\n native_id: string | null\n raw_object_id: ObjectId\n decoded_json_object_id: ObjectId | null\n parser_status: 'ok' | 'partial' | 'failed'\n confidence: 'high' | 'medium' | 'low'\n import_batch_id: string\n}\n\n/** Session row staged from `session_meta` or a filename fallback. */\ninterface PendingSession {\n session_id: string\n source_session_id: string\n parent_session_id: string | null\n is_subagent: 0 | 1\n agent_role: string | null\n agent_nickname: string | null\n title: string | null\n start_ts: string | null\n cwd_initial: string | null\n git_branch_initial: string | null\n raw_record_id: string | null\n}\n\n/** Turn row staged from Codex `turn_context` events. */\ninterface PendingTurn {\n turn_id: string\n ordinal: number\n source_turn_id: string | null\n start_ts: string | null\n model: string | null\n cwd: string | null\n approval_policy: string | null\n sandbox_policy: string | null\n effort: string | null\n raw_record_id: string\n}\n\n/** Event row staged from Codex response items and operational event messages. */\ninterface PendingEvent {\n event_id: string\n ordinal: number\n turn_id: string | null\n source_event_id: string | null\n event_type: string\n source_type: string\n subtype: string | null\n timestamp: string | null\n actor: string | null\n payload_object_id: ObjectId | null\n raw_record_id: string\n confidence: 'high' | 'medium' | 'low'\n}\n\n/** Message row staged from Codex assistant/user/tool content. */\ninterface PendingMessage {\n message_id: string\n turn_id: string | null\n event_id: string | null\n source_message_id: string | null\n role: 'system_prompt' | 'developer' | 'user' | 'assistant' | 'tool' | 'operational'\n model: string | null\n timestamp: string | null\n ordinal: number\n raw_record_id: string\n}\n\n/** Content block row staged from Codex message content arrays. */\ninterface PendingBlock {\n block_id: string\n message_id: string | null\n event_id: string | null\n ordinal: number\n block_type: string\n text_object_id: ObjectId | null\n text_inline: string | null\n raw_record_id: string\n}\n\n/** Tool call row staged from Codex function-call style records. */\ninterface PendingToolCall {\n tool_call_id: string\n turn_id: string | null\n message_id: string | null\n event_id: string | null\n source_call_id: string | null\n tool_name: string\n canonical_tool_type: string\n args_object_id: ObjectId | null\n command: string | null\n cwd: string | null\n path: string | null\n query: string | null\n timestamp_start: string | null\n status: string | null\n raw_record_id: string\n}\n\n/** Tool result row staged from function-call output and operational tool events. */\ninterface PendingToolResult {\n tool_result_id: string\n tool_call_id: string | null\n source_call_id: string | null\n message_id: string | null\n event_id: string | null\n status: string | null\n is_error: 0 | 1\n exit_code: number | null\n duration_ms: number | null\n stdout_object_id: ObjectId | null\n stderr_object_id: ObjectId | null\n output_object_id: ObjectId | null\n preview: string | null\n raw_record_id: string\n}\n\n/** Artifact row staged from Codex patch or file-producing events. */\ninterface PendingArtifact {\n artifact_id: string\n kind: string\n path: string | null\n logical_path: string | null\n object_id: ObjectId | null\n text_object_id: ObjectId | null\n mime_type: string | null\n size_bytes: number\n created_ts: string | null\n raw_record_id: string\n}\n\n/** Graph edge row staged for recovered Codex subagent relationships. */\ninterface PendingEdge {\n src_type: string\n src_id: string\n dst_type: string\n dst_id: string\n edge_type: string\n confidence: 'high' | 'medium' | 'low'\n source: string\n raw_record_id: string | null\n}\n\n/** Search index row staged from normalized Codex messages, commands, paths, and previews. */\ninterface PendingSearchDoc {\n doc_id: string\n entity_type: string\n entity_id: string\n timestamp: string | null\n role: string | null\n tool_name: string | null\n canonical_tool_type: string | null\n field_kind: string\n text: string\n}\n\n/** Parse a Codex JSONL file, stage CAS objects, and return rows for later synchronous flush. */\nasync function prepareCodexFile(\n bundle: Bundle,\n batch: ImportBatch,\n filePath: string,\n logger?: CompileLogger,\n): Promise<{ prepared: CodexPrepared | null; counts: FileCounts }> {\n const counts = emptyFileCounts()\n\n const { row: sourceFileRow, alreadyKnown } = await registerSourceFile(bundle, {\n sourceTool: 'codex',\n absolutePath: path.resolve(filePath),\n fileKind: 'jsonl',\n })\n\n if (alreadyKnown) {\n // We've already imported this file (same path,size,mtime,hash). Skip.\n counts.source_files_skipped = 1\n logger?.debug({ path: filePath, source_file_id: sourceFileRow.source_file_id }, 'codex source file skipped')\n return { prepared: null, counts }\n }\n\n counts.source_files_imported = 1\n logger?.debug({ path: filePath, source_file_id: sourceFileRow.source_file_id }, 'codex source file registered')\n\n const text = await readFile(filePath, 'utf8')\n const rawLines = text.split('\\n')\n const lines = rawLines[rawLines.length - 1] === '' ? rawLines.slice(0, -1) : rawLines\n\n const pending = {\n rawRecords: [] as PendingRawRecord[],\n session: null as PendingSession | null,\n turns: [] as PendingTurn[],\n events: [] as PendingEvent[],\n messages: [] as PendingMessage[],\n blocks: [] as PendingBlock[],\n toolCalls: new Map<string, PendingToolCall>(), // by source_call_id\n toolCallsList: [] as PendingToolCall[],\n toolResults: [] as PendingToolResult[],\n artifacts: [] as PendingArtifact[],\n edges: [] as PendingEdge[],\n searchDocs: [] as PendingSearchDoc[],\n objects: createPendingObjects(),\n }\n\n let sessionStartTs: string | null = null\n let sessionEndTs: string | null = null\n let modelFirst: string | null = null\n let modelLast: string | null = null\n let messageOrdinal = 0\n let turnOrdinal = 0\n\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i]\n if (!line || line.length === 0) continue\n const lineNo = i + 1\n const ordinal = i\n\n const lineBytes = Buffer.from(line, 'utf8')\n const rawObjectId = stageBytes(pending.objects, lineBytes, {\n mimeType: 'application/jsonl-line',\n encoding: 'utf-8',\n })\n\n let parsed: CodexEnvelope | null = null\n let parserStatus: 'ok' | 'partial' | 'failed' = 'ok'\n try {\n parsed = JSON.parse(line) as CodexEnvelope\n } catch {\n parserStatus = 'failed'\n }\n\n // The raw line already IS the JSON for `parserStatus === 'ok'`, so we\n // skip storing a re-serialized copy as `decoded_json_object_id`. Saves\n // ~half the CAS writes per file. Nothing reads it back later.\n const decodedObjectId: ObjectId | null = null\n\n const nativeId = parsed ? extractNativeId(parsed) : null\n\n const rawRecordId = makeRawRecordId(sourceFileRow.source_file_id, ordinal, rawObjectId)\n\n pending.rawRecords.push({\n raw_record_id: rawRecordId,\n source_file_id: sourceFileRow.source_file_id,\n source_tool: 'codex',\n record_kind: 'jsonl_line',\n ordinal,\n line_no: lineNo,\n json_pointer: null,\n native_id: nativeId,\n raw_object_id: rawObjectId,\n decoded_json_object_id: decodedObjectId,\n parser_status: parserStatus,\n confidence: parserStatus === 'ok' ? 'high' : 'low',\n import_batch_id: batch.batch_id,\n })\n\n if (!parsed) continue\n\n const ts = typeof parsed.timestamp === 'string' ? parsed.timestamp : null\n if (ts) {\n if (!sessionStartTs || ts < sessionStartTs) sessionStartTs = ts\n if (!sessionEndTs || ts > sessionEndTs) sessionEndTs = ts\n }\n\n const type = typeof parsed.type === 'string' ? parsed.type : null\n const payload = (parsed.payload ?? {}) as Record<string, unknown>\n\n if (type === 'session_meta') {\n const meta = payload as CodexSessionMetaPayload\n const sourceSessionId = meta.id ?? path.basename(filePath, '.jsonl')\n const sessionId = makeSessionId('codex', sourceSessionId)\n\n // First session_meta wins; later ones (rare) become operational events.\n if (!pending.session) {\n const sub = parseSubagent(meta.source)\n const parentSessionId = sub ? makeSessionId('codex', sub.parent_thread_id) : null\n pending.session = {\n session_id: sessionId,\n source_session_id: sourceSessionId,\n parent_session_id: parentSessionId,\n is_subagent: sub ? 1 : 0,\n agent_role: meta.agent_role ?? sub?.agent_role ?? null,\n agent_nickname: meta.agent_nickname ?? sub?.agent_nickname ?? null,\n title: null,\n start_ts: meta.timestamp ?? ts,\n cwd_initial: meta.cwd ?? null,\n git_branch_initial: meta.git?.branch ?? null,\n raw_record_id: rawRecordId,\n }\n if (parentSessionId) {\n pending.edges.push({\n src_type: 'session',\n src_id: parentSessionId,\n dst_type: 'session',\n dst_id: sessionId,\n edge_type: 'spawned',\n confidence: 'high',\n source: 'explicit',\n raw_record_id: rawRecordId,\n })\n }\n }\n continue\n }\n\n // From here on, we need a session_id. Ensure we have one (fallback if no\n // session_meta appeared yet).\n const sessionId = pending.session?.session_id ?? makeSessionId('codex', path.basename(filePath, '.jsonl'))\n if (!pending.session) {\n pending.session = {\n session_id: sessionId,\n source_session_id: path.basename(filePath, '.jsonl'),\n parent_session_id: null,\n is_subagent: 0,\n agent_role: null,\n agent_nickname: null,\n title: null,\n start_ts: ts,\n cwd_initial: null,\n git_branch_initial: null,\n raw_record_id: null,\n }\n }\n\n if (type === 'turn_context') {\n const tc = payload as CodexTurnContextPayload\n const turnId = makeTurnId(sessionId, turnOrdinal, tc.turn_id ?? null)\n const turn: PendingTurn = {\n turn_id: turnId,\n ordinal: turnOrdinal++,\n source_turn_id: tc.turn_id ?? null,\n start_ts: ts,\n model: tc.model ?? null,\n cwd: tc.cwd ?? null,\n approval_policy: tc.approval_policy ?? null,\n sandbox_policy: stringifyOrNull(tc.sandbox_policy),\n effort: tc.effort ?? null,\n raw_record_id: rawRecordId,\n }\n pending.turns.push(turn)\n if (turn.model) {\n if (!modelFirst) modelFirst = turn.model\n modelLast = turn.model\n }\n continue\n }\n\n const currentTurnId = pending.turns.length > 0 ? pending.turns[pending.turns.length - 1]!.turn_id : null\n\n if (type === 'response_item') {\n const ri = payload as CodexResponseItemPayload\n handleResponseItem(\n bundle,\n sessionId,\n currentTurnId,\n rawRecordId,\n ordinal,\n ts,\n ri,\n decodedObjectId,\n () => messageOrdinal++,\n modelLast,\n pending,\n )\n continue\n }\n\n if (type === 'event_msg') {\n const em = payload as CodexEventMsgPayload\n await handleEventMsg(bundle, sessionId, currentTurnId, rawRecordId, ordinal, ts, em, decodedObjectId, pending)\n continue\n }\n\n if (type === 'compacted') {\n pending.events.push({\n event_id: makeEventId(sessionId, ordinal, 'compaction'),\n ordinal,\n turn_id: currentTurnId,\n source_event_id: null,\n event_type: 'compaction',\n source_type: 'compacted',\n subtype: null,\n timestamp: ts,\n actor: 'system',\n payload_object_id: decodedObjectId,\n raw_record_id: rawRecordId,\n confidence: 'high',\n })\n continue\n }\n\n // Legacy top-level message / function_call etc.\n if (type === 'message') {\n const ri = payload as CodexResponseItemPayload\n // Treat as if it were wrapped in response_item.\n handleResponseItem(\n bundle,\n sessionId,\n currentTurnId,\n rawRecordId,\n ordinal,\n ts,\n { ...ri, type: 'message' },\n decodedObjectId,\n () => messageOrdinal++,\n modelLast,\n pending,\n )\n }\n // Anything else: keep as raw record, do not normalize. The presence in\n // raw_records is enough for re-processing later.\n }\n\n if (pending.session) {\n pending.session.start_ts ??= sessionStartTs\n }\n\n // Build search_docs from messages and tool calls already accumulated.\n buildSearchDocs(pending)\n\n // Persist the staged CAS objects to disk + the `objects` table BEFORE the\n // domain transaction. We do filesystem writes in parallel (better-sqlite3\n // transactions are synchronous, so this can't run inside `transactional`).\n await flushPendingObjects(bundle, pending.objects)\n\n counts.raw_records = pending.rawRecords.length\n counts.sessions = pending.session ? 1 : 0\n counts.turns = pending.turns.length\n counts.events = pending.events.length\n counts.messages = pending.messages.length\n counts.content_blocks = pending.blocks.length\n counts.tool_calls = pending.toolCallsList.length\n counts.tool_results = pending.toolResults.length\n counts.artifacts = pending.artifacts.length\n counts.edges = pending.edges.length\n logger?.debug({ path: filePath, source_file_id: sourceFileRow.source_file_id, counts }, 'codex source file prepared')\n\n return {\n prepared: {\n filePath,\n pending,\n meta: { sessionEndTs, modelFirst, modelLast },\n },\n counts,\n }\n}\n\n/** Flush one prepared Codex file's normalized rows inside the caller's transaction. */\nfunction applyCodexFile(bundle: Bundle, prep: CodexPrepared): void {\n flushPending(bundle, prep.pending, {\n sessionEndTs: prep.meta.sessionEndTs,\n modelFirst: prep.meta.modelFirst,\n modelLast: prep.meta.modelLast,\n sourceTool: 'codex',\n })\n}\n\n/** All normalized Codex rows staged for one source file before FK-ordered flush. */\ninterface PendingState {\n rawRecords: PendingRawRecord[]\n session: PendingSession | null\n turns: PendingTurn[]\n events: PendingEvent[]\n messages: PendingMessage[]\n blocks: PendingBlock[]\n toolCalls: Map<string, PendingToolCall>\n toolCallsList: PendingToolCall[]\n toolResults: PendingToolResult[]\n artifacts: PendingArtifact[]\n edges: PendingEdge[]\n searchDocs: PendingSearchDoc[]\n objects: PendingObjects\n}\n\ntype ResponseItemCtx = {\n sessionId: string\n currentTurnId: string | null\n rawRecordId: string\n ordinal: number\n ts: string | null\n payloadObjectId: ObjectId | null\n nextMsgOrdinal: () => number\n currentModel: string | null\n pending: PendingState\n}\n\nfunction handleResponseItemMessage(ctx: ResponseItemCtx, ri: CodexResponseItemPayload): void {\n const { sessionId, currentTurnId, rawRecordId, ordinal, ts, payloadObjectId, nextMsgOrdinal, currentModel, pending } =\n ctx\n const role = mapMessageRole(ri.role)\n const msgOrdinal = nextMsgOrdinal()\n const messageId = makeMessageId(sessionId, msgOrdinal, null)\n\n const eventId = makeEventId(sessionId, ordinal, 'message')\n pending.events.push({\n event_id: eventId,\n ordinal,\n turn_id: currentTurnId,\n source_event_id: null,\n event_type: 'message',\n source_type: 'response_item.message',\n subtype: null,\n timestamp: ts,\n actor: ri.role ?? null,\n payload_object_id: payloadObjectId,\n raw_record_id: rawRecordId,\n confidence: 'high',\n })\n\n pending.messages.push({\n message_id: messageId,\n turn_id: currentTurnId,\n event_id: eventId,\n source_message_id: null,\n role,\n model: role === 'assistant' ? currentModel : null,\n timestamp: ts,\n ordinal: msgOrdinal,\n raw_record_id: rawRecordId,\n })\n\n const contentItems = Array.isArray(ri.content) ? (ri.content as CodexContentItem[]) : []\n for (let bi = 0; bi < contentItems.length; bi++) {\n const item = contentItems[bi]\n if (!item) continue\n const text = typeof item.text === 'string' ? item.text : null\n const blockType = item.type ?? 'text'\n pending.blocks.push({\n block_id: blockId(messageId, bi),\n message_id: messageId,\n event_id: null,\n ordinal: bi,\n block_type: blockType,\n text_object_id: null,\n text_inline: text,\n raw_record_id: rawRecordId,\n })\n }\n}\n\nfunction handleResponseItemFunctionCall(ctx: ResponseItemCtx, ri: CodexResponseItemPayload): void {\n const { sessionId, currentTurnId, rawRecordId, ordinal, ts, payloadObjectId, pending } = ctx\n const sourceCallId = typeof ri.call_id === 'string' ? ri.call_id : null\n const toolName = typeof ri.name === 'string' ? ri.name : 'unknown'\n const toolCallId = makeToolCallId(sessionId, sourceCallId ?? `${ordinal}`)\n const argsObjectId = ri.arguments != null ? stageJson(pending.objects, ri.arguments) : null\n const command = inferCommandFromArgs(toolName, ri.arguments)\n\n const eventId = makeEventId(sessionId, ordinal, 'tool_call')\n pending.events.push({\n event_id: eventId,\n ordinal,\n turn_id: currentTurnId,\n source_event_id: null,\n event_type: 'tool_call',\n source_type: 'response_item.function_call',\n subtype: toolName,\n timestamp: ts,\n actor: 'assistant',\n payload_object_id: payloadObjectId,\n raw_record_id: rawRecordId,\n confidence: 'high',\n })\n\n const call: PendingToolCall = {\n tool_call_id: toolCallId,\n turn_id: currentTurnId,\n message_id: null,\n event_id: eventId,\n source_call_id: sourceCallId,\n tool_name: toolName,\n canonical_tool_type: canonicalToolType(toolName),\n args_object_id: argsObjectId,\n command,\n cwd: null,\n path: inferPathFromArgs(ri.arguments),\n query: null,\n timestamp_start: ts,\n status: 'started',\n raw_record_id: rawRecordId,\n }\n if (sourceCallId) pending.toolCalls.set(sourceCallId, call)\n pending.toolCallsList.push(call)\n}\n\nfunction handleResponseItemFunctionCallOutput(ctx: ResponseItemCtx, ri: CodexResponseItemPayload): void {\n const { sessionId, currentTurnId, rawRecordId, ordinal, ts, payloadObjectId, pending } = ctx\n const sourceCallId = typeof ri.call_id === 'string' ? ri.call_id : null\n const outputText = stringifyOrNull(ri.output) ?? ''\n const outputObj = isRecord(ri.output) ? ri.output : null\n const isError =\n outputObj?.is_error === true ||\n outputObj?.isError === true ||\n ri.status === 'incomplete' ||\n looksLikeError(outputText)\n ? 1\n : 0\n\n const eventId = makeEventId(sessionId, ordinal, 'tool_result')\n pending.events.push({\n event_id: eventId,\n ordinal,\n turn_id: currentTurnId,\n source_event_id: null,\n event_type: 'tool_result',\n source_type: 'response_item.function_call_output',\n subtype: null,\n timestamp: ts,\n actor: 'tool',\n payload_object_id: payloadObjectId,\n raw_record_id: rawRecordId,\n confidence: 'high',\n })\n\n const matchedCall = sourceCallId ? pending.toolCalls.get(sourceCallId) : undefined\n pending.toolResults.push({\n tool_result_id: makeToolResultId(sessionId, sourceCallId ?? `${ordinal}`),\n tool_call_id: matchedCall?.tool_call_id ?? null,\n source_call_id: sourceCallId,\n message_id: null,\n event_id: eventId,\n status: normalizeToolCallStatus('codex', ri.status),\n is_error: isError,\n exit_code: null,\n duration_ms: null,\n stdout_object_id: null,\n stderr_object_id: null,\n output_object_id: null,\n preview: outputText.slice(0, PREVIEW_MAX),\n raw_record_id: rawRecordId,\n })\n if (matchedCall) {\n matchedCall.status = matchedCall.status === 'started' ? (isError ? 'error' : 'success') : matchedCall.status\n }\n}\n\nfunction handleResponseItemPassthrough(ctx: ResponseItemCtx, ri: CodexResponseItemPayload): void {\n // reasoning, custom_tool_*, web_search_call, ghost_snapshot, etc.: keep as\n // operational events for now. Raw is preserved either way.\n const { sessionId, currentTurnId, rawRecordId, ordinal, ts, payloadObjectId, pending } = ctx\n const subtype = ri.type ?? null\n const eventId = makeEventId(sessionId, ordinal, `response_item.${subtype ?? 'unknown'}`)\n pending.events.push({\n event_id: eventId,\n ordinal,\n turn_id: currentTurnId,\n source_event_id: null,\n event_type: subtype ?? 'response_item',\n source_type: `response_item.${subtype ?? 'unknown'}`,\n subtype,\n timestamp: ts,\n actor: 'assistant',\n payload_object_id: payloadObjectId,\n raw_record_id: rawRecordId,\n confidence: 'high',\n })\n}\n\nconst RESPONSE_ITEM_HANDLERS: Record<string, (ctx: ResponseItemCtx, ri: CodexResponseItemPayload) => void> = {\n message: handleResponseItemMessage,\n function_call: handleResponseItemFunctionCall,\n function_call_output: handleResponseItemFunctionCallOutput,\n}\n\n/** Normalize a Codex `response_item` payload into messages, tool calls/results, or events. */\nfunction handleResponseItem(\n _bundle: Bundle,\n sessionId: string,\n currentTurnId: string | null,\n rawRecordId: string,\n ordinal: number,\n ts: string | null,\n ri: CodexResponseItemPayload,\n payloadObjectId: ObjectId | null,\n nextMsgOrdinal: () => number,\n currentModel: string | null,\n pending: PendingState,\n): void {\n const ctx: ResponseItemCtx = {\n sessionId,\n currentTurnId,\n rawRecordId,\n ordinal,\n ts,\n payloadObjectId,\n nextMsgOrdinal,\n currentModel,\n pending,\n }\n const handler = ri.type ? RESPONSE_ITEM_HANDLERS[ri.type] : undefined\n ;(handler ?? handleResponseItemPassthrough)(ctx, ri)\n}\n\ntype EventMsgCtx = {\n sessionId: string\n currentTurnId: string | null\n rawRecordId: string\n ordinal: number\n ts: string | null\n payloadObjectId: ObjectId | null\n pending: PendingState\n}\n\nfunction handleExecCommandEnd(ctx: EventMsgCtx, em: CodexEventMsgPayload): void {\n const { sessionId, currentTurnId, rawRecordId, ordinal, ts, payloadObjectId, pending } = ctx\n const sourceCallId = em.call_id ?? null\n const stdoutId = em.stdout ? stageText(pending.objects, em.stdout, { mimeType: 'text/plain' }) : null\n const stderrId = em.stderr ? stageText(pending.objects, em.stderr, { mimeType: 'text/plain' }) : null\n const preview = (em.formatted_output ?? em.aggregated_output ?? em.stdout ?? '').slice(0, PREVIEW_MAX)\n const exitCode = typeof em.exit_code === 'number' ? em.exit_code : null\n const isError = exitCode != null && exitCode !== 0 ? 1 : 0\n\n const eventId = makeEventId(sessionId, ordinal, 'exec_command_end')\n pending.events.push({\n event_id: eventId,\n ordinal,\n turn_id: currentTurnId,\n source_event_id: null,\n event_type: 'tool_result',\n source_type: 'event_msg.exec_command_end',\n subtype: 'shell',\n timestamp: ts,\n actor: 'tool',\n payload_object_id: payloadObjectId,\n raw_record_id: rawRecordId,\n confidence: 'high',\n })\n\n const matchedCall = sourceCallId ? pending.toolCalls.get(sourceCallId) : undefined\n pending.toolResults.push({\n tool_result_id: makeToolResultId(sessionId, `${sourceCallId ?? ordinal}::exec_command_end`),\n tool_call_id: matchedCall?.tool_call_id ?? null,\n source_call_id: sourceCallId,\n message_id: null,\n event_id: eventId,\n status: normalizeToolCallStatus('codex', em.status ?? (isError ? 'error' : 'success')),\n is_error: isError,\n exit_code: exitCode,\n duration_ms: durationMs(em.duration),\n stdout_object_id: stdoutId,\n stderr_object_id: stderrId,\n output_object_id: null,\n preview,\n raw_record_id: rawRecordId,\n })\n if (matchedCall) {\n matchedCall.status = isError ? 'error' : 'success'\n if (em.cwd && !matchedCall.cwd) matchedCall.cwd = em.cwd\n }\n}\n\nfunction handlePatchApplyEnd(ctx: EventMsgCtx, em: CodexEventMsgPayload): void {\n const { sessionId, currentTurnId, rawRecordId, ordinal, ts, payloadObjectId, pending } = ctx\n const eventId = makeEventId(sessionId, ordinal, 'patch_apply_end')\n pending.events.push({\n event_id: eventId,\n ordinal,\n turn_id: currentTurnId,\n source_event_id: null,\n event_type: 'patch',\n source_type: 'event_msg.patch_apply_end',\n subtype: null,\n timestamp: ts,\n actor: 'tool',\n payload_object_id: payloadObjectId,\n raw_record_id: rawRecordId,\n confidence: 'high',\n })\n if (em.changes && typeof em.changes === 'object') {\n for (const filePath of Object.keys(em.changes)) {\n pending.artifacts.push({\n artifact_id: artifactId(sessionId, 'codex', `${eventId}:${filePath}`),\n kind: 'diff',\n path: filePath,\n logical_path: filePath,\n object_id: null,\n text_object_id: null,\n mime_type: 'text/x-diff',\n size_bytes: 0,\n created_ts: ts,\n raw_record_id: rawRecordId,\n })\n }\n }\n}\n\nfunction handleMcpToolCallEnd(ctx: EventMsgCtx, em: CodexEventMsgPayload): void {\n const { sessionId, currentTurnId, rawRecordId, ordinal, ts, payloadObjectId, pending } = ctx\n const sourceCallId = em.call_id ?? null\n const eventId = makeEventId(sessionId, ordinal, 'mcp_tool_call_end')\n pending.events.push({\n event_id: eventId,\n ordinal,\n turn_id: currentTurnId,\n source_event_id: null,\n event_type: 'tool_result',\n source_type: 'event_msg.mcp_tool_call_end',\n subtype: 'mcp',\n timestamp: ts,\n actor: 'tool',\n payload_object_id: payloadObjectId,\n raw_record_id: rawRecordId,\n confidence: 'high',\n })\n const preview = stringifyOrNull(em.result)?.slice(0, PREVIEW_MAX) ?? null\n const matchedCall = sourceCallId ? pending.toolCalls.get(sourceCallId) : undefined\n const isError = isMcpResultError(em.status, em.result) ? 1 : 0\n const status = normalizeToolCallStatus('codex', em.status ?? (isError ? 'error' : 'success'))\n pending.toolResults.push({\n tool_result_id: makeToolResultId(sessionId, `${sourceCallId ?? ordinal}::mcp_tool_call_end`),\n tool_call_id: matchedCall?.tool_call_id ?? null,\n source_call_id: sourceCallId,\n message_id: null,\n event_id: eventId,\n status,\n is_error: isError,\n exit_code: null,\n duration_ms: durationMs(em.duration),\n stdout_object_id: null,\n stderr_object_id: null,\n output_object_id: null,\n preview,\n raw_record_id: rawRecordId,\n })\n if (matchedCall) {\n matchedCall.status = isError ? 'error' : status\n }\n}\n\nfunction handleContextCompacted(ctx: EventMsgCtx): void {\n const { sessionId, currentTurnId, rawRecordId, ordinal, ts, payloadObjectId, pending } = ctx\n pending.events.push({\n event_id: makeEventId(sessionId, ordinal, 'compaction'),\n ordinal,\n turn_id: currentTurnId,\n source_event_id: null,\n event_type: 'compaction',\n source_type: 'event_msg.context_compacted',\n subtype: null,\n timestamp: ts,\n actor: 'system',\n payload_object_id: payloadObjectId,\n raw_record_id: rawRecordId,\n confidence: 'high',\n })\n}\n\nfunction handleEventMsgPassthrough(ctx: EventMsgCtx, em: CodexEventMsgPayload): void {\n // user_message / agent_message / task_started / task_complete / turn_aborted /\n // token_count / others — keep as operational events.\n const { sessionId, currentTurnId, rawRecordId, ordinal, ts, payloadObjectId, pending } = ctx\n const subtype = em.type ?? 'unknown'\n pending.events.push({\n event_id: makeEventId(sessionId, ordinal, `event_msg.${subtype}`),\n ordinal,\n turn_id: currentTurnId,\n source_event_id: null,\n event_type: 'system_operational',\n source_type: `event_msg.${subtype}`,\n subtype,\n timestamp: ts,\n actor: 'system',\n payload_object_id: payloadObjectId,\n raw_record_id: rawRecordId,\n confidence: 'high',\n })\n}\n\nconst EVENT_MSG_HANDLERS: Record<string, (ctx: EventMsgCtx, em: CodexEventMsgPayload) => void> = {\n exec_command_end: handleExecCommandEnd,\n patch_apply_end: handlePatchApplyEnd,\n mcp_tool_call_end: handleMcpToolCallEnd,\n context_compacted: (ctx) => handleContextCompacted(ctx),\n}\n\n/** Normalize Codex operational `event_msg` payloads while preserving unknown types as events. */\nasync function handleEventMsg(\n _bundle: Bundle,\n sessionId: string,\n currentTurnId: string | null,\n rawRecordId: string,\n ordinal: number,\n ts: string | null,\n em: CodexEventMsgPayload,\n payloadObjectId: ObjectId | null,\n pending: PendingState,\n): Promise<void> {\n const ctx: EventMsgCtx = {\n sessionId,\n currentTurnId,\n rawRecordId,\n ordinal,\n ts,\n payloadObjectId,\n pending,\n }\n const handler = em.type ? EVENT_MSG_HANDLERS[em.type] : undefined\n ;(handler ?? handleEventMsgPassthrough)(ctx, em)\n}\n\n// ---- helpers -------------------------------------------------------------\n\n/** Pick the best native locator from a loose Codex envelope for raw record lookup. */\nfunction extractNativeId(env: CodexEnvelope): string | null {\n const p = env.payload as Record<string, unknown> | undefined\n if (!p) return null\n if (typeof p.id === 'string') return p.id\n if (typeof p.call_id === 'string') return p.call_id\n if (typeof p.turn_id === 'string') return p.turn_id\n return null\n}\n\n/** Map native Codex roles into prosa's normalized message role vocabulary. */\nfunction mapMessageRole(role: unknown): PendingMessage['role'] {\n switch (role) {\n case 'user':\n return 'user'\n case 'assistant':\n return 'assistant'\n case 'tool':\n return 'tool'\n case 'developer':\n return 'developer'\n case 'system':\n // Codex 'system' content is real system instructions — map to system_prompt.\n return 'system_prompt'\n default:\n return 'operational'\n }\n}\n\n/** Collapse Codex and MCP tool names into broad search/filter tool categories. */\nfunction canonicalToolType(toolName: string): string {\n const lower = toolName.toLowerCase()\n if (lower.startsWith('mcp__')) return 'mcp'\n if (\n lower === 'shell' ||\n lower === 'exec_command' ||\n lower === 'shell_command' ||\n lower === 'write_stdin' ||\n lower === 'unified_exec' ||\n lower === 'run_terminal_cmd'\n ) {\n return 'shell'\n }\n if (lower === 'read_file' || lower === 'readfile') return 'read_file'\n if (lower === 'write_file' || lower === 'writefile') return 'write_file'\n if (lower === 'apply_patch' || lower === 'applypatch' || lower === 'patch') return 'patch'\n if (lower === 'web_search' || lower === 'websearch' || lower === 'web_search_call') {\n return 'web_search'\n }\n if (lower === 'agent' || lower === 'subagent' || lower === 'collab_spawn') return 'subagent'\n return 'other'\n}\n\n/** Extract a shell command from loose tool arguments when the native tool exposes one. */\nfunction inferCommandFromArgs(toolName: string, args: unknown): string | null {\n if (!args || typeof args !== 'object') {\n if (typeof args === 'string') {\n try {\n const parsed = JSON.parse(args) as Record<string, unknown>\n return inferCommandFromArgs(toolName, parsed)\n } catch {\n return null\n }\n }\n return null\n }\n const obj = args as Record<string, unknown>\n if (typeof obj.command === 'string') return obj.command\n if (Array.isArray(obj.command)) {\n return obj.command.map(String).join(' ')\n }\n return null\n}\n\n/** Extract a file path from loose tool arguments without treating absence as an error. */\nfunction inferPathFromArgs(args: unknown): string | null {\n if (!args || typeof args !== 'object') {\n if (typeof args === 'string') {\n try {\n const parsed = JSON.parse(args) as Record<string, unknown>\n return inferPathFromArgs(parsed)\n } catch {\n return null\n }\n }\n return null\n }\n const obj = args as Record<string, unknown>\n if (typeof obj.file_path === 'string') return obj.file_path\n if (typeof obj.path === 'string') return obj.path\n if (typeof obj.absolute_path === 'string') return obj.absolute_path\n return null\n}\n\n/** Heuristic for legacy tool outputs that do not carry an explicit error flag. */\nfunction looksLikeError(text: string): boolean {\n return /\\b(error|exception|failed|stack trace)\\b/i.test(text)\n}\n\n/** Recover structured MCP failures from loose event payloads. */\nfunction isMcpResultError(status: string | null | undefined, result: unknown): boolean {\n const normalized = normalizeToolCallStatus('codex', status)\n if (normalized === 'error' || normalized === 'cancelled') return true\n if (Array.isArray(result)) return result.some((item) => isMcpResultError(null, item))\n if (!isRecord(result)) return false\n if (result.is_error === true || result.isError === true) return true\n if (typeof result.status === 'string' && normalizeToolCallStatus('codex', result.status) === 'error') return true\n return result.error != null\n}\n\n/** Convert Codex's seconds/nanoseconds duration object to milliseconds. */\nfunction durationMs(d: CodexEventMsgPayload['duration']): number | null {\n if (!d || typeof d !== 'object') return null\n const secs = typeof d.secs === 'number' ? d.secs : 0\n const nanos = typeof d.nanos === 'number' ? d.nanos : 0\n return secs * 1000 + Math.floor(nanos / 1e6)\n}\n\n/** Convert arbitrary recovered payload values into compact text previews when possible. */\nfunction stringifyOrNull(value: unknown): string | null {\n if (value == null) return null\n if (typeof value === 'string') return value\n try {\n return JSON.stringify(value)\n } catch {\n return null\n }\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n}\n\n/** Recover explicit Codex subagent spawn metadata from `session_meta.source`. */\nfunction parseSubagent(\n source: unknown,\n): { parent_thread_id: string; agent_role?: string; agent_nickname?: string } | null {\n if (!source || typeof source !== 'object') return null\n const obj = source as Record<string, unknown>\n const sub = obj.subagent\n if (!sub || typeof sub !== 'object') return null\n const ts = (sub as Record<string, unknown>).thread_spawn\n if (!ts || typeof ts !== 'object') return null\n const tso = ts as Record<string, unknown>\n const parent = tso.parent_thread_id\n if (typeof parent !== 'string') return null\n return {\n parent_thread_id: parent,\n agent_role: typeof tso.agent_role === 'string' ? tso.agent_role : undefined,\n agent_nickname: typeof tso.agent_nickname === 'string' ? tso.agent_nickname : undefined,\n }\n}\n\n/** Build searchable Codex documents from staged messages, tool calls, and result previews. */\nfunction buildSearchDocs(pending: PendingState): void {\n const sessionId = pending.session?.session_id ?? null\n if (!sessionId) return\n\n // Group blocks by message for indexing concatenated text.\n const blocksByMsg = new Map<string, PendingBlock[]>()\n for (const b of pending.blocks) {\n if (!b.message_id) continue\n const list = blocksByMsg.get(b.message_id) ?? []\n list.push(b)\n blocksByMsg.set(b.message_id, list)\n }\n\n for (const m of pending.messages) {\n const text = (blocksByMsg.get(m.message_id) ?? [])\n .filter(\n (b) =>\n b.text_inline && (b.block_type === 'input_text' || b.block_type === 'output_text' || b.block_type === 'text'),\n )\n .map((b) => b.text_inline as string)\n .join('\\n')\n if (!text || text.length === 0) continue\n pending.searchDocs.push({\n doc_id: `msg:${m.message_id}`,\n entity_type: 'message',\n entity_id: m.message_id,\n timestamp: m.timestamp,\n role: m.role,\n tool_name: null,\n canonical_tool_type: null,\n field_kind: m.role === 'user' ? 'user_prompt' : 'assistant_text',\n text,\n })\n }\n\n for (const c of pending.toolCallsList) {\n if (c.command) {\n pending.searchDocs.push({\n doc_id: `tc:cmd:${c.tool_call_id}`,\n entity_type: 'tool_call',\n entity_id: c.tool_call_id,\n timestamp: c.timestamp_start,\n role: null,\n tool_name: c.tool_name,\n canonical_tool_type: c.canonical_tool_type,\n field_kind: 'command',\n text: c.command,\n })\n }\n if (c.path) {\n pending.searchDocs.push({\n doc_id: `tc:path:${c.tool_call_id}`,\n entity_type: 'tool_call',\n entity_id: c.tool_call_id,\n timestamp: c.timestamp_start,\n role: null,\n tool_name: c.tool_name,\n canonical_tool_type: c.canonical_tool_type,\n field_kind: 'file_path',\n text: c.path,\n })\n }\n }\n\n for (const r of pending.toolResults) {\n if (r.preview) {\n pending.searchDocs.push({\n doc_id: `tr:preview:${r.tool_result_id}`,\n entity_type: 'tool_result',\n entity_id: r.tool_result_id,\n timestamp: null,\n role: null,\n tool_name: null,\n canonical_tool_type: null,\n field_kind: r.is_error ? 'error' : 'command_output_preview',\n text: r.preview,\n })\n }\n }\n}\n\n/** Insert staged Codex rows in foreign-key order after CAS objects are already durable. */\nfunction flushPending(\n bundle: Bundle,\n pending: PendingState,\n meta: {\n sessionEndTs: string | null\n modelFirst: string | null\n modelLast: string | null\n sourceTool: 'codex'\n },\n): void {\n if (!pending.session) return\n\n // Order matters under SQLite's immediate FK checking: rows must be inserted\n // before any other row references them. raw_records → sessions →\n // turns/events → messages → blocks → tool_calls → tool_results.\n //\n // We also insert sessions with parent_session_id=NULL initially because the\n // parent session may live in a different file/batch. The cross-file linkage\n // happens in `linkParents` below, after every file is committed.\n\n const insertRaw = prepare(\n bundle.db,\n `INSERT OR IGNORE INTO raw_records (\n raw_record_id, source_file_id, source_tool, record_kind, ordinal,\n line_no, json_pointer, native_id, raw_object_id, decoded_json_object_id,\n parser_status, confidence, import_batch_id\n ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,\n )\n for (const r of pending.rawRecords) {\n insertRaw.run(\n r.raw_record_id,\n r.source_file_id,\n r.source_tool,\n r.record_kind,\n r.ordinal,\n r.line_no,\n r.json_pointer,\n r.native_id,\n r.raw_object_id,\n r.decoded_json_object_id,\n r.parser_status,\n r.confidence,\n r.import_batch_id,\n )\n }\n\n const insertSession = prepare(\n bundle.db,\n `INSERT OR REPLACE INTO sessions (\n session_id, source_tool, source_session_id, project_id, parent_session_id,\n is_subagent, agent_role, agent_nickname, title, summary,\n start_ts, end_ts, cwd_initial, git_branch_initial,\n model_first, model_last, status, timeline_confidence, raw_record_id\n ) VALUES (?, ?, ?, ?, NULL, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 'high', ?)`,\n )\n insertSession.run(\n pending.session.session_id,\n meta.sourceTool,\n pending.session.source_session_id,\n null,\n pending.session.is_subagent,\n pending.session.agent_role,\n pending.session.agent_nickname,\n pending.session.title,\n null,\n pending.session.start_ts,\n meta.sessionEndTs,\n pending.session.cwd_initial,\n pending.session.git_branch_initial,\n meta.modelFirst,\n meta.modelLast,\n 'completed',\n pending.session.raw_record_id,\n )\n\n const insertTurn = prepare(\n bundle.db,\n `INSERT OR REPLACE INTO turns (\n turn_id, session_id, source_turn_id, ordinal, start_ts, end_ts,\n model, cwd, git_branch, approval_policy, sandbox_policy, effort, raw_record_id\n ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,\n )\n for (const t of pending.turns) {\n insertTurn.run(\n t.turn_id,\n pending.session.session_id,\n t.source_turn_id,\n t.ordinal,\n t.start_ts,\n null,\n t.model,\n t.cwd,\n null,\n t.approval_policy,\n t.sandbox_policy,\n t.effort,\n t.raw_record_id,\n )\n }\n\n const insertEvent = prepare(\n bundle.db,\n `INSERT OR REPLACE INTO events (\n event_id, session_id, turn_id, source_event_id, event_type, source_type,\n subtype, timestamp, ordinal, actor, payload_object_id, raw_record_id,\n confidence, is_derived\n ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 0)`,\n )\n for (const e of pending.events) {\n insertEvent.run(\n e.event_id,\n pending.session.session_id,\n e.turn_id,\n e.source_event_id,\n e.event_type,\n e.source_type,\n e.subtype,\n e.timestamp,\n e.ordinal,\n e.actor,\n e.payload_object_id,\n e.raw_record_id,\n e.confidence,\n )\n }\n\n const insertMessage = prepare(\n bundle.db,\n `INSERT OR REPLACE INTO messages (\n message_id, session_id, turn_id, event_id, source_message_id, role,\n author_name, model, timestamp, ordinal, parent_message_id, request_id,\n status, raw_record_id\n ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,\n )\n for (const m of pending.messages) {\n insertMessage.run(\n m.message_id,\n pending.session.session_id,\n m.turn_id,\n m.event_id,\n m.source_message_id,\n m.role,\n null,\n m.model,\n m.timestamp,\n m.ordinal,\n null,\n null,\n null,\n m.raw_record_id,\n )\n }\n\n const insertBlock = prepare(\n bundle.db,\n `INSERT OR REPLACE INTO content_blocks (\n block_id, message_id, event_id, session_id, ordinal, block_type,\n text_object_id, text_inline, mime_type, token_count, is_error,\n is_redacted, visibility, raw_record_id\n ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 'default', ?)`,\n )\n for (const b of pending.blocks) {\n insertBlock.run(\n b.block_id,\n b.message_id,\n b.event_id,\n pending.session.session_id,\n b.ordinal,\n b.block_type,\n b.text_object_id,\n b.text_inline,\n null,\n null,\n 0,\n 0,\n b.raw_record_id,\n )\n }\n\n const insertToolCall = prepare(\n bundle.db,\n `INSERT OR REPLACE INTO tool_calls (\n tool_call_id, session_id, turn_id, message_id, event_id,\n source_call_id, tool_name, canonical_tool_type, args_object_id,\n command, cwd, path, query, timestamp_start, timestamp_end, status,\n raw_record_id\n ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,\n )\n for (const c of pending.toolCallsList) {\n insertToolCall.run(\n c.tool_call_id,\n pending.session.session_id,\n c.turn_id,\n c.message_id,\n c.event_id,\n c.source_call_id,\n c.tool_name,\n c.canonical_tool_type,\n c.args_object_id,\n c.command,\n c.cwd,\n c.path,\n c.query,\n c.timestamp_start,\n null,\n c.status,\n c.raw_record_id,\n )\n }\n\n const insertToolResult = prepare(\n bundle.db,\n `INSERT OR REPLACE INTO tool_results (\n tool_result_id, tool_call_id, session_id, message_id, event_id,\n source_call_id, status, is_error, exit_code, duration_ms,\n stdout_object_id, stderr_object_id, output_object_id, preview, raw_record_id\n ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,\n )\n for (const r of pending.toolResults) {\n insertToolResult.run(\n r.tool_result_id,\n r.tool_call_id,\n pending.session.session_id,\n r.message_id,\n r.event_id,\n r.source_call_id,\n r.status,\n r.is_error,\n r.exit_code,\n r.duration_ms,\n r.stdout_object_id,\n r.stderr_object_id,\n r.output_object_id,\n r.preview,\n r.raw_record_id,\n )\n }\n\n const insertArtifact = prepare(\n bundle.db,\n `INSERT OR REPLACE INTO artifacts (\n artifact_id, session_id, project_id, source_tool, kind, path,\n logical_path, object_id, text_object_id, mime_type, size_bytes,\n created_ts, raw_record_id\n ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,\n )\n for (const a of pending.artifacts) {\n insertArtifact.run(\n a.artifact_id,\n pending.session.session_id,\n null,\n 'codex',\n a.kind,\n a.path,\n a.logical_path,\n a.object_id,\n a.text_object_id,\n a.mime_type,\n a.size_bytes,\n a.created_ts,\n a.raw_record_id,\n )\n }\n\n const insertEdge = prepare(\n bundle.db,\n `INSERT OR IGNORE INTO edges (\n src_type, src_id, dst_type, dst_id, edge_type, confidence, source,\n raw_record_id, metadata_object_id\n ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, NULL)`,\n )\n for (const e of pending.edges) {\n insertEdge.run(e.src_type, e.src_id, e.dst_type, e.dst_id, e.edge_type, e.confidence, e.source, e.raw_record_id)\n }\n\n const insertSearch = prepare(\n bundle.db,\n `INSERT OR REPLACE INTO search_docs (\n doc_id, entity_type, entity_id, session_id, project_id, timestamp,\n role, tool_name, canonical_tool_type, field_kind, text\n ) VALUES (?, ?, ?, ?, NULL, ?, ?, ?, ?, ?, ?)`,\n )\n for (const d of pending.searchDocs) {\n insertSearch.run(\n d.doc_id,\n d.entity_type,\n d.entity_id,\n pending.session.session_id,\n d.timestamp,\n d.role,\n d.tool_name,\n d.canonical_tool_type,\n d.field_kind,\n d.text,\n )\n }\n}\n","import { readdir } from 'node:fs/promises'\nimport path from 'node:path'\n\n/**\n * Walk a Codex sessions root (default `~/.codex/sessions`) and yield every\n * `rollout-*.jsonl` file. The native layout is `YYYY/MM/DD/rollout-...jsonl`,\n * but we don't depend on that — anything ending in `.jsonl` under `root`\n * counts.\n */\nexport async function* discoverCodexSessions(root: string): AsyncGenerator<string, void, void> {\n yield* walk(root)\n}\n\n/** Recursively traverse a possibly-missing sessions directory without failing discovery. */\nasync function* walk(dir: string): AsyncGenerator<string, void, void> {\n let entries: import('node:fs').Dirent[]\n try {\n entries = await readdir(dir, { withFileTypes: true })\n } catch {\n return\n }\n\n for (const entry of entries) {\n const full = path.join(dir, entry.name)\n if (entry.isDirectory()) {\n yield* walk(full)\n } else if (entry.isFile() && entry.name.endsWith('.jsonl')) {\n yield full\n }\n }\n}\n","import path from 'node:path'\nimport Database from 'better-sqlite3'\nimport type { Bundle } from '../../core/bundle.js'\nimport {\n type ObjectId,\n type PendingObjects,\n createPendingObjects,\n flushPendingObjects,\n stageBytes,\n stageJson,\n stageText,\n} from '../../core/cas/index.js'\nimport { prepare, transactional } from '../../core/db.js'\nimport {\n artifactId,\n blockId,\n eventId as makeEventId,\n messageId as makeMessageId,\n rawRecordId as makeRawRecordId,\n sessionId as makeSessionId,\n toolCallId as makeToolCallId,\n toolResultId as makeToolResultId,\n} from '../../core/domain/ids.js'\nimport { normalizeToolCallStatus } from '../../core/domain/status.js'\nimport { getErrorMessage } from '../../core/errors.js'\nimport {\n type ImportBatch,\n type ImportCounts,\n emptyCounts,\n finishBatch,\n recordError,\n startBatch,\n} from '../../core/ingest/batch.js'\nimport { registerSourceFile } from '../../core/ingest/idempotency.js'\nimport type { CompileLogger, CompileOptions } from '../compile-options.js'\nimport { type CursorStoreDb, discoverCursorStores } from './discover.js'\n\n/** Result returned after a Cursor compile batch finishes or records a failed batch. */\nexport interface CompileResult {\n /** Import batch created for this Cursor run. */\n batch: ImportBatch\n /** Final counts accumulated while importing Cursor stores. */\n counts: ImportCounts\n}\n\n/** Maximum inline text retained in normalized rows before full content moves to CAS. */\nconst PREVIEW_MAX = 4_000\n\n/**\n * Recovered Cursor `meta` row shape. This is a loose importer input for\n * observed store databases, not a validator for Cursor's native format.\n */\ninterface CursorMeta {\n agentId?: string\n latestRootBlobId?: string\n name?: string\n mode?: string\n createdAt?: number\n lastUsedModel?: string\n}\n\n/**\n * Recovered Cursor JSON blob shape. Many blobs are protobuf state instead, so\n * this shape is only used after a blob looks like JSON and parses successfully.\n */\ninterface CursorBlobJson {\n role?: string\n id?: string\n content?: string | CursorContentItem[]\n providerOptions?: Record<string, unknown>\n}\n\n/** Loose Cursor content item recovered from parsed JSON message blobs. */\ninterface CursorContentItem {\n type?: string\n text?: string\n toolCallId?: string\n toolName?: string\n args?: unknown\n result?: unknown\n experimental_content?: unknown\n signature?: string\n data?: unknown\n}\n\n/** Compile Cursor `store.db` files under `root` into the bundle. */\nexport async function compileCursor(\n bundle: Bundle,\n root: string,\n options: CompileOptions = {},\n): Promise<CompileResult> {\n const logger = options.logger\n const batch = startBatch(bundle, 'cursor', [root])\n const counts = emptyCounts()\n logger?.info({ batch_id: batch.batch_id, root }, 'cursor batch started')\n try {\n for await (const store of discoverCursorStores(root)) {\n counts.source_files_seen++\n logger?.debug(\n {\n path: store.filePath,\n workspace_id: store.workspaceId,\n agent_id: store.agentId,\n },\n 'cursor store discovered',\n )\n try {\n const fc = await compileCursorStore(bundle, batch, store, logger)\n addCounts(counts, fc)\n } catch (error) {\n counts.errors++\n logger?.warn(\n {\n err: error,\n path: store.filePath,\n },\n 'cursor store failed',\n )\n await recordError(bundle, batch.batch_id, {\n kind: 'cursor_store_failed',\n message: getErrorMessage(error),\n payload: { path: store.filePath },\n })\n }\n }\n finishBatch(bundle, batch, counts, 'completed')\n logger?.info({ batch_id: batch.batch_id, counts }, 'cursor batch completed')\n } catch (error) {\n finishBatch(bundle, batch, counts, 'failed')\n logger?.error({ err: error, batch_id: batch.batch_id, counts }, 'cursor batch failed')\n throw error\n }\n return { batch, counts }\n}\n\n/** Per-store deltas that are merged into the import batch counts. */\ninterface FileCounts {\n source_files_imported: number\n source_files_skipped: number\n raw_records: number\n sessions: number\n events: number\n messages: number\n content_blocks: number\n tool_calls: number\n tool_results: number\n artifacts: number\n edges: number\n errors: number\n}\n\n/** Create zeroed file counters for a Cursor store that may still fail or be skipped. */\nfunction emptyFileCounts(): FileCounts {\n return {\n source_files_imported: 0,\n source_files_skipped: 0,\n raw_records: 0,\n sessions: 0,\n events: 0,\n messages: 0,\n content_blocks: 0,\n tool_calls: 0,\n tool_results: 0,\n artifacts: 0,\n edges: 0,\n errors: 0,\n }\n}\n\n/** Merge a single Cursor store's normalized row counts into batch totals. */\nfunction addCounts(target: ImportCounts, source: FileCounts): void {\n target.source_files_imported += source.source_files_imported\n target.source_files_skipped += source.source_files_skipped\n target.raw_records += source.raw_records\n target.sessions += source.sessions\n target.events += source.events\n target.messages += source.messages\n target.content_blocks += source.content_blocks\n target.tool_calls += source.tool_calls\n target.tool_results += source.tool_results\n target.artifacts += source.artifacts\n target.edges += source.edges\n target.errors += source.errors\n}\n\n/** All normalized Cursor rows staged for one store before FK-ordered flush. */\ninterface PendingState {\n rawRecords: PendingRaw[]\n session: PendingSession | null\n events: PendingEvent[]\n messages: PendingMessage[]\n blocks: PendingBlock[]\n toolCalls: Map<string, PendingToolCall>\n toolCallsList: PendingToolCall[]\n toolResults: PendingToolResult[]\n artifacts: PendingArtifact[]\n searchDocs: PendingSearchDoc[]\n objects: PendingObjects\n}\n\n/** Raw record row staged from Cursor SQLite meta rows or blobs before insertion. */\ninterface PendingRaw {\n raw_record_id: string\n source_file_id: string\n ordinal: number\n line_no: null\n json_pointer: string | null\n native_id: string | null\n raw_object_id: ObjectId\n decoded_json_object_id: ObjectId | null\n parser_status: 'ok' | 'partial' | 'failed'\n confidence: 'high' | 'medium' | 'low'\n import_batch_id: string\n record_kind: 'sqlite_meta' | 'sqlite_blob'\n}\n\n/** Session row staged from Cursor meta with low-confidence timeline metadata. */\ninterface PendingSession {\n session_id: string\n source_session_id: string\n agent_role: string | null\n agent_nickname: string | null\n title: string | null\n start_ts: string | null\n raw_record_id: string\n model: string | null\n}\n\n/** Event row staged from Cursor JSON message blobs. */\ninterface PendingEvent {\n event_id: string\n ordinal: number\n source_event_id: string | null\n event_type: string\n source_type: string\n subtype: string | null\n timestamp: string | null\n actor: string | null\n payload_object_id: ObjectId | null\n raw_record_id: string\n confidence: 'high' | 'medium' | 'low'\n}\n\n/** Message row staged from Cursor parsed JSON blobs. */\ninterface PendingMessage {\n message_id: string\n event_id: string | null\n source_message_id: string | null\n role: 'system_prompt' | 'developer' | 'user' | 'assistant' | 'tool' | 'operational'\n model: string | null\n timestamp: string | null\n ordinal: number\n raw_record_id: string\n}\n\n/** Content block row staged from Cursor text, reasoning, tool, or unknown content. */\ninterface PendingBlock {\n block_id: string\n message_id: string | null\n event_id: string | null\n ordinal: number\n block_type: string\n text_object_id: ObjectId | null\n text_inline: string | null\n is_error: 0 | 1\n visibility: 'default' | 'hidden_by_default' | 'audit_only'\n raw_record_id: string\n}\n\n/** Tool call row staged from Cursor `tool-call` content items. */\ninterface PendingToolCall {\n tool_call_id: string\n message_id: string | null\n event_id: string | null\n source_call_id: string\n tool_name: string\n canonical_tool_type: string\n args_object_id: ObjectId | null\n command: string | null\n cwd: string | null\n path: string | null\n query: string | null\n timestamp_start: string | null\n status: string | null\n raw_record_id: string\n}\n\n/** Tool result row staged from Cursor `tool-result` content items. */\ninterface PendingToolResult {\n tool_result_id: string\n tool_call_id: string | null\n source_call_id: string\n message_id: string | null\n event_id: string | null\n status: string | null\n is_error: 0 | 1\n output_object_id: ObjectId | null\n preview: string | null\n raw_record_id: string\n}\n\n/** Artifact row staged from Cursor content that references generated outputs. */\ninterface PendingArtifact {\n artifact_id: string\n kind: string\n path: string | null\n logical_path: string | null\n object_id: ObjectId | null\n text_object_id: ObjectId | null\n mime_type: string | null\n size_bytes: number\n created_ts: string | null\n raw_record_id: string\n}\n\n/** Search index row staged from normalized Cursor messages, commands, and paths. */\ninterface PendingSearchDoc {\n doc_id: string\n entity_type: string\n entity_id: string\n timestamp: string | null\n role: string | null\n tool_name: string | null\n canonical_tool_type: string | null\n field_kind: string\n text: string\n}\n\n/** Read one Cursor SQLite store, preserve raw blobs, and normalize parseable chat JSON. */\nasync function compileCursorStore(\n bundle: Bundle,\n batch: ImportBatch,\n store: CursorStoreDb,\n logger?: CompileLogger,\n): Promise<FileCounts> {\n const counts = emptyFileCounts()\n\n const { row: sourceFile, alreadyKnown } = await registerSourceFile(bundle, {\n sourceTool: 'cursor',\n absolutePath: path.resolve(store.filePath),\n fileKind: 'sqlite',\n workspaceHint: store.workspaceId,\n })\n if (alreadyKnown) {\n counts.source_files_skipped = 1\n logger?.debug({ path: store.filePath, source_file_id: sourceFile.source_file_id }, 'cursor store skipped')\n return counts\n }\n counts.source_files_imported = 1\n logger?.debug({ path: store.filePath, source_file_id: sourceFile.source_file_id }, 'cursor store registered')\n\n // Open the Cursor store as an immutable URI so SQLite never touches WAL/SHM\n // files owned by a running Cursor process.\n const cdb = openCursorStoreReadOnly(store.filePath)\n\n try {\n const pending: PendingState = {\n rawRecords: [],\n session: null,\n events: [],\n messages: [],\n blocks: [],\n toolCalls: new Map(),\n toolCallsList: [],\n toolResults: [],\n artifacts: [],\n searchDocs: [],\n objects: createPendingObjects(),\n }\n\n // ---- meta: hex-encoded JSON ----\n const metaRow = cdb.prepare<[], { value: string }>(`SELECT value FROM meta WHERE key='0'`).get()\n let meta: CursorMeta = {}\n let metaRawId = ''\n if (metaRow) {\n const metaText = hexToUtf8(metaRow.value)\n try {\n meta = JSON.parse(metaText) as CursorMeta\n } catch {\n meta = {}\n }\n const metaObjId = stageBytes(pending.objects, Buffer.from(metaText, 'utf8'), {\n mimeType: 'application/json',\n encoding: 'utf-8',\n })\n metaRawId = makeRawRecordId(sourceFile.source_file_id, 0, metaObjId)\n pending.rawRecords.push({\n raw_record_id: metaRawId,\n source_file_id: sourceFile.source_file_id,\n ordinal: 0,\n line_no: null,\n json_pointer: 'meta/0',\n native_id: meta.agentId ?? store.agentId,\n raw_object_id: metaObjId,\n decoded_json_object_id: metaObjId,\n parser_status: 'ok',\n confidence: 'high',\n import_batch_id: batch.batch_id,\n record_kind: 'sqlite_meta',\n })\n }\n\n const sourceSessionId = meta.agentId ?? store.agentId\n const sessionPk = makeSessionId('cursor', sourceSessionId)\n const startTs = meta.createdAt ? new Date(meta.createdAt).toISOString() : null\n pending.session = {\n session_id: sessionPk,\n source_session_id: sourceSessionId,\n agent_role: meta.mode ?? null,\n agent_nickname: meta.name ?? null,\n title: meta.name ?? null,\n start_ts: startTs,\n raw_record_id: metaRawId || makeRawRecordId(sourceFile.source_file_id, 0, 'blake3:none'),\n model: meta.lastUsedModel ?? null,\n }\n\n // ---- blobs ----\n const blobs = cdb.prepare<[], { id: string; data: Buffer }>(`SELECT id, data FROM blobs ORDER BY rowid`).all()\n\n let messageOrdinal = 0\n for (let i = 0; i < blobs.length; i++) {\n const blob = blobs[i]\n if (!blob) continue\n const ordinal = i + 1\n const blobObjectId = stageBytes(pending.objects, blob.data)\n const blobRawId = makeRawRecordId(sourceFile.source_file_id, ordinal, blobObjectId)\n\n // Try to parse JSON. Many blobs are protobuf state and won't parse.\n let parsed: CursorBlobJson | null = null\n const firstByte = blob.data[0]\n const looksJson = firstByte === 0x7b /* '{' */ || firstByte === 0x5b /* '[' */\n if (looksJson) {\n try {\n parsed = JSON.parse(blob.data.toString('utf8')) as CursorBlobJson\n } catch {\n parsed = null\n }\n }\n\n pending.rawRecords.push({\n raw_record_id: blobRawId,\n source_file_id: sourceFile.source_file_id,\n ordinal,\n line_no: null,\n json_pointer: `blobs/${blob.id}`,\n native_id: blob.id,\n raw_object_id: blobObjectId,\n decoded_json_object_id: parsed != null ? stageJson(pending.objects, parsed) : null,\n parser_status: parsed != null ? 'ok' : looksJson ? 'failed' : 'partial',\n confidence: 'low', // timeline order from blob list isn't canonical\n import_batch_id: batch.batch_id,\n record_kind: 'sqlite_blob',\n })\n\n if (!parsed || typeof parsed.role !== 'string') continue\n\n // Normalize JSON blobs that look like chat messages.\n const role = mapRole(parsed.role)\n const messageId = makeMessageId(sessionPk, messageOrdinal++, parsed.id ?? blob.id)\n const eventId = makeEventId(sessionPk, ordinal, 'message')\n\n pending.events.push({\n event_id: eventId,\n ordinal,\n source_event_id: blob.id,\n event_type: 'message',\n source_type: `cursor.${parsed.role}`,\n subtype: null,\n timestamp: null,\n actor: parsed.role,\n payload_object_id: pending.rawRecords[pending.rawRecords.length - 1]?.decoded_json_object_id ?? null,\n raw_record_id: blobRawId,\n confidence: 'low',\n })\n\n pending.messages.push({\n message_id: messageId,\n event_id: eventId,\n source_message_id: parsed.id ?? blob.id,\n role,\n model: role === 'assistant' ? (meta.lastUsedModel ?? null) : null,\n timestamp: null,\n ordinal: messageOrdinal,\n raw_record_id: blobRawId,\n })\n\n const content = parsed.content\n if (typeof content === 'string') {\n await pushTextBlock(bundle, pending, messageId, 0, 'text', content, blobRawId)\n } else if (Array.isArray(content)) {\n for (let bi = 0; bi < content.length; bi++) {\n const item = content[bi]\n if (!item) continue\n await processContentItem(bundle, sessionPk, messageId, eventId, bi, item, blobRawId, pending)\n }\n }\n }\n\n reconcileUnfinishedToolCalls(pending)\n buildSearchDocs(pending)\n\n // Persist staged CAS objects (FS + objects rows) before the domain\n // transaction. better-sqlite3 transactions are sync.\n await flushPendingObjects(bundle, pending.objects)\n\n transactional(bundle.db, () => {\n flushPending(bundle, pending)\n })\n\n counts.raw_records = pending.rawRecords.length\n counts.sessions = 1\n counts.events = pending.events.length\n counts.messages = pending.messages.length\n counts.content_blocks = pending.blocks.length\n counts.tool_calls = pending.toolCallsList.length\n counts.tool_results = pending.toolResults.length\n counts.artifacts = pending.artifacts.length\n logger?.debug({ path: store.filePath, source_file_id: sourceFile.source_file_id, counts }, 'cursor store imported')\n return counts\n } finally {\n cdb.close()\n }\n}\n\n/** Decode Cursor meta values, which are stored as hex-encoded UTF-8 JSON. */\nfunction hexToUtf8(hex: string): string {\n return Buffer.from(hex, 'hex').toString('utf8')\n}\n\n/** Map Cursor chat roles into prosa's normalized message role vocabulary. */\nfunction mapRole(role: string): PendingMessage['role'] {\n switch (role) {\n case 'user':\n return 'user'\n case 'assistant':\n return 'assistant'\n case 'tool':\n return 'tool'\n case 'system':\n // In Cursor's chat blobs, role=system is actually the system prompt\n // (unlike Claude Code's `type:\"system\"` event_log usage).\n return 'system_prompt'\n default:\n return 'operational'\n }\n}\n\n/** Stage a Cursor text-like content block, storing long bodies in CAS. */\nasync function pushTextBlock(\n bundle: Bundle,\n pending: PendingState,\n messageId: string,\n ordinal: number,\n blockType: string,\n text: string,\n rawRecordId: string,\n visibility: 'default' | 'hidden_by_default' | 'audit_only' = 'default',\n): Promise<void> {\n if (!text) return\n const overflow = text.length > PREVIEW_MAX ? stageText(pending.objects, text) : null\n pending.blocks.push({\n block_id: blockId(messageId, ordinal),\n message_id: messageId,\n event_id: null,\n ordinal,\n block_type: blockType,\n text_object_id: overflow,\n text_inline: text.slice(0, PREVIEW_MAX),\n is_error: 0,\n visibility,\n raw_record_id: rawRecordId,\n })\n}\n\n/** Normalize one Cursor content item into blocks, tool calls, tool results, or audit rows. */\nasync function processContentItem(\n bundle: Bundle,\n sessionId: string,\n messageId: string,\n eventId: string,\n ordinal: number,\n item: CursorContentItem,\n rawRecordId: string,\n pending: PendingState,\n): Promise<void> {\n const t = item.type\n if (t === 'text') {\n await pushTextBlock(bundle, pending, messageId, ordinal, 'text', item.text ?? '', rawRecordId)\n return\n }\n if (t === 'reasoning') {\n await pushTextBlock(\n bundle,\n pending,\n messageId,\n ordinal,\n 'thinking',\n item.text ?? '',\n rawRecordId,\n 'hidden_by_default',\n )\n return\n }\n if (t === 'redacted-reasoning') {\n pending.blocks.push({\n block_id: blockId(messageId, ordinal),\n message_id: messageId,\n event_id: null,\n ordinal,\n block_type: 'thinking',\n text_object_id: null,\n text_inline: '[redacted]',\n is_error: 0,\n visibility: 'audit_only',\n raw_record_id: rawRecordId,\n })\n return\n }\n if (t === 'tool-call') {\n const sourceCallId = item.toolCallId ?? `${ordinal}`\n const toolName = item.toolName ?? 'unknown'\n const argsObjectId = item.args != null ? stageJson(pending.objects, item.args) : null\n const tcId = makeToolCallId(sessionId, sourceCallId)\n\n pending.blocks.push({\n block_id: blockId(messageId, ordinal),\n message_id: messageId,\n event_id: null,\n ordinal,\n block_type: 'tool_use',\n text_object_id: null,\n text_inline: null,\n is_error: 0,\n visibility: 'default',\n raw_record_id: rawRecordId,\n })\n\n const call: PendingToolCall = {\n tool_call_id: tcId,\n message_id: messageId,\n event_id: eventId,\n source_call_id: sourceCallId,\n tool_name: toolName,\n canonical_tool_type: canonicalToolType(toolName),\n args_object_id: argsObjectId,\n command:\n typeof (item.args as { command?: unknown })?.command === 'string'\n ? (item.args as { command: string }).command\n : null,\n cwd: null,\n path:\n typeof (item.args as { file_path?: unknown })?.file_path === 'string'\n ? (item.args as { file_path: string }).file_path\n : typeof (item.args as { path?: unknown })?.path === 'string'\n ? (item.args as { path: string }).path\n : null,\n query: null,\n timestamp_start: null,\n status: 'started',\n raw_record_id: rawRecordId,\n }\n pending.toolCalls.set(sourceCallId, call)\n pending.toolCallsList.push(call)\n return\n }\n if (t === 'tool-result') {\n const sourceCallId = item.toolCallId ?? `${ordinal}`\n const text = stringifyOrNull(item.result) ?? ''\n const overflow = text.length > PREVIEW_MAX ? stageText(pending.objects, text) : null\n const outputObjectId = text ? (overflow ?? stageText(pending.objects, text)) : null\n const isError = readIsError(item) ? 1 : 0\n\n pending.blocks.push({\n block_id: blockId(messageId, ordinal),\n message_id: messageId,\n event_id: null,\n ordinal,\n block_type: 'tool_result',\n text_object_id: overflow,\n text_inline: text.slice(0, PREVIEW_MAX),\n is_error: isError,\n visibility: 'default',\n raw_record_id: rawRecordId,\n })\n\n const matched = pending.toolCalls.get(sourceCallId)\n pending.toolResults.push({\n tool_result_id: makeToolResultId(sessionId, sourceCallId),\n tool_call_id: matched?.tool_call_id ?? null,\n source_call_id: sourceCallId,\n message_id: messageId,\n event_id: eventId,\n status: normalizeToolCallStatus('cursor', isError ? 'error' : matched ? 'success' : null),\n is_error: isError,\n output_object_id: outputObjectId,\n preview: text.slice(0, PREVIEW_MAX) || null,\n raw_record_id: rawRecordId,\n })\n if (matched) matched.status = isError ? 'error' : 'success'\n return\n }\n\n // Unknown content type — keep as audit-only block.\n pending.blocks.push({\n block_id: blockId(messageId, ordinal),\n message_id: messageId,\n event_id: null,\n ordinal,\n block_type: t ?? 'unknown',\n text_object_id: null,\n text_inline: stringifyOrNull(item)?.slice(0, PREVIEW_MAX) ?? null,\n is_error: 0,\n visibility: 'audit_only',\n raw_record_id: rawRecordId,\n })\n}\n\nfunction reconcileUnfinishedToolCalls(pending: PendingState): void {\n for (const call of pending.toolCallsList) {\n if (call.status === 'started') {\n call.status = 'unknown'\n }\n }\n}\n\nfunction openCursorStoreReadOnly(filePath: string): Database.Database {\n try {\n return new Database(`file:${filePath}?mode=ro&immutable=1`, {\n fileMustExist: true,\n })\n } catch {\n return new Database(filePath, { readonly: true, fileMustExist: true })\n }\n}\n\n/** Recover Cursor's high-level tool error flag from experimental content metadata. */\nfunction readIsError(item: CursorContentItem): boolean {\n // Cursor stores isError under providerOptions.cursor.highLevelToolCallResult.\n const exp = item.experimental_content as { isError?: boolean } | undefined\n if (exp && typeof exp.isError === 'boolean') return exp.isError\n return false\n}\n\n/** Collapse Cursor tool names into broad search/filter tool categories. */\nfunction canonicalToolType(toolName: string): string {\n const lower = toolName.toLowerCase()\n if (lower.startsWith('mcp__')) return 'mcp'\n if (lower === 'shell' || lower === 'run_terminal_cmd' || lower === 'bash') return 'shell'\n if (lower === 'read' || lower === 'readfile' || lower === 'read_file') return 'read_file'\n if (lower === 'write' || lower === 'writefile' || lower === 'write_file') return 'write_file'\n if (lower === 'strreplace' || lower === 'str_replace' || lower === 'edit' || lower === 'search_replace') {\n return 'edit_file'\n }\n if (lower === 'grep' || lower === 'glob' || lower === 'codebase_search' || lower === 'glob_file_search') {\n return 'search_file'\n }\n if (lower === 'websearch') return 'web_search'\n if (lower === 'applypatch' || lower === 'apply_patch') return 'patch'\n return 'other'\n}\n\n/** Convert arbitrary recovered payload values into compact text previews when possible. */\nfunction stringifyOrNull(value: unknown): string | null {\n if (value == null) return null\n if (typeof value === 'string') return value\n try {\n return JSON.stringify(value)\n } catch {\n return null\n }\n}\n\n/** Build searchable Cursor documents while excluding hidden and audit-only blocks. */\nfunction buildSearchDocs(pending: PendingState): void {\n const sessionId = pending.session?.session_id ?? null\n if (!sessionId) return\n const blocksByMsg = new Map<string, PendingBlock[]>()\n for (const b of pending.blocks) {\n if (!b.message_id) continue\n if (b.visibility === 'hidden_by_default' || b.visibility === 'audit_only') continue\n if (!b.text_inline) continue\n const list = blocksByMsg.get(b.message_id) ?? []\n list.push(b)\n blocksByMsg.set(b.message_id, list)\n }\n for (const m of pending.messages) {\n const text = (blocksByMsg.get(m.message_id) ?? [])\n .map((b) => b.text_inline ?? '')\n .join('\\n')\n .trim()\n if (!text) continue\n pending.searchDocs.push({\n doc_id: `msg:${m.message_id}`,\n entity_type: 'message',\n entity_id: m.message_id,\n timestamp: m.timestamp,\n role: m.role,\n tool_name: null,\n canonical_tool_type: null,\n field_kind: m.role === 'user' ? 'user_prompt' : m.role === 'tool' ? 'tool_result' : 'assistant_text',\n text,\n })\n }\n for (const tc of pending.toolCallsList) {\n if (tc.command) {\n pending.searchDocs.push({\n doc_id: `tc:cmd:${tc.tool_call_id}`,\n entity_type: 'tool_call',\n entity_id: tc.tool_call_id,\n timestamp: tc.timestamp_start,\n role: null,\n tool_name: tc.tool_name,\n canonical_tool_type: tc.canonical_tool_type,\n field_kind: 'command',\n text: tc.command,\n })\n }\n if (tc.path) {\n pending.searchDocs.push({\n doc_id: `tc:path:${tc.tool_call_id}`,\n entity_type: 'tool_call',\n entity_id: tc.tool_call_id,\n timestamp: tc.timestamp_start,\n role: null,\n tool_name: tc.tool_name,\n canonical_tool_type: tc.canonical_tool_type,\n field_kind: 'file_path',\n text: tc.path,\n })\n }\n }\n}\n\n/** Insert staged Cursor rows in foreign-key order after CAS objects are already durable. */\nfunction flushPending(bundle: Bundle, pending: PendingState): void {\n if (!pending.session) return\n\n const insertRaw = prepare(\n bundle.db,\n `INSERT OR IGNORE INTO raw_records (\n raw_record_id, source_file_id, source_tool, record_kind, ordinal,\n line_no, json_pointer, native_id, raw_object_id, decoded_json_object_id,\n parser_status, confidence, import_batch_id\n ) VALUES (?, ?, 'cursor', ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,\n )\n for (const r of pending.rawRecords) {\n insertRaw.run(\n r.raw_record_id,\n r.source_file_id,\n r.record_kind,\n r.ordinal,\n r.line_no,\n r.json_pointer,\n r.native_id,\n r.raw_object_id,\n r.decoded_json_object_id,\n r.parser_status,\n r.confidence,\n r.import_batch_id,\n )\n }\n\n prepare(\n bundle.db,\n `INSERT OR REPLACE INTO sessions (\n session_id, source_tool, source_session_id, project_id, parent_session_id,\n is_subagent, agent_role, agent_nickname, title, summary,\n start_ts, end_ts, cwd_initial, git_branch_initial,\n model_first, model_last, status, timeline_confidence, raw_record_id\n ) VALUES (?, 'cursor', ?, NULL, NULL, 0, ?, ?, ?, NULL, ?, NULL, NULL, NULL, ?, ?, NULL, 'low', ?)`,\n ).run(\n pending.session.session_id,\n pending.session.source_session_id,\n pending.session.agent_role,\n pending.session.agent_nickname,\n pending.session.title,\n pending.session.start_ts,\n pending.session.model,\n pending.session.model,\n pending.session.raw_record_id,\n )\n\n const insertEvent = prepare(\n bundle.db,\n `INSERT OR REPLACE INTO events (\n event_id, session_id, turn_id, source_event_id, event_type, source_type,\n subtype, timestamp, ordinal, actor, payload_object_id, raw_record_id,\n confidence, is_derived\n ) VALUES (?, ?, NULL, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 0)`,\n )\n for (const e of pending.events) {\n insertEvent.run(\n e.event_id,\n pending.session.session_id,\n e.source_event_id,\n e.event_type,\n e.source_type,\n e.subtype,\n e.timestamp,\n e.ordinal,\n e.actor,\n e.payload_object_id,\n e.raw_record_id,\n e.confidence,\n )\n }\n\n const insertMsg = prepare(\n bundle.db,\n `INSERT OR REPLACE INTO messages (\n message_id, session_id, turn_id, event_id, source_message_id, role,\n author_name, model, timestamp, ordinal, parent_message_id, request_id,\n status, raw_record_id\n ) VALUES (?, ?, NULL, ?, ?, ?, NULL, ?, ?, ?, NULL, NULL, NULL, ?)`,\n )\n for (const m of pending.messages) {\n insertMsg.run(\n m.message_id,\n pending.session.session_id,\n m.event_id,\n m.source_message_id,\n m.role,\n m.model,\n m.timestamp,\n m.ordinal,\n m.raw_record_id,\n )\n }\n\n const insertBlock = prepare(\n bundle.db,\n `INSERT OR REPLACE INTO content_blocks (\n block_id, message_id, event_id, session_id, ordinal, block_type,\n text_object_id, text_inline, mime_type, token_count, is_error,\n is_redacted, visibility, raw_record_id\n ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, NULL, NULL, ?, 0, ?, ?)`,\n )\n for (const b of pending.blocks) {\n insertBlock.run(\n b.block_id,\n b.message_id,\n b.event_id,\n pending.session.session_id,\n b.ordinal,\n b.block_type,\n b.text_object_id,\n b.text_inline,\n b.is_error,\n b.visibility,\n b.raw_record_id,\n )\n }\n\n const insertCall = prepare(\n bundle.db,\n `INSERT OR REPLACE INTO tool_calls (\n tool_call_id, session_id, turn_id, message_id, event_id,\n source_call_id, tool_name, canonical_tool_type, args_object_id,\n command, cwd, path, query, timestamp_start, timestamp_end, status,\n raw_record_id\n ) VALUES (?, ?, NULL, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, NULL, ?, ?)`,\n )\n for (const c of pending.toolCallsList) {\n insertCall.run(\n c.tool_call_id,\n pending.session.session_id,\n c.message_id,\n c.event_id,\n c.source_call_id,\n c.tool_name,\n c.canonical_tool_type,\n c.args_object_id,\n c.command,\n c.cwd,\n c.path,\n c.query,\n c.timestamp_start,\n c.status,\n c.raw_record_id,\n )\n }\n\n const insertResult = prepare(\n bundle.db,\n `INSERT OR REPLACE INTO tool_results (\n tool_result_id, tool_call_id, session_id, message_id, event_id,\n source_call_id, status, is_error, exit_code, duration_ms,\n stdout_object_id, stderr_object_id, output_object_id, preview, raw_record_id\n ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, NULL, NULL, NULL, NULL, ?, ?, ?)`,\n )\n for (const r of pending.toolResults) {\n insertResult.run(\n r.tool_result_id,\n r.tool_call_id,\n pending.session.session_id,\n r.message_id,\n r.event_id,\n r.source_call_id,\n r.status,\n r.is_error,\n r.output_object_id,\n r.preview,\n r.raw_record_id,\n )\n }\n\n const insertSearch = prepare(\n bundle.db,\n `INSERT OR REPLACE INTO search_docs (\n doc_id, entity_type, entity_id, session_id, project_id, timestamp,\n role, tool_name, canonical_tool_type, field_kind, text\n ) VALUES (?, ?, ?, ?, NULL, ?, ?, ?, ?, ?, ?)`,\n )\n for (const d of pending.searchDocs) {\n insertSearch.run(\n d.doc_id,\n d.entity_type,\n d.entity_id,\n pending.session.session_id,\n d.timestamp,\n d.role,\n d.tool_name,\n d.canonical_tool_type,\n d.field_kind,\n d.text,\n )\n }\n\n void artifactId // referenced by other importers; kept here for symmetry\n}\n","import { readdir } from 'node:fs/promises'\nimport path from 'node:path'\n\n/** Discovered Cursor `store.db` with workspace and agent ids derived from the path. */\nexport interface CursorStoreDb {\n filePath: string\n workspaceId: string\n agentId: string\n}\n\n/**\n * Walk `<root>` (typically `~/.cursor/chats`) and yield every `store.db`\n * SQLite file together with the workspace/agent ids derived from the path.\n * Layout: `<root>/<workspace>/<agent>/store.db`.\n */\nexport async function* discoverCursorStores(root: string): AsyncGenerator<CursorStoreDb, void, void> {\n const workspaces = await readdirSafe(root)\n for (const ws of workspaces) {\n if (!ws.isDirectory()) continue\n const wsPath = path.join(root, ws.name)\n const agents = await readdirSafe(wsPath)\n for (const ag of agents) {\n if (!ag.isDirectory()) continue\n const dbPath = path.join(wsPath, ag.name, 'store.db')\n const dbEntries = await readdirSafe(path.join(wsPath, ag.name))\n const hasStoreDb = dbEntries.some((e) => e.isFile() && e.name === 'store.db')\n if (!hasStoreDb) continue\n yield {\n filePath: dbPath,\n workspaceId: ws.name,\n agentId: ag.name,\n }\n }\n }\n}\n\n/** Read optional Cursor workspace directories as empty when they are missing. */\nasync function readdirSafe(dir: string): Promise<import('node:fs').Dirent[]> {\n try {\n return await readdir(dir, { withFileTypes: true })\n } catch {\n return []\n }\n}\n","import { readFile } from 'node:fs/promises'\nimport path from 'node:path'\nimport type { Bundle } from '../../core/bundle.js'\nimport { sha256Hex } from '../../core/cas/hash.js'\nimport {\n type ObjectId,\n type PendingObjects,\n createPendingObjects,\n flushPendingObjects,\n stageBytes,\n stageJson,\n stageText,\n} from '../../core/cas/index.js'\nimport { prepare, transactional } from '../../core/db.js'\nimport {\n artifactId,\n blockId,\n eventId as makeEventId,\n messageId as makeMessageId,\n projectId as makeProjectId,\n rawRecordId as makeRawRecordId,\n sessionId as makeSessionId,\n toolCallId as makeToolCallId,\n toolResultId as makeToolResultId,\n} from '../../core/domain/ids.js'\nimport { normalizeToolCallStatus } from '../../core/domain/status.js'\nimport { getErrorMessage } from '../../core/errors.js'\nimport {\n type ImportBatch,\n type ImportCounts,\n emptyCounts,\n finishBatch,\n recordError,\n startBatch,\n} from '../../core/ingest/batch.js'\nimport { registerSourceFile } from '../../core/ingest/idempotency.js'\nimport type { CompileLogger, CompileOptions } from '../compile-options.js'\nimport { type GeminiChatFile, discoverGeminiChats } from './discover.js'\nimport type { GeminiContentItem, GeminiMessage, GeminiSessionFile, GeminiToolCall, GeminiToolResult } from './types.js'\n\n/** Result returned after a Gemini compile batch finishes or records a failed batch. */\nexport interface CompileResult {\n /** Import batch created for this Gemini run. */\n batch: ImportBatch\n /** Final counts accumulated while importing Gemini files. */\n counts: ImportCounts\n}\n\n/** Maximum inline text retained in normalized rows before full content moves to CAS. */\nconst PREVIEW_MAX = 4_000\n\n/** Compile Gemini CLI chat snapshot files under `root` into the bundle. */\nexport async function compileGemini(\n bundle: Bundle,\n root: string,\n options: CompileOptions = {},\n): Promise<CompileResult> {\n const logger = options.logger\n const batch = startBatch(bundle, 'gemini', [root])\n const counts = emptyCounts()\n logger?.info({ batch_id: batch.batch_id, root }, 'gemini batch started')\n try {\n for await (const file of discoverGeminiChats(root)) {\n counts.source_files_seen++\n logger?.debug(\n {\n path: file.filePath,\n project_dir: file.projectDir,\n project_root: file.projectRoot,\n },\n 'gemini source file discovered',\n )\n try {\n const fc = await compileGeminiFile(bundle, batch, file, logger)\n addCounts(counts, fc)\n } catch (error) {\n counts.errors++\n logger?.warn(\n {\n err: error,\n path: file.filePath,\n },\n 'gemini source file failed',\n )\n await recordError(bundle, batch.batch_id, {\n kind: 'gemini_file_failed',\n message: getErrorMessage(error),\n payload: { path: file.filePath },\n })\n }\n }\n finishBatch(bundle, batch, counts, 'completed')\n logger?.info({ batch_id: batch.batch_id, counts }, 'gemini batch completed')\n } catch (error) {\n finishBatch(bundle, batch, counts, 'failed')\n logger?.error({ err: error, batch_id: batch.batch_id, counts }, 'gemini batch failed')\n throw error\n }\n return { batch, counts }\n}\n\n/** Per-source-file deltas that are merged into the import batch counts. */\ninterface FileCounts {\n source_files_imported: number\n source_files_skipped: number\n raw_records: number\n sessions: number\n events: number\n messages: number\n content_blocks: number\n tool_calls: number\n tool_results: number\n artifacts: number\n edges: number\n errors: number\n}\n\n/** Create zeroed file counters for a Gemini file that may still fail or be skipped. */\nfunction emptyFileCounts(): FileCounts {\n return {\n source_files_imported: 0,\n source_files_skipped: 0,\n raw_records: 0,\n sessions: 0,\n events: 0,\n messages: 0,\n content_blocks: 0,\n tool_calls: 0,\n tool_results: 0,\n artifacts: 0,\n edges: 0,\n errors: 0,\n }\n}\n\n/** Merge a single Gemini file's normalized row counts into batch totals. */\nfunction addCounts(target: ImportCounts, source: FileCounts): void {\n target.source_files_imported += source.source_files_imported\n target.source_files_skipped += source.source_files_skipped\n target.raw_records += source.raw_records\n target.sessions += source.sessions\n target.events += source.events\n target.messages += source.messages\n target.content_blocks += source.content_blocks\n target.tool_calls += source.tool_calls\n target.tool_results += source.tool_results\n target.artifacts += source.artifacts\n target.edges += source.edges\n target.errors += source.errors\n}\n\n/** All normalized Gemini rows staged for one source file before FK-ordered flush. */\ninterface PendingState {\n rawRecords: PendingRawRecord[]\n session: PendingSession | null\n events: PendingEvent[]\n messages: PendingMessage[]\n blocks: PendingBlock[]\n toolCallsList: PendingToolCall[]\n toolResults: PendingToolResult[]\n artifacts: PendingArtifact[]\n searchDocs: PendingSearchDoc[]\n project: PendingProject | null\n objects: PendingObjects\n}\n\n/** Raw record row staged from a Gemini JSON pointer before database insertion. */\ninterface PendingRawRecord {\n raw_record_id: string\n source_file_id: string\n ordinal: number | null\n line_no: number | null\n json_pointer: string | null\n native_id: string | null\n raw_object_id: ObjectId\n decoded_json_object_id: ObjectId | null\n parser_status: 'ok' | 'partial' | 'failed'\n confidence: 'high' | 'medium' | 'low'\n import_batch_id: string\n record_kind: 'json_pointer' | 'jsonl_line'\n}\n\n/** Session row staged from the Gemini snapshot root object. */\ninterface PendingSession {\n session_id: string\n source_session_id: string\n start_ts: string | null\n end_ts: string | null\n cwd_initial: string | null\n title: string | null\n raw_record_id: string | null\n}\n\n/** Project row staged from Gemini `.project_root` metadata when available. */\ninterface PendingProject {\n project_id: string\n canonical_path: string | null\n source_project_id: string\n}\n\n/** Event row staged from Gemini messages and operational snapshot entries. */\ninterface PendingEvent {\n event_id: string\n ordinal: number\n source_event_id: string | null\n event_type: string\n source_type: string\n subtype: string | null\n timestamp: string | null\n actor: string | null\n payload_object_id: ObjectId | null\n raw_record_id: string\n confidence: 'high' | 'medium' | 'low'\n}\n\n/** Message row staged from Gemini user and model entries. */\ninterface PendingMessage {\n message_id: string\n event_id: string | null\n source_message_id: string | null\n role: 'system_prompt' | 'developer' | 'user' | 'assistant' | 'tool' | 'operational'\n model: string | null\n timestamp: string | null\n ordinal: number\n raw_record_id: string\n}\n\n/** Content block row staged from Gemini content strings, content arrays, and thoughts. */\ninterface PendingBlock {\n block_id: string\n message_id: string | null\n event_id: string | null\n ordinal: number\n block_type: string\n text_object_id: ObjectId | null\n text_inline: string | null\n visibility: 'default' | 'hidden_by_default' | 'audit_only'\n raw_record_id: string\n}\n\n/** Tool call row staged from Gemini message-level tool calls. */\ninterface PendingToolCall {\n tool_call_id: string\n message_id: string | null\n event_id: string | null\n source_call_id: string\n tool_name: string\n canonical_tool_type: string\n args_object_id: ObjectId | null\n command: string | null\n cwd: string | null\n path: string | null\n query: string | null\n timestamp_start: string | null\n status: string | null\n raw_record_id: string\n}\n\n/** Tool result row staged from Gemini tool-call result arrays. */\ninterface PendingToolResult {\n tool_result_id: string\n tool_call_id: string\n source_call_id: string\n message_id: string | null\n event_id: string | null\n status: string | null\n is_error: 0 | 1\n output_object_id: ObjectId | null\n preview: string | null\n raw_record_id: string\n}\n\n/** Artifact row staged from Gemini result display diffs. */\ninterface PendingArtifact {\n artifact_id: string\n kind: string\n path: string | null\n logical_path: string | null\n object_id: ObjectId | null\n text_object_id: ObjectId | null\n mime_type: string | null\n size_bytes: number\n created_ts: string | null\n raw_record_id: string\n}\n\n/** Search index row staged from normalized Gemini messages, commands, paths, and previews. */\ninterface PendingSearchDoc {\n doc_id: string\n entity_type: string\n entity_id: string\n timestamp: string | null\n role: string | null\n tool_name: string | null\n canonical_tool_type: string | null\n field_kind: string\n text: string\n}\n\n/** Parse one Gemini chat snapshot, stage CAS objects, and flush normalized rows. */\nasync function compileGeminiFile(\n bundle: Bundle,\n batch: ImportBatch,\n file: GeminiChatFile,\n logger?: CompileLogger,\n): Promise<FileCounts> {\n const counts = emptyFileCounts()\n\n const { row: sourceFile, alreadyKnown } = await registerSourceFile(bundle, {\n sourceTool: 'gemini',\n absolutePath: path.resolve(file.filePath),\n fileKind: 'json',\n workspaceHint: file.projectDir,\n })\n if (alreadyKnown) {\n counts.source_files_skipped = 1\n logger?.debug({ path: file.filePath, source_file_id: sourceFile.source_file_id }, 'gemini source file skipped')\n return counts\n }\n counts.source_files_imported = 1\n logger?.debug({ path: file.filePath, source_file_id: sourceFile.source_file_id }, 'gemini source file registered')\n\n const text = await readFile(file.filePath, 'utf8')\n const parsed = JSON.parse(text) as GeminiSessionFile\n const objects = createPendingObjects()\n const fileObjectId = stageBytes(objects, Buffer.from(text, 'utf8'), {\n mimeType: 'application/json',\n encoding: 'utf-8',\n })\n\n const rootRawRecordId = makeRawRecordId(sourceFile.source_file_id, 0, fileObjectId)\n const pending: PendingState = {\n rawRecords: [\n {\n raw_record_id: rootRawRecordId,\n source_file_id: sourceFile.source_file_id,\n ordinal: 0,\n line_no: null,\n json_pointer: '',\n native_id: parsed.sessionId ?? null,\n raw_object_id: fileObjectId,\n decoded_json_object_id: fileObjectId,\n parser_status: 'ok',\n confidence: 'high',\n import_batch_id: batch.batch_id,\n record_kind: 'json_pointer',\n },\n ],\n session: null,\n events: [],\n messages: [],\n blocks: [],\n toolCallsList: [],\n toolResults: [],\n artifacts: [],\n searchDocs: [],\n project: null,\n objects,\n }\n\n const sourceSid = parsed.sessionId ?? path.basename(file.filePath, '.json')\n const sessionPk = makeSessionId('gemini', sourceSid)\n\n const existingSession = prepare<[string], { session_id: string }>(\n bundle.db,\n `SELECT session_id FROM sessions WHERE session_id = ? LIMIT 1`,\n ).get(sessionPk)\n if (existingSession) {\n logger?.warn(\n {\n path: file.filePath,\n session_id: sessionPk,\n source_session_id: sourceSid,\n },\n 'gemini duplicate snapshot detected; later rows will be dropped by INSERT OR IGNORE',\n )\n await recordError(bundle, batch.batch_id, {\n sourceFileId: sourceFile.source_file_id,\n kind: 'gemini_duplicate_snapshot',\n message: `duplicate Gemini snapshot for sessionId ${sourceSid}; first-sorted snapshot wins, rows from this file are dropped at the normalized layer`,\n payload: {\n path: file.filePath,\n session_id: sessionPk,\n source_session_id: sourceSid,\n },\n })\n }\n\n const projectKey = parsed.projectHash ?? file.projectDir\n if (projectKey) {\n pending.project = {\n project_id: makeProjectId('gemini', projectKey),\n canonical_path: file.projectRoot,\n source_project_id: projectKey,\n }\n }\n\n const start = parsed.startTime ?? null\n const end = parsed.lastUpdated ?? null\n pending.session = {\n session_id: sessionPk,\n source_session_id: sourceSid,\n start_ts: start,\n end_ts: end,\n cwd_initial: file.projectRoot,\n title: parsed.summary ?? null,\n raw_record_id: rootRawRecordId,\n }\n\n const messages = Array.isArray(parsed.messages) ? parsed.messages : []\n\n for (let i = 0; i < messages.length; i++) {\n const msg = messages[i]\n if (!msg) continue\n processMessage(sessionPk, sourceFile.source_file_id, i, msg, batch.batch_id, pending)\n }\n\n buildSearchDocs(pending)\n\n // Persist staged CAS objects (FS + objects rows) before the domain\n // transaction. better-sqlite3 transactions are sync.\n await flushPendingObjects(bundle, pending.objects)\n\n transactional(bundle.db, () => {\n flushPending(bundle, pending)\n })\n\n counts.raw_records = pending.rawRecords.length\n counts.sessions = pending.session ? 1 : 0\n counts.events = pending.events.length\n counts.messages = pending.messages.length\n counts.content_blocks = pending.blocks.length\n counts.tool_calls = pending.toolCallsList.length\n counts.tool_results = pending.toolResults.length\n counts.artifacts = pending.artifacts.length\n logger?.debug(\n { path: file.filePath, source_file_id: sourceFile.source_file_id, counts },\n 'gemini source file imported',\n )\n return counts\n}\n\n/** Normalize one Gemini message snapshot entry into events, messages, blocks, and tools. */\nfunction processMessage(\n sessionId: string,\n sourceFileId: string,\n index: number,\n msg: GeminiMessage,\n batchId: string,\n pending: PendingState,\n): void {\n const ordinal = index + 1\n const ts = msg.timestamp ?? null\n\n const payloadId = stageJson(pending.objects, msg)\n // Use the JSON pointer as a stable per-record locator inside the file.\n const pointer = `/messages/${index}`\n const rawRecordId = makeRawRecordId(sourceFileId, ordinal, payloadId)\n\n pending.rawRecords.push({\n raw_record_id: rawRecordId,\n source_file_id: sourceFileId,\n ordinal,\n line_no: null,\n json_pointer: pointer,\n native_id: msg.id ?? null,\n raw_object_id: payloadId,\n decoded_json_object_id: payloadId,\n parser_status: 'ok',\n confidence: 'high',\n import_batch_id: batchId,\n record_kind: 'json_pointer',\n })\n\n const kind = msg.type ?? 'unknown'\n\n if (kind === 'user' || kind === 'gemini') {\n const role: PendingMessage['role'] = kind === 'user' ? 'user' : 'assistant'\n const messageId = makeMessageId(sessionId, ordinal, msg.id ?? null)\n const eventId = makeEventId(sessionId, ordinal, 'message')\n\n pending.events.push({\n event_id: eventId,\n ordinal,\n source_event_id: msg.id ?? null,\n event_type: 'message',\n source_type: kind,\n subtype: null,\n timestamp: ts,\n actor: role,\n payload_object_id: payloadId,\n raw_record_id: rawRecordId,\n confidence: 'high',\n })\n\n pending.messages.push({\n message_id: messageId,\n event_id: eventId,\n source_message_id: msg.id ?? null,\n role,\n model: role === 'assistant' ? (msg.model ?? null) : null,\n timestamp: ts,\n ordinal,\n raw_record_id: rawRecordId,\n })\n\n // Content blocks.\n const content = msg.content\n if (typeof content === 'string') {\n pushTextBlock(pending, messageId, 0, 'text', content, rawRecordId)\n } else if (Array.isArray(content)) {\n for (let i = 0; i < content.length; i++) {\n const item = content[i] as GeminiContentItem | undefined\n if (!item) continue\n const t = item.text ?? ''\n pushTextBlock(pending, messageId, i, item.type ?? 'text', t, rawRecordId)\n }\n }\n\n // Thoughts → audit-only blocks (don't pollute search by default).\n const thoughts = Array.isArray(msg.thoughts) ? msg.thoughts : []\n for (let i = 0; i < thoughts.length; i++) {\n const th = thoughts[i]\n if (!th) continue\n const text = [th.subject, th.description].filter(Boolean).join('\\n\\n')\n pushTextBlock(pending, messageId, 100 + i, 'thinking', text, rawRecordId, 'hidden_by_default')\n }\n\n // Tool calls.\n const toolCalls = Array.isArray(msg.toolCalls) ? msg.toolCalls : []\n for (let i = 0; i < toolCalls.length; i++) {\n const tc = toolCalls[i]\n if (!tc) continue\n processToolCall(sessionId, messageId, eventId, i, tc, rawRecordId, pending)\n }\n return\n }\n\n if (kind === 'info' || kind === 'error') {\n const eventId = makeEventId(sessionId, ordinal, kind)\n pending.events.push({\n event_id: eventId,\n ordinal,\n source_event_id: msg.id ?? null,\n event_type: kind === 'error' ? 'error' : 'system_operational',\n source_type: kind,\n subtype: null,\n timestamp: ts,\n actor: 'system',\n payload_object_id: payloadId,\n raw_record_id: rawRecordId,\n confidence: 'high',\n })\n return\n }\n\n // Unknown type — keep as operational event.\n pending.events.push({\n event_id: makeEventId(sessionId, ordinal, `unknown.${kind}`),\n ordinal,\n source_event_id: msg.id ?? null,\n event_type: 'system_operational',\n source_type: kind,\n subtype: null,\n timestamp: ts,\n actor: 'system',\n payload_object_id: payloadId,\n raw_record_id: rawRecordId,\n confidence: 'high',\n })\n}\n\n/** Stage a Gemini text-like content block, storing long bodies in CAS. */\nfunction pushTextBlock(\n pending: PendingState,\n messageId: string,\n blockOrdinal: number,\n blockType: string,\n text: string,\n rawRecordId: string,\n visibility: 'default' | 'hidden_by_default' | 'audit_only' = 'default',\n): void {\n if (!text) return\n const overflowId = text.length > PREVIEW_MAX ? stageText(pending.objects, text) : null\n pending.blocks.push({\n block_id: blockId(messageId, blockOrdinal),\n message_id: messageId,\n event_id: null,\n ordinal: blockOrdinal,\n block_type: blockType,\n text_object_id: overflowId,\n text_inline: text.slice(0, PREVIEW_MAX),\n visibility,\n raw_record_id: rawRecordId,\n })\n}\n\n/** Normalize a Gemini tool call and its embedded result/display metadata. */\nfunction processToolCall(\n sessionId: string,\n messageId: string,\n eventId: string,\n index: number,\n tc: GeminiToolCall,\n rawRecordId: string,\n pending: PendingState,\n): void {\n const sourceCallId = tc.id ?? `${messageId}:${index}`\n const toolName = tc.name ?? 'unknown'\n const toolCallId = makeToolCallId(sessionId, sourceCallId)\n const argsObjectId = tc.args ? stageJson(pending.objects, tc.args) : null\n\n pending.toolCallsList.push({\n tool_call_id: toolCallId,\n message_id: messageId,\n event_id: eventId,\n source_call_id: sourceCallId,\n tool_name: toolName,\n canonical_tool_type: canonicalToolType(toolName),\n args_object_id: argsObjectId,\n command: typeof tc.args?.command === 'string' ? (tc.args.command as string) : null,\n cwd: typeof tc.args?.dir_path === 'string' ? (tc.args.dir_path as string) : null,\n path:\n typeof tc.args?.file_path === 'string'\n ? (tc.args.file_path as string)\n : typeof tc.args?.path === 'string'\n ? (tc.args.path as string)\n : null,\n query: typeof tc.args?.query === 'string' ? (tc.args.query as string) : null,\n timestamp_start: tc.timestamp ?? null,\n status: normalizeToolCallStatus('gemini', tc.status),\n raw_record_id: rawRecordId,\n })\n\n const isError = tc.status === 'error' ? 1 : 0\n const resultText = renderToolResultText(tc.result)\n const overflowId = resultText.length > PREVIEW_MAX ? stageText(pending.objects, resultText) : null\n\n pending.toolResults.push({\n tool_result_id: makeToolResultId(sessionId, sourceCallId),\n tool_call_id: toolCallId,\n source_call_id: sourceCallId,\n message_id: messageId,\n event_id: eventId,\n status: normalizeToolCallStatus('gemini', tc.status),\n is_error: isError,\n output_object_id: overflowId,\n preview: resultText.slice(0, PREVIEW_MAX) || null,\n raw_record_id: rawRecordId,\n })\n\n // resultDisplay diffs become artifacts.\n if (tc.resultDisplay && typeof tc.resultDisplay === 'object') {\n const rd = tc.resultDisplay\n if (rd.fileDiff || rd.filePath) {\n const diffText = rd.fileDiff ?? ''\n const diffId = diffText ? stageText(pending.objects, diffText, { mimeType: 'text/x-diff' }) : null\n pending.artifacts.push({\n artifact_id: artifactId(sessionId, 'gemini', `${toolCallId}:diff`),\n kind: 'diff',\n path: rd.filePath ?? null,\n logical_path: rd.fileName ?? rd.filePath ?? null,\n object_id: diffId,\n text_object_id: diffId,\n mime_type: 'text/x-diff',\n size_bytes: diffText.length,\n created_ts: tc.timestamp ?? null,\n raw_record_id: rawRecordId,\n })\n }\n pushResultDisplayFileArtifact(pending, sessionId, toolCallId, rawRecordId, tc, rd, 'newContent', 'new')\n pushResultDisplayFileArtifact(pending, sessionId, toolCallId, rawRecordId, tc, rd, 'originalContent', 'original')\n }\n}\n\nfunction pushResultDisplayFileArtifact(\n pending: PendingState,\n sessionId: string,\n toolCallId: string,\n rawRecordId: string,\n tc: GeminiToolCall,\n rd: Exclude<GeminiToolCall['resultDisplay'], string | undefined>,\n field: 'newContent' | 'originalContent',\n suffix: 'new' | 'original',\n): void {\n const text = rd[field]\n if (typeof text !== 'string' || text.length === 0) return\n const objectId = stageText(pending.objects, text)\n pending.artifacts.push({\n artifact_id: artifactId(sessionId, 'gemini', `${toolCallId}:${suffix}`),\n kind: 'file',\n path: rd.filePath ?? null,\n logical_path: rd.fileName ?? rd.filePath ?? null,\n object_id: objectId,\n text_object_id: objectId,\n mime_type: null,\n size_bytes: Buffer.byteLength(text, 'utf8'),\n created_ts: tc.timestamp ?? null,\n raw_record_id: rawRecordId,\n })\n}\n\n/** Render Gemini's heterogeneous tool result array into the preview text used for search. */\nfunction renderToolResultText(result: GeminiToolResult[] | undefined): string {\n if (!Array.isArray(result)) return ''\n const parts: string[] = []\n for (const r of result) {\n if (r.text) {\n parts.push(r.text)\n continue\n }\n if (r.functionResponse?.response) {\n const rr = r.functionResponse.response\n if (rr.error != null) parts.push(typeof rr.error === 'string' ? rr.error : JSON.stringify(rr.error))\n else if (rr.output != null) parts.push(typeof rr.output === 'string' ? rr.output : JSON.stringify(rr.output))\n }\n }\n return parts.join('\\n')\n}\n\n/** Collapse Gemini tool names into broad search/filter tool categories. */\nfunction canonicalToolType(toolName: string): string {\n switch (toolName) {\n case 'run_shell_command':\n case 'shell':\n case 'shell_command':\n return 'shell'\n case 'read_file':\n case 'read_many_files':\n return 'read_file'\n case 'write_file':\n return 'write_file'\n case 'replace':\n case 'search_replace':\n return 'edit_file'\n case 'list_directory':\n case 'glob':\n case 'grep_search':\n case 'search_file_content':\n return 'search_file'\n case 'google_web_search':\n return 'web_search'\n case 'codebase_investigator':\n return 'other'\n default:\n return toolName.startsWith('mcp__') ? 'mcp' : 'other'\n }\n}\n\n/** Build searchable Gemini documents while excluding hidden thought blocks. */\nfunction buildSearchDocs(pending: PendingState): void {\n const sessionId = pending.session?.session_id ?? null\n if (!sessionId) return\n const blocksByMsg = new Map<string, PendingBlock[]>()\n for (const b of pending.blocks) {\n if (!b.message_id) continue\n if (b.visibility === 'hidden_by_default') continue\n const list = blocksByMsg.get(b.message_id) ?? []\n list.push(b)\n blocksByMsg.set(b.message_id, list)\n }\n for (const m of pending.messages) {\n const text = (blocksByMsg.get(m.message_id) ?? [])\n .map((b) => b.text_inline ?? '')\n .join('\\n')\n .trim()\n if (!text) continue\n pending.searchDocs.push({\n doc_id: `msg:${m.message_id}`,\n entity_type: 'message',\n entity_id: m.message_id,\n timestamp: m.timestamp,\n role: m.role,\n tool_name: null,\n canonical_tool_type: null,\n field_kind: m.role === 'user' ? 'user_prompt' : 'assistant_text',\n text,\n })\n }\n for (const tc of pending.toolCallsList) {\n if (tc.command) {\n pending.searchDocs.push({\n doc_id: `tc:cmd:${tc.tool_call_id}`,\n entity_type: 'tool_call',\n entity_id: tc.tool_call_id,\n timestamp: tc.timestamp_start,\n role: null,\n tool_name: tc.tool_name,\n canonical_tool_type: tc.canonical_tool_type,\n field_kind: 'command',\n text: tc.command,\n })\n }\n if (tc.path) {\n pending.searchDocs.push({\n doc_id: `tc:path:${tc.tool_call_id}`,\n entity_type: 'tool_call',\n entity_id: tc.tool_call_id,\n timestamp: tc.timestamp_start,\n role: null,\n tool_name: tc.tool_name,\n canonical_tool_type: tc.canonical_tool_type,\n field_kind: 'file_path',\n text: tc.path,\n })\n }\n }\n for (const tr of pending.toolResults) {\n if (!tr.preview) continue\n pending.searchDocs.push({\n doc_id: `tr:preview:${tr.tool_result_id}`,\n entity_type: 'tool_result',\n entity_id: tr.tool_result_id,\n timestamp: null,\n role: null,\n tool_name: null,\n canonical_tool_type: null,\n field_kind: tr.is_error ? 'error' : 'tool_result',\n text: tr.preview,\n })\n }\n}\n\n/** Insert staged Gemini rows in foreign-key order after CAS objects are already durable. */\nfunction flushPending(bundle: Bundle, pending: PendingState): void {\n if (!pending.session) return\n\n const insertRaw = prepare(\n bundle.db,\n `INSERT OR IGNORE INTO raw_records (\n raw_record_id, source_file_id, source_tool, record_kind, ordinal,\n line_no, json_pointer, native_id, raw_object_id, decoded_json_object_id,\n parser_status, confidence, import_batch_id\n ) VALUES (?, ?, 'gemini', ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,\n )\n for (const r of pending.rawRecords) {\n insertRaw.run(\n r.raw_record_id,\n r.source_file_id,\n r.record_kind,\n r.ordinal,\n r.line_no,\n r.json_pointer,\n r.native_id,\n r.raw_object_id,\n r.decoded_json_object_id,\n r.parser_status,\n r.confidence,\n r.import_batch_id,\n )\n }\n\n if (pending.project) {\n prepare(\n bundle.db,\n `INSERT OR IGNORE INTO projects (\n project_id, canonical_path, path_hash, source_tool, source_project_id,\n display_name, created_at\n ) VALUES (?, ?, ?, 'gemini', ?, NULL, ?)`,\n ).run(\n pending.project.project_id,\n pending.project.canonical_path,\n pending.project.canonical_path ? sha256Hex(pending.project.canonical_path).slice(0, 32) : null,\n pending.project.source_project_id,\n new Date().toISOString(),\n )\n }\n\n prepare(\n bundle.db,\n `INSERT OR IGNORE INTO sessions (\n session_id, source_tool, source_session_id, project_id, parent_session_id,\n is_subagent, agent_role, agent_nickname, title, summary,\n start_ts, end_ts, cwd_initial, git_branch_initial,\n model_first, model_last, status, timeline_confidence, raw_record_id\n ) VALUES (?, 'gemini', ?, ?, NULL, 0, NULL, NULL, ?, NULL, ?, ?, ?, NULL, NULL, NULL, 'completed', 'high', ?)`,\n ).run(\n pending.session.session_id,\n pending.session.source_session_id,\n pending.project?.project_id ?? null,\n pending.session.title,\n pending.session.start_ts,\n pending.session.end_ts,\n pending.session.cwd_initial,\n pending.session.raw_record_id,\n )\n\n const insertEvent = prepare(\n bundle.db,\n `INSERT OR IGNORE INTO events (\n event_id, session_id, turn_id, source_event_id, event_type, source_type,\n subtype, timestamp, ordinal, actor, payload_object_id, raw_record_id,\n confidence, is_derived\n ) VALUES (?, ?, NULL, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 0)`,\n )\n for (const e of pending.events) {\n insertEvent.run(\n e.event_id,\n pending.session.session_id,\n e.source_event_id,\n e.event_type,\n e.source_type,\n e.subtype,\n e.timestamp,\n e.ordinal,\n e.actor,\n e.payload_object_id,\n e.raw_record_id,\n e.confidence,\n )\n }\n\n const insertMsg = prepare(\n bundle.db,\n `INSERT OR IGNORE INTO messages (\n message_id, session_id, turn_id, event_id, source_message_id, role,\n author_name, model, timestamp, ordinal, parent_message_id, request_id,\n status, raw_record_id\n ) VALUES (?, ?, NULL, ?, ?, ?, NULL, ?, ?, ?, NULL, NULL, NULL, ?)`,\n )\n for (const m of pending.messages) {\n insertMsg.run(\n m.message_id,\n pending.session.session_id,\n m.event_id,\n m.source_message_id,\n m.role,\n m.model,\n m.timestamp,\n m.ordinal,\n m.raw_record_id,\n )\n }\n\n const insertBlock = prepare(\n bundle.db,\n `INSERT OR IGNORE INTO content_blocks (\n block_id, message_id, event_id, session_id, ordinal, block_type,\n text_object_id, text_inline, mime_type, token_count, is_error,\n is_redacted, visibility, raw_record_id\n ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, NULL, NULL, 0, 0, ?, ?)`,\n )\n for (const b of pending.blocks) {\n insertBlock.run(\n b.block_id,\n b.message_id,\n b.event_id,\n pending.session.session_id,\n b.ordinal,\n b.block_type,\n b.text_object_id,\n b.text_inline,\n b.visibility,\n b.raw_record_id,\n )\n }\n\n const insertCall = prepare(\n bundle.db,\n `INSERT OR IGNORE INTO tool_calls (\n tool_call_id, session_id, turn_id, message_id, event_id,\n source_call_id, tool_name, canonical_tool_type, args_object_id,\n command, cwd, path, query, timestamp_start, timestamp_end, status,\n raw_record_id\n ) VALUES (?, ?, NULL, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, NULL, ?, ?)`,\n )\n for (const c of pending.toolCallsList) {\n insertCall.run(\n c.tool_call_id,\n pending.session.session_id,\n c.message_id,\n c.event_id,\n c.source_call_id,\n c.tool_name,\n c.canonical_tool_type,\n c.args_object_id,\n c.command,\n c.cwd,\n c.path,\n c.query,\n c.timestamp_start,\n c.status,\n c.raw_record_id,\n )\n }\n\n const insertResult = prepare(\n bundle.db,\n `INSERT OR IGNORE INTO tool_results (\n tool_result_id, tool_call_id, session_id, message_id, event_id,\n source_call_id, status, is_error, exit_code, duration_ms,\n stdout_object_id, stderr_object_id, output_object_id, preview, raw_record_id\n ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, NULL, NULL, NULL, NULL, ?, ?, ?)`,\n )\n for (const r of pending.toolResults) {\n insertResult.run(\n r.tool_result_id,\n r.tool_call_id,\n pending.session.session_id,\n r.message_id,\n r.event_id,\n r.source_call_id,\n r.status,\n r.is_error,\n r.output_object_id,\n r.preview,\n r.raw_record_id,\n )\n }\n\n const insertArtifact = prepare(\n bundle.db,\n `INSERT OR IGNORE INTO artifacts (\n artifact_id, session_id, project_id, source_tool, kind, path,\n logical_path, object_id, text_object_id, mime_type, size_bytes,\n created_ts, raw_record_id\n ) VALUES (?, ?, ?, 'gemini', ?, ?, ?, ?, ?, ?, ?, ?, ?)`,\n )\n for (const a of pending.artifacts) {\n insertArtifact.run(\n a.artifact_id,\n pending.session.session_id,\n pending.project?.project_id ?? null,\n a.kind,\n a.path,\n a.logical_path,\n a.object_id,\n a.text_object_id,\n a.mime_type,\n a.size_bytes,\n a.created_ts,\n a.raw_record_id,\n )\n }\n\n const insertSearch = prepare(\n bundle.db,\n `INSERT OR IGNORE INTO search_docs (\n doc_id, entity_type, entity_id, session_id, project_id, timestamp,\n role, tool_name, canonical_tool_type, field_kind, text\n ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,\n )\n for (const d of pending.searchDocs) {\n insertSearch.run(\n d.doc_id,\n d.entity_type,\n d.entity_id,\n pending.session.session_id,\n pending.project?.project_id ?? null,\n d.timestamp,\n d.role,\n d.tool_name,\n d.canonical_tool_type,\n d.field_kind,\n d.text,\n )\n }\n}\n","import { readFile, readdir } from 'node:fs/promises'\nimport path from 'node:path'\n\n/** Discovered Gemini chat snapshot with project directory context. */\nexport interface GeminiChatFile {\n filePath: string\n /** Either a 64-hex hash or a project slug. */\n projectDir: string\n /** Resolved from `.project_root` if it exists in the project dir. */\n projectRoot: string | null\n}\n\n/**\n * Walk `<root>` (typically `~/.gemini/tmp`) and yield every\n * `chats/session-*.json` file together with the resolved `.project_root`.\n * Ignores `logs.json` and the `bin/` directory.\n */\nexport async function* discoverGeminiChats(root: string): AsyncGenerator<GeminiChatFile, void, void> {\n const entries = await readdirSafe(root)\n for (const entry of entries.sort((a, b) => a.name.localeCompare(b.name))) {\n if (!entry.isDirectory()) continue\n if (entry.name === 'bin') continue\n const projectRoot = await readProjectRoot(path.join(root, entry.name))\n const chatsDir = path.join(root, entry.name, 'chats')\n const chatEntries = await readdirSafe(chatsDir)\n for (const c of chatEntries.sort((a, b) => a.name.localeCompare(b.name))) {\n if (!c.isFile()) continue\n if (!c.name.startsWith('session-') || !c.name.endsWith('.json')) continue\n yield {\n filePath: path.join(chatsDir, c.name),\n projectDir: entry.name,\n projectRoot,\n }\n }\n }\n}\n\n/** Resolve Gemini's optional `.project_root` companion file. */\nasync function readProjectRoot(dir: string): Promise<string | null> {\n try {\n const text = await readFile(path.join(dir, '.project_root'), 'utf8')\n return text.replace(/\\n+$/, '').trim() || null\n } catch {\n return null\n }\n}\n\n/** Read optional Gemini directories as empty when they are missing. */\nasync function readdirSafe(dir: string): Promise<import('node:fs').Dirent[]> {\n try {\n return await readdir(dir, { withFileTypes: true })\n } catch {\n return []\n }\n}\n","import { readFile } from 'node:fs/promises'\nimport path from 'node:path'\nimport Database from 'better-sqlite3'\nimport type { Bundle } from '../../core/bundle.js'\nimport {\n type ObjectId,\n type PendingObjects,\n createPendingObjects,\n flushPendingObjects,\n stageJson,\n stageText,\n} from '../../core/cas/index.js'\nimport { prepare, transactional } from '../../core/db.js'\nimport {\n blockId,\n eventId as makeEventId,\n messageId as makeMessageId,\n projectId as makeProjectId,\n rawRecordId as makeRawRecordId,\n sessionId as makeSessionId,\n toolCallId as makeToolCallId,\n toolResultId as makeToolResultId,\n} from '../../core/domain/ids.js'\nimport { normalizeSessionStatus, normalizeToolCallStatus } from '../../core/domain/status.js'\nimport type { MessageRole, ToolCallStatus } from '../../core/domain/types.js'\nimport { getErrorMessage } from '../../core/errors.js'\nimport {\n type ImportBatch,\n type ImportCounts,\n emptyCounts,\n finishBatch,\n recordError,\n startBatch,\n} from '../../core/ingest/batch.js'\nimport { registerSourceFile } from '../../core/ingest/idempotency.js'\nimport type { CompileOptions } from '../compile-options.js'\nimport { discoverHermesSources } from './discover.js'\nimport type { HermesMessageRow, HermesSessionJson, HermesSessionRow, HermesTranscriptMessage } from './types.js'\n\n/** Result returned after a Hermes compile batch finishes or records a failed batch. */\nexport interface CompileResult {\n /** Import batch created for this Hermes run. */\n batch: ImportBatch\n /** Final counts accumulated while importing Hermes files. */\n counts: ImportCounts\n}\n\nconst PREVIEW_MAX = 4_000\n// Hidden reasoning blocks are ordered after default content blocks.\nconst HIDDEN_BLOCK_ORDINAL_BASE = 100\n\ninterface SourceFileRef {\n sourceFileId: string\n path: string\n kind: 'sqlite' | 'json' | 'jsonl' | 'index'\n imported: boolean\n}\n\ninterface SessionCandidate {\n source: 'sqlite' | 'json' | 'jsonl'\n session: NormalizedSession\n messages: NormalizedMessage[]\n sourceFile: SourceFileRef\n}\n\ninterface NormalizedSession {\n sourceSessionId: string\n source: string | null\n model: string | null\n systemPrompt: string | null\n parentSessionId: string | null\n startTs: string | null\n endTs: string | null\n status: string | null\n title: string | null\n rawPayload: unknown\n}\n\ninterface NormalizedMessage {\n sourceMessageId: string\n ordinal: number\n role: string\n content: unknown\n timestamp: string | null\n model: string | null\n toolCallId: string | null\n toolCalls: unknown\n toolName: string | null\n tokenCount: number | null\n finishReason: string | null\n reasoning: unknown\n reasoningContent: unknown\n reasoningDetails: unknown\n codexReasoningItems: unknown\n codexMessageItems: unknown\n rawPayload: unknown\n lineNo: number | null\n}\n\ninterface PendingState {\n rawRecords: PendingRawRecord[]\n projects: PendingProject[]\n sessions: PendingSession[]\n events: PendingEvent[]\n messages: PendingMessage[]\n blocks: PendingBlock[]\n toolCalls: PendingToolCall[]\n toolResults: PendingToolResult[]\n searchDocs: PendingSearchDoc[]\n objects: PendingObjects\n}\n\ninterface PendingRawRecord {\n raw_record_id: string\n source_file_id: string\n ordinal: number | null\n line_no: number | null\n json_pointer: string | null\n native_id: string | null\n raw_object_id: ObjectId\n decoded_json_object_id: ObjectId | null\n parser_status: 'ok' | 'partial' | 'failed'\n confidence: 'high' | 'medium' | 'low'\n import_batch_id: string\n record_kind: 'sqlite_row' | 'json_pointer' | 'jsonl_line'\n}\n\ninterface PendingProject {\n project_id: string\n source_project_id: string\n display_name: string | null\n}\n\ninterface PendingSession {\n session_id: string\n source_session_id: string\n project_id: string | null\n parent_session_id: string | null\n is_subagent: 0 | 1\n title: string | null\n start_ts: string | null\n end_ts: string | null\n model_first: string | null\n model_last: string | null\n status: string | null\n raw_record_id: string\n}\n\ninterface PendingEvent {\n event_id: string\n session_id: string\n ordinal: number\n source_event_id: string | null\n event_type: string\n source_type: string\n subtype: string | null\n timestamp: string | null\n actor: string | null\n payload_object_id: ObjectId | null\n raw_record_id: string\n confidence: 'high' | 'medium' | 'low'\n}\n\ninterface PendingMessage {\n message_id: string\n session_id: string\n event_id: string | null\n source_message_id: string | null\n role: MessageRole\n model: string | null\n timestamp: string | null\n ordinal: number\n status: string | null\n raw_record_id: string\n}\n\ninterface PendingBlock {\n block_id: string\n session_id: string\n message_id: string | null\n event_id: string | null\n ordinal: number\n block_type: string\n text_object_id: ObjectId | null\n text_inline: string | null\n token_count: number | null\n visibility: 'default' | 'hidden_by_default' | 'audit_only'\n raw_record_id: string\n}\n\ninterface PendingToolCall {\n tool_call_id: string\n session_id: string\n message_id: string | null\n event_id: string | null\n source_call_id: string\n tool_name: string\n canonical_tool_type: string\n args_object_id: ObjectId | null\n command: string | null\n path: string | null\n query: string | null\n timestamp_start: string | null\n status: ToolCallStatus | null\n raw_record_id: string\n}\n\ninterface PendingToolResult {\n tool_result_id: string\n tool_call_id: string\n session_id: string\n message_id: string | null\n event_id: string | null\n source_call_id: string\n status: ToolCallStatus | null\n is_error: 0 | 1\n output_object_id: ObjectId | null\n preview: string | null\n raw_record_id: string\n}\n\ninterface PendingSearchDoc {\n doc_id: string\n entity_type: string\n entity_id: string\n session_id: string\n project_id: string | null\n timestamp: string | null\n role: string | null\n tool_name: string | null\n canonical_tool_type: string | null\n field_kind: string\n text: string\n}\n\n/** Compile Hermes session storage under `root` into the bundle. */\nexport async function compileHermes(\n bundle: Bundle,\n root: string,\n options: CompileOptions = {},\n): Promise<CompileResult> {\n const logger = options.logger\n const batch = startBatch(bundle, 'hermes', [root])\n const counts = emptyCounts()\n logger?.info({ batch_id: batch.batch_id, root }, 'hermes batch started')\n\n try {\n const sources = await discoverHermesSources(root)\n const registered: SourceFileRef[] = []\n const candidates: SessionCandidate[] = []\n if (\n !sources.stateDbPath &&\n !sources.indexPath &&\n sources.jsonlFiles.length === 0 &&\n sources.jsonFiles.length === 0\n ) {\n logger?.warn({ root: sources.sessionsDir }, 'no hermes sources discovered')\n }\n\n if (sources.stateDbPath) {\n counts.source_files_seen++\n const sourceFile = await registerHermesSourceFile(bundle, sources.stateDbPath, 'sqlite', counts)\n registered.push(sourceFile)\n if (sourceFile.imported) {\n logger?.debug(\n { path: sources.stateDbPath, source_file_id: sourceFile.sourceFileId },\n 'hermes state db discovered',\n )\n try {\n candidates.push(...readSqliteCandidates(sources.stateDbPath, sourceFile))\n } catch (error) {\n await recordHermesSourceError(bundle, batch, counts, sources.stateDbPath, error, 'hermes_sqlite_failed')\n logger?.warn({ err: error, path: sources.stateDbPath }, 'hermes state db failed')\n }\n } else {\n logger?.debug(\n { path: sources.stateDbPath, source_file_id: sourceFile.sourceFileId },\n 'hermes state db unchanged, skipping read',\n )\n }\n }\n\n for (const filePath of sources.jsonlFiles) {\n counts.source_files_seen++\n const sourceFile = await registerHermesSourceFile(bundle, filePath, 'jsonl', counts)\n registered.push(sourceFile)\n if (!sourceFile.imported) {\n logger?.debug(\n { path: filePath, source_file_id: sourceFile.sourceFileId },\n 'hermes jsonl unchanged, skipping read',\n )\n continue\n }\n logger?.debug({ path: filePath, source_file_id: sourceFile.sourceFileId }, 'hermes jsonl transcript discovered')\n try {\n candidates.push(await readJsonlCandidate(filePath, sourceFile))\n } catch (error) {\n await recordHermesSourceError(bundle, batch, counts, filePath, error, 'hermes_file_failed')\n logger?.warn({ err: error, path: filePath }, 'hermes jsonl transcript failed')\n }\n }\n\n for (const filePath of sources.jsonFiles) {\n counts.source_files_seen++\n const sourceFile = await registerHermesSourceFile(bundle, filePath, 'json', counts)\n registered.push(sourceFile)\n if (!sourceFile.imported) {\n logger?.debug(\n { path: filePath, source_file_id: sourceFile.sourceFileId },\n 'hermes json unchanged, skipping read',\n )\n continue\n }\n logger?.debug({ path: filePath, source_file_id: sourceFile.sourceFileId }, 'hermes json snapshot discovered')\n try {\n candidates.push(await readJsonCandidate(filePath, sourceFile))\n } catch (error) {\n await recordHermesSourceError(bundle, batch, counts, filePath, error, 'hermes_file_failed')\n logger?.warn({ err: error, path: filePath }, 'hermes json snapshot failed')\n }\n }\n\n if (sources.indexPath) {\n counts.source_files_seen++\n const sourceFile = await registerHermesSourceFile(bundle, sources.indexPath, 'index', counts)\n registered.push(sourceFile)\n logger?.debug(\n { path: sources.indexPath, source_file_id: sourceFile.sourceFileId },\n 'hermes sessions index discovered',\n )\n }\n\n const selection = selectCandidates(candidates)\n const pending = buildPending(\n batch,\n selection.selected,\n selection.rejected,\n registered.filter((sourceFile) => sourceFile.imported),\n )\n await flushPendingObjects(bundle, pending.objects)\n transactional(bundle.db, () => flushPending(bundle, pending))\n\n counts.raw_records = pending.rawRecords.length\n counts.sessions = pending.sessions.length\n counts.events = pending.events.length\n counts.messages = pending.messages.length\n counts.content_blocks = pending.blocks.length\n counts.tool_calls = pending.toolCalls.length\n counts.tool_results = pending.toolResults.length\n counts.artifacts = 0\n counts.edges = 0\n\n finishBatch(bundle, batch, counts, 'completed')\n logger?.info({ batch_id: batch.batch_id, counts }, 'hermes batch completed')\n } catch (error) {\n finishBatch(bundle, batch, counts, 'failed')\n counts.errors++\n logger?.error({ err: error, batch_id: batch.batch_id, counts }, 'hermes batch failed')\n await recordError(bundle, batch.batch_id, {\n kind: 'hermes_batch_failed',\n message: getErrorMessage(error),\n payload: { root },\n })\n throw error\n }\n\n return { batch, counts }\n}\n\nasync function registerHermesSourceFile(\n bundle: Bundle,\n absolutePath: string,\n fileKind: SourceFileRef['kind'],\n counts: ImportCounts,\n): Promise<SourceFileRef> {\n const { row, alreadyKnown } = await registerSourceFile(bundle, {\n sourceTool: 'hermes',\n absolutePath: path.resolve(absolutePath),\n fileKind,\n })\n if (alreadyKnown) counts.source_files_skipped++\n else counts.source_files_imported++\n return {\n sourceFileId: row.source_file_id,\n path: row.path,\n kind: fileKind,\n imported: !alreadyKnown,\n }\n}\n\nasync function recordHermesSourceError(\n bundle: Bundle,\n batch: ImportBatch,\n counts: ImportCounts,\n filePath: string,\n error: unknown,\n kind: 'hermes_file_failed' | 'hermes_sqlite_failed',\n): Promise<void> {\n counts.errors++\n await recordError(bundle, batch.batch_id, {\n kind,\n message: getErrorMessage(error),\n payload: { path: filePath },\n })\n}\n\nfunction readSqliteCandidates(dbPath: string, sourceFile: SourceFileRef): SessionCandidate[] {\n const db = new Database(dbPath, { readonly: true, fileMustExist: true })\n try {\n const sessions = db\n .prepare<[], HermesSessionRow>(\n `SELECT id, source, user_id, model, model_config, system_prompt, parent_session_id,\n started_at, ended_at, end_reason, message_count, tool_call_count, title\n FROM sessions ORDER BY started_at, id`,\n )\n .all()\n const messagesBySession = new Map<string, HermesMessageRow[]>()\n const messages = db\n .prepare<[], HermesMessageRow>(\n `SELECT id, session_id, role, content, tool_call_id, tool_calls, tool_name,\n timestamp, token_count, finish_reason, reasoning, reasoning_content,\n reasoning_details, codex_reasoning_items, codex_message_items\n FROM messages ORDER BY session_id, id`,\n )\n .all()\n for (const message of messages) {\n const list = messagesBySession.get(message.session_id) ?? []\n list.push(message)\n messagesBySession.set(message.session_id, list)\n }\n\n return sessions.map((session) => ({\n source: 'sqlite',\n sourceFile,\n session: {\n sourceSessionId: session.id,\n source: session.source,\n model: session.model,\n systemPrompt: session.system_prompt,\n parentSessionId: session.parent_session_id,\n startTs: unixToIso(session.started_at),\n endTs: unixToIso(session.ended_at),\n status: session.end_reason,\n title: session.title,\n rawPayload: session,\n },\n messages: (messagesBySession.get(session.id) ?? []).map((message, index) =>\n normalizeSqliteMessage(message, index + 1),\n ),\n }))\n } finally {\n db.close()\n }\n}\n\nfunction normalizeSqliteMessage(message: HermesMessageRow, ordinal: number): NormalizedMessage {\n return {\n sourceMessageId: String(message.id),\n ordinal,\n role: message.role,\n content: decodeMaybeJson(message.content),\n timestamp: unixToIso(message.timestamp),\n model: null,\n toolCallId: message.tool_call_id,\n toolCalls: decodeMaybeJson(message.tool_calls),\n toolName: message.tool_name,\n tokenCount: message.token_count,\n finishReason: message.finish_reason,\n reasoning: decodeMaybeJson(message.reasoning),\n reasoningContent: decodeMaybeJson(message.reasoning_content),\n reasoningDetails: decodeMaybeJson(message.reasoning_details),\n codexReasoningItems: decodeMaybeJson(message.codex_reasoning_items),\n codexMessageItems: decodeMaybeJson(message.codex_message_items),\n rawPayload: message,\n lineNo: null,\n }\n}\n\nasync function readJsonlCandidate(filePath: string, sourceFile: SourceFileRef): Promise<SessionCandidate> {\n const text = await readFile(filePath, 'utf8')\n const messages: NormalizedMessage[] = []\n const sourceSessionId = path.basename(filePath, '.jsonl')\n const lines = text.split(/\\r?\\n/)\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i] ?? ''\n if (!line.trim()) continue\n const parsed = JSON.parse(line) as HermesTranscriptMessage\n messages.push(normalizeTranscriptMessage(parsed, messages.length + 1, i + 1))\n }\n return {\n source: 'jsonl',\n sourceFile,\n session: {\n sourceSessionId,\n source: null,\n model: firstString(messages.map((message) => message.model)),\n systemPrompt: null,\n parentSessionId: null,\n startTs: messages[0]?.timestamp ?? null,\n endTs: messages.at(-1)?.timestamp ?? null,\n status: null,\n title: null,\n rawPayload: { session_id: sourceSessionId, path: filePath },\n },\n messages,\n }\n}\n\nasync function readJsonCandidate(filePath: string, sourceFile: SourceFileRef): Promise<SessionCandidate> {\n const text = await readFile(filePath, 'utf8')\n const parsed = JSON.parse(text) as HermesSessionJson\n const sourceSessionId = parsed.session_id ?? path.basename(filePath, '.json').replace(/^session_/, '')\n const messages = (Array.isArray(parsed.messages) ? parsed.messages : []).map((message, index) =>\n normalizeTranscriptMessage(message, index + 1, null),\n )\n return {\n source: 'json',\n sourceFile,\n session: {\n sourceSessionId,\n source: parsed.platform ?? null,\n model: parsed.model ?? null,\n systemPrompt: parsed.system_prompt ?? null,\n parentSessionId: null,\n startTs: coerceTimestamp(parsed.session_start),\n endTs: coerceTimestamp(parsed.last_updated) ?? messages.at(-1)?.timestamp ?? null,\n status: null,\n title: null,\n rawPayload: parsed,\n },\n messages,\n }\n}\n\nfunction normalizeTranscriptMessage(\n message: HermesTranscriptMessage,\n ordinal: number,\n lineNo: number | null,\n): NormalizedMessage {\n return {\n sourceMessageId: String(lineNo ?? ordinal),\n ordinal,\n role: message.role ?? 'unknown',\n content: message.content ?? null,\n timestamp: coerceTimestamp(message.timestamp),\n model: message.model ?? null,\n toolCallId: message.tool_call_id ?? null,\n toolCalls: message.tool_calls ?? null,\n toolName: message.tool_name ?? null,\n tokenCount: message.token_count ?? null,\n finishReason: message.finish_reason ?? null,\n reasoning: message.reasoning ?? null,\n reasoningContent: message.reasoning_content ?? null,\n reasoningDetails: message.reasoning_details ?? null,\n codexReasoningItems: message.codex_reasoning_items ?? null,\n codexMessageItems: message.codex_message_items ?? null,\n rawPayload: message,\n lineNo,\n }\n}\n\nfunction selectCandidates(candidates: SessionCandidate[]): {\n selected: SessionCandidate[]\n rejected: SessionCandidate[]\n} {\n const selected = new Map<string, SessionCandidate>()\n const rejected: SessionCandidate[] = []\n for (const candidate of candidates) {\n const existing = selected.get(candidate.session.sourceSessionId)\n if (!existing) {\n selected.set(candidate.session.sourceSessionId, candidate)\n continue\n }\n if (candidate.messages.length > existing.messages.length) {\n rejected.push(existing)\n selected.set(candidate.session.sourceSessionId, candidate)\n } else {\n rejected.push(candidate)\n }\n }\n return { selected: [...selected.values()], rejected }\n}\n\nfunction buildPending(\n batch: ImportBatch,\n selected: SessionCandidate[],\n rejected: SessionCandidate[],\n importedSources: SourceFileRef[],\n): PendingState {\n const pending: PendingState = {\n rawRecords: [],\n projects: [],\n sessions: [],\n events: [],\n messages: [],\n blocks: [],\n toolCalls: [],\n toolResults: [],\n searchDocs: [],\n objects: createPendingObjects(),\n }\n\n const candidateSourceIds = new Set([...selected, ...rejected].map((candidate) => candidate.sourceFile.sourceFileId))\n for (const sourceFile of importedSources) {\n if (candidateSourceIds.has(sourceFile.sourceFileId)) continue\n const payload = { path: sourceFile.path, kind: sourceFile.kind }\n const objectId = stageJson(pending.objects, payload)\n pending.rawRecords.push({\n raw_record_id: makeRawRecordId(sourceFile.sourceFileId, 0, objectId),\n source_file_id: sourceFile.sourceFileId,\n ordinal: 0,\n line_no: null,\n json_pointer: '',\n native_id: null,\n raw_object_id: objectId,\n decoded_json_object_id: objectId,\n parser_status: 'partial',\n confidence: 'high',\n import_batch_id: batch.batch_id,\n record_kind: sourceFile.kind === 'jsonl' ? 'jsonl_line' : 'json_pointer',\n })\n }\n\n for (const candidate of selected) {\n stageCandidate(batch, candidate, pending)\n }\n for (const candidate of rejected) {\n stageRejectedCandidate(batch, candidate, pending)\n }\n buildSearchDocs(pending)\n return pending\n}\n\nfunction stageRejectedCandidate(batch: ImportBatch, candidate: SessionCandidate, pending: PendingState): void {\n const payloadId = stageJson(pending.objects, candidate.session.rawPayload)\n pending.rawRecords.push({\n raw_record_id: makeRawRecordId(candidate.sourceFile.sourceFileId, 0, payloadId),\n source_file_id: candidate.sourceFile.sourceFileId,\n ordinal: 0,\n line_no: null,\n json_pointer: candidate.source === 'sqlite' ? `$.sessions.${candidate.session.sourceSessionId}` : '$.candidate',\n native_id: candidate.session.sourceSessionId,\n raw_object_id: payloadId,\n decoded_json_object_id: payloadId,\n parser_status: 'partial',\n confidence: 'high',\n import_batch_id: batch.batch_id,\n record_kind: candidate.source === 'sqlite' ? 'sqlite_row' : 'json_pointer',\n })\n}\n\nfunction stageCandidate(batch: ImportBatch, candidate: SessionCandidate, pending: PendingState): void {\n const sessionPk = makeSessionId('hermes', candidate.session.sourceSessionId)\n const sessionPayloadId = stageJson(pending.objects, candidate.session.rawPayload)\n const sessionRawId = makeRawRecordId(candidate.sourceFile.sourceFileId, 0, sessionPayloadId)\n pending.rawRecords.push({\n raw_record_id: sessionRawId,\n source_file_id: candidate.sourceFile.sourceFileId,\n ordinal: 0,\n line_no: null,\n json_pointer: candidate.source === 'sqlite' ? '$.sessions' : '',\n native_id: candidate.session.sourceSessionId,\n raw_object_id: sessionPayloadId,\n decoded_json_object_id: sessionPayloadId,\n parser_status: 'ok',\n confidence: 'high',\n import_batch_id: batch.batch_id,\n record_kind: candidate.source === 'sqlite' ? 'sqlite_row' : 'json_pointer',\n })\n\n const projectId = candidate.session.source ? makeProjectId('hermes', candidate.session.source) : null\n if (candidate.session.source && projectId) {\n pending.projects.push({\n project_id: projectId,\n source_project_id: candidate.session.source,\n display_name: candidate.session.source,\n })\n }\n\n const models = candidate.messages.map((message) => message.model).filter((model): model is string => Boolean(model))\n pending.sessions.push({\n session_id: sessionPk,\n source_session_id: candidate.session.sourceSessionId,\n project_id: projectId,\n parent_session_id: candidate.session.parentSessionId\n ? makeSessionId('hermes', candidate.session.parentSessionId)\n : null,\n is_subagent: candidate.session.parentSessionId ? 1 : 0,\n title: candidate.session.title,\n start_ts: candidate.session.startTs,\n end_ts: candidate.session.endTs,\n model_first: candidate.session.model ?? models[0] ?? null,\n model_last: models.at(-1) ?? candidate.session.model ?? null,\n status: normalizeSessionStatus(candidate.session.status),\n raw_record_id: sessionRawId,\n })\n\n if (candidate.session.systemPrompt) {\n const rawRecordId = sessionRawId\n const messageId = makeMessageId(sessionPk, 0, 'system_prompt')\n pending.messages.push({\n message_id: messageId,\n session_id: sessionPk,\n event_id: null,\n source_message_id: 'system_prompt',\n role: 'system_prompt',\n model: null,\n timestamp: candidate.session.startTs,\n ordinal: 0,\n status: null,\n raw_record_id: rawRecordId,\n })\n pushTextBlock(pending, sessionPk, messageId, null, 0, 'text', candidate.session.systemPrompt, rawRecordId)\n }\n\n const toolCallsBySourceId = new Map<string, PendingToolCall>()\n for (const message of candidate.messages) {\n stageMessage(candidate, sessionPk, message, batch.batch_id, pending, toolCallsBySourceId)\n }\n}\n\nfunction stageMessage(\n candidate: SessionCandidate,\n sessionPk: string,\n message: NormalizedMessage,\n batchId: string,\n pending: PendingState,\n toolCallsBySourceId: Map<string, PendingToolCall>,\n): void {\n const payloadId = stageJson(pending.objects, message.rawPayload)\n const rawRecordId = makeRawRecordId(candidate.sourceFile.sourceFileId, message.ordinal, payloadId)\n pending.rawRecords.push({\n raw_record_id: rawRecordId,\n source_file_id: candidate.sourceFile.sourceFileId,\n ordinal: message.ordinal,\n line_no: message.lineNo,\n json_pointer: candidate.source === 'json' ? `/messages/${message.ordinal - 1}` : null,\n native_id: message.sourceMessageId,\n raw_object_id: payloadId,\n decoded_json_object_id: payloadId,\n parser_status: 'ok',\n confidence: 'high',\n import_batch_id: batchId,\n record_kind:\n candidate.source === 'sqlite' ? 'sqlite_row' : candidate.source === 'jsonl' ? 'jsonl_line' : 'json_pointer',\n })\n\n if (message.role === 'session_meta') {\n pending.events.push({\n event_id: makeEventId(sessionPk, message.ordinal, 'session_meta'),\n session_id: sessionPk,\n ordinal: message.ordinal,\n source_event_id: message.sourceMessageId,\n event_type: 'system_operational',\n source_type: 'session_meta',\n subtype: null,\n timestamp: message.timestamp,\n actor: 'system',\n payload_object_id: payloadId,\n raw_record_id: rawRecordId,\n confidence: 'high',\n })\n return\n }\n\n const role = mapRole(message.role)\n const eventId = makeEventId(sessionPk, message.ordinal, 'message')\n const messageId = makeMessageId(sessionPk, message.ordinal, message.sourceMessageId)\n pending.events.push({\n event_id: eventId,\n session_id: sessionPk,\n ordinal: message.ordinal,\n source_event_id: message.sourceMessageId,\n event_type: 'message',\n source_type: message.role,\n subtype: null,\n timestamp: message.timestamp,\n actor: role,\n payload_object_id: payloadId,\n raw_record_id: rawRecordId,\n confidence: 'high',\n })\n pending.messages.push({\n message_id: messageId,\n session_id: sessionPk,\n event_id: eventId,\n source_message_id: message.sourceMessageId,\n role,\n model: role === 'assistant' ? message.model : null,\n timestamp: message.timestamp,\n ordinal: message.ordinal,\n status: message.finishReason,\n raw_record_id: rawRecordId,\n })\n\n const text = renderContentText(message.content)\n pushTextBlock(pending, sessionPk, messageId, eventId, 0, 'text', text, rawRecordId, 'default', message.tokenCount)\n pushHiddenBlock(pending, sessionPk, messageId, eventId, message, rawRecordId)\n\n for (const [index, call] of parseToolCalls(message.toolCalls).entries()) {\n const sourceCallId = getToolCallSourceId(call, `${messageId}:${index}`)\n const toolName = getToolName(call, message.toolName)\n const args = getToolArgs(call)\n const toolCallId = makeToolCallId(sessionPk, sourceCallId)\n const pendingCall: PendingToolCall = {\n tool_call_id: toolCallId,\n session_id: sessionPk,\n message_id: messageId,\n event_id: eventId,\n source_call_id: sourceCallId,\n tool_name: toolName,\n canonical_tool_type: canonicalToolType(toolName),\n args_object_id: args ? stageJson(pending.objects, args) : null,\n command: stringField(args, 'command'),\n path: stringField(args, 'path') ?? stringField(args, 'file_path'),\n query: stringField(args, 'query'),\n timestamp_start: message.timestamp,\n status: normalizeToolCallStatus('hermes', message.finishReason),\n raw_record_id: rawRecordId,\n }\n toolCallsBySourceId.set(sourceCallId, pendingCall)\n pending.toolCalls.push(pendingCall)\n }\n\n if (role === 'tool' && message.toolCallId) {\n const sourceCallId = message.toolCallId\n let pendingCall = toolCallsBySourceId.get(sourceCallId)\n if (!pendingCall) {\n pendingCall = {\n tool_call_id: makeToolCallId(sessionPk, sourceCallId),\n session_id: sessionPk,\n message_id: null,\n event_id: null,\n source_call_id: sourceCallId,\n tool_name: message.toolName ?? 'unknown',\n canonical_tool_type: canonicalToolType(message.toolName ?? 'unknown'),\n args_object_id: null,\n command: null,\n path: null,\n query: null,\n timestamp_start: message.timestamp,\n status: 'unknown',\n raw_record_id: rawRecordId,\n }\n toolCallsBySourceId.set(sourceCallId, pendingCall)\n pending.toolCalls.push(pendingCall)\n }\n const outputObjectId = text.length > PREVIEW_MAX ? stageText(pending.objects, text) : null\n const status = normalizeToolResultStatus(message, text)\n if (status === 'error' || pendingCall.status === 'unknown' || pendingCall.status == null) {\n pendingCall.status = status\n }\n pending.toolResults.push({\n tool_result_id: makeToolResultId(sessionPk, sourceCallId),\n tool_call_id: pendingCall.tool_call_id,\n session_id: sessionPk,\n message_id: messageId,\n event_id: eventId,\n source_call_id: sourceCallId,\n status,\n is_error: status === 'error' ? 1 : 0,\n output_object_id: outputObjectId,\n preview: text.slice(0, PREVIEW_MAX) || null,\n raw_record_id: rawRecordId,\n })\n }\n}\n\nfunction pushTextBlock(\n pending: PendingState,\n sessionId: string,\n messageId: string | null,\n eventId: string | null,\n ordinal: number,\n blockType: string,\n text: string,\n rawRecordId: string,\n visibility: 'default' | 'hidden_by_default' | 'audit_only' = 'default',\n tokenCount: number | null = null,\n): void {\n if (!text) return\n const objectId = text.length > PREVIEW_MAX ? stageText(pending.objects, text) : null\n pending.blocks.push({\n block_id: blockId(messageId ?? eventId ?? rawRecordId, ordinal),\n session_id: sessionId,\n message_id: messageId,\n event_id: eventId,\n ordinal,\n block_type: blockType,\n text_object_id: objectId,\n text_inline: text.slice(0, PREVIEW_MAX),\n token_count: tokenCount,\n visibility,\n raw_record_id: rawRecordId,\n })\n}\n\nfunction pushHiddenBlock(\n pending: PendingState,\n sessionId: string,\n messageId: string,\n eventId: string,\n message: NormalizedMessage,\n rawRecordId: string,\n): void {\n const hidden = [\n ['reasoning', message.reasoning],\n ['reasoning_content', message.reasoningContent],\n ['reasoning_details', message.reasoningDetails],\n ['codex_reasoning_items', message.codexReasoningItems],\n ['codex_message_items', message.codexMessageItems],\n ] as const\n let offset = HIDDEN_BLOCK_ORDINAL_BASE\n for (const [kind, value] of hidden) {\n const text = renderContentText(value)\n if (!text) continue\n pushTextBlock(pending, sessionId, messageId, eventId, offset++, kind, text, rawRecordId, 'hidden_by_default')\n }\n}\n\nfunction buildSearchDocs(pending: PendingState): void {\n const projectIdBySession = new Map(pending.sessions.map((session) => [session.session_id, session.project_id]))\n for (const message of pending.messages) {\n const text = pending.blocks\n .filter((block) => block.message_id === message.message_id && block.visibility === 'default')\n .map((block) => block.text_inline ?? '')\n .join('\\n')\n .trim()\n if (!text) continue\n pending.searchDocs.push({\n doc_id: `msg:${message.message_id}`,\n entity_type: 'message',\n entity_id: message.message_id,\n session_id: message.session_id,\n project_id: projectIdBySession.get(message.session_id) ?? null,\n timestamp: message.timestamp,\n role: message.role,\n tool_name: null,\n canonical_tool_type: null,\n field_kind: message.role === 'user' ? 'user_prompt' : message.role === 'tool' ? 'tool_result' : 'assistant_text',\n text,\n })\n }\n for (const call of pending.toolCalls) {\n const text = [call.tool_name, call.command, call.path, call.query].filter(Boolean).join('\\n')\n if (!text) continue\n pending.searchDocs.push({\n doc_id: `tc:${call.tool_call_id}`,\n entity_type: 'tool_call',\n entity_id: call.tool_call_id,\n session_id: call.session_id,\n project_id: projectIdBySession.get(call.session_id) ?? null,\n timestamp: call.timestamp_start,\n role: null,\n tool_name: call.tool_name,\n canonical_tool_type: call.canonical_tool_type,\n field_kind: call.command ? 'command' : 'tool_call',\n text,\n })\n }\n for (const result of pending.toolResults) {\n if (!result.preview) continue\n pending.searchDocs.push({\n doc_id: `tr:${result.tool_result_id}`,\n entity_type: 'tool_result',\n entity_id: result.tool_result_id,\n session_id: result.session_id,\n project_id: projectIdBySession.get(result.session_id) ?? null,\n timestamp: null,\n role: 'tool',\n tool_name: null,\n canonical_tool_type: null,\n field_kind: result.is_error ? 'error' : 'tool_result',\n text: result.preview,\n })\n }\n}\n\nfunction flushPending(bundle: Bundle, pending: PendingState): void {\n const insertRaw = prepare(\n bundle.db,\n `INSERT OR IGNORE INTO raw_records (\n raw_record_id, source_file_id, source_tool, record_kind, ordinal,\n line_no, json_pointer, native_id, raw_object_id, decoded_json_object_id,\n parser_status, confidence, import_batch_id\n ) VALUES (?, ?, 'hermes', ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,\n )\n for (const record of pending.rawRecords) {\n insertRaw.run(\n record.raw_record_id,\n record.source_file_id,\n record.record_kind,\n record.ordinal,\n record.line_no,\n record.json_pointer,\n record.native_id,\n record.raw_object_id,\n record.decoded_json_object_id,\n record.parser_status,\n record.confidence,\n record.import_batch_id,\n )\n }\n\n const existingSession = prepare<[string], { found: number }>(\n bundle.db,\n `SELECT 1 AS found FROM sessions WHERE session_id = ? LIMIT 1`,\n )\n for (const session of pending.sessions) {\n if (existingSession.get(session.session_id)) {\n deleteSessionProjection(bundle, session.session_id)\n }\n }\n\n const insertProject = prepare(\n bundle.db,\n `INSERT OR IGNORE INTO projects (\n project_id, canonical_path, path_hash, source_tool, source_project_id,\n display_name, created_at\n ) VALUES (?, NULL, NULL, 'hermes', ?, ?, ?)`,\n )\n for (const project of pending.projects) {\n insertProject.run(project.project_id, project.source_project_id, project.display_name, new Date().toISOString())\n }\n\n const insertSession = prepare(\n bundle.db,\n `INSERT OR REPLACE INTO sessions (\n session_id, source_tool, source_session_id, project_id, parent_session_id,\n is_subagent, agent_role, agent_nickname, title, summary,\n start_ts, end_ts, cwd_initial, git_branch_initial,\n model_first, model_last, status, timeline_confidence, raw_record_id\n ) VALUES (?, 'hermes', ?, ?, ?, ?, NULL, NULL, ?, NULL, ?, ?, NULL, NULL, ?, ?, ?, 'high', ?)`,\n )\n for (const session of pending.sessions) {\n insertSession.run(\n session.session_id,\n session.source_session_id,\n session.project_id,\n session.parent_session_id,\n session.is_subagent,\n session.title,\n session.start_ts,\n session.end_ts,\n session.model_first,\n session.model_last,\n session.status,\n session.raw_record_id,\n )\n }\n\n const insertEvent = prepare(\n bundle.db,\n `INSERT OR REPLACE INTO events (\n event_id, session_id, turn_id, source_event_id, event_type, source_type,\n subtype, timestamp, ordinal, actor, payload_object_id, raw_record_id,\n confidence, is_derived\n ) VALUES (?, ?, NULL, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 0)`,\n )\n for (const event of pending.events) {\n insertEvent.run(\n event.event_id,\n event.session_id,\n event.source_event_id,\n event.event_type,\n event.source_type,\n event.subtype,\n event.timestamp,\n event.ordinal,\n event.actor,\n event.payload_object_id,\n event.raw_record_id,\n event.confidence,\n )\n }\n\n const insertMessage = prepare(\n bundle.db,\n `INSERT OR REPLACE INTO messages (\n message_id, session_id, turn_id, event_id, source_message_id, role,\n author_name, model, timestamp, ordinal, parent_message_id, request_id,\n status, raw_record_id\n ) VALUES (?, ?, NULL, ?, ?, ?, NULL, ?, ?, ?, NULL, NULL, ?, ?)`,\n )\n for (const message of pending.messages) {\n insertMessage.run(\n message.message_id,\n message.session_id,\n message.event_id,\n message.source_message_id,\n message.role,\n message.model,\n message.timestamp,\n message.ordinal,\n message.status,\n message.raw_record_id,\n )\n }\n\n const insertBlock = prepare(\n bundle.db,\n `INSERT OR REPLACE INTO content_blocks (\n block_id, message_id, event_id, session_id, ordinal, block_type,\n text_object_id, text_inline, mime_type, token_count, is_error,\n is_redacted, visibility, raw_record_id\n ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, NULL, ?, 0, 0, ?, ?)`,\n )\n for (const block of pending.blocks) {\n insertBlock.run(\n block.block_id,\n block.message_id,\n block.event_id,\n block.session_id,\n block.ordinal,\n block.block_type,\n block.text_object_id,\n block.text_inline,\n block.token_count,\n block.visibility,\n block.raw_record_id,\n )\n }\n\n const insertCall = prepare(\n bundle.db,\n `INSERT OR REPLACE INTO tool_calls (\n tool_call_id, session_id, turn_id, message_id, event_id,\n source_call_id, tool_name, canonical_tool_type, args_object_id,\n command, cwd, path, query, timestamp_start, timestamp_end, status,\n raw_record_id\n ) VALUES (?, ?, NULL, ?, ?, ?, ?, ?, ?, ?, NULL, ?, ?, ?, NULL, ?, ?)`,\n )\n for (const call of pending.toolCalls) {\n insertCall.run(\n call.tool_call_id,\n call.session_id,\n call.message_id,\n call.event_id,\n call.source_call_id,\n call.tool_name,\n call.canonical_tool_type,\n call.args_object_id,\n call.command,\n call.path,\n call.query,\n call.timestamp_start,\n call.status,\n call.raw_record_id,\n )\n }\n\n const insertResult = prepare(\n bundle.db,\n `INSERT OR REPLACE INTO tool_results (\n tool_result_id, tool_call_id, session_id, message_id, event_id,\n source_call_id, status, is_error, exit_code, duration_ms,\n stdout_object_id, stderr_object_id, output_object_id, preview, raw_record_id\n ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, NULL, NULL, NULL, NULL, ?, ?, ?)`,\n )\n for (const result of pending.toolResults) {\n insertResult.run(\n result.tool_result_id,\n result.tool_call_id,\n result.session_id,\n result.message_id,\n result.event_id,\n result.source_call_id,\n result.status,\n result.is_error,\n result.output_object_id,\n result.preview,\n result.raw_record_id,\n )\n }\n\n const insertSearch = prepare(\n bundle.db,\n `INSERT OR REPLACE INTO search_docs (\n doc_id, entity_type, entity_id, session_id, project_id, timestamp,\n role, tool_name, canonical_tool_type, field_kind, text\n ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,\n )\n for (const doc of pending.searchDocs) {\n insertSearch.run(\n doc.doc_id,\n doc.entity_type,\n doc.entity_id,\n doc.session_id,\n doc.project_id,\n doc.timestamp,\n doc.role,\n doc.tool_name,\n doc.canonical_tool_type,\n doc.field_kind,\n doc.text,\n )\n }\n}\n\nfunction deleteSessionProjection(bundle: Bundle, sessionId: string): void {\n prepare<[string]>(bundle.db, `DELETE FROM search_docs WHERE session_id = ?`).run(sessionId)\n prepare<[string]>(bundle.db, `DELETE FROM tool_results WHERE session_id = ?`).run(sessionId)\n prepare<[string]>(bundle.db, `DELETE FROM tool_calls WHERE session_id = ?`).run(sessionId)\n prepare<[string]>(bundle.db, `DELETE FROM content_blocks WHERE session_id = ?`).run(sessionId)\n prepare<[string]>(bundle.db, `DELETE FROM messages WHERE session_id = ?`).run(sessionId)\n prepare<[string, string]>(\n bundle.db,\n `DELETE FROM edges WHERE (src_type = 'session' AND src_id = ?) OR (dst_type = 'session' AND dst_id = ?)`,\n ).run(sessionId, sessionId)\n prepare<[string]>(bundle.db, `DELETE FROM artifacts WHERE session_id = ?`).run(sessionId)\n prepare<[string]>(bundle.db, `DELETE FROM events WHERE session_id = ?`).run(sessionId)\n prepare<[string]>(bundle.db, `DELETE FROM turns WHERE session_id = ?`).run(sessionId)\n prepare<[string]>(bundle.db, `DELETE FROM sessions WHERE session_id = ?`).run(sessionId)\n}\n\nfunction unixToIso(value: number | null | undefined): string | null {\n if (value == null || !Number.isFinite(value)) return null\n return new Date(value * 1000).toISOString()\n}\n\nfunction coerceTimestamp(value: string | number | null | undefined): string | null {\n if (value == null) return null\n // Hermes currently stores numeric timestamps as unix seconds.\n if (typeof value === 'number') return unixToIso(value)\n const parsed = Date.parse(value)\n return Number.isFinite(parsed) ? new Date(parsed).toISOString() : null\n}\n\nfunction normalizeToolResultStatus(message: NormalizedMessage, text: string): ToolCallStatus {\n if (isToolError(message, text)) return 'error'\n const status = normalizeToolCallStatus('hermes', message.finishReason)\n return status === 'unknown' ? 'success' : status\n}\n\nfunction isToolError(message: NormalizedMessage, text: string): boolean {\n if (message.finishReason === 'error') return true\n if (hasErrorMarker(message.rawPayload)) return true\n if (hasErrorMarker(message.content)) return true\n return /^(error|tool_use_error|exception)[: ]/i.test(text.trim())\n}\n\nfunction hasErrorMarker(value: unknown): boolean {\n if (Array.isArray(value)) return value.some(hasErrorMarker)\n if (!isRecord(value)) return false\n if (value.is_error === true) return true\n if (typeof value.status === 'string' && value.status.toLowerCase() === 'error') return true\n if (typeof value.type === 'string' && value.type.toLowerCase() === 'tool_use_error') return true\n return false\n}\n\nfunction decodeMaybeJson(value: string | null): unknown {\n if (value == null) return null\n const trimmed = value.trim()\n if (!trimmed) return value\n if (!trimmed.startsWith('{') && !trimmed.startsWith('[')) return value\n try {\n return JSON.parse(trimmed) as unknown\n } catch {\n return value\n }\n}\n\nfunction renderContentText(value: unknown): string {\n if (value == null) return ''\n if (typeof value === 'string') return value\n if (Array.isArray(value)) {\n return value\n .map((item) => {\n if (typeof item === 'string') return item\n if (isRecord(item)) {\n if (typeof item.text === 'string') return item.text\n if (typeof item.content === 'string') return item.content\n }\n return JSON.stringify(item)\n })\n .filter(Boolean)\n .join('\\n')\n }\n return JSON.stringify(value)\n}\n\nfunction mapRole(role: string): MessageRole {\n if (role === 'user' || role === 'assistant' || role === 'tool') return role\n if (role === 'system' || role === 'system_prompt') return 'system_prompt'\n if (role === 'developer') return 'developer'\n return 'operational'\n}\n\nfunction parseToolCalls(value: unknown): Record<string, unknown>[] {\n const decoded = typeof value === 'string' ? decodeMaybeJson(value) : value\n if (Array.isArray(decoded)) return decoded.filter(isRecord)\n if (isRecord(decoded)) return [decoded]\n return []\n}\n\nfunction getToolCallSourceId(call: Record<string, unknown>, fallback: string): string {\n return stringField(call, 'id') ?? stringField(call, 'call_id') ?? stringField(call, 'tool_call_id') ?? fallback\n}\n\nfunction getToolName(call: Record<string, unknown>, fallback: string | null): string {\n const fn = isRecord(call.function) ? call.function : null\n return stringField(fn, 'name') ?? stringField(call, 'name') ?? stringField(call, 'tool_name') ?? fallback ?? 'unknown'\n}\n\nfunction getToolArgs(call: Record<string, unknown>): Record<string, unknown> | null {\n const fn = isRecord(call.function) ? call.function : null\n const args = fn?.arguments ?? call.args ?? call.input\n if (isRecord(args)) return args\n if (typeof args === 'string') {\n try {\n const parsed = JSON.parse(args) as unknown\n return isRecord(parsed) ? parsed : { value: parsed }\n } catch {\n return { value: args }\n }\n }\n return null\n}\n\nfunction canonicalToolType(toolName: string): string {\n const lowered = toolName.toLowerCase()\n if (lowered.includes('shell') || lowered.includes('bash') || lowered.includes('terminal')) return 'shell'\n if (lowered.includes('read')) return 'read_file'\n if (lowered.includes('write')) return 'write_file'\n if (lowered.includes('edit') || lowered.includes('patch')) return 'edit_file'\n if (lowered.includes('search') || lowered.includes('grep') || lowered.includes('glob')) return 'search_file'\n if (lowered.includes('web')) return 'web_search'\n if (lowered.includes('mcp')) return 'mcp'\n if (lowered.includes('delegate') || lowered.includes('agent')) return 'subagent'\n return 'other'\n}\n\nfunction stringField(record: Record<string, unknown> | null, key: string): string | null {\n if (!record) return null\n const value = record[key]\n return typeof value === 'string' && value.length > 0 ? value : null\n}\n\nfunction firstString(values: Array<string | null>): string | null {\n return values.find((value): value is string => Boolean(value)) ?? null\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n}\n","import { access, readdir } from 'node:fs/promises'\nimport path from 'node:path'\n\n/** Hermes source files discovered from a sessions directory. */\nexport interface HermesSources {\n /** Root sessions directory passed to the importer. */\n sessionsDir: string\n /** Sibling `state.db`, when present. */\n stateDbPath: string | null\n /** Top-level `sessions.json` index, when present. */\n indexPath: string | null\n /** Top-level legacy transcript JSONL files. */\n jsonlFiles: string[]\n /** Top-level CLI JSON session snapshots. */\n jsonFiles: string[]\n}\n\n/** Discover Hermes session storage under `root`, normally `~/.hermes/sessions`. */\nexport async function discoverHermesSources(root: string): Promise<HermesSources> {\n const sessionsDir = path.resolve(root)\n const stateDbCandidate = path.join(path.dirname(sessionsDir), 'state.db')\n const indexCandidate = path.join(sessionsDir, 'sessions.json')\n const entries = await readdirSafe(sessionsDir)\n\n const jsonlFiles: string[] = []\n const jsonFiles: string[] = []\n for (const entry of entries) {\n if (!entry.isFile()) continue\n const full = path.join(sessionsDir, entry.name)\n if (entry.name === 'sessions.json') continue\n if (entry.name.endsWith('.jsonl')) {\n jsonlFiles.push(full)\n continue\n }\n if (entry.name.startsWith('session_') && entry.name.endsWith('.json')) {\n jsonFiles.push(full)\n }\n }\n\n return {\n sessionsDir,\n stateDbPath: (await exists(stateDbCandidate)) ? stateDbCandidate : null,\n indexPath: (await exists(indexCandidate)) ? indexCandidate : null,\n jsonlFiles: jsonlFiles.sort(),\n jsonFiles: jsonFiles.sort(),\n }\n}\n\nasync function exists(filePath: string): Promise<boolean> {\n try {\n await access(filePath)\n return true\n } catch {\n return false\n }\n}\n\nasync function readdirSafe(dir: string): Promise<import('node:fs').Dirent[]> {\n try {\n return await readdir(dir, { withFileTypes: true })\n } catch {\n return []\n }\n}\n","import { mkdir, rm, writeFile } from 'node:fs/promises'\nimport path from 'node:path'\nimport { DuckDBConnection } from '@duckdb/node-api'\nimport { closeBundle, openBundle } from '../../core/bundle.js'\nimport { getErrorMessage } from '../../core/errors.js'\n\n/** Canonical SQLite tables exported as one Parquet file per table. */\nexport const PARQUET_TABLES = [\n 'objects',\n 'source_files',\n 'import_batches',\n 'raw_records',\n 'import_errors',\n 'uncertainties',\n 'projects',\n 'sessions',\n 'turns',\n 'events',\n 'messages',\n 'content_blocks',\n 'tool_calls',\n 'tool_results',\n 'artifacts',\n 'edges',\n 'search_docs',\n] as const\n\n/** Derived analytics views recreated in DuckDB alongside exported tables. */\nexport const ANALYTICS_VIEWS = [\n 'session_facts',\n 'tool_usage_facts',\n 'error_facts',\n 'model_usage',\n 'project_activity',\n] as const\n\n/** Exportable canonical table name. */\nexport type ParquetTable = (typeof PARQUET_TABLES)[number]\n\n/** DuckDB analytics view name exposed over exported Parquet data. */\nexport type AnalyticsView = (typeof ANALYTICS_VIEWS)[number]\n\n/** Options for exporting a bundle's canonical tables to Parquet. */\nexport interface ParquetExportOptions {\n /** Bundle root to open and export. */\n bundlePath: string\n /** Output directory; defaults to the bundle's parquet directory. */\n outDir?: string\n}\n\n/** Result metadata for a Parquet export operation. */\nexport interface ParquetExportResult {\n /** Directory containing generated Parquet files. */\n outDir: string\n /** Path to the generated manifest JSON. */\n manifestPath: string\n /** Absolute Parquet file path by canonical table. */\n files: Record<ParquetTable, string>\n /** Exported row count by canonical table. */\n counts: Record<ParquetTable, number>\n}\n\n/** Options for querying exported Parquet files through DuckDB. */\nexport interface DuckDbQueryOptions {\n /** Directory containing exported Parquet files. */\n parquetDir: string\n /** SQL query to run after table and analytics views are created. */\n sql: string\n}\n\n/** Column-oriented query result shape returned by analytics services. */\nexport interface DuckDbQueryResult {\n /** Result column names in DuckDB output order. */\n columns: string[]\n /** Result rows as plain JSON-compatible objects. */\n rows: Record<string, unknown>[]\n}\n\n/** Immutable bundle metadata captured before DuckDB reads from SQLite. */\ninterface BundleSnapshot {\n dbPath: string\n schemaVersion: number\n parserVersion: string\n defaultOutDir: string\n counts: Record<ParquetTable, number>\n}\n\n/** Exports canonical bundle tables to Parquet and writes a manifest. */\nexport async function exportBundleParquet(options: ParquetExportOptions): Promise<ParquetExportResult> {\n const snapshot = await openBundleSnapshot(options.bundlePath)\n const outDir = path.resolve(options.outDir ?? snapshot.defaultOutDir)\n await mkdir(outDir, { recursive: true })\n\n const files = Object.fromEntries(\n PARQUET_TABLES.map((table) => [table, path.join(outDir, `${table}.parquet`)]),\n ) as Record<ParquetTable, string>\n const manifestPath = path.join(outDir, 'manifest.json')\n\n for (const file of [...Object.values(files), manifestPath]) {\n await rm(file, { force: true })\n }\n\n const connection = await createDuckDbConnection()\n try {\n await attachSqlite(connection, snapshot.dbPath)\n for (const table of PARQUET_TABLES) {\n // Tuned via bench/bench-parquet.ts: zstd-1 matches snappy on write\n // time but halves file size, and ROW_GROUP_SIZE=100k cuts ~20% off\n // total export time for prosa's table widths. See\n // docs/roadmap/parquet-export-perf.md.\n await connection.run(\n `COPY (SELECT * FROM prosa.${quoteIdentifier(table)}) TO ${sqlString(files[table])} (FORMAT parquet, COMPRESSION zstd, COMPRESSION_LEVEL 1, ROW_GROUP_SIZE 100000)`,\n )\n }\n } finally {\n connection.closeSync()\n }\n\n const manifest = {\n exported_at: new Date().toISOString(),\n source_db: snapshot.dbPath,\n schema_version: snapshot.schemaVersion,\n parser_version: snapshot.parserVersion,\n tables: Object.fromEntries(\n PARQUET_TABLES.map((table) => [\n table,\n {\n file: path.basename(files[table]),\n rows: snapshot.counts[table],\n },\n ]),\n ),\n }\n await writeFile(manifestPath, `${JSON.stringify(manifest, null, 2)}\\n`, 'utf8')\n\n return { outDir, manifestPath, files, counts: snapshot.counts }\n}\n\n/** Queries Parquet exports after creating table and analytics views in DuckDB. */\nexport async function queryDuckDbParquet(options: DuckDbQueryOptions): Promise<DuckDbQueryResult> {\n const parquetDir = path.resolve(options.parquetDir)\n const connection = await createDuckDbConnection()\n try {\n for (const table of PARQUET_TABLES) {\n await connection.run(\n `CREATE OR REPLACE VIEW ${quoteIdentifier(table)} AS SELECT * FROM read_parquet(${sqlString(\n path.join(parquetDir, `${table}.parquet`),\n )})`,\n )\n }\n await createAnalyticsViews(connection)\n\n const reader = await connection.runAndReadAll(options.sql)\n return {\n columns: reader.deduplicatedColumnNames(),\n rows: reader.getRowObjectsJson() as Record<string, unknown>[],\n }\n } catch (error) {\n if (isMissingParquetError(error)) {\n throw new Error(`Parquet export not found in ${parquetDir}; run \\`prosa export parquet --store <path>\\` first`)\n }\n throw error\n } finally {\n connection.closeSync()\n }\n}\n\n/** Opens an in-process DuckDB connection for export or query work. */\nasync function createDuckDbConnection(): Promise<DuckDBConnection> {\n return DuckDBConnection.create()\n}\n\n/** Loads DuckDB's sqlite extension and attaches the source bundle database. */\nasync function attachSqlite(connection: DuckDBConnection, dbPath: string): Promise<void> {\n try {\n await connection.run('INSTALL sqlite')\n await connection.run('LOAD sqlite')\n await connection.run(`ATTACH ${sqlString(dbPath)} AS prosa (TYPE sqlite)`)\n } catch (error) {\n throw new Error(`DuckDB could not attach prosa.sqlite via the sqlite extension: ${getErrorMessage(error)}`)\n }\n}\n\n/** Recreates analytics views in DuckDB with semantics matching SQLite views. */\nasync function createAnalyticsViews(connection: DuckDBConnection): Promise<void> {\n await connection.run(`\n CREATE OR REPLACE VIEW session_facts AS\n WITH turn_counts AS (\n SELECT session_id, count(*) AS turn_count\n FROM turns\n GROUP BY session_id\n ),\n message_counts AS (\n SELECT session_id,\n count(*) AS message_count,\n sum(CASE WHEN role = 'user' THEN 1 ELSE 0 END) AS user_message_count,\n sum(CASE WHEN role = 'assistant' THEN 1 ELSE 0 END) AS assistant_message_count\n FROM messages\n GROUP BY session_id\n ),\n tool_call_counts AS (\n SELECT session_id,\n count(*) AS tool_call_count,\n sum(CASE WHEN status = 'error' THEN 1 ELSE 0 END) AS tool_call_error_count\n FROM tool_calls\n GROUP BY session_id\n ),\n tool_result_counts AS (\n SELECT session_id,\n count(*) AS tool_result_count,\n sum(CASE WHEN is_error = 1 OR (exit_code IS NOT NULL AND exit_code <> 0)\n THEN 1 ELSE 0 END) AS tool_result_error_count,\n sum(COALESCE(duration_ms, 0)) AS tool_duration_ms\n FROM tool_results\n GROUP BY session_id\n ),\n search_doc_counts AS (\n SELECT session_id, count(*) AS search_doc_count\n FROM search_docs\n WHERE session_id IS NOT NULL\n GROUP BY session_id\n )\n SELECT s.session_id,\n s.source_tool,\n s.source_session_id,\n s.project_id,\n p.display_name AS project_name,\n p.canonical_path AS project_path,\n s.parent_session_id,\n s.is_subagent,\n s.agent_role,\n s.agent_nickname,\n s.title,\n s.start_ts,\n s.end_ts,\n CASE\n WHEN s.start_ts IS NOT NULL AND s.end_ts IS NOT NULL\n THEN date_diff('millisecond', TRY_CAST(s.start_ts AS TIMESTAMP),\n TRY_CAST(s.end_ts AS TIMESTAMP)) / 1000.0\n ELSE NULL\n END AS duration_seconds,\n s.cwd_initial,\n s.git_branch_initial,\n s.model_first,\n s.model_last,\n s.status,\n s.timeline_confidence,\n sf.path AS source_file_path,\n COALESCE(tc.turn_count, 0) AS turn_count,\n COALESCE(mc.message_count, 0) AS message_count,\n COALESCE(mc.user_message_count, 0) AS user_message_count,\n COALESCE(mc.assistant_message_count, 0) AS assistant_message_count,\n COALESCE(tcc.tool_call_count, 0) AS tool_call_count,\n COALESCE(trc.tool_result_count, 0) AS tool_result_count,\n COALESCE(tcc.tool_call_error_count, 0)\n + COALESCE(trc.tool_result_error_count, 0) AS tool_error_count,\n COALESCE(trc.tool_duration_ms, 0) AS tool_duration_ms,\n COALESCE(sdc.search_doc_count, 0) AS search_doc_count\n FROM sessions s\n LEFT JOIN projects p ON p.project_id = s.project_id\n LEFT JOIN raw_records rr ON rr.raw_record_id = s.raw_record_id\n LEFT JOIN source_files sf ON sf.source_file_id = rr.source_file_id\n LEFT JOIN turn_counts tc ON tc.session_id = s.session_id\n LEFT JOIN message_counts mc ON mc.session_id = s.session_id\n LEFT JOIN tool_call_counts tcc ON tcc.session_id = s.session_id\n LEFT JOIN tool_result_counts trc ON trc.session_id = s.session_id\n LEFT JOIN search_doc_counts sdc ON sdc.session_id = s.session_id\n `)\n\n await connection.run(`\n CREATE OR REPLACE VIEW tool_usage_facts AS\n WITH result_rollup AS (\n SELECT tool_call_id,\n session_id,\n count(*) AS tool_result_count,\n max(status) AS result_status,\n max(is_error) AS is_error,\n min(exit_code) AS exit_code,\n sum(COALESCE(duration_ms, 0)) AS duration_ms,\n max(preview) AS preview\n FROM tool_results\n GROUP BY tool_call_id, session_id\n )\n SELECT tc.tool_call_id,\n tc.session_id,\n s.source_tool,\n s.source_session_id,\n s.project_id,\n p.display_name AS project_name,\n p.canonical_path AS project_path,\n tc.turn_id,\n tc.message_id,\n tc.event_id,\n tc.source_call_id,\n tc.tool_name,\n tc.canonical_tool_type,\n tc.command,\n tc.cwd,\n tc.path,\n tc.query,\n tc.timestamp_start,\n tc.timestamp_end,\n CASE\n WHEN tc.timestamp_start IS NOT NULL AND tc.timestamp_end IS NOT NULL\n THEN date_diff('millisecond', TRY_CAST(tc.timestamp_start AS TIMESTAMP),\n TRY_CAST(tc.timestamp_end AS TIMESTAMP)) / 1000.0\n ELSE NULL\n END AS call_duration_seconds,\n tc.status AS call_status,\n rr.result_status,\n COALESCE(rr.is_error, 0) AS is_error,\n rr.exit_code,\n rr.duration_ms AS result_duration_ms,\n COALESCE(rr.tool_result_count, 0) AS tool_result_count,\n rr.preview,\n tc.raw_record_id\n FROM tool_calls tc\n LEFT JOIN sessions s ON s.session_id = tc.session_id\n LEFT JOIN projects p ON p.project_id = s.project_id\n LEFT JOIN result_rollup rr ON rr.tool_call_id = tc.tool_call_id\n `)\n\n await connection.run(`\n CREATE OR REPLACE VIEW error_facts AS\n SELECT 'tool_result:' || tr.tool_result_id AS error_id,\n 'tool_result' AS error_category,\n s.source_tool,\n s.project_id,\n p.display_name AS project_name,\n tr.session_id,\n COALESCE(tc.timestamp_end, tc.timestamp_start) AS timestamp,\n tc.tool_name,\n tc.canonical_tool_type,\n COALESCE(tr.status, tc.status) AS status,\n tr.exit_code,\n NULL AS message,\n tr.preview,\n NULL AS entity_type,\n NULL AS entity_id,\n tr.raw_record_id\n FROM tool_results tr\n LEFT JOIN tool_calls tc ON tc.tool_call_id = tr.tool_call_id\n LEFT JOIN sessions s ON s.session_id = tr.session_id\n LEFT JOIN projects p ON p.project_id = s.project_id\n WHERE tr.is_error = 1 OR (tr.exit_code IS NOT NULL AND tr.exit_code <> 0)\n UNION ALL\n SELECT 'import_error:' || CAST(ie.error_id AS VARCHAR) AS error_id,\n 'import_error' AS error_category,\n COALESCE(rr.source_tool, ib.source_tool) AS source_tool,\n NULL AS project_id,\n NULL AS project_name,\n NULL AS session_id,\n ie.occurred_at AS timestamp,\n NULL AS tool_name,\n NULL AS canonical_tool_type,\n ie.kind AS status,\n NULL AS exit_code,\n ie.message,\n NULL AS preview,\n NULL AS entity_type,\n NULL AS entity_id,\n ie.raw_record_id\n FROM import_errors ie\n LEFT JOIN import_batches ib ON ib.batch_id = ie.batch_id\n LEFT JOIN raw_records rr ON rr.raw_record_id = ie.raw_record_id\n UNION ALL\n SELECT 'uncertainty:' || CAST(u.uncertainty_id AS VARCHAR) AS error_id,\n 'uncertainty' AS error_category,\n NULL AS source_tool,\n NULL AS project_id,\n NULL AS project_name,\n CASE WHEN u.entity_type = 'session' THEN u.entity_id ELSE NULL END AS session_id,\n NULL AS timestamp,\n NULL AS tool_name,\n NULL AS canonical_tool_type,\n u.reason AS status,\n NULL AS exit_code,\n u.reason AS message,\n NULL AS preview,\n u.entity_type,\n u.entity_id,\n NULL AS raw_record_id\n FROM uncertainties u\n `)\n\n await connection.run(`\n CREATE OR REPLACE VIEW model_usage AS\n WITH model_events AS (\n SELECT s.source_tool,\n s.project_id,\n p.display_name AS project_name,\n p.canonical_path AS project_path,\n s.session_id,\n NULL AS turn_id,\n s.model_first AS model,\n s.start_ts AS timestamp,\n 'session_first' AS observation_type\n FROM sessions s\n LEFT JOIN projects p ON p.project_id = s.project_id\n WHERE s.model_first IS NOT NULL\n UNION ALL\n SELECT s.source_tool, s.project_id, p.display_name, p.canonical_path,\n s.session_id, NULL AS turn_id, s.model_last AS model, s.end_ts AS timestamp,\n 'session_last' AS observation_type\n FROM sessions s\n LEFT JOIN projects p ON p.project_id = s.project_id\n WHERE s.model_last IS NOT NULL\n UNION ALL\n SELECT s.source_tool, s.project_id, p.display_name, p.canonical_path,\n t.session_id, t.turn_id, t.model, t.start_ts AS timestamp, 'turn' AS observation_type\n FROM turns t\n LEFT JOIN sessions s ON s.session_id = t.session_id\n LEFT JOIN projects p ON p.project_id = s.project_id\n WHERE t.model IS NOT NULL\n UNION ALL\n SELECT s.source_tool, s.project_id, p.display_name, p.canonical_path,\n m.session_id, m.turn_id, m.model, m.timestamp, 'message' AS observation_type\n FROM messages m\n LEFT JOIN sessions s ON s.session_id = m.session_id\n LEFT JOIN projects p ON p.project_id = s.project_id\n WHERE m.model IS NOT NULL\n )\n SELECT source_tool,\n project_id,\n project_name,\n project_path,\n model,\n count(DISTINCT session_id) AS session_count,\n count(DISTINCT turn_id) AS turn_count,\n count(*) AS observation_count,\n sum(CASE WHEN observation_type = 'message' THEN 1 ELSE 0 END) AS message_count,\n min(timestamp) AS first_seen_ts,\n max(timestamp) AS last_seen_ts\n FROM model_events\n GROUP BY source_tool, project_id, project_name, project_path, model\n `)\n\n await connection.run(`\n CREATE OR REPLACE VIEW project_activity AS\n SELECT s.source_tool,\n s.project_id,\n COALESCE(p.display_name, s.cwd_initial, '(unknown)') AS project_name,\n p.canonical_path AS project_path,\n min(s.start_ts) AS first_session_ts,\n max(COALESCE(s.end_ts, s.start_ts)) AS latest_session_ts,\n count(DISTINCT s.session_id) AS session_count,\n count(DISTINCT CASE WHEN s.timeline_confidence = 'low' THEN s.session_id END)\n AS low_confidence_session_count,\n count(DISTINCT t.turn_id) AS turn_count,\n count(DISTINCT m.message_id) AS message_count,\n count(DISTINCT tc.tool_call_id) AS tool_call_count,\n count(DISTINCT tr.tool_result_id) AS tool_result_count,\n count(DISTINCT CASE\n WHEN tr.is_error = 1 OR (tr.exit_code IS NOT NULL AND tr.exit_code <> 0)\n THEN tr.tool_result_id\n END) AS tool_error_count,\n count(DISTINCT sd.doc_id) AS search_doc_count\n FROM sessions s\n LEFT JOIN projects p ON p.project_id = s.project_id\n LEFT JOIN turns t ON t.session_id = s.session_id\n LEFT JOIN messages m ON m.session_id = s.session_id\n LEFT JOIN tool_calls tc ON tc.session_id = s.session_id\n LEFT JOIN tool_results tr ON tr.session_id = s.session_id\n LEFT JOIN search_docs sd ON sd.session_id = s.session_id\n GROUP BY s.source_tool, s.project_id, p.display_name, s.cwd_initial, p.canonical_path\n `)\n}\n\n/** Opens the bundle briefly to collect paths, manifest versions, and row counts. */\nasync function openBundleSnapshot(bundlePath: string): Promise<BundleSnapshot> {\n const bundle = await openBundle(bundlePath)\n try {\n const counts = Object.fromEntries(\n PARQUET_TABLES.map((table) => {\n const row = bundle.db.prepare<[], { n: number }>(`SELECT count(*) AS n FROM ${quoteIdentifier(table)}`).get()\n return [table, row?.n ?? 0]\n }),\n ) as Record<ParquetTable, number>\n\n return {\n dbPath: bundle.paths.db,\n schemaVersion: bundle.manifest.schema_version,\n parserVersion: bundle.manifest.parser_version,\n defaultOutDir: bundle.paths.parquet,\n counts,\n }\n } finally {\n closeBundle(bundle)\n }\n}\n\n/** Quotes a SQL identifier for fixed table and view names. */\nfunction quoteIdentifier(value: string): string {\n return `\"${value.replace(/\"/g, '\"\"')}\"`\n}\n\n/** Quotes a SQL string literal for DuckDB statements. */\nfunction sqlString(value: string): string {\n return `'${value.replace(/'/g, \"''\")}'`\n}\n\n/** Detects DuckDB read failures caused by absent Parquet files. */\nfunction isMissingParquetError(error: unknown): boolean {\n const message = getErrorMessage(error)\n return /No files found|does not exist|not found/i.test(message) && /\\.parquet/i.test(message)\n}\n","import type { Bundle } from '../core/bundle.js'\nimport { clampLimit } from '../core/limits.js'\nimport { type DuckDbQueryResult, queryDuckDbParquet } from './export/parquet.js'\n\n/** Stable report names exposed by CLI and MCP analytics surfaces. */\nexport const ANALYTICS_REPORTS = ['sessions', 'tools', 'errors', 'models', 'projects'] as const\n\n/** Analytics report identifier. */\nexport type AnalyticsReport = (typeof ANALYTICS_REPORTS)[number]\n\n/** SQL dialects supported by the analytics query builder. */\nexport type AnalyticsDialect = 'sqlite' | 'duckdb'\n\n/** Cross-report filters accepted by analytics read surfaces. */\nexport interface AnalyticsReportFilters {\n /** Source tool filter. */\n source?: string\n /** Inclusive lower time bound for report-specific timestamps. */\n since?: string\n /** Exclusive upper time bound for report-specific timestamps. */\n until?: string\n /** Maximum row count, clamped by service limits. */\n limit?: number\n /** Native tool name filter for tool/error reports. */\n toolName?: string\n /** Canonical tool category filter. */\n canonicalType?: string\n /** Restrict tool/error reports to failed operations. */\n errorsOnly?: boolean\n /** Error category filter. */\n category?: string\n /** Model name filter. */\n model?: string\n /** Project name filter. */\n project?: string\n /** Canonical session identifier filter. */\n sessionId?: string\n /** Source file path substring filter. */\n sourcePathSubstring?: string\n}\n\n/** Options for running an analytics report against exported Parquet files. */\nexport interface AnalyticsReportOptions {\n /** Directory containing exported Parquet tables. */\n parquetDir: string\n /** Report to run. */\n report: AnalyticsReport\n /** Optional report filters. */\n filters?: AnalyticsReportFilters\n}\n\n/** Options for running an analytics report directly against a SQLite bundle. */\nexport interface AnalyticsBundleReportOptions {\n /** Open bundle queried through SQLite analytics views. */\n bundle: Bundle\n /** Report to run. */\n report: AnalyticsReport\n /** Optional report filters. */\n filters?: AnalyticsReportFilters\n}\n\n/** Runs a fixed analytics report over DuckDB views backed by Parquet exports. */\nexport async function runAnalyticsReport(options: AnalyticsReportOptions): Promise<DuckDbQueryResult> {\n return queryDuckDbParquet({\n parquetDir: options.parquetDir,\n sql: buildAnalyticsSql(options.report, options.filters ?? {}, 'duckdb'),\n })\n}\n\n/** Runs the same fixed analytics reports against SQLite analytics views. */\nexport function runAnalyticsReportFromBundle(options: AnalyticsBundleReportOptions): DuckDbQueryResult {\n const sql = buildAnalyticsSql(options.report, options.filters ?? {}, 'sqlite')\n const stmt = options.bundle.db.prepare<unknown[], Record<string, unknown>>(sql)\n const rows = stmt.all()\n const columns = stmt.columns().map((column) => column.name)\n return { columns, rows }\n}\n\n/** Dispatches to the report-specific SQL template for the requested dialect. */\nfunction buildAnalyticsSql(\n report: AnalyticsReport,\n filters: AnalyticsReportFilters,\n dialect: AnalyticsDialect,\n): string {\n switch (report) {\n case 'sessions':\n return buildSessionsSql(filters, dialect)\n case 'tools':\n return buildToolsSql(filters, dialect)\n case 'errors':\n return buildErrorsSql(filters, dialect)\n case 'models':\n return buildModelsSql(filters, dialect)\n case 'projects':\n return buildProjectsSql(filters, dialect)\n }\n}\n\n/** Builds the session_facts report query with stable output columns. */\nfunction buildSessionsSql(filters: AnalyticsReportFilters, dialect: AnalyticsDialect): string {\n const where = buildWhere([\n sourceFilter(filters),\n timeFilter('start_ts', filters),\n projectFilter(filters, dialect),\n filters.sessionId ? `session_id = ${sqlString(filters.sessionId)}` : null,\n filters.sourcePathSubstring\n ? `source_file_path LIKE ${sqlString(`%${escapeLike(filters.sourcePathSubstring)}%`)} ESCAPE '\\\\'`\n : null,\n ])\n return `\n SELECT start_ts, source_tool, project_name, source_file_path, session_id,\n source_session_id, model_last, duration_seconds,\n message_count, tool_call_count, tool_result_count, tool_error_count,\n tool_duration_ms, timeline_confidence, title\n FROM session_facts\n ${where}\n ORDER BY start_ts DESC NULLS LAST\n LIMIT ${limit(filters)}\n `\n}\n\n/** Builds the tool_usage_facts aggregate query grouped by tool and project. */\nfunction buildToolsSql(filters: AnalyticsReportFilters, dialect: AnalyticsDialect): string {\n const where = buildWhere([\n sourceFilter(filters),\n timeFilter('timestamp_start', filters),\n projectFilter(filters, dialect),\n filters.toolName ? `tool_name = ${sqlString(filters.toolName)}` : null,\n filters.canonicalType ? `canonical_tool_type = ${sqlString(filters.canonicalType)}` : null,\n filters.errorsOnly ? `(is_error = 1 OR call_status = 'error')` : null,\n ])\n return `\n SELECT tool_name, canonical_tool_type, source_tool, project_name,\n count(*) AS call_count,\n sum(CASE WHEN is_error = 1 OR call_status = 'error' THEN 1 ELSE 0 END) AS error_count,\n round(avg(result_duration_ms), 3) AS avg_result_duration_ms,\n max(timestamp_start) AS latest_ts\n FROM tool_usage_facts\n ${where}\n GROUP BY tool_name, canonical_tool_type, source_tool, project_name\n ORDER BY call_count DESC, error_count DESC, tool_name ASC\n LIMIT ${limit(filters)}\n `\n}\n\n/** Builds the error_facts detail query for tool, import, and uncertainty errors. */\nfunction buildErrorsSql(filters: AnalyticsReportFilters, dialect: AnalyticsDialect): string {\n const where = buildWhere([\n sourceFilter(filters),\n timeFilter('timestamp', filters),\n projectFilter(filters, dialect),\n filters.toolName ? `tool_name = ${sqlString(filters.toolName)}` : null,\n filters.category ? `error_category = ${sqlString(filters.category)}` : null,\n ])\n return `\n SELECT timestamp, error_category, source_tool, project_name, session_id,\n tool_name, status, exit_code, message, preview\n FROM error_facts\n ${where}\n ORDER BY timestamp DESC NULLS LAST, error_id DESC\n LIMIT ${limit(filters)}\n `\n}\n\n/** Builds the model_usage report using range-overlap filtering semantics. */\nfunction buildModelsSql(filters: AnalyticsReportFilters, dialect: AnalyticsDialect): string {\n const where = buildWhere([\n sourceFilter(filters),\n rangeOverlapFilter('first_seen_ts', 'last_seen_ts', filters),\n projectFilter(filters, dialect),\n filters.model ? `model = ${sqlString(filters.model)}` : null,\n ])\n return `\n SELECT model, source_tool, project_name, session_count, turn_count,\n message_count, observation_count, first_seen_ts, last_seen_ts\n FROM model_usage\n ${where}\n ORDER BY session_count DESC, observation_count DESC, model ASC\n LIMIT ${limit(filters)}\n `\n}\n\n/** Builds the project_activity rollup query. */\nfunction buildProjectsSql(filters: AnalyticsReportFilters, dialect: AnalyticsDialect): string {\n const where = buildWhere([\n sourceFilter(filters),\n rangeOverlapFilter('first_session_ts', 'latest_session_ts', filters),\n projectFilter(filters, dialect),\n ])\n return `\n SELECT latest_session_ts, source_tool, project_name, project_path,\n session_count, message_count, tool_call_count, tool_error_count,\n low_confidence_session_count\n FROM project_activity\n ${where}\n ORDER BY latest_session_ts DESC NULLS LAST, session_count DESC, project_name ASC\n LIMIT ${limit(filters)}\n `\n}\n\n/** Builds an exact source_tool predicate when a source filter is present. */\nfunction sourceFilter(filters: AnalyticsReportFilters): string | null {\n return filters.source ? `source_tool = ${sqlString(filters.source)}` : null\n}\n\n/** Applies point-in-time bounds while retaining rows with unknown timestamps. */\nfunction timeFilter(column: string, filters: AnalyticsReportFilters): string | null {\n const filtersSql: string[] = []\n if (filters.since) filtersSql.push(`(${column} IS NULL OR ${column} >= ${sqlString(filters.since)})`)\n if (filters.until) filtersSql.push(`(${column} IS NULL OR ${column} < ${sqlString(filters.until)})`)\n return filtersSql.length ? filtersSql.join(' AND ') : null\n}\n\n/** Applies date bounds to fact rows whose observed span overlaps the filter range. */\nfunction rangeOverlapFilter(firstColumn: string, lastColumn: string, filters: AnalyticsReportFilters): string | null {\n const filtersSql: string[] = []\n if (filters.since) {\n filtersSql.push(`(${lastColumn} IS NULL OR ${lastColumn} >= ${sqlString(filters.since)})`)\n }\n if (filters.until) {\n filtersSql.push(`(${firstColumn} IS NULL OR ${firstColumn} < ${sqlString(filters.until)})`)\n }\n return filtersSql.length ? filtersSql.join(' AND ') : null\n}\n\n/** Builds the project matcher, accounting for SQLite and DuckDB LIKE semantics. */\nfunction projectFilter(filters: AnalyticsReportFilters, dialect: AnalyticsDialect): string | null {\n if (!filters.project) return null\n const exact = sqlString(filters.project)\n const like = sqlString(`%${escapeLike(filters.project)}%`)\n // DuckDB's LIKE is case-sensitive, ILIKE is case-insensitive. SQLite's LIKE\n // is case-insensitive for ASCII by default, so we use LIKE there.\n const op = dialect === 'duckdb' ? 'ILIKE' : 'LIKE'\n return `(project_id = ${exact} OR project_name ${op} ${like} ESCAPE '\\\\' OR project_path ${op} ${like} ESCAPE '\\\\')`\n}\n\n/** Joins active predicates into a WHERE clause. */\nfunction buildWhere(filters: Array<string | null>): string {\n const active = filters.filter((filter): filter is string => Boolean(filter))\n return active.length ? `WHERE ${active.join(' AND ')}` : ''\n}\n\n/** Clamps analytics report limits to the service maximum. */\nfunction limit(filters: AnalyticsReportFilters): number {\n const value = Number.isFinite(filters.limit) ? filters.limit : undefined\n return clampLimit(value, { max: 500, fallback: 50 })\n}\n\n/** Quotes a SQL string literal for fixed-template analytics SQL. */\nfunction sqlString(value: string): string {\n return `'${value.replace(/'/g, \"''\")}'`\n}\n\n/** Escapes wildcards in user-provided LIKE fragments. */\nfunction escapeLike(value: string): string {\n return value.replace(/[\\\\%_]/g, (match) => `\\\\${match}`)\n}\n","import { access, readFile, stat } from 'node:fs/promises'\nimport path from 'node:path'\nimport { type Bundle, type BundleManifest, closeBundle, defaultBundlePath, openBundle } from '../core/bundle.js'\nimport { decompressBytes } from '../core/cas/compress.js'\nimport { blake3HexAsync } from '../core/cas/hash.js'\nimport { getErrorMessage } from '../core/errors.js'\nimport { currentSchemaVersion } from '../core/schema/migrate.js'\nimport { PROSA_PARSER_VERSION, PROSA_SCHEMA_VERSION } from '../core/version.js'\nimport {\n type SearchIndexStatus,\n countFts5Docs,\n countSearchDocs,\n getCurrentTantivySchemaFingerprint,\n getSearchIndexStatuses,\n tantivyIndexDirIsValid,\n} from './indexing.js'\n\n/** Severity/status emitted by an individual doctor check. */\nexport type CheckStatus = 'pass' | 'info' | 'warn' | 'fail' | 'skipped'\n\n/** One diagnostic result produced by doctor. */\nexport interface CheckResult {\n check: string\n status: CheckStatus\n message: string\n hint?: string\n details?: Record<string, unknown>\n}\n\n/** Complete doctor run result, including filtered checks and status counts. */\nexport interface DoctorReport {\n storePath: string\n bundleOpened: boolean\n checks: CheckResult[]\n summary: {\n pass: number\n info: number\n warn: number\n fail: number\n skipped: number\n duration_ms: number\n }\n}\n\n/** Options controlling bundle selection, deep checks, and check filtering. */\nexport interface DoctorOptions {\n storePath?: string\n deep?: boolean\n deepSample?: number\n /** Dotted prefixes or exact check names to include. Empty/undefined = all. */\n checks?: string[]\n}\n\n/** Freelist percentage above which doctor recommends VACUUM. */\nconst VACUUM_THRESHOLD_PCT = 10\n\n/** WAL size threshold that usually indicates checkpoint blockage. */\nconst WAL_WARN_BYTES = 256 * 1024 * 1024\n\n/** Age threshold for considering an unfinished import batch abandoned. */\nconst STUCK_BATCH_AGE_HOURS = 1\n\n/** Number of recent import batches sampled for import error warnings. */\nconst RECENT_BATCHES_FOR_ERRORS = 3\n\n/** Default number of CAS objects sampled by deep doctor checks. */\nconst DEFAULT_DEEP_SAMPLE = 100\n\n/**\n * Return true when freelist waste crosses the vacuum-recommendation threshold.\n * Pure so the threshold logic is unit-testable without a fixture bundle.\n */\nexport function shouldRecommendVacuum(\n freelistCount: number,\n pageCount: number,\n thresholdPct = VACUUM_THRESHOLD_PCT,\n): boolean {\n if (pageCount <= 0) return false\n const pct = (freelistCount / pageCount) * 100\n return pct > thresholdPct\n}\n\n/**\n * Audit a bundle's health. Tolerates open failures: when `openBundle` throws\n * (missing manifest, schema mismatch, corrupt sqlite), doctor still produces\n * a report — the bundle-layout / schema checks fire and the rest are marked\n * `skipped`. Doctor never throws on bundle problems; only catastrophic errors\n * inside the check engine propagate.\n */\nexport async function runDoctor(opts: DoctorOptions = {}): Promise<DoctorReport> {\n const storePath = path.resolve(opts.storePath ?? defaultBundlePath())\n const deep = opts.deep === true\n const deepSample = Math.max(1, opts.deepSample ?? DEFAULT_DEEP_SAMPLE)\n const filters = opts.checks?.filter((c) => c.length > 0) ?? []\n\n const started = Date.now()\n const results: CheckResult[] = []\n\n const push = (result: CheckResult): void => {\n if (filters.length === 0 || matchesFilter(result.check, filters)) {\n results.push(result)\n }\n }\n\n // Phase 1: layout checks that don't need an open bundle.\n const layout = await checkBundleLayout(storePath)\n for (const r of layout.results) push(r)\n\n // Phase 2: try to open the bundle. If it fails, surface as a fail check and\n // skip the SQLite/search/data checks.\n let bundle: Bundle | null = null\n let openError: Error | null = null\n if (layout.canOpen) {\n try {\n bundle = await openBundle(storePath)\n } catch (err) {\n openError = err as Error\n }\n }\n\n if (openError) {\n push({\n check: 'bundle.open',\n status: 'fail',\n message: `openBundle failed: ${getErrorMessage(openError)}`,\n hint: 'fix the bundle layout or schema, then re-run doctor',\n details: { error: getErrorMessage(openError) },\n })\n } else if (!layout.canOpen) {\n push({\n check: 'bundle.open',\n status: 'skipped',\n message: 'bundle layout checks failed; not attempting to open',\n })\n } else if (bundle) {\n push({\n check: 'bundle.open',\n status: 'pass',\n message: `bundle opened at ${storePath}`,\n })\n }\n\n if (bundle) {\n try {\n // Schema triangulation.\n const schemaResults = checkSchema(bundle)\n for (const r of schemaResults) push(r)\n\n // SQLite-level health.\n for (const r of checkSqliteHealth(bundle)) push(r)\n const walResult = await checkWalSize(bundle)\n push(walResult)\n\n // Search index status + tantivy validity + drift.\n const liveCount = countSearchDocs(bundle)\n const liveFts5 = countFts5Docs(bundle)\n const statuses = getSearchIndexStatuses(bundle)\n for (const r of checkSearchIndexes(bundle, statuses, liveCount, liveFts5)) push(r)\n\n // Import errors + stuck batches.\n for (const r of checkImports(bundle)) push(r)\n\n // Data sanity.\n for (const r of checkData(bundle)) push(r)\n\n // Deep checks (opt-in).\n if (deep) {\n push(checkIntegrityFull(bundle))\n for (const r of await checkCasSample(bundle, deepSample)) push(r)\n } else {\n push({\n check: 'deep',\n status: 'skipped',\n message: 'run with --deep to include integrity_check and CAS hash sampling',\n })\n }\n } finally {\n closeBundle(bundle)\n }\n }\n\n const summary = {\n pass: results.filter((r) => r.status === 'pass').length,\n info: results.filter((r) => r.status === 'info').length,\n warn: results.filter((r) => r.status === 'warn').length,\n fail: results.filter((r) => r.status === 'fail').length,\n skipped: results.filter((r) => r.status === 'skipped').length,\n duration_ms: Date.now() - started,\n }\n\n return {\n storePath,\n bundleOpened: bundle !== null,\n checks: results,\n summary,\n }\n}\n\n/** Matches exact doctor check names or dotted check-family prefixes. */\nfunction matchesFilter(check: string, filters: string[]): boolean {\n return filters.some((f) => check === f || check.startsWith(`${f}.`))\n}\n\n// -- Phase 1: layout checks (run without a Bundle) ---------------------------\n\n/** Layout phase result, including whether openBundle should be attempted. */\ninterface LayoutResult {\n results: CheckResult[]\n canOpen: boolean\n}\n\n/** Checks the on-disk bundle layout without opening SQLite. */\nasync function checkBundleLayout(storePath: string): Promise<LayoutResult> {\n const results: CheckResult[] = []\n let manifestParsed: BundleManifest | null = null\n\n const dirStat = await stat(storePath).catch(() => null)\n if (!dirStat?.isDirectory()) {\n results.push({\n check: 'bundle.dir',\n status: 'fail',\n message: `${storePath} is not a directory`,\n hint: `prosa init --store ${storePath}`,\n })\n return { results, canOpen: false }\n }\n results.push({\n check: 'bundle.dir',\n status: 'pass',\n message: `bundle directory present at ${storePath}`,\n })\n\n const manifestPath = path.join(storePath, 'manifest.json')\n try {\n const raw = await readFile(manifestPath, 'utf8')\n manifestParsed = JSON.parse(raw) as BundleManifest\n const requiredFields: (keyof BundleManifest)[] = [\n 'version',\n 'parser_version',\n 'schema_version',\n 'created_at',\n 'hash_alg',\n 'default_compression',\n ]\n const missing = requiredFields.filter((f) => manifestParsed?.[f] == null)\n if (missing.length > 0) {\n results.push({\n check: 'bundle.manifest',\n status: 'fail',\n message: `manifest.json missing required fields: ${missing.join(', ')}`,\n details: { missing },\n })\n return { results, canOpen: false }\n }\n results.push({\n check: 'bundle.manifest',\n status: 'pass',\n message: `manifest.json valid (version=${manifestParsed.version}, schema_version=${manifestParsed.schema_version})`,\n details: { manifest: manifestParsed as unknown as Record<string, unknown> },\n })\n } catch (err) {\n results.push({\n check: 'bundle.manifest',\n status: 'fail',\n message: `manifest.json not readable: ${getErrorMessage(err)}`,\n hint: `prosa init --store ${storePath}`,\n })\n return { results, canOpen: false }\n }\n\n // sqlite file.\n const dbPath = path.join(storePath, 'prosa.sqlite')\n const dbStat = await stat(dbPath).catch(() => null)\n if (!dbStat?.isFile() || dbStat.size === 0) {\n results.push({\n check: 'bundle.sqlite',\n status: 'fail',\n message: 'prosa.sqlite missing or empty',\n hint: `prosa init --store ${storePath}`,\n })\n return { results, canOpen: false }\n }\n results.push({\n check: 'bundle.sqlite',\n status: 'pass',\n message: `prosa.sqlite present (${formatBytes(dbStat.size)})`,\n details: { size_bytes: dbStat.size },\n })\n\n // Required sidecar directories.\n const requiredDirs: { key: string; rel: string }[] = [\n { key: 'objects', rel: 'objects' },\n { key: 'rawSources', rel: 'raw/sources' },\n { key: 'search', rel: 'search' },\n { key: 'tantivy', rel: 'search/tantivy' },\n { key: 'exports', rel: 'exports' },\n { key: 'parquet', rel: 'parquet' },\n ]\n const missingDirs: string[] = []\n for (const d of requiredDirs) {\n const s = await stat(path.join(storePath, d.rel)).catch(() => null)\n if (!s?.isDirectory()) missingDirs.push(d.rel)\n }\n if (missingDirs.length > 0) {\n results.push({\n check: 'bundle.dirs',\n status: 'warn',\n message: `missing sidecar directories: ${missingDirs.join(', ')}`,\n hint: 'openBundle recreates search/ and search/tantivy/ on next open; others come from init',\n details: { missing: missingDirs },\n })\n } else {\n results.push({\n check: 'bundle.dirs',\n status: 'pass',\n message: 'all sidecar directories present',\n })\n }\n\n // Format guards.\n if (manifestParsed.hash_alg !== 'blake3') {\n results.push({\n check: 'bundle.format',\n status: 'fail',\n message: `unexpected hash_alg=${manifestParsed.hash_alg}; expected blake3`,\n })\n } else if (manifestParsed.default_compression !== 'zstd') {\n results.push({\n check: 'bundle.format',\n status: 'warn',\n message: `default_compression=${manifestParsed.default_compression}; expected zstd`,\n })\n } else {\n results.push({\n check: 'bundle.format',\n status: 'pass',\n message: 'hash_alg=blake3, default_compression=zstd',\n })\n }\n\n return { results, canOpen: true }\n}\n\n// -- Phase 2: checks with an open Bundle -------------------------------------\n\n/** Compares manifest, SQLite, and code schema/parser versions. */\nfunction checkSchema(bundle: Bundle): CheckResult[] {\n const results: CheckResult[] = []\n const dbVersion = currentSchemaVersion(bundle.db)\n const manifestVersion = bundle.manifest.schema_version\n const details = { manifest: manifestVersion, db: dbVersion, code: PROSA_SCHEMA_VERSION }\n\n // openBundle already enforces db === code, so by the time we run we know\n // they agree. The remaining axis is the manifest, which is written once at\n // init and currently never updated by migrations.\n if (dbVersion !== PROSA_SCHEMA_VERSION) {\n results.push({\n check: 'schema.version',\n status: 'fail',\n message: `db schema_version=${dbVersion} but code expects ${PROSA_SCHEMA_VERSION}`,\n hint: 'upgrade or downgrade prosa to match the bundle, or re-run any command to apply pending migrations',\n details,\n })\n } else if (manifestVersion !== dbVersion) {\n results.push({\n check: 'schema.version',\n status: 'warn',\n message: `manifest.schema_version=${manifestVersion} but db has migrated to ${dbVersion}`,\n hint: 'manifest is stale after a migration; safe to ignore or refresh manually',\n details,\n })\n } else {\n results.push({\n check: 'schema.version',\n status: 'pass',\n message: `schema_version=${PROSA_SCHEMA_VERSION} (manifest, db, code agree)`,\n })\n }\n\n if (bundle.manifest.parser_version === PROSA_PARSER_VERSION) {\n results.push({\n check: 'schema.parser_version',\n status: 'pass',\n message: `parser_version=${PROSA_PARSER_VERSION}`,\n })\n } else {\n results.push({\n check: 'schema.parser_version',\n status: 'info',\n message: `manifest.parser_version=${bundle.manifest.parser_version} != code ${PROSA_PARSER_VERSION} (will be refreshed on next openBundle)`,\n })\n }\n\n return results\n}\n\n/** Runs lightweight SQLite health and storage-efficiency checks. */\nfunction checkSqliteHealth(bundle: Bundle): CheckResult[] {\n const results: CheckResult[] = []\n\n // PRAGMA quick_check returns rows with the column named 'quick_check' — read by index.\n const quickRows = bundle.db.prepare(`PRAGMA quick_check`).all() as Array<Record<string, unknown>>\n const quickValue = quickRows[0] ? Object.values(quickRows[0])[0] : null\n if (quickValue === 'ok') {\n results.push({ check: 'sqlite.quick_check', status: 'pass', message: 'quick_check=ok' })\n } else {\n results.push({\n check: 'sqlite.quick_check',\n status: 'fail',\n message: `quick_check returned ${String(quickValue)}`,\n hint: 'run with --deep for full integrity_check, or restore from backup',\n details: { rows: quickRows },\n })\n }\n\n const fkRows = bundle.db.prepare(`PRAGMA foreign_key_check`).all() as Array<Record<string, unknown>>\n if (fkRows.length === 0) {\n results.push({\n check: 'sqlite.foreign_keys',\n status: 'pass',\n message: 'no foreign key violations',\n })\n } else {\n results.push({\n check: 'sqlite.foreign_keys',\n status: 'fail',\n message: `${fkRows.length} foreign key violation(s)`,\n details: { violations: fkRows.slice(0, 5) },\n })\n }\n\n const journalMode = (bundle.db.prepare(`PRAGMA journal_mode`).get() as { journal_mode?: string } | undefined)\n ?.journal_mode\n if (journalMode === 'wal') {\n results.push({ check: 'sqlite.journal_mode', status: 'pass', message: 'journal_mode=wal' })\n } else {\n results.push({\n check: 'sqlite.journal_mode',\n status: 'warn',\n message: `journal_mode=${journalMode ?? 'unknown'}; expected wal`,\n })\n }\n\n const pageSize = (bundle.db.prepare(`PRAGMA page_size`).get() as { page_size?: number } | undefined)?.page_size ?? 0\n if (pageSize === 16384) {\n results.push({ check: 'sqlite.page_size', status: 'pass', message: 'page_size=16384' })\n } else {\n results.push({\n check: 'sqlite.page_size',\n status: 'warn',\n message: `page_size=${pageSize}; current openDb expects 16384`,\n hint: `migrate with: sqlite3 prosa.sqlite \"PRAGMA page_size=16384; VACUUM INTO 'prosa16k.sqlite';\" and swap files`,\n details: { page_size: pageSize },\n })\n }\n\n const pageCount =\n (bundle.db.prepare(`PRAGMA page_count`).get() as { page_count?: number } | undefined)?.page_count ?? 0\n const freelistCount =\n (bundle.db.prepare(`PRAGMA freelist_count`).get() as { freelist_count?: number } | undefined)?.freelist_count ?? 0\n const pctWaste = pageCount > 0 ? (freelistCount / pageCount) * 100 : 0\n const dbSizeBytes = pageCount * pageSize\n if (shouldRecommendVacuum(freelistCount, pageCount)) {\n results.push({\n check: 'sqlite.vacuum_hint',\n status: 'warn',\n message: `${pctWaste.toFixed(1)}% of pages are free (${freelistCount}/${pageCount})`,\n hint: 'run VACUUM to reclaim space and defragment indexes',\n details: {\n page_count: pageCount,\n freelist_count: freelistCount,\n pct_waste: Number(pctWaste.toFixed(2)),\n db_size_bytes: dbSizeBytes,\n },\n })\n } else {\n results.push({\n check: 'sqlite.vacuum_hint',\n status: 'pass',\n message: `${pctWaste.toFixed(2)}% pages free; VACUUM not needed`,\n details: {\n page_count: pageCount,\n freelist_count: freelistCount,\n pct_waste: Number(pctWaste.toFixed(2)),\n db_size_bytes: dbSizeBytes,\n },\n })\n }\n\n return results\n}\n\n/** Warns when a WAL file is large enough to suggest blocked checkpointing. */\nasync function checkWalSize(bundle: Bundle): Promise<CheckResult> {\n const walPath = `${bundle.paths.db}-wal`\n const s = await stat(walPath).catch(() => null)\n if (!s) {\n return {\n check: 'sqlite.wal_size',\n status: 'pass',\n message: 'WAL file absent (DB closed cleanly or checkpointed)',\n }\n }\n if (s.size > WAL_WARN_BYTES) {\n return {\n check: 'sqlite.wal_size',\n status: 'warn',\n message: `WAL file is ${formatBytes(s.size)}; a long-lived read transaction is preventing checkpoint`,\n hint: `close other prosa processes, then: sqlite3 prosa.sqlite \"PRAGMA wal_checkpoint(TRUNCATE);\"`,\n details: { wal_size_bytes: s.size },\n }\n }\n return {\n check: 'sqlite.wal_size',\n status: 'pass',\n message: `WAL size ${formatBytes(s.size)}`,\n details: { wal_size_bytes: s.size },\n }\n}\n\n/** Checks FTS5 and Tantivy readiness, validity, and source-count drift. */\nfunction checkSearchIndexes(\n bundle: Bundle,\n statuses: SearchIndexStatus[],\n liveDocCount: number,\n liveFts5Count: number,\n): CheckResult[] {\n const results: CheckResult[] = []\n const byEngine = new Map(statuses.map((s) => [s.engine, s]))\n\n // FTS5.\n const fts5 = byEngine.get('fts5')\n if (!fts5 || fts5.status === 'missing') {\n results.push({\n check: 'search.fts5',\n status: 'warn',\n message: 'fts5 index missing',\n hint: 'prosa index fts5',\n })\n } else if (fts5.status === 'ready') {\n if (liveFts5Count !== liveDocCount) {\n results.push({\n check: 'search.fts5',\n status: 'warn',\n message: `fts5 indexed ${liveFts5Count} docs but search_docs has ${liveDocCount}`,\n hint: 'prosa index fts5',\n details: { fts5_count: liveFts5Count, source_count: liveDocCount, ...statusDetails(fts5) },\n })\n } else {\n results.push({\n check: 'search.fts5',\n status: 'pass',\n message: `fts5 ready (${liveFts5Count} docs)`,\n details: statusDetails(fts5),\n })\n }\n } else if (fts5.status === 'failed') {\n results.push({\n check: 'search.fts5',\n status: 'fail',\n message: `fts5 failed: ${fts5.error_message ?? 'unknown error'}`,\n hint: 'prosa index fts5',\n details: statusDetails(fts5),\n })\n } else {\n results.push({\n check: 'search.fts5',\n status: 'warn',\n message: `fts5 status=${fts5.status}`,\n hint: 'prosa index fts5',\n details: statusDetails(fts5),\n })\n }\n\n // Tantivy.\n const tantivy = byEngine.get('tantivy')\n if (!tantivy || tantivy.status === 'missing') {\n results.push({\n check: 'search.tantivy',\n status: 'info',\n message: 'tantivy index not built (optional)',\n hint: 'prosa index tantivy',\n })\n } else {\n const dirValid = tantivyIndexDirIsValid(bundle.paths.tantivy)\n const currentFingerprint = getCurrentTantivySchemaFingerprint()\n const fingerprintOk = tantivy.schema_fingerprint == null || tantivy.schema_fingerprint === currentFingerprint\n\n if (tantivy.status === 'failed') {\n results.push({\n check: 'search.tantivy',\n status: 'fail',\n message: `tantivy failed: ${tantivy.error_message ?? 'unknown error'}`,\n hint: 'prosa index tantivy --overwrite',\n details: statusDetails(tantivy),\n })\n } else if (tantivy.status === 'ready' && !dirValid) {\n results.push({\n check: 'search.tantivy',\n status: 'fail',\n message: 'tantivy status=ready but index directory has no meta.json',\n hint: 'prosa index tantivy --overwrite',\n details: { ...statusDetails(tantivy), dir: bundle.paths.tantivy },\n })\n } else if (!fingerprintOk) {\n results.push({\n check: 'search.tantivy',\n status: 'warn',\n message: 'tantivy schema fingerprint drift; rebuild will be forced full',\n hint: 'prosa index tantivy --overwrite',\n details: {\n stored: tantivy.schema_fingerprint,\n current: currentFingerprint,\n ...statusDetails(tantivy),\n },\n })\n } else if (tantivy.status === 'ready') {\n results.push({\n check: 'search.tantivy',\n status: 'pass',\n message: `tantivy ready (${tantivy.indexed_doc_count} docs)`,\n details: statusDetails(tantivy),\n })\n } else {\n results.push({\n check: 'search.tantivy',\n status: 'warn',\n message: `tantivy status=${tantivy.status}`,\n hint: 'prosa index tantivy',\n details: statusDetails(tantivy),\n })\n }\n }\n\n // Drift between live search_docs and what indexes recorded.\n const drift = statuses\n .filter((s) => s.status === 'ready')\n .map((s) => ({\n engine: s.engine,\n stored: s.source_doc_count,\n live: liveDocCount,\n diff: liveDocCount - s.source_doc_count,\n }))\n .filter((d) => d.diff !== 0)\n if (drift.length > 0) {\n results.push({\n check: 'search.drift',\n status: 'warn',\n message: `search_docs count drifted from recorded source_doc_count: ${drift\n .map((d) => `${d.engine} off by ${d.diff}`)\n .join('; ')}`,\n hint: 'prosa index <engine> for each affected engine',\n details: { drift },\n })\n } else {\n results.push({\n check: 'search.drift',\n status: 'pass',\n message: `search_docs (${liveDocCount}) matches recorded source counts`,\n })\n }\n\n return results\n}\n\n/** Serializes common search-index status fields into doctor details. */\nfunction statusDetails(s: SearchIndexStatus): Record<string, unknown> {\n return {\n engine: s.engine,\n status: s.status,\n source_doc_count: s.source_doc_count,\n indexed_doc_count: s.indexed_doc_count,\n updated_at: s.updated_at,\n }\n}\n\n/** Checks recent import errors and abandoned import batches. */\nfunction checkImports(bundle: Bundle): CheckResult[] {\n const results: CheckResult[] = []\n\n const stuckRows = bundle.db\n .prepare(\n `SELECT batch_id, started_at, source_tool, status FROM import_batches\n WHERE finished_at IS NULL\n AND (julianday('now') - julianday(started_at)) * 24 > ?`,\n )\n .all(STUCK_BATCH_AGE_HOURS) as Array<Record<string, unknown>>\n if (stuckRows.length > 0) {\n results.push({\n check: 'import_batches.stuck',\n status: 'warn',\n message: `${stuckRows.length} unfinished import batch(es) older than ${STUCK_BATCH_AGE_HOURS}h`,\n hint: 'a previous compile crashed; re-run prosa compile or compile-all',\n details: { batches: stuckRows },\n })\n } else {\n results.push({\n check: 'import_batches.stuck',\n status: 'pass',\n message: 'no stuck import batches',\n })\n }\n\n // Errors in the most recent N batches.\n const recentErrors = bundle.db\n .prepare(\n `WITH recent AS (\n SELECT batch_id FROM import_batches ORDER BY started_at DESC LIMIT ?\n )\n SELECT kind, COUNT(*) AS n\n FROM import_errors\n WHERE batch_id IN (SELECT batch_id FROM recent)\n GROUP BY kind\n ORDER BY n DESC`,\n )\n .all(RECENT_BATCHES_FOR_ERRORS) as Array<{ kind: string; n: number }>\n\n const recentSamples = bundle.db\n .prepare(\n `WITH recent AS (\n SELECT batch_id FROM import_batches ORDER BY started_at DESC LIMIT ?\n )\n SELECT kind, message, occurred_at\n FROM import_errors\n WHERE batch_id IN (SELECT batch_id FROM recent)\n ORDER BY occurred_at DESC\n LIMIT 3`,\n )\n .all(RECENT_BATCHES_FOR_ERRORS) as Array<Record<string, unknown>>\n\n const totalRecent = recentErrors.reduce((s, r) => s + r.n, 0)\n if (totalRecent > 0) {\n results.push({\n check: 'import_errors.recent',\n status: 'warn',\n message: `${totalRecent} error(s) across the last ${RECENT_BATCHES_FOR_ERRORS} import batch(es)`,\n hint: 'inspect import_errors or re-run the affected compile with --verbose',\n details: { by_kind: recentErrors, samples: recentSamples },\n })\n } else {\n results.push({\n check: 'import_errors.recent',\n status: 'pass',\n message: `no errors in the last ${RECENT_BATCHES_FOR_ERRORS} import batch(es)`,\n })\n }\n\n return results\n}\n\n/** Runs cross-table sanity checks for imported session data. */\nfunction checkData(bundle: Bundle): CheckResult[] {\n const results: CheckResult[] = []\n\n const counts = bundle.db\n .prepare(\n `SELECT\n (SELECT COUNT(*) FROM sessions) AS sessions,\n (SELECT COUNT(*) FROM messages) AS messages,\n (SELECT COUNT(*) FROM raw_records) AS raw_records,\n (SELECT COUNT(*) FROM objects) AS objects`,\n )\n .get() as { sessions: number; messages: number; raw_records: number; objects: number }\n\n if (counts.sessions === 0) {\n results.push({\n check: 'data.counts',\n status: 'info',\n message: 'bundle is empty (no sessions imported yet)',\n details: counts,\n })\n } else if (counts.messages === 0) {\n results.push({\n check: 'data.counts',\n status: 'fail',\n message: `${counts.sessions} session(s) but 0 messages — import likely broke mid-file`,\n hint: 'inspect import_errors and re-run prosa compile-all',\n details: counts,\n })\n } else {\n results.push({\n check: 'data.counts',\n status: 'pass',\n message: `sessions=${counts.sessions}, messages=${counts.messages}, raw_records=${counts.raw_records}, objects=${counts.objects}`,\n details: counts,\n })\n }\n\n // Subagent edges pointing at sessions that don't exist (info-only).\n const orphanSubagents = bundle.db\n .prepare(\n `SELECT COUNT(*) AS n\n FROM edges e\n WHERE e.edge_type = 'spawned'\n AND e.dst_type = 'session'\n AND NOT EXISTS (SELECT 1 FROM sessions s WHERE s.session_id = e.dst_id)`,\n )\n .get() as { n: number }\n if (orphanSubagents.n > 0) {\n results.push({\n check: 'data.subagents',\n status: 'info',\n message: `${orphanSubagents.n} spawned-edge(s) point to sessions not in the bundle (subagent files not yet imported)`,\n details: { count: orphanSubagents.n },\n })\n } else {\n results.push({\n check: 'data.subagents',\n status: 'pass',\n message: 'no orphan subagent edges',\n })\n }\n\n return results\n}\n\n// -- Deep checks -------------------------------------------------------------\n\n/** Runs SQLite's full integrity_check for opt-in deep diagnostics. */\nfunction checkIntegrityFull(bundle: Bundle): CheckResult {\n const rows = bundle.db.prepare(`PRAGMA integrity_check`).all() as Array<Record<string, unknown>>\n const first = rows[0] ? Object.values(rows[0])[0] : null\n if (rows.length === 1 && first === 'ok') {\n return {\n check: 'deep.integrity_check',\n status: 'pass',\n message: 'integrity_check=ok',\n }\n }\n return {\n check: 'deep.integrity_check',\n status: 'fail',\n message: `integrity_check returned ${rows.length} issue(s)`,\n details: { issues: rows.slice(0, 20) },\n }\n}\n\n/** CAS object row sampled during deep hash verification. */\ninterface CasSampleRow {\n object_id: string\n hash: string\n compression: 'zstd' | 'none'\n storage_path: string\n size_bytes: number\n}\n\n/** Samples CAS files, verifying file existence and decoded blake3 hashes. */\nasync function checkCasSample(bundle: Bundle, sampleSize: number): Promise<CheckResult[]> {\n const rows = bundle.db\n .prepare(\n `SELECT object_id, hash, compression, storage_path, size_bytes\n FROM objects\n ORDER BY random()\n LIMIT ?`,\n )\n .all(sampleSize) as CasSampleRow[]\n\n if (rows.length === 0) {\n return [\n {\n check: 'deep.cas_file_exists',\n status: 'info',\n message: 'objects table empty; nothing to sample',\n },\n {\n check: 'deep.cas_hash_sample',\n status: 'info',\n message: 'objects table empty; nothing to sample',\n },\n ]\n }\n\n const missing: string[] = []\n const hashMismatches: string[] = []\n const readErrors: string[] = []\n let checked = 0\n\n // Rows in `objects` can live under either `objects/blake3/.../<hash>.<ext>`\n // (the CAS layout used by stage*/flushPendingObjects) or `raw/sources/<hash>.<ext>`\n // (source files registered by registerSourceFile). The on-disk path is always\n // stored verbatim in `storage_path` — trust that column rather than recomputing.\n for (const row of rows) {\n const abs = path.join(bundle.path, row.storage_path)\n try {\n await access(abs)\n } catch {\n missing.push(row.object_id)\n continue\n }\n try {\n const compressed = await readFile(abs)\n const plain = decompressBytes(compressed, row.compression)\n const recomputed = `blake3:${await blake3HexAsync(plain)}`\n if (recomputed !== row.object_id) {\n hashMismatches.push(`${row.object_id} (file decodes to ${recomputed})`)\n }\n checked++\n } catch (err) {\n readErrors.push(`${row.object_id}: ${getErrorMessage(err)}`)\n }\n }\n\n const results: CheckResult[] = []\n if (missing.length === 0) {\n results.push({\n check: 'deep.cas_file_exists',\n status: 'pass',\n message: `all ${rows.length} sampled objects have files on disk`,\n })\n } else {\n results.push({\n check: 'deep.cas_file_exists',\n status: 'fail',\n message: `${missing.length}/${rows.length} sampled objects have missing files`,\n hint: 'CAS files were deleted outside prosa; re-import the affected source files',\n details: { missing: missing.slice(0, 10) },\n })\n }\n\n if (hashMismatches.length === 0 && readErrors.length === 0) {\n results.push({\n check: 'deep.cas_hash_sample',\n status: 'pass',\n message: `re-hashed ${checked} sampled object(s); all match`,\n })\n } else if (hashMismatches.length > 0) {\n results.push({\n check: 'deep.cas_hash_sample',\n status: 'fail',\n message: `${hashMismatches.length} hash mismatch(es) in ${rows.length} sampled object(s)`,\n hint: 'silent corruption on disk; restore from backup',\n details: {\n mismatches: hashMismatches.slice(0, 10),\n read_errors: readErrors.slice(0, 5),\n },\n })\n } else {\n results.push({\n check: 'deep.cas_hash_sample',\n status: 'warn',\n message: `${readErrors.length} read error(s) while sampling CAS objects`,\n details: { read_errors: readErrors.slice(0, 10) },\n })\n }\n\n return results\n}\n\n// -- Helpers -----------------------------------------------------------------\n\n/** Formats byte counts for human-readable doctor messages. */\nfunction formatBytes(n: number): string {\n if (n < 1024) return `${n} B`\n const units = ['KiB', 'MiB', 'GiB', 'TiB']\n let v = n / 1024\n let i = 0\n while (v >= 1024 && i < units.length - 1) {\n v /= 1024\n i++\n }\n return `${v.toFixed(1)} ${units[i]}`\n}\n","import type { Bundle } from '../core/bundle.js'\nimport { clampLimit } from '../core/limits.js'\n\n/** Entity kinds surfaced by tool-call history queries. */\nexport type ToolCallEntity = 'tool_call' | 'artifact'\n\n/** Tool-call or artifact evidence row returned by file and command history queries. */\nexport interface ToolCallEvidence {\n /** Whether this row describes a tool call or a matching artifact. */\n entity_type: ToolCallEntity\n /** Session that owns the evidence. */\n session_id: string | null\n /** Tool call identifier when `entity_type` is `tool_call`. */\n tool_call_id: string | null\n /** Artifact identifier when `entity_type` is `artifact`. */\n artifact_id: string | null\n /** Native tool name. */\n tool_name: string | null\n /** Canonical tool category. */\n canonical_tool_type: string | null\n /** Command text, when the tool represents shell execution. */\n command: string | null\n /** File path associated with the tool call or artifact. */\n path: string | null\n /** Normalized tool call status. */\n status: string | null\n /** Tool call start timestamp or artifact creation timestamp. */\n timestamp_start: string | null\n /** SQLite boolean indicating an error result. */\n is_error: 0 | 1 | null\n /** Process exit code when available. */\n exit_code: number | null\n /** Human-sized result preview. */\n preview: string | null\n}\n\n/** Filters for tool-call history and file-history queries. */\nexport interface ToolCallFilters {\n /** Restrict evidence to one session. */\n sessionId?: string\n /** Restrict evidence to a native tool name. */\n toolName?: string\n /** Restrict evidence to a canonical tool category. */\n canonicalType?: string\n /** Match paths on tool calls and artifacts. */\n pathSubstring?: string\n /** Include only tool calls with error evidence. */\n errorsOnly?: boolean\n /** Inclusive lower bound for tool timestamps. */\n sinceIso?: string\n /** Exclusive upper bound for tool timestamps. */\n untilIso?: string\n /** Maximum rows to return, clamped by service limits. */\n limit?: number\n}\n\n/** Lists tool-call evidence, including artifacts when filtering by path substring. */\nexport function listToolCalls(bundle: Bundle, filters: ToolCallFilters = {}): ToolCallEvidence[] {\n const conds: string[] = []\n const params: unknown[] = []\n\n if (filters.toolName) {\n conds.push('tc.tool_name = ?')\n params.push(filters.toolName)\n }\n if (filters.canonicalType) {\n conds.push('tc.canonical_tool_type = ?')\n params.push(filters.canonicalType)\n }\n if (filters.sessionId) {\n conds.push('tc.session_id = ?')\n params.push(filters.sessionId)\n }\n if (filters.errorsOnly) {\n conds.push('(tr.is_error = 1 OR tc.status = ?)')\n params.push('error')\n }\n if (filters.pathSubstring) {\n conds.push('tc.path IS NOT NULL AND tc.path LIKE ?')\n params.push(`%${filters.pathSubstring}%`)\n }\n if (filters.sinceIso) {\n conds.push('(tc.timestamp_start IS NULL OR tc.timestamp_start >= ?)')\n params.push(filters.sinceIso)\n }\n if (filters.untilIso) {\n conds.push('(tc.timestamp_start IS NULL OR tc.timestamp_start < ?)')\n params.push(filters.untilIso)\n }\n\n const where = conds.length ? `WHERE ${conds.join(' AND ')}` : ''\n const limit = clampLimit(filters.limit, { max: 500, fallback: 100 })\n\n const toolCallSql = `\n SELECT 'tool_call' AS entity_type,\n tc.session_id,\n tc.tool_call_id,\n NULL AS artifact_id,\n tc.tool_name,\n tc.canonical_tool_type,\n tc.command,\n tc.path,\n tc.status,\n tc.timestamp_start,\n tr.is_error,\n tr.exit_code,\n tr.preview\n FROM tool_calls tc\n LEFT JOIN tool_results tr ON tr.tool_call_id = tc.tool_call_id\n ${where}\n `\n\n if (!filters.pathSubstring) {\n const sql = `${toolCallSql} ORDER BY tc.timestamp_start DESC LIMIT ${limit}`\n return bundle.db.prepare(sql).all(...params) as ToolCallEvidence[]\n }\n\n // path_substring is set: also surface artifacts with matching paths so\n // file-history queries return both tool_calls that touched a path and\n // artifacts produced for that path.\n const artifactSql = `\n SELECT 'artifact' AS entity_type,\n a.session_id,\n NULL AS tool_call_id,\n a.artifact_id,\n NULL AS tool_name,\n NULL AS canonical_tool_type,\n NULL AS command,\n a.path,\n NULL AS status,\n a.created_ts AS timestamp_start,\n NULL AS is_error,\n NULL AS exit_code,\n NULL AS preview\n FROM artifacts a\n WHERE a.path IS NOT NULL AND a.path LIKE ?\n `\n const sql = `\n ${toolCallSql}\n UNION ALL\n ${artifactSql}\n ORDER BY timestamp_start DESC\n LIMIT ${limit}\n `\n return bundle.db.prepare(sql).all(...params, `%${filters.pathSubstring}%`) as ToolCallEvidence[]\n}\n","import type { Bundle } from '../core/bundle.js'\nimport { getText } from '../core/cas/index.js'\nimport type { ObjectId } from '../core/cas/index.js'\nimport type { SessionRow } from './sessions.js'\n\n/** Default inline-text byte budget for block resolution. Larger blobs stay in CAS. */\nconst DEFAULT_MAX_INLINE_BYTES = 64 * 1024\n/** Default inline-text byte budget for tool-call args JSON. */\nconst DEFAULT_MAX_ARGS_INLINE_BYTES = 8 * 1024\n\n/** Matched `tool_results` row attached to its owning `TranscriptToolCall`. */\nexport interface TranscriptToolResult {\n toolResultId: string\n status: string | null\n isError: boolean\n exitCode: number | null\n durationMs: number | null\n preview: string | null\n /** Full stdout, if any, is in CAS; pass-through id so renderers can fetch on demand. */\n stdoutObjectId: string | null\n /** Full stderr, if any, is in CAS; pass-through id so renderers can fetch on demand. */\n stderrObjectId: string | null\n /** Full output, if any, is in CAS; pass-through id so renderers can fetch on demand. */\n outputObjectId: string | null\n}\n\n/** Tool invocation rendered alongside its owning turn (or as unattached). */\nexport interface TranscriptToolCall {\n toolCallId: string\n toolName: string\n canonicalToolType: string | null\n /** Resolved args JSON text when ≤ maxArgsInlineBytes; otherwise null. */\n argsInline: string | null\n /** Source CAS id for args. Kept so renderers can fetch on demand. */\n argsObjectId: string | null\n command: string | null\n path: string | null\n status: string | null\n timestampStart: string | null\n result: TranscriptToolResult | null\n}\n\n/** One content block in a message: text, thinking, tool_use, tool_result, etc. */\nexport interface TranscriptBlock {\n blockId: string\n blockType: 'text' | 'thinking' | 'tool_use' | 'tool_result' | string\n /** Resolved inline OR fetched from CAS when ≤ maxInlineBytes. Null for oversize. */\n text: string | null\n /** Source CAS id for text. Kept so renderers can fetch oversized blobs on demand. */\n textObjectId: string | null\n /** Mirrors `content_blocks.visibility = 'hidden_by_default'`. */\n hidden: boolean\n mimeType: string | null\n isError: boolean\n}\n\n/** One conversational turn: a message plus its blocks and outbound tool calls. */\nexport interface TranscriptTurn {\n messageId: string\n ordinal: number\n role: 'system_prompt' | 'developer' | 'user' | 'assistant' | 'tool' | 'operational'\n model: string | null\n timestamp: string | null\n blocks: TranscriptBlock[]\n toolCalls: TranscriptToolCall[]\n}\n\n/** Full structured transcript for one session. */\nexport interface SessionTranscript {\n session: SessionRow\n turns: TranscriptTurn[]\n /** Tool calls whose `message_id` is NULL (legacy / event-only imports). */\n unattachedToolCalls: TranscriptToolCall[]\n}\n\n/** Options controlling how aggressively the loader inlines CAS-backed text. */\nexport interface LoadTranscriptOptions {\n /** Maximum UTF-8 byte size to inline a block's text. Default 64KB. */\n maxInlineBytes?: number\n /** Maximum UTF-8 byte size to inline a tool-call's args JSON. Default 8KB. */\n maxArgsInlineBytes?: number\n}\n\ninterface MessageRow {\n message_id: string\n role: string\n timestamp: string | null\n ordinal: number\n model: string | null\n}\n\ninterface BlockRow {\n block_id: string\n message_id: string | null\n block_type: string\n text_object_id: string | null\n text_inline: string | null\n ordinal: number\n mime_type: string | null\n is_error: 0 | 1 | null\n visibility: 'default' | 'hidden_by_default' | 'audit_only'\n}\n\ninterface ToolCallRow {\n tool_call_id: string\n message_id: string | null\n tool_name: string\n canonical_tool_type: string | null\n args_object_id: string | null\n command: string | null\n path: string | null\n status: string | null\n timestamp_start: string | null\n}\n\ninterface ToolResultRow {\n tool_call_id: string | null\n tool_result_id: string\n status: string | null\n is_error: 0 | 1 | null\n exit_code: number | null\n duration_ms: number | null\n preview: string | null\n stdout_object_id: string | null\n stderr_object_id: string | null\n output_object_id: string | null\n}\n\n/**\n * Assemble a session's full conversation — messages, content blocks, and tool\n * calls with matched results — from the local bundle SQLite. Returns null\n * when the session is absent (callers handle \"not found\" themselves).\n *\n * Text bodies are resolved inline when small enough; oversize bodies surface\n * only as `textObjectId`/`argsObjectId` so renderers can fetch on demand.\n */\nexport async function loadTranscript(\n bundle: Bundle,\n sessionId: string,\n options: LoadTranscriptOptions = {},\n): Promise<SessionTranscript | null> {\n const maxInlineBytes = options.maxInlineBytes ?? DEFAULT_MAX_INLINE_BYTES\n const maxArgsInlineBytes = options.maxArgsInlineBytes ?? DEFAULT_MAX_ARGS_INLINE_BYTES\n\n const session = bundle.db\n .prepare<[string], SessionRow>(\n `SELECT s.session_id,\n s.source_tool,\n s.source_session_id,\n s.project_id,\n s.parent_session_id,\n s.is_subagent,\n s.title,\n s.start_ts,\n s.end_ts,\n s.cwd_initial,\n s.git_branch_initial,\n s.model_first,\n s.model_last,\n s.status,\n s.timeline_confidence,\n (SELECT count(*) FROM messages m WHERE m.session_id = s.session_id) AS message_count,\n (SELECT count(*) FROM tool_calls tc WHERE tc.session_id = s.session_id) AS tool_call_count\n FROM sessions s\n WHERE s.session_id = ?`,\n )\n .get(sessionId)\n\n if (!session) return null\n\n const messages = bundle.db\n .prepare<[string], MessageRow>(\n `SELECT message_id, role, timestamp, ordinal, model\n FROM messages WHERE session_id = ? ORDER BY ordinal`,\n )\n .all(sessionId)\n\n // Include hidden_by_default rows; the renderer decides whether to display\n // thinking blocks. audit_only stays excluded (privacy posture).\n const blocks = bundle.db\n .prepare<[string], BlockRow>(\n `SELECT block_id, message_id, block_type, text_object_id, text_inline,\n ordinal, mime_type, is_error, visibility\n FROM content_blocks\n WHERE session_id = ? AND visibility != 'audit_only'\n ORDER BY message_id, ordinal`,\n )\n .all(sessionId)\n\n const toolCalls = bundle.db\n .prepare<[string], ToolCallRow>(\n `SELECT tool_call_id, message_id, tool_name, canonical_tool_type, args_object_id,\n command, path, status, timestamp_start\n FROM tool_calls WHERE session_id = ?\n ORDER BY timestamp_start, tool_call_id`,\n )\n .all(sessionId)\n\n // LEFT JOIN equivalent: one query gets all results for the session, then we\n // group by tool_call_id below. Multiple results per call are possible in\n // theory; we keep the latest by tool_result_id ordering.\n const toolResults = bundle.db\n .prepare<[string], ToolResultRow>(\n `SELECT tool_call_id, tool_result_id, status, is_error, exit_code, duration_ms,\n preview, stdout_object_id, stderr_object_id, output_object_id\n FROM tool_results WHERE session_id = ?`,\n )\n .all(sessionId)\n\n const resultByCallId = new Map<string, ToolResultRow>()\n for (const r of toolResults) {\n if (!r.tool_call_id) continue\n resultByCallId.set(r.tool_call_id, r)\n }\n\n // Group blocks under their owning message_id; orphan blocks (event-only)\n // are dropped from the per-turn view but kept reachable via raw queries.\n const blocksByMessage = new Map<string, BlockRow[]>()\n for (const b of blocks) {\n if (!b.message_id) continue\n const list = blocksByMessage.get(b.message_id) ?? []\n list.push(b)\n blocksByMessage.set(b.message_id, list)\n }\n\n const callsByMessage = new Map<string, ToolCallRow[]>()\n const unattached: ToolCallRow[] = []\n for (const c of toolCalls) {\n if (c.message_id == null) {\n unattached.push(c)\n continue\n }\n const list = callsByMessage.get(c.message_id) ?? []\n list.push(c)\n callsByMessage.set(c.message_id, list)\n }\n\n const turns: TranscriptTurn[] = []\n for (const m of messages) {\n const mblocks = (blocksByMessage.get(m.message_id) ?? []).sort((a, b) => a.ordinal - b.ordinal)\n const renderedBlocks: TranscriptBlock[] = []\n for (const b of mblocks) {\n renderedBlocks.push(await renderBlock(bundle, b, maxInlineBytes))\n }\n\n const mcalls = (callsByMessage.get(m.message_id) ?? []).sort((a, b) => {\n const ta = a.timestamp_start ?? ''\n const tb = b.timestamp_start ?? ''\n if (ta !== tb) return ta < tb ? -1 : 1\n return a.tool_call_id < b.tool_call_id ? -1 : a.tool_call_id > b.tool_call_id ? 1 : 0\n })\n const renderedCalls: TranscriptToolCall[] = []\n for (const c of mcalls) {\n renderedCalls.push(\n await renderToolCall(bundle, c, resultByCallId.get(c.tool_call_id) ?? null, maxArgsInlineBytes),\n )\n }\n\n turns.push({\n messageId: m.message_id,\n ordinal: m.ordinal,\n role: m.role as TranscriptTurn['role'],\n model: m.model,\n timestamp: m.timestamp,\n blocks: renderedBlocks,\n toolCalls: renderedCalls,\n })\n }\n\n const unattachedRendered: TranscriptToolCall[] = []\n for (const c of unattached) {\n unattachedRendered.push(\n await renderToolCall(bundle, c, resultByCallId.get(c.tool_call_id) ?? null, maxArgsInlineBytes),\n )\n }\n\n return { session, turns, unattachedToolCalls: unattachedRendered }\n}\n\n/**\n * Resolve a block's printable text. Returns null when neither inline nor CAS\n * has a body; returns null `text` (but keeps `textObjectId`) when the CAS\n * blob exceeds `maxInlineBytes` so renderers can fetch on demand.\n *\n * Exported so the markdown exporter can share the same resolution path.\n */\nexport async function resolveBlockText(\n bundle: Bundle,\n block: { text_inline: string | null; text_object_id: string | null },\n maxInlineBytes: number = DEFAULT_MAX_INLINE_BYTES,\n): Promise<{ text: string | null; textObjectId: string | null; unavailable: boolean }> {\n if (block.text_inline != null) {\n return { text: block.text_inline, textObjectId: block.text_object_id, unavailable: false }\n }\n if (block.text_object_id) {\n try {\n const resolved = await getText(bundle, block.text_object_id)\n if (Buffer.byteLength(resolved, 'utf8') > maxInlineBytes) {\n return { text: null, textObjectId: block.text_object_id, unavailable: false }\n }\n return { text: resolved, textObjectId: block.text_object_id, unavailable: false }\n } catch {\n return { text: null, textObjectId: block.text_object_id, unavailable: true }\n }\n }\n return { text: null, textObjectId: null, unavailable: false }\n}\n\n/**\n * Resolve a tool call's args JSON. Returns null when the blob is missing or\n * exceeds `maxBytes`; the caller keeps the object id for \"show full\" UX.\n *\n * Exported so the markdown exporter can share the same resolution path.\n */\nexport async function resolveArgsText(\n bundle: Bundle,\n argsObjectId: ObjectId | null,\n maxBytes: number = DEFAULT_MAX_ARGS_INLINE_BYTES,\n): Promise<string | null> {\n if (!argsObjectId) return null\n try {\n const text = await getText(bundle, argsObjectId)\n if (Buffer.byteLength(text, 'utf8') > maxBytes) return null\n return text\n } catch {\n return null\n }\n}\n\nasync function renderBlock(bundle: Bundle, b: BlockRow, maxInlineBytes: number): Promise<TranscriptBlock> {\n const resolved = await resolveBlockText(bundle, b, maxInlineBytes)\n // Surface CAS-fetch failure as an explicit marker so renderers can decide\n // whether to dim or annotate the block; we keep textObjectId for retry.\n const text = resolved.unavailable ? `[content unavailable: ${b.text_object_id}]` : resolved.text\n return {\n blockId: b.block_id,\n blockType: b.block_type,\n text,\n textObjectId: resolved.textObjectId,\n hidden: b.visibility === 'hidden_by_default',\n mimeType: b.mime_type,\n isError: b.is_error === 1,\n }\n}\n\nasync function renderToolCall(\n bundle: Bundle,\n c: ToolCallRow,\n r: ToolResultRow | null,\n maxArgsInlineBytes: number,\n): Promise<TranscriptToolCall> {\n const argsInline = await resolveArgsText(bundle, c.args_object_id, maxArgsInlineBytes)\n return {\n toolCallId: c.tool_call_id,\n toolName: c.tool_name,\n canonicalToolType: c.canonical_tool_type,\n argsInline,\n argsObjectId: c.args_object_id,\n command: c.command,\n path: c.path,\n status: c.status,\n timestampStart: c.timestamp_start,\n result: r\n ? {\n toolResultId: r.tool_result_id,\n status: r.status,\n isError: r.is_error === 1,\n exitCode: r.exit_code,\n durationMs: r.duration_ms,\n preview: r.preview,\n stdoutObjectId: r.stdout_object_id,\n stderrObjectId: r.stderr_object_id,\n outputObjectId: r.output_object_id,\n }\n : null,\n }\n}\n","import type { Bundle } from '../../core/bundle.js'\nimport { loadTranscript } from '../transcript.js'\nimport type { TranscriptToolCall } from '../transcript.js'\n\n/**\n * Render a session into Markdown. Big tool outputs aren't dumped inline:\n * we show a preview line plus a `[object: blake3:…]` reference, leaving the\n * raw bytes in the CAS for downstream tools.\n *\n * Built on top of {@link loadTranscript} so the CLI's `session show --format\n * markdown` path and `prosa export session --format markdown` share one\n * resolution pipeline (inline + CAS text + tool result preview).\n */\nexport async function exportSessionMarkdown(bundle: Bundle, sessionId: string): Promise<string> {\n // We resolve full text bodies for markdown export so the dumped file is\n // self-contained; bump the inline budget high enough to avoid truncation\n // on the same blocks the previous renderer would have inlined.\n const transcript = await loadTranscript(bundle, sessionId, { maxInlineBytes: Number.MAX_SAFE_INTEGER })\n if (!transcript) {\n throw new Error(`session not found: ${sessionId}`)\n }\n\n const session = transcript.session\n const lines: string[] = []\n const title = session.title?.trim() || `${session.source_tool} session ${session.source_session_id}`\n lines.push(`# ${title}`, '')\n lines.push(`- **source**: ${session.source_tool}`)\n lines.push(`- **session_id**: \\`${session.session_id}\\``)\n lines.push(`- **source_session_id**: \\`${session.source_session_id}\\``)\n if (session.start_ts) lines.push(`- **start**: ${session.start_ts}`)\n if (session.end_ts) lines.push(`- **end**: ${session.end_ts}`)\n if (session.cwd_initial) lines.push(`- **cwd**: \\`${session.cwd_initial}\\``)\n if (session.git_branch_initial) lines.push(`- **git branch**: ${session.git_branch_initial}`)\n if (session.model_first || session.model_last) {\n lines.push(`- **models**: ${session.model_first ?? '?'} → ${session.model_last ?? session.model_first ?? '?'}`)\n }\n lines.push(`- **timeline confidence**: ${session.timeline_confidence}`)\n lines.push('')\n\n for (const turn of transcript.turns) {\n const ts = turn.timestamp ? ` · ${turn.timestamp}` : ''\n const model = turn.model ? ` · ${turn.model}` : ''\n lines.push(`## ${turn.role}${model}${ts}`, '')\n\n for (const block of turn.blocks) {\n // Preserve historical markdown behavior: skip blocks the old query\n // filtered out (`visibility='default'`-only) and drop blocks with no\n // resolved text payload.\n if (block.hidden) continue\n if (block.text == null) continue\n lines.push(block.text, '')\n }\n\n for (const call of turn.toolCalls) {\n lines.push(renderToolCallMarkdown(call), '')\n }\n }\n\n // Tool calls that didn't bind to any specific message (legacy / event-only).\n if (transcript.unattachedToolCalls.length > 0) {\n lines.push('## tool calls (unattached)', '')\n for (const call of transcript.unattachedToolCalls) {\n lines.push(renderToolCallMarkdown(call), '')\n }\n }\n\n return `${lines.join('\\n')}\\n`\n}\n\n/** Renders command, path, status, and preview for one Markdown tool-call block. */\nfunction renderToolCallMarkdown(c: TranscriptToolCall): string {\n const status = c.status ? ` · ${c.status}` : ''\n const errFlag = c.result?.isError ? ' · ERROR' : ''\n const lines: string[] = []\n lines.push(`### tool: ${c.toolName}${status}${errFlag}`)\n if (c.command) {\n lines.push('```sh', c.command, '```')\n }\n if (c.path) lines.push(`*path:* \\`${c.path}\\``)\n if (c.result?.preview) {\n lines.push('```')\n lines.push(c.result.preview)\n lines.push('```')\n }\n return lines.join('\\n')\n}\n","import type { SessionTranscript, TranscriptBlock, TranscriptToolCall, TranscriptTurn } from './transcript.js'\n\n/** Options controlling the textual transcript rendering. */\nexport interface FormatTranscriptTextOptions {\n /** When true, thinking blocks are rendered in full. Default false. */\n showThinking?: boolean\n /** Max preview/output lines to keep per tool result; over-long output is truncated. */\n maxOutputLines?: number\n /**\n * Accepted for source-compat with prior releases. Ignored: this formatter\n * always emits plain text (no ANSI escapes) so piped output stays clean.\n * Callers that want colored interactive output should use Ink directly\n * (apps/cli ships `renderTranscriptInk`).\n */\n color?: boolean\n}\n\nconst DEFAULT_MAX_OUTPUT_LINES = 40\n\n/**\n * Render a `SessionTranscript` as plaintext. Output is always ANSI-free so it\n * round-trips through pipes (`prosa session show --format text > file.txt`).\n *\n * Layout: a metadata header (title, ids, models, confidence), then one section\n * per turn with a role header and inline blocks/tool-call summaries. Thinking\n * blocks collapse to one line by default; tool outputs truncate at\n * `maxOutputLines` and surface CAS object ids for full retrieval downstream.\n */\nexport function formatTranscriptText(transcript: SessionTranscript, options: FormatTranscriptTextOptions = {}): string {\n const showThinking = options.showThinking ?? false\n const maxOutputLines = options.maxOutputLines ?? DEFAULT_MAX_OUTPUT_LINES\n\n const out: string[] = []\n out.push(...renderHeader(transcript))\n\n for (const turn of transcript.turns) {\n out.push('')\n out.push(...renderTurn(turn, { showThinking, maxOutputLines }))\n }\n\n if (transcript.unattachedToolCalls.length > 0) {\n out.push('')\n out.push('── tool calls (unattached) ──')\n for (const call of transcript.unattachedToolCalls) {\n out.push(...renderToolCallLines(call, '', { maxOutputLines }))\n }\n }\n\n return `${out.join('\\n')}\\n`\n}\n\nfunction renderHeader(transcript: SessionTranscript): string[] {\n const s = transcript.session\n const title = s.title?.trim() || `${s.source_tool} session ${s.source_session_id}`\n const lines: string[] = []\n lines.push(`# ${title}`)\n lines.push(`source: ${s.source_tool}`)\n lines.push(`session_id: ${s.session_id}`)\n lines.push(`source_id: ${s.source_session_id}`)\n if (s.start_ts) lines.push(`start: ${s.start_ts}`)\n if (s.end_ts) lines.push(`end: ${s.end_ts}`)\n if (s.model_first || s.model_last) {\n lines.push(`models: ${s.model_first ?? '?'} → ${s.model_last ?? s.model_first ?? '?'}`)\n }\n lines.push(`confidence: ${s.timeline_confidence}`)\n return lines\n}\n\nfunction renderTurn(turn: TranscriptTurn, ctx: { showThinking: boolean; maxOutputLines: number }): string[] {\n const lines: string[] = []\n const meta: string[] = []\n if (turn.model) meta.push(turn.model)\n if (turn.timestamp) meta.push(turn.timestamp)\n const metaSuffix = meta.length > 0 ? ` · ${meta.join(' · ')}` : ''\n lines.push(`[${turn.role}]${metaSuffix}`)\n\n for (const block of turn.blocks) {\n lines.push(...renderBlock(block, ctx))\n }\n for (const call of turn.toolCalls) {\n lines.push(...renderToolCallLines(call, ' ', { maxOutputLines: ctx.maxOutputLines }))\n }\n return lines\n}\n\nfunction renderBlock(block: TranscriptBlock, ctx: { showThinking: boolean; maxOutputLines: number }): string[] {\n const isThinking = block.hidden || block.blockType === 'thinking'\n if (isThinking && !ctx.showThinking) {\n const charCount = block.text ? block.text.length : 0\n return [` ▶ thinking (≈${charCount} chars)`]\n }\n\n if (block.text == null) {\n // Body wasn't inlined (oversize) or block has no text payload.\n if (block.textObjectId) {\n return [` ▶ ${block.blockType} (oversize; objectId=${block.textObjectId})`]\n }\n return []\n }\n\n return block.text.split('\\n').map((l) => ` ${l}`)\n}\n\nfunction renderToolCallLines(call: TranscriptToolCall, indent: string, ctx: { maxOutputLines: number }): string[] {\n const lines: string[] = []\n const statusBits: string[] = []\n if (call.status) statusBits.push(call.status)\n if (call.result?.isError) statusBits.push('ERROR')\n const statusSuffix = statusBits.length > 0 ? ` [${statusBits.join(' · ')}]` : ''\n lines.push(`${indent}▶ tool: ${call.toolName}${statusSuffix}`)\n\n if (call.command) {\n lines.push(`${indent} $ ${call.command}`)\n }\n if (call.path) {\n lines.push(`${indent} path: ${call.path}`)\n }\n if (call.argsInline) {\n const argsLines = call.argsInline.split('\\n')\n const shown = argsLines.slice(0, ctx.maxOutputLines)\n for (const l of shown) lines.push(`${indent} ${l}`)\n if (argsLines.length > ctx.maxOutputLines) {\n lines.push(\n `${indent} … (${argsLines.length - ctx.maxOutputLines} more lines; use --max-output-lines or open via objectId=${call.argsObjectId ?? '?'})`,\n )\n }\n } else if (call.argsObjectId) {\n lines.push(`${indent} args: objectId=${call.argsObjectId} (oversize)`)\n }\n\n if (call.result?.preview) {\n const previewLines = call.result.preview.split('\\n')\n const shown = previewLines.slice(0, ctx.maxOutputLines)\n lines.push(`${indent} ─ result ─`)\n for (const l of shown) lines.push(`${indent} ${l}`)\n if (previewLines.length > ctx.maxOutputLines) {\n const objectId = call.result.outputObjectId ?? call.result.stdoutObjectId ?? call.result.stderrObjectId\n lines.push(\n `${indent} … (${previewLines.length - ctx.maxOutputLines} more lines; use --max-output-lines or open via objectId=${objectId ?? '?'})`,\n )\n }\n } else if (call.result?.outputObjectId || call.result?.stdoutObjectId) {\n const objectId = call.result.outputObjectId ?? call.result.stdoutObjectId\n lines.push(`${indent} result objectId=${objectId}`)\n }\n\n return lines\n}\n","/** System instructions advertised by the MCP server to guide evidence-first use of prosa tools. */\nexport const PROSA_MCP_INSTRUCTIONS = `\nprosa is a local memory over local agent session histories. Use it to find prior work, commands,\ndecisions, file touches, transcripts, and analytical rollups before answering from memory.\n\nThere are six tools:\n- search: full-text over messages, commands, paths, diffs, and previews. Start here for open-ended\n questions with 2-5 concrete terms. Optional engine, field_kind, raw, since/until filters.\n- sessions: without session_id, lists candidates filtered by source/time/limit. With session_id,\n opens the session: format=detail (default) returns metadata + timeline, format=summary returns\n only the session row, format=markdown renders the full transcript.\n- tool_calls: audit commands and tool usage. Filters by tool_name, canonical_type, session_id,\n errors_only. When path_substring is set, also returns artifacts touching that path — use this for\n file-history questions.\n- analytics: built-in aggregate reports backed by SQLite views. Pick report=sessions|tools|errors|\n models|projects with the matching filters. Use report=sessions with session_id or\n source_path_substring for per-session metrics.\n- artifact: fetch full text for an artifact_id when previews are not enough. Binary artifacts return\n a placeholder.\n- compile: with no input, returns a status snapshot (search index health). With source (and\n optionally sessions_path), imports that provider into the bundle. Use status mode when search\n results look stale; use import mode when local sessions may not be indexed yet.\n\nWhen answering, cite concrete evidence: session_id, timestamp, tool/file path, and the relevant\nsnippet or event. Do not treat search snippets as the whole truth; open the session with\n\\`sessions session_id=… format=detail\\` when accuracy matters.\n`.trim()\n\n/** Prompt template for investigating prior sessions by topic. */\nexport const INVESTIGATE_PRIOR_WORK_PROMPT = `\nInvestigate prior work in prosa for the topic: {{topic}}\n\nUse this workflow:\n1. Call \\`search\\` with a short query built from the topic.\n2. If results are broad, search again with narrower terms from the best snippets.\n3. Open the most relevant session_ids with \\`sessions session_id=… format=detail\\`.\n4. Use \\`sessions session_id=… format=markdown\\` only for sessions that appear directly relevant.\n5. Answer with evidence: session_id, timestamp, and the decisive snippet or event.\n`.trim()\n\n/** Prompt template for tracing sessions and tool calls that touched a file or path. */\nexport const FIND_FILE_HISTORY_PROMPT = `\nInvestigate history for file/path: {{path}}\n\nUse this workflow:\n1. Call \\`tool_calls\\` with path_substring set to the path or its most distinctive suffix.\n2. Open returned session_ids with \\`sessions session_id=… format=detail\\`.\n3. Call \\`tool_calls\\` with session_id when you need command-level detail inside one session.\n4. Use \\`sessions session_id=… format=markdown\\` only for the most relevant session.\n5. Summarize what changed, who/what tool touched it, and cite session_id plus timestamp.\n`.trim()\n\n/** Prompt template for grouping failed tool calls and related context by likely cause. */\nexport const AUDIT_TOOL_FAILURES_PROMPT = `\nAudit tool failures in prosa{{query_clause}}.\n\nUse this workflow:\n1. For an aggregate report, call \\`analytics report=errors\\` (filter by source/since/until/tool_name\n as needed).\n2. For per-call evidence, call \\`tool_calls\\` with errors_only=true.\n3. If a query is provided, also call \\`search\\` for that query to find related context.\n4. Open relevant session_ids with \\`sessions session_id=… format=detail\\`.\n5. Group failures by tool_name, command/path, and likely cause.\n6. Answer with evidence: session_id, timestamp, command/path, exit code, and preview.\n`.trim()\n","import { randomUUID } from 'node:crypto'\nimport http from 'node:http'\nimport type { IncomingMessage, ServerResponse } from 'node:http'\nimport { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'\nimport { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js'\nimport type { Transport } from '@modelcontextprotocol/sdk/shared/transport.js'\nimport type { Bundle } from '../core/bundle.js'\nimport { getErrorMessage } from '../core/errors.js'\nimport { PROSA_PARSER_VERSION } from '../core/version.js'\nimport type { SearchEngine } from '../services/indexing.js'\nimport { PROSA_MCP_INSTRUCTIONS } from './guidance.js'\nimport { registerProsaTools } from './tools.js'\n\ninterface SessionEntry {\n server: McpServer\n transport: StreamableHTTPServerTransport\n}\n\n/** HTTP transport options for exposing a prosa bundle as an MCP server. */\nexport interface McpServerOptions {\n /** Hostname or IP address to bind. */\n host: string\n /** TCP port to bind. */\n port: number\n /** HTTP path that receives MCP Streamable HTTP requests. Defaults to `/mcp`. */\n path?: string\n /** Default search engine passed to MCP search tools. */\n searchEngine?: SearchEngine\n /** Bundle path reopened by long-lived tool handlers. Defaults to `bundle.path`. */\n storePath?: string\n}\n\n/** Handle returned by the HTTP MCP server listener. */\nexport interface RunningServer {\n /** Full URL clients should use for Streamable HTTP requests. */\n url: string\n /** Stop the HTTP listener and close all active MCP sessions. */\n close(): Promise<void>\n}\n\n/** Handle returned by the stdio MCP server listener. */\nexport interface RunningStdioServer {\n /** Close the MCP server and stdio transport. */\n close(): Promise<void>\n}\n\n/** Stdio transport options for exposing a prosa bundle as an MCP server. */\nexport interface McpStdioServerOptions {\n /** Default search engine passed to MCP search tools. */\n searchEngine?: SearchEngine\n /** Bundle path reopened by long-lived tool handlers. Defaults to `bundle.path`. */\n storePath?: string\n}\n\n/** Start a stdio MCP server backed by an already-open prosa bundle. */\nexport async function listenMcpStdioServer(\n bundle: Bundle,\n options: McpStdioServerOptions = {},\n): Promise<RunningStdioServer> {\n const server = createMcpServer(bundle, options.searchEngine ?? 'fts5', options.storePath)\n const transport = new StdioServerTransport()\n await server.connect(transport)\n\n return {\n close: async () => {\n await safeClose(server)\n await safeClose(transport)\n },\n }\n}\n\n/**\n * Bind an HTTP MCP server on `host:port` backed by `bundle`. Implements the\n * Streamable HTTP transport with stateful sessions (one McpServer per\n * `MCP-Session-Id`).\n *\n * - POST /mcp — JSON-RPC requests; opens a session if `MCP-Session-Id` is missing\n * - DELETE /mcp — close an existing session by header\n * - GET /mcp — 405 (we don't expose server-initiated SSE streams)\n */\nexport async function listenMcpServer(bundle: Bundle, options: McpServerOptions): Promise<RunningServer> {\n const mcpPath = options.path ?? '/mcp'\n const sessions = new Map<string, SessionEntry>()\n\n const searchEngine = options.searchEngine ?? 'fts5'\n const storePath = options.storePath ?? bundle.path\n\n const httpServer = http.createServer((req, res) => {\n handleRequest(req, res, mcpPath, sessions, bundle, searchEngine, storePath).catch((error: unknown) => {\n writeError(res, error)\n })\n })\n\n await new Promise<void>((resolve, reject) => {\n httpServer.once('error', reject)\n httpServer.listen(options.port, options.host, () => {\n httpServer.removeListener('error', reject)\n resolve()\n })\n })\n\n return {\n url: `http://${options.host}:${options.port}${mcpPath}`,\n close: async () => {\n await new Promise<void>((resolve, reject) => {\n httpServer.close((err) => (err ? reject(err) : resolve()))\n })\n for (const entry of sessions.values()) {\n await safeClose(entry.server)\n await safeClose(entry.transport)\n }\n sessions.clear()\n },\n }\n}\n\nasync function handleRequest(\n req: IncomingMessage,\n res: ServerResponse,\n mcpPath: string,\n sessions: Map<string, SessionEntry>,\n bundle: Bundle,\n searchEngine: SearchEngine,\n storePath: string,\n): Promise<void> {\n // Keep HTTP routing deliberately small: this listener owns exactly one MCP\n // endpoint and delegates protocol details to StreamableHTTPServerTransport.\n if (!req.url || !req.url.startsWith(mcpPath)) {\n res.writeHead(404).end()\n return\n }\n const method = req.method ?? 'GET'\n\n if (method === 'GET') {\n // Match the Sourcebot reference: we don't initiate SSE streams from the\n // server side, so GET is rejected per the MCP Streamable HTTP spec.\n res.writeHead(405, { Allow: 'POST, DELETE' }).end()\n return\n }\n if (method !== 'POST' && method !== 'DELETE') {\n res.writeHead(405, { Allow: 'POST, DELETE' }).end()\n return\n }\n\n const headerSessionId = req.headers['mcp-session-id']\n const sessionId =\n typeof headerSessionId === 'string'\n ? headerSessionId\n : Array.isArray(headerSessionId)\n ? headerSessionId[0]\n : undefined\n\n let entry: SessionEntry | undefined = sessionId ? sessions.get(sessionId) : undefined\n\n if (!entry) {\n if (method === 'DELETE') {\n res.writeHead(404).end()\n return\n }\n entry = await openSession(bundle, sessions, searchEngine, storePath)\n }\n\n const bodyText = await readBody(req)\n const body = bodyText.length > 0 ? safeJsonParse(bodyText) : undefined\n await entry.transport.handleRequest(req, res, body)\n}\n\n/** Create and connect a new MCP session, then let the transport register its generated id. */\nasync function openSession(\n bundle: Bundle,\n store: Map<string, SessionEntry>,\n searchEngine: SearchEngine,\n storePath: string,\n): Promise<SessionEntry> {\n // We need to assemble server + transport together because the transport's\n // `onsessioninitialized` callback wants to register both into the map.\n const server = createMcpServer(bundle, searchEngine, storePath)\n const transport = new StreamableHTTPServerTransport({\n sessionIdGenerator: () => randomUUID(),\n onsessioninitialized: (id: string) => {\n store.set(id, { server, transport })\n },\n onsessionclosed: async (id: string) => {\n const e = store.get(id)\n if (e) {\n await safeClose(e.server)\n await safeClose(e.transport)\n store.delete(id)\n }\n },\n })\n\n await server.connect(transport)\n return { server, transport }\n}\n\n/** Build a per-session MCP server instance with prosa instructions and tools attached. */\nfunction createMcpServer(bundle: Bundle, searchEngine: SearchEngine, storePath?: string): McpServer {\n const server = new McpServer(\n {\n name: 'prosa',\n version: PROSA_PARSER_VERSION,\n },\n { instructions: PROSA_MCP_INSTRUCTIONS },\n )\n registerProsaTools(server, bundle, { ensureStore: true, searchEngine, storePath })\n return server\n}\n\n/** Read a request body once so the MCP transport can consume a parsed JSON-RPC payload. */\nasync function readBody(req: IncomingMessage): Promise<string> {\n return new Promise((resolve, reject) => {\n const chunks: Buffer[] = []\n req.on('data', (chunk: Buffer) => chunks.push(chunk))\n req.on('end', () => resolve(Buffer.concat(chunks).toString('utf8')))\n req.on('error', reject)\n })\n}\n\n/** Parse optional JSON request bodies; invalid or empty bodies are passed through as undefined. */\nfunction safeJsonParse(text: string): unknown {\n try {\n return JSON.parse(text)\n } catch {\n return undefined\n }\n}\n\n/** Close transports and servers defensively during shutdown. */\nasync function safeClose(o: { close: () => Promise<void> | void } | Transport): Promise<void> {\n try {\n await o.close()\n } catch {\n /* ignore */\n }\n}\n\n/** Write a JSON-RPC internal error response when request handling fails before transport dispatch. */\nfunction writeError(res: ServerResponse, error: unknown): void {\n if (!res.headersSent) {\n res.writeHead(500, { 'Content-Type': 'application/json' })\n }\n res.end(\n JSON.stringify({\n jsonrpc: '2.0',\n error: { code: -32603, message: getErrorMessage(error) },\n id: null,\n }),\n )\n}\n","import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'\nimport { z } from 'zod'\nimport { type Bundle, closeBundle, openOrInitBundle } from '../core/bundle.js'\nimport { getText } from '../core/cas/index.js'\nimport { SOURCE_TOOLS } from '../core/domain/types.js'\nimport { getErrorMessage } from '../core/errors.js'\nimport { ANALYTICS_REPORTS, type AnalyticsReportFilters, runAnalyticsReportFromBundle } from '../services/analytics.js'\nimport { COMPILE_PROVIDERS, exportCompileParquet, getCompileProvider, runCompileImports } from '../services/compile.js'\nimport { exportSessionMarkdown } from '../services/export/markdown.js'\nimport { type SearchEngine, getSearchIndexStatuses } from '../services/indexing.js'\nimport { searchFullText } from '../services/search.js'\nimport { getSession, listSessions } from '../services/sessions.js'\nimport { listToolCalls } from '../services/tool_calls.js'\nimport { AUDIT_TOOL_FAILURES_PROMPT, FIND_FILE_HISTORY_PROMPT, INVESTIGATE_PRIOR_WORK_PROMPT } from './guidance.js'\n\n/** Options that tune how registered MCP tools open bundles and choose search backends. */\nexport interface ProsaToolOptions {\n /** Default search engine used when a `search` tool call does not specify one. */\n searchEngine?: SearchEngine\n /** Store path to reopen for each tool call when `ensureStore` is enabled. */\n storePath?: string\n /** Reopen or initialize the bundle per call instead of reusing the startup handle. */\n ensureStore?: boolean\n}\n\nconst CANONICAL_TOOL_TYPES = [\n 'shell',\n 'read_file',\n 'write_file',\n 'edit_file',\n 'search_file',\n 'web_search',\n 'mcp',\n 'subagent',\n 'patch',\n 'other',\n] as const\n\nconst FIELD_KINDS = [\n 'message_text',\n 'user_prompt',\n 'assistant_text',\n 'command',\n 'command_output_preview',\n 'error',\n 'file_path',\n 'diff',\n 'summary',\n 'artifact_text',\n 'tool_args',\n 'tool_result',\n] as const\n\n/**\n * Register the six prosa MCP tools on `server`. Five are read-only; `compile`\n * is dual-mode (no args = bundle status snapshot, with args = mutating import).\n */\nexport function registerProsaTools(server: McpServer, bundle: Bundle, options: ProsaToolOptions = {}): void {\n const searchEngine = options.searchEngine ?? 'fts5'\n const storePath = options.storePath ?? bundle.path\n const ensureStore = options.ensureStore ?? false\n registerProsaPrompts(server)\n\n server.registerTool(\n 'search',\n {\n title: 'Full-text search',\n description: `Search messages, commands, paths, diffs, and result previews using the server-selected ${searchEngine} engine. Start here for open-ended questions with 2-5 concrete terms; then call \\`sessions\\` for relevant hits.`,\n inputSchema: {\n query: z.string().min(1),\n engine: z.enum(['fts5', 'tantivy']).optional(),\n field_kind: z.enum(FIELD_KINDS).optional(),\n limit: z.number().int().min(1).max(500).optional().default(50),\n raw: z\n .boolean()\n .optional()\n .default(false)\n .describe('Pass query straight to FTS5 MATCH (allows OR/NEAR/prefixes).'),\n },\n annotations: { readOnlyHint: true, idempotentHint: true },\n },\n async ({ query, engine, field_kind, limit, raw }) =>\n withToolBundle(bundle, storePath, ensureStore, (activeBundle) => {\n const selectedEngine = engine ?? searchEngine\n const hits = searchFullText(activeBundle, {\n query,\n limit: limit ?? 50,\n raw,\n engine: selectedEngine,\n })\n const filtered = field_kind ? hits.filter((hit) => hit.field_kind === field_kind) : hits\n return {\n content: [\n {\n type: 'text',\n text: JSON.stringify(\n {\n query,\n engine: selectedEngine,\n field_kind: field_kind ?? null,\n count: filtered.length,\n hits: filtered,\n },\n null,\n 2,\n ),\n },\n ],\n }\n }),\n )\n\n server.registerTool(\n 'sessions',\n {\n title: 'List or open sessions',\n description:\n 'Without `session_id`, lists sessions filtered by source/time/limit. With `session_id`, opens that session: `format=detail` (default) returns metadata plus timeline events; `format=summary` returns only the session row; `format=markdown` renders the readable transcript. Call after `search` to get evidence behind a hit.',\n inputSchema: {\n session_id: z.string().min(1).optional(),\n format: z.enum(['summary', 'detail', 'markdown']).optional().default('detail'),\n source: z.enum(SOURCE_TOOLS).optional(),\n since: z.string().optional().describe('ISO timestamp lower bound (inclusive)'),\n until: z.string().optional().describe('ISO timestamp upper bound (exclusive)'),\n limit: z.number().int().min(1).max(500).optional().default(50),\n },\n annotations: { readOnlyHint: true, idempotentHint: true },\n },\n async ({ session_id, format, source, since, until, limit }) =>\n withToolBundle(bundle, storePath, ensureStore, async (activeBundle) => {\n if (!session_id) {\n const rows = listSessions(activeBundle, {\n sourceTool: source,\n sinceIso: since,\n untilIso: until,\n limit: limit ?? 50,\n })\n return {\n content: [{ type: 'text', text: JSON.stringify(rows, null, 2) }],\n }\n }\n\n if (format === 'markdown') {\n try {\n const md = await exportSessionMarkdown(activeBundle, session_id)\n return { content: [{ type: 'text', text: md }] }\n } catch (error) {\n return {\n content: [{ type: 'text', text: getErrorMessage(error) }],\n isError: true,\n }\n }\n }\n\n const detail = getSession(activeBundle, session_id)\n if (!detail) {\n return {\n content: [{ type: 'text', text: `session not found: ${session_id}` }],\n isError: true,\n }\n }\n const payload = format === 'summary' ? { session: detail.session } : detail\n return {\n content: [{ type: 'text', text: JSON.stringify(payload, null, 2) }],\n }\n }),\n )\n\n server.registerTool(\n 'tool_calls',\n {\n title: 'Audit tool calls and file touches',\n description:\n 'Audit commands and tool usage. Filter by tool_name, canonical_type, session_id, errors_only, or path_substring. When `path_substring` is set, also surfaces matching artifacts so file-history questions return both invocations and produced files.',\n inputSchema: {\n session_id: z.string().min(1).optional(),\n tool_name: z.string().optional(),\n canonical_type: z.enum(CANONICAL_TOOL_TYPES).optional(),\n path_substring: z\n .string()\n .min(1)\n .optional()\n .describe('Filter rows where tool_calls.path or artifacts.path contains this substring.'),\n errors_only: z.boolean().optional().default(false),\n since: z.string().optional().describe('ISO timestamp lower bound (inclusive)'),\n until: z.string().optional().describe('ISO timestamp upper bound (exclusive)'),\n limit: z.number().int().min(1).max(500).optional().default(100),\n },\n annotations: { readOnlyHint: true, idempotentHint: true },\n },\n async (input) =>\n withToolBundle(bundle, storePath, ensureStore, (activeBundle) => {\n const rows = listToolCalls(activeBundle, {\n sessionId: input.session_id,\n toolName: input.tool_name,\n canonicalType: input.canonical_type,\n pathSubstring: input.path_substring,\n errorsOnly: input.errors_only,\n sinceIso: input.since,\n untilIso: input.until,\n limit: input.limit ?? 100,\n })\n return {\n content: [{ type: 'text', text: JSON.stringify(rows, null, 2) }],\n }\n }),\n )\n\n server.registerTool(\n 'analytics',\n {\n title: 'Aggregate analytics reports',\n description:\n 'Run a built-in aggregation over the bundle: per-session metrics (`sessions`), tool usage rollup (`tools`), error timeline (`errors`), model usage (`models`), or project activity (`projects`). Backed by SQLite views; mirrors the `prosa analytics` CLI.',\n inputSchema: {\n report: z.enum(ANALYTICS_REPORTS),\n source: z.enum(SOURCE_TOOLS).optional(),\n since: z.string().optional().describe('ISO timestamp lower bound (inclusive)'),\n until: z.string().optional().describe('ISO timestamp upper bound (exclusive)'),\n limit: z.number().int().min(1).max(500).optional().default(50),\n session_id: z.string().min(1).optional().describe('Drill-down filter (applies to `sessions` report).'),\n source_path_substring: z\n .string()\n .min(1)\n .optional()\n .describe('Filter `sessions` rows by imported source file path substring.'),\n project: z.string().min(1).optional().describe('Filter by project id, name, or path substring.'),\n tool_name: z.string().min(1).optional().describe('Filter `tools`/`errors` rows by exact tool name.'),\n canonical_type: z.enum(CANONICAL_TOOL_TYPES).optional().describe('Filter `tools` rows by canonical tool type.'),\n errors_only: z.boolean().optional().describe('`tools` report: only error rows.'),\n category: z\n .string()\n .min(1)\n .optional()\n .describe('Filter `errors` by category: tool_result|import_error|uncertainty.'),\n model: z.string().min(1).optional().describe('Filter `models` rows by exact model name.'),\n },\n annotations: { readOnlyHint: true, idempotentHint: true },\n },\n async (input) =>\n withToolBundle(bundle, storePath, ensureStore, (activeBundle) => {\n const filters: AnalyticsReportFilters = {\n source: input.source,\n since: input.since,\n until: input.until,\n limit: input.limit,\n sessionId: input.session_id,\n sourcePathSubstring: input.source_path_substring,\n project: input.project,\n toolName: input.tool_name,\n canonicalType: input.canonical_type,\n errorsOnly: input.errors_only,\n category: input.category,\n model: input.model,\n }\n try {\n const result = runAnalyticsReportFromBundle({\n bundle: activeBundle,\n report: input.report,\n filters,\n })\n return {\n content: [\n {\n type: 'text',\n text: JSON.stringify({ report: input.report, count: result.rows.length, rows: result.rows }, null, 2),\n },\n ],\n }\n } catch (error) {\n return {\n content: [{ type: 'text', text: getErrorMessage(error) }],\n isError: true,\n }\n }\n }),\n )\n\n server.registerTool(\n 'artifact',\n {\n title: 'Get artifact bytes/text',\n description:\n 'Retrieve full text for an `artifact_id` referenced in a session, search hit, or tool_calls row. Use this when previews are not enough; binary artifacts return a placeholder.',\n inputSchema: {\n artifact_id: z.string().min(1),\n },\n annotations: { readOnlyHint: true, idempotentHint: true },\n },\n async ({ artifact_id }) =>\n withToolBundle(bundle, storePath, ensureStore, async (activeBundle) => {\n const row = activeBundle.db\n .prepare<[string], { text_object_id: string | null; object_id: string | null; mime_type: string | null }>(\n `SELECT text_object_id, object_id, mime_type FROM artifacts WHERE artifact_id = ?`,\n )\n .get(artifact_id)\n if (!row) {\n return {\n content: [{ type: 'text', text: `artifact not found: ${artifact_id}` }],\n isError: true,\n }\n }\n const objectId = row.text_object_id ?? row.object_id\n if (!objectId) {\n return { content: [{ type: 'text', text: '[no content stored]' }] }\n }\n try {\n const text = await getText(activeBundle, objectId)\n return { content: [{ type: 'text', text }] }\n } catch {\n return { content: [{ type: 'text', text: `[binary artifact: ${objectId}]` }] }\n }\n }),\n )\n\n server.registerTool(\n 'compile',\n {\n title: 'Compile sessions or report bundle status',\n description:\n 'Without input, returns a status snapshot (search index health, last batch, schema version) without mutating anything. With `source`, imports that provider; `sessions_path` may override its default. Pass `overwrite: true` to force a full rebuild of derived indexes (Tantivy from scratch). With neither `source` nor `sessions_path`, only status is returned.',\n inputSchema: {\n source: z.enum(SOURCE_TOOLS).optional(),\n sessions_path: z.string().min(1).optional(),\n overwrite: z.boolean().optional(),\n },\n annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: true },\n },\n async ({ source, sessions_path, overwrite }) =>\n withToolBundle(bundle, storePath, ensureStore, async (activeBundle) => {\n if (sessions_path && !source) {\n return {\n content: [\n {\n type: 'text',\n text: 'sessions_path requires source because providers use incompatible source layouts',\n },\n ],\n isError: true,\n }\n }\n\n if (!source && !sessions_path) {\n return {\n content: [\n {\n type: 'text',\n text: JSON.stringify({ mode: 'status', search_index: getSearchIndexStatuses(activeBundle) }, null, 2),\n },\n ],\n }\n }\n\n try {\n const result = await runCompileImports({\n bundle: activeBundle,\n providers: source ? [getCompileProvider(source)] : COMPILE_PROVIDERS,\n sessionsPath: sessions_path,\n overwrite,\n })\n const parquet = result.importedAny ? await exportCompileParquet({ storePath }) : null\n\n return {\n content: [\n {\n type: 'text',\n text: JSON.stringify(\n {\n mode: 'import',\n providers: result.providers.map((provider) => ({\n source: provider.source,\n source_path: provider.sourcePath,\n batch_id: provider.batchId,\n counts: provider.counts,\n })),\n imported_any: result.importedAny,\n tantivy: result.tantivy ? { indexed_doc_count: result.tantivy.indexedDocCount } : null,\n tantivy_error: result.tantivyError,\n fts5_error: result.fts5Error,\n parquet: parquet\n ? {\n out_dir: parquet.outDir,\n manifest_path: parquet.manifestPath,\n table_count: parquet.tableCount,\n files: parquet.files,\n counts: parquet.counts,\n }\n : null,\n search_index: getSearchIndexStatuses(activeBundle),\n },\n null,\n 2,\n ),\n },\n ],\n }\n } catch (error) {\n return {\n content: [{ type: 'text', text: getErrorMessage(error) }],\n isError: true,\n }\n }\n }),\n )\n}\n\nasync function withToolBundle<T>(\n fallbackBundle: Bundle,\n storePath: string,\n ensureStore: boolean,\n fn: (bundle: Bundle) => Promise<T> | T,\n): Promise<T> {\n // MCP servers can stay alive while the store is compiled elsewhere. Reopening\n // per call keeps schema/index changes visible without restarting the server.\n if (!ensureStore) {\n return await fn(fallbackBundle)\n }\n\n const bundle = await openOrInitBundle(storePath)\n try {\n return await fn(bundle)\n } finally {\n closeBundle(bundle)\n }\n}\n\n/** Register reusable MCP prompt templates alongside the callable prosa tools. */\nfunction registerProsaPrompts(server: McpServer): void {\n server.registerPrompt(\n 'investigate_prior_work',\n {\n title: 'Investigate prior work',\n description:\n 'Guide an agent through searching prosa for prior work on a topic, opening relevant sessions, and citing evidence.',\n argsSchema: {\n topic: z.string().min(1).describe('Topic, feature, error, command, or decision to investigate'),\n },\n },\n ({ topic }) => ({\n description: 'Search prosa for relevant prior work and answer with session evidence.',\n messages: [\n {\n role: 'user',\n content: {\n type: 'text',\n text: INVESTIGATE_PRIOR_WORK_PROMPT.replace('{{topic}}', topic),\n },\n },\n ],\n }),\n )\n\n server.registerPrompt(\n 'find_file_history',\n {\n title: 'Find file history',\n description:\n 'Guide an agent through finding sessions that touched a file/path and summarizing the relevant history.',\n argsSchema: {\n path: z.string().min(1).describe('File path, directory, or distinctive path suffix'),\n },\n },\n ({ path }) => ({\n description: 'Find sessions that touched a path and summarize the evidence.',\n messages: [\n {\n role: 'user',\n content: {\n type: 'text',\n text: FIND_FILE_HISTORY_PROMPT.replace('{{path}}', path),\n },\n },\n ],\n }),\n )\n\n server.registerPrompt(\n 'audit_tool_failures',\n {\n title: 'Audit tool failures',\n description: 'Guide an agent through finding failed tool calls and grouping them by likely cause.',\n argsSchema: {\n query: z.string().optional().describe('Optional topic, file, command, or error to narrow audit'),\n },\n },\n ({ query }) => ({\n description: 'Audit failed tool calls and cite operational evidence.',\n messages: [\n {\n role: 'user',\n content: {\n type: 'text',\n text: AUDIT_TOOL_FAILURES_PROMPT.replace('{{query_clause}}', query ? ` related to: ${query}` : ''),\n },\n },\n ],\n }),\n )\n}\n"],"mappings":"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","names":["constants","fsConstants","access","mkdir","readFile","stat","writeFile","os","path","Database","openDb","path","db","Database","pragma","closeDb","close","stmtCache","WeakMap","prepare","sql","cache","get","Map","set","stmt","transactional","fn","wrapped","transaction","SQL_001_INIT","String","raw","SQL_002_SEARCH_INDEX_STATUS","String","raw","SQL_003_ANALYTICS_VIEWS","String","raw","SQL_004_TANTIVY_CHECKPOINT","String","raw","SQL_005_OBJECT_TRANSPORT_HASH","String","raw","MIGRATIONS","version","name","sql","SQL_001_INIT","SQL_002_SEARCH_INDEX_STATUS","SQL_003_ANALYTICS_VIEWS","SQL_004_TANTIVY_CHECKPOINT","SQL_005_OBJECT_TRANSPORT_HASH","runMigrations","db","exec","applied","Set","prepare","all","map","row","newlyApplied","migration","has","tx","transaction","run","Date","toISOString","push","currentSchemaVersion","get","PROSA_PARSER_VERSION","packageJson","version","PROSA_SCHEMA_VERSION","BundleNotInitializedError","Error","bundlePath","reason","name","defaultBundlePath","env","process","PROSA_STORE","length","path","resolve","join","os","homedir","bundlePaths","rootPath","db","manifest","objects","rawSources","search","tantivy","exports","parquet","lock","exists","p","access","fsConstants","F_OK","initBundle","resolved","paths","mkdir","recursive","version","parser_version","PROSA_PARSER_VERSION","schema_version","PROSA_SCHEMA_VERSION","created_at","Date","toISOString","hash_alg","default_compression","writeFile","JSON","stringify","openDb","runMigrations","openBundle","dirStat","stat","catch","isDirectory","parse","readFile","currentVersion","currentSchemaVersion","closeDb","manifestDirty","openOrInitBundle","closeBundle","bundle","SOURCE_TOOLS","mkdir","readFile","writeFile","path","compress","zstdCompress","decompress","zstdDecompress","COMPRESS_THRESHOLD_BYTES","ZSTD_LEVEL","compressBytes","input","byteLength","bytes","Buffer","from","compression","out","zstdCompress","compressionLevel","decompressBytes","zstdDecompress","createHash","blake3","nobleBlake3","bytesToHex","wasmBlake3","blake3Hex","bytes","bytesToHex","nobleBlake3","blake3HexAsync","wasmBlake3","sha256Hex","createHash","update","digest","objectIdFromHash","hashHex","objectStoragePath","compression","ext","a","slice","b","ensuredDirs","Set","ensureDir","absoluteDir","has","mkdir","recursive","add","putBytes","bundle","bytes","options","hash","blake3HexAsync","objectId","objectIdFromHash","existing","prepare","db","get","stored","compression","compressBytes","storagePath","objectStoragePath","absolutePath","path","join","dirname","writeFile","run","byteLength","mimeType","encoding","Date","toISOString","putText","text","buf","Buffer","from","putJson","value","JSON","stringify","getBytes","meta","Error","readFile","storage_path","decompressBytes","getText","toString","getJson","parse","getObjectMeta","createPendingObjects","byId","Map","stageBytes","pending","isBuffer","blake3Hex","set","stageText","stageJson","flushPendingObjects","size","ids","keys","existingIds","queryExistingObjectIds","toWrite","obj","values","compressedBytes","push","staged","length","writeFilesParallel","transportHashes","Promise","all","map","p","insertObject","now","i","entries","found","CHUNK","start","slice","placeholders","rows","row","object_id","FS_WRITE_CONCURRENCY","tasks","cursor","workers","limit","Math","min","w","task","ID_PREFIX_BYTES","tupleId","parts","sha256Hex","join","slice","sourceFileId","sourceTool","absolutePath","contentHash","rawRecordId","ordinal","rawObjectId","String","sessionId","sourceSessionId","turnId","sourceTurnId","eventId","kind","messageId","sourceMsgId","blockId","messageOrEventId","toolCallId","sourceCallId","toolResultId","artifactId","key","projectId","sourceProjectId","importBatchId","startedAtIso","Math","random","emptyCounts","source_files_seen","source_files_imported","source_files_skipped","raw_records","sessions","turns","events","messages","content_blocks","tool_calls","tool_results","artifacts","edges","errors","startBatch","bundle","sourceTool","paths","startedAt","Date","toISOString","id","importBatchId","prepare","db","run","PROSA_PARSER_VERSION","JSON","stringify","batch_id","source_tool","parser_version","started_at","finishBatch","batch","counts","status","recordError","batchId","args","payloadObjectId","payload","undefined","putJson","sourceFileId","rawRecordId","kind","message","access","readFile","stat","writeFile","path","registerSourceFile","bundle","args","st","stat","absolutePath","size","mtime","toISOString","cheap","prepare","db","get","sourceTool","row","ensureSourceFilePreserved","alreadyKnown","buf","readFile","contentHash","sha256Hex","exact","objectId","preserveRawSourceBytes","id","sourceFileId","source_file_id","source_tool","path","file_kind","fileKind","size_bytes","content_hash","object_id","discovered_at","Date","workspace_hint","workspaceHint","run","bytes","sourceBytes","hash","blake3HexAsync","objectIdFromHash","stored","compression","compressBytes","storagePath","rawSourceStoragePath","join","ensureDir","dirname","fileExists","writeFile","existing","byteLength","hashHex","ext","filePath","access","clampLimit","value","opts","Math","max","min","fallback","sessionFilterWhere","filters","conds","params","sourceTool","push","sinceIso","untilIso","where","length","join","listSessions","bundle","limit","clampLimit","max","fallback","sql","db","prepare","all","countSessions","row","get","count","getSession","sessionId","rows","events","session","existsSync","createRequire","getErrorMessage","err","Error","message","String","createHash","existsSync","mkdir","rm","writeFile","path","SEARCH_INDEX_STATUS_COLUMNS","FTS5_TRIGGER_SQL","enableFts5Triggers","bundle","db","exec","disableFts5Triggers","getSearchIndexStatuses","ensureSearchIndexStatusRows","prepare","all","getSearchIndexStatus","engine","get","markIndexesAfterImport","options","changed","tantivy","status","updateSearchIndexStatus","sourceDocCount","countSearchDocs","indexedDocCount","indexed_doc_count","errorMessage","rebuildFts5Index","countFts5Docs","transactional","error","getErrorMessage","TANTIVY_SCHEMA_FIELDS","name","tokenizer","buildTantivySchema","builder","SchemaBuilder","field","addTextField","stored","tokenizerName","build","getCurrentTantivySchemaFingerprint","canonical","map","f","join","createHash","update","digest","tantivyIndexDirIsValid","dir","existsSync","path","makeTantivyDoc","row","doc","Document","addText","doc_id","entity_type","entity_id","session_id","project_id","timestamp","role","tool_name","canonical_tool_type","field_kind","text","SEARCH_DOCS_SELECT","rebuildTantivyIndex","prev","fingerprint","indexDirValid","paths","fingerprintMatches","schema_fingerprint","lastIndexedRowid","last_indexed_rowid","wantFullRebuild","overwrite","schema","index","rm","recursive","force","mkdir","Index","open","writer","select","addedDocCount","maxRowid","iterate","deleteDocumentsByTerm","addDocument","rowid","commit","reload","waitMergingThreads","countTantivyDocsBest","writeFile","JSON","stringify","source","built_at","Date","toISOString","mode","source_doc_count","schemaFingerprint","added","now","stmt","run","values","setClauses","params","undefined","push","n","require","createRequire","url","escapeFtsQuery","q","split","filter","t","length","map","replace","join","searchFullText","bundle","options","engine","searchTantivy","limit","clampLimit","max","fallback","sql","ftsQuery","raw","query","db","prepare","all","existsSync","paths","tantivy","Error","status","getSearchIndexStatus","queryText","trim","requireTantivy","index","Index","open","searcher","parseQuery","parseQueryLenient","undefined","text","result","search","snippets","SnippetGenerator","create","schema","setMaxNumChars","hits","hit","doc","docAddress","snippet","snippetFromDoc","getStoredText","renderedSnippet","fragment","highlightSnippet","highlighted","slice","doc_id","entity_type","entity_id","session_id","nullIfEmpty","timestamp","role","tool_name","field_kind","error","getErrorMessage","field","value","getFirst","Array","isArray","String","ranges","out","cursor","range","start","end","os","path","readFile","path","CANONICAL_TOOL_CALL_STATUSES","Set","normalizeSessionStatus","status","normalized","trim","toLowerCase","normalizeToolCallStatus","sourceTool","raw","has","readdir","path","discoverClaudeFiles","root","projectDirs","readdirSafe","project","isDirectory","projectRoot","path","join","name","walkProject","projectSlug","entries","entry","isFile","endsWith","filePath","isSubagent","parentSessionId","agentId","metaPath","subagentsDir","subagentEntries","sub","startsWith","slice","length","metaCandidate","metaExists","some","e","dir","readdir","withFileTypes","PREVIEW_MAX","compileClaude","bundle","root","options","logger","batch","startBatch","counts","emptyCounts","info","batch_id","file","discoverClaudeFiles","source_files_seen","debug","path","filePath","project_slug","projectSlug","is_subagent","isSubagent","fc","compileClaudeFile","addCounts","error","errors","warn","err","recordError","kind","message","getErrorMessage","payload","linkSubagentParents","finishBatch","db","exec","emptyFileCounts","source_files_imported","source_files_skipped","raw_records","sessions","turns","events","messages","content_blocks","tool_calls","tool_results","artifacts","edges","target","source","row","sourceFile","alreadyKnown","registerSourceFile","sourceTool","absolutePath","resolve","fileKind","workspaceHint","source_file_id","text","readFile","rawLines","split","lines","length","slice","meta","metaPath","readMeta","pending","rawRecords","session","blocks","toolCalls","Map","toolCallsList","toolResults","searchDocs","uuidToMessageId","objects","createPendingObjects","modelFirst","modelLast","messageOrdinal","sessionStartTs","sessionEndTs","cwdInitial","branchInitial","i","line","lineNo","ordinal","lineBytes","Buffer","from","rawObjectId","stageBytes","mimeType","encoding","parsed","parserStatus","JSON","parse","decodedObjectId","nativeId","uuid","rawRecordId","makeRawRecordId","push","raw_record_id","line_no","native_id","raw_object_id","decoded_json_object_id","parser_status","confidence","import_batch_id","ts","timestamp","cwd","gitBranch","sessionId","createSessionFromFirstRecord","parentSessionId","parentSid","makeSessionId","src_type","src_id","dst_type","dst_id","session_id","edge_type","parent_session_id_pending","basename","type","msgRole","role","inferRoleFromContent","msgOrdinal","messageId","makeMessageId","id","eventId","makeEventId","event_id","source_event_id","event_type","source_type","subtype","actor","payload_object_id","model","message_id","source_message_id","parent_message_id","parent_uuid","parentUuid","set","isSidechain","sourceToolAssistantUUID","content","block_id","blockId","block_type","text_object_id","text_inline","is_error","visibility","fullId","stageText","last","Array","isArray","bi","block","processContentBlock","progressType","data","attachment","isSnapshotUpdate","artifact_id","artifactId","snapshot","logical_path","object_id","mime_type","size_bytes","created_ts","m","has","parentId","get","start_ts","end_ts","cwd_initial","git_branch_initial","buildSearchDocs","flushPendingObjects","transactional","flushPending","sourceSid","composite","agentId","source_session_id","agent_role","agentType","agent_nickname","agentName","title","description","fallback","c","allToolResult","every","b","blockOrdinal","blkId","thinking","tu","sourceCallId","toolName","name","argsId","input","stageJson","command","inferCommandFromArgs","inferPathFromArgs","tcId","makeToolCallId","call","tool_call_id","source_call_id","tool_name","canonical_tool_type","canonicalToolType","args_object_id","query","timestamp_start","status","tr","tool_use_id","isError","stringifyOrNull","overflowId","matched","undefined","tool_result_id","makeToolResultId","normalizeToolCallStatus","exit_code","duration_ms","stdout_object_id","stderr_object_id","output_object_id","preview","lower","toLowerCase","startsWith","args","obj","cmd","file_path","absolute_path","value","stringify","blocksByMsg","list","blks","filter","map","join","trim","doc_id","entity_type","entity_id","field_kind","r","insertRaw","prepare","run","insertEvent","e","insertMessage","insertBlock","insertToolCall","insertToolResult","insertArtifact","a","insertEdge","insertSearch","d","readFile","path","readdir","path","discoverCodexSessions","root","walk","dir","entries","readdir","withFileTypes","entry","full","path","join","name","isDirectory","isFile","endsWith","PREVIEW_MAX","CODEX_PREPARE_CONCURRENCY","compileCodex","bundle","root","options","logger","batch","startBatch","counts","emptyCounts","info","batch_id","files","filePath","discoverCodexSessions","push","debug","path","source_files_seen","length","i","slice","processCodexBatch","linkSubagentParents","finishBatch","error","err","items","Promise","all","map","result","prepareCodexFile","prepared","fileCounts","prepareError","applyError","emptyFileCounts","item","transactional","db","applyCodexFile","errors","warn","recordError","kind","message","getErrorMessage","payload","addCounts","exec","source_files_imported","source_files_skipped","raw_records","sessions","turns","events","messages","content_blocks","tool_calls","tool_results","artifacts","edges","target","source","row","sourceFileRow","alreadyKnown","registerSourceFile","sourceTool","absolutePath","resolve","fileKind","source_file_id","text","readFile","rawLines","split","lines","pending","rawRecords","session","blocks","toolCalls","Map","toolCallsList","toolResults","searchDocs","objects","createPendingObjects","sessionStartTs","sessionEndTs","modelFirst","modelLast","messageOrdinal","turnOrdinal","line","lineNo","ordinal","lineBytes","Buffer","from","rawObjectId","stageBytes","mimeType","encoding","parsed","parserStatus","JSON","parse","decodedObjectId","nativeId","extractNativeId","rawRecordId","makeRawRecordId","raw_record_id","source_tool","record_kind","line_no","json_pointer","native_id","raw_object_id","decoded_json_object_id","parser_status","confidence","import_batch_id","ts","timestamp","type","meta","sourceSessionId","id","basename","sessionId","makeSessionId","sub","parseSubagent","parentSessionId","parent_thread_id","session_id","source_session_id","parent_session_id","is_subagent","agent_role","agent_nickname","title","start_ts","cwd_initial","cwd","git_branch_initial","git","branch","src_type","src_id","dst_type","dst_id","edge_type","tc","turnId","makeTurnId","turn_id","turn","source_turn_id","model","approval_policy","sandbox_policy","stringifyOrNull","effort","currentTurnId","ri","handleResponseItem","em","handleEventMsg","event_id","makeEventId","source_event_id","event_type","source_type","subtype","actor","payload_object_id","buildSearchDocs","flushPendingObjects","prep","flushPending","handleResponseItemMessage","ctx","payloadObjectId","nextMsgOrdinal","currentModel","role","mapMessageRole","msgOrdinal","messageId","makeMessageId","eventId","message_id","source_message_id","contentItems","Array","isArray","content","bi","blockType","block_id","blockId","block_type","text_object_id","text_inline","handleResponseItemFunctionCall","sourceCallId","call_id","toolName","name","toolCallId","makeToolCallId","argsObjectId","arguments","stageJson","command","inferCommandFromArgs","call","tool_call_id","source_call_id","tool_name","canonical_tool_type","canonicalToolType","args_object_id","inferPathFromArgs","query","timestamp_start","status","set","handleResponseItemFunctionCallOutput","outputText","output","outputObj","isRecord","isError","is_error","looksLikeError","matchedCall","get","undefined","tool_result_id","makeToolResultId","normalizeToolCallStatus","exit_code","duration_ms","stdout_object_id","stderr_object_id","output_object_id","preview","handleResponseItemPassthrough","RESPONSE_ITEM_HANDLERS","function_call","function_call_output","_bundle","handler","handleExecCommandEnd","stdoutId","stdout","stageText","stderrId","stderr","formatted_output","aggregated_output","exitCode","durationMs","duration","handlePatchApplyEnd","changes","Object","keys","artifact_id","artifactId","logical_path","object_id","mime_type","size_bytes","created_ts","handleMcpToolCallEnd","isMcpResultError","handleContextCompacted","handleEventMsgPassthrough","EVENT_MSG_HANDLERS","exec_command_end","patch_apply_end","mcp_tool_call_end","context_compacted","env","p","lower","toLowerCase","startsWith","args","obj","String","join","file_path","absolute_path","test","normalized","some","d","secs","nanos","Math","floor","value","stringify","subagent","thread_spawn","tso","parent","blocksByMsg","b","list","m","filter","doc_id","entity_type","entity_id","field_kind","c","r","insertRaw","prepare","run","insertSession","insertTurn","t","insertEvent","e","insertMessage","insertBlock","insertToolCall","insertToolResult","insertArtifact","a","insertEdge","insertSearch","path","Database","readdir","path","discoverCursorStores","root","workspaces","readdirSafe","ws","isDirectory","wsPath","path","join","name","agents","ag","dbPath","dbEntries","hasStoreDb","some","e","isFile","filePath","workspaceId","agentId","dir","readdir","withFileTypes","PREVIEW_MAX","compileCursor","bundle","root","options","logger","batch","startBatch","counts","emptyCounts","info","batch_id","store","discoverCursorStores","source_files_seen","debug","path","filePath","workspace_id","workspaceId","agent_id","agentId","fc","compileCursorStore","addCounts","error","errors","warn","err","recordError","kind","message","getErrorMessage","payload","finishBatch","emptyFileCounts","source_files_imported","source_files_skipped","raw_records","sessions","events","messages","content_blocks","tool_calls","tool_results","artifacts","edges","target","source","row","sourceFile","alreadyKnown","registerSourceFile","sourceTool","absolutePath","resolve","fileKind","workspaceHint","source_file_id","cdb","openCursorStoreReadOnly","pending","rawRecords","session","blocks","toolCalls","Map","toolCallsList","toolResults","searchDocs","objects","createPendingObjects","metaRow","prepare","get","meta","metaRawId","metaText","hexToUtf8","value","JSON","parse","metaObjId","stageBytes","Buffer","from","mimeType","encoding","makeRawRecordId","push","raw_record_id","ordinal","line_no","json_pointer","native_id","raw_object_id","decoded_json_object_id","parser_status","confidence","import_batch_id","record_kind","sourceSessionId","sessionPk","makeSessionId","startTs","createdAt","Date","toISOString","session_id","source_session_id","agent_role","mode","agent_nickname","name","title","start_ts","model","lastUsedModel","blobs","all","messageOrdinal","i","length","blob","blobObjectId","data","blobRawId","parsed","firstByte","looksJson","toString","id","stageJson","role","mapRole","messageId","makeMessageId","eventId","makeEventId","event_id","source_event_id","event_type","source_type","subtype","timestamp","actor","payload_object_id","message_id","source_message_id","content","pushTextBlock","Array","isArray","bi","item","processContentItem","reconcileUnfinishedToolCalls","buildSearchDocs","flushPendingObjects","transactional","db","flushPending","close","hex","blockType","text","rawRecordId","visibility","overflow","stageText","block_id","blockId","block_type","text_object_id","text_inline","slice","is_error","sessionId","t","type","sourceCallId","toolCallId","toolName","argsObjectId","args","tcId","makeToolCallId","call","tool_call_id","source_call_id","tool_name","canonical_tool_type","canonicalToolType","args_object_id","command","cwd","file_path","query","timestamp_start","status","set","stringifyOrNull","result","outputObjectId","isError","readIsError","matched","tool_result_id","makeToolResultId","normalizeToolCallStatus","output_object_id","preview","Database","fileMustExist","readonly","exp","experimental_content","lower","toLowerCase","startsWith","stringify","blocksByMsg","b","list","m","map","join","trim","doc_id","entity_type","entity_id","field_kind","tc","insertRaw","r","run","insertEvent","e","insertMsg","insertBlock","insertCall","c","insertResult","insertSearch","d","artifactId","readFile","path","readFile","readdir","path","discoverGeminiChats","root","entries","readdirSafe","entry","sort","a","b","name","localeCompare","isDirectory","projectRoot","readProjectRoot","path","join","chatsDir","chatEntries","c","isFile","startsWith","endsWith","filePath","projectDir","dir","text","readFile","replace","trim","readdir","withFileTypes","PREVIEW_MAX","compileGemini","bundle","root","options","logger","batch","startBatch","counts","emptyCounts","info","batch_id","file","discoverGeminiChats","source_files_seen","debug","path","filePath","project_dir","projectDir","project_root","projectRoot","fc","compileGeminiFile","addCounts","error","errors","warn","err","recordError","kind","message","getErrorMessage","payload","finishBatch","emptyFileCounts","source_files_imported","source_files_skipped","raw_records","sessions","events","messages","content_blocks","tool_calls","tool_results","artifacts","edges","target","source","row","sourceFile","alreadyKnown","registerSourceFile","sourceTool","absolutePath","resolve","fileKind","workspaceHint","source_file_id","text","readFile","parsed","JSON","parse","objects","createPendingObjects","fileObjectId","stageBytes","Buffer","from","mimeType","encoding","rootRawRecordId","makeRawRecordId","pending","rawRecords","raw_record_id","ordinal","line_no","json_pointer","native_id","sessionId","raw_object_id","decoded_json_object_id","parser_status","confidence","import_batch_id","record_kind","session","blocks","toolCallsList","toolResults","searchDocs","project","sourceSid","basename","sessionPk","makeSessionId","existingSession","prepare","db","get","session_id","source_session_id","sourceFileId","projectKey","projectHash","project_id","makeProjectId","canonical_path","source_project_id","start","startTime","end","lastUpdated","start_ts","end_ts","cwd_initial","title","summary","Array","isArray","i","length","msg","processMessage","buildSearchDocs","flushPendingObjects","transactional","flushPending","index","batchId","ts","timestamp","payloadId","stageJson","pointer","rawRecordId","push","id","type","role","messageId","makeMessageId","eventId","makeEventId","event_id","source_event_id","event_type","source_type","subtype","actor","payload_object_id","message_id","source_message_id","model","content","pushTextBlock","item","t","thoughts","th","subject","description","filter","Boolean","join","toolCalls","tc","processToolCall","blockOrdinal","blockType","visibility","overflowId","stageText","block_id","blockId","block_type","text_object_id","text_inline","slice","sourceCallId","toolName","name","toolCallId","makeToolCallId","argsObjectId","args","tool_call_id","source_call_id","tool_name","canonical_tool_type","canonicalToolType","args_object_id","command","cwd","dir_path","file_path","query","timestamp_start","status","normalizeToolCallStatus","isError","resultText","renderToolResultText","result","tool_result_id","makeToolResultId","is_error","output_object_id","preview","resultDisplay","rd","fileDiff","diffText","diffId","artifact_id","artifactId","logical_path","fileName","object_id","mime_type","size_bytes","created_ts","pushResultDisplayFileArtifact","field","suffix","objectId","byteLength","parts","r","functionResponse","response","rr","stringify","output","startsWith","blocksByMsg","Map","b","list","set","m","map","trim","doc_id","entity_type","entity_id","field_kind","tr","insertRaw","run","sha256Hex","Date","toISOString","insertEvent","e","insertMsg","insertBlock","insertCall","c","insertResult","insertArtifact","a","insertSearch","d","readFile","path","Database","access","readdir","path","discoverHermesSources","root","sessionsDir","path","resolve","stateDbCandidate","join","dirname","indexCandidate","entries","readdirSafe","jsonlFiles","jsonFiles","entry","isFile","full","name","endsWith","push","startsWith","stateDbPath","exists","indexPath","sort","filePath","access","dir","readdir","withFileTypes","PREVIEW_MAX","HIDDEN_BLOCK_ORDINAL_BASE","compileHermes","bundle","root","options","logger","batch","startBatch","counts","emptyCounts","info","batch_id","sources","discoverHermesSources","registered","candidates","stateDbPath","indexPath","jsonlFiles","length","jsonFiles","warn","sessionsDir","source_files_seen","sourceFile","registerHermesSourceFile","push","imported","debug","path","source_file_id","sourceFileId","readSqliteCandidates","error","recordHermesSourceError","err","filePath","readJsonlCandidate","readJsonCandidate","selection","selectCandidates","pending","buildPending","selected","rejected","filter","flushPendingObjects","objects","transactional","db","flushPending","raw_records","rawRecords","sessions","events","messages","content_blocks","blocks","tool_calls","toolCalls","tool_results","toolResults","artifacts","edges","finishBatch","errors","recordError","kind","message","getErrorMessage","payload","absolutePath","fileKind","row","alreadyKnown","registerSourceFile","sourceTool","resolve","source_files_skipped","source_files_imported","dbPath","Database","readonly","fileMustExist","prepare","all","messagesBySession","Map","list","get","session_id","set","map","session","source","sourceSessionId","id","model","systemPrompt","system_prompt","parentSessionId","parent_session_id","startTs","unixToIso","started_at","endTs","ended_at","status","end_reason","title","rawPayload","index","normalizeSqliteMessage","close","ordinal","sourceMessageId","String","role","content","decodeMaybeJson","timestamp","toolCallId","tool_call_id","toolName","tool_name","tokenCount","token_count","finishReason","finish_reason","reasoning","reasoningContent","reasoning_content","reasoningDetails","reasoning_details","codexReasoningItems","codex_reasoning_items","codexMessageItems","codex_message_items","lineNo","text","readFile","basename","lines","split","i","line","trim","parsed","JSON","parse","normalizeTranscriptMessage","firstString","at","replace","Array","isArray","platform","coerceTimestamp","session_start","last_updated","candidate","existing","values","importedSources","projects","searchDocs","createPendingObjects","candidateSourceIds","Set","has","objectId","stageJson","raw_record_id","makeRawRecordId","line_no","json_pointer","native_id","raw_object_id","decoded_json_object_id","parser_status","confidence","import_batch_id","record_kind","stageCandidate","stageRejectedCandidate","buildSearchDocs","payloadId","sessionPk","makeSessionId","sessionPayloadId","sessionRawId","projectId","makeProjectId","project_id","source_project_id","display_name","models","Boolean","source_session_id","is_subagent","start_ts","end_ts","model_first","model_last","normalizeSessionStatus","rawRecordId","messageId","makeMessageId","message_id","event_id","source_message_id","pushTextBlock","toolCallsBySourceId","stageMessage","batchId","makeEventId","source_event_id","event_type","source_type","subtype","actor","payload_object_id","mapRole","eventId","renderContentText","pushHiddenBlock","call","parseToolCalls","entries","sourceCallId","getToolCallSourceId","getToolName","args","getToolArgs","makeToolCallId","pendingCall","source_call_id","canonical_tool_type","canonicalToolType","args_object_id","command","stringField","query","timestamp_start","normalizeToolCallStatus","outputObjectId","stageText","normalizeToolResultStatus","tool_result_id","makeToolResultId","is_error","output_object_id","preview","slice","sessionId","blockType","visibility","block_id","blockId","block_type","text_object_id","text_inline","hidden","offset","value","projectIdBySession","block","join","doc_id","entity_type","entity_id","field_kind","result","insertRaw","record","run","existingSession","deleteSessionProjection","insertProject","project","Date","toISOString","insertSession","insertEvent","event","insertMessage","insertBlock","insertCall","insertResult","insertSearch","doc","Number","isFinite","isToolError","hasErrorMarker","test","some","isRecord","toLowerCase","type","trimmed","startsWith","item","stringify","decoded","fallback","fn","function","arguments","input","lowered","includes","key","find","mkdir","rm","writeFile","path","DuckDBConnection","PARQUET_TABLES","ANALYTICS_VIEWS","exportBundleParquet","options","snapshot","openBundleSnapshot","bundlePath","outDir","path","resolve","defaultOutDir","mkdir","recursive","files","Object","fromEntries","map","table","join","manifestPath","file","values","rm","force","connection","createDuckDbConnection","attachSqlite","dbPath","run","quoteIdentifier","sqlString","closeSync","manifest","exported_at","Date","toISOString","source_db","schema_version","schemaVersion","parser_version","parserVersion","tables","basename","rows","counts","writeFile","JSON","stringify","queryDuckDbParquet","parquetDir","createAnalyticsViews","reader","runAndReadAll","sql","columns","deduplicatedColumnNames","getRowObjectsJson","error","isMissingParquetError","Error","DuckDBConnection","create","getErrorMessage","bundle","openBundle","row","db","prepare","get","n","paths","parquet","closeBundle","value","replace","message","test","COMPILE_PROVIDERS","name","description","pathHelp","defaultSessionsPath","path","join","os","homedir","compile","compileCodex","compileClaude","compileGemini","compileCursor","compileHermes","getCompileProvider","source","provider","find","p","Error","resolveCompilePath","basePath","process","env","INIT_CWD","cwd","startsWith","slice","isAbsolute","resolve","runCompileImports","options","bundle","providers","logger","overwrite","importedAny","summaries","tantivy","tantivyError","fts5Error","sweep","db","prepare","run","changes","warn","batches_reaped","info","disableFts5Triggers","sourcePath","sessionsPath","providerLogger","child","source_tool","source_path","r","counts","source_files_imported","batch_id","batch","summary","batchId","push","onProviderComplete","shouldRebuildIndexes","changed","markIndexesAfterImport","rebuildFts5Index","error","getErrorMessage","err","status","rebuildTantivyIndex","indexedDocCount","indexed_doc_count","onTantivyComplete","enableFts5Triggers","exportCompileParquet","storePath","store_path","result","exportBundleParquet","bundlePath","outDir","manifestPath","tableCount","Object","keys","files","length","ANALYTICS_REPORTS","runAnalyticsReport","options","queryDuckDbParquet","parquetDir","sql","buildAnalyticsSql","report","filters","runAnalyticsReportFromBundle","stmt","bundle","db","prepare","rows","all","columns","map","column","name","dialect","buildSessionsSql","buildToolsSql","buildErrorsSql","buildModelsSql","buildProjectsSql","where","buildWhere","sourceFilter","timeFilter","projectFilter","sessionId","sqlString","sourcePathSubstring","escapeLike","limit","toolName","canonicalType","errorsOnly","category","rangeOverlapFilter","model","source","filtersSql","since","push","until","length","join","firstColumn","lastColumn","project","exact","like","op","active","filter","Boolean","value","Number","isFinite","undefined","clampLimit","max","fallback","replace","match","access","readFile","stat","path","VACUUM_THRESHOLD_PCT","WAL_WARN_BYTES","STUCK_BATCH_AGE_HOURS","RECENT_BATCHES_FOR_ERRORS","DEFAULT_DEEP_SAMPLE","shouldRecommendVacuum","freelistCount","pageCount","thresholdPct","pct","runDoctor","opts","storePath","path","resolve","defaultBundlePath","deep","deepSample","Math","max","filters","checks","filter","c","length","started","Date","now","results","push","result","matchesFilter","check","layout","checkBundleLayout","r","bundle","openError","canOpen","openBundle","err","status","message","getErrorMessage","hint","details","error","schemaResults","checkSchema","checkSqliteHealth","walResult","checkWalSize","liveCount","countSearchDocs","liveFts5","countFts5Docs","statuses","getSearchIndexStatuses","checkSearchIndexes","checkImports","checkData","checkIntegrityFull","checkCasSample","closeBundle","summary","pass","info","warn","fail","skipped","duration_ms","bundleOpened","some","f","startsWith","manifestParsed","dirStat","stat","catch","isDirectory","manifestPath","join","raw","readFile","JSON","parse","requiredFields","missing","version","schema_version","manifest","dbPath","dbStat","isFile","size","formatBytes","size_bytes","requiredDirs","key","rel","missingDirs","d","s","hash_alg","default_compression","dbVersion","currentSchemaVersion","db","manifestVersion","code","PROSA_SCHEMA_VERSION","parser_version","PROSA_PARSER_VERSION","quickRows","prepare","all","quickValue","Object","values","String","rows","fkRows","violations","slice","journalMode","get","journal_mode","pageSize","page_size","page_count","freelist_count","pctWaste","dbSizeBytes","toFixed","pct_waste","Number","db_size_bytes","walPath","paths","wal_size_bytes","liveDocCount","liveFts5Count","byEngine","Map","map","engine","fts5","fts5_count","source_count","statusDetails","error_message","tantivy","dirValid","tantivyIndexDirIsValid","currentFingerprint","getCurrentTantivySchemaFingerprint","fingerprintOk","schema_fingerprint","dir","stored","current","indexed_doc_count","drift","source_doc_count","live","diff","updated_at","stuckRows","batches","recentErrors","recentSamples","totalRecent","reduce","n","by_kind","samples","counts","sessions","messages","raw_records","objects","orphanSubagents","count","first","issues","sampleSize","hashMismatches","readErrors","checked","row","abs","storage_path","access","object_id","compressed","plain","decompressBytes","compression","recomputed","blake3HexAsync","mismatches","read_errors","units","v","i","listToolCalls","bundle","filters","conds","params","toolName","push","canonicalType","sessionId","errorsOnly","pathSubstring","sinceIso","untilIso","where","length","join","limit","clampLimit","max","fallback","toolCallSql","sql","db","prepare","all","artifactSql","DEFAULT_MAX_INLINE_BYTES","DEFAULT_MAX_ARGS_INLINE_BYTES","loadTranscript","bundle","sessionId","options","maxInlineBytes","maxArgsInlineBytes","session","db","prepare","get","messages","all","blocks","toolCalls","toolResults","resultByCallId","Map","r","tool_call_id","set","blocksByMessage","b","message_id","list","push","callsByMessage","unattached","c","turns","m","mblocks","sort","a","ordinal","renderedBlocks","renderBlock","mcalls","ta","timestamp_start","tb","renderedCalls","renderToolCall","messageId","role","model","timestamp","unattachedRendered","unattachedToolCalls","resolveBlockText","block","text_inline","text","textObjectId","text_object_id","unavailable","resolved","getText","Buffer","byteLength","resolveArgsText","argsObjectId","maxBytes","blockId","block_id","blockType","block_type","hidden","visibility","mimeType","mime_type","isError","is_error","argsInline","args_object_id","toolCallId","toolName","tool_name","canonicalToolType","canonical_tool_type","command","path","status","timestampStart","result","toolResultId","tool_result_id","exitCode","exit_code","durationMs","duration_ms","preview","stdoutObjectId","stdout_object_id","stderrObjectId","stderr_object_id","outputObjectId","output_object_id","exportSessionMarkdown","bundle","sessionId","transcript","loadTranscript","maxInlineBytes","Number","MAX_SAFE_INTEGER","Error","session","lines","title","trim","source_tool","source_session_id","push","session_id","start_ts","end_ts","cwd_initial","git_branch_initial","model_first","model_last","timeline_confidence","turn","turns","ts","timestamp","model","role","block","blocks","hidden","text","call","toolCalls","renderToolCallMarkdown","unattachedToolCalls","length","join","c","status","errFlag","result","isError","toolName","command","path","preview","DEFAULT_MAX_OUTPUT_LINES","formatTranscriptText","transcript","options","showThinking","maxOutputLines","out","push","renderHeader","turn","turns","renderTurn","unattachedToolCalls","length","call","renderToolCallLines","join","s","session","title","trim","source_tool","source_session_id","lines","session_id","start_ts","end_ts","model_first","model_last","timeline_confidence","ctx","meta","model","timestamp","metaSuffix","role","block","blocks","renderBlock","toolCalls","isThinking","hidden","blockType","charCount","text","textObjectId","split","map","l","indent","statusBits","status","result","isError","statusSuffix","toolName","command","path","argsInline","argsLines","shown","slice","argsObjectId","preview","previewLines","objectId","outputObjectId","stdoutObjectId","stderrObjectId","PROSA_MCP_INSTRUCTIONS","trim","INVESTIGATE_PRIOR_WORK_PROMPT","FIND_FILE_HISTORY_PROMPT","AUDIT_TOOL_FAILURES_PROMPT","randomUUID","http","McpServer","StdioServerTransport","StreamableHTTPServerTransport","z","CANONICAL_TOOL_TYPES","FIELD_KINDS","registerProsaTools","server","bundle","options","searchEngine","storePath","path","ensureStore","registerProsaPrompts","registerTool","title","description","inputSchema","query","z","string","min","engine","enum","optional","field_kind","limit","number","int","max","default","raw","boolean","describe","annotations","readOnlyHint","idempotentHint","withToolBundle","activeBundle","selectedEngine","hits","searchFullText","filtered","filter","hit","content","type","text","JSON","stringify","count","length","session_id","format","source","SOURCE_TOOLS","since","until","rows","listSessions","sourceTool","sinceIso","untilIso","md","exportSessionMarkdown","error","getErrorMessage","isError","detail","getSession","payload","session","tool_name","canonical_type","path_substring","errors_only","input","listToolCalls","sessionId","toolName","canonicalType","pathSubstring","errorsOnly","report","ANALYTICS_REPORTS","source_path_substring","project","category","model","filters","sourcePathSubstring","result","runAnalyticsReportFromBundle","artifact_id","row","db","prepare","get","objectId","text_object_id","object_id","getText","sessions_path","overwrite","destructiveHint","mode","search_index","getSearchIndexStatuses","runCompileImports","providers","getCompileProvider","COMPILE_PROVIDERS","sessionsPath","parquet","importedAny","exportCompileParquet","map","provider","source_path","sourcePath","batch_id","batchId","counts","imported_any","tantivy","indexed_doc_count","indexedDocCount","tantivy_error","tantivyError","fts5_error","fts5Error","out_dir","outDir","manifest_path","manifestPath","table_count","tableCount","files","fallbackBundle","fn","openOrInitBundle","closeBundle","registerPrompt","argsSchema","topic","messages","role","INVESTIGATE_PRIOR_WORK_PROMPT","replace","FIND_FILE_HISTORY_PROMPT","AUDIT_TOOL_FAILURES_PROMPT","listenMcpStdioServer","bundle","options","server","createMcpServer","searchEngine","storePath","transport","StdioServerTransport","connect","close","safeClose","listenMcpServer","mcpPath","path","sessions","Map","httpServer","http","createServer","req","res","handleRequest","catch","error","writeError","Promise","resolve","reject","once","listen","port","host","removeListener","url","err","entry","values","clear","startsWith","writeHead","end","method","Allow","headerSessionId","headers","sessionId","Array","isArray","undefined","get","openSession","bodyText","readBody","body","length","safeJsonParse","store","StreamableHTTPServerTransport","sessionIdGenerator","randomUUID","onsessioninitialized","id","set","onsessionclosed","e","delete","McpServer","name","version","PROSA_PARSER_VERSION","instructions","PROSA_MCP_INSTRUCTIONS","registerProsaTools","ensureStore","chunks","on","chunk","push","Buffer","concat","toString","text","JSON","parse","o","headersSent","stringify","jsonrpc","code","message","getErrorMessage"]}
|
|
1
|
+
{"version":3,"sources":["../src/core/bundle.ts","../src/core/db.ts","../src/core/schema/sql/001_init.ts","../src/core/schema/sql/002_search_index_status.ts","../src/core/schema/sql/003_analytics_views.ts","../src/core/schema/sql/004_tantivy_checkpoint.ts","../src/core/schema/sql/005_object_transport_hash.ts","../src/core/schema/migrate.ts","../package.json","../src/core/version.ts","../src/core/domain/types.ts","../src/core/cas/index.ts","../src/core/cas/compress.ts","../src/core/cas/hash.ts","../src/core/domain/ids.ts","../src/core/ingest/batch.ts","../src/core/ingest/idempotency.ts","../src/core/limits.ts","../src/services/sessions.ts","../src/services/search.ts","../src/core/errors.ts","../src/services/indexing.ts","../src/services/compile.ts","../src/importers/claude/index.ts","../src/core/domain/status.ts","../src/importers/claude/discover.ts","../src/importers/codex/index.ts","../src/importers/codex/discover.ts","../src/importers/cursor/index.ts","../src/importers/cursor/discover.ts","../src/importers/gemini/index.ts","../src/importers/gemini/discover.ts","../src/importers/hermes/index.ts","../src/importers/hermes/discover.ts","../src/services/export/parquet.ts","../src/services/analytics.ts","../src/services/doctor.ts","../src/services/tool_calls.ts","../src/services/transcript.ts","../src/services/export/markdown.ts","../src/services/transcript-format-text.ts","../src/mcp/guidance.ts","../src/mcp/server.ts","../src/mcp/tools.ts"],"sourcesContent":["import { constants as fsConstants } from 'node:fs'\nimport { access, mkdir, readFile, stat, writeFile } from 'node:fs/promises'\nimport os from 'node:os'\nimport path from 'node:path'\nimport { type Db, closeDb, openDb } from './db.js'\nimport { currentSchemaVersion, runMigrations } from './schema/migrate.js'\nimport { PROSA_PARSER_VERSION, PROSA_SCHEMA_VERSION } from './version.js'\n\n/**\n * Durable metadata written to `manifest.json` at the root of a bundle.\n *\n * The manifest records the store format and the parser/schema versions that\n * last opened the bundle. SQLite remains the authoritative schema source after\n * migrations; `openBundle` refreshes the version stamps when they drift.\n */\nexport interface BundleManifest {\n /** Manifest file format version. */\n version: 1\n /** Parser version that last initialized or opened the bundle. */\n parser_version: string\n /** SQLite schema version expected by the last opener. */\n schema_version: number\n /** ISO timestamp for bundle creation. */\n created_at: string\n /** Hash algorithm used for content-addressed object IDs. */\n hash_alg: 'blake3'\n /** Default compression used for stored CAS payloads. */\n default_compression: 'zstd'\n}\n\n/**\n * Open bundle handle shared by core services.\n *\n * `path` is the resolved bundle root. `paths` contains all managed locations\n * under that root, including SQLite, CAS/object storage, raw source copies,\n * search indexes, and generated exports.\n */\nexport interface Bundle {\n /** Absolute bundle root path. */\n path: string\n /** Open better-sqlite3 database handle for `prosa.sqlite`. */\n db: Db\n /** Parsed bundle manifest metadata. */\n manifest: BundleManifest\n /** Canonical absolute paths for bundle-managed files and directories. */\n paths: {\n /** SQLite database file. */\n db: string\n /** Manifest JSON file. */\n manifest: string\n /** Main CAS fanout directory. */\n objects: string\n /** Raw preserved source-file directory. */\n rawSources: string\n /** Search-related sidecar root. */\n search: string\n /** Tantivy index directory. */\n tantivy: string\n /** Generated export root. */\n exports: string\n /** Default Parquet export directory. */\n parquet: string\n /** Reserved lock-file path for future single-writer coordination. */\n lock: string\n }\n}\n\n/** Store path exists or was requested, but no initialized bundle is available. */\nexport class BundleNotInitializedError extends Error {\n constructor(\n readonly bundlePath: string,\n readonly reason: 'missing-directory' | 'missing-manifest',\n ) {\n super(reason === 'missing-directory' ? `bundle path not found: ${bundlePath}` : `no manifest.json in ${bundlePath}`)\n this.name = 'BundleNotInitializedError'\n }\n}\n\n/**\n * Resolve the default bundle root.\n *\n * `PROSA_STORE` wins when set; otherwise the local-first store lives in\n * `~/.prosa`. The return value is absolute in both cases.\n */\nexport function defaultBundlePath(): string {\n const env = process.env.PROSA_STORE\n if (env && env.length > 0) return path.resolve(env)\n return path.join(os.homedir(), '.prosa')\n}\n\n/**\n * Derive every managed filesystem path for a bundle without touching disk.\n */\nfunction bundlePaths(rootPath: string): Bundle['paths'] {\n return {\n db: path.join(rootPath, 'prosa.sqlite'),\n manifest: path.join(rootPath, 'manifest.json'),\n objects: path.join(rootPath, 'objects'),\n rawSources: path.join(rootPath, 'raw', 'sources'),\n search: path.join(rootPath, 'search'),\n tantivy: path.join(rootPath, 'search', 'tantivy'),\n exports: path.join(rootPath, 'exports'),\n parquet: path.join(rootPath, 'parquet'),\n lock: path.join(rootPath, 'prosa.lock'),\n }\n}\n\nasync function exists(p: string): Promise<boolean> {\n try {\n await access(p, fsConstants.F_OK)\n return true\n } catch {\n return false\n }\n}\n\n/**\n * Create a fresh bundle at `rootPath`. Fails if the directory already contains\n * a manifest (use openBundle for that case).\n *\n * Side effects: creates the bundle directory tree, writes `manifest.json`,\n * opens `prosa.sqlite`, and applies all schema migrations. The caller owns the\n * returned database handle and must close it via `closeBundle`.\n */\nexport async function initBundle(rootPath: string): Promise<Bundle> {\n const resolved = path.resolve(rootPath)\n const paths = bundlePaths(resolved)\n\n await mkdir(resolved, { recursive: true })\n\n if (await exists(paths.manifest)) {\n throw new Error(`bundle already exists at ${resolved} (found manifest.json) — use openBundle instead`)\n }\n\n await mkdir(paths.objects, { recursive: true })\n await mkdir(paths.rawSources, { recursive: true })\n await mkdir(paths.search, { recursive: true })\n await mkdir(paths.tantivy, { recursive: true })\n await mkdir(paths.exports, { recursive: true })\n await mkdir(paths.parquet, { recursive: true })\n\n const manifest: BundleManifest = {\n version: 1,\n parser_version: PROSA_PARSER_VERSION,\n schema_version: PROSA_SCHEMA_VERSION,\n created_at: new Date().toISOString(),\n hash_alg: 'blake3',\n default_compression: 'zstd',\n }\n\n await writeFile(paths.manifest, `${JSON.stringify(manifest, null, 2)}\\n`, 'utf8')\n\n const db = openDb(paths.db)\n runMigrations(db)\n\n return { path: resolved, db, manifest, paths }\n}\n\n/**\n * Open an existing bundle. Applies pending migrations if the schema is older\n * than the current code expects.\n *\n * Fails when the root is missing, lacks a manifest, or the migrated database\n * version still does not match the code-time schema version. On success it may\n * rewrite only manifest version metadata.\n */\nexport async function openBundle(rootPath: string): Promise<Bundle> {\n const resolved = path.resolve(rootPath)\n const paths = bundlePaths(resolved)\n\n const dirStat = await stat(resolved).catch(() => null)\n if (!dirStat) {\n throw new BundleNotInitializedError(resolved, 'missing-directory')\n }\n if (!dirStat.isDirectory()) {\n throw new Error(`bundle path not found or not a directory: ${resolved}`)\n }\n if (!(await exists(paths.manifest))) {\n throw new BundleNotInitializedError(resolved, 'missing-manifest')\n }\n\n const manifest = JSON.parse(await readFile(paths.manifest, 'utf8')) as BundleManifest\n await mkdir(paths.search, { recursive: true })\n await mkdir(paths.tantivy, { recursive: true })\n const db = openDb(paths.db)\n runMigrations(db)\n\n const currentVersion = currentSchemaVersion(db)\n if (currentVersion !== PROSA_SCHEMA_VERSION) {\n closeDb(db)\n throw new Error(`schema version mismatch (db=${currentVersion}, code=${PROSA_SCHEMA_VERSION})`)\n }\n\n // Refresh manifest's parser_version and schema_version stamps on every open.\n // schema_version drifts after migrations apply to an older bundle; rewriting\n // the manifest keeps it in sync with the actual db state and avoids a stale\n // metadata warning from `prosa doctor`.\n let manifestDirty = false\n if (manifest.parser_version !== PROSA_PARSER_VERSION) {\n manifest.parser_version = PROSA_PARSER_VERSION\n manifestDirty = true\n }\n if (manifest.schema_version !== currentVersion) {\n manifest.schema_version = currentVersion\n manifestDirty = true\n }\n if (manifestDirty) {\n await writeFile(paths.manifest, `${JSON.stringify(manifest, null, 2)}\\n`, 'utf8')\n }\n\n return { path: resolved, db, manifest, paths }\n}\n\n/**\n * Open an existing bundle or transparently initialize one if the store path is\n * missing or has not been initialized yet.\n *\n * Fails when `rootPath` exists but is not a directory. This is the CLI-friendly\n * entrypoint for commands that should create the store on first use.\n */\nexport async function openOrInitBundle(rootPath: string): Promise<Bundle> {\n const resolved = path.resolve(rootPath)\n const paths = bundlePaths(resolved)\n\n const dirStat = await stat(resolved).catch(() => null)\n if (dirStat && !dirStat.isDirectory()) {\n throw new Error(`bundle path not found or not a directory: ${resolved}`)\n }\n\n if (!dirStat || !(await exists(paths.manifest))) {\n return await initBundle(resolved)\n }\n\n return await openBundle(resolved)\n}\n\n/**\n * Close the SQLite handle associated with a bundle.\n */\nexport function closeBundle(bundle: Bundle): void {\n closeDb(bundle.db)\n}\n","import Database, { type Database as DatabaseType, type Statement } from 'better-sqlite3'\n\n/**\n * Synchronous better-sqlite3 database handle used throughout core.\n */\nexport type Db = DatabaseType\n\n/**\n * Open a SQLite database with Prosa's write-heavy import pragmas applied.\n *\n * The function does not run migrations. It configures WAL mode, foreign key\n * enforcement, larger cache/mmap windows, and import-friendly checkpointing\n * before callers create or access schema objects.\n */\nexport function openDb(path: string): Db {\n const db = new Database(path)\n // page_size must be set before any table is created. On an existing DB it\n // is a no-op (changing requires VACUUM). 16 KiB pages cut B-tree depth and\n // pack more rows per page — measurable wins on insert-heavy workloads.\n db.pragma('page_size = 16384')\n db.pragma('journal_mode = WAL')\n db.pragma('foreign_keys = ON')\n db.pragma('synchronous = NORMAL')\n // Reduce contention on long imports.\n db.pragma('busy_timeout = 5000')\n // 256 MiB page cache (default is 2 MiB) — keeps the working set of long\n // imports in memory and avoids re-reading hot index pages from disk.\n db.pragma('cache_size = -262144')\n // 256 MiB mmap window for read-side; cheap on macOS/Linux and lets SQLite\n // skip pread() syscalls when pages are already paged in.\n db.pragma('mmap_size = 268435456')\n // Keep temp btrees (used by FTS5 merges, large IN lists) in RAM.\n db.pragma('temp_store = MEMORY')\n // Default 1000 pages (~4 MiB) causes a WAL checkpoint every few hundred\n // INSERTs during compile; bump to ~80 MiB so checkpoints don't interrupt\n // the steady-state write loop.\n db.pragma('wal_autocheckpoint = 20000')\n return db\n}\n\n/**\n * Close an open SQLite handle.\n */\nexport function closeDb(db: Db): void {\n db.close()\n}\n\n/**\n * Prepared-statement cache keyed by database object and SQL text.\n *\n * WeakMap ownership lets statements become collectible when the corresponding\n * DB handle is no longer referenced.\n */\nconst stmtCache = new WeakMap<Db, Map<string, Statement>>()\n\n/**\n * Cache prepared statements per database. Importers call the same INSERTs\n * thousands of times — preparing once cuts a lot of overhead and the cache\n * vanishes when the Db is garbage-collected.\n *\n * `TParams` defaults to `unknown[]` so callers don't have to type their\n * arguments. When precise typing matters, pass a tuple type as the first\n * generic argument and `Statement<TParams, TRow>` is returned directly.\n */\nexport function prepare<TParams extends unknown[] = unknown[], TRow = unknown>(\n db: Db,\n sql: string,\n): Statement<TParams, TRow> {\n let cache = stmtCache.get(db)\n if (!cache) {\n cache = new Map()\n stmtCache.set(db, cache)\n }\n let stmt = cache.get(sql)\n if (!stmt) {\n stmt = db.prepare(sql)\n cache.set(sql, stmt)\n }\n return stmt as Statement<TParams, TRow>\n}\n\n/**\n * Execute `fn` inside a single synchronous SQLite transaction.\n *\n * Any exception thrown by `fn` rolls back the transaction and is rethrown by\n * better-sqlite3. Async work must happen before or after this helper.\n */\nexport function transactional<T>(db: Db, fn: () => T): T {\n const wrapped = db.transaction(fn)\n return wrapped()\n}\n","// Auto-generated from schema description. Edit the SQL here directly.\n// Loaded at runtime by core/schema/migrate.ts.\n\n/**\n * Initial bundle schema.\n *\n * Defines the raw immutable layer, canonical projection tables, and derived\n * search index tables/triggers. Projection rows are rebuildable from preserved\n * raw records and CAS objects.\n */\nexport const SQL_001_INIT = String.raw`\n-- Schema W v1\n--\n-- Three layers:\n-- 1. raw immutable : raw_records pointing at preserved bytes (objects)\n-- 2. canonical projection: sessions, turns, events, messages, blocks,\n-- tool_calls, tool_results, artifacts, edges\n-- 3. derived indexes : search_docs + FTS5\n--\n-- Projections are regenerable from raw_records. Raw is the source of truth.\n\nCREATE TABLE IF NOT EXISTS objects (\n object_id TEXT PRIMARY KEY,\n hash_alg TEXT NOT NULL,\n hash TEXT NOT NULL,\n size_bytes INTEGER NOT NULL,\n compressed_size_bytes INTEGER,\n compression TEXT NOT NULL DEFAULT 'zstd',\n mime_type TEXT,\n encoding TEXT,\n storage_path TEXT NOT NULL,\n created_at TEXT NOT NULL\n);\n\nCREATE INDEX IF NOT EXISTS objects_hash_idx ON objects(hash_alg, hash);\n\nCREATE TABLE IF NOT EXISTS source_files (\n source_file_id TEXT PRIMARY KEY,\n source_tool TEXT NOT NULL,\n path TEXT NOT NULL,\n file_kind TEXT NOT NULL,\n size_bytes INTEGER NOT NULL,\n mtime TEXT,\n content_hash TEXT NOT NULL,\n object_id TEXT REFERENCES objects(object_id),\n discovered_at TEXT NOT NULL,\n workspace_hint TEXT,\n UNIQUE(source_tool, path, size_bytes, mtime, content_hash)\n);\n\nCREATE INDEX IF NOT EXISTS source_files_tool_idx ON source_files(source_tool);\nCREATE INDEX IF NOT EXISTS source_files_hash_idx ON source_files(content_hash);\n\nCREATE TABLE IF NOT EXISTS import_batches (\n batch_id TEXT PRIMARY KEY,\n parser_version TEXT NOT NULL,\n source_tool TEXT,\n paths TEXT,\n started_at TEXT NOT NULL,\n finished_at TEXT,\n status TEXT NOT NULL DEFAULT 'running',\n counts_json TEXT\n);\n\nCREATE TABLE IF NOT EXISTS raw_records (\n raw_record_id TEXT PRIMARY KEY,\n source_file_id TEXT NOT NULL REFERENCES source_files(source_file_id),\n source_tool TEXT NOT NULL,\n record_kind TEXT NOT NULL,\n ordinal INTEGER,\n line_no INTEGER,\n json_pointer TEXT,\n native_id TEXT,\n raw_object_id TEXT NOT NULL REFERENCES objects(object_id),\n decoded_json_object_id TEXT REFERENCES objects(object_id),\n parser_status TEXT NOT NULL,\n confidence TEXT NOT NULL DEFAULT 'high',\n import_batch_id TEXT NOT NULL REFERENCES import_batches(batch_id),\n UNIQUE(source_file_id, ordinal, raw_object_id)\n);\n\nCREATE INDEX IF NOT EXISTS raw_records_file_idx ON raw_records(source_file_id);\nCREATE INDEX IF NOT EXISTS raw_records_native_idx ON raw_records(source_tool, native_id);\n\nCREATE TABLE IF NOT EXISTS import_errors (\n error_id INTEGER PRIMARY KEY AUTOINCREMENT,\n batch_id TEXT NOT NULL REFERENCES import_batches(batch_id),\n source_file_id TEXT,\n raw_record_id TEXT,\n kind TEXT NOT NULL,\n message TEXT NOT NULL,\n payload_object_id TEXT REFERENCES objects(object_id),\n occurred_at TEXT NOT NULL\n);\n\nCREATE TABLE IF NOT EXISTS uncertainties (\n uncertainty_id INTEGER PRIMARY KEY AUTOINCREMENT,\n entity_type TEXT NOT NULL,\n entity_id TEXT NOT NULL,\n reason TEXT NOT NULL,\n metadata_object_id TEXT REFERENCES objects(object_id)\n);\n\nCREATE TABLE IF NOT EXISTS projects (\n project_id TEXT PRIMARY KEY,\n canonical_path TEXT,\n path_hash TEXT,\n source_tool TEXT,\n source_project_id TEXT,\n display_name TEXT,\n created_at TEXT NOT NULL,\n UNIQUE(source_tool, source_project_id)\n);\n\nCREATE TABLE IF NOT EXISTS sessions (\n session_id TEXT PRIMARY KEY,\n source_tool TEXT NOT NULL,\n source_session_id TEXT NOT NULL,\n project_id TEXT REFERENCES projects(project_id),\n parent_session_id TEXT REFERENCES sessions(session_id),\n is_subagent INTEGER NOT NULL DEFAULT 0,\n agent_role TEXT,\n agent_nickname TEXT,\n title TEXT,\n summary TEXT,\n start_ts TEXT,\n end_ts TEXT,\n cwd_initial TEXT,\n git_branch_initial TEXT,\n model_first TEXT,\n model_last TEXT,\n status TEXT,\n timeline_confidence TEXT NOT NULL DEFAULT 'high'\n CHECK (timeline_confidence IN ('high','medium','low')),\n raw_record_id TEXT REFERENCES raw_records(raw_record_id),\n UNIQUE(source_tool, source_session_id)\n);\n\nCREATE INDEX IF NOT EXISTS sessions_source_idx ON sessions(source_tool);\nCREATE INDEX IF NOT EXISTS sessions_start_idx ON sessions(start_ts);\nCREATE INDEX IF NOT EXISTS sessions_project_idx ON sessions(project_id);\nCREATE INDEX IF NOT EXISTS sessions_parent_idx ON sessions(parent_session_id);\n\nCREATE TABLE IF NOT EXISTS turns (\n turn_id TEXT PRIMARY KEY,\n session_id TEXT NOT NULL REFERENCES sessions(session_id),\n source_turn_id TEXT,\n ordinal INTEGER NOT NULL,\n start_ts TEXT,\n end_ts TEXT,\n model TEXT,\n cwd TEXT,\n git_branch TEXT,\n approval_policy TEXT,\n sandbox_policy TEXT,\n effort TEXT,\n raw_record_id TEXT REFERENCES raw_records(raw_record_id)\n);\n\nCREATE INDEX IF NOT EXISTS turns_session_idx ON turns(session_id, ordinal);\n\nCREATE TABLE IF NOT EXISTS events (\n event_id TEXT PRIMARY KEY,\n session_id TEXT NOT NULL REFERENCES sessions(session_id),\n turn_id TEXT REFERENCES turns(turn_id),\n source_event_id TEXT,\n event_type TEXT NOT NULL,\n source_type TEXT,\n subtype TEXT,\n timestamp TEXT,\n ordinal INTEGER NOT NULL,\n actor TEXT,\n payload_object_id TEXT REFERENCES objects(object_id),\n raw_record_id TEXT NOT NULL REFERENCES raw_records(raw_record_id),\n confidence TEXT NOT NULL DEFAULT 'high',\n is_derived INTEGER NOT NULL DEFAULT 0\n);\n\nCREATE INDEX IF NOT EXISTS events_session_idx ON events(session_id, ordinal);\nCREATE INDEX IF NOT EXISTS events_type_idx ON events(event_type, subtype);\n\nCREATE TABLE IF NOT EXISTS messages (\n message_id TEXT PRIMARY KEY,\n session_id TEXT NOT NULL REFERENCES sessions(session_id),\n turn_id TEXT REFERENCES turns(turn_id),\n event_id TEXT REFERENCES events(event_id),\n source_message_id TEXT,\n role TEXT NOT NULL CHECK (role IN (\n 'system_prompt','developer','user','assistant','tool','operational'\n )),\n author_name TEXT,\n model TEXT,\n timestamp TEXT,\n ordinal INTEGER NOT NULL,\n parent_message_id TEXT REFERENCES messages(message_id),\n request_id TEXT,\n status TEXT,\n raw_record_id TEXT NOT NULL REFERENCES raw_records(raw_record_id)\n);\n\nCREATE INDEX IF NOT EXISTS messages_session_idx ON messages(session_id, ordinal);\nCREATE INDEX IF NOT EXISTS messages_role_idx ON messages(role);\n\nCREATE TABLE IF NOT EXISTS content_blocks (\n block_id TEXT PRIMARY KEY,\n message_id TEXT REFERENCES messages(message_id),\n event_id TEXT REFERENCES events(event_id),\n session_id TEXT NOT NULL REFERENCES sessions(session_id),\n ordinal INTEGER NOT NULL,\n block_type TEXT NOT NULL,\n text_object_id TEXT REFERENCES objects(object_id),\n text_inline TEXT,\n mime_type TEXT,\n token_count INTEGER,\n is_error INTEGER NOT NULL DEFAULT 0,\n is_redacted INTEGER NOT NULL DEFAULT 0,\n visibility TEXT NOT NULL DEFAULT 'default'\n CHECK (visibility IN ('default','hidden_by_default','audit_only')),\n raw_record_id TEXT NOT NULL REFERENCES raw_records(raw_record_id)\n);\n\nCREATE INDEX IF NOT EXISTS blocks_session_idx ON content_blocks(session_id, ordinal);\nCREATE INDEX IF NOT EXISTS blocks_message_idx ON content_blocks(message_id);\n\nCREATE TABLE IF NOT EXISTS tool_calls (\n tool_call_id TEXT PRIMARY KEY,\n session_id TEXT NOT NULL REFERENCES sessions(session_id),\n turn_id TEXT REFERENCES turns(turn_id),\n message_id TEXT REFERENCES messages(message_id),\n event_id TEXT REFERENCES events(event_id),\n source_call_id TEXT,\n tool_name TEXT NOT NULL,\n canonical_tool_type TEXT,\n args_object_id TEXT REFERENCES objects(object_id),\n command TEXT,\n cwd TEXT,\n path TEXT,\n query TEXT,\n timestamp_start TEXT,\n timestamp_end TEXT,\n status TEXT,\n raw_record_id TEXT NOT NULL REFERENCES raw_records(raw_record_id)\n);\n\nCREATE INDEX IF NOT EXISTS tool_calls_session_idx ON tool_calls(session_id, timestamp_start);\nCREATE INDEX IF NOT EXISTS tool_calls_name_idx ON tool_calls(tool_name);\nCREATE INDEX IF NOT EXISTS tool_calls_canon_idx ON tool_calls(canonical_tool_type);\nCREATE INDEX IF NOT EXISTS tool_calls_source_call_idx ON tool_calls(session_id, source_call_id);\n\nCREATE TABLE IF NOT EXISTS tool_results (\n tool_result_id TEXT PRIMARY KEY,\n tool_call_id TEXT REFERENCES tool_calls(tool_call_id),\n session_id TEXT NOT NULL REFERENCES sessions(session_id),\n message_id TEXT REFERENCES messages(message_id),\n event_id TEXT REFERENCES events(event_id),\n source_call_id TEXT,\n status TEXT,\n is_error INTEGER NOT NULL DEFAULT 0,\n exit_code INTEGER,\n duration_ms INTEGER,\n stdout_object_id TEXT REFERENCES objects(object_id),\n stderr_object_id TEXT REFERENCES objects(object_id),\n output_object_id TEXT REFERENCES objects(object_id),\n preview TEXT,\n raw_record_id TEXT NOT NULL REFERENCES raw_records(raw_record_id)\n);\n\nCREATE INDEX IF NOT EXISTS tool_results_session_idx ON tool_results(session_id);\nCREATE INDEX IF NOT EXISTS tool_results_call_idx ON tool_results(tool_call_id);\nCREATE INDEX IF NOT EXISTS tool_results_source_call_idx ON tool_results(session_id, source_call_id);\nCREATE INDEX IF NOT EXISTS tool_results_error_idx ON tool_results(is_error);\n\nCREATE TABLE IF NOT EXISTS artifacts (\n artifact_id TEXT PRIMARY KEY,\n session_id TEXT REFERENCES sessions(session_id),\n project_id TEXT REFERENCES projects(project_id),\n source_tool TEXT NOT NULL,\n kind TEXT NOT NULL,\n path TEXT,\n logical_path TEXT,\n object_id TEXT REFERENCES objects(object_id),\n text_object_id TEXT REFERENCES objects(object_id),\n mime_type TEXT,\n size_bytes INTEGER NOT NULL,\n created_ts TEXT,\n raw_record_id TEXT NOT NULL REFERENCES raw_records(raw_record_id)\n);\n\nCREATE INDEX IF NOT EXISTS artifacts_session_idx ON artifacts(session_id);\nCREATE INDEX IF NOT EXISTS artifacts_path_idx ON artifacts(path);\n\nCREATE TABLE IF NOT EXISTS edges (\n edge_id INTEGER PRIMARY KEY AUTOINCREMENT,\n src_type TEXT NOT NULL,\n src_id TEXT NOT NULL,\n dst_type TEXT NOT NULL,\n dst_id TEXT NOT NULL,\n edge_type TEXT NOT NULL,\n confidence TEXT NOT NULL DEFAULT 'high',\n source TEXT NOT NULL DEFAULT 'explicit',\n raw_record_id TEXT REFERENCES raw_records(raw_record_id),\n metadata_object_id TEXT REFERENCES objects(object_id),\n UNIQUE(src_type, src_id, dst_type, dst_id, edge_type)\n);\n\nCREATE INDEX IF NOT EXISTS edges_src_idx ON edges(src_type, src_id);\nCREATE INDEX IF NOT EXISTS edges_dst_idx ON edges(dst_type, dst_id);\nCREATE INDEX IF NOT EXISTS edges_type_idx ON edges(edge_type);\n\nCREATE TABLE IF NOT EXISTS search_docs (\n doc_id TEXT PRIMARY KEY,\n entity_type TEXT NOT NULL,\n entity_id TEXT NOT NULL,\n session_id TEXT,\n project_id TEXT,\n timestamp TEXT,\n role TEXT,\n tool_name TEXT,\n canonical_tool_type TEXT,\n field_kind TEXT NOT NULL,\n text TEXT NOT NULL\n);\n\nCREATE INDEX IF NOT EXISTS search_docs_session_idx ON search_docs(session_id);\nCREATE INDEX IF NOT EXISTS search_docs_entity_idx ON search_docs(entity_type, entity_id);\nCREATE INDEX IF NOT EXISTS search_docs_field_idx ON search_docs(field_kind);\n\nCREATE VIRTUAL TABLE IF NOT EXISTS search_docs_fts USING fts5(\n text,\n role UNINDEXED,\n tool_name UNINDEXED,\n field_kind UNINDEXED,\n content='search_docs',\n content_rowid='rowid',\n tokenize='unicode61 remove_diacritics 2'\n);\n\nCREATE TRIGGER IF NOT EXISTS search_docs_ai AFTER INSERT ON search_docs BEGIN\n INSERT INTO search_docs_fts(rowid, text, role, tool_name, field_kind)\n VALUES (new.rowid, new.text, new.role, new.tool_name, new.field_kind);\nEND;\n\nCREATE TRIGGER IF NOT EXISTS search_docs_ad AFTER DELETE ON search_docs BEGIN\n INSERT INTO search_docs_fts(search_docs_fts, rowid, text, role, tool_name, field_kind)\n VALUES('delete', old.rowid, old.text, old.role, old.tool_name, old.field_kind);\nEND;\n\nCREATE TRIGGER IF NOT EXISTS search_docs_au AFTER UPDATE ON search_docs BEGIN\n INSERT INTO search_docs_fts(search_docs_fts, rowid, text, role, tool_name, field_kind)\n VALUES('delete', old.rowid, old.text, old.role, old.tool_name, old.field_kind);\n INSERT INTO search_docs_fts(rowid, text, role, tool_name, field_kind)\n VALUES (new.rowid, new.text, new.role, new.tool_name, new.field_kind);\nEND;\n`\n","/**\n * Adds durable status tracking for local search index engines.\n *\n * FTS5 starts as ready because it is maintained inside SQLite; Tantivy starts\n * missing until the external index is built.\n */\nexport const SQL_002_SEARCH_INDEX_STATUS = String.raw`\nCREATE TABLE IF NOT EXISTS search_index_status (\n engine TEXT PRIMARY KEY,\n status TEXT NOT NULL CHECK (status IN ('missing','ready','stale','building','failed')),\n source_doc_count INTEGER NOT NULL DEFAULT 0,\n indexed_doc_count INTEGER NOT NULL DEFAULT 0,\n updated_at TEXT NOT NULL,\n error_message TEXT\n);\n\nINSERT OR IGNORE INTO search_index_status (\n engine, status, source_doc_count, indexed_doc_count, updated_at, error_message\n) VALUES\n ('fts5', 'ready', 0, 0, strftime('%Y-%m-%dT%H:%M:%fZ','now'), NULL),\n ('tantivy', 'missing', 0, 0, strftime('%Y-%m-%dT%H:%M:%fZ','now'), NULL);\n`\n","/**\n * Derived analytics views over canonical projection tables.\n *\n * These views are read models only; importers should continue to write source,\n * raw, and canonical tables directly.\n */\nexport const SQL_003_ANALYTICS_VIEWS = String.raw`\nCREATE VIEW IF NOT EXISTS session_facts AS\nWITH turn_counts AS (\n SELECT session_id, count(*) AS turn_count\n FROM turns\n GROUP BY session_id\n),\nmessage_counts AS (\n SELECT session_id,\n count(*) AS message_count,\n sum(CASE WHEN role = 'user' THEN 1 ELSE 0 END) AS user_message_count,\n sum(CASE WHEN role = 'assistant' THEN 1 ELSE 0 END) AS assistant_message_count\n FROM messages\n GROUP BY session_id\n),\ntool_call_counts AS (\n SELECT session_id,\n count(*) AS tool_call_count,\n sum(CASE WHEN status = 'error' THEN 1 ELSE 0 END) AS tool_call_error_count\n FROM tool_calls\n GROUP BY session_id\n),\ntool_result_counts AS (\n SELECT session_id,\n count(*) AS tool_result_count,\n sum(CASE WHEN is_error = 1 OR (exit_code IS NOT NULL AND exit_code <> 0)\n THEN 1 ELSE 0 END) AS tool_result_error_count,\n sum(COALESCE(duration_ms, 0)) AS tool_duration_ms\n FROM tool_results\n GROUP BY session_id\n),\nsearch_doc_counts AS (\n SELECT session_id, count(*) AS search_doc_count\n FROM search_docs\n WHERE session_id IS NOT NULL\n GROUP BY session_id\n)\nSELECT s.session_id,\n s.source_tool,\n s.source_session_id,\n s.project_id,\n p.display_name AS project_name,\n p.canonical_path AS project_path,\n s.parent_session_id,\n s.is_subagent,\n s.agent_role,\n s.agent_nickname,\n s.title,\n s.start_ts,\n s.end_ts,\n CASE\n WHEN s.start_ts IS NOT NULL AND s.end_ts IS NOT NULL\n THEN ROUND((julianday(s.end_ts) - julianday(s.start_ts)) * 86400, 3)\n ELSE NULL\n END AS duration_seconds,\n s.cwd_initial,\n s.git_branch_initial,\n s.model_first,\n s.model_last,\n s.status,\n s.timeline_confidence,\n sf.path AS source_file_path,\n COALESCE(tc.turn_count, 0) AS turn_count,\n COALESCE(mc.message_count, 0) AS message_count,\n COALESCE(mc.user_message_count, 0) AS user_message_count,\n COALESCE(mc.assistant_message_count, 0) AS assistant_message_count,\n COALESCE(tcc.tool_call_count, 0) AS tool_call_count,\n COALESCE(trc.tool_result_count, 0) AS tool_result_count,\n COALESCE(tcc.tool_call_error_count, 0)\n + COALESCE(trc.tool_result_error_count, 0) AS tool_error_count,\n COALESCE(trc.tool_duration_ms, 0) AS tool_duration_ms,\n COALESCE(sdc.search_doc_count, 0) AS search_doc_count\n FROM sessions s\n LEFT JOIN projects p ON p.project_id = s.project_id\n LEFT JOIN raw_records rr ON rr.raw_record_id = s.raw_record_id\n LEFT JOIN source_files sf ON sf.source_file_id = rr.source_file_id\n LEFT JOIN turn_counts tc ON tc.session_id = s.session_id\n LEFT JOIN message_counts mc ON mc.session_id = s.session_id\n LEFT JOIN tool_call_counts tcc ON tcc.session_id = s.session_id\n LEFT JOIN tool_result_counts trc ON trc.session_id = s.session_id\n LEFT JOIN search_doc_counts sdc ON sdc.session_id = s.session_id;\n\nCREATE VIEW IF NOT EXISTS tool_usage_facts AS\nWITH result_rollup AS (\n SELECT tool_call_id,\n session_id,\n count(*) AS tool_result_count,\n max(status) AS result_status,\n max(is_error) AS is_error,\n min(exit_code) AS exit_code,\n sum(COALESCE(duration_ms, 0)) AS duration_ms,\n max(preview) AS preview\n FROM tool_results\n GROUP BY tool_call_id, session_id\n)\nSELECT tc.tool_call_id,\n tc.session_id,\n s.source_tool,\n s.source_session_id,\n s.project_id,\n p.display_name AS project_name,\n p.canonical_path AS project_path,\n tc.turn_id,\n tc.message_id,\n tc.event_id,\n tc.source_call_id,\n tc.tool_name,\n tc.canonical_tool_type,\n tc.command,\n tc.cwd,\n tc.path,\n tc.query,\n tc.timestamp_start,\n tc.timestamp_end,\n CASE\n WHEN tc.timestamp_start IS NOT NULL AND tc.timestamp_end IS NOT NULL\n THEN ROUND((julianday(tc.timestamp_end) - julianday(tc.timestamp_start)) * 86400, 3)\n ELSE NULL\n END AS call_duration_seconds,\n tc.status AS call_status,\n rr.result_status,\n COALESCE(rr.is_error, 0) AS is_error,\n rr.exit_code,\n rr.duration_ms AS result_duration_ms,\n COALESCE(rr.tool_result_count, 0) AS tool_result_count,\n rr.preview,\n tc.raw_record_id\n FROM tool_calls tc\n LEFT JOIN sessions s ON s.session_id = tc.session_id\n LEFT JOIN projects p ON p.project_id = s.project_id\n LEFT JOIN result_rollup rr ON rr.tool_call_id = tc.tool_call_id;\n\nCREATE VIEW IF NOT EXISTS error_facts AS\nSELECT 'tool_result:' || tr.tool_result_id AS error_id,\n 'tool_result' AS error_category,\n s.source_tool,\n s.project_id,\n p.display_name AS project_name,\n tr.session_id,\n COALESCE(tc.timestamp_end, tc.timestamp_start) AS timestamp,\n tc.tool_name,\n tc.canonical_tool_type,\n COALESCE(tr.status, tc.status) AS status,\n tr.exit_code,\n NULL AS message,\n tr.preview,\n NULL AS entity_type,\n NULL AS entity_id,\n tr.raw_record_id\n FROM tool_results tr\n LEFT JOIN tool_calls tc ON tc.tool_call_id = tr.tool_call_id\n LEFT JOIN sessions s ON s.session_id = tr.session_id\n LEFT JOIN projects p ON p.project_id = s.project_id\n WHERE tr.is_error = 1 OR (tr.exit_code IS NOT NULL AND tr.exit_code <> 0)\nUNION ALL\nSELECT 'import_error:' || CAST(ie.error_id AS TEXT) AS error_id,\n 'import_error' AS error_category,\n COALESCE(rr.source_tool, ib.source_tool) AS source_tool,\n NULL AS project_id,\n NULL AS project_name,\n NULL AS session_id,\n ie.occurred_at AS timestamp,\n NULL AS tool_name,\n NULL AS canonical_tool_type,\n ie.kind AS status,\n NULL AS exit_code,\n ie.message,\n NULL AS preview,\n NULL AS entity_type,\n NULL AS entity_id,\n ie.raw_record_id\n FROM import_errors ie\n LEFT JOIN import_batches ib ON ib.batch_id = ie.batch_id\n LEFT JOIN raw_records rr ON rr.raw_record_id = ie.raw_record_id\nUNION ALL\nSELECT 'uncertainty:' || CAST(u.uncertainty_id AS TEXT) AS error_id,\n 'uncertainty' AS error_category,\n NULL AS source_tool,\n NULL AS project_id,\n NULL AS project_name,\n CASE WHEN u.entity_type = 'session' THEN u.entity_id ELSE NULL END AS session_id,\n NULL AS timestamp,\n NULL AS tool_name,\n NULL AS canonical_tool_type,\n u.reason AS status,\n NULL AS exit_code,\n u.reason AS message,\n NULL AS preview,\n u.entity_type,\n u.entity_id,\n NULL AS raw_record_id\n FROM uncertainties u;\n\nCREATE VIEW IF NOT EXISTS model_usage AS\nWITH model_events AS (\n SELECT s.source_tool,\n s.project_id,\n p.display_name AS project_name,\n p.canonical_path AS project_path,\n s.session_id,\n NULL AS turn_id,\n s.model_first AS model,\n s.start_ts AS timestamp,\n 'session_first' AS observation_type\n FROM sessions s\n LEFT JOIN projects p ON p.project_id = s.project_id\n WHERE s.model_first IS NOT NULL\n UNION ALL\n SELECT s.source_tool, s.project_id, p.display_name, p.canonical_path,\n s.session_id, NULL AS turn_id, s.model_last AS model, s.end_ts AS timestamp,\n 'session_last' AS observation_type\n FROM sessions s\n LEFT JOIN projects p ON p.project_id = s.project_id\n WHERE s.model_last IS NOT NULL\n UNION ALL\n SELECT s.source_tool, s.project_id, p.display_name, p.canonical_path,\n t.session_id, t.turn_id, t.model, t.start_ts AS timestamp, 'turn' AS observation_type\n FROM turns t\n LEFT JOIN sessions s ON s.session_id = t.session_id\n LEFT JOIN projects p ON p.project_id = s.project_id\n WHERE t.model IS NOT NULL\n UNION ALL\n SELECT s.source_tool, s.project_id, p.display_name, p.canonical_path,\n m.session_id, m.turn_id, m.model, m.timestamp, 'message' AS observation_type\n FROM messages m\n LEFT JOIN sessions s ON s.session_id = m.session_id\n LEFT JOIN projects p ON p.project_id = s.project_id\n WHERE m.model IS NOT NULL\n)\nSELECT source_tool,\n project_id,\n project_name,\n project_path,\n model,\n count(DISTINCT session_id) AS session_count,\n count(DISTINCT turn_id) AS turn_count,\n count(*) AS observation_count,\n sum(CASE WHEN observation_type = 'message' THEN 1 ELSE 0 END) AS message_count,\n min(timestamp) AS first_seen_ts,\n max(timestamp) AS last_seen_ts\n FROM model_events\n GROUP BY source_tool, project_id, project_name, project_path, model;\n\nCREATE VIEW IF NOT EXISTS project_activity AS\nSELECT s.source_tool,\n s.project_id,\n COALESCE(p.display_name, s.cwd_initial, '(unknown)') AS project_name,\n p.canonical_path AS project_path,\n min(s.start_ts) AS first_session_ts,\n max(COALESCE(s.end_ts, s.start_ts)) AS latest_session_ts,\n count(DISTINCT s.session_id) AS session_count,\n count(DISTINCT CASE WHEN s.timeline_confidence = 'low' THEN s.session_id END)\n AS low_confidence_session_count,\n count(DISTINCT t.turn_id) AS turn_count,\n count(DISTINCT m.message_id) AS message_count,\n count(DISTINCT tc.tool_call_id) AS tool_call_count,\n count(DISTINCT tr.tool_result_id) AS tool_result_count,\n count(DISTINCT CASE\n WHEN tr.is_error = 1 OR (tr.exit_code IS NOT NULL AND tr.exit_code <> 0)\n THEN tr.tool_result_id\n END) AS tool_error_count,\n count(DISTINCT sd.doc_id) AS search_doc_count\n FROM sessions s\n LEFT JOIN projects p ON p.project_id = s.project_id\n LEFT JOIN turns t ON t.session_id = s.session_id\n LEFT JOIN messages m ON m.session_id = s.session_id\n LEFT JOIN tool_calls tc ON tc.session_id = s.session_id\n LEFT JOIN tool_results tr ON tr.session_id = s.session_id\n LEFT JOIN search_docs sd ON sd.session_id = s.session_id\n GROUP BY s.source_tool, s.project_id, p.display_name, s.cwd_initial, p.canonical_path;\n`\n","/**\n * Adds checkpoint columns for incremental Tantivy rebuilds.\n *\n * `last_indexed_rowid` is the highest `search_docs.rowid` already present in\n * Tantivy segments. `schema_fingerprint` lets the rebuild path detect index\n * schema changes and fall back to a full re-index. Both columns are nullable;\n * upgraded v3 bundles therefore default to the safe full-rebuild behavior.\n */\nexport const SQL_004_TANTIVY_CHECKPOINT = String.raw`\nALTER TABLE search_index_status ADD COLUMN last_indexed_rowid INTEGER;\nALTER TABLE search_index_status ADD COLUMN schema_fingerprint TEXT;\n`\n","// Loaded at runtime by core/schema/migrate.ts.\n\n/**\n * Add the optional transport hash cached for object upload bodies.\n *\n * `objects.hash` remains the canonical uncompressed BLAKE3 digest. This column\n * stores the BLAKE3 digest of the bytes sent over sync transport, which may be\n * compressed bytes for zstd-backed objects.\n */\nexport const SQL_005_OBJECT_TRANSPORT_HASH = String.raw`\n-- Schema W v5\n\nALTER TABLE objects ADD COLUMN transport_hash TEXT;\n`\n","import type { Db } from '../db.js'\nimport { SQL_001_INIT } from './sql/001_init.js'\nimport { SQL_002_SEARCH_INDEX_STATUS } from './sql/002_search_index_status.js'\nimport { SQL_003_ANALYTICS_VIEWS } from './sql/003_analytics_views.js'\nimport { SQL_004_TANTIVY_CHECKPOINT } from './sql/004_tantivy_checkpoint.js'\nimport { SQL_005_OBJECT_TRANSPORT_HASH } from './sql/005_object_transport_hash.js'\n\n/**\n * One immutable schema migration entry.\n *\n * The `version` is the durable ordering key stored in `_prosa_migrations`;\n * `sql` may contain multiple DDL/DML statements.\n */\ninterface Migration {\n version: number\n name: string\n sql: string\n}\n\n/**\n * Ordered migration list applied to every opened bundle.\n *\n * Each entry is a self-contained set of DDL statements run inside a single\n * transaction together with its bookkeeping insert.\n */\nconst MIGRATIONS: readonly Migration[] = [\n { version: 1, name: 'init', sql: SQL_001_INIT },\n { version: 2, name: 'search_index_status', sql: SQL_002_SEARCH_INDEX_STATUS },\n { version: 3, name: 'analytics_views', sql: SQL_003_ANALYTICS_VIEWS },\n { version: 4, name: 'tantivy_checkpoint', sql: SQL_004_TANTIVY_CHECKPOINT },\n { version: 5, name: 'object_transport_hash', sql: SQL_005_OBJECT_TRANSPORT_HASH },\n]\n\n/** Result returned after running schema migrations. */\nexport interface MigrationResult {\n /** Migration versions applied during this call. */\n applied: number[]\n}\n\n/**\n * Apply all unapplied schema migrations and return the versions newly applied.\n *\n * The migrations table is created on demand. Each migration either fully\n * applies with its bookkeeping row or rolls back through SQLite's transaction\n * machinery; errors propagate to the caller.\n */\nexport function runMigrations(db: Db): MigrationResult {\n db.exec(`\n CREATE TABLE IF NOT EXISTS _prosa_migrations (\n version INTEGER PRIMARY KEY,\n name TEXT NOT NULL,\n applied_at TEXT NOT NULL\n );\n `)\n\n const applied = new Set<number>(\n db\n .prepare<[], { version: number }>(`SELECT version FROM _prosa_migrations`)\n .all()\n .map((row) => row.version),\n )\n\n const newlyApplied: number[] = []\n\n for (const migration of MIGRATIONS) {\n if (applied.has(migration.version)) continue\n const tx = db.transaction(() => {\n db.exec(migration.sql)\n db.prepare(`INSERT INTO _prosa_migrations(version, name, applied_at) VALUES (?, ?, ?)`).run(\n migration.version,\n migration.name,\n new Date().toISOString(),\n )\n })\n tx()\n newlyApplied.push(migration.version)\n }\n\n return { applied: newlyApplied }\n}\n\n/**\n * Read the highest applied schema version from the database.\n *\n * Returns 0 for an uninitialized database or if migration metadata cannot be\n * queried yet.\n */\nexport function currentSchemaVersion(db: Db): number {\n try {\n const row = db\n .prepare<[], { version: number | null }>(`SELECT MAX(version) AS version FROM _prosa_migrations`)\n .get()\n return row?.version ?? 0\n } catch {\n return 0\n }\n}\n","{\n \"name\": \"@c3-oss/prosa-core\",\n \"version\": \"0.8.1\",\n \"description\": \"Core storage, import, search, export, analytics, and MCP APIs for prosa.\",\n \"author\": \"Caian Ertl <hi@caian.org>\",\n \"license\": \"MIT\",\n \"type\": \"module\",\n \"homepage\": \"https://github.com/c3-oss/prosa#readme\",\n \"bugs\": {\n \"url\": \"https://github.com/c3-oss/prosa/issues\"\n },\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://github.com/c3-oss/prosa.git\",\n \"directory\": \"packages/prosa-core\"\n },\n \"files\": [\"dist\"],\n \"main\": \"./dist/index.js\",\n \"types\": \"./dist/index.d.ts\",\n \"exports\": {\n \".\": {\n \"prosa-dev\": \"./src/index.ts\",\n \"import\": \"./dist/index.js\",\n \"types\": \"./dist/index.d.ts\"\n }\n },\n \"typedocOptions\": {\n \"entryPoints\": [\"src/index.ts\"],\n \"tsconfig\": \"tsconfig.json\"\n },\n \"publishConfig\": {\n \"access\": \"public\",\n \"registry\": \"https://registry.npmjs.org/\"\n },\n \"scripts\": {\n \"build\": \"tsup\",\n \"typecheck\": \"tsc --noEmit\",\n \"test\": \"vitest run\",\n \"test:coverage\": \"vitest run --coverage\",\n \"lint\": \"biome check .\",\n \"lint:fix\": \"biome check --fix .\",\n \"clean\": \"rm -rf dist coverage .turbo\"\n },\n \"dependencies\": {\n \"@duckdb/node-api\": \"1.5.2-r.1\",\n \"@modelcontextprotocol/sdk\": \"^1.29.0\",\n \"@noble/hashes\": \"^1.7.0\",\n \"@oxdev03/node-tantivy-binding\": \"0.2.0\",\n \"better-sqlite3\": \"^12.10.0\",\n \"filtrex\": \"^3.1.0\",\n \"hash-wasm\": \"^4.12.0\",\n \"pino\": \"^10.3.1\",\n \"zod\": \"^3.23.8\",\n \"zstd-napi\": \"^0.0.10\"\n },\n \"devDependencies\": {\n \"@c3-oss/config-biome\": \"^0.3.1\",\n \"@c3-oss/config-tsup\": \"^0.2.0\",\n \"@c3-oss/config-typescript\": \"^0.1.0\",\n \"@c3-oss/config-vitest\": \"^0.3.0\",\n \"@types/better-sqlite3\": \"^7.6.12\"\n },\n \"optionalDependencies\": {\n \"@oxdev03/node-tantivy-binding-darwin-arm64\": \"0.2.0\",\n \"@oxdev03/node-tantivy-binding-darwin-x64\": \"0.2.0\",\n \"@oxdev03/node-tantivy-binding-linux-x64-gnu\": \"0.2.0\",\n \"@oxdev03/node-tantivy-binding-win32-x64-msvc\": \"0.2.0\"\n }\n}\n","import packageJson from '../../package.json' with { type: 'json' }\n\n/**\n * Parser/projection version for normalized importer output.\n *\n * Bump when importer or normalizer semantics change in a way that can make\n * existing canonical rows stale relative to preserved raw records. Stored on\n * every `import_batches` row for future re-projection decisions.\n */\nexport const PROSA_PARSER_VERSION = packageJson.version\n\n/**\n * Current SQLite schema version, matching the highest migration in\n * `src/core/schema`.\n */\nexport const PROSA_SCHEMA_VERSION = 5\n","// Row-shaped TypeScript types matching the SQLite schema. These are the\n// boundary contract between importers and the catalog. Optional fields use\n// `null` (not `undefined`) to mirror SQLite NULL semantics directly.\n\n/**\n * Source tools that have first-class importer support and stable schema\n * semantics.\n */\nexport const SOURCE_TOOLS = ['cursor', 'codex', 'claude', 'gemini', 'hermes'] as const\n\n/**\n * Normalized source-tool discriminator stored on source files, raw records,\n * sessions, and analytics views.\n */\nexport type SourceTool = (typeof SOURCE_TOOLS)[number]\n\n/**\n * Confidence level for inferred timeline positions and recovered relations.\n */\nexport type Confidence = 'high' | 'medium' | 'low'\n\n/**\n * Canonical message role vocabulary used by the `messages.role` CHECK\n * constraint. `operational` is reserved for runtime/system events that are not\n * user-visible system prompts.\n */\nexport type MessageRole = 'system_prompt' | 'developer' | 'user' | 'assistant' | 'tool' | 'operational'\n\n/**\n * Coarse tool categories used for cross-importer aggregation while preserving\n * the native tool name separately.\n */\nexport type CanonicalToolType =\n | 'shell'\n | 'read_file'\n | 'write_file'\n | 'edit_file'\n | 'search_file'\n | 'web_search'\n | 'mcp'\n | 'subagent'\n | 'patch'\n | 'other'\n\n/**\n * Directed graph relationship vocabulary for `edges`, covering conversation\n * lineage, tool call/result links, artifacts, and recovered equivalence.\n */\nexport type EdgeType =\n | 'parent_of'\n | 'calls'\n | 'returns'\n | 'spawned'\n | 'contains'\n | 'produced'\n | 'consumed'\n | 'derived_from'\n | 'summarizes'\n | 'compacts'\n | 'same_as'\n | 'refers_to'\n\n/**\n * Importer-normalized lifecycle state for tool calls when the source format\n * provides enough evidence to distinguish outcomes.\n */\nexport type ToolCallStatus = 'started' | 'success' | 'error' | 'cancelled' | 'unknown'\n\n/**\n * Complete row projection for the `sessions` table.\n *\n * Boolean flags are represented as SQLite integers and absent values are\n * represented as `null` so callers can bind/read rows without conversion.\n */\nexport interface SessionRowFull {\n /** Canonical prosa session identifier. */\n session_id: string\n /** Source tool that produced the session. */\n source_tool: SourceTool\n /** Native session identifier from the source tool. */\n source_session_id: string\n /** Canonical project identifier, when recovered. */\n project_id: string | null\n /** Parent session identifier for subagent sessions. */\n parent_session_id: string | null\n /** SQLite boolean indicating whether this session is a subagent. */\n is_subagent: 0 | 1\n /** Source-specific role for a subagent. */\n agent_role: string | null\n /** Display nickname for a subagent. */\n agent_nickname: string | null\n /** Best recovered session title. */\n title: string | null\n /** Best recovered session summary. */\n summary: string | null\n /** Earliest recovered session timestamp. */\n start_ts: string | null\n /** Latest recovered session timestamp. */\n end_ts: string | null\n /** Initial working directory, when available. */\n cwd_initial: string | null\n /** Initial git branch, when available. */\n git_branch_initial: string | null\n /** First observed model name. */\n model_first: string | null\n /** Last observed model name. */\n model_last: string | null\n /** Source or importer session status. */\n status: string | null\n /** Confidence in recovered timeline ordering. */\n timeline_confidence: Confidence\n /** Raw record that introduced the session, when applicable. */\n raw_record_id: string | null\n}\n","import { mkdir, readFile, writeFile } from 'node:fs/promises'\nimport path from 'node:path'\nimport type { Bundle } from '../bundle.js'\nimport { prepare } from '../db.js'\nimport { type Compression, compressBytes, decompressBytes } from './compress.js'\nimport { blake3Hex, blake3HexAsync, objectIdFromHash, objectStoragePath } from './hash.js'\n\n/**\n * Content-addressed object identifier stored as `blake3:<hex>`.\n */\nexport type ObjectId = string\n\n/**\n * Complete metadata row for one object stored in the CAS.\n *\n * `storage_path` is relative to the bundle root and points at compressed or\n * raw bytes depending on `compression`.\n */\nexport interface ObjectMeta {\n /** Canonical object identifier, formatted as `blake3:<hex>`. */\n object_id: ObjectId\n /** Hash algorithm used to derive `hash` and `object_id`. */\n hash_alg: 'blake3'\n /** Raw BLAKE3 hex digest without the `blake3:` prefix. */\n hash: string\n /** Original uncompressed payload size in bytes. */\n size_bytes: number\n /** Stored compressed payload size, or null when stored uncompressed. */\n compressed_size_bytes: number | null\n /** Compression algorithm used for the stored payload. */\n compression: Compression\n /** Optional media type supplied by the writer. */\n mime_type: string | null\n /** Optional text encoding supplied by the writer. */\n encoding: string | null\n /** Bundle-relative path to the stored bytes. */\n storage_path: string\n /** BLAKE3 hex digest of the bytes stored on disk and uploaded over sync. */\n transport_hash: string | null\n /** ISO timestamp for the metadata row insertion. */\n created_at: string\n}\n\n/**\n * Optional MIME and text-encoding metadata for newly stored CAS objects.\n */\nexport interface PutOptions {\n /** Optional media type to persist on the object metadata row. */\n mimeType?: string\n /** Optional text encoding to persist on the object metadata row. */\n encoding?: string\n}\n\n/**\n * Per-process cache of directories we've already mkdir'd. The CAS fanout\n * creates `objects/blake3/ab/cd/` for 65k possible leaves; calling\n * `mkdir(... { recursive: true })` for every staged object during a large\n * import was a measurable cost. Cache by absolute path.\n */\nconst ensuredDirs = new Set<string>()\n\nexport async function ensureDir(absoluteDir: string): Promise<void> {\n if (ensuredDirs.has(absoluteDir)) return\n await mkdir(absoluteDir, { recursive: true })\n ensuredDirs.add(absoluteDir)\n}\n\n/**\n * Store raw bytes in the CAS. Returns the object_id. Idempotent: if the same\n * content already exists, returns the existing object_id without rewriting.\n *\n * Bytes are compressed with zstd when worth it (see compress.ts threshold).\n * The on-disk path is `<bundle>/objects/blake3/ab/cd/<hash>.zst`.\n */\nexport async function putBytes(bundle: Bundle, bytes: Uint8Array, options: PutOptions = {}): Promise<ObjectId> {\n const hash = await blake3HexAsync(bytes)\n const objectId = objectIdFromHash(hash)\n\n const existing = prepare<[string], ObjectMeta>(\n bundle.db,\n `SELECT object_id, hash_alg, hash, size_bytes, compressed_size_bytes,\n compression, mime_type, encoding, storage_path, transport_hash, created_at\n FROM objects WHERE object_id = ?`,\n ).get(objectId)\n\n if (existing) return objectId\n\n const { bytes: stored, compression } = compressBytes(bytes)\n const storagePath = objectStoragePath(hash, compression)\n const absolutePath = path.join(bundle.path, storagePath)\n\n await ensureDir(path.dirname(absolutePath))\n await writeFile(absolutePath, stored)\n\n prepare(\n bundle.db,\n `INSERT INTO objects (\n object_id, hash_alg, hash, size_bytes, compressed_size_bytes,\n compression, mime_type, encoding, storage_path, transport_hash, created_at\n ) VALUES (?, 'blake3', ?, ?, ?, ?, ?, ?, ?, ?, ?)`,\n ).run(\n objectId,\n hash,\n bytes.byteLength,\n compression === 'zstd' ? stored.byteLength : null,\n compression,\n options.mimeType ?? null,\n options.encoding ?? null,\n storagePath,\n await blake3HexAsync(stored),\n new Date().toISOString(),\n )\n\n return objectId\n}\n\n/**\n * Store UTF-8 text in the CAS with text metadata.\n */\nexport async function putText(bundle: Bundle, text: string, options: { mimeType?: string } = {}): Promise<ObjectId> {\n const buf = Buffer.from(text, 'utf8')\n return putBytes(bundle, buf, {\n mimeType: options.mimeType ?? 'text/plain; charset=utf-8',\n encoding: 'utf-8',\n })\n}\n\n/**\n * Store a JSON-serialized value in the CAS.\n *\n * Serialization is compact but not canonicalized; callers should not rely on\n * object key ordering for cross-process identity unless the input itself is\n * produced deterministically.\n */\nexport async function putJson(bundle: Bundle, value: unknown): Promise<ObjectId> {\n // Compact serialization. Stable enough for the importer's own writes; we\n // don't promise canonical JSON across producers.\n const text = JSON.stringify(value)\n return putBytes(bundle, Buffer.from(text, 'utf8'), {\n mimeType: 'application/json',\n encoding: 'utf-8',\n })\n}\n\n/**\n * Read and decompress object bytes from the CAS.\n *\n * Throws when `objectId` is absent from the `objects` table; filesystem read or\n * decompression errors also propagate because they indicate bundle corruption\n * or inaccessible storage.\n */\nexport async function getBytes(bundle: Bundle, objectId: ObjectId): Promise<Buffer> {\n const meta = prepare<[string], ObjectMeta>(\n bundle.db,\n `SELECT object_id, hash_alg, hash, size_bytes, compressed_size_bytes,\n compression, mime_type, encoding, storage_path, transport_hash, created_at\n FROM objects WHERE object_id = ?`,\n ).get(objectId)\n if (!meta) {\n throw new Error(`object not found: ${objectId}`)\n }\n const buf = await readFile(path.join(bundle.path, meta.storage_path))\n return decompressBytes(buf, meta.compression)\n}\n\n/**\n * Read an object as UTF-8 text.\n */\nexport async function getText(bundle: Bundle, objectId: ObjectId): Promise<string> {\n const buf = await getBytes(bundle, objectId)\n return buf.toString('utf8')\n}\n\n/**\n * Read an object as UTF-8 JSON and parse it as `T`.\n */\nexport async function getJson<T = unknown>(bundle: Bundle, objectId: ObjectId): Promise<T> {\n const text = await getText(bundle, objectId)\n return JSON.parse(text) as T\n}\n\n/**\n * Look up object metadata without reading object bytes.\n */\nexport function getObjectMeta(bundle: Bundle, objectId: ObjectId): ObjectMeta | null {\n return (\n prepare<[string], ObjectMeta>(\n bundle.db,\n `SELECT object_id, hash_alg, hash, size_bytes, compressed_size_bytes,\n compression, mime_type, encoding, storage_path, transport_hash, created_at\n FROM objects WHERE object_id = ?`,\n ).get(objectId) ?? null\n )\n}\n\n// -- Staging API for high-volume importers ---------------------------------\n//\n// Importers parse thousands of records per file and call putBytes/putJson per\n// record. Doing each as its own SQLite auto-commit + mkdir + writeFile is the\n// dominant cost on a fresh import. The staging API splits CAS work into:\n//\n// 1. stageBytes/stageJson/stageText — synchronous; computes the blake3 hash,\n// builds the ObjectId, and accumulates pending bytes in a per-batch Map\n// deduped by ObjectId. Returns the ObjectId immediately so the rest of\n// the importer can reference it.\n// 2. flushPendingObjects — async; runs once per batch. Bulk-checks which\n// ObjectIds already exist, writes the missing files in parallel, then\n// bulk-inserts the new `objects` rows in a single transaction.\n//\n// The shape lets importers keep their existing\n// `transactional(bundle.db, () => flushPending(...))` block as the only\n// SQLite write boundary for the file, with `flushPendingObjects` running just\n// before that (FS writes can't run inside a sync transaction).\n\n/**\n * Object staged for a high-volume importer flush.\n *\n * Bytes are the original uncompressed payload; compression and storage path are\n * decided once during `flushPendingObjects`.\n */\nexport interface StagedObject {\n objectId: ObjectId\n hash: string\n bytes: Buffer\n mimeType: string | null\n encoding: string | null\n}\n\n/**\n * Mutable per-import accumulator of staged CAS objects, deduped by object ID.\n */\nexport interface PendingObjects {\n byId: Map<ObjectId, StagedObject>\n}\n\n/**\n * Create an empty CAS staging accumulator.\n */\nexport function createPendingObjects(): PendingObjects {\n return { byId: new Map() }\n}\n\n/**\n * Stage bytes for later CAS persistence and return their object ID.\n *\n * This is synchronous and idempotent within the pending set; the first staged\n * metadata for a given object ID wins.\n */\nexport function stageBytes(pending: PendingObjects, bytes: Uint8Array, options: PutOptions = {}): ObjectId {\n const buf = Buffer.isBuffer(bytes) ? bytes : Buffer.from(bytes)\n const hash = blake3Hex(buf)\n const objectId = objectIdFromHash(hash)\n if (!pending.byId.has(objectId)) {\n pending.byId.set(objectId, {\n objectId,\n hash,\n bytes: buf,\n mimeType: options.mimeType ?? null,\n encoding: options.encoding ?? null,\n })\n }\n return objectId\n}\n\n/**\n * Stage UTF-8 text for later CAS persistence.\n */\nexport function stageText(pending: PendingObjects, text: string, options: { mimeType?: string } = {}): ObjectId {\n return stageBytes(pending, Buffer.from(text, 'utf8'), {\n mimeType: options.mimeType ?? 'text/plain; charset=utf-8',\n encoding: 'utf-8',\n })\n}\n\n/**\n * Stage a compact JSON representation for later CAS persistence.\n */\nexport function stageJson(pending: PendingObjects, value: unknown): ObjectId {\n return stageBytes(pending, Buffer.from(JSON.stringify(value), 'utf8'), {\n mimeType: 'application/json',\n encoding: 'utf-8',\n })\n}\n\n/**\n * Flush every staged object to disk and to the `objects` table.\n *\n * Writes happen before the caller's domain transaction starts because\n * better-sqlite3 transactions are synchronous and we want to overlap the\n * filesystem writes with each other. The `objects` rows are inserted with\n * INSERT OR IGNORE, so any rows another writer added between our existence\n * check and our insert are tolerated.\n */\nexport async function flushPendingObjects(bundle: Bundle, pending: PendingObjects): Promise<void> {\n if (pending.byId.size === 0) return\n\n const ids = [...pending.byId.keys()]\n const existingIds = queryExistingObjectIds(bundle, ids)\n\n // Compress once. The same buffer + path are reused for the FS write and\n // the `objects` row.\n /**\n * Fully prepared representation used for both filesystem and SQLite writes.\n */\n interface PreparedObject {\n staged: StagedObject\n compression: Compression\n compressedBytes: Buffer\n storagePath: string\n absolutePath: string\n }\n const toWrite: PreparedObject[] = []\n for (const obj of pending.byId.values()) {\n if (existingIds.has(obj.objectId)) continue\n const { bytes: compressedBytes, compression } = compressBytes(obj.bytes)\n const storagePath = objectStoragePath(obj.hash, compression)\n toWrite.push({\n staged: obj,\n compression,\n compressedBytes,\n storagePath,\n absolutePath: path.join(bundle.path, storagePath),\n })\n }\n\n if (toWrite.length > 0) {\n await writeFilesParallel(toWrite)\n }\n\n // Compute transport hashes in parallel using WASM before entering the sync\n // SQLite insert loop. Promise.all lets the WASM calls overlap.\n const transportHashes = await Promise.all(toWrite.map((p) => blake3HexAsync(p.compressedBytes)))\n\n const insertObject = prepare(\n bundle.db,\n `INSERT OR IGNORE INTO objects (\n object_id, hash_alg, hash, size_bytes, compressed_size_bytes,\n compression, mime_type, encoding, storage_path, transport_hash, created_at\n ) VALUES (?, 'blake3', ?, ?, ?, ?, ?, ?, ?, ?, ?)`,\n )\n const now = new Date().toISOString()\n for (const [i, p] of toWrite.entries()) {\n insertObject.run(\n p.staged.objectId,\n p.staged.hash,\n p.staged.bytes.byteLength,\n p.compression === 'zstd' ? p.compressedBytes.byteLength : null,\n p.compression,\n p.staged.mimeType,\n p.staged.encoding,\n p.storagePath,\n transportHashes[i],\n now,\n )\n }\n}\n\n/**\n * Query existing object IDs in chunks to stay below SQLite variable limits.\n */\nfunction queryExistingObjectIds(bundle: Bundle, ids: ObjectId[]): Set<ObjectId> {\n const found = new Set<ObjectId>()\n if (ids.length === 0) return found\n // SQLite's default SQLITE_LIMIT_VARIABLE_NUMBER is 32766; chunk well under\n // that for safety.\n const CHUNK = 500\n for (let start = 0; start < ids.length; start += CHUNK) {\n const slice = ids.slice(start, start + CHUNK)\n const placeholders = slice.map(() => '?').join(',')\n const rows = bundle.db\n .prepare<ObjectId[], { object_id: ObjectId }>(\n `SELECT object_id FROM objects WHERE object_id IN (${placeholders})`,\n )\n .all(...slice)\n for (const row of rows) found.add(row.object_id)\n }\n return found\n}\n\n/**\n * Maximum concurrent filesystem writes during staged CAS flushes.\n */\nconst FS_WRITE_CONCURRENCY = 16\n\n/**\n * Write compressed object payloads with bounded concurrency.\n *\n * Directory creation is cached via `ensureDir`; individual write failures\n * reject the whole flush.\n */\nasync function writeFilesParallel(tasks: { absolutePath: string; compressedBytes: Buffer }[]): Promise<void> {\n let cursor = 0\n const workers: Promise<void>[] = []\n const limit = Math.min(FS_WRITE_CONCURRENCY, tasks.length)\n for (let w = 0; w < limit; w++) {\n workers.push(\n (async () => {\n while (true) {\n const i = cursor++\n if (i >= tasks.length) return\n const task = tasks[i]!\n await ensureDir(path.dirname(task.absolutePath))\n await writeFile(task.absolutePath, task.compressedBytes)\n }\n })(),\n )\n }\n await Promise.all(workers)\n}\n","import { compress as zstdCompress, decompress as zstdDecompress } from 'zstd-napi'\n\n/**\n * Minimum payload size for zstd compression.\n *\n * Below this threshold the zstd frame overhead and CPU cost are not worth the\n * small storage savings.\n */\nconst COMPRESS_THRESHOLD_BYTES = 256\n\n/**\n * Conservative zstd level used for importer throughput.\n */\nconst ZSTD_LEVEL = 3\n\n/**\n * Stored object compression marker persisted in the `objects` table.\n */\nexport type Compression = 'zstd' | 'none'\n\n/**\n * Bytes plus the storage codec needed to recover them.\n */\nexport interface CompressionResult {\n bytes: Buffer\n compression: Compression\n}\n\n/**\n * Compress bytes when they are large enough to benefit.\n *\n * Returns a Buffer regardless of input type. Small payloads are copied and\n * tagged as `none` so reads can skip decompression.\n */\nexport function compressBytes(input: Uint8Array): CompressionResult {\n if (input.byteLength < COMPRESS_THRESHOLD_BYTES) {\n return { bytes: Buffer.from(input), compression: 'none' }\n }\n const out = zstdCompress(Buffer.from(input), { compressionLevel: ZSTD_LEVEL })\n return { bytes: out, compression: 'zstd' }\n}\n\n/**\n * Reverse `compressBytes` according to the persisted compression marker.\n */\nexport function decompressBytes(input: Buffer, compression: Compression): Buffer {\n if (compression === 'none') return input\n return zstdDecompress(input)\n}\n","import { createHash } from 'node:crypto'\nimport { blake3 as nobleBlake3 } from '@noble/hashes/blake3'\nimport { bytesToHex } from '@noble/hashes/utils'\nimport { blake3 as wasmBlake3 } from 'hash-wasm'\n\n/**\n * Hash bytes with BLAKE3 and return lowercase hex.\n *\n * Uses the pure-JS @noble/hashes implementation to remain synchronous.\n * Call sites that are already async should use blake3HexAsync instead for\n * better throughput via the WASM implementation.\n */\nexport function blake3Hex(bytes: Uint8Array): string {\n return bytesToHex(nobleBlake3(bytes))\n}\n\n/**\n * Hash bytes with BLAKE3 and return lowercase hex.\n *\n * Uses the hash-wasm WASM implementation for better throughput on large\n * payloads. Output is byte-identical to blake3Hex for the same input.\n * Prefer this in async call sites (putBytes, flushPendingObjects, etc.).\n */\nexport async function blake3HexAsync(bytes: Uint8Array): Promise<string> {\n return wasmBlake3(bytes)\n}\n\n/**\n * Hash bytes or text with SHA-256 and return lowercase hex.\n */\nexport function sha256Hex(bytes: Uint8Array | string): string {\n return createHash('sha256').update(bytes).digest('hex')\n}\n\n/** \"blake3:<hex>\" — the canonical object_id format in the schema. */\nexport function objectIdFromHash(hashHex: string): string {\n return `blake3:${hashHex}`\n}\n\n/**\n * Storage path under `objects/blake3/`: `ab/cd/<hash>.zst` to avoid one giant\n * directory. Uses the first 4 hex chars (2-level fanout).\n */\nexport function objectStoragePath(hashHex: string, compression: 'zstd' | 'none'): string {\n const ext = compression === 'zstd' ? '.zst' : '.bin'\n const a = hashHex.slice(0, 2)\n const b = hashHex.slice(2, 4)\n return `objects/blake3/${a}/${b}/${hashHex}${ext}`\n}\n","import { sha256Hex } from '../cas/hash.js'\n\n// Deterministic IDs let reimports converge on the same row instead of\n// duplicating. The shape is sha256 of a tuple of natural keys, hex-truncated\n// to 32 chars (128 bits). 128 bits is overkill for collision but makes IDs\n// short enough to grep without losing essentially zero safety.\n\n/**\n * Number of hash bytes retained for deterministic catalog IDs.\n */\nconst ID_PREFIX_BYTES = 16 // 128 bits => 32 hex chars\n\n/**\n * Build a deterministic fixed-width ID from natural-key tuple components.\n *\n * The NUL separator is outside normal path/session identifiers and avoids\n * ambiguous concatenations between differently shaped tuples.\n */\nfunction tupleId(parts: readonly string[]): string {\n // The separator avoids ambiguity between (\"a:b\",\"c\") and (\"a\",\"b:c\").\n return sha256Hex(parts.join('\u0000')).slice(0, ID_PREFIX_BYTES * 2)\n}\n\n/**\n * Deterministic ID for one preserved source-file version.\n *\n * The content hash is part of the key so modified files preserve historical\n * source rows instead of overwriting prior projections.\n */\nexport function sourceFileId(sourceTool: string, absolutePath: string, contentHash: string): string {\n // Includes contentHash so that a modified version of the same file gets a\n // new row instead of clashing with the previous import (which we keep around\n // for history / re-projection).\n return tupleId(['source_file', sourceTool, absolutePath, contentHash])\n}\n\n/**\n * Deterministic ID for a raw record recovered from a source file.\n *\n * `ordinal` may be null for single-record or pointer-addressed formats; it is\n * normalized to `-1` so the tuple remains stable.\n */\nexport function rawRecordId(sourceFileId: string, ordinal: number | null, rawObjectId: string): string {\n return tupleId(['raw_record', sourceFileId, String(ordinal ?? -1), rawObjectId])\n}\n\n/**\n * Deterministic ID for a logical session from a source tool.\n */\nexport function sessionId(sourceTool: string, sourceSessionId: string): string {\n return tupleId(['session', sourceTool, sourceSessionId])\n}\n\n/**\n * Deterministic ID for a turn within a session ordinal stream.\n */\nexport function turnId(sessionId: string, ordinal: number, sourceTurnId?: string | null): string {\n return tupleId(['turn', sessionId, String(ordinal), sourceTurnId ?? ''])\n}\n\n/**\n * Deterministic ID for an event when only session, ordinal, and kind are stable.\n */\nexport function eventId(sessionId: string, ordinal: number, kind: string): string {\n return tupleId(['event', sessionId, String(ordinal), kind])\n}\n\n/**\n * Deterministic ID for a message within a session ordinal stream.\n */\nexport function messageId(sessionId: string, ordinal: number, sourceMsgId?: string | null): string {\n return tupleId(['message', sessionId, String(ordinal), sourceMsgId ?? ''])\n}\n\n/**\n * Deterministic ID for a content block attached to a message or event.\n */\nexport function blockId(messageOrEventId: string, ordinal: number): string {\n return tupleId(['block', messageOrEventId, String(ordinal)])\n}\n\n/**\n * Deterministic ID for a tool call scoped by session and native call ID.\n */\nexport function toolCallId(sessionId: string, sourceCallId: string): string {\n return tupleId(['tool_call', sessionId, sourceCallId])\n}\n\n/**\n * Deterministic ID for a tool result scoped by session and native call ID.\n */\nexport function toolResultId(sessionId: string, sourceCallId: string): string {\n return tupleId(['tool_result', sessionId, sourceCallId])\n}\n\n/**\n * Deterministic ID for an artifact keyed by source tool and source-specific\n * artifact key. `sessionId` may be null for workspace-level artifacts.\n */\nexport function artifactId(sessionId: string | null, sourceTool: string, key: string): string {\n return tupleId(['artifact', sessionId ?? '', sourceTool, key])\n}\n\n/**\n * Deterministic ID for a source-tool project/workspace identity.\n */\nexport function projectId(sourceTool: string, sourceProjectId: string): string {\n return tupleId(['project', sourceTool, sourceProjectId])\n}\n\n/**\n * Import batch IDs are intentionally unique per run, not idempotent.\n *\n * `startedAtIso` keeps IDs sortable-ish while the random component avoids\n * collisions for concurrent or same-millisecond batch starts.\n */\nexport function importBatchId(sourceTool: string, startedAtIso: string): string {\n return tupleId(['import_batch', sourceTool, startedAtIso, String(Math.random())])\n}\n","import type { Bundle } from '../bundle.js'\nimport { type ObjectId, putJson } from '../cas/index.js'\nimport { prepare } from '../db.js'\nimport { importBatchId } from '../domain/ids.js'\nimport type { SourceTool } from '../domain/types.js'\nimport { PROSA_PARSER_VERSION } from '../version.js'\n\n/**\n * In-memory representation of an `import_batches` row while a compile/import\n * run is active.\n *\n * `finished_at` is populated only after `finishBatch` persists terminal status.\n */\nexport interface ImportBatch {\n /** Stable batch identifier derived from source and start time. */\n batch_id: string\n /** Source importer for this batch, or null for multi-source orchestration. */\n source_tool: SourceTool | null\n /** Parser version that produced this batch. */\n parser_version: string\n /** Source roots or files covered by the batch. */\n paths: string[]\n /** ISO timestamp when the batch was created. */\n started_at: string\n /** ISO timestamp set after terminal status is persisted. */\n finished_at?: string\n}\n\n/**\n * Per-batch counters serialized into `import_batches.counts_json`.\n *\n * Counts describe importer work, not necessarily net-new durable rows; skipped\n * source files and idempotent inserts are tracked explicitly.\n */\nexport interface ImportCounts {\n /** Source files discovered by the importer. */\n source_files_seen: number\n /** Source files parsed and imported. */\n source_files_imported: number\n /** Source files skipped by idempotency checks. */\n source_files_skipped: number\n /** Raw source records preserved. */\n raw_records: number\n /** Session rows inserted or updated. */\n sessions: number\n /** Turn rows inserted or updated. */\n turns: number\n /** Timeline event rows inserted or updated. */\n events: number\n /** Message rows inserted or updated. */\n messages: number\n /** Content block rows inserted or updated. */\n content_blocks: number\n /** Tool call rows inserted or updated. */\n tool_calls: number\n /** Tool result rows inserted or updated. */\n tool_results: number\n /** Artifact rows inserted or updated. */\n artifacts: number\n /** Edge rows inserted or updated. */\n edges: number\n /** Import errors recorded for the batch. */\n errors: number\n}\n\n/**\n * Create a zeroed counter object for a new import batch.\n */\nexport function emptyCounts(): ImportCounts {\n return {\n source_files_seen: 0,\n source_files_imported: 0,\n source_files_skipped: 0,\n raw_records: 0,\n sessions: 0,\n turns: 0,\n events: 0,\n messages: 0,\n content_blocks: 0,\n tool_calls: 0,\n tool_results: 0,\n artifacts: 0,\n edges: 0,\n errors: 0,\n }\n}\n\n/**\n * Insert a running import batch and return its process-local handle.\n *\n * Batch IDs are intentionally unique per run so repeated compiles preserve\n * their own audit trail even when all source rows are skipped idempotently.\n */\nexport function startBatch(bundle: Bundle, sourceTool: SourceTool | null, paths: string[]): ImportBatch {\n const startedAt = new Date().toISOString()\n const id = importBatchId(sourceTool ?? 'all', startedAt)\n prepare(\n bundle.db,\n `INSERT INTO import_batches (\n batch_id, parser_version, source_tool, paths, started_at, status\n ) VALUES (?, ?, ?, ?, ?, 'running')`,\n ).run(id, PROSA_PARSER_VERSION, sourceTool, JSON.stringify(paths), startedAt)\n\n return {\n batch_id: id,\n source_tool: sourceTool,\n parser_version: PROSA_PARSER_VERSION,\n paths,\n started_at: startedAt,\n }\n}\n\n/**\n * Mark an import batch completed or failed and persist final counts.\n */\nexport function finishBatch(\n bundle: Bundle,\n batch: ImportBatch,\n counts: ImportCounts,\n status: 'completed' | 'failed',\n): void {\n prepare(\n bundle.db,\n `UPDATE import_batches\n SET finished_at = ?, status = ?, counts_json = ?\n WHERE batch_id = ?`,\n ).run(new Date().toISOString(), status, JSON.stringify(counts), batch.batch_id)\n}\n\n/**\n * Record an importer error tied to an optional source file or raw record.\n *\n * Non-string payloads are preserved in the CAS as JSON and referenced from the\n * error row; this keeps diagnostic detail out of inline SQLite columns while\n * preserving it for later inspection.\n */\nexport async function recordError(\n bundle: Bundle,\n batchId: string,\n args: {\n sourceFileId?: string | null\n rawRecordId?: string | null\n kind: string\n message: string\n payload?: unknown\n },\n): Promise<void> {\n let payloadObjectId: ObjectId | null = null\n if (args.payload !== undefined) {\n payloadObjectId = await putJson(bundle, args.payload)\n }\n prepare(\n bundle.db,\n `INSERT INTO import_errors (\n batch_id, source_file_id, raw_record_id, kind, message,\n payload_object_id, occurred_at\n ) VALUES (?, ?, ?, ?, ?, ?, ?)`,\n ).run(\n batchId,\n args.sourceFileId ?? null,\n args.rawRecordId ?? null,\n args.kind,\n args.message,\n payloadObjectId,\n new Date().toISOString(),\n )\n}\n","import { access, readFile, stat, writeFile } from 'node:fs/promises'\nimport path from 'node:path'\nimport type { Bundle } from '../bundle.js'\nimport { compressBytes } from '../cas/compress.js'\nimport { blake3HexAsync, objectIdFromHash, sha256Hex } from '../cas/hash.js'\nimport { ensureDir } from '../cas/index.js'\nimport { prepare } from '../db.js'\nimport { sourceFileId } from '../domain/ids.js'\nimport type { SourceTool } from '../domain/types.js'\n\n/**\n * Complete `source_files` row used by source discovery and importer idempotency.\n *\n * Paths are absolute source paths. `object_id` points at preserved raw source\n * bytes and may be backfilled for rows created before raw preservation existed.\n */\nexport interface SourceFileRow {\n /** Stable source file identifier. */\n source_file_id: string\n /** Importer that discovered the file. */\n source_tool: SourceTool\n /** Absolute path to the native source file. */\n path: string\n /** Importer-specific file kind. */\n file_kind: string\n /** File size observed during discovery. */\n size_bytes: number\n /** Filesystem modification time as ISO text, when available. */\n mtime: string | null\n /** SHA-256 content hash used for idempotency. */\n content_hash: string\n /** CAS object ID for preserved raw bytes, if available. */\n object_id: string | null\n /** ISO timestamp when the file was first registered. */\n discovered_at: string\n /** Optional project/workspace hint derived during discovery. */\n workspace_hint: string | null\n}\n\n/**\n * Result of source-file registration.\n *\n * `alreadyKnown` means the same path/content tuple was already registered and\n * the caller can usually skip parsing/importing the file.\n */\nexport interface RegisterResult {\n /** Registered source file row. */\n row: SourceFileRow\n /** True when the caller can usually skip parsing the file. */\n alreadyKnown: boolean\n}\n\n/**\n * Idempotent registration of a source file. The natural key is\n * (source_tool, path, size, mtime, content_hash). If a row with the same\n * tuple already exists we return it untouched and the caller can skip\n * re-importing. Otherwise we insert a new row.\n *\n * This is the cheapest form of idempotency: re-running `prosa compile` over\n * the same Codex tree is a no-op (no rehash unless the file changed).\n */\nexport async function registerSourceFile(\n bundle: Bundle,\n args: {\n sourceTool: SourceTool\n absolutePath: string\n fileKind: string\n workspaceHint?: string | null\n },\n): Promise<RegisterResult> {\n const st = await stat(args.absolutePath)\n const size = st.size\n const mtime = st.mtime.toISOString()\n\n // Hash on demand. We could memoize per (path,size,mtime) but the cheap\n // pre-check below already covers the common case.\n const cheap = prepare<[SourceTool, string, number, string], SourceFileRow>(\n bundle.db,\n `SELECT source_file_id, source_tool, path, file_kind, size_bytes, mtime,\n content_hash, object_id, discovered_at, workspace_hint\n FROM source_files\n WHERE source_tool = ? AND path = ? AND size_bytes = ? AND mtime = ?\n LIMIT 1`,\n ).get(args.sourceTool, args.absolutePath, size, mtime)\n\n if (cheap) {\n return {\n row: await ensureSourceFilePreserved(bundle, cheap, args.absolutePath),\n alreadyKnown: true,\n }\n }\n\n const buf = await readFile(args.absolutePath)\n const contentHash = sha256Hex(buf)\n\n // Slow path: same content under same path was perhaps re-saved with new\n // mtime; honor the (tool,path,size,mtime,hash) UNIQUE constraint.\n const exact = prepare<[SourceTool, string, string], SourceFileRow>(\n bundle.db,\n `SELECT source_file_id, source_tool, path, file_kind, size_bytes, mtime,\n content_hash, object_id, discovered_at, workspace_hint\n FROM source_files\n WHERE source_tool = ? AND path = ? AND content_hash = ?\n LIMIT 1`,\n ).get(args.sourceTool, args.absolutePath, contentHash)\n\n if (exact) {\n return {\n row: await ensureSourceFilePreserved(bundle, exact, args.absolutePath, buf),\n alreadyKnown: true,\n }\n }\n\n const objectId = await preserveRawSourceBytes(bundle, buf)\n\n const id = sourceFileId(args.sourceTool, args.absolutePath, contentHash)\n const row: SourceFileRow = {\n source_file_id: id,\n source_tool: args.sourceTool,\n path: args.absolutePath,\n file_kind: args.fileKind,\n size_bytes: size,\n mtime,\n content_hash: contentHash,\n object_id: objectId,\n discovered_at: new Date().toISOString(),\n workspace_hint: args.workspaceHint ?? null,\n }\n\n prepare(\n bundle.db,\n `INSERT INTO source_files (\n source_file_id, source_tool, path, file_kind, size_bytes, mtime,\n content_hash, object_id, discovered_at, workspace_hint\n ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,\n ).run(\n row.source_file_id,\n row.source_tool,\n row.path,\n row.file_kind,\n row.size_bytes,\n row.mtime,\n row.content_hash,\n row.object_id,\n row.discovered_at,\n row.workspace_hint,\n )\n\n return { row, alreadyKnown: false }\n}\n\n/**\n * Backfill raw-byte preservation for an existing `source_files` row.\n *\n * Older rows or cheap-path matches may not have `object_id`; this helper stores\n * the current source bytes and updates the row before returning it.\n */\nasync function ensureSourceFilePreserved(\n bundle: Bundle,\n row: SourceFileRow,\n absolutePath: string,\n bytes?: Buffer,\n): Promise<SourceFileRow> {\n if (row.object_id) return row\n\n const sourceBytes = bytes ?? (await readFile(absolutePath))\n const objectId = await preserveRawSourceBytes(bundle, sourceBytes)\n\n prepare<[string, string]>(bundle.db, `UPDATE source_files SET object_id = ? WHERE source_file_id = ?`).run(\n objectId,\n row.source_file_id,\n )\n\n return { ...row, object_id: objectId }\n}\n\n/**\n * Preserve raw source bytes outside the main CAS fanout and record them in\n * `objects`.\n *\n * The storage path is `raw/sources/<blake3>.<ext>` so original input files are\n * easy to distinguish from normalized payloads under `objects/blake3`. The DB\n * insert is idempotent, and the file write is skipped if the object already\n * exists on disk.\n */\nasync function preserveRawSourceBytes(bundle: Bundle, bytes: Uint8Array): Promise<string> {\n const hash = await blake3HexAsync(bytes)\n const objectId = objectIdFromHash(hash)\n const { bytes: stored, compression } = compressBytes(bytes)\n const storagePath = rawSourceStoragePath(hash, compression)\n const absolutePath = path.join(bundle.path, storagePath)\n\n await ensureDir(path.dirname(absolutePath))\n if (!(await fileExists(absolutePath))) {\n await writeFile(absolutePath, stored)\n }\n\n const existing = prepare<[string], { object_id: string }>(\n bundle.db,\n `SELECT object_id FROM objects WHERE object_id = ?`,\n ).get(objectId)\n\n if (!existing) {\n prepare(\n bundle.db,\n `INSERT INTO objects (\n object_id, hash_alg, hash, size_bytes, compressed_size_bytes,\n compression, mime_type, encoding, storage_path, transport_hash, created_at\n ) VALUES (?, 'blake3', ?, ?, ?, ?, ?, ?, ?, ?, ?)`,\n ).run(\n objectId,\n hash,\n bytes.byteLength,\n compression === 'zstd' ? stored.byteLength : null,\n compression,\n 'application/octet-stream',\n null,\n storagePath,\n await blake3HexAsync(stored),\n new Date().toISOString(),\n )\n }\n\n return objectId\n}\n\n/**\n * Relative bundle path for preserved raw source bytes.\n */\nfunction rawSourceStoragePath(hashHex: string, compression: 'zstd' | 'none'): string {\n const ext = compression === 'zstd' ? '.zst' : '.bin'\n return `raw/sources/${hashHex}${ext}`\n}\n\nasync function fileExists(filePath: string): Promise<boolean> {\n try {\n await access(filePath)\n return true\n } catch {\n return false\n }\n}\n","/**\n * Bounds and default for CLI/API limit values.\n */\nexport interface ClampLimitOptions {\n min?: number\n max: number\n fallback: number\n}\n\n/**\n * Clamp a possibly-missing numeric limit into an inclusive range.\n *\n * Undefined values resolve to `fallback`; omitted `min` defaults to 1 so\n * callers do not accidentally request empty or unbounded result sets.\n */\nexport function clampLimit(value: number | undefined, opts: ClampLimitOptions): number {\n return Math.max(opts.min ?? 1, Math.min(opts.max, value ?? opts.fallback))\n}\n","import type { Bundle } from '../core/bundle.js'\nimport type { Confidence, SourceTool } from '../core/domain/types.js'\nimport { clampLimit } from '../core/limits.js'\n\n/** Filters applied consistently to session list and count queries. */\nexport interface SessionListFilters {\n /** Restrict results to one source tool. */\n sourceTool?: SourceTool\n /** Inclusive lower bound for `start_ts`; unknown timestamps are retained. */\n sinceIso?: string\n /** Exclusive upper bound for `start_ts`; unknown timestamps are retained. */\n untilIso?: string\n /** Maximum rows to return, clamped by service limits. */\n limit?: number\n}\n\n/** Summary row returned by session listing surfaces. */\nexport interface SessionRow {\n /** Canonical prosa session identifier. */\n session_id: string\n /** Source tool that produced the session. */\n source_tool: SourceTool\n /** Native source session identifier. */\n source_session_id: string\n /** Canonical project identifier this session belongs to, when one was recovered. */\n project_id: string | null\n /** Parent session for subagent sessions. */\n parent_session_id: string | null\n /** SQLite boolean indicating whether this is a subagent session. */\n is_subagent: 0 | 1\n /** Best recovered title. */\n title: string | null\n /** Earliest recovered timestamp. */\n start_ts: string | null\n /** Latest recovered timestamp. */\n end_ts: string | null\n /** Initial working directory. */\n cwd_initial: string | null\n /** Initial git branch. */\n git_branch_initial: string | null\n /** First observed model. */\n model_first: string | null\n /** Last observed model. */\n model_last: string | null\n /** Source or importer status. */\n status: string | null\n /** Confidence in recovered timeline ordering. */\n timeline_confidence: Confidence\n /** Number of messages attached to the session. */\n message_count: number\n /** Number of tool calls attached to the session. */\n tool_call_count: number\n}\n\n/** Builds the shared WHERE clause so list and count stay filter-equivalent. */\nfunction sessionFilterWhere(filters: SessionListFilters): { where: string; params: unknown[] } {\n const conds: string[] = []\n const params: unknown[] = []\n\n if (filters.sourceTool) {\n conds.push('s.source_tool = ?')\n params.push(filters.sourceTool)\n }\n if (filters.sinceIso) {\n conds.push('(s.start_ts IS NULL OR s.start_ts >= ?)')\n params.push(filters.sinceIso)\n }\n if (filters.untilIso) {\n conds.push('(s.start_ts IS NULL OR s.start_ts < ?)')\n params.push(filters.untilIso)\n }\n\n return {\n where: conds.length ? `WHERE ${conds.join(' AND ')}` : '',\n params,\n }\n}\n\n/** Lists sessions newest-first, preserving rows with unknown timestamps at the end. */\nexport function listSessions(bundle: Bundle, filters: SessionListFilters = {}): SessionRow[] {\n const { where, params } = sessionFilterWhere(filters)\n const limit = clampLimit(filters.limit, { max: 1000, fallback: 50 })\n\n const sql = `\n SELECT s.session_id,\n s.source_tool,\n s.source_session_id,\n s.project_id,\n s.parent_session_id,\n s.is_subagent,\n s.title,\n s.start_ts,\n s.end_ts,\n s.cwd_initial,\n s.git_branch_initial,\n s.model_first,\n s.model_last,\n s.status,\n s.timeline_confidence,\n (SELECT count(*) FROM messages m WHERE m.session_id = s.session_id) AS message_count,\n (SELECT count(*) FROM tool_calls tc WHERE tc.session_id = s.session_id) AS tool_call_count\n FROM sessions s\n ${where}\n ORDER BY s.start_ts DESC NULLS LAST\n LIMIT ${limit}\n `\n\n return bundle.db.prepare(sql).all(...params) as SessionRow[]\n}\n\n/** Counts sessions using the same filter policy as {@link listSessions}. */\nexport function countSessions(bundle: Bundle, filters: SessionListFilters = {}): number {\n const { where, params } = sessionFilterWhere(filters)\n const row = bundle.db\n .prepare(\n `\n SELECT count(*) AS count\n FROM sessions s\n ${where}\n `,\n )\n .get(...params) as { count: number } | undefined\n\n return row?.count ?? 0\n}\n\n/** Timeline event row used by session detail views. */\nexport interface SessionDetailEvent {\n /** Timeline ordinal within the session. */\n ordinal: number\n /** Event timestamp when known. */\n timestamp: string | null\n /** Canonical event type. */\n event_type: string\n /** Native source event type, when retained. */\n source_type: string | null\n /** Source-specific event subtype. */\n subtype: string | null\n /** Actor associated with the event. */\n actor: string | null\n /** Message row attached to the event. */\n message_id: string | null\n /** Message role attached to the event. */\n role: string | null\n /** Tool name attached to the event. */\n tool_name: string | null\n /** SQLite boolean indicating a failed tool result. */\n is_error: 0 | 1 | null\n /** Human-sized preview for detail rendering. */\n preview: string | null\n}\n\n/** Full session detail with summary metadata and ordered timeline events. */\nexport interface SessionDetail {\n /** Session summary row. */\n session: SessionRow\n /** Ordered timeline events. */\n events: SessionDetailEvent[]\n}\n\n/** Returns a single session with its event timeline, or null when absent. */\nexport function getSession(bundle: Bundle, sessionId: string): SessionDetail | null {\n const rows = listSessions(bundle) // small query reused for shape\n const row = bundle.db\n .prepare<[string], SessionRow>(\n `SELECT s.session_id, s.source_tool, s.source_session_id, s.project_id,\n s.parent_session_id, s.is_subagent, s.title, s.start_ts, s.end_ts,\n s.cwd_initial, s.git_branch_initial, s.model_first, s.model_last,\n s.status, s.timeline_confidence,\n (SELECT count(*) FROM messages m WHERE m.session_id = s.session_id) AS message_count,\n (SELECT count(*) FROM tool_calls tc WHERE tc.session_id = s.session_id) AS tool_call_count\n FROM sessions s\n WHERE s.session_id = ?`,\n )\n .get(sessionId)\n void rows\n if (!row) return null\n\n const events = bundle.db\n .prepare<[string], SessionDetailEvent>(\n `SELECT e.ordinal,\n e.timestamp,\n e.event_type,\n e.source_type,\n e.subtype,\n e.actor,\n m.message_id,\n m.role,\n tc.tool_name,\n tr.is_error,\n tr.preview\n FROM events e\n LEFT JOIN messages m ON m.event_id = e.event_id\n LEFT JOIN tool_calls tc ON tc.event_id = e.event_id\n LEFT JOIN tool_results tr ON tr.event_id = e.event_id\n WHERE e.session_id = ?\n ORDER BY e.ordinal`,\n )\n .all(sessionId)\n\n return { session: row, events }\n}\n","import { existsSync } from 'node:fs'\nimport { createRequire } from 'node:module'\nimport type { Bundle } from '../core/bundle.js'\nimport { getErrorMessage } from '../core/errors.js'\nimport { clampLimit } from '../core/limits.js'\nimport { type SearchEngine, getSearchIndexStatus } from './indexing.js'\n\nconst require = createRequire(import.meta.url)\n\n/** Search result projected from either FTS5 or Tantivy into the common service shape. */\nexport interface SearchHit {\n /** Search document identifier. */\n doc_id: string\n /** Indexed entity kind. */\n entity_type: string\n /** Identifier of the indexed entity. */\n entity_id: string\n /** Session that owns the document, when applicable. */\n session_id: string | null\n /** Timestamp used for result ordering. */\n timestamp: string | null\n /** Message role associated with the document. */\n role: string | null\n /** Tool name associated with the document. */\n tool_name: string | null\n /** Indexed text field category. */\n field_kind: string\n /** Highlighted or truncated result snippet. */\n snippet: string\n}\n\n/** Options for full-text search across indexed conversation and tool evidence. */\nexport interface SearchOptions {\n /** Query text, interpreted by the selected engine. */\n query: string\n /** Maximum hit count, clamped by service limits. */\n limit?: number\n /** Search backend to query; defaults to FTS5. */\n engine?: SearchEngine\n /**\n * When true, pass `query` straight to FTS5 (MATCH expression). When false\n * (default), each whitespace-delimited token is wrapped in double quotes so\n * punctuation like `package.json` doesn't trip the FTS5 parser. Set true if\n * you want to use FTS5 operators like `OR`, `NEAR`, prefixes, etc.\n */\n raw?: boolean\n}\n\n/**\n * Wrap each whitespace-delimited token in double quotes so the FTS5 parser\n * treats them as phrases. This avoids syntax errors on punctuation that the\n * unicode61 tokenizer splits on (dots, slashes, hyphens, etc.) while still\n * AND-matching across tokens.\n */\nfunction escapeFtsQuery(q: string): string {\n return q\n .split(/\\s+/)\n .filter((t) => t.length > 0)\n .map((t) => `\"${t.replace(/\"/g, '\"\"')}\"`)\n .join(' ')\n}\n\n/** Runs full-text search with FTS5 by default, or Tantivy when requested. */\nexport function searchFullText(bundle: Bundle, options: SearchOptions): SearchHit[] {\n if (options.engine === 'tantivy') {\n return searchTantivy(bundle, options)\n }\n\n const limit = clampLimit(options.limit, { max: 500, fallback: 50 })\n const sql = `\n SELECT d.doc_id,\n d.entity_type,\n d.entity_id,\n d.session_id,\n d.timestamp,\n d.role,\n d.tool_name,\n d.field_kind,\n snippet(search_docs_fts, 0, '⟪', '⟫', '…', 12) AS snippet\n FROM search_docs_fts\n JOIN search_docs d ON d.rowid = search_docs_fts.rowid\n WHERE search_docs_fts MATCH ?\n ORDER BY bm25(search_docs_fts), d.timestamp DESC\n LIMIT ${limit}\n `\n const ftsQuery = options.raw ? options.query : escapeFtsQuery(options.query)\n if (!ftsQuery) return []\n return bundle.db.prepare(sql).all(ftsQuery) as SearchHit[]\n}\n\n/** Searches the Tantivy sidecar and maps stored fields back to {@link SearchHit}. */\nfunction searchTantivy(bundle: Bundle, options: SearchOptions): SearchHit[] {\n if (!existsSync(bundle.paths.tantivy)) {\n throw new Error('tantivy index not found; run `prosa index tantivy` first')\n }\n\n const status = getSearchIndexStatus(bundle, 'tantivy')\n if (status?.status !== 'ready') {\n throw new Error(`tantivy index is ${status?.status ?? 'missing'}; run \\`prosa index tantivy\\` first`)\n }\n\n const limit = clampLimit(options.limit, { max: 500, fallback: 50 })\n const queryText = options.query.trim()\n if (!queryText) return []\n\n const tantivy = requireTantivy()\n const index = tantivy.Index.open(bundle.paths.tantivy)\n const searcher = index.searcher()\n const [query] = options.raw\n ? [index.parseQuery(queryText, ['text'])]\n : index.parseQueryLenient(queryText, ['text'], undefined, {\n text: [true, 2, true],\n })\n const result = searcher.search(query, limit, true)\n const snippets = tantivy.SnippetGenerator.create(searcher, query, index.schema, 'text')\n snippets.setMaxNumChars(180)\n\n return result.hits.map((hit: TantivySearchHit) => {\n const doc = searcher.doc(hit.docAddress)\n const snippet = snippets.snippetFromDoc(doc)\n const text = getStoredText(doc, 'text')\n const renderedSnippet = snippet.fragment()\n ? highlightSnippet(snippet.fragment(), snippet.highlighted())\n : text.slice(0, 180)\n return {\n doc_id: getStoredText(doc, 'doc_id'),\n entity_type: getStoredText(doc, 'entity_type'),\n entity_id: getStoredText(doc, 'entity_id'),\n session_id: nullIfEmpty(getStoredText(doc, 'session_id')),\n timestamp: nullIfEmpty(getStoredText(doc, 'timestamp')),\n role: nullIfEmpty(getStoredText(doc, 'role')),\n tool_name: nullIfEmpty(getStoredText(doc, 'tool_name')),\n field_kind: getStoredText(doc, 'field_kind'),\n snippet: renderedSnippet,\n }\n })\n}\n\ntype TantivyModule = typeof import('@oxdev03/node-tantivy-binding')\ntype TantivyDocument = InstanceType<TantivyModule['Document']>\ntype TantivySearchHit = import('@oxdev03/node-tantivy-binding').SearchHit\n\n/** Loads the optional Tantivy binding and normalizes missing-module failures. */\nfunction requireTantivy(): TantivyModule {\n try {\n return require('@oxdev03/node-tantivy-binding') as TantivyModule\n } catch (error) {\n throw new Error(`tantivy engine is unavailable: ${getErrorMessage(error)}`)\n }\n}\n\n/** Reads a stored Tantivy text field across scalar and array binding shapes. */\nfunction getStoredText(doc: TantivyDocument, field: string): string {\n const value = doc.getFirst(field)\n if (typeof value === 'string') return value\n if (Array.isArray(value) && typeof value[0] === 'string') return value[0]\n if (value == null) return ''\n return String(value)\n}\n\n/** Converts Tantivy's empty-string null sentinel back to service-level null. */\nfunction nullIfEmpty(value: string): string | null {\n return value.length > 0 ? value : null\n}\n\n/** Renders Tantivy highlight byte ranges with the same markers used by FTS5 snippets. */\nfunction highlightSnippet(fragment: string, ranges: Array<{ start: number; end: number }>): string {\n if (ranges.length === 0) return fragment\n\n let out = ''\n let cursor = 0\n for (const range of ranges) {\n out += fragment.slice(cursor, range.start)\n out += `⟪${fragment.slice(range.start, range.end)}⟫`\n cursor = range.end\n }\n out += fragment.slice(cursor)\n return out\n}\n","/**\n * Convert unknown caught values into a display/log-safe message string.\n */\nexport const getErrorMessage = (err: unknown): string => (err instanceof Error ? err.message : String(err))\n","import { createHash } from 'node:crypto'\nimport { existsSync } from 'node:fs'\nimport { mkdir, rm, writeFile } from 'node:fs/promises'\nimport path from 'node:path'\nimport type { Bundle } from '../core/bundle.js'\nimport { prepare, transactional } from '../core/db.js'\nimport { getErrorMessage } from '../core/errors.js'\n\n/** Supported search backends tracked by the bundle. */\nexport type SearchEngine = 'fts5' | 'tantivy'\n\n/** Persisted status row for a search index sidecar. */\nexport interface SearchIndexStatus {\n /** Search backend represented by this status row. */\n engine: SearchEngine\n /** Current index lifecycle state. */\n status: 'missing' | 'ready' | 'stale' | 'building' | 'failed'\n /** Number of canonical search_docs rows available to index. */\n source_doc_count: number\n /** Number of documents known to be present in the index. */\n indexed_doc_count: number\n /** ISO timestamp for the last status update. */\n updated_at: string\n /** Last build error message, if the index failed. */\n error_message: string | null\n /** Last indexed SQLite rowid for incremental sidecars. */\n last_indexed_rowid: number | null\n /** Schema fingerprint used to decide whether incremental rebuild is valid. */\n schema_fingerprint: string | null\n}\n\n/** Canonical search document row used to feed external indexes. */\ninterface SearchDocRow {\n rowid: number\n doc_id: string\n entity_type: string\n entity_id: string\n session_id: string | null\n project_id: string | null\n timestamp: string | null\n role: string | null\n tool_name: string | null\n canonical_tool_type: string | null\n field_kind: string\n text: string\n}\n\n/** Shared projection for search index status queries. */\nconst SEARCH_INDEX_STATUS_COLUMNS = `\n engine, status, source_doc_count, indexed_doc_count, updated_at,\n error_message, last_indexed_rowid, schema_fingerprint\n`\n\n/** Triggers that keep the SQLite FTS5 virtual table synchronized with search_docs. */\nconst FTS5_TRIGGER_SQL = `\nCREATE TRIGGER IF NOT EXISTS search_docs_ai AFTER INSERT ON search_docs BEGIN\n INSERT INTO search_docs_fts(rowid, text, role, tool_name, field_kind)\n VALUES (new.rowid, new.text, new.role, new.tool_name, new.field_kind);\nEND;\n\nCREATE TRIGGER IF NOT EXISTS search_docs_ad AFTER DELETE ON search_docs BEGIN\n INSERT INTO search_docs_fts(search_docs_fts, rowid, text, role, tool_name, field_kind)\n VALUES('delete', old.rowid, old.text, old.role, old.tool_name, old.field_kind);\nEND;\n\nCREATE TRIGGER IF NOT EXISTS search_docs_au AFTER UPDATE ON search_docs BEGIN\n INSERT INTO search_docs_fts(search_docs_fts, rowid, text, role, tool_name, field_kind)\n VALUES('delete', old.rowid, old.text, old.role, old.tool_name, old.field_kind);\n INSERT INTO search_docs_fts(rowid, text, role, tool_name, field_kind)\n VALUES (new.rowid, new.text, new.role, new.tool_name, new.field_kind);\nEND;\n`\n\n/** Enables incremental FTS5 maintenance after bulk rebuilds or imports. */\nexport function enableFts5Triggers(bundle: Bundle): void {\n bundle.db.exec(FTS5_TRIGGER_SQL)\n}\n\n/** Disables FTS5 maintenance triggers while import code performs bulk writes. */\nexport function disableFts5Triggers(bundle: Bundle): void {\n bundle.db.exec(`\n DROP TRIGGER IF EXISTS search_docs_ai;\n DROP TRIGGER IF EXISTS search_docs_ad;\n DROP TRIGGER IF EXISTS search_docs_au;\n `)\n}\n\n/** Returns status rows for all known search engines, creating defaults if absent. */\nexport function getSearchIndexStatuses(bundle: Bundle): SearchIndexStatus[] {\n ensureSearchIndexStatusRows(bundle)\n return bundle.db\n .prepare<[], SearchIndexStatus>(\n `SELECT ${SEARCH_INDEX_STATUS_COLUMNS}\n FROM search_index_status\n ORDER BY engine`,\n )\n .all()\n}\n\n/** Returns the status row for one search engine, or null only if initialization failed. */\nexport function getSearchIndexStatus(bundle: Bundle, engine: SearchEngine): SearchIndexStatus | null {\n ensureSearchIndexStatusRows(bundle)\n return (\n bundle.db\n .prepare<[SearchEngine], SearchIndexStatus>(\n `SELECT ${SEARCH_INDEX_STATUS_COLUMNS}\n FROM search_index_status\n WHERE engine = ?`,\n )\n .get(engine) ?? null\n )\n}\n\n/** Marks derived search indexes stale after canonical search_docs changed. */\nexport function markIndexesAfterImport(bundle: Bundle, options: { changed: boolean }): void {\n if (!options.changed) return\n\n const tantivy = getSearchIndexStatus(bundle, 'tantivy')\n if (tantivy?.status === 'ready' || tantivy?.status === 'stale' || tantivy?.status === 'failed') {\n updateSearchIndexStatus(bundle, 'tantivy', {\n status: 'stale',\n sourceDocCount: countSearchDocs(bundle),\n indexedDocCount: tantivy.indexed_doc_count,\n errorMessage: null,\n })\n }\n}\n\n/** Fully rebuilds the SQLite FTS5 index from search_docs and records status. */\nexport function rebuildFts5Index(bundle: Bundle): SearchIndexStatus {\n ensureSearchIndexStatusRows(bundle)\n updateSearchIndexStatus(bundle, 'fts5', {\n status: 'building',\n sourceDocCount: countSearchDocs(bundle),\n indexedDocCount: countFts5Docs(bundle),\n errorMessage: null,\n })\n\n try {\n transactional(bundle.db, () => {\n enableFts5Triggers(bundle)\n bundle.db.exec(`INSERT INTO search_docs_fts(search_docs_fts) VALUES('rebuild')`)\n })\n updateSearchIndexStatus(bundle, 'fts5', {\n status: 'ready',\n sourceDocCount: countSearchDocs(bundle),\n indexedDocCount: countFts5Docs(bundle),\n errorMessage: null,\n })\n } catch (error) {\n updateSearchIndexStatus(bundle, 'fts5', {\n status: 'failed',\n sourceDocCount: countSearchDocs(bundle),\n indexedDocCount: countFts5Docs(bundle),\n errorMessage: getErrorMessage(error),\n })\n throw error\n }\n\n return getSearchIndexStatus(bundle, 'fts5') as SearchIndexStatus\n}\n\n/** Options controlling Tantivy sidecar rebuild behavior. */\nexport interface RebuildTantivyOptions {\n /**\n * Force a full re-index even when an incremental run would be valid.\n * Surfaced by the `--overwrite` flag on `prosa index tantivy` and on\n * `prosa compile`.\n */\n overwrite?: boolean\n}\n\ntype TantivyModule = typeof import('@oxdev03/node-tantivy-binding')\n\n/** Stored Tantivy schema field used for schema fingerprinting and indexing. */\ninterface TantivySchemaField {\n name: string\n tokenizer: string\n}\n\n/**\n * Ordered list of fields stored on every Tantivy document.\n *\n * The order is load-bearing: the schema fingerprint hashes this list verbatim,\n * so changing the order forces a full rebuild on existing bundles.\n */\nconst TANTIVY_SCHEMA_FIELDS: readonly TantivySchemaField[] = [\n { name: 'doc_id', tokenizer: 'raw' },\n { name: 'entity_type', tokenizer: 'raw' },\n { name: 'entity_id', tokenizer: 'raw' },\n { name: 'session_id', tokenizer: 'raw' },\n { name: 'project_id', tokenizer: 'raw' },\n { name: 'timestamp', tokenizer: 'raw' },\n { name: 'role', tokenizer: 'raw' },\n { name: 'tool_name', tokenizer: 'raw' },\n { name: 'canonical_tool_type', tokenizer: 'raw' },\n { name: 'field_kind', tokenizer: 'raw' },\n // The text field uses Tantivy's default tokenizer (en_stem in the binding).\n { name: 'text', tokenizer: 'default' },\n]\n\n/** Builds the Tantivy schema from the fingerprinted field policy. */\nfunction buildTantivySchema(tantivy: TantivyModule): InstanceType<TantivyModule['Schema']> {\n const builder = new tantivy.SchemaBuilder()\n for (const field of TANTIVY_SCHEMA_FIELDS) {\n if (field.tokenizer === 'default') {\n builder.addTextField(field.name, { stored: true })\n } else {\n builder.addTextField(field.name, { stored: true, tokenizerName: field.tokenizer })\n }\n }\n return builder.build()\n}\n\n/** Returns the fingerprint that decides whether Tantivy can rebuild incrementally. */\nexport function getCurrentTantivySchemaFingerprint(): string {\n const canonical = TANTIVY_SCHEMA_FIELDS.map((f) => `${f.name}:${f.tokenizer}:stored`).join('|')\n return createHash('sha256').update(canonical).digest('hex')\n}\n\n/** Checks for Tantivy's metadata file without opening the optional binding. */\nexport function tantivyIndexDirIsValid(dir: string): boolean {\n return existsSync(path.join(dir, 'meta.json'))\n}\n\n/** Maps a canonical search_docs row into one stored Tantivy document. */\nfunction makeTantivyDoc(tantivy: TantivyModule, row: SearchDocRow): InstanceType<TantivyModule['Document']> {\n const doc = new tantivy.Document()\n doc.addText('doc_id', row.doc_id)\n doc.addText('entity_type', row.entity_type)\n doc.addText('entity_id', row.entity_id)\n doc.addText('session_id', row.session_id ?? '')\n doc.addText('project_id', row.project_id ?? '')\n doc.addText('timestamp', row.timestamp ?? '')\n doc.addText('role', row.role ?? '')\n doc.addText('tool_name', row.tool_name ?? '')\n doc.addText('canonical_tool_type', row.canonical_tool_type ?? '')\n doc.addText('field_kind', row.field_kind)\n doc.addText('text', row.text)\n return doc\n}\n\n/** Base projection used by full and incremental Tantivy indexing. */\nconst SEARCH_DOCS_SELECT = `\n SELECT rowid, doc_id, entity_type, entity_id, session_id, project_id, timestamp,\n role, tool_name, canonical_tool_type, field_kind, text\n FROM search_docs\n`\n\n/** Rebuilds the Tantivy sidecar, using an incremental append path when valid. */\nexport async function rebuildTantivyIndex(\n bundle: Bundle,\n options: RebuildTantivyOptions = {},\n): Promise<SearchIndexStatus> {\n ensureSearchIndexStatusRows(bundle)\n const sourceDocCount = countSearchDocs(bundle)\n\n // Read the *previous* status before we mark it 'building' — we rely on it\n // to decide between full and incremental, and on the prior indexed count\n // to project the post-incremental total.\n const prev = getSearchIndexStatus(bundle, 'tantivy')\n const fingerprint = getCurrentTantivySchemaFingerprint()\n const indexDirValid = tantivyIndexDirIsValid(bundle.paths.tantivy)\n const fingerprintMatches = prev?.schema_fingerprint === fingerprint\n const lastIndexedRowid = typeof prev?.last_indexed_rowid === 'number' ? prev.last_indexed_rowid : 0\n const wantFullRebuild = options.overwrite === true || !indexDirValid || !fingerprintMatches || lastIndexedRowid <= 0\n\n updateSearchIndexStatus(bundle, 'tantivy', {\n status: 'building',\n sourceDocCount,\n indexedDocCount: 0,\n errorMessage: null,\n })\n\n try {\n const tantivy = await import('@oxdev03/node-tantivy-binding')\n const schema = buildTantivySchema(tantivy)\n\n let index: InstanceType<TantivyModule['Index']>\n if (wantFullRebuild) {\n await rm(bundle.paths.tantivy, { recursive: true, force: true })\n await mkdir(bundle.paths.tantivy, { recursive: true })\n index = new tantivy.Index(schema, bundle.paths.tantivy, false)\n } else {\n index = tantivy.Index.open(bundle.paths.tantivy)\n }\n\n const writer = index.writer(300_000_000, 4)\n const select = wantFullRebuild\n ? `${SEARCH_DOCS_SELECT} ORDER BY rowid`\n : `${SEARCH_DOCS_SELECT} WHERE rowid > ${lastIndexedRowid} ORDER BY rowid`\n\n let addedDocCount = 0\n let maxRowid = wantFullRebuild ? 0 : lastIndexedRowid\n for (const row of bundle.db.prepare<[], SearchDocRow>(select).iterate()) {\n if (!wantFullRebuild) {\n // Defensive: lets re-imported docs replace the prior copy. The\n // tokenizer for `doc_id` is `raw`, so the stored value maps 1:1\n // to a single deletable term.\n writer.deleteDocumentsByTerm('doc_id', row.doc_id)\n }\n writer.addDocument(makeTantivyDoc(tantivy, row))\n addedDocCount++\n if (row.rowid > maxRowid) maxRowid = row.rowid\n }\n\n writer.commit()\n index.reload()\n // Drop the writer deterministically so the directory lock is released\n // before the next rebuildTantivyIndex call (e.g. consecutive runs in\n // the same process).\n writer.waitMergingThreads()\n\n const indexedDocCount = wantFullRebuild ? addedDocCount : countTantivyDocsBest(prev, addedDocCount)\n\n await writeFile(\n path.join(bundle.paths.tantivy, 'prosa-index.json'),\n `${JSON.stringify(\n {\n engine: 'tantivy',\n source: 'search_docs',\n built_at: new Date().toISOString(),\n mode: wantFullRebuild ? 'full' : 'incremental',\n source_doc_count: sourceDocCount,\n indexed_doc_count: indexedDocCount,\n last_indexed_rowid: maxRowid,\n schema_fingerprint: fingerprint,\n },\n null,\n 2,\n )}\\n`,\n 'utf8',\n )\n\n updateSearchIndexStatus(bundle, 'tantivy', {\n status: 'ready',\n sourceDocCount,\n indexedDocCount,\n errorMessage: null,\n lastIndexedRowid: maxRowid,\n schemaFingerprint: fingerprint,\n })\n } catch (error) {\n updateSearchIndexStatus(bundle, 'tantivy', {\n status: 'failed',\n sourceDocCount,\n indexedDocCount: 0,\n errorMessage: getErrorMessage(error),\n })\n throw error\n }\n\n return getSearchIndexStatus(bundle, 'tantivy') as SearchIndexStatus\n}\n\n/**\n * Estimates Tantivy's post-incremental document count from prior recorded\n * state because the binding does not expose a cheap committed count here.\n */\nfunction countTantivyDocsBest(prev: SearchIndexStatus | null, added: number): number {\n if (prev && typeof prev.indexed_doc_count === 'number') {\n return prev.indexed_doc_count + added\n }\n return added\n}\n\n/** Ensures every supported search engine has a status row before reads/writes. */\nfunction ensureSearchIndexStatusRows(bundle: Bundle): void {\n const now = new Date().toISOString()\n const stmt = prepare(\n bundle.db,\n `INSERT OR IGNORE INTO search_index_status (\n engine, status, source_doc_count, indexed_doc_count, updated_at,\n error_message, last_indexed_rowid, schema_fingerprint\n ) VALUES (?, ?, 0, 0, ?, NULL, NULL, NULL)`,\n )\n stmt.run('fts5', 'ready', now)\n stmt.run('tantivy', 'missing', now)\n}\n\n/** Partial search_index_status update; optional fields leave columns unchanged. */\ninterface UpdateSearchIndexValues {\n status: SearchIndexStatus['status']\n sourceDocCount: number\n indexedDocCount: number\n errorMessage: string | null\n /** undefined leaves the column untouched; null clears it. */\n lastIndexedRowid?: number | null\n /** undefined leaves the column untouched; null clears it. */\n schemaFingerprint?: string | null\n}\n\n/** Writes status metadata while preserving optional columns unless explicitly provided. */\nfunction updateSearchIndexStatus(bundle: Bundle, engine: SearchEngine, values: UpdateSearchIndexValues): void {\n ensureSearchIndexStatusRows(bundle)\n const setClauses = [\n 'status = ?',\n 'source_doc_count = ?',\n 'indexed_doc_count = ?',\n 'updated_at = ?',\n 'error_message = ?',\n ]\n const params: unknown[] = [\n values.status,\n values.sourceDocCount,\n values.indexedDocCount,\n new Date().toISOString(),\n values.errorMessage,\n ]\n if (values.lastIndexedRowid !== undefined) {\n setClauses.push('last_indexed_rowid = ?')\n params.push(values.lastIndexedRowid)\n }\n if (values.schemaFingerprint !== undefined) {\n setClauses.push('schema_fingerprint = ?')\n params.push(values.schemaFingerprint)\n }\n params.push(engine)\n prepare(bundle.db, `UPDATE search_index_status SET ${setClauses.join(', ')} WHERE engine = ?`).run(...params)\n}\n\n/** Counts canonical search_docs rows that derived indexes should cover. */\nexport function countSearchDocs(bundle: Bundle): number {\n return bundle.db.prepare<[], { n: number }>(`SELECT count(*) AS n FROM search_docs`).get()?.n ?? 0\n}\n\n/** Counts rows currently present in the SQLite FTS5 virtual table. */\nexport function countFts5Docs(bundle: Bundle): number {\n return bundle.db.prepare<[], { n: number }>(`SELECT count(*) AS n FROM search_docs_fts`).get()?.n ?? 0\n}\n","import os from 'node:os'\nimport path from 'node:path'\nimport type { Bundle } from '../core/bundle.js'\nimport type { SourceTool } from '../core/domain/types.js'\nimport { getErrorMessage } from '../core/errors.js'\nimport type { ImportBatch, ImportCounts } from '../core/ingest/batch.js'\nimport { compileClaude } from '../importers/claude/index.js'\nimport { compileCodex } from '../importers/codex/index.js'\nimport type { CompileLogger, CompileOptions } from '../importers/compile-options.js'\nimport { compileCursor } from '../importers/cursor/index.js'\nimport { compileGemini } from '../importers/gemini/index.js'\nimport { compileHermes } from '../importers/hermes/index.js'\nimport { exportBundleParquet } from './export/parquet.js'\nimport {\n disableFts5Triggers,\n enableFts5Triggers,\n markIndexesAfterImport,\n rebuildFts5Index,\n rebuildTantivyIndex,\n} from './indexing.js'\n\n/** Importer result shape normalized for compile orchestration. */\nexport interface CompileResult {\n /** Import batch created by the provider. */\n batch: ImportBatch\n /** Final provider import counts. */\n counts: ImportCounts\n}\n\n/** Configures one source-tool importer for the compile service. */\nexport interface CompileProviderConfig {\n /** Source tool handled by this provider. */\n name: SourceTool\n /** Human-readable provider description. */\n description: string\n /** Help text describing the expected root path. */\n pathHelp: string\n /** Default native history location for this provider. */\n defaultSessionsPath: () => string\n /** Provider compile implementation. */\n compile: (bundle: Bundle, root: string, options?: CompileOptions) => Promise<CompileResult>\n}\n\n/** Per-provider summary emitted after an importer finishes. */\nexport interface ProviderCompileSummary {\n /** Source tool that completed. */\n source: SourceTool\n /** Resolved source path compiled by the provider. */\n sourcePath: string\n /** Batch identifier for this provider run. */\n batchId: string\n /** Import batch metadata. */\n batch: ImportBatch\n /** Final import counts. */\n counts: ImportCounts\n}\n\n/** Summary emitted after a Tantivy rebuild completes during compile. */\nexport interface TantivyCompileSummary {\n /** Documents present in the rebuilt Tantivy index. */\n indexedDocCount: number\n}\n\n/** Aggregate result for a compile import run across one or more providers. */\nexport interface CompileImportSummary {\n /** Per-provider summaries in execution order. */\n providers: ProviderCompileSummary[]\n /** True when at least one source file was imported. */\n importedAny: boolean\n /** Tantivy rebuild summary, if it completed. */\n tantivy: TantivyCompileSummary | null\n /** Tantivy rebuild error message, if rebuild failed but compile continued. */\n tantivyError: string | null\n /** FTS5 rebuild error message, if rebuild failed but compile continued. */\n fts5Error: string | null\n}\n\n/** Summary returned after compile-triggered Parquet export. */\nexport interface ParquetCompileSummary {\n /** Directory containing generated Parquet files. */\n outDir: string\n /** Path to the generated export manifest. */\n manifestPath: string\n /** Number of exported canonical tables. */\n tableCount: number\n /** Absolute output file path by table. */\n files: Record<string, string>\n /** Row count by table. */\n counts: Record<string, number>\n}\n\n/** Options for running compile imports across configured providers. */\nexport interface CompileImportOptions {\n /** Open bundle to import into. */\n bundle: Bundle\n /** Providers to run in order. */\n providers: CompileProviderConfig[]\n /** Optional override for every provider's default source path. */\n sessionsPath?: string\n /**\n * Force a full rebuild of derived indexes after import. Tantivy is the\n * only sidecar with an incremental path today, so this currently flips\n * Tantivy to a from-scratch rebuild; FTS5 and Parquet are always\n * full-rewrite. Surfaced by `prosa compile … --overwrite`.\n */\n overwrite?: boolean\n /** Optional structured logger. */\n logger?: CompileLogger\n /** Callback invoked after each provider completes. */\n onProviderComplete?: (summary: ProviderCompileSummary) => void\n /** Callback invoked after Tantivy rebuild completes. */\n onTantivyComplete?: (summary: TantivyCompileSummary) => void\n}\n\n/** Options for compile's Parquet export step. */\nexport interface ExportCompileParquetOptions {\n /** Bundle root whose canonical tables should be exported. */\n storePath: string\n /** Optional structured logger. */\n logger?: CompileLogger\n}\n\n/** Built-in compile providers and their default history locations. */\nexport const COMPILE_PROVIDERS: CompileProviderConfig[] = [\n {\n name: 'codex',\n description: 'Import Codex CLI session histories into the bundle.',\n pathHelp: 'root of Codex CLI sessions',\n defaultSessionsPath: () => path.join(os.homedir(), '.codex', 'sessions'),\n compile: compileCodex,\n },\n {\n name: 'claude',\n description: 'Import Claude Code project histories into the bundle.',\n pathHelp: 'root of Claude Code projects',\n defaultSessionsPath: () => path.join(os.homedir(), '.claude', 'projects'),\n compile: compileClaude,\n },\n {\n name: 'gemini',\n description: 'Import Gemini CLI session histories into the bundle.',\n pathHelp: 'root of Gemini CLI tmp dir',\n defaultSessionsPath: () => path.join(os.homedir(), '.gemini', 'tmp'),\n compile: compileGemini,\n },\n {\n name: 'cursor',\n description: 'Import Cursor agent stores into the bundle.',\n pathHelp: 'root of Cursor agent stores',\n defaultSessionsPath: () => path.join(os.homedir(), '.cursor', 'chats'),\n compile: compileCursor,\n },\n {\n name: 'hermes',\n description: 'Import Hermes session histories into the bundle.',\n pathHelp: 'root of Hermes sessions',\n defaultSessionsPath: () => path.join(os.homedir(), '.hermes', 'sessions'),\n compile: compileHermes,\n },\n]\n\n/** Resolves a compile provider by source tool, throwing for unsupported names. */\nexport function getCompileProvider(source: SourceTool): CompileProviderConfig {\n const provider = COMPILE_PROVIDERS.find((p) => p.name === source)\n if (!provider) {\n throw new Error(`unknown compile source: ${source}`)\n }\n return provider\n}\n\n/** Expands shell-style home paths and resolves compile paths to absolutes. */\nexport function resolveCompilePath(p: string, basePath = process.env.INIT_CWD ?? process.cwd()): string {\n if (p === '~') return os.homedir()\n if (p.startsWith('~/')) return path.join(os.homedir(), p.slice(2))\n if (path.isAbsolute(p)) return path.resolve(p)\n return path.resolve(basePath, p)\n}\n\n/** Runs provider imports and refreshes derived search indexes when data changed. */\nexport async function runCompileImports(options: CompileImportOptions): Promise<CompileImportSummary> {\n const { bundle, providers, logger } = options\n const overwrite = options.overwrite === true\n let importedAny = false\n const summaries: ProviderCompileSummary[] = []\n let tantivy: TantivyCompileSummary | null = null\n let tantivyError: string | null = null\n let fts5Error: string | null = null\n\n try {\n // Sweep any unfinished import_batches left behind by a previous crash so\n // they don't keep tripping `prosa doctor` after every successful compile.\n // SQLite is single-writer; if we're here, no other process owns those rows.\n const sweep = bundle.db\n .prepare(\n `UPDATE import_batches SET status = 'failed', finished_at = datetime('now')\n WHERE finished_at IS NULL`,\n )\n .run()\n if (sweep.changes > 0) {\n logger?.warn({ batches_reaped: sweep.changes }, 'reaped unfinished import_batches from a prior crash')\n }\n\n logger?.info('disabling FTS5 triggers for bulk rebuild')\n disableFts5Triggers(bundle)\n\n for (const provider of providers) {\n const sourcePath = resolveCompilePath(options.sessionsPath ?? provider.defaultSessionsPath())\n const providerLogger = logger?.child({\n source_tool: provider.name,\n source_path: sourcePath,\n })\n providerLogger?.info('starting compile')\n const r = await provider.compile(bundle, sourcePath, { logger: providerLogger })\n importedAny ||= r.counts.source_files_imported > 0\n providerLogger?.info(\n {\n batch_id: r.batch.batch_id,\n counts: r.counts,\n },\n 'compile finished',\n )\n\n const summary = {\n source: provider.name,\n sourcePath,\n batchId: r.batch.batch_id,\n batch: r.batch,\n counts: r.counts,\n }\n summaries.push(summary)\n options.onProviderComplete?.(summary)\n }\n\n const shouldRebuildIndexes = importedAny || overwrite\n if (shouldRebuildIndexes) {\n logger?.info(\n { changed: importedAny, overwrite },\n importedAny ? 'marking indexes' : 'overwrite forces rebuild despite no new imports',\n )\n markIndexesAfterImport(bundle, { changed: true })\n\n try {\n logger?.info('rebuilding fts5 index')\n rebuildFts5Index(bundle)\n } catch (error) {\n fts5Error = getErrorMessage(error)\n logger?.error({ err: error }, 'fts5 rebuild failed; SQLite data is intact')\n }\n\n try {\n logger?.info({ overwrite }, 'rebuilding tantivy index')\n const status = await rebuildTantivyIndex(bundle, { overwrite })\n tantivy = { indexedDocCount: status.indexed_doc_count }\n options.onTantivyComplete?.(tantivy)\n } catch (error) {\n tantivyError = getErrorMessage(error)\n logger?.error({ err: error }, 'tantivy rebuild failed; SQLite data is intact')\n }\n }\n } finally {\n enableFts5Triggers(bundle)\n }\n\n return {\n providers: summaries,\n importedAny,\n tantivy,\n tantivyError,\n fts5Error,\n }\n}\n\n/** Exports the compiled bundle to Parquet using compile command path semantics. */\nexport async function exportCompileParquet(options: ExportCompileParquetOptions): Promise<ParquetCompileSummary> {\n const storePath = resolveCompilePath(options.storePath)\n options.logger?.info({ store_path: storePath }, 'exporting parquet')\n const result = await exportBundleParquet({ bundlePath: storePath })\n return {\n outDir: result.outDir,\n manifestPath: result.manifestPath,\n tableCount: Object.keys(result.files).length,\n files: result.files,\n counts: result.counts,\n }\n}\n","import { readFile } from 'node:fs/promises'\nimport path from 'node:path'\nimport type { Bundle } from '../../core/bundle.js'\nimport {\n type ObjectId,\n type PendingObjects,\n createPendingObjects,\n flushPendingObjects,\n stageBytes,\n stageJson,\n stageText,\n} from '../../core/cas/index.js'\nimport { prepare, transactional } from '../../core/db.js'\nimport {\n artifactId,\n blockId,\n eventId as makeEventId,\n messageId as makeMessageId,\n rawRecordId as makeRawRecordId,\n sessionId as makeSessionId,\n toolCallId as makeToolCallId,\n toolResultId as makeToolResultId,\n} from '../../core/domain/ids.js'\nimport { normalizeToolCallStatus } from '../../core/domain/status.js'\nimport { getErrorMessage } from '../../core/errors.js'\nimport {\n type ImportBatch,\n type ImportCounts,\n emptyCounts,\n finishBatch,\n recordError,\n startBatch,\n} from '../../core/ingest/batch.js'\nimport { registerSourceFile } from '../../core/ingest/idempotency.js'\nimport type { CompileLogger, CompileOptions } from '../compile-options.js'\nimport { type ClaudeFile, discoverClaudeFiles } from './discover.js'\nimport type { ClaudeContentBlock, ClaudeRecord, ClaudeSubagentMeta } from './types.js'\n\n/** Result returned after a Claude compile batch finishes or records a failed batch. */\nexport interface CompileResult {\n /** Import batch created for this Claude run. */\n batch: ImportBatch\n /** Final counts accumulated while importing Claude files. */\n counts: ImportCounts\n}\n\n/** Maximum inline text retained in normalized rows before full content moves to CAS. */\nconst PREVIEW_MAX = 4_000\n\n/** Compile Claude Code JSONL files under `root` into the bundle. */\nexport async function compileClaude(\n bundle: Bundle,\n root: string,\n options: CompileOptions = {},\n): Promise<CompileResult> {\n const logger = options.logger\n const batch = startBatch(bundle, 'claude', [root])\n const counts = emptyCounts()\n logger?.info({ batch_id: batch.batch_id, root }, 'claude batch started')\n\n try {\n for await (const file of discoverClaudeFiles(root)) {\n counts.source_files_seen++\n logger?.debug(\n {\n path: file.filePath,\n project_slug: file.projectSlug,\n is_subagent: file.isSubagent,\n },\n 'claude source file discovered',\n )\n try {\n const fc = await compileClaudeFile(bundle, batch, file, logger)\n addCounts(counts, fc)\n } catch (error) {\n counts.errors++\n logger?.warn(\n {\n err: error,\n path: file.filePath,\n },\n 'claude source file failed',\n )\n await recordError(bundle, batch.batch_id, {\n kind: 'claude_file_failed',\n message: getErrorMessage(error),\n payload: { path: file.filePath },\n })\n }\n }\n linkSubagentParents(bundle)\n logger?.debug({ batch_id: batch.batch_id }, 'claude subagent parent links refreshed')\n finishBatch(bundle, batch, counts, 'completed')\n logger?.info({ batch_id: batch.batch_id, counts }, 'claude batch completed')\n } catch (error) {\n finishBatch(bundle, batch, counts, 'failed')\n logger?.error({ err: error, batch_id: batch.batch_id, counts }, 'claude batch failed')\n throw error\n }\n\n return { batch, counts }\n}\n\n/** Resolve Claude subagent parent links after all files in the batch have been inserted. */\nfunction linkSubagentParents(bundle: Bundle): void {\n bundle.db.exec(`\n UPDATE edges\n SET src_id = (\n SELECT m.message_id\n FROM messages m\n JOIN raw_records r ON r.raw_record_id = m.raw_record_id\n WHERE r.source_tool = 'claude'\n AND r.native_id = edges.src_id\n LIMIT 1\n )\n WHERE src_type = 'message'\n AND edge_type = 'spawned'\n AND source = 'source_tool_assistant_uuid'\n AND EXISTS (\n SELECT 1\n FROM messages m\n JOIN raw_records r ON r.raw_record_id = m.raw_record_id\n WHERE r.source_tool = 'claude'\n AND r.native_id = edges.src_id\n );\n\n UPDATE sessions\n SET parent_session_id = (\n SELECT e.src_id\n FROM edges e\n WHERE e.edge_type = 'spawned'\n AND e.dst_type = 'session'\n AND e.dst_id = sessions.session_id\n AND EXISTS (SELECT 1 FROM sessions p WHERE p.session_id = e.src_id)\n LIMIT 1\n )\n WHERE parent_session_id IS NULL\n AND is_subagent = 1\n AND source_tool = 'claude'\n `)\n}\n\n/** Per-source-file deltas that are merged into the import batch counts. */\ninterface FileCounts {\n source_files_imported: number\n source_files_skipped: number\n raw_records: number\n sessions: number\n turns: number\n events: number\n messages: number\n content_blocks: number\n tool_calls: number\n tool_results: number\n artifacts: number\n edges: number\n errors: number\n}\n\n/** Create zeroed file counters for a Claude file that may still fail or be skipped. */\nfunction emptyFileCounts(): FileCounts {\n return {\n source_files_imported: 0,\n source_files_skipped: 0,\n raw_records: 0,\n sessions: 0,\n turns: 0,\n events: 0,\n messages: 0,\n content_blocks: 0,\n tool_calls: 0,\n tool_results: 0,\n artifacts: 0,\n edges: 0,\n errors: 0,\n }\n}\n\n/** Merge a single Claude file's normalized row counts into batch totals. */\nfunction addCounts(target: ImportCounts, source: FileCounts): void {\n target.source_files_imported += source.source_files_imported\n target.source_files_skipped += source.source_files_skipped\n target.raw_records += source.raw_records\n target.sessions += source.sessions\n target.turns += source.turns\n target.events += source.events\n target.messages += source.messages\n target.content_blocks += source.content_blocks\n target.tool_calls += source.tool_calls\n target.tool_results += source.tool_results\n target.artifacts += source.artifacts\n target.edges += source.edges\n target.errors += source.errors\n}\n\n// -- per file --\n\n/** Raw record row staged from a Claude JSONL line before database insertion. */\ninterface PendingRawRecord {\n raw_record_id: string\n source_file_id: string\n ordinal: number\n line_no: number\n native_id: string | null\n raw_object_id: ObjectId\n decoded_json_object_id: ObjectId | null\n parser_status: 'ok' | 'partial' | 'failed'\n confidence: 'high' | 'medium' | 'low'\n import_batch_id: string\n}\n\n/** Session row staged from the first Claude record with a session id. */\ninterface PendingSession {\n session_id: string\n source_session_id: string\n is_subagent: 0 | 1\n agent_role: string | null\n agent_nickname: string | null\n title: string | null\n start_ts: string | null\n end_ts: string | null\n cwd_initial: string | null\n git_branch_initial: string | null\n raw_record_id: string | null\n /** for subagent files; resolved cross-file in linkSubagentParents */\n parent_session_id_pending: string | null\n}\n\n/** Event row staged from Claude user, assistant, system, or operational records. */\ninterface PendingEvent {\n event_id: string\n ordinal: number\n source_event_id: string | null\n event_type: string\n source_type: string\n subtype: string | null\n timestamp: string | null\n actor: string | null\n payload_object_id: ObjectId | null\n raw_record_id: string\n confidence: 'high' | 'medium' | 'low'\n}\n\n/** Message row staged from Claude user and assistant records. */\ninterface PendingMessage {\n message_id: string\n event_id: string | null\n source_message_id: string | null\n role: 'system_prompt' | 'developer' | 'user' | 'assistant' | 'tool' | 'operational'\n model: string | null\n timestamp: string | null\n ordinal: number\n parent_message_id: string | null\n parent_uuid: string | null // for parent_of edge linking by uuid\n uuid: string | null\n raw_record_id: string\n}\n\n/** Content block row staged from Claude text, thinking, tool, image, or unknown blocks. */\ninterface PendingBlock {\n block_id: string\n message_id: string | null\n event_id: string | null\n ordinal: number\n block_type: string\n text_object_id: ObjectId | null\n text_inline: string | null\n is_error: 0 | 1\n visibility: 'default' | 'hidden_by_default' | 'audit_only'\n raw_record_id: string\n}\n\n/** Tool call row staged from Claude `tool_use` content blocks. */\ninterface PendingToolCall {\n tool_call_id: string\n message_id: string | null\n event_id: string | null\n source_call_id: string\n tool_name: string\n canonical_tool_type: string\n args_object_id: ObjectId | null\n command: string | null\n cwd: string | null\n path: string | null\n query: string | null\n timestamp_start: string | null\n status: string | null\n raw_record_id: string\n}\n\n/** Tool result row staged from Claude `tool_result` content blocks. */\ninterface PendingToolResult {\n tool_result_id: string\n tool_call_id: string | null\n source_call_id: string | null\n message_id: string | null\n event_id: string | null\n status: string | null\n is_error: 0 | 1\n exit_code: number | null\n duration_ms: number | null\n stdout_object_id: ObjectId | null\n stderr_object_id: ObjectId | null\n output_object_id: ObjectId | null\n preview: string | null\n raw_record_id: string\n}\n\n/** Artifact row staged from Claude records that point to external or generated content. */\ninterface PendingArtifact {\n artifact_id: string\n kind: string\n path: string | null\n logical_path: string | null\n object_id: ObjectId | null\n text_object_id: ObjectId | null\n mime_type: string | null\n size_bytes: number\n created_ts: string | null\n raw_record_id: string\n}\n\n/** Graph edge row staged for Claude parent-message and subagent relationships. */\ninterface PendingEdge {\n src_type: string\n src_id: string\n dst_type: string\n dst_id: string\n edge_type: string\n confidence: 'high' | 'medium' | 'low'\n source: string\n raw_record_id: string | null\n}\n\n/** Search index row staged from normalized Claude messages, commands, paths, and previews. */\ninterface PendingSearchDoc {\n doc_id: string\n entity_type: string\n entity_id: string\n timestamp: string | null\n role: string | null\n tool_name: string | null\n canonical_tool_type: string | null\n field_kind: string\n text: string\n}\n\n/** All normalized Claude rows staged for one source file before FK-ordered flush. */\ninterface PendingState {\n rawRecords: PendingRawRecord[]\n session: PendingSession | null\n events: PendingEvent[]\n messages: PendingMessage[]\n blocks: PendingBlock[]\n toolCalls: Map<string, PendingToolCall>\n toolCallsList: PendingToolCall[]\n toolResults: PendingToolResult[]\n artifacts: PendingArtifact[]\n edges: PendingEdge[]\n searchDocs: PendingSearchDoc[]\n /** map uuid → message_id for parent_of edges resolved at flush time. */\n uuidToMessageId: Map<string, string>\n objects: PendingObjects\n}\n\n/** Parse one Claude JSONL file, stage CAS objects, and flush normalized rows. */\nasync function compileClaudeFile(\n bundle: Bundle,\n batch: ImportBatch,\n file: ClaudeFile,\n logger?: CompileLogger,\n): Promise<FileCounts> {\n const counts = emptyFileCounts()\n\n const { row: sourceFile, alreadyKnown } = await registerSourceFile(bundle, {\n sourceTool: 'claude',\n absolutePath: path.resolve(file.filePath),\n fileKind: 'jsonl',\n workspaceHint: file.projectSlug,\n })\n\n if (alreadyKnown) {\n counts.source_files_skipped = 1\n logger?.debug({ path: file.filePath, source_file_id: sourceFile.source_file_id }, 'claude source file skipped')\n return counts\n }\n counts.source_files_imported = 1\n logger?.debug({ path: file.filePath, source_file_id: sourceFile.source_file_id }, 'claude source file registered')\n\n const text = await readFile(file.filePath, 'utf8')\n const rawLines = text.split('\\n')\n const lines = rawLines[rawLines.length - 1] === '' ? rawLines.slice(0, -1) : rawLines\n\n const meta = file.metaPath ? await readMeta(file.metaPath) : null\n\n const pending: PendingState = {\n rawRecords: [],\n session: null,\n events: [],\n messages: [],\n blocks: [],\n toolCalls: new Map(),\n toolCallsList: [],\n toolResults: [],\n artifacts: [],\n edges: [],\n searchDocs: [],\n uuidToMessageId: new Map(),\n objects: createPendingObjects(),\n }\n\n let modelFirst: string | null = null\n let modelLast: string | null = null\n let messageOrdinal = 0\n let sessionStartTs: string | null = null\n let sessionEndTs: string | null = null\n let cwdInitial: string | null = null\n let branchInitial: string | null = null\n\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i]\n if (!line || line.length === 0) continue\n const lineNo = i + 1\n const ordinal = i\n\n const lineBytes = Buffer.from(line, 'utf8')\n const rawObjectId = stageBytes(pending.objects, lineBytes, {\n mimeType: 'application/jsonl-line',\n encoding: 'utf-8',\n })\n\n let parsed: ClaudeRecord | null = null\n let parserStatus: 'ok' | 'partial' | 'failed' = 'ok'\n try {\n parsed = JSON.parse(line) as ClaudeRecord\n } catch {\n parserStatus = 'failed'\n }\n\n // The raw line already IS the JSON for `parserStatus === 'ok'`, so we\n // skip storing a re-serialized copy as `decoded_json_object_id`. Saves\n // ~half the CAS writes per file. Nothing reads it back later.\n const decodedObjectId: ObjectId | null = null\n\n const nativeId = parsed?.uuid ?? null\n const rawRecordId = makeRawRecordId(sourceFile.source_file_id, ordinal, rawObjectId)\n\n pending.rawRecords.push({\n raw_record_id: rawRecordId,\n source_file_id: sourceFile.source_file_id,\n ordinal,\n line_no: lineNo,\n native_id: nativeId,\n raw_object_id: rawObjectId,\n decoded_json_object_id: decodedObjectId,\n parser_status: parserStatus,\n confidence: parserStatus === 'ok' ? 'high' : 'low',\n import_batch_id: batch.batch_id,\n })\n\n if (!parsed) continue\n\n const ts = typeof parsed.timestamp === 'string' ? parsed.timestamp : null\n if (ts) {\n if (!sessionStartTs || ts < sessionStartTs) sessionStartTs = ts\n if (!sessionEndTs || ts > sessionEndTs) sessionEndTs = ts\n }\n if (!cwdInitial && typeof parsed.cwd === 'string') cwdInitial = parsed.cwd\n if (!branchInitial && typeof parsed.gitBranch === 'string') branchInitial = parsed.gitBranch\n\n // Resolve session on first record that carries a sessionId.\n if (!pending.session && typeof parsed.sessionId === 'string') {\n pending.session = createSessionFromFirstRecord(file, parsed, meta, ts, rawRecordId)\n if (file.isSubagent && file.parentSessionId) {\n const parentSid = makeSessionId('claude', file.parentSessionId)\n pending.edges.push({\n src_type: 'session',\n src_id: parentSid,\n dst_type: 'session',\n dst_id: pending.session.session_id,\n edge_type: 'spawned',\n confidence: 'high',\n source: 'path_inferred',\n raw_record_id: rawRecordId,\n })\n pending.session.parent_session_id_pending = parentSid\n }\n }\n\n const sessionId = pending.session?.session_id ?? makeSessionId('claude', `unknown:${path.basename(file.filePath)}`)\n\n const type = typeof parsed.type === 'string' ? parsed.type : null\n\n if (type === 'user' || type === 'assistant') {\n const msgRole: PendingMessage['role'] = type === 'user' ? 'user' : 'assistant'\n const role = inferRoleFromContent(parsed, msgRole)\n const msgOrdinal = messageOrdinal++\n const messageId = makeMessageId(sessionId, msgOrdinal, parsed.message?.id ?? parsed.uuid ?? null)\n const eventId = makeEventId(sessionId, ordinal, 'message')\n\n pending.events.push({\n event_id: eventId,\n ordinal,\n source_event_id: parsed.uuid ?? null,\n event_type: 'message',\n source_type: type,\n subtype: null,\n timestamp: ts,\n actor: msgRole,\n payload_object_id: decodedObjectId,\n raw_record_id: rawRecordId,\n confidence: 'high',\n })\n\n const model = parsed.message?.model ?? null\n if (msgRole === 'assistant' && model) {\n if (!modelFirst) modelFirst = model\n modelLast = model\n }\n\n pending.messages.push({\n message_id: messageId,\n event_id: eventId,\n source_message_id: parsed.message?.id ?? null,\n role,\n model: msgRole === 'assistant' ? model : null,\n timestamp: ts,\n ordinal: msgOrdinal,\n parent_message_id: null,\n parent_uuid: parsed.parentUuid ?? null,\n uuid: parsed.uuid ?? null,\n raw_record_id: rawRecordId,\n })\n if (parsed.uuid) pending.uuidToMessageId.set(parsed.uuid, messageId)\n if (parsed.isSidechain && parsed.sourceToolAssistantUUID) {\n pending.edges.push({\n src_type: 'message',\n src_id: parsed.sourceToolAssistantUUID,\n dst_type: 'session',\n dst_id: sessionId,\n edge_type: 'spawned',\n confidence: 'high',\n source: 'source_tool_assistant_uuid',\n raw_record_id: rawRecordId,\n })\n }\n\n const content = parsed.message?.content\n if (typeof content === 'string') {\n pending.blocks.push({\n block_id: blockId(messageId, 0),\n message_id: messageId,\n event_id: null,\n ordinal: 0,\n block_type: 'text',\n text_object_id: null,\n text_inline: content.slice(0, PREVIEW_MAX),\n is_error: 0,\n visibility: 'default',\n raw_record_id: rawRecordId,\n })\n if (content.length > PREVIEW_MAX) {\n // Big text — also store full body in CAS for later retrieval.\n const fullId = stageText(pending.objects, content)\n const last = pending.blocks[pending.blocks.length - 1]\n if (last) last.text_object_id = fullId\n }\n } else if (Array.isArray(content)) {\n for (let bi = 0; bi < content.length; bi++) {\n const block = content[bi] as ClaudeContentBlock | undefined\n if (!block) continue\n await processContentBlock(bundle, sessionId, messageId, eventId, bi, block, ts, rawRecordId, pending)\n }\n }\n continue\n }\n\n if (type === 'system') {\n // Critical: Claude's `type=system` is OPERATIONAL (hooks, turn duration,\n // local commands, api errors). It's not a system prompt.\n pending.events.push({\n event_id: makeEventId(sessionId, ordinal, 'system_operational'),\n ordinal,\n source_event_id: parsed.uuid ?? null,\n event_type: 'system_operational',\n source_type: 'system',\n subtype: parsed.subtype ?? null,\n timestamp: ts,\n actor: 'system',\n payload_object_id: decodedObjectId,\n raw_record_id: rawRecordId,\n confidence: 'high',\n })\n continue\n }\n\n if (type === 'progress') {\n const progressType = typeof parsed.data?.type === 'string' ? (parsed.data.type as string) : null\n pending.events.push({\n event_id: makeEventId(sessionId, ordinal, `progress.${progressType ?? 'unknown'}`),\n ordinal,\n source_event_id: parsed.uuid ?? null,\n event_type: 'progress',\n source_type: 'progress',\n subtype: progressType,\n timestamp: ts,\n actor: 'system',\n payload_object_id: decodedObjectId,\n raw_record_id: rawRecordId,\n confidence: 'high',\n })\n continue\n }\n\n if (type === 'attachment') {\n pending.events.push({\n event_id: makeEventId(sessionId, ordinal, 'attachment'),\n ordinal,\n source_event_id: parsed.uuid ?? null,\n event_type: 'file_history_snapshot',\n source_type: 'attachment',\n subtype: parsed.attachment?.type ?? null,\n timestamp: ts,\n actor: 'system',\n payload_object_id: decodedObjectId,\n raw_record_id: rawRecordId,\n confidence: 'high',\n })\n continue\n }\n\n if (type === 'file-history-snapshot') {\n pending.events.push({\n event_id: makeEventId(sessionId, ordinal, 'file_history_snapshot'),\n ordinal,\n source_event_id: parsed.uuid ?? null,\n event_type: 'attachment',\n source_type: 'file-history-snapshot',\n subtype: parsed.isSnapshotUpdate ? 'update' : 'snapshot',\n timestamp: ts,\n actor: 'system',\n payload_object_id: decodedObjectId,\n raw_record_id: rawRecordId,\n confidence: 'high',\n })\n pending.artifacts.push({\n artifact_id: artifactId(sessionId, 'claude', `snapshot:${parsed.snapshot?.messageId ?? ordinal}`),\n kind: 'snapshot',\n path: null,\n logical_path: null,\n object_id: null,\n text_object_id: null,\n mime_type: 'application/json',\n size_bytes: line.length,\n created_ts: ts,\n raw_record_id: rawRecordId,\n })\n continue\n }\n\n // permission-mode, last-prompt, queue-operation, agent-name, custom-title,\n // pr-link, etc. — keep as operational events.\n pending.events.push({\n event_id: makeEventId(sessionId, ordinal, `claude.${type ?? 'unknown'}`),\n ordinal,\n source_event_id: parsed.uuid ?? null,\n event_type: 'system_operational',\n source_type: type ?? 'unknown',\n subtype: null,\n timestamp: ts,\n actor: 'system',\n payload_object_id: decodedObjectId,\n raw_record_id: rawRecordId,\n confidence: 'high',\n })\n }\n\n // Resolve parent_of edges by uuid.\n for (const m of pending.messages) {\n if (m.parent_uuid && pending.uuidToMessageId.has(m.parent_uuid)) {\n const parentId = pending.uuidToMessageId.get(m.parent_uuid)!\n m.parent_message_id = parentId\n pending.edges.push({\n src_type: 'message',\n src_id: parentId,\n dst_type: 'message',\n dst_id: m.message_id,\n edge_type: 'parent_of',\n confidence: 'high',\n source: 'explicit',\n raw_record_id: m.raw_record_id,\n })\n }\n }\n\n if (pending.session) {\n pending.session.start_ts ??= sessionStartTs\n pending.session.end_ts ??= sessionEndTs\n pending.session.cwd_initial ??= cwdInitial\n pending.session.git_branch_initial ??= branchInitial\n }\n\n buildSearchDocs(pending)\n\n // Persist staged CAS objects (FS + objects rows) before the domain\n // transaction. better-sqlite3 transactions are sync, so we can't await\n // file writes inside them.\n await flushPendingObjects(bundle, pending.objects)\n\n transactional(bundle.db, () => {\n flushPending(bundle, pending, { modelFirst, modelLast })\n })\n\n counts.raw_records = pending.rawRecords.length\n counts.sessions = pending.session ? 1 : 0\n counts.events = pending.events.length\n counts.messages = pending.messages.length\n counts.content_blocks = pending.blocks.length\n counts.tool_calls = pending.toolCallsList.length\n counts.tool_results = pending.toolResults.length\n counts.artifacts = pending.artifacts.length\n counts.edges = pending.edges.length\n logger?.debug(\n { path: file.filePath, source_file_id: sourceFile.source_file_id, counts },\n 'claude source file imported',\n )\n\n return counts\n}\n\n/** Build the normalized session id, keeping Claude subagents distinct from parent sessions. */\nfunction createSessionFromFirstRecord(\n file: ClaudeFile,\n parsed: ClaudeRecord,\n meta: ClaudeSubagentMeta | null,\n ts: string | null,\n rawRecordId: string,\n): PendingSession {\n const sourceSid = parsed.sessionId as string\n // Subagent and main share the same `sessionId` field. Differentiate by\n // appending the agentId for subagents to keep PKs stable.\n const composite = file.isSubagent && file.agentId ? `${sourceSid}:${file.agentId}` : sourceSid\n return {\n session_id: makeSessionId('claude', composite),\n source_session_id: composite,\n is_subagent: file.isSubagent ? 1 : 0,\n agent_role: meta?.agentType ?? null,\n agent_nickname: parsed.agentName ?? null,\n title: meta?.description ?? null,\n start_ts: ts,\n end_ts: null,\n cwd_initial: parsed.cwd ?? null,\n git_branch_initial: parsed.gitBranch ?? null,\n raw_record_id: rawRecordId,\n parent_session_id_pending: null,\n }\n}\n\n/** Read optional Claude subagent metadata, treating missing or malformed files as absent. */\nasync function readMeta(metaPath: string): Promise<ClaudeSubagentMeta | null> {\n try {\n const text = await readFile(metaPath, 'utf8')\n return JSON.parse(text) as ClaudeSubagentMeta\n } catch {\n return null\n }\n}\n\n/** Reclassify tool-result-only Claude user messages as tool output for search and filters. */\nfunction inferRoleFromContent(parsed: ClaudeRecord, fallback: 'user' | 'assistant'): PendingMessage['role'] {\n // A user-typed message that contains only tool_result blocks is the agent\n // delivering tool output back to itself. Mark as 'tool' role for clarity in\n // search/filters; mixed messages stay as 'user'.\n if (fallback !== 'user') return 'assistant'\n const c = parsed.message?.content\n if (!Array.isArray(c) || c.length === 0) return 'user'\n const allToolResult = c.every((b) => b && typeof b === 'object' && (b as { type?: string }).type === 'tool_result')\n return allToolResult ? 'tool' : 'user'\n}\n\n/** Normalize one Claude content block into blocks, tool calls, tool results, or audit rows. */\nasync function processContentBlock(\n bundle: Bundle,\n sessionId: string,\n messageId: string,\n eventId: string,\n blockOrdinal: number,\n block: ClaudeContentBlock,\n ts: string | null,\n rawRecordId: string,\n pending: PendingState,\n): Promise<void> {\n const blkId = blockId(messageId, blockOrdinal)\n\n if (block.type === 'text') {\n const text = (block as { text?: string }).text ?? ''\n pending.blocks.push({\n block_id: blkId,\n message_id: messageId,\n event_id: null,\n ordinal: blockOrdinal,\n block_type: 'text',\n text_object_id: text.length > PREVIEW_MAX ? stageText(pending.objects, text) : null,\n text_inline: text.slice(0, PREVIEW_MAX),\n is_error: 0,\n visibility: 'default',\n raw_record_id: rawRecordId,\n })\n return\n }\n\n if (block.type === 'thinking') {\n const text = (block as { thinking?: string }).thinking ?? ''\n pending.blocks.push({\n block_id: blkId,\n message_id: messageId,\n event_id: null,\n ordinal: blockOrdinal,\n block_type: 'thinking',\n text_object_id: text.length > PREVIEW_MAX ? stageText(pending.objects, text) : null,\n text_inline: text.slice(0, PREVIEW_MAX),\n is_error: 0,\n visibility: 'hidden_by_default',\n raw_record_id: rawRecordId,\n })\n return\n }\n\n if (block.type === 'tool_use') {\n const tu = block as { id?: string; name?: string; input?: unknown }\n const sourceCallId = tu.id ?? `${blockOrdinal}`\n const toolName = tu.name ?? 'unknown'\n const argsId = tu.input != null ? stageJson(pending.objects, tu.input) : null\n const command = inferCommandFromArgs(toolName, tu.input)\n const filePath = inferPathFromArgs(tu.input)\n const tcId = makeToolCallId(sessionId, sourceCallId)\n\n pending.blocks.push({\n block_id: blkId,\n message_id: messageId,\n event_id: null,\n ordinal: blockOrdinal,\n block_type: 'tool_use',\n text_object_id: null,\n text_inline: null,\n is_error: 0,\n visibility: 'default',\n raw_record_id: rawRecordId,\n })\n\n const call: PendingToolCall = {\n tool_call_id: tcId,\n message_id: messageId,\n event_id: eventId,\n source_call_id: sourceCallId,\n tool_name: toolName,\n canonical_tool_type: canonicalToolType(toolName),\n args_object_id: argsId,\n command,\n cwd: null,\n path: filePath,\n query: null,\n timestamp_start: ts,\n status: 'started',\n raw_record_id: rawRecordId,\n }\n pending.toolCalls.set(sourceCallId, call)\n pending.toolCallsList.push(call)\n return\n }\n\n if (block.type === 'tool_result') {\n const tr = block as { tool_use_id?: string; content?: unknown; is_error?: boolean }\n const sourceCallId = tr.tool_use_id ?? null\n const isError = tr.is_error === true ? 1 : 0\n const text = stringifyOrNull(tr.content) ?? ''\n const overflowId = text.length > PREVIEW_MAX ? stageText(pending.objects, text) : null\n pending.blocks.push({\n block_id: blkId,\n message_id: messageId,\n event_id: null,\n ordinal: blockOrdinal,\n block_type: 'tool_result',\n text_object_id: overflowId,\n text_inline: text.slice(0, PREVIEW_MAX),\n is_error: isError,\n visibility: 'default',\n raw_record_id: rawRecordId,\n })\n\n const matched = sourceCallId ? pending.toolCalls.get(sourceCallId) : undefined\n pending.toolResults.push({\n tool_result_id: makeToolResultId(sessionId, sourceCallId ?? `${messageId}:${blockOrdinal}`),\n tool_call_id: matched?.tool_call_id ?? null,\n source_call_id: sourceCallId,\n message_id: messageId,\n event_id: eventId,\n status: normalizeToolCallStatus('claude', matched ? (isError ? 'error' : 'success') : null),\n is_error: isError,\n exit_code: null,\n duration_ms: null,\n stdout_object_id: null,\n stderr_object_id: null,\n output_object_id: overflowId,\n preview: text.slice(0, PREVIEW_MAX),\n raw_record_id: rawRecordId,\n })\n if (matched) {\n matched.status = isError ? 'error' : 'success'\n }\n return\n }\n\n if (block.type === 'image') {\n pending.blocks.push({\n block_id: blkId,\n message_id: messageId,\n event_id: null,\n ordinal: blockOrdinal,\n block_type: 'image',\n text_object_id: null,\n text_inline: null,\n is_error: 0,\n visibility: 'default',\n raw_record_id: rawRecordId,\n })\n return\n }\n\n // Unknown block type — keep it as raw inline JSON for visibility.\n pending.blocks.push({\n block_id: blkId,\n message_id: messageId,\n event_id: null,\n ordinal: blockOrdinal,\n block_type: (block as { type?: string }).type ?? 'unknown',\n text_object_id: null,\n text_inline: stringifyOrNull(block)?.slice(0, PREVIEW_MAX) ?? null,\n is_error: 0,\n visibility: 'audit_only',\n raw_record_id: rawRecordId,\n })\n}\n\n/** Collapse Claude tool names into broad search/filter tool categories. */\nfunction canonicalToolType(toolName: string): string {\n const lower = toolName.toLowerCase()\n if (lower.startsWith('mcp__')) return 'mcp'\n if (lower === 'bash' || lower === 'shell' || lower === 'run_terminal_cmd') return 'shell'\n if (lower === 'read' || lower === 'readfile' || lower === 'read_file') return 'read_file'\n if (lower === 'write' || lower === 'writefile' || lower === 'write_file') return 'write_file'\n if (\n lower === 'edit' ||\n lower === 'strreplace' ||\n lower === 'str_replace' ||\n lower === 'replace' ||\n lower === 'search_replace'\n ) {\n return 'edit_file'\n }\n if (lower === 'grep' || lower === 'glob' || lower === 'glob_file_search') return 'search_file'\n if (lower === 'websearch' || lower === 'google_web_search') return 'web_search'\n if (lower === 'webfetch') return 'other'\n if (lower === 'agent') return 'subagent'\n if (lower === 'applypatch' || lower === 'apply_patch') return 'patch'\n return 'other'\n}\n\n/** Extract a shell command from Claude tool arguments when the native tool exposes one. */\nfunction inferCommandFromArgs(toolName: string, args: unknown): string | null {\n if (!args || typeof args !== 'object') return null\n const obj = args as Record<string, unknown>\n if (typeof obj.command === 'string') return obj.command\n if (toolName.toLowerCase() === 'bash' && typeof obj.cmd === 'string') return obj.cmd\n return null\n}\n\n/** Extract a file path from Claude tool arguments without treating absence as an error. */\nfunction inferPathFromArgs(args: unknown): string | null {\n if (!args || typeof args !== 'object') return null\n const obj = args as Record<string, unknown>\n if (typeof obj.file_path === 'string') return obj.file_path\n if (typeof obj.path === 'string') return obj.path\n if (typeof obj.absolute_path === 'string') return obj.absolute_path\n return null\n}\n\n/** Convert arbitrary recovered payload values into compact text previews when possible. */\nfunction stringifyOrNull(value: unknown): string | null {\n if (value == null) return null\n if (typeof value === 'string') return value\n try {\n return JSON.stringify(value)\n } catch {\n return null\n }\n}\n\n/** Build searchable Claude documents while excluding hidden thinking from default search. */\nfunction buildSearchDocs(pending: PendingState): void {\n const sessionId = pending.session?.session_id ?? null\n if (!sessionId) return\n\n const blocksByMsg = new Map<string, PendingBlock[]>()\n for (const b of pending.blocks) {\n if (!b.message_id) continue\n if (!b.text_inline) continue\n if (b.block_type !== 'text' && b.block_type !== 'thinking' && b.block_type !== 'tool_result') continue\n const list = blocksByMsg.get(b.message_id) ?? []\n list.push(b)\n blocksByMsg.set(b.message_id, list)\n }\n\n for (const m of pending.messages) {\n const blks = blocksByMsg.get(m.message_id) ?? []\n const text = blks\n .filter((b) => b.block_type !== 'thinking') // hide reasoning from default search\n .map((b) => b.text_inline ?? '')\n .join('\\n')\n .trim()\n if (!text) continue\n pending.searchDocs.push({\n doc_id: `msg:${m.message_id}`,\n entity_type: 'message',\n entity_id: m.message_id,\n timestamp: m.timestamp,\n role: m.role,\n tool_name: null,\n canonical_tool_type: null,\n field_kind: m.role === 'user' ? 'user_prompt' : m.role === 'tool' ? 'tool_result' : 'assistant_text',\n text,\n })\n }\n\n for (const c of pending.toolCallsList) {\n if (c.command) {\n pending.searchDocs.push({\n doc_id: `tc:cmd:${c.tool_call_id}`,\n entity_type: 'tool_call',\n entity_id: c.tool_call_id,\n timestamp: c.timestamp_start,\n role: null,\n tool_name: c.tool_name,\n canonical_tool_type: c.canonical_tool_type,\n field_kind: 'command',\n text: c.command,\n })\n }\n if (c.path) {\n pending.searchDocs.push({\n doc_id: `tc:path:${c.tool_call_id}`,\n entity_type: 'tool_call',\n entity_id: c.tool_call_id,\n timestamp: c.timestamp_start,\n role: null,\n tool_name: c.tool_name,\n canonical_tool_type: c.canonical_tool_type,\n field_kind: 'file_path',\n text: c.path,\n })\n }\n }\n\n for (const r of pending.toolResults) {\n if (!r.preview) continue\n pending.searchDocs.push({\n doc_id: `tr:preview:${r.tool_result_id}`,\n entity_type: 'tool_result',\n entity_id: r.tool_result_id,\n timestamp: null,\n role: null,\n tool_name: null,\n canonical_tool_type: null,\n field_kind: r.is_error ? 'error' : 'tool_result',\n text: r.preview,\n })\n }\n}\n\n/** Insert staged Claude rows in foreign-key order after CAS objects are already durable. */\nfunction flushPending(\n bundle: Bundle,\n pending: PendingState,\n meta: { modelFirst: string | null; modelLast: string | null },\n): void {\n if (!pending.session) return\n\n const insertRaw = prepare(\n bundle.db,\n `INSERT OR IGNORE INTO raw_records (\n raw_record_id, source_file_id, source_tool, record_kind, ordinal,\n line_no, json_pointer, native_id, raw_object_id, decoded_json_object_id,\n parser_status, confidence, import_batch_id\n ) VALUES (?, ?, 'claude', 'jsonl_line', ?, ?, NULL, ?, ?, ?, ?, ?, ?)`,\n )\n for (const r of pending.rawRecords) {\n insertRaw.run(\n r.raw_record_id,\n r.source_file_id,\n r.ordinal,\n r.line_no,\n r.native_id,\n r.raw_object_id,\n r.decoded_json_object_id,\n r.parser_status,\n r.confidence,\n r.import_batch_id,\n )\n }\n\n prepare(\n bundle.db,\n `INSERT OR REPLACE INTO sessions (\n session_id, source_tool, source_session_id, project_id, parent_session_id,\n is_subagent, agent_role, agent_nickname, title, summary,\n start_ts, end_ts, cwd_initial, git_branch_initial,\n model_first, model_last, status, timeline_confidence, raw_record_id\n ) VALUES (?, 'claude', ?, NULL, NULL, ?, ?, ?, ?, NULL, ?, ?, ?, ?, ?, ?, 'completed', 'high', ?)`,\n ).run(\n pending.session.session_id,\n pending.session.source_session_id,\n pending.session.is_subagent,\n pending.session.agent_role,\n pending.session.agent_nickname,\n pending.session.title,\n pending.session.start_ts,\n pending.session.end_ts,\n pending.session.cwd_initial,\n pending.session.git_branch_initial,\n meta.modelFirst,\n meta.modelLast,\n pending.session.raw_record_id,\n )\n\n const insertEvent = prepare(\n bundle.db,\n `INSERT OR REPLACE INTO events (\n event_id, session_id, turn_id, source_event_id, event_type, source_type,\n subtype, timestamp, ordinal, actor, payload_object_id, raw_record_id,\n confidence, is_derived\n ) VALUES (?, ?, NULL, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 0)`,\n )\n for (const e of pending.events) {\n insertEvent.run(\n e.event_id,\n pending.session.session_id,\n e.source_event_id,\n e.event_type,\n e.source_type,\n e.subtype,\n e.timestamp,\n e.ordinal,\n e.actor,\n e.payload_object_id,\n e.raw_record_id,\n e.confidence,\n )\n }\n\n const insertMessage = prepare(\n bundle.db,\n `INSERT OR REPLACE INTO messages (\n message_id, session_id, turn_id, event_id, source_message_id, role,\n author_name, model, timestamp, ordinal, parent_message_id, request_id,\n status, raw_record_id\n ) VALUES (?, ?, NULL, ?, ?, ?, NULL, ?, ?, ?, ?, NULL, NULL, ?)`,\n )\n for (const m of pending.messages) {\n insertMessage.run(\n m.message_id,\n pending.session.session_id,\n m.event_id,\n m.source_message_id,\n m.role,\n m.model,\n m.timestamp,\n m.ordinal,\n m.parent_message_id,\n m.raw_record_id,\n )\n }\n\n const insertBlock = prepare(\n bundle.db,\n `INSERT OR REPLACE INTO content_blocks (\n block_id, message_id, event_id, session_id, ordinal, block_type,\n text_object_id, text_inline, mime_type, token_count, is_error,\n is_redacted, visibility, raw_record_id\n ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, NULL, NULL, ?, 0, ?, ?)`,\n )\n for (const b of pending.blocks) {\n insertBlock.run(\n b.block_id,\n b.message_id,\n b.event_id,\n pending.session.session_id,\n b.ordinal,\n b.block_type,\n b.text_object_id,\n b.text_inline,\n b.is_error,\n b.visibility,\n b.raw_record_id,\n )\n }\n\n const insertToolCall = prepare(\n bundle.db,\n `INSERT OR REPLACE INTO tool_calls (\n tool_call_id, session_id, turn_id, message_id, event_id,\n source_call_id, tool_name, canonical_tool_type, args_object_id,\n command, cwd, path, query, timestamp_start, timestamp_end, status,\n raw_record_id\n ) VALUES (?, ?, NULL, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, NULL, ?, ?)`,\n )\n for (const c of pending.toolCallsList) {\n insertToolCall.run(\n c.tool_call_id,\n pending.session.session_id,\n c.message_id,\n c.event_id,\n c.source_call_id,\n c.tool_name,\n c.canonical_tool_type,\n c.args_object_id,\n c.command,\n c.cwd,\n c.path,\n c.query,\n c.timestamp_start,\n c.status,\n c.raw_record_id,\n )\n }\n\n const insertToolResult = prepare(\n bundle.db,\n `INSERT OR REPLACE INTO tool_results (\n tool_result_id, tool_call_id, session_id, message_id, event_id,\n source_call_id, status, is_error, exit_code, duration_ms,\n stdout_object_id, stderr_object_id, output_object_id, preview, raw_record_id\n ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,\n )\n for (const r of pending.toolResults) {\n insertToolResult.run(\n r.tool_result_id,\n r.tool_call_id,\n pending.session.session_id,\n r.message_id,\n r.event_id,\n r.source_call_id,\n r.status,\n r.is_error,\n r.exit_code,\n r.duration_ms,\n r.stdout_object_id,\n r.stderr_object_id,\n r.output_object_id,\n r.preview,\n r.raw_record_id,\n )\n }\n\n const insertArtifact = prepare(\n bundle.db,\n `INSERT OR REPLACE INTO artifacts (\n artifact_id, session_id, project_id, source_tool, kind, path,\n logical_path, object_id, text_object_id, mime_type, size_bytes,\n created_ts, raw_record_id\n ) VALUES (?, ?, NULL, 'claude', ?, ?, ?, ?, ?, ?, ?, ?, ?)`,\n )\n for (const a of pending.artifacts) {\n insertArtifact.run(\n a.artifact_id,\n pending.session.session_id,\n a.kind,\n a.path,\n a.logical_path,\n a.object_id,\n a.text_object_id,\n a.mime_type,\n a.size_bytes,\n a.created_ts,\n a.raw_record_id,\n )\n }\n\n const insertEdge = prepare(\n bundle.db,\n `INSERT OR IGNORE INTO edges (\n src_type, src_id, dst_type, dst_id, edge_type, confidence, source,\n raw_record_id, metadata_object_id\n ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, NULL)`,\n )\n for (const e of pending.edges) {\n insertEdge.run(e.src_type, e.src_id, e.dst_type, e.dst_id, e.edge_type, e.confidence, e.source, e.raw_record_id)\n }\n\n const insertSearch = prepare(\n bundle.db,\n `INSERT OR REPLACE INTO search_docs (\n doc_id, entity_type, entity_id, session_id, project_id, timestamp,\n role, tool_name, canonical_tool_type, field_kind, text\n ) VALUES (?, ?, ?, ?, NULL, ?, ?, ?, ?, ?, ?)`,\n )\n for (const d of pending.searchDocs) {\n insertSearch.run(\n d.doc_id,\n d.entity_type,\n d.entity_id,\n pending.session.session_id,\n d.timestamp,\n d.role,\n d.tool_name,\n d.canonical_tool_type,\n d.field_kind,\n d.text,\n )\n }\n}\n","import type { SourceTool, ToolCallStatus } from './types.js'\n\nconst CANONICAL_TOOL_CALL_STATUSES = new Set<string>(['started', 'success', 'error', 'cancelled', 'unknown'])\n\n/**\n * Canonical session lifecycle vocabulary used across importers. Sources spell\n * these out in many ways (`stop`, `tool_calls`, `failure`, `cancel`); the\n * normalizer collapses them so the projection stays consistent.\n */\nexport function normalizeSessionStatus(status: string | null | undefined): string | null {\n if (!status) return null\n const normalized = status.trim().toLowerCase()\n if (normalized === 'stop' || normalized === 'completed' || normalized === 'success') return 'completed'\n if (normalized === 'tool_calls') return 'completed'\n if (normalized === 'error' || normalized === 'failed' || normalized === 'failure') return 'error'\n if (normalized === 'cancelled' || normalized === 'canceled' || normalized === 'cancel') return 'cancelled'\n return 'unknown'\n}\n\n/** Normalize source-specific tool lifecycle values into the canonical vocabulary. */\nexport function normalizeToolCallStatus(sourceTool: SourceTool, raw: string | null | undefined): ToolCallStatus {\n const status = raw?.trim()\n if (!status) return 'unknown'\n if (CANONICAL_TOOL_CALL_STATUSES.has(status)) return status as ToolCallStatus\n\n switch (sourceTool) {\n case 'codex':\n if (status === 'completed') return 'success'\n if (status === 'in_progress') return 'started'\n if (status === 'incomplete' || status === 'failed' || status === 'timeout') return 'error'\n if (status === 'canceled') return 'cancelled'\n return 'unknown'\n case 'hermes':\n if (status === 'stop' || status === 'tool_calls') return 'success'\n if (status === 'length' || status === 'content_filter') return 'error'\n return 'unknown'\n case 'gemini':\n case 'claude':\n case 'cursor':\n return 'unknown'\n }\n}\n","import { readdir } from 'node:fs/promises'\nimport path from 'node:path'\n\n/** Discovered Claude Code JSONL file plus path-derived project/subagent context. */\nexport interface ClaudeFile {\n /** Absolute path to a JSONL session file. */\n filePath: string\n /** Project slug (the dashed directory name under projects/). */\n projectSlug: string\n /** Whether the file is a subagent rollout under `<session>/subagents/`. */\n isSubagent: boolean\n /**\n * For main files: the session-id derived from the filename.\n * For subagent files: the session-id from the parent directory; the subagent\n * has the same `sessionId` field internally but a distinct `agentId`.\n */\n parentSessionId: string | null\n /** For subagent files only: agent id parsed from `agent-<id>.jsonl`. */\n agentId: string | null\n /** Path to the companion `.meta.json`, if any (subagents only). */\n metaPath: string | null\n}\n\n/**\n * Walk `<root>` (typically `~/.claude/projects`) and yield every JSONL file\n * under it, classified as main session or subagent. We deliberately ignore\n * `sessions-index.json` (per the recovery report it's incomplete) and skip\n * `tool-results/` and `memory/` for the MVP.\n */\nexport async function* discoverClaudeFiles(root: string): AsyncGenerator<ClaudeFile, void, void> {\n const projectDirs = await readdirSafe(root)\n for (const project of projectDirs) {\n if (!project.isDirectory()) continue\n const projectRoot = path.join(root, project.name)\n yield* walkProject(projectRoot, project.name)\n }\n}\n\n/** Classify project children as top-level session files or subagent rollouts. */\nasync function* walkProject(projectRoot: string, projectSlug: string): AsyncGenerator<ClaudeFile, void, void> {\n const entries = await readdirSafe(projectRoot)\n for (const entry of entries) {\n if (entry.isFile() && entry.name.endsWith('.jsonl')) {\n yield {\n filePath: path.join(projectRoot, entry.name),\n projectSlug,\n isSubagent: false,\n parentSessionId: null,\n agentId: null,\n metaPath: null,\n }\n continue\n }\n if (entry.isDirectory()) {\n // Could be a session-id dir with subagents/ inside; or memory/; or other.\n const subagentsDir = path.join(projectRoot, entry.name, 'subagents')\n const subagentEntries = await readdirSafe(subagentsDir)\n for (const sub of subagentEntries) {\n if (!sub.isFile() || !sub.name.endsWith('.jsonl')) continue\n if (!sub.name.startsWith('agent-')) continue\n const agentId = sub.name.slice('agent-'.length, -'.jsonl'.length)\n const metaCandidate = path.join(subagentsDir, `agent-${agentId}.meta.json`)\n const metaExists = subagentEntries.some((e) => e.isFile() && e.name === `agent-${agentId}.meta.json`)\n yield {\n filePath: path.join(subagentsDir, sub.name),\n projectSlug,\n isSubagent: true,\n parentSessionId: entry.name,\n agentId,\n metaPath: metaExists ? metaCandidate : null,\n }\n }\n }\n }\n}\n\n/** Read a directory as empty when optional Claude folders are absent. */\nasync function readdirSafe(dir: string): Promise<import('node:fs').Dirent[]> {\n try {\n return await readdir(dir, { withFileTypes: true })\n } catch {\n return []\n }\n}\n","import { readFile } from 'node:fs/promises'\nimport path from 'node:path'\nimport type { Bundle } from '../../core/bundle.js'\nimport {\n type ObjectId,\n type PendingObjects,\n createPendingObjects,\n flushPendingObjects,\n stageBytes,\n stageJson,\n stageText,\n} from '../../core/cas/index.js'\nimport { prepare, transactional } from '../../core/db.js'\nimport {\n artifactId,\n blockId,\n eventId as makeEventId,\n messageId as makeMessageId,\n rawRecordId as makeRawRecordId,\n sessionId as makeSessionId,\n toolCallId as makeToolCallId,\n toolResultId as makeToolResultId,\n turnId as makeTurnId,\n} from '../../core/domain/ids.js'\nimport { normalizeToolCallStatus } from '../../core/domain/status.js'\nimport { getErrorMessage } from '../../core/errors.js'\nimport {\n type ImportBatch,\n type ImportCounts,\n emptyCounts,\n finishBatch,\n recordError,\n startBatch,\n} from '../../core/ingest/batch.js'\nimport { registerSourceFile } from '../../core/ingest/idempotency.js'\nimport type { CompileLogger, CompileOptions } from '../compile-options.js'\nimport { discoverCodexSessions } from './discover.js'\nimport type {\n CodexContentItem,\n CodexEnvelope,\n CodexEventMsgPayload,\n CodexResponseItemPayload,\n CodexSessionMetaPayload,\n CodexTurnContextPayload,\n} from './types.js'\n\n/** Result returned after a Codex compile batch finishes or records a failed batch. */\nexport interface CompileResult {\n /** Import batch created for this Codex run. */\n batch: ImportBatch\n /** Final counts accumulated while importing Codex files. */\n counts: ImportCounts\n}\n\n/** Maximum inline text retained in normalized rows before full content moves to CAS. */\nconst PREVIEW_MAX = 4_000\n\n/**\n * Number of Codex files prepared concurrently before each short per-file\n * database transaction. Prepare is I/O-heavy; applying rows stays serial to\n * avoid long write transactions and growing WAL lookup costs.\n */\nconst CODEX_PREPARE_CONCURRENCY = 8\n\n/** Compile Codex JSONL session files under `root` into the bundle. */\nexport async function compileCodex(bundle: Bundle, root: string, options: CompileOptions = {}): Promise<CompileResult> {\n const logger = options.logger\n const batch = startBatch(bundle, 'codex', [root])\n const counts = emptyCounts()\n logger?.info({ batch_id: batch.batch_id, root }, 'codex batch started')\n\n try {\n const files: string[] = []\n for await (const filePath of discoverCodexSessions(root)) {\n files.push(filePath)\n logger?.debug({ path: filePath }, 'codex source file discovered')\n }\n counts.source_files_seen = files.length\n\n for (let i = 0; i < files.length; i += CODEX_PREPARE_CONCURRENCY) {\n const slice = files.slice(i, i + CODEX_PREPARE_CONCURRENCY)\n await processCodexBatch(bundle, batch, slice, counts, logger)\n }\n\n linkSubagentParents(bundle)\n logger?.debug({ batch_id: batch.batch_id }, 'codex subagent parent links refreshed')\n finishBatch(bundle, batch, counts, 'completed')\n logger?.info({ batch_id: batch.batch_id, counts }, 'codex batch completed')\n } catch (error) {\n finishBatch(bundle, batch, counts, 'failed')\n logger?.error({ err: error, batch_id: batch.batch_id, counts }, 'codex batch failed')\n throw error\n }\n\n return { batch, counts }\n}\n\n/** Parsed and CAS-staged Codex file waiting for the short domain insert transaction. */\ninterface CodexPrepared {\n filePath: string\n pending: PendingState\n meta: { sessionEndTs: string | null; modelFirst: string | null; modelLast: string | null }\n}\n\n/** Per-file state tracked while a concurrent Codex prepare slice is applied. */\ninterface CodexBatchItem {\n filePath: string\n prepared: CodexPrepared | null\n fileCounts: FileCounts\n prepareError: Error | null\n applyError: Error | null\n}\n\n/** Prepare a slice concurrently, then apply each prepared file in its own transaction. */\nasync function processCodexBatch(\n bundle: Bundle,\n batch: ImportBatch,\n slice: string[],\n counts: ImportCounts,\n logger?: CompileLogger,\n): Promise<void> {\n // Phase A: parse + CAS flush for the whole slice concurrently. Each file's\n // prepare is independent — registerSourceFile is idempotent and CAS writes\n // are content-addressed — so we can overlap their I/O.\n const items = await Promise.all(\n slice.map(async (filePath): Promise<CodexBatchItem> => {\n try {\n const result = await prepareCodexFile(bundle, batch, filePath, logger)\n return {\n filePath,\n prepared: result.prepared,\n fileCounts: result.counts,\n prepareError: null,\n applyError: null,\n }\n } catch (err) {\n return {\n filePath,\n prepared: null,\n fileCounts: emptyFileCounts(),\n prepareError: err as Error,\n applyError: null,\n }\n }\n }),\n )\n\n // Phase B: domain INSERTs run one file at a time, each in its own short\n // transaction. We tried wrapping the whole slice in one outer transaction\n // with savepoints per file — that turned the steady-state insert loop CPU-\n // bound because INSERT OR IGNORE lookups had to walk the growing WAL inside\n // the long transaction. Per-file commits keep the WAL small.\n for (const item of items) {\n if (item.prepareError || !item.prepared) continue\n try {\n transactional(bundle.db, () => applyCodexFile(bundle, item.prepared as CodexPrepared))\n } catch (err) {\n item.applyError = err as Error\n }\n }\n\n // Phase C: aggregate counts and record per-file errors.\n for (const item of items) {\n const err = item.prepareError ?? item.applyError\n if (err) {\n counts.errors++\n logger?.warn({ err, path: item.filePath }, 'codex source file failed')\n await recordError(bundle, batch.batch_id, {\n kind: 'codex_file_failed',\n message: getErrorMessage(err),\n payload: { path: item.filePath },\n })\n } else {\n addCounts(counts, item.fileCounts)\n }\n }\n}\n\n/**\n * After every file is committed, fill `sessions.parent_session_id` from any\n * `edges(spawned)` whose target session now exists. We deliberately set\n * `parent_session_id=NULL` during per-file inserts because a subagent file may\n * be processed before the parent file; deferring the link to a single UPDATE\n * keeps every per-file transaction self-contained.\n */\nfunction linkSubagentParents(bundle: Bundle): void {\n bundle.db.exec(`\n UPDATE sessions\n SET parent_session_id = (\n SELECT e.src_id\n FROM edges e\n WHERE e.edge_type = 'spawned'\n AND e.dst_type = 'session'\n AND e.dst_id = sessions.session_id\n AND EXISTS (SELECT 1 FROM sessions p WHERE p.session_id = e.src_id)\n LIMIT 1\n )\n WHERE parent_session_id IS NULL\n AND is_subagent = 1\n `)\n}\n\n/** Per-source-file deltas that are merged into the import batch counts. */\ninterface FileCounts {\n source_files_imported: number\n source_files_skipped: number\n raw_records: number\n sessions: number\n turns: number\n events: number\n messages: number\n content_blocks: number\n tool_calls: number\n tool_results: number\n artifacts: number\n edges: number\n errors: number\n}\n\n/** Create zeroed file counters for a Codex file that may still fail or be skipped. */\nfunction emptyFileCounts(): FileCounts {\n return {\n source_files_imported: 0,\n source_files_skipped: 0,\n raw_records: 0,\n sessions: 0,\n turns: 0,\n events: 0,\n messages: 0,\n content_blocks: 0,\n tool_calls: 0,\n tool_results: 0,\n artifacts: 0,\n edges: 0,\n errors: 0,\n }\n}\n\n/** Merge a single Codex file's normalized row counts into batch totals. */\nfunction addCounts(target: ImportCounts, source: FileCounts): void {\n target.source_files_imported += source.source_files_imported\n target.source_files_skipped += source.source_files_skipped\n target.raw_records += source.raw_records\n target.sessions += source.sessions\n target.turns += source.turns\n target.events += source.events\n target.messages += source.messages\n target.content_blocks += source.content_blocks\n target.tool_calls += source.tool_calls\n target.tool_results += source.tool_results\n target.artifacts += source.artifacts\n target.edges += source.edges\n target.errors += source.errors\n}\n\n// ---- per-file pipeline ---------------------------------------------------\n\n/** Raw record row staged from a Codex JSONL line before database insertion. */\ninterface PendingRawRecord {\n raw_record_id: string\n source_file_id: string\n source_tool: 'codex'\n record_kind: 'jsonl_line'\n ordinal: number\n line_no: number\n json_pointer: null\n native_id: string | null\n raw_object_id: ObjectId\n decoded_json_object_id: ObjectId | null\n parser_status: 'ok' | 'partial' | 'failed'\n confidence: 'high' | 'medium' | 'low'\n import_batch_id: string\n}\n\n/** Session row staged from `session_meta` or a filename fallback. */\ninterface PendingSession {\n session_id: string\n source_session_id: string\n parent_session_id: string | null\n is_subagent: 0 | 1\n agent_role: string | null\n agent_nickname: string | null\n title: string | null\n start_ts: string | null\n cwd_initial: string | null\n git_branch_initial: string | null\n raw_record_id: string | null\n}\n\n/** Turn row staged from Codex `turn_context` events. */\ninterface PendingTurn {\n turn_id: string\n ordinal: number\n source_turn_id: string | null\n start_ts: string | null\n model: string | null\n cwd: string | null\n approval_policy: string | null\n sandbox_policy: string | null\n effort: string | null\n raw_record_id: string\n}\n\n/** Event row staged from Codex response items and operational event messages. */\ninterface PendingEvent {\n event_id: string\n ordinal: number\n turn_id: string | null\n source_event_id: string | null\n event_type: string\n source_type: string\n subtype: string | null\n timestamp: string | null\n actor: string | null\n payload_object_id: ObjectId | null\n raw_record_id: string\n confidence: 'high' | 'medium' | 'low'\n}\n\n/** Message row staged from Codex assistant/user/tool content. */\ninterface PendingMessage {\n message_id: string\n turn_id: string | null\n event_id: string | null\n source_message_id: string | null\n role: 'system_prompt' | 'developer' | 'user' | 'assistant' | 'tool' | 'operational'\n model: string | null\n timestamp: string | null\n ordinal: number\n raw_record_id: string\n}\n\n/** Content block row staged from Codex message content arrays. */\ninterface PendingBlock {\n block_id: string\n message_id: string | null\n event_id: string | null\n ordinal: number\n block_type: string\n text_object_id: ObjectId | null\n text_inline: string | null\n raw_record_id: string\n}\n\n/** Tool call row staged from Codex function-call style records. */\ninterface PendingToolCall {\n tool_call_id: string\n turn_id: string | null\n message_id: string | null\n event_id: string | null\n source_call_id: string | null\n tool_name: string\n canonical_tool_type: string\n args_object_id: ObjectId | null\n command: string | null\n cwd: string | null\n path: string | null\n query: string | null\n timestamp_start: string | null\n status: string | null\n raw_record_id: string\n}\n\n/** Tool result row staged from function-call output and operational tool events. */\ninterface PendingToolResult {\n tool_result_id: string\n tool_call_id: string | null\n source_call_id: string | null\n message_id: string | null\n event_id: string | null\n status: string | null\n is_error: 0 | 1\n exit_code: number | null\n duration_ms: number | null\n stdout_object_id: ObjectId | null\n stderr_object_id: ObjectId | null\n output_object_id: ObjectId | null\n preview: string | null\n raw_record_id: string\n}\n\n/** Artifact row staged from Codex patch or file-producing events. */\ninterface PendingArtifact {\n artifact_id: string\n kind: string\n path: string | null\n logical_path: string | null\n object_id: ObjectId | null\n text_object_id: ObjectId | null\n mime_type: string | null\n size_bytes: number\n created_ts: string | null\n raw_record_id: string\n}\n\n/** Graph edge row staged for recovered Codex subagent relationships. */\ninterface PendingEdge {\n src_type: string\n src_id: string\n dst_type: string\n dst_id: string\n edge_type: string\n confidence: 'high' | 'medium' | 'low'\n source: string\n raw_record_id: string | null\n}\n\n/** Search index row staged from normalized Codex messages, commands, paths, and previews. */\ninterface PendingSearchDoc {\n doc_id: string\n entity_type: string\n entity_id: string\n timestamp: string | null\n role: string | null\n tool_name: string | null\n canonical_tool_type: string | null\n field_kind: string\n text: string\n}\n\n/** Parse a Codex JSONL file, stage CAS objects, and return rows for later synchronous flush. */\nasync function prepareCodexFile(\n bundle: Bundle,\n batch: ImportBatch,\n filePath: string,\n logger?: CompileLogger,\n): Promise<{ prepared: CodexPrepared | null; counts: FileCounts }> {\n const counts = emptyFileCounts()\n\n const { row: sourceFileRow, alreadyKnown } = await registerSourceFile(bundle, {\n sourceTool: 'codex',\n absolutePath: path.resolve(filePath),\n fileKind: 'jsonl',\n })\n\n if (alreadyKnown) {\n // We've already imported this file (same path,size,mtime,hash). Skip.\n counts.source_files_skipped = 1\n logger?.debug({ path: filePath, source_file_id: sourceFileRow.source_file_id }, 'codex source file skipped')\n return { prepared: null, counts }\n }\n\n counts.source_files_imported = 1\n logger?.debug({ path: filePath, source_file_id: sourceFileRow.source_file_id }, 'codex source file registered')\n\n const text = await readFile(filePath, 'utf8')\n const rawLines = text.split('\\n')\n const lines = rawLines[rawLines.length - 1] === '' ? rawLines.slice(0, -1) : rawLines\n\n const pending = {\n rawRecords: [] as PendingRawRecord[],\n session: null as PendingSession | null,\n turns: [] as PendingTurn[],\n events: [] as PendingEvent[],\n messages: [] as PendingMessage[],\n blocks: [] as PendingBlock[],\n toolCalls: new Map<string, PendingToolCall>(), // by source_call_id\n toolCallsList: [] as PendingToolCall[],\n toolResults: [] as PendingToolResult[],\n artifacts: [] as PendingArtifact[],\n edges: [] as PendingEdge[],\n searchDocs: [] as PendingSearchDoc[],\n objects: createPendingObjects(),\n }\n\n let sessionStartTs: string | null = null\n let sessionEndTs: string | null = null\n let modelFirst: string | null = null\n let modelLast: string | null = null\n let messageOrdinal = 0\n let turnOrdinal = 0\n\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i]\n if (!line || line.length === 0) continue\n const lineNo = i + 1\n const ordinal = i\n\n const lineBytes = Buffer.from(line, 'utf8')\n const rawObjectId = stageBytes(pending.objects, lineBytes, {\n mimeType: 'application/jsonl-line',\n encoding: 'utf-8',\n })\n\n let parsed: CodexEnvelope | null = null\n let parserStatus: 'ok' | 'partial' | 'failed' = 'ok'\n try {\n parsed = JSON.parse(line) as CodexEnvelope\n } catch {\n parserStatus = 'failed'\n }\n\n // The raw line already IS the JSON for `parserStatus === 'ok'`, so we\n // skip storing a re-serialized copy as `decoded_json_object_id`. Saves\n // ~half the CAS writes per file. Nothing reads it back later.\n const decodedObjectId: ObjectId | null = null\n\n const nativeId = parsed ? extractNativeId(parsed) : null\n\n const rawRecordId = makeRawRecordId(sourceFileRow.source_file_id, ordinal, rawObjectId)\n\n pending.rawRecords.push({\n raw_record_id: rawRecordId,\n source_file_id: sourceFileRow.source_file_id,\n source_tool: 'codex',\n record_kind: 'jsonl_line',\n ordinal,\n line_no: lineNo,\n json_pointer: null,\n native_id: nativeId,\n raw_object_id: rawObjectId,\n decoded_json_object_id: decodedObjectId,\n parser_status: parserStatus,\n confidence: parserStatus === 'ok' ? 'high' : 'low',\n import_batch_id: batch.batch_id,\n })\n\n if (!parsed) continue\n\n const ts = typeof parsed.timestamp === 'string' ? parsed.timestamp : null\n if (ts) {\n if (!sessionStartTs || ts < sessionStartTs) sessionStartTs = ts\n if (!sessionEndTs || ts > sessionEndTs) sessionEndTs = ts\n }\n\n const type = typeof parsed.type === 'string' ? parsed.type : null\n const payload = (parsed.payload ?? {}) as Record<string, unknown>\n\n if (type === 'session_meta') {\n const meta = payload as CodexSessionMetaPayload\n const sourceSessionId = meta.id ?? path.basename(filePath, '.jsonl')\n const sessionId = makeSessionId('codex', sourceSessionId)\n\n // First session_meta wins; later ones (rare) become operational events.\n if (!pending.session) {\n const sub = parseSubagent(meta.source)\n const parentSessionId = sub ? makeSessionId('codex', sub.parent_thread_id) : null\n pending.session = {\n session_id: sessionId,\n source_session_id: sourceSessionId,\n parent_session_id: parentSessionId,\n is_subagent: sub ? 1 : 0,\n agent_role: meta.agent_role ?? sub?.agent_role ?? null,\n agent_nickname: meta.agent_nickname ?? sub?.agent_nickname ?? null,\n title: null,\n start_ts: meta.timestamp ?? ts,\n cwd_initial: meta.cwd ?? null,\n git_branch_initial: meta.git?.branch ?? null,\n raw_record_id: rawRecordId,\n }\n if (parentSessionId) {\n pending.edges.push({\n src_type: 'session',\n src_id: parentSessionId,\n dst_type: 'session',\n dst_id: sessionId,\n edge_type: 'spawned',\n confidence: 'high',\n source: 'explicit',\n raw_record_id: rawRecordId,\n })\n }\n }\n continue\n }\n\n // From here on, we need a session_id. Ensure we have one (fallback if no\n // session_meta appeared yet).\n const sessionId = pending.session?.session_id ?? makeSessionId('codex', path.basename(filePath, '.jsonl'))\n if (!pending.session) {\n pending.session = {\n session_id: sessionId,\n source_session_id: path.basename(filePath, '.jsonl'),\n parent_session_id: null,\n is_subagent: 0,\n agent_role: null,\n agent_nickname: null,\n title: null,\n start_ts: ts,\n cwd_initial: null,\n git_branch_initial: null,\n raw_record_id: null,\n }\n }\n\n if (type === 'turn_context') {\n const tc = payload as CodexTurnContextPayload\n const turnId = makeTurnId(sessionId, turnOrdinal, tc.turn_id ?? null)\n const turn: PendingTurn = {\n turn_id: turnId,\n ordinal: turnOrdinal++,\n source_turn_id: tc.turn_id ?? null,\n start_ts: ts,\n model: tc.model ?? null,\n cwd: tc.cwd ?? null,\n approval_policy: tc.approval_policy ?? null,\n sandbox_policy: stringifyOrNull(tc.sandbox_policy),\n effort: tc.effort ?? null,\n raw_record_id: rawRecordId,\n }\n pending.turns.push(turn)\n if (turn.model) {\n if (!modelFirst) modelFirst = turn.model\n modelLast = turn.model\n }\n continue\n }\n\n const currentTurnId = pending.turns.length > 0 ? pending.turns[pending.turns.length - 1]!.turn_id : null\n\n if (type === 'response_item') {\n const ri = payload as CodexResponseItemPayload\n handleResponseItem(\n bundle,\n sessionId,\n currentTurnId,\n rawRecordId,\n ordinal,\n ts,\n ri,\n decodedObjectId,\n () => messageOrdinal++,\n modelLast,\n pending,\n )\n continue\n }\n\n if (type === 'event_msg') {\n const em = payload as CodexEventMsgPayload\n await handleEventMsg(bundle, sessionId, currentTurnId, rawRecordId, ordinal, ts, em, decodedObjectId, pending)\n continue\n }\n\n if (type === 'compacted') {\n pending.events.push({\n event_id: makeEventId(sessionId, ordinal, 'compaction'),\n ordinal,\n turn_id: currentTurnId,\n source_event_id: null,\n event_type: 'compaction',\n source_type: 'compacted',\n subtype: null,\n timestamp: ts,\n actor: 'system',\n payload_object_id: decodedObjectId,\n raw_record_id: rawRecordId,\n confidence: 'high',\n })\n continue\n }\n\n // Legacy top-level message / function_call etc.\n if (type === 'message') {\n const ri = payload as CodexResponseItemPayload\n // Treat as if it were wrapped in response_item.\n handleResponseItem(\n bundle,\n sessionId,\n currentTurnId,\n rawRecordId,\n ordinal,\n ts,\n { ...ri, type: 'message' },\n decodedObjectId,\n () => messageOrdinal++,\n modelLast,\n pending,\n )\n }\n // Anything else: keep as raw record, do not normalize. The presence in\n // raw_records is enough for re-processing later.\n }\n\n if (pending.session) {\n pending.session.start_ts ??= sessionStartTs\n }\n\n // Build search_docs from messages and tool calls already accumulated.\n buildSearchDocs(pending)\n\n // Persist the staged CAS objects to disk + the `objects` table BEFORE the\n // domain transaction. We do filesystem writes in parallel (better-sqlite3\n // transactions are synchronous, so this can't run inside `transactional`).\n await flushPendingObjects(bundle, pending.objects)\n\n counts.raw_records = pending.rawRecords.length\n counts.sessions = pending.session ? 1 : 0\n counts.turns = pending.turns.length\n counts.events = pending.events.length\n counts.messages = pending.messages.length\n counts.content_blocks = pending.blocks.length\n counts.tool_calls = pending.toolCallsList.length\n counts.tool_results = pending.toolResults.length\n counts.artifacts = pending.artifacts.length\n counts.edges = pending.edges.length\n logger?.debug({ path: filePath, source_file_id: sourceFileRow.source_file_id, counts }, 'codex source file prepared')\n\n return {\n prepared: {\n filePath,\n pending,\n meta: { sessionEndTs, modelFirst, modelLast },\n },\n counts,\n }\n}\n\n/** Flush one prepared Codex file's normalized rows inside the caller's transaction. */\nfunction applyCodexFile(bundle: Bundle, prep: CodexPrepared): void {\n flushPending(bundle, prep.pending, {\n sessionEndTs: prep.meta.sessionEndTs,\n modelFirst: prep.meta.modelFirst,\n modelLast: prep.meta.modelLast,\n sourceTool: 'codex',\n })\n}\n\n/** All normalized Codex rows staged for one source file before FK-ordered flush. */\ninterface PendingState {\n rawRecords: PendingRawRecord[]\n session: PendingSession | null\n turns: PendingTurn[]\n events: PendingEvent[]\n messages: PendingMessage[]\n blocks: PendingBlock[]\n toolCalls: Map<string, PendingToolCall>\n toolCallsList: PendingToolCall[]\n toolResults: PendingToolResult[]\n artifacts: PendingArtifact[]\n edges: PendingEdge[]\n searchDocs: PendingSearchDoc[]\n objects: PendingObjects\n}\n\ntype ResponseItemCtx = {\n sessionId: string\n currentTurnId: string | null\n rawRecordId: string\n ordinal: number\n ts: string | null\n payloadObjectId: ObjectId | null\n nextMsgOrdinal: () => number\n currentModel: string | null\n pending: PendingState\n}\n\nfunction handleResponseItemMessage(ctx: ResponseItemCtx, ri: CodexResponseItemPayload): void {\n const { sessionId, currentTurnId, rawRecordId, ordinal, ts, payloadObjectId, nextMsgOrdinal, currentModel, pending } =\n ctx\n const role = mapMessageRole(ri.role)\n const msgOrdinal = nextMsgOrdinal()\n const messageId = makeMessageId(sessionId, msgOrdinal, null)\n\n const eventId = makeEventId(sessionId, ordinal, 'message')\n pending.events.push({\n event_id: eventId,\n ordinal,\n turn_id: currentTurnId,\n source_event_id: null,\n event_type: 'message',\n source_type: 'response_item.message',\n subtype: null,\n timestamp: ts,\n actor: ri.role ?? null,\n payload_object_id: payloadObjectId,\n raw_record_id: rawRecordId,\n confidence: 'high',\n })\n\n pending.messages.push({\n message_id: messageId,\n turn_id: currentTurnId,\n event_id: eventId,\n source_message_id: null,\n role,\n model: role === 'assistant' ? currentModel : null,\n timestamp: ts,\n ordinal: msgOrdinal,\n raw_record_id: rawRecordId,\n })\n\n const contentItems = Array.isArray(ri.content) ? (ri.content as CodexContentItem[]) : []\n for (let bi = 0; bi < contentItems.length; bi++) {\n const item = contentItems[bi]\n if (!item) continue\n const text = typeof item.text === 'string' ? item.text : null\n const blockType = item.type ?? 'text'\n pending.blocks.push({\n block_id: blockId(messageId, bi),\n message_id: messageId,\n event_id: null,\n ordinal: bi,\n block_type: blockType,\n text_object_id: null,\n text_inline: text,\n raw_record_id: rawRecordId,\n })\n }\n}\n\nfunction handleResponseItemFunctionCall(ctx: ResponseItemCtx, ri: CodexResponseItemPayload): void {\n const { sessionId, currentTurnId, rawRecordId, ordinal, ts, payloadObjectId, pending } = ctx\n const sourceCallId = typeof ri.call_id === 'string' ? ri.call_id : null\n const toolName = typeof ri.name === 'string' ? ri.name : 'unknown'\n const toolCallId = makeToolCallId(sessionId, sourceCallId ?? `${ordinal}`)\n const argsObjectId = ri.arguments != null ? stageJson(pending.objects, ri.arguments) : null\n const command = inferCommandFromArgs(toolName, ri.arguments)\n\n const eventId = makeEventId(sessionId, ordinal, 'tool_call')\n pending.events.push({\n event_id: eventId,\n ordinal,\n turn_id: currentTurnId,\n source_event_id: null,\n event_type: 'tool_call',\n source_type: 'response_item.function_call',\n subtype: toolName,\n timestamp: ts,\n actor: 'assistant',\n payload_object_id: payloadObjectId,\n raw_record_id: rawRecordId,\n confidence: 'high',\n })\n\n const call: PendingToolCall = {\n tool_call_id: toolCallId,\n turn_id: currentTurnId,\n message_id: null,\n event_id: eventId,\n source_call_id: sourceCallId,\n tool_name: toolName,\n canonical_tool_type: canonicalToolType(toolName),\n args_object_id: argsObjectId,\n command,\n cwd: null,\n path: inferPathFromArgs(ri.arguments),\n query: null,\n timestamp_start: ts,\n status: 'started',\n raw_record_id: rawRecordId,\n }\n if (sourceCallId) pending.toolCalls.set(sourceCallId, call)\n pending.toolCallsList.push(call)\n}\n\nfunction handleResponseItemFunctionCallOutput(ctx: ResponseItemCtx, ri: CodexResponseItemPayload): void {\n const { sessionId, currentTurnId, rawRecordId, ordinal, ts, payloadObjectId, pending } = ctx\n const sourceCallId = typeof ri.call_id === 'string' ? ri.call_id : null\n const outputText = stringifyOrNull(ri.output) ?? ''\n const outputObj = isRecord(ri.output) ? ri.output : null\n const isError =\n outputObj?.is_error === true ||\n outputObj?.isError === true ||\n ri.status === 'incomplete' ||\n looksLikeError(outputText)\n ? 1\n : 0\n\n const eventId = makeEventId(sessionId, ordinal, 'tool_result')\n pending.events.push({\n event_id: eventId,\n ordinal,\n turn_id: currentTurnId,\n source_event_id: null,\n event_type: 'tool_result',\n source_type: 'response_item.function_call_output',\n subtype: null,\n timestamp: ts,\n actor: 'tool',\n payload_object_id: payloadObjectId,\n raw_record_id: rawRecordId,\n confidence: 'high',\n })\n\n const matchedCall = sourceCallId ? pending.toolCalls.get(sourceCallId) : undefined\n pending.toolResults.push({\n tool_result_id: makeToolResultId(sessionId, sourceCallId ?? `${ordinal}`),\n tool_call_id: matchedCall?.tool_call_id ?? null,\n source_call_id: sourceCallId,\n message_id: null,\n event_id: eventId,\n status: normalizeToolCallStatus('codex', ri.status),\n is_error: isError,\n exit_code: null,\n duration_ms: null,\n stdout_object_id: null,\n stderr_object_id: null,\n output_object_id: null,\n preview: outputText.slice(0, PREVIEW_MAX),\n raw_record_id: rawRecordId,\n })\n if (matchedCall) {\n matchedCall.status = matchedCall.status === 'started' ? (isError ? 'error' : 'success') : matchedCall.status\n }\n}\n\nfunction handleResponseItemPassthrough(ctx: ResponseItemCtx, ri: CodexResponseItemPayload): void {\n // reasoning, custom_tool_*, web_search_call, ghost_snapshot, etc.: keep as\n // operational events for now. Raw is preserved either way.\n const { sessionId, currentTurnId, rawRecordId, ordinal, ts, payloadObjectId, pending } = ctx\n const subtype = ri.type ?? null\n const eventId = makeEventId(sessionId, ordinal, `response_item.${subtype ?? 'unknown'}`)\n pending.events.push({\n event_id: eventId,\n ordinal,\n turn_id: currentTurnId,\n source_event_id: null,\n event_type: subtype ?? 'response_item',\n source_type: `response_item.${subtype ?? 'unknown'}`,\n subtype,\n timestamp: ts,\n actor: 'assistant',\n payload_object_id: payloadObjectId,\n raw_record_id: rawRecordId,\n confidence: 'high',\n })\n}\n\nconst RESPONSE_ITEM_HANDLERS: Record<string, (ctx: ResponseItemCtx, ri: CodexResponseItemPayload) => void> = {\n message: handleResponseItemMessage,\n function_call: handleResponseItemFunctionCall,\n function_call_output: handleResponseItemFunctionCallOutput,\n}\n\n/** Normalize a Codex `response_item` payload into messages, tool calls/results, or events. */\nfunction handleResponseItem(\n _bundle: Bundle,\n sessionId: string,\n currentTurnId: string | null,\n rawRecordId: string,\n ordinal: number,\n ts: string | null,\n ri: CodexResponseItemPayload,\n payloadObjectId: ObjectId | null,\n nextMsgOrdinal: () => number,\n currentModel: string | null,\n pending: PendingState,\n): void {\n const ctx: ResponseItemCtx = {\n sessionId,\n currentTurnId,\n rawRecordId,\n ordinal,\n ts,\n payloadObjectId,\n nextMsgOrdinal,\n currentModel,\n pending,\n }\n const handler = ri.type ? RESPONSE_ITEM_HANDLERS[ri.type] : undefined\n ;(handler ?? handleResponseItemPassthrough)(ctx, ri)\n}\n\ntype EventMsgCtx = {\n sessionId: string\n currentTurnId: string | null\n rawRecordId: string\n ordinal: number\n ts: string | null\n payloadObjectId: ObjectId | null\n pending: PendingState\n}\n\nfunction handleExecCommandEnd(ctx: EventMsgCtx, em: CodexEventMsgPayload): void {\n const { sessionId, currentTurnId, rawRecordId, ordinal, ts, payloadObjectId, pending } = ctx\n const sourceCallId = em.call_id ?? null\n const stdoutId = em.stdout ? stageText(pending.objects, em.stdout, { mimeType: 'text/plain' }) : null\n const stderrId = em.stderr ? stageText(pending.objects, em.stderr, { mimeType: 'text/plain' }) : null\n const preview = (em.formatted_output ?? em.aggregated_output ?? em.stdout ?? '').slice(0, PREVIEW_MAX)\n const exitCode = typeof em.exit_code === 'number' ? em.exit_code : null\n const isError = exitCode != null && exitCode !== 0 ? 1 : 0\n\n const eventId = makeEventId(sessionId, ordinal, 'exec_command_end')\n pending.events.push({\n event_id: eventId,\n ordinal,\n turn_id: currentTurnId,\n source_event_id: null,\n event_type: 'tool_result',\n source_type: 'event_msg.exec_command_end',\n subtype: 'shell',\n timestamp: ts,\n actor: 'tool',\n payload_object_id: payloadObjectId,\n raw_record_id: rawRecordId,\n confidence: 'high',\n })\n\n const matchedCall = sourceCallId ? pending.toolCalls.get(sourceCallId) : undefined\n pending.toolResults.push({\n tool_result_id: makeToolResultId(sessionId, `${sourceCallId ?? ordinal}::exec_command_end`),\n tool_call_id: matchedCall?.tool_call_id ?? null,\n source_call_id: sourceCallId,\n message_id: null,\n event_id: eventId,\n status: normalizeToolCallStatus('codex', em.status ?? (isError ? 'error' : 'success')),\n is_error: isError,\n exit_code: exitCode,\n duration_ms: durationMs(em.duration),\n stdout_object_id: stdoutId,\n stderr_object_id: stderrId,\n output_object_id: null,\n preview,\n raw_record_id: rawRecordId,\n })\n if (matchedCall) {\n matchedCall.status = isError ? 'error' : 'success'\n if (em.cwd && !matchedCall.cwd) matchedCall.cwd = em.cwd\n }\n}\n\nfunction handlePatchApplyEnd(ctx: EventMsgCtx, em: CodexEventMsgPayload): void {\n const { sessionId, currentTurnId, rawRecordId, ordinal, ts, payloadObjectId, pending } = ctx\n const eventId = makeEventId(sessionId, ordinal, 'patch_apply_end')\n pending.events.push({\n event_id: eventId,\n ordinal,\n turn_id: currentTurnId,\n source_event_id: null,\n event_type: 'patch',\n source_type: 'event_msg.patch_apply_end',\n subtype: null,\n timestamp: ts,\n actor: 'tool',\n payload_object_id: payloadObjectId,\n raw_record_id: rawRecordId,\n confidence: 'high',\n })\n if (em.changes && typeof em.changes === 'object') {\n for (const filePath of Object.keys(em.changes)) {\n pending.artifacts.push({\n artifact_id: artifactId(sessionId, 'codex', `${eventId}:${filePath}`),\n kind: 'diff',\n path: filePath,\n logical_path: filePath,\n object_id: null,\n text_object_id: null,\n mime_type: 'text/x-diff',\n size_bytes: 0,\n created_ts: ts,\n raw_record_id: rawRecordId,\n })\n }\n }\n}\n\nfunction handleMcpToolCallEnd(ctx: EventMsgCtx, em: CodexEventMsgPayload): void {\n const { sessionId, currentTurnId, rawRecordId, ordinal, ts, payloadObjectId, pending } = ctx\n const sourceCallId = em.call_id ?? null\n const eventId = makeEventId(sessionId, ordinal, 'mcp_tool_call_end')\n pending.events.push({\n event_id: eventId,\n ordinal,\n turn_id: currentTurnId,\n source_event_id: null,\n event_type: 'tool_result',\n source_type: 'event_msg.mcp_tool_call_end',\n subtype: 'mcp',\n timestamp: ts,\n actor: 'tool',\n payload_object_id: payloadObjectId,\n raw_record_id: rawRecordId,\n confidence: 'high',\n })\n const preview = stringifyOrNull(em.result)?.slice(0, PREVIEW_MAX) ?? null\n const matchedCall = sourceCallId ? pending.toolCalls.get(sourceCallId) : undefined\n const isError = isMcpResultError(em.status, em.result) ? 1 : 0\n const status = normalizeToolCallStatus('codex', em.status ?? (isError ? 'error' : 'success'))\n pending.toolResults.push({\n tool_result_id: makeToolResultId(sessionId, `${sourceCallId ?? ordinal}::mcp_tool_call_end`),\n tool_call_id: matchedCall?.tool_call_id ?? null,\n source_call_id: sourceCallId,\n message_id: null,\n event_id: eventId,\n status,\n is_error: isError,\n exit_code: null,\n duration_ms: durationMs(em.duration),\n stdout_object_id: null,\n stderr_object_id: null,\n output_object_id: null,\n preview,\n raw_record_id: rawRecordId,\n })\n if (matchedCall) {\n matchedCall.status = isError ? 'error' : status\n }\n}\n\nfunction handleContextCompacted(ctx: EventMsgCtx): void {\n const { sessionId, currentTurnId, rawRecordId, ordinal, ts, payloadObjectId, pending } = ctx\n pending.events.push({\n event_id: makeEventId(sessionId, ordinal, 'compaction'),\n ordinal,\n turn_id: currentTurnId,\n source_event_id: null,\n event_type: 'compaction',\n source_type: 'event_msg.context_compacted',\n subtype: null,\n timestamp: ts,\n actor: 'system',\n payload_object_id: payloadObjectId,\n raw_record_id: rawRecordId,\n confidence: 'high',\n })\n}\n\nfunction handleEventMsgPassthrough(ctx: EventMsgCtx, em: CodexEventMsgPayload): void {\n // user_message / agent_message / task_started / task_complete / turn_aborted /\n // token_count / others — keep as operational events.\n const { sessionId, currentTurnId, rawRecordId, ordinal, ts, payloadObjectId, pending } = ctx\n const subtype = em.type ?? 'unknown'\n pending.events.push({\n event_id: makeEventId(sessionId, ordinal, `event_msg.${subtype}`),\n ordinal,\n turn_id: currentTurnId,\n source_event_id: null,\n event_type: 'system_operational',\n source_type: `event_msg.${subtype}`,\n subtype,\n timestamp: ts,\n actor: 'system',\n payload_object_id: payloadObjectId,\n raw_record_id: rawRecordId,\n confidence: 'high',\n })\n}\n\nconst EVENT_MSG_HANDLERS: Record<string, (ctx: EventMsgCtx, em: CodexEventMsgPayload) => void> = {\n exec_command_end: handleExecCommandEnd,\n patch_apply_end: handlePatchApplyEnd,\n mcp_tool_call_end: handleMcpToolCallEnd,\n context_compacted: (ctx) => handleContextCompacted(ctx),\n}\n\n/** Normalize Codex operational `event_msg` payloads while preserving unknown types as events. */\nasync function handleEventMsg(\n _bundle: Bundle,\n sessionId: string,\n currentTurnId: string | null,\n rawRecordId: string,\n ordinal: number,\n ts: string | null,\n em: CodexEventMsgPayload,\n payloadObjectId: ObjectId | null,\n pending: PendingState,\n): Promise<void> {\n const ctx: EventMsgCtx = {\n sessionId,\n currentTurnId,\n rawRecordId,\n ordinal,\n ts,\n payloadObjectId,\n pending,\n }\n const handler = em.type ? EVENT_MSG_HANDLERS[em.type] : undefined\n ;(handler ?? handleEventMsgPassthrough)(ctx, em)\n}\n\n// ---- helpers -------------------------------------------------------------\n\n/** Pick the best native locator from a loose Codex envelope for raw record lookup. */\nfunction extractNativeId(env: CodexEnvelope): string | null {\n const p = env.payload as Record<string, unknown> | undefined\n if (!p) return null\n if (typeof p.id === 'string') return p.id\n if (typeof p.call_id === 'string') return p.call_id\n if (typeof p.turn_id === 'string') return p.turn_id\n return null\n}\n\n/** Map native Codex roles into prosa's normalized message role vocabulary. */\nfunction mapMessageRole(role: unknown): PendingMessage['role'] {\n switch (role) {\n case 'user':\n return 'user'\n case 'assistant':\n return 'assistant'\n case 'tool':\n return 'tool'\n case 'developer':\n return 'developer'\n case 'system':\n // Codex 'system' content is real system instructions — map to system_prompt.\n return 'system_prompt'\n default:\n return 'operational'\n }\n}\n\n/** Collapse Codex and MCP tool names into broad search/filter tool categories. */\nfunction canonicalToolType(toolName: string): string {\n const lower = toolName.toLowerCase()\n if (lower.startsWith('mcp__')) return 'mcp'\n if (\n lower === 'shell' ||\n lower === 'exec_command' ||\n lower === 'shell_command' ||\n lower === 'write_stdin' ||\n lower === 'unified_exec' ||\n lower === 'run_terminal_cmd'\n ) {\n return 'shell'\n }\n if (lower === 'read_file' || lower === 'readfile') return 'read_file'\n if (lower === 'write_file' || lower === 'writefile') return 'write_file'\n if (lower === 'apply_patch' || lower === 'applypatch' || lower === 'patch') return 'patch'\n if (lower === 'web_search' || lower === 'websearch' || lower === 'web_search_call') {\n return 'web_search'\n }\n if (lower === 'agent' || lower === 'subagent' || lower === 'collab_spawn') return 'subagent'\n return 'other'\n}\n\n/** Extract a shell command from loose tool arguments when the native tool exposes one. */\nfunction inferCommandFromArgs(toolName: string, args: unknown): string | null {\n if (!args || typeof args !== 'object') {\n if (typeof args === 'string') {\n try {\n const parsed = JSON.parse(args) as Record<string, unknown>\n return inferCommandFromArgs(toolName, parsed)\n } catch {\n return null\n }\n }\n return null\n }\n const obj = args as Record<string, unknown>\n if (typeof obj.command === 'string') return obj.command\n if (Array.isArray(obj.command)) {\n return obj.command.map(String).join(' ')\n }\n return null\n}\n\n/** Extract a file path from loose tool arguments without treating absence as an error. */\nfunction inferPathFromArgs(args: unknown): string | null {\n if (!args || typeof args !== 'object') {\n if (typeof args === 'string') {\n try {\n const parsed = JSON.parse(args) as Record<string, unknown>\n return inferPathFromArgs(parsed)\n } catch {\n return null\n }\n }\n return null\n }\n const obj = args as Record<string, unknown>\n if (typeof obj.file_path === 'string') return obj.file_path\n if (typeof obj.path === 'string') return obj.path\n if (typeof obj.absolute_path === 'string') return obj.absolute_path\n return null\n}\n\n/** Heuristic for legacy tool outputs that do not carry an explicit error flag. */\nfunction looksLikeError(text: string): boolean {\n return /\\b(error|exception|failed|stack trace)\\b/i.test(text)\n}\n\n/** Recover structured MCP failures from loose event payloads. */\nfunction isMcpResultError(status: string | null | undefined, result: unknown): boolean {\n const normalized = normalizeToolCallStatus('codex', status)\n if (normalized === 'error' || normalized === 'cancelled') return true\n if (Array.isArray(result)) return result.some((item) => isMcpResultError(null, item))\n if (!isRecord(result)) return false\n if (result.is_error === true || result.isError === true) return true\n if (typeof result.status === 'string' && normalizeToolCallStatus('codex', result.status) === 'error') return true\n return result.error != null\n}\n\n/** Convert Codex's seconds/nanoseconds duration object to milliseconds. */\nfunction durationMs(d: CodexEventMsgPayload['duration']): number | null {\n if (!d || typeof d !== 'object') return null\n const secs = typeof d.secs === 'number' ? d.secs : 0\n const nanos = typeof d.nanos === 'number' ? d.nanos : 0\n return secs * 1000 + Math.floor(nanos / 1e6)\n}\n\n/** Convert arbitrary recovered payload values into compact text previews when possible. */\nfunction stringifyOrNull(value: unknown): string | null {\n if (value == null) return null\n if (typeof value === 'string') return value\n try {\n return JSON.stringify(value)\n } catch {\n return null\n }\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n}\n\n/** Recover explicit Codex subagent spawn metadata from `session_meta.source`. */\nfunction parseSubagent(\n source: unknown,\n): { parent_thread_id: string; agent_role?: string; agent_nickname?: string } | null {\n if (!source || typeof source !== 'object') return null\n const obj = source as Record<string, unknown>\n const sub = obj.subagent\n if (!sub || typeof sub !== 'object') return null\n const ts = (sub as Record<string, unknown>).thread_spawn\n if (!ts || typeof ts !== 'object') return null\n const tso = ts as Record<string, unknown>\n const parent = tso.parent_thread_id\n if (typeof parent !== 'string') return null\n return {\n parent_thread_id: parent,\n agent_role: typeof tso.agent_role === 'string' ? tso.agent_role : undefined,\n agent_nickname: typeof tso.agent_nickname === 'string' ? tso.agent_nickname : undefined,\n }\n}\n\n/** Build searchable Codex documents from staged messages, tool calls, and result previews. */\nfunction buildSearchDocs(pending: PendingState): void {\n const sessionId = pending.session?.session_id ?? null\n if (!sessionId) return\n\n // Group blocks by message for indexing concatenated text.\n const blocksByMsg = new Map<string, PendingBlock[]>()\n for (const b of pending.blocks) {\n if (!b.message_id) continue\n const list = blocksByMsg.get(b.message_id) ?? []\n list.push(b)\n blocksByMsg.set(b.message_id, list)\n }\n\n for (const m of pending.messages) {\n const text = (blocksByMsg.get(m.message_id) ?? [])\n .filter(\n (b) =>\n b.text_inline && (b.block_type === 'input_text' || b.block_type === 'output_text' || b.block_type === 'text'),\n )\n .map((b) => b.text_inline as string)\n .join('\\n')\n if (!text || text.length === 0) continue\n pending.searchDocs.push({\n doc_id: `msg:${m.message_id}`,\n entity_type: 'message',\n entity_id: m.message_id,\n timestamp: m.timestamp,\n role: m.role,\n tool_name: null,\n canonical_tool_type: null,\n field_kind: m.role === 'user' ? 'user_prompt' : 'assistant_text',\n text,\n })\n }\n\n for (const c of pending.toolCallsList) {\n if (c.command) {\n pending.searchDocs.push({\n doc_id: `tc:cmd:${c.tool_call_id}`,\n entity_type: 'tool_call',\n entity_id: c.tool_call_id,\n timestamp: c.timestamp_start,\n role: null,\n tool_name: c.tool_name,\n canonical_tool_type: c.canonical_tool_type,\n field_kind: 'command',\n text: c.command,\n })\n }\n if (c.path) {\n pending.searchDocs.push({\n doc_id: `tc:path:${c.tool_call_id}`,\n entity_type: 'tool_call',\n entity_id: c.tool_call_id,\n timestamp: c.timestamp_start,\n role: null,\n tool_name: c.tool_name,\n canonical_tool_type: c.canonical_tool_type,\n field_kind: 'file_path',\n text: c.path,\n })\n }\n }\n\n for (const r of pending.toolResults) {\n if (r.preview) {\n pending.searchDocs.push({\n doc_id: `tr:preview:${r.tool_result_id}`,\n entity_type: 'tool_result',\n entity_id: r.tool_result_id,\n timestamp: null,\n role: null,\n tool_name: null,\n canonical_tool_type: null,\n field_kind: r.is_error ? 'error' : 'command_output_preview',\n text: r.preview,\n })\n }\n }\n}\n\n/** Insert staged Codex rows in foreign-key order after CAS objects are already durable. */\nfunction flushPending(\n bundle: Bundle,\n pending: PendingState,\n meta: {\n sessionEndTs: string | null\n modelFirst: string | null\n modelLast: string | null\n sourceTool: 'codex'\n },\n): void {\n if (!pending.session) return\n\n // Order matters under SQLite's immediate FK checking: rows must be inserted\n // before any other row references them. raw_records → sessions →\n // turns/events → messages → blocks → tool_calls → tool_results.\n //\n // We also insert sessions with parent_session_id=NULL initially because the\n // parent session may live in a different file/batch. The cross-file linkage\n // happens in `linkParents` below, after every file is committed.\n\n const insertRaw = prepare(\n bundle.db,\n `INSERT OR IGNORE INTO raw_records (\n raw_record_id, source_file_id, source_tool, record_kind, ordinal,\n line_no, json_pointer, native_id, raw_object_id, decoded_json_object_id,\n parser_status, confidence, import_batch_id\n ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,\n )\n for (const r of pending.rawRecords) {\n insertRaw.run(\n r.raw_record_id,\n r.source_file_id,\n r.source_tool,\n r.record_kind,\n r.ordinal,\n r.line_no,\n r.json_pointer,\n r.native_id,\n r.raw_object_id,\n r.decoded_json_object_id,\n r.parser_status,\n r.confidence,\n r.import_batch_id,\n )\n }\n\n const insertSession = prepare(\n bundle.db,\n `INSERT OR REPLACE INTO sessions (\n session_id, source_tool, source_session_id, project_id, parent_session_id,\n is_subagent, agent_role, agent_nickname, title, summary,\n start_ts, end_ts, cwd_initial, git_branch_initial,\n model_first, model_last, status, timeline_confidence, raw_record_id\n ) VALUES (?, ?, ?, ?, NULL, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 'high', ?)`,\n )\n insertSession.run(\n pending.session.session_id,\n meta.sourceTool,\n pending.session.source_session_id,\n null,\n pending.session.is_subagent,\n pending.session.agent_role,\n pending.session.agent_nickname,\n pending.session.title,\n null,\n pending.session.start_ts,\n meta.sessionEndTs,\n pending.session.cwd_initial,\n pending.session.git_branch_initial,\n meta.modelFirst,\n meta.modelLast,\n 'completed',\n pending.session.raw_record_id,\n )\n\n const insertTurn = prepare(\n bundle.db,\n `INSERT OR REPLACE INTO turns (\n turn_id, session_id, source_turn_id, ordinal, start_ts, end_ts,\n model, cwd, git_branch, approval_policy, sandbox_policy, effort, raw_record_id\n ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,\n )\n for (const t of pending.turns) {\n insertTurn.run(\n t.turn_id,\n pending.session.session_id,\n t.source_turn_id,\n t.ordinal,\n t.start_ts,\n null,\n t.model,\n t.cwd,\n null,\n t.approval_policy,\n t.sandbox_policy,\n t.effort,\n t.raw_record_id,\n )\n }\n\n const insertEvent = prepare(\n bundle.db,\n `INSERT OR REPLACE INTO events (\n event_id, session_id, turn_id, source_event_id, event_type, source_type,\n subtype, timestamp, ordinal, actor, payload_object_id, raw_record_id,\n confidence, is_derived\n ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 0)`,\n )\n for (const e of pending.events) {\n insertEvent.run(\n e.event_id,\n pending.session.session_id,\n e.turn_id,\n e.source_event_id,\n e.event_type,\n e.source_type,\n e.subtype,\n e.timestamp,\n e.ordinal,\n e.actor,\n e.payload_object_id,\n e.raw_record_id,\n e.confidence,\n )\n }\n\n const insertMessage = prepare(\n bundle.db,\n `INSERT OR REPLACE INTO messages (\n message_id, session_id, turn_id, event_id, source_message_id, role,\n author_name, model, timestamp, ordinal, parent_message_id, request_id,\n status, raw_record_id\n ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,\n )\n for (const m of pending.messages) {\n insertMessage.run(\n m.message_id,\n pending.session.session_id,\n m.turn_id,\n m.event_id,\n m.source_message_id,\n m.role,\n null,\n m.model,\n m.timestamp,\n m.ordinal,\n null,\n null,\n null,\n m.raw_record_id,\n )\n }\n\n const insertBlock = prepare(\n bundle.db,\n `INSERT OR REPLACE INTO content_blocks (\n block_id, message_id, event_id, session_id, ordinal, block_type,\n text_object_id, text_inline, mime_type, token_count, is_error,\n is_redacted, visibility, raw_record_id\n ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 'default', ?)`,\n )\n for (const b of pending.blocks) {\n insertBlock.run(\n b.block_id,\n b.message_id,\n b.event_id,\n pending.session.session_id,\n b.ordinal,\n b.block_type,\n b.text_object_id,\n b.text_inline,\n null,\n null,\n 0,\n 0,\n b.raw_record_id,\n )\n }\n\n const insertToolCall = prepare(\n bundle.db,\n `INSERT OR REPLACE INTO tool_calls (\n tool_call_id, session_id, turn_id, message_id, event_id,\n source_call_id, tool_name, canonical_tool_type, args_object_id,\n command, cwd, path, query, timestamp_start, timestamp_end, status,\n raw_record_id\n ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,\n )\n for (const c of pending.toolCallsList) {\n insertToolCall.run(\n c.tool_call_id,\n pending.session.session_id,\n c.turn_id,\n c.message_id,\n c.event_id,\n c.source_call_id,\n c.tool_name,\n c.canonical_tool_type,\n c.args_object_id,\n c.command,\n c.cwd,\n c.path,\n c.query,\n c.timestamp_start,\n null,\n c.status,\n c.raw_record_id,\n )\n }\n\n const insertToolResult = prepare(\n bundle.db,\n `INSERT OR REPLACE INTO tool_results (\n tool_result_id, tool_call_id, session_id, message_id, event_id,\n source_call_id, status, is_error, exit_code, duration_ms,\n stdout_object_id, stderr_object_id, output_object_id, preview, raw_record_id\n ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,\n )\n for (const r of pending.toolResults) {\n insertToolResult.run(\n r.tool_result_id,\n r.tool_call_id,\n pending.session.session_id,\n r.message_id,\n r.event_id,\n r.source_call_id,\n r.status,\n r.is_error,\n r.exit_code,\n r.duration_ms,\n r.stdout_object_id,\n r.stderr_object_id,\n r.output_object_id,\n r.preview,\n r.raw_record_id,\n )\n }\n\n const insertArtifact = prepare(\n bundle.db,\n `INSERT OR REPLACE INTO artifacts (\n artifact_id, session_id, project_id, source_tool, kind, path,\n logical_path, object_id, text_object_id, mime_type, size_bytes,\n created_ts, raw_record_id\n ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,\n )\n for (const a of pending.artifacts) {\n insertArtifact.run(\n a.artifact_id,\n pending.session.session_id,\n null,\n 'codex',\n a.kind,\n a.path,\n a.logical_path,\n a.object_id,\n a.text_object_id,\n a.mime_type,\n a.size_bytes,\n a.created_ts,\n a.raw_record_id,\n )\n }\n\n const insertEdge = prepare(\n bundle.db,\n `INSERT OR IGNORE INTO edges (\n src_type, src_id, dst_type, dst_id, edge_type, confidence, source,\n raw_record_id, metadata_object_id\n ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, NULL)`,\n )\n for (const e of pending.edges) {\n insertEdge.run(e.src_type, e.src_id, e.dst_type, e.dst_id, e.edge_type, e.confidence, e.source, e.raw_record_id)\n }\n\n const insertSearch = prepare(\n bundle.db,\n `INSERT OR REPLACE INTO search_docs (\n doc_id, entity_type, entity_id, session_id, project_id, timestamp,\n role, tool_name, canonical_tool_type, field_kind, text\n ) VALUES (?, ?, ?, ?, NULL, ?, ?, ?, ?, ?, ?)`,\n )\n for (const d of pending.searchDocs) {\n insertSearch.run(\n d.doc_id,\n d.entity_type,\n d.entity_id,\n pending.session.session_id,\n d.timestamp,\n d.role,\n d.tool_name,\n d.canonical_tool_type,\n d.field_kind,\n d.text,\n )\n }\n}\n","import { readdir } from 'node:fs/promises'\nimport path from 'node:path'\n\n/**\n * Walk a Codex sessions root (default `~/.codex/sessions`) and yield every\n * `rollout-*.jsonl` file. The native layout is `YYYY/MM/DD/rollout-...jsonl`,\n * but we don't depend on that — anything ending in `.jsonl` under `root`\n * counts.\n */\nexport async function* discoverCodexSessions(root: string): AsyncGenerator<string, void, void> {\n yield* walk(root)\n}\n\n/** Recursively traverse a possibly-missing sessions directory without failing discovery. */\nasync function* walk(dir: string): AsyncGenerator<string, void, void> {\n let entries: import('node:fs').Dirent[]\n try {\n entries = await readdir(dir, { withFileTypes: true })\n } catch {\n return\n }\n\n for (const entry of entries) {\n const full = path.join(dir, entry.name)\n if (entry.isDirectory()) {\n yield* walk(full)\n } else if (entry.isFile() && entry.name.endsWith('.jsonl')) {\n yield full\n }\n }\n}\n","import path from 'node:path'\nimport Database from 'better-sqlite3'\nimport type { Bundle } from '../../core/bundle.js'\nimport {\n type ObjectId,\n type PendingObjects,\n createPendingObjects,\n flushPendingObjects,\n stageBytes,\n stageJson,\n stageText,\n} from '../../core/cas/index.js'\nimport { prepare, transactional } from '../../core/db.js'\nimport {\n artifactId,\n blockId,\n eventId as makeEventId,\n messageId as makeMessageId,\n rawRecordId as makeRawRecordId,\n sessionId as makeSessionId,\n toolCallId as makeToolCallId,\n toolResultId as makeToolResultId,\n} from '../../core/domain/ids.js'\nimport { normalizeToolCallStatus } from '../../core/domain/status.js'\nimport { getErrorMessage } from '../../core/errors.js'\nimport {\n type ImportBatch,\n type ImportCounts,\n emptyCounts,\n finishBatch,\n recordError,\n startBatch,\n} from '../../core/ingest/batch.js'\nimport { registerSourceFile } from '../../core/ingest/idempotency.js'\nimport type { CompileLogger, CompileOptions } from '../compile-options.js'\nimport { type CursorStoreDb, discoverCursorStores } from './discover.js'\n\n/** Result returned after a Cursor compile batch finishes or records a failed batch. */\nexport interface CompileResult {\n /** Import batch created for this Cursor run. */\n batch: ImportBatch\n /** Final counts accumulated while importing Cursor stores. */\n counts: ImportCounts\n}\n\n/** Maximum inline text retained in normalized rows before full content moves to CAS. */\nconst PREVIEW_MAX = 4_000\n\n/**\n * Recovered Cursor `meta` row shape. This is a loose importer input for\n * observed store databases, not a validator for Cursor's native format.\n */\ninterface CursorMeta {\n agentId?: string\n latestRootBlobId?: string\n name?: string\n mode?: string\n createdAt?: number\n lastUsedModel?: string\n}\n\n/**\n * Recovered Cursor JSON blob shape. Many blobs are protobuf state instead, so\n * this shape is only used after a blob looks like JSON and parses successfully.\n */\ninterface CursorBlobJson {\n role?: string\n id?: string\n content?: string | CursorContentItem[]\n providerOptions?: Record<string, unknown>\n}\n\n/** Loose Cursor content item recovered from parsed JSON message blobs. */\ninterface CursorContentItem {\n type?: string\n text?: string\n toolCallId?: string\n toolName?: string\n args?: unknown\n result?: unknown\n experimental_content?: unknown\n signature?: string\n data?: unknown\n}\n\n/** Compile Cursor `store.db` files under `root` into the bundle. */\nexport async function compileCursor(\n bundle: Bundle,\n root: string,\n options: CompileOptions = {},\n): Promise<CompileResult> {\n const logger = options.logger\n const batch = startBatch(bundle, 'cursor', [root])\n const counts = emptyCounts()\n logger?.info({ batch_id: batch.batch_id, root }, 'cursor batch started')\n try {\n for await (const store of discoverCursorStores(root)) {\n counts.source_files_seen++\n logger?.debug(\n {\n path: store.filePath,\n workspace_id: store.workspaceId,\n agent_id: store.agentId,\n },\n 'cursor store discovered',\n )\n try {\n const fc = await compileCursorStore(bundle, batch, store, logger)\n addCounts(counts, fc)\n } catch (error) {\n counts.errors++\n logger?.warn(\n {\n err: error,\n path: store.filePath,\n },\n 'cursor store failed',\n )\n await recordError(bundle, batch.batch_id, {\n kind: 'cursor_store_failed',\n message: getErrorMessage(error),\n payload: { path: store.filePath },\n })\n }\n }\n finishBatch(bundle, batch, counts, 'completed')\n logger?.info({ batch_id: batch.batch_id, counts }, 'cursor batch completed')\n } catch (error) {\n finishBatch(bundle, batch, counts, 'failed')\n logger?.error({ err: error, batch_id: batch.batch_id, counts }, 'cursor batch failed')\n throw error\n }\n return { batch, counts }\n}\n\n/** Per-store deltas that are merged into the import batch counts. */\ninterface FileCounts {\n source_files_imported: number\n source_files_skipped: number\n raw_records: number\n sessions: number\n events: number\n messages: number\n content_blocks: number\n tool_calls: number\n tool_results: number\n artifacts: number\n edges: number\n errors: number\n}\n\n/** Create zeroed file counters for a Cursor store that may still fail or be skipped. */\nfunction emptyFileCounts(): FileCounts {\n return {\n source_files_imported: 0,\n source_files_skipped: 0,\n raw_records: 0,\n sessions: 0,\n events: 0,\n messages: 0,\n content_blocks: 0,\n tool_calls: 0,\n tool_results: 0,\n artifacts: 0,\n edges: 0,\n errors: 0,\n }\n}\n\n/** Merge a single Cursor store's normalized row counts into batch totals. */\nfunction addCounts(target: ImportCounts, source: FileCounts): void {\n target.source_files_imported += source.source_files_imported\n target.source_files_skipped += source.source_files_skipped\n target.raw_records += source.raw_records\n target.sessions += source.sessions\n target.events += source.events\n target.messages += source.messages\n target.content_blocks += source.content_blocks\n target.tool_calls += source.tool_calls\n target.tool_results += source.tool_results\n target.artifacts += source.artifacts\n target.edges += source.edges\n target.errors += source.errors\n}\n\n/** All normalized Cursor rows staged for one store before FK-ordered flush. */\ninterface PendingState {\n rawRecords: PendingRaw[]\n session: PendingSession | null\n events: PendingEvent[]\n messages: PendingMessage[]\n blocks: PendingBlock[]\n toolCalls: Map<string, PendingToolCall>\n toolCallsList: PendingToolCall[]\n toolResults: PendingToolResult[]\n artifacts: PendingArtifact[]\n searchDocs: PendingSearchDoc[]\n objects: PendingObjects\n}\n\n/** Raw record row staged from Cursor SQLite meta rows or blobs before insertion. */\ninterface PendingRaw {\n raw_record_id: string\n source_file_id: string\n ordinal: number\n line_no: null\n json_pointer: string | null\n native_id: string | null\n raw_object_id: ObjectId\n decoded_json_object_id: ObjectId | null\n parser_status: 'ok' | 'partial' | 'failed'\n confidence: 'high' | 'medium' | 'low'\n import_batch_id: string\n record_kind: 'sqlite_meta' | 'sqlite_blob'\n}\n\n/** Session row staged from Cursor meta with low-confidence timeline metadata. */\ninterface PendingSession {\n session_id: string\n source_session_id: string\n agent_role: string | null\n agent_nickname: string | null\n title: string | null\n start_ts: string | null\n raw_record_id: string\n model: string | null\n}\n\n/** Event row staged from Cursor JSON message blobs. */\ninterface PendingEvent {\n event_id: string\n ordinal: number\n source_event_id: string | null\n event_type: string\n source_type: string\n subtype: string | null\n timestamp: string | null\n actor: string | null\n payload_object_id: ObjectId | null\n raw_record_id: string\n confidence: 'high' | 'medium' | 'low'\n}\n\n/** Message row staged from Cursor parsed JSON blobs. */\ninterface PendingMessage {\n message_id: string\n event_id: string | null\n source_message_id: string | null\n role: 'system_prompt' | 'developer' | 'user' | 'assistant' | 'tool' | 'operational'\n model: string | null\n timestamp: string | null\n ordinal: number\n raw_record_id: string\n}\n\n/** Content block row staged from Cursor text, reasoning, tool, or unknown content. */\ninterface PendingBlock {\n block_id: string\n message_id: string | null\n event_id: string | null\n ordinal: number\n block_type: string\n text_object_id: ObjectId | null\n text_inline: string | null\n is_error: 0 | 1\n visibility: 'default' | 'hidden_by_default' | 'audit_only'\n raw_record_id: string\n}\n\n/** Tool call row staged from Cursor `tool-call` content items. */\ninterface PendingToolCall {\n tool_call_id: string\n message_id: string | null\n event_id: string | null\n source_call_id: string\n tool_name: string\n canonical_tool_type: string\n args_object_id: ObjectId | null\n command: string | null\n cwd: string | null\n path: string | null\n query: string | null\n timestamp_start: string | null\n status: string | null\n raw_record_id: string\n}\n\n/** Tool result row staged from Cursor `tool-result` content items. */\ninterface PendingToolResult {\n tool_result_id: string\n tool_call_id: string | null\n source_call_id: string\n message_id: string | null\n event_id: string | null\n status: string | null\n is_error: 0 | 1\n output_object_id: ObjectId | null\n preview: string | null\n raw_record_id: string\n}\n\n/** Artifact row staged from Cursor content that references generated outputs. */\ninterface PendingArtifact {\n artifact_id: string\n kind: string\n path: string | null\n logical_path: string | null\n object_id: ObjectId | null\n text_object_id: ObjectId | null\n mime_type: string | null\n size_bytes: number\n created_ts: string | null\n raw_record_id: string\n}\n\n/** Search index row staged from normalized Cursor messages, commands, and paths. */\ninterface PendingSearchDoc {\n doc_id: string\n entity_type: string\n entity_id: string\n timestamp: string | null\n role: string | null\n tool_name: string | null\n canonical_tool_type: string | null\n field_kind: string\n text: string\n}\n\n/** Read one Cursor SQLite store, preserve raw blobs, and normalize parseable chat JSON. */\nasync function compileCursorStore(\n bundle: Bundle,\n batch: ImportBatch,\n store: CursorStoreDb,\n logger?: CompileLogger,\n): Promise<FileCounts> {\n const counts = emptyFileCounts()\n\n const { row: sourceFile, alreadyKnown } = await registerSourceFile(bundle, {\n sourceTool: 'cursor',\n absolutePath: path.resolve(store.filePath),\n fileKind: 'sqlite',\n workspaceHint: store.workspaceId,\n })\n if (alreadyKnown) {\n counts.source_files_skipped = 1\n logger?.debug({ path: store.filePath, source_file_id: sourceFile.source_file_id }, 'cursor store skipped')\n return counts\n }\n counts.source_files_imported = 1\n logger?.debug({ path: store.filePath, source_file_id: sourceFile.source_file_id }, 'cursor store registered')\n\n // Open the Cursor store as an immutable URI so SQLite never touches WAL/SHM\n // files owned by a running Cursor process.\n const cdb = openCursorStoreReadOnly(store.filePath)\n\n try {\n const pending: PendingState = {\n rawRecords: [],\n session: null,\n events: [],\n messages: [],\n blocks: [],\n toolCalls: new Map(),\n toolCallsList: [],\n toolResults: [],\n artifacts: [],\n searchDocs: [],\n objects: createPendingObjects(),\n }\n\n // ---- meta: hex-encoded JSON ----\n const metaRow = cdb.prepare<[], { value: string }>(`SELECT value FROM meta WHERE key='0'`).get()\n let meta: CursorMeta = {}\n let metaRawId = ''\n if (metaRow) {\n const metaText = hexToUtf8(metaRow.value)\n try {\n meta = JSON.parse(metaText) as CursorMeta\n } catch {\n meta = {}\n }\n const metaObjId = stageBytes(pending.objects, Buffer.from(metaText, 'utf8'), {\n mimeType: 'application/json',\n encoding: 'utf-8',\n })\n metaRawId = makeRawRecordId(sourceFile.source_file_id, 0, metaObjId)\n pending.rawRecords.push({\n raw_record_id: metaRawId,\n source_file_id: sourceFile.source_file_id,\n ordinal: 0,\n line_no: null,\n json_pointer: 'meta/0',\n native_id: meta.agentId ?? store.agentId,\n raw_object_id: metaObjId,\n decoded_json_object_id: metaObjId,\n parser_status: 'ok',\n confidence: 'high',\n import_batch_id: batch.batch_id,\n record_kind: 'sqlite_meta',\n })\n }\n\n const sourceSessionId = meta.agentId ?? store.agentId\n const sessionPk = makeSessionId('cursor', sourceSessionId)\n const startTs = meta.createdAt ? new Date(meta.createdAt).toISOString() : null\n pending.session = {\n session_id: sessionPk,\n source_session_id: sourceSessionId,\n agent_role: meta.mode ?? null,\n agent_nickname: meta.name ?? null,\n title: meta.name ?? null,\n start_ts: startTs,\n raw_record_id: metaRawId || makeRawRecordId(sourceFile.source_file_id, 0, 'blake3:none'),\n model: meta.lastUsedModel ?? null,\n }\n\n // ---- blobs ----\n const blobs = cdb.prepare<[], { id: string; data: Buffer }>(`SELECT id, data FROM blobs ORDER BY rowid`).all()\n\n let messageOrdinal = 0\n for (let i = 0; i < blobs.length; i++) {\n const blob = blobs[i]\n if (!blob) continue\n const ordinal = i + 1\n const blobObjectId = stageBytes(pending.objects, blob.data)\n const blobRawId = makeRawRecordId(sourceFile.source_file_id, ordinal, blobObjectId)\n\n // Try to parse JSON. Many blobs are protobuf state and won't parse.\n let parsed: CursorBlobJson | null = null\n const firstByte = blob.data[0]\n const looksJson = firstByte === 0x7b /* '{' */ || firstByte === 0x5b /* '[' */\n if (looksJson) {\n try {\n parsed = JSON.parse(blob.data.toString('utf8')) as CursorBlobJson\n } catch {\n parsed = null\n }\n }\n\n pending.rawRecords.push({\n raw_record_id: blobRawId,\n source_file_id: sourceFile.source_file_id,\n ordinal,\n line_no: null,\n json_pointer: `blobs/${blob.id}`,\n native_id: blob.id,\n raw_object_id: blobObjectId,\n decoded_json_object_id: parsed != null ? stageJson(pending.objects, parsed) : null,\n parser_status: parsed != null ? 'ok' : looksJson ? 'failed' : 'partial',\n confidence: 'low', // timeline order from blob list isn't canonical\n import_batch_id: batch.batch_id,\n record_kind: 'sqlite_blob',\n })\n\n if (!parsed || typeof parsed.role !== 'string') continue\n\n // Normalize JSON blobs that look like chat messages.\n const role = mapRole(parsed.role)\n const messageId = makeMessageId(sessionPk, messageOrdinal++, parsed.id ?? blob.id)\n const eventId = makeEventId(sessionPk, ordinal, 'message')\n\n pending.events.push({\n event_id: eventId,\n ordinal,\n source_event_id: blob.id,\n event_type: 'message',\n source_type: `cursor.${parsed.role}`,\n subtype: null,\n timestamp: null,\n actor: parsed.role,\n payload_object_id: pending.rawRecords[pending.rawRecords.length - 1]?.decoded_json_object_id ?? null,\n raw_record_id: blobRawId,\n confidence: 'low',\n })\n\n pending.messages.push({\n message_id: messageId,\n event_id: eventId,\n source_message_id: parsed.id ?? blob.id,\n role,\n model: role === 'assistant' ? (meta.lastUsedModel ?? null) : null,\n timestamp: null,\n ordinal: messageOrdinal,\n raw_record_id: blobRawId,\n })\n\n const content = parsed.content\n if (typeof content === 'string') {\n await pushTextBlock(bundle, pending, messageId, 0, 'text', content, blobRawId)\n } else if (Array.isArray(content)) {\n for (let bi = 0; bi < content.length; bi++) {\n const item = content[bi]\n if (!item) continue\n await processContentItem(bundle, sessionPk, messageId, eventId, bi, item, blobRawId, pending)\n }\n }\n }\n\n reconcileUnfinishedToolCalls(pending)\n buildSearchDocs(pending)\n\n // Persist staged CAS objects (FS + objects rows) before the domain\n // transaction. better-sqlite3 transactions are sync.\n await flushPendingObjects(bundle, pending.objects)\n\n transactional(bundle.db, () => {\n flushPending(bundle, pending)\n })\n\n counts.raw_records = pending.rawRecords.length\n counts.sessions = 1\n counts.events = pending.events.length\n counts.messages = pending.messages.length\n counts.content_blocks = pending.blocks.length\n counts.tool_calls = pending.toolCallsList.length\n counts.tool_results = pending.toolResults.length\n counts.artifacts = pending.artifacts.length\n logger?.debug({ path: store.filePath, source_file_id: sourceFile.source_file_id, counts }, 'cursor store imported')\n return counts\n } finally {\n cdb.close()\n }\n}\n\n/** Decode Cursor meta values, which are stored as hex-encoded UTF-8 JSON. */\nfunction hexToUtf8(hex: string): string {\n return Buffer.from(hex, 'hex').toString('utf8')\n}\n\n/** Map Cursor chat roles into prosa's normalized message role vocabulary. */\nfunction mapRole(role: string): PendingMessage['role'] {\n switch (role) {\n case 'user':\n return 'user'\n case 'assistant':\n return 'assistant'\n case 'tool':\n return 'tool'\n case 'system':\n // In Cursor's chat blobs, role=system is actually the system prompt\n // (unlike Claude Code's `type:\"system\"` event_log usage).\n return 'system_prompt'\n default:\n return 'operational'\n }\n}\n\n/** Stage a Cursor text-like content block, storing long bodies in CAS. */\nasync function pushTextBlock(\n bundle: Bundle,\n pending: PendingState,\n messageId: string,\n ordinal: number,\n blockType: string,\n text: string,\n rawRecordId: string,\n visibility: 'default' | 'hidden_by_default' | 'audit_only' = 'default',\n): Promise<void> {\n if (!text) return\n const overflow = text.length > PREVIEW_MAX ? stageText(pending.objects, text) : null\n pending.blocks.push({\n block_id: blockId(messageId, ordinal),\n message_id: messageId,\n event_id: null,\n ordinal,\n block_type: blockType,\n text_object_id: overflow,\n text_inline: text.slice(0, PREVIEW_MAX),\n is_error: 0,\n visibility,\n raw_record_id: rawRecordId,\n })\n}\n\n/** Normalize one Cursor content item into blocks, tool calls, tool results, or audit rows. */\nasync function processContentItem(\n bundle: Bundle,\n sessionId: string,\n messageId: string,\n eventId: string,\n ordinal: number,\n item: CursorContentItem,\n rawRecordId: string,\n pending: PendingState,\n): Promise<void> {\n const t = item.type\n if (t === 'text') {\n await pushTextBlock(bundle, pending, messageId, ordinal, 'text', item.text ?? '', rawRecordId)\n return\n }\n if (t === 'reasoning') {\n await pushTextBlock(\n bundle,\n pending,\n messageId,\n ordinal,\n 'thinking',\n item.text ?? '',\n rawRecordId,\n 'hidden_by_default',\n )\n return\n }\n if (t === 'redacted-reasoning') {\n pending.blocks.push({\n block_id: blockId(messageId, ordinal),\n message_id: messageId,\n event_id: null,\n ordinal,\n block_type: 'thinking',\n text_object_id: null,\n text_inline: '[redacted]',\n is_error: 0,\n visibility: 'audit_only',\n raw_record_id: rawRecordId,\n })\n return\n }\n if (t === 'tool-call') {\n const sourceCallId = item.toolCallId ?? `${ordinal}`\n const toolName = item.toolName ?? 'unknown'\n const argsObjectId = item.args != null ? stageJson(pending.objects, item.args) : null\n const tcId = makeToolCallId(sessionId, sourceCallId)\n\n pending.blocks.push({\n block_id: blockId(messageId, ordinal),\n message_id: messageId,\n event_id: null,\n ordinal,\n block_type: 'tool_use',\n text_object_id: null,\n text_inline: null,\n is_error: 0,\n visibility: 'default',\n raw_record_id: rawRecordId,\n })\n\n const call: PendingToolCall = {\n tool_call_id: tcId,\n message_id: messageId,\n event_id: eventId,\n source_call_id: sourceCallId,\n tool_name: toolName,\n canonical_tool_type: canonicalToolType(toolName),\n args_object_id: argsObjectId,\n command:\n typeof (item.args as { command?: unknown })?.command === 'string'\n ? (item.args as { command: string }).command\n : null,\n cwd: null,\n path:\n typeof (item.args as { file_path?: unknown })?.file_path === 'string'\n ? (item.args as { file_path: string }).file_path\n : typeof (item.args as { path?: unknown })?.path === 'string'\n ? (item.args as { path: string }).path\n : null,\n query: null,\n timestamp_start: null,\n status: 'started',\n raw_record_id: rawRecordId,\n }\n pending.toolCalls.set(sourceCallId, call)\n pending.toolCallsList.push(call)\n return\n }\n if (t === 'tool-result') {\n const sourceCallId = item.toolCallId ?? `${ordinal}`\n const text = stringifyOrNull(item.result) ?? ''\n const overflow = text.length > PREVIEW_MAX ? stageText(pending.objects, text) : null\n const outputObjectId = text ? (overflow ?? stageText(pending.objects, text)) : null\n const isError = readIsError(item) ? 1 : 0\n\n pending.blocks.push({\n block_id: blockId(messageId, ordinal),\n message_id: messageId,\n event_id: null,\n ordinal,\n block_type: 'tool_result',\n text_object_id: overflow,\n text_inline: text.slice(0, PREVIEW_MAX),\n is_error: isError,\n visibility: 'default',\n raw_record_id: rawRecordId,\n })\n\n const matched = pending.toolCalls.get(sourceCallId)\n pending.toolResults.push({\n tool_result_id: makeToolResultId(sessionId, sourceCallId),\n tool_call_id: matched?.tool_call_id ?? null,\n source_call_id: sourceCallId,\n message_id: messageId,\n event_id: eventId,\n status: normalizeToolCallStatus('cursor', isError ? 'error' : matched ? 'success' : null),\n is_error: isError,\n output_object_id: outputObjectId,\n preview: text.slice(0, PREVIEW_MAX) || null,\n raw_record_id: rawRecordId,\n })\n if (matched) matched.status = isError ? 'error' : 'success'\n return\n }\n\n // Unknown content type — keep as audit-only block.\n pending.blocks.push({\n block_id: blockId(messageId, ordinal),\n message_id: messageId,\n event_id: null,\n ordinal,\n block_type: t ?? 'unknown',\n text_object_id: null,\n text_inline: stringifyOrNull(item)?.slice(0, PREVIEW_MAX) ?? null,\n is_error: 0,\n visibility: 'audit_only',\n raw_record_id: rawRecordId,\n })\n}\n\nfunction reconcileUnfinishedToolCalls(pending: PendingState): void {\n for (const call of pending.toolCallsList) {\n if (call.status === 'started') {\n call.status = 'unknown'\n }\n }\n}\n\nfunction openCursorStoreReadOnly(filePath: string): Database.Database {\n try {\n return new Database(`file:${filePath}?mode=ro&immutable=1`, {\n fileMustExist: true,\n })\n } catch {\n return new Database(filePath, { readonly: true, fileMustExist: true })\n }\n}\n\n/** Recover Cursor's high-level tool error flag from experimental content metadata. */\nfunction readIsError(item: CursorContentItem): boolean {\n // Cursor stores isError under providerOptions.cursor.highLevelToolCallResult.\n const exp = item.experimental_content as { isError?: boolean } | undefined\n if (exp && typeof exp.isError === 'boolean') return exp.isError\n return false\n}\n\n/** Collapse Cursor tool names into broad search/filter tool categories. */\nfunction canonicalToolType(toolName: string): string {\n const lower = toolName.toLowerCase()\n if (lower.startsWith('mcp__')) return 'mcp'\n if (lower === 'shell' || lower === 'run_terminal_cmd' || lower === 'bash') return 'shell'\n if (lower === 'read' || lower === 'readfile' || lower === 'read_file') return 'read_file'\n if (lower === 'write' || lower === 'writefile' || lower === 'write_file') return 'write_file'\n if (lower === 'strreplace' || lower === 'str_replace' || lower === 'edit' || lower === 'search_replace') {\n return 'edit_file'\n }\n if (lower === 'grep' || lower === 'glob' || lower === 'codebase_search' || lower === 'glob_file_search') {\n return 'search_file'\n }\n if (lower === 'websearch') return 'web_search'\n if (lower === 'applypatch' || lower === 'apply_patch') return 'patch'\n return 'other'\n}\n\n/** Convert arbitrary recovered payload values into compact text previews when possible. */\nfunction stringifyOrNull(value: unknown): string | null {\n if (value == null) return null\n if (typeof value === 'string') return value\n try {\n return JSON.stringify(value)\n } catch {\n return null\n }\n}\n\n/** Build searchable Cursor documents while excluding hidden and audit-only blocks. */\nfunction buildSearchDocs(pending: PendingState): void {\n const sessionId = pending.session?.session_id ?? null\n if (!sessionId) return\n const blocksByMsg = new Map<string, PendingBlock[]>()\n for (const b of pending.blocks) {\n if (!b.message_id) continue\n if (b.visibility === 'hidden_by_default' || b.visibility === 'audit_only') continue\n if (!b.text_inline) continue\n const list = blocksByMsg.get(b.message_id) ?? []\n list.push(b)\n blocksByMsg.set(b.message_id, list)\n }\n for (const m of pending.messages) {\n const text = (blocksByMsg.get(m.message_id) ?? [])\n .map((b) => b.text_inline ?? '')\n .join('\\n')\n .trim()\n if (!text) continue\n pending.searchDocs.push({\n doc_id: `msg:${m.message_id}`,\n entity_type: 'message',\n entity_id: m.message_id,\n timestamp: m.timestamp,\n role: m.role,\n tool_name: null,\n canonical_tool_type: null,\n field_kind: m.role === 'user' ? 'user_prompt' : m.role === 'tool' ? 'tool_result' : 'assistant_text',\n text,\n })\n }\n for (const tc of pending.toolCallsList) {\n if (tc.command) {\n pending.searchDocs.push({\n doc_id: `tc:cmd:${tc.tool_call_id}`,\n entity_type: 'tool_call',\n entity_id: tc.tool_call_id,\n timestamp: tc.timestamp_start,\n role: null,\n tool_name: tc.tool_name,\n canonical_tool_type: tc.canonical_tool_type,\n field_kind: 'command',\n text: tc.command,\n })\n }\n if (tc.path) {\n pending.searchDocs.push({\n doc_id: `tc:path:${tc.tool_call_id}`,\n entity_type: 'tool_call',\n entity_id: tc.tool_call_id,\n timestamp: tc.timestamp_start,\n role: null,\n tool_name: tc.tool_name,\n canonical_tool_type: tc.canonical_tool_type,\n field_kind: 'file_path',\n text: tc.path,\n })\n }\n }\n}\n\n/** Insert staged Cursor rows in foreign-key order after CAS objects are already durable. */\nfunction flushPending(bundle: Bundle, pending: PendingState): void {\n if (!pending.session) return\n\n const insertRaw = prepare(\n bundle.db,\n `INSERT OR IGNORE INTO raw_records (\n raw_record_id, source_file_id, source_tool, record_kind, ordinal,\n line_no, json_pointer, native_id, raw_object_id, decoded_json_object_id,\n parser_status, confidence, import_batch_id\n ) VALUES (?, ?, 'cursor', ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,\n )\n for (const r of pending.rawRecords) {\n insertRaw.run(\n r.raw_record_id,\n r.source_file_id,\n r.record_kind,\n r.ordinal,\n r.line_no,\n r.json_pointer,\n r.native_id,\n r.raw_object_id,\n r.decoded_json_object_id,\n r.parser_status,\n r.confidence,\n r.import_batch_id,\n )\n }\n\n prepare(\n bundle.db,\n `INSERT OR REPLACE INTO sessions (\n session_id, source_tool, source_session_id, project_id, parent_session_id,\n is_subagent, agent_role, agent_nickname, title, summary,\n start_ts, end_ts, cwd_initial, git_branch_initial,\n model_first, model_last, status, timeline_confidence, raw_record_id\n ) VALUES (?, 'cursor', ?, NULL, NULL, 0, ?, ?, ?, NULL, ?, NULL, NULL, NULL, ?, ?, NULL, 'low', ?)`,\n ).run(\n pending.session.session_id,\n pending.session.source_session_id,\n pending.session.agent_role,\n pending.session.agent_nickname,\n pending.session.title,\n pending.session.start_ts,\n pending.session.model,\n pending.session.model,\n pending.session.raw_record_id,\n )\n\n const insertEvent = prepare(\n bundle.db,\n `INSERT OR REPLACE INTO events (\n event_id, session_id, turn_id, source_event_id, event_type, source_type,\n subtype, timestamp, ordinal, actor, payload_object_id, raw_record_id,\n confidence, is_derived\n ) VALUES (?, ?, NULL, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 0)`,\n )\n for (const e of pending.events) {\n insertEvent.run(\n e.event_id,\n pending.session.session_id,\n e.source_event_id,\n e.event_type,\n e.source_type,\n e.subtype,\n e.timestamp,\n e.ordinal,\n e.actor,\n e.payload_object_id,\n e.raw_record_id,\n e.confidence,\n )\n }\n\n const insertMsg = prepare(\n bundle.db,\n `INSERT OR REPLACE INTO messages (\n message_id, session_id, turn_id, event_id, source_message_id, role,\n author_name, model, timestamp, ordinal, parent_message_id, request_id,\n status, raw_record_id\n ) VALUES (?, ?, NULL, ?, ?, ?, NULL, ?, ?, ?, NULL, NULL, NULL, ?)`,\n )\n for (const m of pending.messages) {\n insertMsg.run(\n m.message_id,\n pending.session.session_id,\n m.event_id,\n m.source_message_id,\n m.role,\n m.model,\n m.timestamp,\n m.ordinal,\n m.raw_record_id,\n )\n }\n\n const insertBlock = prepare(\n bundle.db,\n `INSERT OR REPLACE INTO content_blocks (\n block_id, message_id, event_id, session_id, ordinal, block_type,\n text_object_id, text_inline, mime_type, token_count, is_error,\n is_redacted, visibility, raw_record_id\n ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, NULL, NULL, ?, 0, ?, ?)`,\n )\n for (const b of pending.blocks) {\n insertBlock.run(\n b.block_id,\n b.message_id,\n b.event_id,\n pending.session.session_id,\n b.ordinal,\n b.block_type,\n b.text_object_id,\n b.text_inline,\n b.is_error,\n b.visibility,\n b.raw_record_id,\n )\n }\n\n const insertCall = prepare(\n bundle.db,\n `INSERT OR REPLACE INTO tool_calls (\n tool_call_id, session_id, turn_id, message_id, event_id,\n source_call_id, tool_name, canonical_tool_type, args_object_id,\n command, cwd, path, query, timestamp_start, timestamp_end, status,\n raw_record_id\n ) VALUES (?, ?, NULL, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, NULL, ?, ?)`,\n )\n for (const c of pending.toolCallsList) {\n insertCall.run(\n c.tool_call_id,\n pending.session.session_id,\n c.message_id,\n c.event_id,\n c.source_call_id,\n c.tool_name,\n c.canonical_tool_type,\n c.args_object_id,\n c.command,\n c.cwd,\n c.path,\n c.query,\n c.timestamp_start,\n c.status,\n c.raw_record_id,\n )\n }\n\n const insertResult = prepare(\n bundle.db,\n `INSERT OR REPLACE INTO tool_results (\n tool_result_id, tool_call_id, session_id, message_id, event_id,\n source_call_id, status, is_error, exit_code, duration_ms,\n stdout_object_id, stderr_object_id, output_object_id, preview, raw_record_id\n ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, NULL, NULL, NULL, NULL, ?, ?, ?)`,\n )\n for (const r of pending.toolResults) {\n insertResult.run(\n r.tool_result_id,\n r.tool_call_id,\n pending.session.session_id,\n r.message_id,\n r.event_id,\n r.source_call_id,\n r.status,\n r.is_error,\n r.output_object_id,\n r.preview,\n r.raw_record_id,\n )\n }\n\n const insertSearch = prepare(\n bundle.db,\n `INSERT OR REPLACE INTO search_docs (\n doc_id, entity_type, entity_id, session_id, project_id, timestamp,\n role, tool_name, canonical_tool_type, field_kind, text\n ) VALUES (?, ?, ?, ?, NULL, ?, ?, ?, ?, ?, ?)`,\n )\n for (const d of pending.searchDocs) {\n insertSearch.run(\n d.doc_id,\n d.entity_type,\n d.entity_id,\n pending.session.session_id,\n d.timestamp,\n d.role,\n d.tool_name,\n d.canonical_tool_type,\n d.field_kind,\n d.text,\n )\n }\n\n void artifactId // referenced by other importers; kept here for symmetry\n}\n","import { readdir } from 'node:fs/promises'\nimport path from 'node:path'\n\n/** Discovered Cursor `store.db` with workspace and agent ids derived from the path. */\nexport interface CursorStoreDb {\n filePath: string\n workspaceId: string\n agentId: string\n}\n\n/**\n * Walk `<root>` (typically `~/.cursor/chats`) and yield every `store.db`\n * SQLite file together with the workspace/agent ids derived from the path.\n * Layout: `<root>/<workspace>/<agent>/store.db`.\n */\nexport async function* discoverCursorStores(root: string): AsyncGenerator<CursorStoreDb, void, void> {\n const workspaces = await readdirSafe(root)\n for (const ws of workspaces) {\n if (!ws.isDirectory()) continue\n const wsPath = path.join(root, ws.name)\n const agents = await readdirSafe(wsPath)\n for (const ag of agents) {\n if (!ag.isDirectory()) continue\n const dbPath = path.join(wsPath, ag.name, 'store.db')\n const dbEntries = await readdirSafe(path.join(wsPath, ag.name))\n const hasStoreDb = dbEntries.some((e) => e.isFile() && e.name === 'store.db')\n if (!hasStoreDb) continue\n yield {\n filePath: dbPath,\n workspaceId: ws.name,\n agentId: ag.name,\n }\n }\n }\n}\n\n/** Read optional Cursor workspace directories as empty when they are missing. */\nasync function readdirSafe(dir: string): Promise<import('node:fs').Dirent[]> {\n try {\n return await readdir(dir, { withFileTypes: true })\n } catch {\n return []\n }\n}\n","import { readFile } from 'node:fs/promises'\nimport path from 'node:path'\nimport type { Bundle } from '../../core/bundle.js'\nimport { sha256Hex } from '../../core/cas/hash.js'\nimport {\n type ObjectId,\n type PendingObjects,\n createPendingObjects,\n flushPendingObjects,\n stageBytes,\n stageJson,\n stageText,\n} from '../../core/cas/index.js'\nimport { prepare, transactional } from '../../core/db.js'\nimport {\n artifactId,\n blockId,\n eventId as makeEventId,\n messageId as makeMessageId,\n projectId as makeProjectId,\n rawRecordId as makeRawRecordId,\n sessionId as makeSessionId,\n toolCallId as makeToolCallId,\n toolResultId as makeToolResultId,\n} from '../../core/domain/ids.js'\nimport { normalizeToolCallStatus } from '../../core/domain/status.js'\nimport { getErrorMessage } from '../../core/errors.js'\nimport {\n type ImportBatch,\n type ImportCounts,\n emptyCounts,\n finishBatch,\n recordError,\n startBatch,\n} from '../../core/ingest/batch.js'\nimport { registerSourceFile } from '../../core/ingest/idempotency.js'\nimport type { CompileLogger, CompileOptions } from '../compile-options.js'\nimport { type GeminiChatFile, discoverGeminiChats } from './discover.js'\nimport type { GeminiContentItem, GeminiMessage, GeminiSessionFile, GeminiToolCall, GeminiToolResult } from './types.js'\n\n/** Result returned after a Gemini compile batch finishes or records a failed batch. */\nexport interface CompileResult {\n /** Import batch created for this Gemini run. */\n batch: ImportBatch\n /** Final counts accumulated while importing Gemini files. */\n counts: ImportCounts\n}\n\n/** Maximum inline text retained in normalized rows before full content moves to CAS. */\nconst PREVIEW_MAX = 4_000\n\n/** Compile Gemini CLI chat snapshot files under `root` into the bundle. */\nexport async function compileGemini(\n bundle: Bundle,\n root: string,\n options: CompileOptions = {},\n): Promise<CompileResult> {\n const logger = options.logger\n const batch = startBatch(bundle, 'gemini', [root])\n const counts = emptyCounts()\n logger?.info({ batch_id: batch.batch_id, root }, 'gemini batch started')\n try {\n for await (const file of discoverGeminiChats(root)) {\n counts.source_files_seen++\n logger?.debug(\n {\n path: file.filePath,\n project_dir: file.projectDir,\n project_root: file.projectRoot,\n },\n 'gemini source file discovered',\n )\n try {\n const fc = await compileGeminiFile(bundle, batch, file, logger)\n addCounts(counts, fc)\n } catch (error) {\n counts.errors++\n logger?.warn(\n {\n err: error,\n path: file.filePath,\n },\n 'gemini source file failed',\n )\n await recordError(bundle, batch.batch_id, {\n kind: 'gemini_file_failed',\n message: getErrorMessage(error),\n payload: { path: file.filePath },\n })\n }\n }\n finishBatch(bundle, batch, counts, 'completed')\n logger?.info({ batch_id: batch.batch_id, counts }, 'gemini batch completed')\n } catch (error) {\n finishBatch(bundle, batch, counts, 'failed')\n logger?.error({ err: error, batch_id: batch.batch_id, counts }, 'gemini batch failed')\n throw error\n }\n return { batch, counts }\n}\n\n/** Per-source-file deltas that are merged into the import batch counts. */\ninterface FileCounts {\n source_files_imported: number\n source_files_skipped: number\n raw_records: number\n sessions: number\n events: number\n messages: number\n content_blocks: number\n tool_calls: number\n tool_results: number\n artifacts: number\n edges: number\n errors: number\n}\n\n/** Create zeroed file counters for a Gemini file that may still fail or be skipped. */\nfunction emptyFileCounts(): FileCounts {\n return {\n source_files_imported: 0,\n source_files_skipped: 0,\n raw_records: 0,\n sessions: 0,\n events: 0,\n messages: 0,\n content_blocks: 0,\n tool_calls: 0,\n tool_results: 0,\n artifacts: 0,\n edges: 0,\n errors: 0,\n }\n}\n\n/** Merge a single Gemini file's normalized row counts into batch totals. */\nfunction addCounts(target: ImportCounts, source: FileCounts): void {\n target.source_files_imported += source.source_files_imported\n target.source_files_skipped += source.source_files_skipped\n target.raw_records += source.raw_records\n target.sessions += source.sessions\n target.events += source.events\n target.messages += source.messages\n target.content_blocks += source.content_blocks\n target.tool_calls += source.tool_calls\n target.tool_results += source.tool_results\n target.artifacts += source.artifacts\n target.edges += source.edges\n target.errors += source.errors\n}\n\n/** All normalized Gemini rows staged for one source file before FK-ordered flush. */\ninterface PendingState {\n rawRecords: PendingRawRecord[]\n session: PendingSession | null\n events: PendingEvent[]\n messages: PendingMessage[]\n blocks: PendingBlock[]\n toolCallsList: PendingToolCall[]\n toolResults: PendingToolResult[]\n artifacts: PendingArtifact[]\n searchDocs: PendingSearchDoc[]\n project: PendingProject | null\n objects: PendingObjects\n}\n\n/** Raw record row staged from a Gemini JSON pointer before database insertion. */\ninterface PendingRawRecord {\n raw_record_id: string\n source_file_id: string\n ordinal: number | null\n line_no: number | null\n json_pointer: string | null\n native_id: string | null\n raw_object_id: ObjectId\n decoded_json_object_id: ObjectId | null\n parser_status: 'ok' | 'partial' | 'failed'\n confidence: 'high' | 'medium' | 'low'\n import_batch_id: string\n record_kind: 'json_pointer' | 'jsonl_line'\n}\n\n/** Session row staged from the Gemini snapshot root object. */\ninterface PendingSession {\n session_id: string\n source_session_id: string\n start_ts: string | null\n end_ts: string | null\n cwd_initial: string | null\n title: string | null\n raw_record_id: string | null\n}\n\n/** Project row staged from Gemini `.project_root` metadata when available. */\ninterface PendingProject {\n project_id: string\n canonical_path: string | null\n source_project_id: string\n}\n\n/** Event row staged from Gemini messages and operational snapshot entries. */\ninterface PendingEvent {\n event_id: string\n ordinal: number\n source_event_id: string | null\n event_type: string\n source_type: string\n subtype: string | null\n timestamp: string | null\n actor: string | null\n payload_object_id: ObjectId | null\n raw_record_id: string\n confidence: 'high' | 'medium' | 'low'\n}\n\n/** Message row staged from Gemini user and model entries. */\ninterface PendingMessage {\n message_id: string\n event_id: string | null\n source_message_id: string | null\n role: 'system_prompt' | 'developer' | 'user' | 'assistant' | 'tool' | 'operational'\n model: string | null\n timestamp: string | null\n ordinal: number\n raw_record_id: string\n}\n\n/** Content block row staged from Gemini content strings, content arrays, and thoughts. */\ninterface PendingBlock {\n block_id: string\n message_id: string | null\n event_id: string | null\n ordinal: number\n block_type: string\n text_object_id: ObjectId | null\n text_inline: string | null\n visibility: 'default' | 'hidden_by_default' | 'audit_only'\n raw_record_id: string\n}\n\n/** Tool call row staged from Gemini message-level tool calls. */\ninterface PendingToolCall {\n tool_call_id: string\n message_id: string | null\n event_id: string | null\n source_call_id: string\n tool_name: string\n canonical_tool_type: string\n args_object_id: ObjectId | null\n command: string | null\n cwd: string | null\n path: string | null\n query: string | null\n timestamp_start: string | null\n status: string | null\n raw_record_id: string\n}\n\n/** Tool result row staged from Gemini tool-call result arrays. */\ninterface PendingToolResult {\n tool_result_id: string\n tool_call_id: string\n source_call_id: string\n message_id: string | null\n event_id: string | null\n status: string | null\n is_error: 0 | 1\n output_object_id: ObjectId | null\n preview: string | null\n raw_record_id: string\n}\n\n/** Artifact row staged from Gemini result display diffs. */\ninterface PendingArtifact {\n artifact_id: string\n kind: string\n path: string | null\n logical_path: string | null\n object_id: ObjectId | null\n text_object_id: ObjectId | null\n mime_type: string | null\n size_bytes: number\n created_ts: string | null\n raw_record_id: string\n}\n\n/** Search index row staged from normalized Gemini messages, commands, paths, and previews. */\ninterface PendingSearchDoc {\n doc_id: string\n entity_type: string\n entity_id: string\n timestamp: string | null\n role: string | null\n tool_name: string | null\n canonical_tool_type: string | null\n field_kind: string\n text: string\n}\n\n/** Parse one Gemini chat snapshot, stage CAS objects, and flush normalized rows. */\nasync function compileGeminiFile(\n bundle: Bundle,\n batch: ImportBatch,\n file: GeminiChatFile,\n logger?: CompileLogger,\n): Promise<FileCounts> {\n const counts = emptyFileCounts()\n\n const { row: sourceFile, alreadyKnown } = await registerSourceFile(bundle, {\n sourceTool: 'gemini',\n absolutePath: path.resolve(file.filePath),\n fileKind: 'json',\n workspaceHint: file.projectDir,\n })\n if (alreadyKnown) {\n counts.source_files_skipped = 1\n logger?.debug({ path: file.filePath, source_file_id: sourceFile.source_file_id }, 'gemini source file skipped')\n return counts\n }\n counts.source_files_imported = 1\n logger?.debug({ path: file.filePath, source_file_id: sourceFile.source_file_id }, 'gemini source file registered')\n\n const text = await readFile(file.filePath, 'utf8')\n const parsed = JSON.parse(text) as GeminiSessionFile\n const objects = createPendingObjects()\n const fileObjectId = stageBytes(objects, Buffer.from(text, 'utf8'), {\n mimeType: 'application/json',\n encoding: 'utf-8',\n })\n\n const rootRawRecordId = makeRawRecordId(sourceFile.source_file_id, 0, fileObjectId)\n const pending: PendingState = {\n rawRecords: [\n {\n raw_record_id: rootRawRecordId,\n source_file_id: sourceFile.source_file_id,\n ordinal: 0,\n line_no: null,\n json_pointer: '',\n native_id: parsed.sessionId ?? null,\n raw_object_id: fileObjectId,\n decoded_json_object_id: fileObjectId,\n parser_status: 'ok',\n confidence: 'high',\n import_batch_id: batch.batch_id,\n record_kind: 'json_pointer',\n },\n ],\n session: null,\n events: [],\n messages: [],\n blocks: [],\n toolCallsList: [],\n toolResults: [],\n artifacts: [],\n searchDocs: [],\n project: null,\n objects,\n }\n\n const sourceSid = parsed.sessionId ?? path.basename(file.filePath, '.json')\n const sessionPk = makeSessionId('gemini', sourceSid)\n\n const existingSession = prepare<[string], { session_id: string }>(\n bundle.db,\n `SELECT session_id FROM sessions WHERE session_id = ? LIMIT 1`,\n ).get(sessionPk)\n if (existingSession) {\n logger?.warn(\n {\n path: file.filePath,\n session_id: sessionPk,\n source_session_id: sourceSid,\n },\n 'gemini duplicate snapshot detected; later rows will be dropped by INSERT OR IGNORE',\n )\n await recordError(bundle, batch.batch_id, {\n sourceFileId: sourceFile.source_file_id,\n kind: 'gemini_duplicate_snapshot',\n message: `duplicate Gemini snapshot for sessionId ${sourceSid}; first-sorted snapshot wins, rows from this file are dropped at the normalized layer`,\n payload: {\n path: file.filePath,\n session_id: sessionPk,\n source_session_id: sourceSid,\n },\n })\n }\n\n const projectKey = parsed.projectHash ?? file.projectDir\n if (projectKey) {\n pending.project = {\n project_id: makeProjectId('gemini', projectKey),\n canonical_path: file.projectRoot,\n source_project_id: projectKey,\n }\n }\n\n const start = parsed.startTime ?? null\n const end = parsed.lastUpdated ?? null\n pending.session = {\n session_id: sessionPk,\n source_session_id: sourceSid,\n start_ts: start,\n end_ts: end,\n cwd_initial: file.projectRoot,\n title: parsed.summary ?? null,\n raw_record_id: rootRawRecordId,\n }\n\n const messages = Array.isArray(parsed.messages) ? parsed.messages : []\n\n for (let i = 0; i < messages.length; i++) {\n const msg = messages[i]\n if (!msg) continue\n processMessage(sessionPk, sourceFile.source_file_id, i, msg, batch.batch_id, pending)\n }\n\n buildSearchDocs(pending)\n\n // Persist staged CAS objects (FS + objects rows) before the domain\n // transaction. better-sqlite3 transactions are sync.\n await flushPendingObjects(bundle, pending.objects)\n\n transactional(bundle.db, () => {\n flushPending(bundle, pending)\n })\n\n counts.raw_records = pending.rawRecords.length\n counts.sessions = pending.session ? 1 : 0\n counts.events = pending.events.length\n counts.messages = pending.messages.length\n counts.content_blocks = pending.blocks.length\n counts.tool_calls = pending.toolCallsList.length\n counts.tool_results = pending.toolResults.length\n counts.artifacts = pending.artifacts.length\n logger?.debug(\n { path: file.filePath, source_file_id: sourceFile.source_file_id, counts },\n 'gemini source file imported',\n )\n return counts\n}\n\n/** Normalize one Gemini message snapshot entry into events, messages, blocks, and tools. */\nfunction processMessage(\n sessionId: string,\n sourceFileId: string,\n index: number,\n msg: GeminiMessage,\n batchId: string,\n pending: PendingState,\n): void {\n const ordinal = index + 1\n const ts = msg.timestamp ?? null\n\n const payloadId = stageJson(pending.objects, msg)\n // Use the JSON pointer as a stable per-record locator inside the file.\n const pointer = `/messages/${index}`\n const rawRecordId = makeRawRecordId(sourceFileId, ordinal, payloadId)\n\n pending.rawRecords.push({\n raw_record_id: rawRecordId,\n source_file_id: sourceFileId,\n ordinal,\n line_no: null,\n json_pointer: pointer,\n native_id: msg.id ?? null,\n raw_object_id: payloadId,\n decoded_json_object_id: payloadId,\n parser_status: 'ok',\n confidence: 'high',\n import_batch_id: batchId,\n record_kind: 'json_pointer',\n })\n\n const kind = msg.type ?? 'unknown'\n\n if (kind === 'user' || kind === 'gemini') {\n const role: PendingMessage['role'] = kind === 'user' ? 'user' : 'assistant'\n const messageId = makeMessageId(sessionId, ordinal, msg.id ?? null)\n const eventId = makeEventId(sessionId, ordinal, 'message')\n\n pending.events.push({\n event_id: eventId,\n ordinal,\n source_event_id: msg.id ?? null,\n event_type: 'message',\n source_type: kind,\n subtype: null,\n timestamp: ts,\n actor: role,\n payload_object_id: payloadId,\n raw_record_id: rawRecordId,\n confidence: 'high',\n })\n\n pending.messages.push({\n message_id: messageId,\n event_id: eventId,\n source_message_id: msg.id ?? null,\n role,\n model: role === 'assistant' ? (msg.model ?? null) : null,\n timestamp: ts,\n ordinal,\n raw_record_id: rawRecordId,\n })\n\n // Content blocks.\n const content = msg.content\n if (typeof content === 'string') {\n pushTextBlock(pending, messageId, 0, 'text', content, rawRecordId)\n } else if (Array.isArray(content)) {\n for (let i = 0; i < content.length; i++) {\n const item = content[i] as GeminiContentItem | undefined\n if (!item) continue\n const t = item.text ?? ''\n pushTextBlock(pending, messageId, i, item.type ?? 'text', t, rawRecordId)\n }\n }\n\n // Thoughts → audit-only blocks (don't pollute search by default).\n const thoughts = Array.isArray(msg.thoughts) ? msg.thoughts : []\n for (let i = 0; i < thoughts.length; i++) {\n const th = thoughts[i]\n if (!th) continue\n const text = [th.subject, th.description].filter(Boolean).join('\\n\\n')\n pushTextBlock(pending, messageId, 100 + i, 'thinking', text, rawRecordId, 'hidden_by_default')\n }\n\n // Tool calls.\n const toolCalls = Array.isArray(msg.toolCalls) ? msg.toolCalls : []\n for (let i = 0; i < toolCalls.length; i++) {\n const tc = toolCalls[i]\n if (!tc) continue\n processToolCall(sessionId, messageId, eventId, i, tc, rawRecordId, pending)\n }\n return\n }\n\n if (kind === 'info' || kind === 'error') {\n const eventId = makeEventId(sessionId, ordinal, kind)\n pending.events.push({\n event_id: eventId,\n ordinal,\n source_event_id: msg.id ?? null,\n event_type: kind === 'error' ? 'error' : 'system_operational',\n source_type: kind,\n subtype: null,\n timestamp: ts,\n actor: 'system',\n payload_object_id: payloadId,\n raw_record_id: rawRecordId,\n confidence: 'high',\n })\n return\n }\n\n // Unknown type — keep as operational event.\n pending.events.push({\n event_id: makeEventId(sessionId, ordinal, `unknown.${kind}`),\n ordinal,\n source_event_id: msg.id ?? null,\n event_type: 'system_operational',\n source_type: kind,\n subtype: null,\n timestamp: ts,\n actor: 'system',\n payload_object_id: payloadId,\n raw_record_id: rawRecordId,\n confidence: 'high',\n })\n}\n\n/** Stage a Gemini text-like content block, storing long bodies in CAS. */\nfunction pushTextBlock(\n pending: PendingState,\n messageId: string,\n blockOrdinal: number,\n blockType: string,\n text: string,\n rawRecordId: string,\n visibility: 'default' | 'hidden_by_default' | 'audit_only' = 'default',\n): void {\n if (!text) return\n const overflowId = text.length > PREVIEW_MAX ? stageText(pending.objects, text) : null\n pending.blocks.push({\n block_id: blockId(messageId, blockOrdinal),\n message_id: messageId,\n event_id: null,\n ordinal: blockOrdinal,\n block_type: blockType,\n text_object_id: overflowId,\n text_inline: text.slice(0, PREVIEW_MAX),\n visibility,\n raw_record_id: rawRecordId,\n })\n}\n\n/** Normalize a Gemini tool call and its embedded result/display metadata. */\nfunction processToolCall(\n sessionId: string,\n messageId: string,\n eventId: string,\n index: number,\n tc: GeminiToolCall,\n rawRecordId: string,\n pending: PendingState,\n): void {\n const sourceCallId = tc.id ?? `${messageId}:${index}`\n const toolName = tc.name ?? 'unknown'\n const toolCallId = makeToolCallId(sessionId, sourceCallId)\n const argsObjectId = tc.args ? stageJson(pending.objects, tc.args) : null\n\n pending.toolCallsList.push({\n tool_call_id: toolCallId,\n message_id: messageId,\n event_id: eventId,\n source_call_id: sourceCallId,\n tool_name: toolName,\n canonical_tool_type: canonicalToolType(toolName),\n args_object_id: argsObjectId,\n command: typeof tc.args?.command === 'string' ? (tc.args.command as string) : null,\n cwd: typeof tc.args?.dir_path === 'string' ? (tc.args.dir_path as string) : null,\n path:\n typeof tc.args?.file_path === 'string'\n ? (tc.args.file_path as string)\n : typeof tc.args?.path === 'string'\n ? (tc.args.path as string)\n : null,\n query: typeof tc.args?.query === 'string' ? (tc.args.query as string) : null,\n timestamp_start: tc.timestamp ?? null,\n status: normalizeToolCallStatus('gemini', tc.status),\n raw_record_id: rawRecordId,\n })\n\n const isError = tc.status === 'error' ? 1 : 0\n const resultText = renderToolResultText(tc.result)\n const overflowId = resultText.length > PREVIEW_MAX ? stageText(pending.objects, resultText) : null\n\n pending.toolResults.push({\n tool_result_id: makeToolResultId(sessionId, sourceCallId),\n tool_call_id: toolCallId,\n source_call_id: sourceCallId,\n message_id: messageId,\n event_id: eventId,\n status: normalizeToolCallStatus('gemini', tc.status),\n is_error: isError,\n output_object_id: overflowId,\n preview: resultText.slice(0, PREVIEW_MAX) || null,\n raw_record_id: rawRecordId,\n })\n\n // resultDisplay diffs become artifacts.\n if (tc.resultDisplay && typeof tc.resultDisplay === 'object') {\n const rd = tc.resultDisplay\n if (rd.fileDiff || rd.filePath) {\n const diffText = rd.fileDiff ?? ''\n const diffId = diffText ? stageText(pending.objects, diffText, { mimeType: 'text/x-diff' }) : null\n pending.artifacts.push({\n artifact_id: artifactId(sessionId, 'gemini', `${toolCallId}:diff`),\n kind: 'diff',\n path: rd.filePath ?? null,\n logical_path: rd.fileName ?? rd.filePath ?? null,\n object_id: diffId,\n text_object_id: diffId,\n mime_type: 'text/x-diff',\n size_bytes: diffText.length,\n created_ts: tc.timestamp ?? null,\n raw_record_id: rawRecordId,\n })\n }\n pushResultDisplayFileArtifact(pending, sessionId, toolCallId, rawRecordId, tc, rd, 'newContent', 'new')\n pushResultDisplayFileArtifact(pending, sessionId, toolCallId, rawRecordId, tc, rd, 'originalContent', 'original')\n }\n}\n\nfunction pushResultDisplayFileArtifact(\n pending: PendingState,\n sessionId: string,\n toolCallId: string,\n rawRecordId: string,\n tc: GeminiToolCall,\n rd: Exclude<GeminiToolCall['resultDisplay'], string | undefined>,\n field: 'newContent' | 'originalContent',\n suffix: 'new' | 'original',\n): void {\n const text = rd[field]\n if (typeof text !== 'string' || text.length === 0) return\n const objectId = stageText(pending.objects, text)\n pending.artifacts.push({\n artifact_id: artifactId(sessionId, 'gemini', `${toolCallId}:${suffix}`),\n kind: 'file',\n path: rd.filePath ?? null,\n logical_path: rd.fileName ?? rd.filePath ?? null,\n object_id: objectId,\n text_object_id: objectId,\n mime_type: null,\n size_bytes: Buffer.byteLength(text, 'utf8'),\n created_ts: tc.timestamp ?? null,\n raw_record_id: rawRecordId,\n })\n}\n\n/** Render Gemini's heterogeneous tool result array into the preview text used for search. */\nfunction renderToolResultText(result: GeminiToolResult[] | undefined): string {\n if (!Array.isArray(result)) return ''\n const parts: string[] = []\n for (const r of result) {\n if (r.text) {\n parts.push(r.text)\n continue\n }\n if (r.functionResponse?.response) {\n const rr = r.functionResponse.response\n if (rr.error != null) parts.push(typeof rr.error === 'string' ? rr.error : JSON.stringify(rr.error))\n else if (rr.output != null) parts.push(typeof rr.output === 'string' ? rr.output : JSON.stringify(rr.output))\n }\n }\n return parts.join('\\n')\n}\n\n/** Collapse Gemini tool names into broad search/filter tool categories. */\nfunction canonicalToolType(toolName: string): string {\n switch (toolName) {\n case 'run_shell_command':\n case 'shell':\n case 'shell_command':\n return 'shell'\n case 'read_file':\n case 'read_many_files':\n return 'read_file'\n case 'write_file':\n return 'write_file'\n case 'replace':\n case 'search_replace':\n return 'edit_file'\n case 'list_directory':\n case 'glob':\n case 'grep_search':\n case 'search_file_content':\n return 'search_file'\n case 'google_web_search':\n return 'web_search'\n case 'codebase_investigator':\n return 'other'\n default:\n return toolName.startsWith('mcp__') ? 'mcp' : 'other'\n }\n}\n\n/** Build searchable Gemini documents while excluding hidden thought blocks. */\nfunction buildSearchDocs(pending: PendingState): void {\n const sessionId = pending.session?.session_id ?? null\n if (!sessionId) return\n const blocksByMsg = new Map<string, PendingBlock[]>()\n for (const b of pending.blocks) {\n if (!b.message_id) continue\n if (b.visibility === 'hidden_by_default') continue\n const list = blocksByMsg.get(b.message_id) ?? []\n list.push(b)\n blocksByMsg.set(b.message_id, list)\n }\n for (const m of pending.messages) {\n const text = (blocksByMsg.get(m.message_id) ?? [])\n .map((b) => b.text_inline ?? '')\n .join('\\n')\n .trim()\n if (!text) continue\n pending.searchDocs.push({\n doc_id: `msg:${m.message_id}`,\n entity_type: 'message',\n entity_id: m.message_id,\n timestamp: m.timestamp,\n role: m.role,\n tool_name: null,\n canonical_tool_type: null,\n field_kind: m.role === 'user' ? 'user_prompt' : 'assistant_text',\n text,\n })\n }\n for (const tc of pending.toolCallsList) {\n if (tc.command) {\n pending.searchDocs.push({\n doc_id: `tc:cmd:${tc.tool_call_id}`,\n entity_type: 'tool_call',\n entity_id: tc.tool_call_id,\n timestamp: tc.timestamp_start,\n role: null,\n tool_name: tc.tool_name,\n canonical_tool_type: tc.canonical_tool_type,\n field_kind: 'command',\n text: tc.command,\n })\n }\n if (tc.path) {\n pending.searchDocs.push({\n doc_id: `tc:path:${tc.tool_call_id}`,\n entity_type: 'tool_call',\n entity_id: tc.tool_call_id,\n timestamp: tc.timestamp_start,\n role: null,\n tool_name: tc.tool_name,\n canonical_tool_type: tc.canonical_tool_type,\n field_kind: 'file_path',\n text: tc.path,\n })\n }\n }\n for (const tr of pending.toolResults) {\n if (!tr.preview) continue\n pending.searchDocs.push({\n doc_id: `tr:preview:${tr.tool_result_id}`,\n entity_type: 'tool_result',\n entity_id: tr.tool_result_id,\n timestamp: null,\n role: null,\n tool_name: null,\n canonical_tool_type: null,\n field_kind: tr.is_error ? 'error' : 'tool_result',\n text: tr.preview,\n })\n }\n}\n\n/** Insert staged Gemini rows in foreign-key order after CAS objects are already durable. */\nfunction flushPending(bundle: Bundle, pending: PendingState): void {\n if (!pending.session) return\n\n const insertRaw = prepare(\n bundle.db,\n `INSERT OR IGNORE INTO raw_records (\n raw_record_id, source_file_id, source_tool, record_kind, ordinal,\n line_no, json_pointer, native_id, raw_object_id, decoded_json_object_id,\n parser_status, confidence, import_batch_id\n ) VALUES (?, ?, 'gemini', ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,\n )\n for (const r of pending.rawRecords) {\n insertRaw.run(\n r.raw_record_id,\n r.source_file_id,\n r.record_kind,\n r.ordinal,\n r.line_no,\n r.json_pointer,\n r.native_id,\n r.raw_object_id,\n r.decoded_json_object_id,\n r.parser_status,\n r.confidence,\n r.import_batch_id,\n )\n }\n\n if (pending.project) {\n prepare(\n bundle.db,\n `INSERT OR IGNORE INTO projects (\n project_id, canonical_path, path_hash, source_tool, source_project_id,\n display_name, created_at\n ) VALUES (?, ?, ?, 'gemini', ?, NULL, ?)`,\n ).run(\n pending.project.project_id,\n pending.project.canonical_path,\n pending.project.canonical_path ? sha256Hex(pending.project.canonical_path).slice(0, 32) : null,\n pending.project.source_project_id,\n new Date().toISOString(),\n )\n }\n\n prepare(\n bundle.db,\n `INSERT OR IGNORE INTO sessions (\n session_id, source_tool, source_session_id, project_id, parent_session_id,\n is_subagent, agent_role, agent_nickname, title, summary,\n start_ts, end_ts, cwd_initial, git_branch_initial,\n model_first, model_last, status, timeline_confidence, raw_record_id\n ) VALUES (?, 'gemini', ?, ?, NULL, 0, NULL, NULL, ?, NULL, ?, ?, ?, NULL, NULL, NULL, 'completed', 'high', ?)`,\n ).run(\n pending.session.session_id,\n pending.session.source_session_id,\n pending.project?.project_id ?? null,\n pending.session.title,\n pending.session.start_ts,\n pending.session.end_ts,\n pending.session.cwd_initial,\n pending.session.raw_record_id,\n )\n\n const insertEvent = prepare(\n bundle.db,\n `INSERT OR IGNORE INTO events (\n event_id, session_id, turn_id, source_event_id, event_type, source_type,\n subtype, timestamp, ordinal, actor, payload_object_id, raw_record_id,\n confidence, is_derived\n ) VALUES (?, ?, NULL, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 0)`,\n )\n for (const e of pending.events) {\n insertEvent.run(\n e.event_id,\n pending.session.session_id,\n e.source_event_id,\n e.event_type,\n e.source_type,\n e.subtype,\n e.timestamp,\n e.ordinal,\n e.actor,\n e.payload_object_id,\n e.raw_record_id,\n e.confidence,\n )\n }\n\n const insertMsg = prepare(\n bundle.db,\n `INSERT OR IGNORE INTO messages (\n message_id, session_id, turn_id, event_id, source_message_id, role,\n author_name, model, timestamp, ordinal, parent_message_id, request_id,\n status, raw_record_id\n ) VALUES (?, ?, NULL, ?, ?, ?, NULL, ?, ?, ?, NULL, NULL, NULL, ?)`,\n )\n for (const m of pending.messages) {\n insertMsg.run(\n m.message_id,\n pending.session.session_id,\n m.event_id,\n m.source_message_id,\n m.role,\n m.model,\n m.timestamp,\n m.ordinal,\n m.raw_record_id,\n )\n }\n\n const insertBlock = prepare(\n bundle.db,\n `INSERT OR IGNORE INTO content_blocks (\n block_id, message_id, event_id, session_id, ordinal, block_type,\n text_object_id, text_inline, mime_type, token_count, is_error,\n is_redacted, visibility, raw_record_id\n ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, NULL, NULL, 0, 0, ?, ?)`,\n )\n for (const b of pending.blocks) {\n insertBlock.run(\n b.block_id,\n b.message_id,\n b.event_id,\n pending.session.session_id,\n b.ordinal,\n b.block_type,\n b.text_object_id,\n b.text_inline,\n b.visibility,\n b.raw_record_id,\n )\n }\n\n const insertCall = prepare(\n bundle.db,\n `INSERT OR IGNORE INTO tool_calls (\n tool_call_id, session_id, turn_id, message_id, event_id,\n source_call_id, tool_name, canonical_tool_type, args_object_id,\n command, cwd, path, query, timestamp_start, timestamp_end, status,\n raw_record_id\n ) VALUES (?, ?, NULL, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, NULL, ?, ?)`,\n )\n for (const c of pending.toolCallsList) {\n insertCall.run(\n c.tool_call_id,\n pending.session.session_id,\n c.message_id,\n c.event_id,\n c.source_call_id,\n c.tool_name,\n c.canonical_tool_type,\n c.args_object_id,\n c.command,\n c.cwd,\n c.path,\n c.query,\n c.timestamp_start,\n c.status,\n c.raw_record_id,\n )\n }\n\n const insertResult = prepare(\n bundle.db,\n `INSERT OR IGNORE INTO tool_results (\n tool_result_id, tool_call_id, session_id, message_id, event_id,\n source_call_id, status, is_error, exit_code, duration_ms,\n stdout_object_id, stderr_object_id, output_object_id, preview, raw_record_id\n ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, NULL, NULL, NULL, NULL, ?, ?, ?)`,\n )\n for (const r of pending.toolResults) {\n insertResult.run(\n r.tool_result_id,\n r.tool_call_id,\n pending.session.session_id,\n r.message_id,\n r.event_id,\n r.source_call_id,\n r.status,\n r.is_error,\n r.output_object_id,\n r.preview,\n r.raw_record_id,\n )\n }\n\n const insertArtifact = prepare(\n bundle.db,\n `INSERT OR IGNORE INTO artifacts (\n artifact_id, session_id, project_id, source_tool, kind, path,\n logical_path, object_id, text_object_id, mime_type, size_bytes,\n created_ts, raw_record_id\n ) VALUES (?, ?, ?, 'gemini', ?, ?, ?, ?, ?, ?, ?, ?, ?)`,\n )\n for (const a of pending.artifacts) {\n insertArtifact.run(\n a.artifact_id,\n pending.session.session_id,\n pending.project?.project_id ?? null,\n a.kind,\n a.path,\n a.logical_path,\n a.object_id,\n a.text_object_id,\n a.mime_type,\n a.size_bytes,\n a.created_ts,\n a.raw_record_id,\n )\n }\n\n const insertSearch = prepare(\n bundle.db,\n `INSERT OR IGNORE INTO search_docs (\n doc_id, entity_type, entity_id, session_id, project_id, timestamp,\n role, tool_name, canonical_tool_type, field_kind, text\n ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,\n )\n for (const d of pending.searchDocs) {\n insertSearch.run(\n d.doc_id,\n d.entity_type,\n d.entity_id,\n pending.session.session_id,\n pending.project?.project_id ?? null,\n d.timestamp,\n d.role,\n d.tool_name,\n d.canonical_tool_type,\n d.field_kind,\n d.text,\n )\n }\n}\n","import { readFile, readdir } from 'node:fs/promises'\nimport path from 'node:path'\n\n/** Discovered Gemini chat snapshot with project directory context. */\nexport interface GeminiChatFile {\n filePath: string\n /** Either a 64-hex hash or a project slug. */\n projectDir: string\n /** Resolved from `.project_root` if it exists in the project dir. */\n projectRoot: string | null\n}\n\n/**\n * Walk `<root>` (typically `~/.gemini/tmp`) and yield every\n * `chats/session-*.json` file together with the resolved `.project_root`.\n * Ignores `logs.json` and the `bin/` directory.\n */\nexport async function* discoverGeminiChats(root: string): AsyncGenerator<GeminiChatFile, void, void> {\n const entries = await readdirSafe(root)\n for (const entry of entries.sort((a, b) => a.name.localeCompare(b.name))) {\n if (!entry.isDirectory()) continue\n if (entry.name === 'bin') continue\n const projectRoot = await readProjectRoot(path.join(root, entry.name))\n const chatsDir = path.join(root, entry.name, 'chats')\n const chatEntries = await readdirSafe(chatsDir)\n for (const c of chatEntries.sort((a, b) => a.name.localeCompare(b.name))) {\n if (!c.isFile()) continue\n if (!c.name.startsWith('session-') || !c.name.endsWith('.json')) continue\n yield {\n filePath: path.join(chatsDir, c.name),\n projectDir: entry.name,\n projectRoot,\n }\n }\n }\n}\n\n/** Resolve Gemini's optional `.project_root` companion file. */\nasync function readProjectRoot(dir: string): Promise<string | null> {\n try {\n const text = await readFile(path.join(dir, '.project_root'), 'utf8')\n return text.replace(/\\n+$/, '').trim() || null\n } catch {\n return null\n }\n}\n\n/** Read optional Gemini directories as empty when they are missing. */\nasync function readdirSafe(dir: string): Promise<import('node:fs').Dirent[]> {\n try {\n return await readdir(dir, { withFileTypes: true })\n } catch {\n return []\n }\n}\n","import { readFile } from 'node:fs/promises'\nimport path from 'node:path'\nimport Database from 'better-sqlite3'\nimport type { Bundle } from '../../core/bundle.js'\nimport {\n type ObjectId,\n type PendingObjects,\n createPendingObjects,\n flushPendingObjects,\n stageJson,\n stageText,\n} from '../../core/cas/index.js'\nimport { prepare, transactional } from '../../core/db.js'\nimport {\n blockId,\n eventId as makeEventId,\n messageId as makeMessageId,\n projectId as makeProjectId,\n rawRecordId as makeRawRecordId,\n sessionId as makeSessionId,\n toolCallId as makeToolCallId,\n toolResultId as makeToolResultId,\n} from '../../core/domain/ids.js'\nimport { normalizeSessionStatus, normalizeToolCallStatus } from '../../core/domain/status.js'\nimport type { MessageRole, ToolCallStatus } from '../../core/domain/types.js'\nimport { getErrorMessage } from '../../core/errors.js'\nimport {\n type ImportBatch,\n type ImportCounts,\n emptyCounts,\n finishBatch,\n recordError,\n startBatch,\n} from '../../core/ingest/batch.js'\nimport { registerSourceFile } from '../../core/ingest/idempotency.js'\nimport type { CompileOptions } from '../compile-options.js'\nimport { discoverHermesSources } from './discover.js'\nimport type { HermesMessageRow, HermesSessionJson, HermesSessionRow, HermesTranscriptMessage } from './types.js'\n\n/** Result returned after a Hermes compile batch finishes or records a failed batch. */\nexport interface CompileResult {\n /** Import batch created for this Hermes run. */\n batch: ImportBatch\n /** Final counts accumulated while importing Hermes files. */\n counts: ImportCounts\n}\n\nconst PREVIEW_MAX = 4_000\n// Hidden reasoning blocks are ordered after default content blocks.\nconst HIDDEN_BLOCK_ORDINAL_BASE = 100\n\ninterface SourceFileRef {\n sourceFileId: string\n path: string\n kind: 'sqlite' | 'json' | 'jsonl' | 'index'\n imported: boolean\n}\n\ninterface SessionCandidate {\n source: 'sqlite' | 'json' | 'jsonl'\n session: NormalizedSession\n messages: NormalizedMessage[]\n sourceFile: SourceFileRef\n}\n\ninterface NormalizedSession {\n sourceSessionId: string\n source: string | null\n model: string | null\n systemPrompt: string | null\n parentSessionId: string | null\n startTs: string | null\n endTs: string | null\n status: string | null\n title: string | null\n rawPayload: unknown\n}\n\ninterface NormalizedMessage {\n sourceMessageId: string\n ordinal: number\n role: string\n content: unknown\n timestamp: string | null\n model: string | null\n toolCallId: string | null\n toolCalls: unknown\n toolName: string | null\n tokenCount: number | null\n finishReason: string | null\n reasoning: unknown\n reasoningContent: unknown\n reasoningDetails: unknown\n codexReasoningItems: unknown\n codexMessageItems: unknown\n rawPayload: unknown\n lineNo: number | null\n}\n\ninterface PendingState {\n rawRecords: PendingRawRecord[]\n projects: PendingProject[]\n sessions: PendingSession[]\n events: PendingEvent[]\n messages: PendingMessage[]\n blocks: PendingBlock[]\n toolCalls: PendingToolCall[]\n toolResults: PendingToolResult[]\n searchDocs: PendingSearchDoc[]\n objects: PendingObjects\n}\n\ninterface PendingRawRecord {\n raw_record_id: string\n source_file_id: string\n ordinal: number | null\n line_no: number | null\n json_pointer: string | null\n native_id: string | null\n raw_object_id: ObjectId\n decoded_json_object_id: ObjectId | null\n parser_status: 'ok' | 'partial' | 'failed'\n confidence: 'high' | 'medium' | 'low'\n import_batch_id: string\n record_kind: 'sqlite_row' | 'json_pointer' | 'jsonl_line'\n}\n\ninterface PendingProject {\n project_id: string\n source_project_id: string\n display_name: string | null\n}\n\ninterface PendingSession {\n session_id: string\n source_session_id: string\n project_id: string | null\n parent_session_id: string | null\n is_subagent: 0 | 1\n title: string | null\n start_ts: string | null\n end_ts: string | null\n model_first: string | null\n model_last: string | null\n status: string | null\n raw_record_id: string\n}\n\ninterface PendingEvent {\n event_id: string\n session_id: string\n ordinal: number\n source_event_id: string | null\n event_type: string\n source_type: string\n subtype: string | null\n timestamp: string | null\n actor: string | null\n payload_object_id: ObjectId | null\n raw_record_id: string\n confidence: 'high' | 'medium' | 'low'\n}\n\ninterface PendingMessage {\n message_id: string\n session_id: string\n event_id: string | null\n source_message_id: string | null\n role: MessageRole\n model: string | null\n timestamp: string | null\n ordinal: number\n status: string | null\n raw_record_id: string\n}\n\ninterface PendingBlock {\n block_id: string\n session_id: string\n message_id: string | null\n event_id: string | null\n ordinal: number\n block_type: string\n text_object_id: ObjectId | null\n text_inline: string | null\n token_count: number | null\n visibility: 'default' | 'hidden_by_default' | 'audit_only'\n raw_record_id: string\n}\n\ninterface PendingToolCall {\n tool_call_id: string\n session_id: string\n message_id: string | null\n event_id: string | null\n source_call_id: string\n tool_name: string\n canonical_tool_type: string\n args_object_id: ObjectId | null\n command: string | null\n path: string | null\n query: string | null\n timestamp_start: string | null\n status: ToolCallStatus | null\n raw_record_id: string\n}\n\ninterface PendingToolResult {\n tool_result_id: string\n tool_call_id: string\n session_id: string\n message_id: string | null\n event_id: string | null\n source_call_id: string\n status: ToolCallStatus | null\n is_error: 0 | 1\n output_object_id: ObjectId | null\n preview: string | null\n raw_record_id: string\n}\n\ninterface PendingSearchDoc {\n doc_id: string\n entity_type: string\n entity_id: string\n session_id: string\n project_id: string | null\n timestamp: string | null\n role: string | null\n tool_name: string | null\n canonical_tool_type: string | null\n field_kind: string\n text: string\n}\n\n/** Compile Hermes session storage under `root` into the bundle. */\nexport async function compileHermes(\n bundle: Bundle,\n root: string,\n options: CompileOptions = {},\n): Promise<CompileResult> {\n const logger = options.logger\n const batch = startBatch(bundle, 'hermes', [root])\n const counts = emptyCounts()\n logger?.info({ batch_id: batch.batch_id, root }, 'hermes batch started')\n\n try {\n const sources = await discoverHermesSources(root)\n const registered: SourceFileRef[] = []\n const candidates: SessionCandidate[] = []\n if (\n !sources.stateDbPath &&\n !sources.indexPath &&\n sources.jsonlFiles.length === 0 &&\n sources.jsonFiles.length === 0\n ) {\n logger?.warn({ root: sources.sessionsDir }, 'no hermes sources discovered')\n }\n\n if (sources.stateDbPath) {\n counts.source_files_seen++\n const sourceFile = await registerHermesSourceFile(bundle, sources.stateDbPath, 'sqlite', counts)\n registered.push(sourceFile)\n if (sourceFile.imported) {\n logger?.debug(\n { path: sources.stateDbPath, source_file_id: sourceFile.sourceFileId },\n 'hermes state db discovered',\n )\n try {\n candidates.push(...readSqliteCandidates(sources.stateDbPath, sourceFile))\n } catch (error) {\n await recordHermesSourceError(bundle, batch, counts, sources.stateDbPath, error, 'hermes_sqlite_failed')\n logger?.warn({ err: error, path: sources.stateDbPath }, 'hermes state db failed')\n }\n } else {\n logger?.debug(\n { path: sources.stateDbPath, source_file_id: sourceFile.sourceFileId },\n 'hermes state db unchanged, skipping read',\n )\n }\n }\n\n for (const filePath of sources.jsonlFiles) {\n counts.source_files_seen++\n const sourceFile = await registerHermesSourceFile(bundle, filePath, 'jsonl', counts)\n registered.push(sourceFile)\n if (!sourceFile.imported) {\n logger?.debug(\n { path: filePath, source_file_id: sourceFile.sourceFileId },\n 'hermes jsonl unchanged, skipping read',\n )\n continue\n }\n logger?.debug({ path: filePath, source_file_id: sourceFile.sourceFileId }, 'hermes jsonl transcript discovered')\n try {\n candidates.push(await readJsonlCandidate(filePath, sourceFile))\n } catch (error) {\n await recordHermesSourceError(bundle, batch, counts, filePath, error, 'hermes_file_failed')\n logger?.warn({ err: error, path: filePath }, 'hermes jsonl transcript failed')\n }\n }\n\n for (const filePath of sources.jsonFiles) {\n counts.source_files_seen++\n const sourceFile = await registerHermesSourceFile(bundle, filePath, 'json', counts)\n registered.push(sourceFile)\n if (!sourceFile.imported) {\n logger?.debug(\n { path: filePath, source_file_id: sourceFile.sourceFileId },\n 'hermes json unchanged, skipping read',\n )\n continue\n }\n logger?.debug({ path: filePath, source_file_id: sourceFile.sourceFileId }, 'hermes json snapshot discovered')\n try {\n candidates.push(await readJsonCandidate(filePath, sourceFile))\n } catch (error) {\n await recordHermesSourceError(bundle, batch, counts, filePath, error, 'hermes_file_failed')\n logger?.warn({ err: error, path: filePath }, 'hermes json snapshot failed')\n }\n }\n\n if (sources.indexPath) {\n counts.source_files_seen++\n const sourceFile = await registerHermesSourceFile(bundle, sources.indexPath, 'index', counts)\n registered.push(sourceFile)\n logger?.debug(\n { path: sources.indexPath, source_file_id: sourceFile.sourceFileId },\n 'hermes sessions index discovered',\n )\n }\n\n const selection = selectCandidates(candidates)\n const pending = buildPending(\n batch,\n selection.selected,\n selection.rejected,\n registered.filter((sourceFile) => sourceFile.imported),\n )\n await flushPendingObjects(bundle, pending.objects)\n transactional(bundle.db, () => flushPending(bundle, pending))\n\n counts.raw_records = pending.rawRecords.length\n counts.sessions = pending.sessions.length\n counts.events = pending.events.length\n counts.messages = pending.messages.length\n counts.content_blocks = pending.blocks.length\n counts.tool_calls = pending.toolCalls.length\n counts.tool_results = pending.toolResults.length\n counts.artifacts = 0\n counts.edges = 0\n\n finishBatch(bundle, batch, counts, 'completed')\n logger?.info({ batch_id: batch.batch_id, counts }, 'hermes batch completed')\n } catch (error) {\n finishBatch(bundle, batch, counts, 'failed')\n counts.errors++\n logger?.error({ err: error, batch_id: batch.batch_id, counts }, 'hermes batch failed')\n await recordError(bundle, batch.batch_id, {\n kind: 'hermes_batch_failed',\n message: getErrorMessage(error),\n payload: { root },\n })\n throw error\n }\n\n return { batch, counts }\n}\n\nasync function registerHermesSourceFile(\n bundle: Bundle,\n absolutePath: string,\n fileKind: SourceFileRef['kind'],\n counts: ImportCounts,\n): Promise<SourceFileRef> {\n const { row, alreadyKnown } = await registerSourceFile(bundle, {\n sourceTool: 'hermes',\n absolutePath: path.resolve(absolutePath),\n fileKind,\n })\n if (alreadyKnown) counts.source_files_skipped++\n else counts.source_files_imported++\n return {\n sourceFileId: row.source_file_id,\n path: row.path,\n kind: fileKind,\n imported: !alreadyKnown,\n }\n}\n\nasync function recordHermesSourceError(\n bundle: Bundle,\n batch: ImportBatch,\n counts: ImportCounts,\n filePath: string,\n error: unknown,\n kind: 'hermes_file_failed' | 'hermes_sqlite_failed',\n): Promise<void> {\n counts.errors++\n await recordError(bundle, batch.batch_id, {\n kind,\n message: getErrorMessage(error),\n payload: { path: filePath },\n })\n}\n\nfunction readSqliteCandidates(dbPath: string, sourceFile: SourceFileRef): SessionCandidate[] {\n const db = new Database(dbPath, { readonly: true, fileMustExist: true })\n try {\n const sessions = db\n .prepare<[], HermesSessionRow>(\n `SELECT id, source, user_id, model, model_config, system_prompt, parent_session_id,\n started_at, ended_at, end_reason, message_count, tool_call_count, title\n FROM sessions ORDER BY started_at, id`,\n )\n .all()\n const messagesBySession = new Map<string, HermesMessageRow[]>()\n const messages = db\n .prepare<[], HermesMessageRow>(\n `SELECT id, session_id, role, content, tool_call_id, tool_calls, tool_name,\n timestamp, token_count, finish_reason, reasoning, reasoning_content,\n reasoning_details, codex_reasoning_items, codex_message_items\n FROM messages ORDER BY session_id, id`,\n )\n .all()\n for (const message of messages) {\n const list = messagesBySession.get(message.session_id) ?? []\n list.push(message)\n messagesBySession.set(message.session_id, list)\n }\n\n return sessions.map((session) => ({\n source: 'sqlite',\n sourceFile,\n session: {\n sourceSessionId: session.id,\n source: session.source,\n model: session.model,\n systemPrompt: session.system_prompt,\n parentSessionId: session.parent_session_id,\n startTs: unixToIso(session.started_at),\n endTs: unixToIso(session.ended_at),\n status: session.end_reason,\n title: session.title,\n rawPayload: session,\n },\n messages: (messagesBySession.get(session.id) ?? []).map((message, index) =>\n normalizeSqliteMessage(message, index + 1),\n ),\n }))\n } finally {\n db.close()\n }\n}\n\nfunction normalizeSqliteMessage(message: HermesMessageRow, ordinal: number): NormalizedMessage {\n return {\n sourceMessageId: String(message.id),\n ordinal,\n role: message.role,\n content: decodeMaybeJson(message.content),\n timestamp: unixToIso(message.timestamp),\n model: null,\n toolCallId: message.tool_call_id,\n toolCalls: decodeMaybeJson(message.tool_calls),\n toolName: message.tool_name,\n tokenCount: message.token_count,\n finishReason: message.finish_reason,\n reasoning: decodeMaybeJson(message.reasoning),\n reasoningContent: decodeMaybeJson(message.reasoning_content),\n reasoningDetails: decodeMaybeJson(message.reasoning_details),\n codexReasoningItems: decodeMaybeJson(message.codex_reasoning_items),\n codexMessageItems: decodeMaybeJson(message.codex_message_items),\n rawPayload: message,\n lineNo: null,\n }\n}\n\nasync function readJsonlCandidate(filePath: string, sourceFile: SourceFileRef): Promise<SessionCandidate> {\n const text = await readFile(filePath, 'utf8')\n const messages: NormalizedMessage[] = []\n const sourceSessionId = path.basename(filePath, '.jsonl')\n const lines = text.split(/\\r?\\n/)\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i] ?? ''\n if (!line.trim()) continue\n const parsed = JSON.parse(line) as HermesTranscriptMessage\n messages.push(normalizeTranscriptMessage(parsed, messages.length + 1, i + 1))\n }\n return {\n source: 'jsonl',\n sourceFile,\n session: {\n sourceSessionId,\n source: null,\n model: firstString(messages.map((message) => message.model)),\n systemPrompt: null,\n parentSessionId: null,\n startTs: messages[0]?.timestamp ?? null,\n endTs: messages.at(-1)?.timestamp ?? null,\n status: null,\n title: null,\n rawPayload: { session_id: sourceSessionId, path: filePath },\n },\n messages,\n }\n}\n\nasync function readJsonCandidate(filePath: string, sourceFile: SourceFileRef): Promise<SessionCandidate> {\n const text = await readFile(filePath, 'utf8')\n const parsed = JSON.parse(text) as HermesSessionJson\n const sourceSessionId = parsed.session_id ?? path.basename(filePath, '.json').replace(/^session_/, '')\n const messages = (Array.isArray(parsed.messages) ? parsed.messages : []).map((message, index) =>\n normalizeTranscriptMessage(message, index + 1, null),\n )\n return {\n source: 'json',\n sourceFile,\n session: {\n sourceSessionId,\n source: parsed.platform ?? null,\n model: parsed.model ?? null,\n systemPrompt: parsed.system_prompt ?? null,\n parentSessionId: null,\n startTs: coerceTimestamp(parsed.session_start),\n endTs: coerceTimestamp(parsed.last_updated) ?? messages.at(-1)?.timestamp ?? null,\n status: null,\n title: null,\n rawPayload: parsed,\n },\n messages,\n }\n}\n\nfunction normalizeTranscriptMessage(\n message: HermesTranscriptMessage,\n ordinal: number,\n lineNo: number | null,\n): NormalizedMessage {\n return {\n sourceMessageId: String(lineNo ?? ordinal),\n ordinal,\n role: message.role ?? 'unknown',\n content: message.content ?? null,\n timestamp: coerceTimestamp(message.timestamp),\n model: message.model ?? null,\n toolCallId: message.tool_call_id ?? null,\n toolCalls: message.tool_calls ?? null,\n toolName: message.tool_name ?? null,\n tokenCount: message.token_count ?? null,\n finishReason: message.finish_reason ?? null,\n reasoning: message.reasoning ?? null,\n reasoningContent: message.reasoning_content ?? null,\n reasoningDetails: message.reasoning_details ?? null,\n codexReasoningItems: message.codex_reasoning_items ?? null,\n codexMessageItems: message.codex_message_items ?? null,\n rawPayload: message,\n lineNo,\n }\n}\n\nfunction selectCandidates(candidates: SessionCandidate[]): {\n selected: SessionCandidate[]\n rejected: SessionCandidate[]\n} {\n const selected = new Map<string, SessionCandidate>()\n const rejected: SessionCandidate[] = []\n for (const candidate of candidates) {\n const existing = selected.get(candidate.session.sourceSessionId)\n if (!existing) {\n selected.set(candidate.session.sourceSessionId, candidate)\n continue\n }\n if (candidate.messages.length > existing.messages.length) {\n rejected.push(existing)\n selected.set(candidate.session.sourceSessionId, candidate)\n } else {\n rejected.push(candidate)\n }\n }\n return { selected: [...selected.values()], rejected }\n}\n\nfunction buildPending(\n batch: ImportBatch,\n selected: SessionCandidate[],\n rejected: SessionCandidate[],\n importedSources: SourceFileRef[],\n): PendingState {\n const pending: PendingState = {\n rawRecords: [],\n projects: [],\n sessions: [],\n events: [],\n messages: [],\n blocks: [],\n toolCalls: [],\n toolResults: [],\n searchDocs: [],\n objects: createPendingObjects(),\n }\n\n const candidateSourceIds = new Set([...selected, ...rejected].map((candidate) => candidate.sourceFile.sourceFileId))\n for (const sourceFile of importedSources) {\n if (candidateSourceIds.has(sourceFile.sourceFileId)) continue\n const payload = { path: sourceFile.path, kind: sourceFile.kind }\n const objectId = stageJson(pending.objects, payload)\n pending.rawRecords.push({\n raw_record_id: makeRawRecordId(sourceFile.sourceFileId, 0, objectId),\n source_file_id: sourceFile.sourceFileId,\n ordinal: 0,\n line_no: null,\n json_pointer: '',\n native_id: null,\n raw_object_id: objectId,\n decoded_json_object_id: objectId,\n parser_status: 'partial',\n confidence: 'high',\n import_batch_id: batch.batch_id,\n record_kind: sourceFile.kind === 'jsonl' ? 'jsonl_line' : 'json_pointer',\n })\n }\n\n for (const candidate of selected) {\n stageCandidate(batch, candidate, pending)\n }\n for (const candidate of rejected) {\n stageRejectedCandidate(batch, candidate, pending)\n }\n buildSearchDocs(pending)\n return pending\n}\n\nfunction stageRejectedCandidate(batch: ImportBatch, candidate: SessionCandidate, pending: PendingState): void {\n const payloadId = stageJson(pending.objects, candidate.session.rawPayload)\n pending.rawRecords.push({\n raw_record_id: makeRawRecordId(candidate.sourceFile.sourceFileId, 0, payloadId),\n source_file_id: candidate.sourceFile.sourceFileId,\n ordinal: 0,\n line_no: null,\n json_pointer: candidate.source === 'sqlite' ? `$.sessions.${candidate.session.sourceSessionId}` : '$.candidate',\n native_id: candidate.session.sourceSessionId,\n raw_object_id: payloadId,\n decoded_json_object_id: payloadId,\n parser_status: 'partial',\n confidence: 'high',\n import_batch_id: batch.batch_id,\n record_kind: candidate.source === 'sqlite' ? 'sqlite_row' : 'json_pointer',\n })\n}\n\nfunction stageCandidate(batch: ImportBatch, candidate: SessionCandidate, pending: PendingState): void {\n const sessionPk = makeSessionId('hermes', candidate.session.sourceSessionId)\n const sessionPayloadId = stageJson(pending.objects, candidate.session.rawPayload)\n const sessionRawId = makeRawRecordId(candidate.sourceFile.sourceFileId, 0, sessionPayloadId)\n pending.rawRecords.push({\n raw_record_id: sessionRawId,\n source_file_id: candidate.sourceFile.sourceFileId,\n ordinal: 0,\n line_no: null,\n json_pointer: candidate.source === 'sqlite' ? '$.sessions' : '',\n native_id: candidate.session.sourceSessionId,\n raw_object_id: sessionPayloadId,\n decoded_json_object_id: sessionPayloadId,\n parser_status: 'ok',\n confidence: 'high',\n import_batch_id: batch.batch_id,\n record_kind: candidate.source === 'sqlite' ? 'sqlite_row' : 'json_pointer',\n })\n\n const projectId = candidate.session.source ? makeProjectId('hermes', candidate.session.source) : null\n if (candidate.session.source && projectId) {\n pending.projects.push({\n project_id: projectId,\n source_project_id: candidate.session.source,\n display_name: candidate.session.source,\n })\n }\n\n const models = candidate.messages.map((message) => message.model).filter((model): model is string => Boolean(model))\n pending.sessions.push({\n session_id: sessionPk,\n source_session_id: candidate.session.sourceSessionId,\n project_id: projectId,\n parent_session_id: candidate.session.parentSessionId\n ? makeSessionId('hermes', candidate.session.parentSessionId)\n : null,\n is_subagent: candidate.session.parentSessionId ? 1 : 0,\n title: candidate.session.title,\n start_ts: candidate.session.startTs,\n end_ts: candidate.session.endTs,\n model_first: candidate.session.model ?? models[0] ?? null,\n model_last: models.at(-1) ?? candidate.session.model ?? null,\n status: normalizeSessionStatus(candidate.session.status),\n raw_record_id: sessionRawId,\n })\n\n if (candidate.session.systemPrompt) {\n const rawRecordId = sessionRawId\n const messageId = makeMessageId(sessionPk, 0, 'system_prompt')\n pending.messages.push({\n message_id: messageId,\n session_id: sessionPk,\n event_id: null,\n source_message_id: 'system_prompt',\n role: 'system_prompt',\n model: null,\n timestamp: candidate.session.startTs,\n ordinal: 0,\n status: null,\n raw_record_id: rawRecordId,\n })\n pushTextBlock(pending, sessionPk, messageId, null, 0, 'text', candidate.session.systemPrompt, rawRecordId)\n }\n\n const toolCallsBySourceId = new Map<string, PendingToolCall>()\n for (const message of candidate.messages) {\n stageMessage(candidate, sessionPk, message, batch.batch_id, pending, toolCallsBySourceId)\n }\n}\n\nfunction stageMessage(\n candidate: SessionCandidate,\n sessionPk: string,\n message: NormalizedMessage,\n batchId: string,\n pending: PendingState,\n toolCallsBySourceId: Map<string, PendingToolCall>,\n): void {\n const payloadId = stageJson(pending.objects, message.rawPayload)\n const rawRecordId = makeRawRecordId(candidate.sourceFile.sourceFileId, message.ordinal, payloadId)\n pending.rawRecords.push({\n raw_record_id: rawRecordId,\n source_file_id: candidate.sourceFile.sourceFileId,\n ordinal: message.ordinal,\n line_no: message.lineNo,\n json_pointer: candidate.source === 'json' ? `/messages/${message.ordinal - 1}` : null,\n native_id: message.sourceMessageId,\n raw_object_id: payloadId,\n decoded_json_object_id: payloadId,\n parser_status: 'ok',\n confidence: 'high',\n import_batch_id: batchId,\n record_kind:\n candidate.source === 'sqlite' ? 'sqlite_row' : candidate.source === 'jsonl' ? 'jsonl_line' : 'json_pointer',\n })\n\n if (message.role === 'session_meta') {\n pending.events.push({\n event_id: makeEventId(sessionPk, message.ordinal, 'session_meta'),\n session_id: sessionPk,\n ordinal: message.ordinal,\n source_event_id: message.sourceMessageId,\n event_type: 'system_operational',\n source_type: 'session_meta',\n subtype: null,\n timestamp: message.timestamp,\n actor: 'system',\n payload_object_id: payloadId,\n raw_record_id: rawRecordId,\n confidence: 'high',\n })\n return\n }\n\n const role = mapRole(message.role)\n const eventId = makeEventId(sessionPk, message.ordinal, 'message')\n const messageId = makeMessageId(sessionPk, message.ordinal, message.sourceMessageId)\n pending.events.push({\n event_id: eventId,\n session_id: sessionPk,\n ordinal: message.ordinal,\n source_event_id: message.sourceMessageId,\n event_type: 'message',\n source_type: message.role,\n subtype: null,\n timestamp: message.timestamp,\n actor: role,\n payload_object_id: payloadId,\n raw_record_id: rawRecordId,\n confidence: 'high',\n })\n pending.messages.push({\n message_id: messageId,\n session_id: sessionPk,\n event_id: eventId,\n source_message_id: message.sourceMessageId,\n role,\n model: role === 'assistant' ? message.model : null,\n timestamp: message.timestamp,\n ordinal: message.ordinal,\n status: message.finishReason,\n raw_record_id: rawRecordId,\n })\n\n const text = renderContentText(message.content)\n pushTextBlock(pending, sessionPk, messageId, eventId, 0, 'text', text, rawRecordId, 'default', message.tokenCount)\n pushHiddenBlock(pending, sessionPk, messageId, eventId, message, rawRecordId)\n\n for (const [index, call] of parseToolCalls(message.toolCalls).entries()) {\n const sourceCallId = getToolCallSourceId(call, `${messageId}:${index}`)\n const toolName = getToolName(call, message.toolName)\n const args = getToolArgs(call)\n const toolCallId = makeToolCallId(sessionPk, sourceCallId)\n const pendingCall: PendingToolCall = {\n tool_call_id: toolCallId,\n session_id: sessionPk,\n message_id: messageId,\n event_id: eventId,\n source_call_id: sourceCallId,\n tool_name: toolName,\n canonical_tool_type: canonicalToolType(toolName),\n args_object_id: args ? stageJson(pending.objects, args) : null,\n command: stringField(args, 'command'),\n path: stringField(args, 'path') ?? stringField(args, 'file_path'),\n query: stringField(args, 'query'),\n timestamp_start: message.timestamp,\n status: normalizeToolCallStatus('hermes', message.finishReason),\n raw_record_id: rawRecordId,\n }\n toolCallsBySourceId.set(sourceCallId, pendingCall)\n pending.toolCalls.push(pendingCall)\n }\n\n if (role === 'tool' && message.toolCallId) {\n const sourceCallId = message.toolCallId\n let pendingCall = toolCallsBySourceId.get(sourceCallId)\n if (!pendingCall) {\n pendingCall = {\n tool_call_id: makeToolCallId(sessionPk, sourceCallId),\n session_id: sessionPk,\n message_id: null,\n event_id: null,\n source_call_id: sourceCallId,\n tool_name: message.toolName ?? 'unknown',\n canonical_tool_type: canonicalToolType(message.toolName ?? 'unknown'),\n args_object_id: null,\n command: null,\n path: null,\n query: null,\n timestamp_start: message.timestamp,\n status: 'unknown',\n raw_record_id: rawRecordId,\n }\n toolCallsBySourceId.set(sourceCallId, pendingCall)\n pending.toolCalls.push(pendingCall)\n }\n const outputObjectId = text.length > PREVIEW_MAX ? stageText(pending.objects, text) : null\n const status = normalizeToolResultStatus(message, text)\n if (status === 'error' || pendingCall.status === 'unknown' || pendingCall.status == null) {\n pendingCall.status = status\n }\n pending.toolResults.push({\n tool_result_id: makeToolResultId(sessionPk, sourceCallId),\n tool_call_id: pendingCall.tool_call_id,\n session_id: sessionPk,\n message_id: messageId,\n event_id: eventId,\n source_call_id: sourceCallId,\n status,\n is_error: status === 'error' ? 1 : 0,\n output_object_id: outputObjectId,\n preview: text.slice(0, PREVIEW_MAX) || null,\n raw_record_id: rawRecordId,\n })\n }\n}\n\nfunction pushTextBlock(\n pending: PendingState,\n sessionId: string,\n messageId: string | null,\n eventId: string | null,\n ordinal: number,\n blockType: string,\n text: string,\n rawRecordId: string,\n visibility: 'default' | 'hidden_by_default' | 'audit_only' = 'default',\n tokenCount: number | null = null,\n): void {\n if (!text) return\n const objectId = text.length > PREVIEW_MAX ? stageText(pending.objects, text) : null\n pending.blocks.push({\n block_id: blockId(messageId ?? eventId ?? rawRecordId, ordinal),\n session_id: sessionId,\n message_id: messageId,\n event_id: eventId,\n ordinal,\n block_type: blockType,\n text_object_id: objectId,\n text_inline: text.slice(0, PREVIEW_MAX),\n token_count: tokenCount,\n visibility,\n raw_record_id: rawRecordId,\n })\n}\n\nfunction pushHiddenBlock(\n pending: PendingState,\n sessionId: string,\n messageId: string,\n eventId: string,\n message: NormalizedMessage,\n rawRecordId: string,\n): void {\n const hidden = [\n ['reasoning', message.reasoning],\n ['reasoning_content', message.reasoningContent],\n ['reasoning_details', message.reasoningDetails],\n ['codex_reasoning_items', message.codexReasoningItems],\n ['codex_message_items', message.codexMessageItems],\n ] as const\n let offset = HIDDEN_BLOCK_ORDINAL_BASE\n for (const [kind, value] of hidden) {\n const text = renderContentText(value)\n if (!text) continue\n pushTextBlock(pending, sessionId, messageId, eventId, offset++, kind, text, rawRecordId, 'hidden_by_default')\n }\n}\n\nfunction buildSearchDocs(pending: PendingState): void {\n const projectIdBySession = new Map(pending.sessions.map((session) => [session.session_id, session.project_id]))\n for (const message of pending.messages) {\n const text = pending.blocks\n .filter((block) => block.message_id === message.message_id && block.visibility === 'default')\n .map((block) => block.text_inline ?? '')\n .join('\\n')\n .trim()\n if (!text) continue\n pending.searchDocs.push({\n doc_id: `msg:${message.message_id}`,\n entity_type: 'message',\n entity_id: message.message_id,\n session_id: message.session_id,\n project_id: projectIdBySession.get(message.session_id) ?? null,\n timestamp: message.timestamp,\n role: message.role,\n tool_name: null,\n canonical_tool_type: null,\n field_kind: message.role === 'user' ? 'user_prompt' : message.role === 'tool' ? 'tool_result' : 'assistant_text',\n text,\n })\n }\n for (const call of pending.toolCalls) {\n const text = [call.tool_name, call.command, call.path, call.query].filter(Boolean).join('\\n')\n if (!text) continue\n pending.searchDocs.push({\n doc_id: `tc:${call.tool_call_id}`,\n entity_type: 'tool_call',\n entity_id: call.tool_call_id,\n session_id: call.session_id,\n project_id: projectIdBySession.get(call.session_id) ?? null,\n timestamp: call.timestamp_start,\n role: null,\n tool_name: call.tool_name,\n canonical_tool_type: call.canonical_tool_type,\n field_kind: call.command ? 'command' : 'tool_call',\n text,\n })\n }\n for (const result of pending.toolResults) {\n if (!result.preview) continue\n pending.searchDocs.push({\n doc_id: `tr:${result.tool_result_id}`,\n entity_type: 'tool_result',\n entity_id: result.tool_result_id,\n session_id: result.session_id,\n project_id: projectIdBySession.get(result.session_id) ?? null,\n timestamp: null,\n role: 'tool',\n tool_name: null,\n canonical_tool_type: null,\n field_kind: result.is_error ? 'error' : 'tool_result',\n text: result.preview,\n })\n }\n}\n\nfunction flushPending(bundle: Bundle, pending: PendingState): void {\n const insertRaw = prepare(\n bundle.db,\n `INSERT OR IGNORE INTO raw_records (\n raw_record_id, source_file_id, source_tool, record_kind, ordinal,\n line_no, json_pointer, native_id, raw_object_id, decoded_json_object_id,\n parser_status, confidence, import_batch_id\n ) VALUES (?, ?, 'hermes', ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,\n )\n for (const record of pending.rawRecords) {\n insertRaw.run(\n record.raw_record_id,\n record.source_file_id,\n record.record_kind,\n record.ordinal,\n record.line_no,\n record.json_pointer,\n record.native_id,\n record.raw_object_id,\n record.decoded_json_object_id,\n record.parser_status,\n record.confidence,\n record.import_batch_id,\n )\n }\n\n const existingSession = prepare<[string], { found: number }>(\n bundle.db,\n `SELECT 1 AS found FROM sessions WHERE session_id = ? LIMIT 1`,\n )\n for (const session of pending.sessions) {\n if (existingSession.get(session.session_id)) {\n deleteSessionProjection(bundle, session.session_id)\n }\n }\n\n const insertProject = prepare(\n bundle.db,\n `INSERT OR IGNORE INTO projects (\n project_id, canonical_path, path_hash, source_tool, source_project_id,\n display_name, created_at\n ) VALUES (?, NULL, NULL, 'hermes', ?, ?, ?)`,\n )\n for (const project of pending.projects) {\n insertProject.run(project.project_id, project.source_project_id, project.display_name, new Date().toISOString())\n }\n\n const insertSession = prepare(\n bundle.db,\n `INSERT OR REPLACE INTO sessions (\n session_id, source_tool, source_session_id, project_id, parent_session_id,\n is_subagent, agent_role, agent_nickname, title, summary,\n start_ts, end_ts, cwd_initial, git_branch_initial,\n model_first, model_last, status, timeline_confidence, raw_record_id\n ) VALUES (?, 'hermes', ?, ?, ?, ?, NULL, NULL, ?, NULL, ?, ?, NULL, NULL, ?, ?, ?, 'high', ?)`,\n )\n for (const session of pending.sessions) {\n insertSession.run(\n session.session_id,\n session.source_session_id,\n session.project_id,\n session.parent_session_id,\n session.is_subagent,\n session.title,\n session.start_ts,\n session.end_ts,\n session.model_first,\n session.model_last,\n session.status,\n session.raw_record_id,\n )\n }\n\n const insertEvent = prepare(\n bundle.db,\n `INSERT OR REPLACE INTO events (\n event_id, session_id, turn_id, source_event_id, event_type, source_type,\n subtype, timestamp, ordinal, actor, payload_object_id, raw_record_id,\n confidence, is_derived\n ) VALUES (?, ?, NULL, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 0)`,\n )\n for (const event of pending.events) {\n insertEvent.run(\n event.event_id,\n event.session_id,\n event.source_event_id,\n event.event_type,\n event.source_type,\n event.subtype,\n event.timestamp,\n event.ordinal,\n event.actor,\n event.payload_object_id,\n event.raw_record_id,\n event.confidence,\n )\n }\n\n const insertMessage = prepare(\n bundle.db,\n `INSERT OR REPLACE INTO messages (\n message_id, session_id, turn_id, event_id, source_message_id, role,\n author_name, model, timestamp, ordinal, parent_message_id, request_id,\n status, raw_record_id\n ) VALUES (?, ?, NULL, ?, ?, ?, NULL, ?, ?, ?, NULL, NULL, ?, ?)`,\n )\n for (const message of pending.messages) {\n insertMessage.run(\n message.message_id,\n message.session_id,\n message.event_id,\n message.source_message_id,\n message.role,\n message.model,\n message.timestamp,\n message.ordinal,\n message.status,\n message.raw_record_id,\n )\n }\n\n const insertBlock = prepare(\n bundle.db,\n `INSERT OR REPLACE INTO content_blocks (\n block_id, message_id, event_id, session_id, ordinal, block_type,\n text_object_id, text_inline, mime_type, token_count, is_error,\n is_redacted, visibility, raw_record_id\n ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, NULL, ?, 0, 0, ?, ?)`,\n )\n for (const block of pending.blocks) {\n insertBlock.run(\n block.block_id,\n block.message_id,\n block.event_id,\n block.session_id,\n block.ordinal,\n block.block_type,\n block.text_object_id,\n block.text_inline,\n block.token_count,\n block.visibility,\n block.raw_record_id,\n )\n }\n\n const insertCall = prepare(\n bundle.db,\n `INSERT OR REPLACE INTO tool_calls (\n tool_call_id, session_id, turn_id, message_id, event_id,\n source_call_id, tool_name, canonical_tool_type, args_object_id,\n command, cwd, path, query, timestamp_start, timestamp_end, status,\n raw_record_id\n ) VALUES (?, ?, NULL, ?, ?, ?, ?, ?, ?, ?, NULL, ?, ?, ?, NULL, ?, ?)`,\n )\n for (const call of pending.toolCalls) {\n insertCall.run(\n call.tool_call_id,\n call.session_id,\n call.message_id,\n call.event_id,\n call.source_call_id,\n call.tool_name,\n call.canonical_tool_type,\n call.args_object_id,\n call.command,\n call.path,\n call.query,\n call.timestamp_start,\n call.status,\n call.raw_record_id,\n )\n }\n\n const insertResult = prepare(\n bundle.db,\n `INSERT OR REPLACE INTO tool_results (\n tool_result_id, tool_call_id, session_id, message_id, event_id,\n source_call_id, status, is_error, exit_code, duration_ms,\n stdout_object_id, stderr_object_id, output_object_id, preview, raw_record_id\n ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, NULL, NULL, NULL, NULL, ?, ?, ?)`,\n )\n for (const result of pending.toolResults) {\n insertResult.run(\n result.tool_result_id,\n result.tool_call_id,\n result.session_id,\n result.message_id,\n result.event_id,\n result.source_call_id,\n result.status,\n result.is_error,\n result.output_object_id,\n result.preview,\n result.raw_record_id,\n )\n }\n\n const insertSearch = prepare(\n bundle.db,\n `INSERT OR REPLACE INTO search_docs (\n doc_id, entity_type, entity_id, session_id, project_id, timestamp,\n role, tool_name, canonical_tool_type, field_kind, text\n ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,\n )\n for (const doc of pending.searchDocs) {\n insertSearch.run(\n doc.doc_id,\n doc.entity_type,\n doc.entity_id,\n doc.session_id,\n doc.project_id,\n doc.timestamp,\n doc.role,\n doc.tool_name,\n doc.canonical_tool_type,\n doc.field_kind,\n doc.text,\n )\n }\n}\n\nfunction deleteSessionProjection(bundle: Bundle, sessionId: string): void {\n prepare<[string]>(bundle.db, `DELETE FROM search_docs WHERE session_id = ?`).run(sessionId)\n prepare<[string]>(bundle.db, `DELETE FROM tool_results WHERE session_id = ?`).run(sessionId)\n prepare<[string]>(bundle.db, `DELETE FROM tool_calls WHERE session_id = ?`).run(sessionId)\n prepare<[string]>(bundle.db, `DELETE FROM content_blocks WHERE session_id = ?`).run(sessionId)\n prepare<[string]>(bundle.db, `DELETE FROM messages WHERE session_id = ?`).run(sessionId)\n prepare<[string, string]>(\n bundle.db,\n `DELETE FROM edges WHERE (src_type = 'session' AND src_id = ?) OR (dst_type = 'session' AND dst_id = ?)`,\n ).run(sessionId, sessionId)\n prepare<[string]>(bundle.db, `DELETE FROM artifacts WHERE session_id = ?`).run(sessionId)\n prepare<[string]>(bundle.db, `DELETE FROM events WHERE session_id = ?`).run(sessionId)\n prepare<[string]>(bundle.db, `DELETE FROM turns WHERE session_id = ?`).run(sessionId)\n prepare<[string]>(bundle.db, `DELETE FROM sessions WHERE session_id = ?`).run(sessionId)\n}\n\nfunction unixToIso(value: number | null | undefined): string | null {\n if (value == null || !Number.isFinite(value)) return null\n return new Date(value * 1000).toISOString()\n}\n\nfunction coerceTimestamp(value: string | number | null | undefined): string | null {\n if (value == null) return null\n // Hermes currently stores numeric timestamps as unix seconds.\n if (typeof value === 'number') return unixToIso(value)\n const parsed = Date.parse(value)\n return Number.isFinite(parsed) ? new Date(parsed).toISOString() : null\n}\n\nfunction normalizeToolResultStatus(message: NormalizedMessage, text: string): ToolCallStatus {\n if (isToolError(message, text)) return 'error'\n const status = normalizeToolCallStatus('hermes', message.finishReason)\n return status === 'unknown' ? 'success' : status\n}\n\nfunction isToolError(message: NormalizedMessage, text: string): boolean {\n if (message.finishReason === 'error') return true\n if (hasErrorMarker(message.rawPayload)) return true\n if (hasErrorMarker(message.content)) return true\n return /^(error|tool_use_error|exception)[: ]/i.test(text.trim())\n}\n\nfunction hasErrorMarker(value: unknown): boolean {\n if (Array.isArray(value)) return value.some(hasErrorMarker)\n if (!isRecord(value)) return false\n if (value.is_error === true) return true\n if (typeof value.status === 'string' && value.status.toLowerCase() === 'error') return true\n if (typeof value.type === 'string' && value.type.toLowerCase() === 'tool_use_error') return true\n return false\n}\n\nfunction decodeMaybeJson(value: string | null): unknown {\n if (value == null) return null\n const trimmed = value.trim()\n if (!trimmed) return value\n if (!trimmed.startsWith('{') && !trimmed.startsWith('[')) return value\n try {\n return JSON.parse(trimmed) as unknown\n } catch {\n return value\n }\n}\n\nfunction renderContentText(value: unknown): string {\n if (value == null) return ''\n if (typeof value === 'string') return value\n if (Array.isArray(value)) {\n return value\n .map((item) => {\n if (typeof item === 'string') return item\n if (isRecord(item)) {\n if (typeof item.text === 'string') return item.text\n if (typeof item.content === 'string') return item.content\n }\n return JSON.stringify(item)\n })\n .filter(Boolean)\n .join('\\n')\n }\n return JSON.stringify(value)\n}\n\nfunction mapRole(role: string): MessageRole {\n if (role === 'user' || role === 'assistant' || role === 'tool') return role\n if (role === 'system' || role === 'system_prompt') return 'system_prompt'\n if (role === 'developer') return 'developer'\n return 'operational'\n}\n\nfunction parseToolCalls(value: unknown): Record<string, unknown>[] {\n const decoded = typeof value === 'string' ? decodeMaybeJson(value) : value\n if (Array.isArray(decoded)) return decoded.filter(isRecord)\n if (isRecord(decoded)) return [decoded]\n return []\n}\n\nfunction getToolCallSourceId(call: Record<string, unknown>, fallback: string): string {\n return stringField(call, 'id') ?? stringField(call, 'call_id') ?? stringField(call, 'tool_call_id') ?? fallback\n}\n\nfunction getToolName(call: Record<string, unknown>, fallback: string | null): string {\n const fn = isRecord(call.function) ? call.function : null\n return stringField(fn, 'name') ?? stringField(call, 'name') ?? stringField(call, 'tool_name') ?? fallback ?? 'unknown'\n}\n\nfunction getToolArgs(call: Record<string, unknown>): Record<string, unknown> | null {\n const fn = isRecord(call.function) ? call.function : null\n const args = fn?.arguments ?? call.args ?? call.input\n if (isRecord(args)) return args\n if (typeof args === 'string') {\n try {\n const parsed = JSON.parse(args) as unknown\n return isRecord(parsed) ? parsed : { value: parsed }\n } catch {\n return { value: args }\n }\n }\n return null\n}\n\nfunction canonicalToolType(toolName: string): string {\n const lowered = toolName.toLowerCase()\n if (lowered.includes('shell') || lowered.includes('bash') || lowered.includes('terminal')) return 'shell'\n if (lowered.includes('read')) return 'read_file'\n if (lowered.includes('write')) return 'write_file'\n if (lowered.includes('edit') || lowered.includes('patch')) return 'edit_file'\n if (lowered.includes('search') || lowered.includes('grep') || lowered.includes('glob')) return 'search_file'\n if (lowered.includes('web')) return 'web_search'\n if (lowered.includes('mcp')) return 'mcp'\n if (lowered.includes('delegate') || lowered.includes('agent')) return 'subagent'\n return 'other'\n}\n\nfunction stringField(record: Record<string, unknown> | null, key: string): string | null {\n if (!record) return null\n const value = record[key]\n return typeof value === 'string' && value.length > 0 ? value : null\n}\n\nfunction firstString(values: Array<string | null>): string | null {\n return values.find((value): value is string => Boolean(value)) ?? null\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n}\n","import { access, readdir } from 'node:fs/promises'\nimport path from 'node:path'\n\n/** Hermes source files discovered from a sessions directory. */\nexport interface HermesSources {\n /** Root sessions directory passed to the importer. */\n sessionsDir: string\n /** Sibling `state.db`, when present. */\n stateDbPath: string | null\n /** Top-level `sessions.json` index, when present. */\n indexPath: string | null\n /** Top-level legacy transcript JSONL files. */\n jsonlFiles: string[]\n /** Top-level CLI JSON session snapshots. */\n jsonFiles: string[]\n}\n\n/** Discover Hermes session storage under `root`, normally `~/.hermes/sessions`. */\nexport async function discoverHermesSources(root: string): Promise<HermesSources> {\n const sessionsDir = path.resolve(root)\n const stateDbCandidate = path.join(path.dirname(sessionsDir), 'state.db')\n const indexCandidate = path.join(sessionsDir, 'sessions.json')\n const entries = await readdirSafe(sessionsDir)\n\n const jsonlFiles: string[] = []\n const jsonFiles: string[] = []\n for (const entry of entries) {\n if (!entry.isFile()) continue\n const full = path.join(sessionsDir, entry.name)\n if (entry.name === 'sessions.json') continue\n if (entry.name.endsWith('.jsonl')) {\n jsonlFiles.push(full)\n continue\n }\n if (entry.name.startsWith('session_') && entry.name.endsWith('.json')) {\n jsonFiles.push(full)\n }\n }\n\n return {\n sessionsDir,\n stateDbPath: (await exists(stateDbCandidate)) ? stateDbCandidate : null,\n indexPath: (await exists(indexCandidate)) ? indexCandidate : null,\n jsonlFiles: jsonlFiles.sort(),\n jsonFiles: jsonFiles.sort(),\n }\n}\n\nasync function exists(filePath: string): Promise<boolean> {\n try {\n await access(filePath)\n return true\n } catch {\n return false\n }\n}\n\nasync function readdirSafe(dir: string): Promise<import('node:fs').Dirent[]> {\n try {\n return await readdir(dir, { withFileTypes: true })\n } catch {\n return []\n }\n}\n","import { mkdir, rm, writeFile } from 'node:fs/promises'\nimport path from 'node:path'\nimport { DuckDBConnection } from '@duckdb/node-api'\nimport { closeBundle, openBundle } from '../../core/bundle.js'\nimport { getErrorMessage } from '../../core/errors.js'\n\n/** Canonical SQLite tables exported as one Parquet file per table. */\nexport const PARQUET_TABLES = [\n 'objects',\n 'source_files',\n 'import_batches',\n 'raw_records',\n 'import_errors',\n 'uncertainties',\n 'projects',\n 'sessions',\n 'turns',\n 'events',\n 'messages',\n 'content_blocks',\n 'tool_calls',\n 'tool_results',\n 'artifacts',\n 'edges',\n 'search_docs',\n] as const\n\n/** Derived analytics views recreated in DuckDB alongside exported tables. */\nexport const ANALYTICS_VIEWS = [\n 'session_facts',\n 'tool_usage_facts',\n 'error_facts',\n 'model_usage',\n 'project_activity',\n] as const\n\n/** Exportable canonical table name. */\nexport type ParquetTable = (typeof PARQUET_TABLES)[number]\n\n/** DuckDB analytics view name exposed over exported Parquet data. */\nexport type AnalyticsView = (typeof ANALYTICS_VIEWS)[number]\n\n/** Options for exporting a bundle's canonical tables to Parquet. */\nexport interface ParquetExportOptions {\n /** Bundle root to open and export. */\n bundlePath: string\n /** Output directory; defaults to the bundle's parquet directory. */\n outDir?: string\n}\n\n/** Result metadata for a Parquet export operation. */\nexport interface ParquetExportResult {\n /** Directory containing generated Parquet files. */\n outDir: string\n /** Path to the generated manifest JSON. */\n manifestPath: string\n /** Absolute Parquet file path by canonical table. */\n files: Record<ParquetTable, string>\n /** Exported row count by canonical table. */\n counts: Record<ParquetTable, number>\n}\n\n/** Options for querying exported Parquet files through DuckDB. */\nexport interface DuckDbQueryOptions {\n /** Directory containing exported Parquet files. */\n parquetDir: string\n /** SQL query to run after table and analytics views are created. */\n sql: string\n}\n\n/** Column-oriented query result shape returned by analytics services. */\nexport interface DuckDbQueryResult {\n /** Result column names in DuckDB output order. */\n columns: string[]\n /** Result rows as plain JSON-compatible objects. */\n rows: Record<string, unknown>[]\n}\n\n/** Immutable bundle metadata captured before DuckDB reads from SQLite. */\ninterface BundleSnapshot {\n dbPath: string\n schemaVersion: number\n parserVersion: string\n defaultOutDir: string\n counts: Record<ParquetTable, number>\n}\n\n/** Exports canonical bundle tables to Parquet and writes a manifest. */\nexport async function exportBundleParquet(options: ParquetExportOptions): Promise<ParquetExportResult> {\n const snapshot = await openBundleSnapshot(options.bundlePath)\n const outDir = path.resolve(options.outDir ?? snapshot.defaultOutDir)\n await mkdir(outDir, { recursive: true })\n\n const files = Object.fromEntries(\n PARQUET_TABLES.map((table) => [table, path.join(outDir, `${table}.parquet`)]),\n ) as Record<ParquetTable, string>\n const manifestPath = path.join(outDir, 'manifest.json')\n\n for (const file of [...Object.values(files), manifestPath]) {\n await rm(file, { force: true })\n }\n\n const connection = await createDuckDbConnection()\n try {\n await attachSqlite(connection, snapshot.dbPath)\n for (const table of PARQUET_TABLES) {\n // Tuned via bench/bench-parquet.ts: zstd-1 matches snappy on write\n // time but halves file size, and ROW_GROUP_SIZE=100k cuts ~20% off\n // total export time for prosa's table widths. See\n // docs/roadmap/parquet-export-perf.md.\n await connection.run(\n `COPY (SELECT * FROM prosa.${quoteIdentifier(table)}) TO ${sqlString(files[table])} (FORMAT parquet, COMPRESSION zstd, COMPRESSION_LEVEL 1, ROW_GROUP_SIZE 100000)`,\n )\n }\n } finally {\n connection.closeSync()\n }\n\n const manifest = {\n exported_at: new Date().toISOString(),\n source_db: snapshot.dbPath,\n schema_version: snapshot.schemaVersion,\n parser_version: snapshot.parserVersion,\n tables: Object.fromEntries(\n PARQUET_TABLES.map((table) => [\n table,\n {\n file: path.basename(files[table]),\n rows: snapshot.counts[table],\n },\n ]),\n ),\n }\n await writeFile(manifestPath, `${JSON.stringify(manifest, null, 2)}\\n`, 'utf8')\n\n return { outDir, manifestPath, files, counts: snapshot.counts }\n}\n\n/** Queries Parquet exports after creating table and analytics views in DuckDB. */\nexport async function queryDuckDbParquet(options: DuckDbQueryOptions): Promise<DuckDbQueryResult> {\n const parquetDir = path.resolve(options.parquetDir)\n const connection = await createDuckDbConnection()\n try {\n for (const table of PARQUET_TABLES) {\n await connection.run(\n `CREATE OR REPLACE VIEW ${quoteIdentifier(table)} AS SELECT * FROM read_parquet(${sqlString(\n path.join(parquetDir, `${table}.parquet`),\n )})`,\n )\n }\n await createAnalyticsViews(connection)\n\n const reader = await connection.runAndReadAll(options.sql)\n return {\n columns: reader.deduplicatedColumnNames(),\n rows: reader.getRowObjectsJson() as Record<string, unknown>[],\n }\n } catch (error) {\n if (isMissingParquetError(error)) {\n throw new Error(`Parquet export not found in ${parquetDir}; run \\`prosa export parquet --store <path>\\` first`)\n }\n throw error\n } finally {\n connection.closeSync()\n }\n}\n\n/** Opens an in-process DuckDB connection for export or query work. */\nasync function createDuckDbConnection(): Promise<DuckDBConnection> {\n return DuckDBConnection.create()\n}\n\n/** Loads DuckDB's sqlite extension and attaches the source bundle database. */\nasync function attachSqlite(connection: DuckDBConnection, dbPath: string): Promise<void> {\n try {\n await connection.run('INSTALL sqlite')\n await connection.run('LOAD sqlite')\n await connection.run(`ATTACH ${sqlString(dbPath)} AS prosa (TYPE sqlite)`)\n } catch (error) {\n throw new Error(`DuckDB could not attach prosa.sqlite via the sqlite extension: ${getErrorMessage(error)}`)\n }\n}\n\n/** Recreates analytics views in DuckDB with semantics matching SQLite views. */\nasync function createAnalyticsViews(connection: DuckDBConnection): Promise<void> {\n await connection.run(`\n CREATE OR REPLACE VIEW session_facts AS\n WITH turn_counts AS (\n SELECT session_id, count(*) AS turn_count\n FROM turns\n GROUP BY session_id\n ),\n message_counts AS (\n SELECT session_id,\n count(*) AS message_count,\n sum(CASE WHEN role = 'user' THEN 1 ELSE 0 END) AS user_message_count,\n sum(CASE WHEN role = 'assistant' THEN 1 ELSE 0 END) AS assistant_message_count\n FROM messages\n GROUP BY session_id\n ),\n tool_call_counts AS (\n SELECT session_id,\n count(*) AS tool_call_count,\n sum(CASE WHEN status = 'error' THEN 1 ELSE 0 END) AS tool_call_error_count\n FROM tool_calls\n GROUP BY session_id\n ),\n tool_result_counts AS (\n SELECT session_id,\n count(*) AS tool_result_count,\n sum(CASE WHEN is_error = 1 OR (exit_code IS NOT NULL AND exit_code <> 0)\n THEN 1 ELSE 0 END) AS tool_result_error_count,\n sum(COALESCE(duration_ms, 0)) AS tool_duration_ms\n FROM tool_results\n GROUP BY session_id\n ),\n search_doc_counts AS (\n SELECT session_id, count(*) AS search_doc_count\n FROM search_docs\n WHERE session_id IS NOT NULL\n GROUP BY session_id\n )\n SELECT s.session_id,\n s.source_tool,\n s.source_session_id,\n s.project_id,\n p.display_name AS project_name,\n p.canonical_path AS project_path,\n s.parent_session_id,\n s.is_subagent,\n s.agent_role,\n s.agent_nickname,\n s.title,\n s.start_ts,\n s.end_ts,\n CASE\n WHEN s.start_ts IS NOT NULL AND s.end_ts IS NOT NULL\n THEN date_diff('millisecond', TRY_CAST(s.start_ts AS TIMESTAMP),\n TRY_CAST(s.end_ts AS TIMESTAMP)) / 1000.0\n ELSE NULL\n END AS duration_seconds,\n s.cwd_initial,\n s.git_branch_initial,\n s.model_first,\n s.model_last,\n s.status,\n s.timeline_confidence,\n sf.path AS source_file_path,\n COALESCE(tc.turn_count, 0) AS turn_count,\n COALESCE(mc.message_count, 0) AS message_count,\n COALESCE(mc.user_message_count, 0) AS user_message_count,\n COALESCE(mc.assistant_message_count, 0) AS assistant_message_count,\n COALESCE(tcc.tool_call_count, 0) AS tool_call_count,\n COALESCE(trc.tool_result_count, 0) AS tool_result_count,\n COALESCE(tcc.tool_call_error_count, 0)\n + COALESCE(trc.tool_result_error_count, 0) AS tool_error_count,\n COALESCE(trc.tool_duration_ms, 0) AS tool_duration_ms,\n COALESCE(sdc.search_doc_count, 0) AS search_doc_count\n FROM sessions s\n LEFT JOIN projects p ON p.project_id = s.project_id\n LEFT JOIN raw_records rr ON rr.raw_record_id = s.raw_record_id\n LEFT JOIN source_files sf ON sf.source_file_id = rr.source_file_id\n LEFT JOIN turn_counts tc ON tc.session_id = s.session_id\n LEFT JOIN message_counts mc ON mc.session_id = s.session_id\n LEFT JOIN tool_call_counts tcc ON tcc.session_id = s.session_id\n LEFT JOIN tool_result_counts trc ON trc.session_id = s.session_id\n LEFT JOIN search_doc_counts sdc ON sdc.session_id = s.session_id\n `)\n\n await connection.run(`\n CREATE OR REPLACE VIEW tool_usage_facts AS\n WITH result_rollup AS (\n SELECT tool_call_id,\n session_id,\n count(*) AS tool_result_count,\n max(status) AS result_status,\n max(is_error) AS is_error,\n min(exit_code) AS exit_code,\n sum(COALESCE(duration_ms, 0)) AS duration_ms,\n max(preview) AS preview\n FROM tool_results\n GROUP BY tool_call_id, session_id\n )\n SELECT tc.tool_call_id,\n tc.session_id,\n s.source_tool,\n s.source_session_id,\n s.project_id,\n p.display_name AS project_name,\n p.canonical_path AS project_path,\n tc.turn_id,\n tc.message_id,\n tc.event_id,\n tc.source_call_id,\n tc.tool_name,\n tc.canonical_tool_type,\n tc.command,\n tc.cwd,\n tc.path,\n tc.query,\n tc.timestamp_start,\n tc.timestamp_end,\n CASE\n WHEN tc.timestamp_start IS NOT NULL AND tc.timestamp_end IS NOT NULL\n THEN date_diff('millisecond', TRY_CAST(tc.timestamp_start AS TIMESTAMP),\n TRY_CAST(tc.timestamp_end AS TIMESTAMP)) / 1000.0\n ELSE NULL\n END AS call_duration_seconds,\n tc.status AS call_status,\n rr.result_status,\n COALESCE(rr.is_error, 0) AS is_error,\n rr.exit_code,\n rr.duration_ms AS result_duration_ms,\n COALESCE(rr.tool_result_count, 0) AS tool_result_count,\n rr.preview,\n tc.raw_record_id\n FROM tool_calls tc\n LEFT JOIN sessions s ON s.session_id = tc.session_id\n LEFT JOIN projects p ON p.project_id = s.project_id\n LEFT JOIN result_rollup rr ON rr.tool_call_id = tc.tool_call_id\n `)\n\n await connection.run(`\n CREATE OR REPLACE VIEW error_facts AS\n SELECT 'tool_result:' || tr.tool_result_id AS error_id,\n 'tool_result' AS error_category,\n s.source_tool,\n s.project_id,\n p.display_name AS project_name,\n tr.session_id,\n COALESCE(tc.timestamp_end, tc.timestamp_start) AS timestamp,\n tc.tool_name,\n tc.canonical_tool_type,\n COALESCE(tr.status, tc.status) AS status,\n tr.exit_code,\n NULL AS message,\n tr.preview,\n NULL AS entity_type,\n NULL AS entity_id,\n tr.raw_record_id\n FROM tool_results tr\n LEFT JOIN tool_calls tc ON tc.tool_call_id = tr.tool_call_id\n LEFT JOIN sessions s ON s.session_id = tr.session_id\n LEFT JOIN projects p ON p.project_id = s.project_id\n WHERE tr.is_error = 1 OR (tr.exit_code IS NOT NULL AND tr.exit_code <> 0)\n UNION ALL\n SELECT 'import_error:' || CAST(ie.error_id AS VARCHAR) AS error_id,\n 'import_error' AS error_category,\n COALESCE(rr.source_tool, ib.source_tool) AS source_tool,\n NULL AS project_id,\n NULL AS project_name,\n NULL AS session_id,\n ie.occurred_at AS timestamp,\n NULL AS tool_name,\n NULL AS canonical_tool_type,\n ie.kind AS status,\n NULL AS exit_code,\n ie.message,\n NULL AS preview,\n NULL AS entity_type,\n NULL AS entity_id,\n ie.raw_record_id\n FROM import_errors ie\n LEFT JOIN import_batches ib ON ib.batch_id = ie.batch_id\n LEFT JOIN raw_records rr ON rr.raw_record_id = ie.raw_record_id\n UNION ALL\n SELECT 'uncertainty:' || CAST(u.uncertainty_id AS VARCHAR) AS error_id,\n 'uncertainty' AS error_category,\n NULL AS source_tool,\n NULL AS project_id,\n NULL AS project_name,\n CASE WHEN u.entity_type = 'session' THEN u.entity_id ELSE NULL END AS session_id,\n NULL AS timestamp,\n NULL AS tool_name,\n NULL AS canonical_tool_type,\n u.reason AS status,\n NULL AS exit_code,\n u.reason AS message,\n NULL AS preview,\n u.entity_type,\n u.entity_id,\n NULL AS raw_record_id\n FROM uncertainties u\n `)\n\n await connection.run(`\n CREATE OR REPLACE VIEW model_usage AS\n WITH model_events AS (\n SELECT s.source_tool,\n s.project_id,\n p.display_name AS project_name,\n p.canonical_path AS project_path,\n s.session_id,\n NULL AS turn_id,\n s.model_first AS model,\n s.start_ts AS timestamp,\n 'session_first' AS observation_type\n FROM sessions s\n LEFT JOIN projects p ON p.project_id = s.project_id\n WHERE s.model_first IS NOT NULL\n UNION ALL\n SELECT s.source_tool, s.project_id, p.display_name, p.canonical_path,\n s.session_id, NULL AS turn_id, s.model_last AS model, s.end_ts AS timestamp,\n 'session_last' AS observation_type\n FROM sessions s\n LEFT JOIN projects p ON p.project_id = s.project_id\n WHERE s.model_last IS NOT NULL\n UNION ALL\n SELECT s.source_tool, s.project_id, p.display_name, p.canonical_path,\n t.session_id, t.turn_id, t.model, t.start_ts AS timestamp, 'turn' AS observation_type\n FROM turns t\n LEFT JOIN sessions s ON s.session_id = t.session_id\n LEFT JOIN projects p ON p.project_id = s.project_id\n WHERE t.model IS NOT NULL\n UNION ALL\n SELECT s.source_tool, s.project_id, p.display_name, p.canonical_path,\n m.session_id, m.turn_id, m.model, m.timestamp, 'message' AS observation_type\n FROM messages m\n LEFT JOIN sessions s ON s.session_id = m.session_id\n LEFT JOIN projects p ON p.project_id = s.project_id\n WHERE m.model IS NOT NULL\n )\n SELECT source_tool,\n project_id,\n project_name,\n project_path,\n model,\n count(DISTINCT session_id) AS session_count,\n count(DISTINCT turn_id) AS turn_count,\n count(*) AS observation_count,\n sum(CASE WHEN observation_type = 'message' THEN 1 ELSE 0 END) AS message_count,\n min(timestamp) AS first_seen_ts,\n max(timestamp) AS last_seen_ts\n FROM model_events\n GROUP BY source_tool, project_id, project_name, project_path, model\n `)\n\n await connection.run(`\n CREATE OR REPLACE VIEW project_activity AS\n SELECT s.source_tool,\n s.project_id,\n COALESCE(p.display_name, s.cwd_initial, '(unknown)') AS project_name,\n p.canonical_path AS project_path,\n min(s.start_ts) AS first_session_ts,\n max(COALESCE(s.end_ts, s.start_ts)) AS latest_session_ts,\n count(DISTINCT s.session_id) AS session_count,\n count(DISTINCT CASE WHEN s.timeline_confidence = 'low' THEN s.session_id END)\n AS low_confidence_session_count,\n count(DISTINCT t.turn_id) AS turn_count,\n count(DISTINCT m.message_id) AS message_count,\n count(DISTINCT tc.tool_call_id) AS tool_call_count,\n count(DISTINCT tr.tool_result_id) AS tool_result_count,\n count(DISTINCT CASE\n WHEN tr.is_error = 1 OR (tr.exit_code IS NOT NULL AND tr.exit_code <> 0)\n THEN tr.tool_result_id\n END) AS tool_error_count,\n count(DISTINCT sd.doc_id) AS search_doc_count\n FROM sessions s\n LEFT JOIN projects p ON p.project_id = s.project_id\n LEFT JOIN turns t ON t.session_id = s.session_id\n LEFT JOIN messages m ON m.session_id = s.session_id\n LEFT JOIN tool_calls tc ON tc.session_id = s.session_id\n LEFT JOIN tool_results tr ON tr.session_id = s.session_id\n LEFT JOIN search_docs sd ON sd.session_id = s.session_id\n GROUP BY s.source_tool, s.project_id, p.display_name, s.cwd_initial, p.canonical_path\n `)\n}\n\n/** Opens the bundle briefly to collect paths, manifest versions, and row counts. */\nasync function openBundleSnapshot(bundlePath: string): Promise<BundleSnapshot> {\n const bundle = await openBundle(bundlePath)\n try {\n const counts = Object.fromEntries(\n PARQUET_TABLES.map((table) => {\n const row = bundle.db.prepare<[], { n: number }>(`SELECT count(*) AS n FROM ${quoteIdentifier(table)}`).get()\n return [table, row?.n ?? 0]\n }),\n ) as Record<ParquetTable, number>\n\n return {\n dbPath: bundle.paths.db,\n schemaVersion: bundle.manifest.schema_version,\n parserVersion: bundle.manifest.parser_version,\n defaultOutDir: bundle.paths.parquet,\n counts,\n }\n } finally {\n closeBundle(bundle)\n }\n}\n\n/** Quotes a SQL identifier for fixed table and view names. */\nfunction quoteIdentifier(value: string): string {\n return `\"${value.replace(/\"/g, '\"\"')}\"`\n}\n\n/** Quotes a SQL string literal for DuckDB statements. */\nfunction sqlString(value: string): string {\n return `'${value.replace(/'/g, \"''\")}'`\n}\n\n/** Detects DuckDB read failures caused by absent Parquet files. */\nfunction isMissingParquetError(error: unknown): boolean {\n const message = getErrorMessage(error)\n return /No files found|does not exist|not found/i.test(message) && /\\.parquet/i.test(message)\n}\n","import type { Bundle } from '../core/bundle.js'\nimport { clampLimit } from '../core/limits.js'\nimport { type DuckDbQueryResult, queryDuckDbParquet } from './export/parquet.js'\n\n/** Stable report names exposed by CLI and MCP analytics surfaces. */\nexport const ANALYTICS_REPORTS = ['sessions', 'tools', 'errors', 'models', 'projects'] as const\n\n/** Analytics report identifier. */\nexport type AnalyticsReport = (typeof ANALYTICS_REPORTS)[number]\n\n/** SQL dialects supported by the analytics query builder. */\nexport type AnalyticsDialect = 'sqlite' | 'duckdb'\n\n/** Cross-report filters accepted by analytics read surfaces. */\nexport interface AnalyticsReportFilters {\n /** Source tool filter. */\n source?: string\n /** Inclusive lower time bound for report-specific timestamps. */\n since?: string\n /** Exclusive upper time bound for report-specific timestamps. */\n until?: string\n /** Maximum row count, clamped by service limits. */\n limit?: number\n /** Native tool name filter for tool/error reports. */\n toolName?: string\n /** Canonical tool category filter. */\n canonicalType?: string\n /** Restrict tool/error reports to failed operations. */\n errorsOnly?: boolean\n /** Error category filter. */\n category?: string\n /** Model name filter. */\n model?: string\n /** Project name filter. */\n project?: string\n /** Canonical session identifier filter. */\n sessionId?: string\n /** Source file path substring filter. */\n sourcePathSubstring?: string\n}\n\n/** Options for running an analytics report against exported Parquet files. */\nexport interface AnalyticsReportOptions {\n /** Directory containing exported Parquet tables. */\n parquetDir: string\n /** Report to run. */\n report: AnalyticsReport\n /** Optional report filters. */\n filters?: AnalyticsReportFilters\n}\n\n/** Options for running an analytics report directly against a SQLite bundle. */\nexport interface AnalyticsBundleReportOptions {\n /** Open bundle queried through SQLite analytics views. */\n bundle: Bundle\n /** Report to run. */\n report: AnalyticsReport\n /** Optional report filters. */\n filters?: AnalyticsReportFilters\n}\n\n/** Runs a fixed analytics report over DuckDB views backed by Parquet exports. */\nexport async function runAnalyticsReport(options: AnalyticsReportOptions): Promise<DuckDbQueryResult> {\n return queryDuckDbParquet({\n parquetDir: options.parquetDir,\n sql: buildAnalyticsSql(options.report, options.filters ?? {}, 'duckdb'),\n })\n}\n\n/** Runs the same fixed analytics reports against SQLite analytics views. */\nexport function runAnalyticsReportFromBundle(options: AnalyticsBundleReportOptions): DuckDbQueryResult {\n const sql = buildAnalyticsSql(options.report, options.filters ?? {}, 'sqlite')\n const stmt = options.bundle.db.prepare<unknown[], Record<string, unknown>>(sql)\n const rows = stmt.all()\n const columns = stmt.columns().map((column) => column.name)\n return { columns, rows }\n}\n\n/** Dispatches to the report-specific SQL template for the requested dialect. */\nfunction buildAnalyticsSql(\n report: AnalyticsReport,\n filters: AnalyticsReportFilters,\n dialect: AnalyticsDialect,\n): string {\n switch (report) {\n case 'sessions':\n return buildSessionsSql(filters, dialect)\n case 'tools':\n return buildToolsSql(filters, dialect)\n case 'errors':\n return buildErrorsSql(filters, dialect)\n case 'models':\n return buildModelsSql(filters, dialect)\n case 'projects':\n return buildProjectsSql(filters, dialect)\n }\n}\n\n/** Builds the session_facts report query with stable output columns. */\nfunction buildSessionsSql(filters: AnalyticsReportFilters, dialect: AnalyticsDialect): string {\n const where = buildWhere([\n sourceFilter(filters),\n timeFilter('start_ts', filters),\n projectFilter(filters, dialect),\n filters.sessionId ? `session_id = ${sqlString(filters.sessionId)}` : null,\n filters.sourcePathSubstring\n ? `source_file_path LIKE ${sqlString(`%${escapeLike(filters.sourcePathSubstring)}%`)} ESCAPE '\\\\'`\n : null,\n ])\n return `\n SELECT start_ts, source_tool, project_name, source_file_path, session_id,\n source_session_id, model_last, duration_seconds,\n message_count, tool_call_count, tool_result_count, tool_error_count,\n tool_duration_ms, timeline_confidence, title\n FROM session_facts\n ${where}\n ORDER BY start_ts DESC NULLS LAST\n LIMIT ${limit(filters)}\n `\n}\n\n/** Builds the tool_usage_facts aggregate query grouped by tool and project. */\nfunction buildToolsSql(filters: AnalyticsReportFilters, dialect: AnalyticsDialect): string {\n const where = buildWhere([\n sourceFilter(filters),\n timeFilter('timestamp_start', filters),\n projectFilter(filters, dialect),\n filters.toolName ? `tool_name = ${sqlString(filters.toolName)}` : null,\n filters.canonicalType ? `canonical_tool_type = ${sqlString(filters.canonicalType)}` : null,\n filters.errorsOnly ? `(is_error = 1 OR call_status = 'error')` : null,\n ])\n return `\n SELECT tool_name, canonical_tool_type, source_tool, project_name,\n count(*) AS call_count,\n sum(CASE WHEN is_error = 1 OR call_status = 'error' THEN 1 ELSE 0 END) AS error_count,\n round(avg(result_duration_ms), 3) AS avg_result_duration_ms,\n max(timestamp_start) AS latest_ts\n FROM tool_usage_facts\n ${where}\n GROUP BY tool_name, canonical_tool_type, source_tool, project_name\n ORDER BY call_count DESC, error_count DESC, tool_name ASC\n LIMIT ${limit(filters)}\n `\n}\n\n/** Builds the error_facts detail query for tool, import, and uncertainty errors. */\nfunction buildErrorsSql(filters: AnalyticsReportFilters, dialect: AnalyticsDialect): string {\n const where = buildWhere([\n sourceFilter(filters),\n timeFilter('timestamp', filters),\n projectFilter(filters, dialect),\n filters.toolName ? `tool_name = ${sqlString(filters.toolName)}` : null,\n filters.category ? `error_category = ${sqlString(filters.category)}` : null,\n ])\n return `\n SELECT timestamp, error_category, source_tool, project_name, session_id,\n tool_name, status, exit_code, message, preview\n FROM error_facts\n ${where}\n ORDER BY timestamp DESC NULLS LAST, error_id DESC\n LIMIT ${limit(filters)}\n `\n}\n\n/** Builds the model_usage report using range-overlap filtering semantics. */\nfunction buildModelsSql(filters: AnalyticsReportFilters, dialect: AnalyticsDialect): string {\n const where = buildWhere([\n sourceFilter(filters),\n rangeOverlapFilter('first_seen_ts', 'last_seen_ts', filters),\n projectFilter(filters, dialect),\n filters.model ? `model = ${sqlString(filters.model)}` : null,\n ])\n return `\n SELECT model, source_tool, project_name, session_count, turn_count,\n message_count, observation_count, first_seen_ts, last_seen_ts\n FROM model_usage\n ${where}\n ORDER BY session_count DESC, observation_count DESC, model ASC\n LIMIT ${limit(filters)}\n `\n}\n\n/** Builds the project_activity rollup query. */\nfunction buildProjectsSql(filters: AnalyticsReportFilters, dialect: AnalyticsDialect): string {\n const where = buildWhere([\n sourceFilter(filters),\n rangeOverlapFilter('first_session_ts', 'latest_session_ts', filters),\n projectFilter(filters, dialect),\n ])\n return `\n SELECT latest_session_ts, source_tool, project_name, project_path,\n session_count, message_count, tool_call_count, tool_error_count,\n low_confidence_session_count\n FROM project_activity\n ${where}\n ORDER BY latest_session_ts DESC NULLS LAST, session_count DESC, project_name ASC\n LIMIT ${limit(filters)}\n `\n}\n\n/** Builds an exact source_tool predicate when a source filter is present. */\nfunction sourceFilter(filters: AnalyticsReportFilters): string | null {\n return filters.source ? `source_tool = ${sqlString(filters.source)}` : null\n}\n\n/** Applies point-in-time bounds while retaining rows with unknown timestamps. */\nfunction timeFilter(column: string, filters: AnalyticsReportFilters): string | null {\n const filtersSql: string[] = []\n if (filters.since) filtersSql.push(`(${column} IS NULL OR ${column} >= ${sqlString(filters.since)})`)\n if (filters.until) filtersSql.push(`(${column} IS NULL OR ${column} < ${sqlString(filters.until)})`)\n return filtersSql.length ? filtersSql.join(' AND ') : null\n}\n\n/** Applies date bounds to fact rows whose observed span overlaps the filter range. */\nfunction rangeOverlapFilter(firstColumn: string, lastColumn: string, filters: AnalyticsReportFilters): string | null {\n const filtersSql: string[] = []\n if (filters.since) {\n filtersSql.push(`(${lastColumn} IS NULL OR ${lastColumn} >= ${sqlString(filters.since)})`)\n }\n if (filters.until) {\n filtersSql.push(`(${firstColumn} IS NULL OR ${firstColumn} < ${sqlString(filters.until)})`)\n }\n return filtersSql.length ? filtersSql.join(' AND ') : null\n}\n\n/** Builds the project matcher, accounting for SQLite and DuckDB LIKE semantics. */\nfunction projectFilter(filters: AnalyticsReportFilters, dialect: AnalyticsDialect): string | null {\n if (!filters.project) return null\n const exact = sqlString(filters.project)\n const like = sqlString(`%${escapeLike(filters.project)}%`)\n // DuckDB's LIKE is case-sensitive, ILIKE is case-insensitive. SQLite's LIKE\n // is case-insensitive for ASCII by default, so we use LIKE there.\n const op = dialect === 'duckdb' ? 'ILIKE' : 'LIKE'\n return `(project_id = ${exact} OR project_name ${op} ${like} ESCAPE '\\\\' OR project_path ${op} ${like} ESCAPE '\\\\')`\n}\n\n/** Joins active predicates into a WHERE clause. */\nfunction buildWhere(filters: Array<string | null>): string {\n const active = filters.filter((filter): filter is string => Boolean(filter))\n return active.length ? `WHERE ${active.join(' AND ')}` : ''\n}\n\n/** Clamps analytics report limits to the service maximum. */\nfunction limit(filters: AnalyticsReportFilters): number {\n const value = Number.isFinite(filters.limit) ? filters.limit : undefined\n return clampLimit(value, { max: 500, fallback: 50 })\n}\n\n/** Quotes a SQL string literal for fixed-template analytics SQL. */\nfunction sqlString(value: string): string {\n return `'${value.replace(/'/g, \"''\")}'`\n}\n\n/** Escapes wildcards in user-provided LIKE fragments. */\nfunction escapeLike(value: string): string {\n return value.replace(/[\\\\%_]/g, (match) => `\\\\${match}`)\n}\n","import { access, readFile, stat } from 'node:fs/promises'\nimport path from 'node:path'\nimport { type Bundle, type BundleManifest, closeBundle, defaultBundlePath, openBundle } from '../core/bundle.js'\nimport { decompressBytes } from '../core/cas/compress.js'\nimport { blake3HexAsync } from '../core/cas/hash.js'\nimport { getErrorMessage } from '../core/errors.js'\nimport { currentSchemaVersion } from '../core/schema/migrate.js'\nimport { PROSA_PARSER_VERSION, PROSA_SCHEMA_VERSION } from '../core/version.js'\nimport {\n type SearchIndexStatus,\n countFts5Docs,\n countSearchDocs,\n getCurrentTantivySchemaFingerprint,\n getSearchIndexStatuses,\n tantivyIndexDirIsValid,\n} from './indexing.js'\n\n/** Severity/status emitted by an individual doctor check. */\nexport type CheckStatus = 'pass' | 'info' | 'warn' | 'fail' | 'skipped'\n\n/** One diagnostic result produced by doctor. */\nexport interface CheckResult {\n check: string\n status: CheckStatus\n message: string\n hint?: string\n details?: Record<string, unknown>\n}\n\n/** Complete doctor run result, including filtered checks and status counts. */\nexport interface DoctorReport {\n storePath: string\n bundleOpened: boolean\n checks: CheckResult[]\n summary: {\n pass: number\n info: number\n warn: number\n fail: number\n skipped: number\n duration_ms: number\n }\n}\n\n/** Options controlling bundle selection, deep checks, and check filtering. */\nexport interface DoctorOptions {\n storePath?: string\n deep?: boolean\n deepSample?: number\n /** Dotted prefixes or exact check names to include. Empty/undefined = all. */\n checks?: string[]\n}\n\n/** Freelist percentage above which doctor recommends VACUUM. */\nconst VACUUM_THRESHOLD_PCT = 10\n\n/** WAL size threshold that usually indicates checkpoint blockage. */\nconst WAL_WARN_BYTES = 256 * 1024 * 1024\n\n/** Age threshold for considering an unfinished import batch abandoned. */\nconst STUCK_BATCH_AGE_HOURS = 1\n\n/** Number of recent import batches sampled for import error warnings. */\nconst RECENT_BATCHES_FOR_ERRORS = 3\n\n/** Default number of CAS objects sampled by deep doctor checks. */\nconst DEFAULT_DEEP_SAMPLE = 100\n\n/**\n * Return true when freelist waste crosses the vacuum-recommendation threshold.\n * Pure so the threshold logic is unit-testable without a fixture bundle.\n */\nexport function shouldRecommendVacuum(\n freelistCount: number,\n pageCount: number,\n thresholdPct = VACUUM_THRESHOLD_PCT,\n): boolean {\n if (pageCount <= 0) return false\n const pct = (freelistCount / pageCount) * 100\n return pct > thresholdPct\n}\n\n/**\n * Audit a bundle's health. Tolerates open failures: when `openBundle` throws\n * (missing manifest, schema mismatch, corrupt sqlite), doctor still produces\n * a report — the bundle-layout / schema checks fire and the rest are marked\n * `skipped`. Doctor never throws on bundle problems; only catastrophic errors\n * inside the check engine propagate.\n */\nexport async function runDoctor(opts: DoctorOptions = {}): Promise<DoctorReport> {\n const storePath = path.resolve(opts.storePath ?? defaultBundlePath())\n const deep = opts.deep === true\n const deepSample = Math.max(1, opts.deepSample ?? DEFAULT_DEEP_SAMPLE)\n const filters = opts.checks?.filter((c) => c.length > 0) ?? []\n\n const started = Date.now()\n const results: CheckResult[] = []\n\n const push = (result: CheckResult): void => {\n if (filters.length === 0 || matchesFilter(result.check, filters)) {\n results.push(result)\n }\n }\n\n // Phase 1: layout checks that don't need an open bundle.\n const layout = await checkBundleLayout(storePath)\n for (const r of layout.results) push(r)\n\n // Phase 2: try to open the bundle. If it fails, surface as a fail check and\n // skip the SQLite/search/data checks.\n let bundle: Bundle | null = null\n let openError: Error | null = null\n if (layout.canOpen) {\n try {\n bundle = await openBundle(storePath)\n } catch (err) {\n openError = err as Error\n }\n }\n\n if (openError) {\n push({\n check: 'bundle.open',\n status: 'fail',\n message: `openBundle failed: ${getErrorMessage(openError)}`,\n hint: 'fix the bundle layout or schema, then re-run doctor',\n details: { error: getErrorMessage(openError) },\n })\n } else if (!layout.canOpen) {\n push({\n check: 'bundle.open',\n status: 'skipped',\n message: 'bundle layout checks failed; not attempting to open',\n })\n } else if (bundle) {\n push({\n check: 'bundle.open',\n status: 'pass',\n message: `bundle opened at ${storePath}`,\n })\n }\n\n if (bundle) {\n try {\n // Schema triangulation.\n const schemaResults = checkSchema(bundle)\n for (const r of schemaResults) push(r)\n\n // SQLite-level health.\n for (const r of checkSqliteHealth(bundle)) push(r)\n const walResult = await checkWalSize(bundle)\n push(walResult)\n\n // Search index status + tantivy validity + drift.\n const liveCount = countSearchDocs(bundle)\n const liveFts5 = countFts5Docs(bundle)\n const statuses = getSearchIndexStatuses(bundle)\n for (const r of checkSearchIndexes(bundle, statuses, liveCount, liveFts5)) push(r)\n\n // Import errors + stuck batches.\n for (const r of checkImports(bundle)) push(r)\n\n // Data sanity.\n for (const r of checkData(bundle)) push(r)\n\n // Deep checks (opt-in).\n if (deep) {\n push(checkIntegrityFull(bundle))\n for (const r of await checkCasSample(bundle, deepSample)) push(r)\n } else {\n push({\n check: 'deep',\n status: 'skipped',\n message: 'run with --deep to include integrity_check and CAS hash sampling',\n })\n }\n } finally {\n closeBundle(bundle)\n }\n }\n\n const summary = {\n pass: results.filter((r) => r.status === 'pass').length,\n info: results.filter((r) => r.status === 'info').length,\n warn: results.filter((r) => r.status === 'warn').length,\n fail: results.filter((r) => r.status === 'fail').length,\n skipped: results.filter((r) => r.status === 'skipped').length,\n duration_ms: Date.now() - started,\n }\n\n return {\n storePath,\n bundleOpened: bundle !== null,\n checks: results,\n summary,\n }\n}\n\n/** Matches exact doctor check names or dotted check-family prefixes. */\nfunction matchesFilter(check: string, filters: string[]): boolean {\n return filters.some((f) => check === f || check.startsWith(`${f}.`))\n}\n\n// -- Phase 1: layout checks (run without a Bundle) ---------------------------\n\n/** Layout phase result, including whether openBundle should be attempted. */\ninterface LayoutResult {\n results: CheckResult[]\n canOpen: boolean\n}\n\n/** Checks the on-disk bundle layout without opening SQLite. */\nasync function checkBundleLayout(storePath: string): Promise<LayoutResult> {\n const results: CheckResult[] = []\n let manifestParsed: BundleManifest | null = null\n\n const dirStat = await stat(storePath).catch(() => null)\n if (!dirStat?.isDirectory()) {\n results.push({\n check: 'bundle.dir',\n status: 'fail',\n message: `${storePath} is not a directory`,\n hint: `prosa init --store ${storePath}`,\n })\n return { results, canOpen: false }\n }\n results.push({\n check: 'bundle.dir',\n status: 'pass',\n message: `bundle directory present at ${storePath}`,\n })\n\n const manifestPath = path.join(storePath, 'manifest.json')\n try {\n const raw = await readFile(manifestPath, 'utf8')\n manifestParsed = JSON.parse(raw) as BundleManifest\n const requiredFields: (keyof BundleManifest)[] = [\n 'version',\n 'parser_version',\n 'schema_version',\n 'created_at',\n 'hash_alg',\n 'default_compression',\n ]\n const missing = requiredFields.filter((f) => manifestParsed?.[f] == null)\n if (missing.length > 0) {\n results.push({\n check: 'bundle.manifest',\n status: 'fail',\n message: `manifest.json missing required fields: ${missing.join(', ')}`,\n details: { missing },\n })\n return { results, canOpen: false }\n }\n results.push({\n check: 'bundle.manifest',\n status: 'pass',\n message: `manifest.json valid (version=${manifestParsed.version}, schema_version=${manifestParsed.schema_version})`,\n details: { manifest: manifestParsed as unknown as Record<string, unknown> },\n })\n } catch (err) {\n results.push({\n check: 'bundle.manifest',\n status: 'fail',\n message: `manifest.json not readable: ${getErrorMessage(err)}`,\n hint: `prosa init --store ${storePath}`,\n })\n return { results, canOpen: false }\n }\n\n // sqlite file.\n const dbPath = path.join(storePath, 'prosa.sqlite')\n const dbStat = await stat(dbPath).catch(() => null)\n if (!dbStat?.isFile() || dbStat.size === 0) {\n results.push({\n check: 'bundle.sqlite',\n status: 'fail',\n message: 'prosa.sqlite missing or empty',\n hint: `prosa init --store ${storePath}`,\n })\n return { results, canOpen: false }\n }\n results.push({\n check: 'bundle.sqlite',\n status: 'pass',\n message: `prosa.sqlite present (${formatBytes(dbStat.size)})`,\n details: { size_bytes: dbStat.size },\n })\n\n // Required sidecar directories.\n const requiredDirs: { key: string; rel: string }[] = [\n { key: 'objects', rel: 'objects' },\n { key: 'rawSources', rel: 'raw/sources' },\n { key: 'search', rel: 'search' },\n { key: 'tantivy', rel: 'search/tantivy' },\n { key: 'exports', rel: 'exports' },\n { key: 'parquet', rel: 'parquet' },\n ]\n const missingDirs: string[] = []\n for (const d of requiredDirs) {\n const s = await stat(path.join(storePath, d.rel)).catch(() => null)\n if (!s?.isDirectory()) missingDirs.push(d.rel)\n }\n if (missingDirs.length > 0) {\n results.push({\n check: 'bundle.dirs',\n status: 'warn',\n message: `missing sidecar directories: ${missingDirs.join(', ')}`,\n hint: 'openBundle recreates search/ and search/tantivy/ on next open; others come from init',\n details: { missing: missingDirs },\n })\n } else {\n results.push({\n check: 'bundle.dirs',\n status: 'pass',\n message: 'all sidecar directories present',\n })\n }\n\n // Format guards.\n if (manifestParsed.hash_alg !== 'blake3') {\n results.push({\n check: 'bundle.format',\n status: 'fail',\n message: `unexpected hash_alg=${manifestParsed.hash_alg}; expected blake3`,\n })\n } else if (manifestParsed.default_compression !== 'zstd') {\n results.push({\n check: 'bundle.format',\n status: 'warn',\n message: `default_compression=${manifestParsed.default_compression}; expected zstd`,\n })\n } else {\n results.push({\n check: 'bundle.format',\n status: 'pass',\n message: 'hash_alg=blake3, default_compression=zstd',\n })\n }\n\n return { results, canOpen: true }\n}\n\n// -- Phase 2: checks with an open Bundle -------------------------------------\n\n/** Compares manifest, SQLite, and code schema/parser versions. */\nfunction checkSchema(bundle: Bundle): CheckResult[] {\n const results: CheckResult[] = []\n const dbVersion = currentSchemaVersion(bundle.db)\n const manifestVersion = bundle.manifest.schema_version\n const details = { manifest: manifestVersion, db: dbVersion, code: PROSA_SCHEMA_VERSION }\n\n // openBundle already enforces db === code, so by the time we run we know\n // they agree. The remaining axis is the manifest, which is written once at\n // init and currently never updated by migrations.\n if (dbVersion !== PROSA_SCHEMA_VERSION) {\n results.push({\n check: 'schema.version',\n status: 'fail',\n message: `db schema_version=${dbVersion} but code expects ${PROSA_SCHEMA_VERSION}`,\n hint: 'upgrade or downgrade prosa to match the bundle, or re-run any command to apply pending migrations',\n details,\n })\n } else if (manifestVersion !== dbVersion) {\n results.push({\n check: 'schema.version',\n status: 'warn',\n message: `manifest.schema_version=${manifestVersion} but db has migrated to ${dbVersion}`,\n hint: 'manifest is stale after a migration; safe to ignore or refresh manually',\n details,\n })\n } else {\n results.push({\n check: 'schema.version',\n status: 'pass',\n message: `schema_version=${PROSA_SCHEMA_VERSION} (manifest, db, code agree)`,\n })\n }\n\n if (bundle.manifest.parser_version === PROSA_PARSER_VERSION) {\n results.push({\n check: 'schema.parser_version',\n status: 'pass',\n message: `parser_version=${PROSA_PARSER_VERSION}`,\n })\n } else {\n results.push({\n check: 'schema.parser_version',\n status: 'info',\n message: `manifest.parser_version=${bundle.manifest.parser_version} != code ${PROSA_PARSER_VERSION} (will be refreshed on next openBundle)`,\n })\n }\n\n return results\n}\n\n/** Runs lightweight SQLite health and storage-efficiency checks. */\nfunction checkSqliteHealth(bundle: Bundle): CheckResult[] {\n const results: CheckResult[] = []\n\n // PRAGMA quick_check returns rows with the column named 'quick_check' — read by index.\n const quickRows = bundle.db.prepare(`PRAGMA quick_check`).all() as Array<Record<string, unknown>>\n const quickValue = quickRows[0] ? Object.values(quickRows[0])[0] : null\n if (quickValue === 'ok') {\n results.push({ check: 'sqlite.quick_check', status: 'pass', message: 'quick_check=ok' })\n } else {\n results.push({\n check: 'sqlite.quick_check',\n status: 'fail',\n message: `quick_check returned ${String(quickValue)}`,\n hint: 'run with --deep for full integrity_check, or restore from backup',\n details: { rows: quickRows },\n })\n }\n\n const fkRows = bundle.db.prepare(`PRAGMA foreign_key_check`).all() as Array<Record<string, unknown>>\n if (fkRows.length === 0) {\n results.push({\n check: 'sqlite.foreign_keys',\n status: 'pass',\n message: 'no foreign key violations',\n })\n } else {\n results.push({\n check: 'sqlite.foreign_keys',\n status: 'fail',\n message: `${fkRows.length} foreign key violation(s)`,\n details: { violations: fkRows.slice(0, 5) },\n })\n }\n\n const journalMode = (bundle.db.prepare(`PRAGMA journal_mode`).get() as { journal_mode?: string } | undefined)\n ?.journal_mode\n if (journalMode === 'wal') {\n results.push({ check: 'sqlite.journal_mode', status: 'pass', message: 'journal_mode=wal' })\n } else {\n results.push({\n check: 'sqlite.journal_mode',\n status: 'warn',\n message: `journal_mode=${journalMode ?? 'unknown'}; expected wal`,\n })\n }\n\n const pageSize = (bundle.db.prepare(`PRAGMA page_size`).get() as { page_size?: number } | undefined)?.page_size ?? 0\n if (pageSize === 16384) {\n results.push({ check: 'sqlite.page_size', status: 'pass', message: 'page_size=16384' })\n } else {\n results.push({\n check: 'sqlite.page_size',\n status: 'warn',\n message: `page_size=${pageSize}; current openDb expects 16384`,\n hint: `migrate with: sqlite3 prosa.sqlite \"PRAGMA page_size=16384; VACUUM INTO 'prosa16k.sqlite';\" and swap files`,\n details: { page_size: pageSize },\n })\n }\n\n const pageCount =\n (bundle.db.prepare(`PRAGMA page_count`).get() as { page_count?: number } | undefined)?.page_count ?? 0\n const freelistCount =\n (bundle.db.prepare(`PRAGMA freelist_count`).get() as { freelist_count?: number } | undefined)?.freelist_count ?? 0\n const pctWaste = pageCount > 0 ? (freelistCount / pageCount) * 100 : 0\n const dbSizeBytes = pageCount * pageSize\n if (shouldRecommendVacuum(freelistCount, pageCount)) {\n results.push({\n check: 'sqlite.vacuum_hint',\n status: 'warn',\n message: `${pctWaste.toFixed(1)}% of pages are free (${freelistCount}/${pageCount})`,\n hint: 'run VACUUM to reclaim space and defragment indexes',\n details: {\n page_count: pageCount,\n freelist_count: freelistCount,\n pct_waste: Number(pctWaste.toFixed(2)),\n db_size_bytes: dbSizeBytes,\n },\n })\n } else {\n results.push({\n check: 'sqlite.vacuum_hint',\n status: 'pass',\n message: `${pctWaste.toFixed(2)}% pages free; VACUUM not needed`,\n details: {\n page_count: pageCount,\n freelist_count: freelistCount,\n pct_waste: Number(pctWaste.toFixed(2)),\n db_size_bytes: dbSizeBytes,\n },\n })\n }\n\n return results\n}\n\n/** Warns when a WAL file is large enough to suggest blocked checkpointing. */\nasync function checkWalSize(bundle: Bundle): Promise<CheckResult> {\n const walPath = `${bundle.paths.db}-wal`\n const s = await stat(walPath).catch(() => null)\n if (!s) {\n return {\n check: 'sqlite.wal_size',\n status: 'pass',\n message: 'WAL file absent (DB closed cleanly or checkpointed)',\n }\n }\n if (s.size > WAL_WARN_BYTES) {\n return {\n check: 'sqlite.wal_size',\n status: 'warn',\n message: `WAL file is ${formatBytes(s.size)}; a long-lived read transaction is preventing checkpoint`,\n hint: `close other prosa processes, then: sqlite3 prosa.sqlite \"PRAGMA wal_checkpoint(TRUNCATE);\"`,\n details: { wal_size_bytes: s.size },\n }\n }\n return {\n check: 'sqlite.wal_size',\n status: 'pass',\n message: `WAL size ${formatBytes(s.size)}`,\n details: { wal_size_bytes: s.size },\n }\n}\n\n/** Checks FTS5 and Tantivy readiness, validity, and source-count drift. */\nfunction checkSearchIndexes(\n bundle: Bundle,\n statuses: SearchIndexStatus[],\n liveDocCount: number,\n liveFts5Count: number,\n): CheckResult[] {\n const results: CheckResult[] = []\n const byEngine = new Map(statuses.map((s) => [s.engine, s]))\n\n // FTS5.\n const fts5 = byEngine.get('fts5')\n if (!fts5 || fts5.status === 'missing') {\n results.push({\n check: 'search.fts5',\n status: 'warn',\n message: 'fts5 index missing',\n hint: 'prosa index fts5',\n })\n } else if (fts5.status === 'ready') {\n if (liveFts5Count !== liveDocCount) {\n results.push({\n check: 'search.fts5',\n status: 'warn',\n message: `fts5 indexed ${liveFts5Count} docs but search_docs has ${liveDocCount}`,\n hint: 'prosa index fts5',\n details: { fts5_count: liveFts5Count, source_count: liveDocCount, ...statusDetails(fts5) },\n })\n } else {\n results.push({\n check: 'search.fts5',\n status: 'pass',\n message: `fts5 ready (${liveFts5Count} docs)`,\n details: statusDetails(fts5),\n })\n }\n } else if (fts5.status === 'failed') {\n results.push({\n check: 'search.fts5',\n status: 'fail',\n message: `fts5 failed: ${fts5.error_message ?? 'unknown error'}`,\n hint: 'prosa index fts5',\n details: statusDetails(fts5),\n })\n } else {\n results.push({\n check: 'search.fts5',\n status: 'warn',\n message: `fts5 status=${fts5.status}`,\n hint: 'prosa index fts5',\n details: statusDetails(fts5),\n })\n }\n\n // Tantivy.\n const tantivy = byEngine.get('tantivy')\n if (!tantivy || tantivy.status === 'missing') {\n results.push({\n check: 'search.tantivy',\n status: 'info',\n message: 'tantivy index not built (optional)',\n hint: 'prosa index tantivy',\n })\n } else {\n const dirValid = tantivyIndexDirIsValid(bundle.paths.tantivy)\n const currentFingerprint = getCurrentTantivySchemaFingerprint()\n const fingerprintOk = tantivy.schema_fingerprint == null || tantivy.schema_fingerprint === currentFingerprint\n\n if (tantivy.status === 'failed') {\n results.push({\n check: 'search.tantivy',\n status: 'fail',\n message: `tantivy failed: ${tantivy.error_message ?? 'unknown error'}`,\n hint: 'prosa index tantivy --overwrite',\n details: statusDetails(tantivy),\n })\n } else if (tantivy.status === 'ready' && !dirValid) {\n results.push({\n check: 'search.tantivy',\n status: 'fail',\n message: 'tantivy status=ready but index directory has no meta.json',\n hint: 'prosa index tantivy --overwrite',\n details: { ...statusDetails(tantivy), dir: bundle.paths.tantivy },\n })\n } else if (!fingerprintOk) {\n results.push({\n check: 'search.tantivy',\n status: 'warn',\n message: 'tantivy schema fingerprint drift; rebuild will be forced full',\n hint: 'prosa index tantivy --overwrite',\n details: {\n stored: tantivy.schema_fingerprint,\n current: currentFingerprint,\n ...statusDetails(tantivy),\n },\n })\n } else if (tantivy.status === 'ready') {\n results.push({\n check: 'search.tantivy',\n status: 'pass',\n message: `tantivy ready (${tantivy.indexed_doc_count} docs)`,\n details: statusDetails(tantivy),\n })\n } else {\n results.push({\n check: 'search.tantivy',\n status: 'warn',\n message: `tantivy status=${tantivy.status}`,\n hint: 'prosa index tantivy',\n details: statusDetails(tantivy),\n })\n }\n }\n\n // Drift between live search_docs and what indexes recorded.\n const drift = statuses\n .filter((s) => s.status === 'ready')\n .map((s) => ({\n engine: s.engine,\n stored: s.source_doc_count,\n live: liveDocCount,\n diff: liveDocCount - s.source_doc_count,\n }))\n .filter((d) => d.diff !== 0)\n if (drift.length > 0) {\n results.push({\n check: 'search.drift',\n status: 'warn',\n message: `search_docs count drifted from recorded source_doc_count: ${drift\n .map((d) => `${d.engine} off by ${d.diff}`)\n .join('; ')}`,\n hint: 'prosa index <engine> for each affected engine',\n details: { drift },\n })\n } else {\n results.push({\n check: 'search.drift',\n status: 'pass',\n message: `search_docs (${liveDocCount}) matches recorded source counts`,\n })\n }\n\n return results\n}\n\n/** Serializes common search-index status fields into doctor details. */\nfunction statusDetails(s: SearchIndexStatus): Record<string, unknown> {\n return {\n engine: s.engine,\n status: s.status,\n source_doc_count: s.source_doc_count,\n indexed_doc_count: s.indexed_doc_count,\n updated_at: s.updated_at,\n }\n}\n\n/** Checks recent import errors and abandoned import batches. */\nfunction checkImports(bundle: Bundle): CheckResult[] {\n const results: CheckResult[] = []\n\n const stuckRows = bundle.db\n .prepare(\n `SELECT batch_id, started_at, source_tool, status FROM import_batches\n WHERE finished_at IS NULL\n AND (julianday('now') - julianday(started_at)) * 24 > ?`,\n )\n .all(STUCK_BATCH_AGE_HOURS) as Array<Record<string, unknown>>\n if (stuckRows.length > 0) {\n results.push({\n check: 'import_batches.stuck',\n status: 'warn',\n message: `${stuckRows.length} unfinished import batch(es) older than ${STUCK_BATCH_AGE_HOURS}h`,\n hint: 'a previous compile crashed; re-run prosa compile or compile-all',\n details: { batches: stuckRows },\n })\n } else {\n results.push({\n check: 'import_batches.stuck',\n status: 'pass',\n message: 'no stuck import batches',\n })\n }\n\n // Errors in the most recent N batches.\n const recentErrors = bundle.db\n .prepare(\n `WITH recent AS (\n SELECT batch_id FROM import_batches ORDER BY started_at DESC LIMIT ?\n )\n SELECT kind, COUNT(*) AS n\n FROM import_errors\n WHERE batch_id IN (SELECT batch_id FROM recent)\n GROUP BY kind\n ORDER BY n DESC`,\n )\n .all(RECENT_BATCHES_FOR_ERRORS) as Array<{ kind: string; n: number }>\n\n const recentSamples = bundle.db\n .prepare(\n `WITH recent AS (\n SELECT batch_id FROM import_batches ORDER BY started_at DESC LIMIT ?\n )\n SELECT kind, message, occurred_at\n FROM import_errors\n WHERE batch_id IN (SELECT batch_id FROM recent)\n ORDER BY occurred_at DESC\n LIMIT 3`,\n )\n .all(RECENT_BATCHES_FOR_ERRORS) as Array<Record<string, unknown>>\n\n const totalRecent = recentErrors.reduce((s, r) => s + r.n, 0)\n if (totalRecent > 0) {\n results.push({\n check: 'import_errors.recent',\n status: 'warn',\n message: `${totalRecent} error(s) across the last ${RECENT_BATCHES_FOR_ERRORS} import batch(es)`,\n hint: 'inspect import_errors or re-run the affected compile with --verbose',\n details: { by_kind: recentErrors, samples: recentSamples },\n })\n } else {\n results.push({\n check: 'import_errors.recent',\n status: 'pass',\n message: `no errors in the last ${RECENT_BATCHES_FOR_ERRORS} import batch(es)`,\n })\n }\n\n return results\n}\n\n/** Runs cross-table sanity checks for imported session data. */\nfunction checkData(bundle: Bundle): CheckResult[] {\n const results: CheckResult[] = []\n\n const counts = bundle.db\n .prepare(\n `SELECT\n (SELECT COUNT(*) FROM sessions) AS sessions,\n (SELECT COUNT(*) FROM messages) AS messages,\n (SELECT COUNT(*) FROM raw_records) AS raw_records,\n (SELECT COUNT(*) FROM objects) AS objects`,\n )\n .get() as { sessions: number; messages: number; raw_records: number; objects: number }\n\n if (counts.sessions === 0) {\n results.push({\n check: 'data.counts',\n status: 'info',\n message: 'bundle is empty (no sessions imported yet)',\n details: counts,\n })\n } else if (counts.messages === 0) {\n results.push({\n check: 'data.counts',\n status: 'fail',\n message: `${counts.sessions} session(s) but 0 messages — import likely broke mid-file`,\n hint: 'inspect import_errors and re-run prosa compile-all',\n details: counts,\n })\n } else {\n results.push({\n check: 'data.counts',\n status: 'pass',\n message: `sessions=${counts.sessions}, messages=${counts.messages}, raw_records=${counts.raw_records}, objects=${counts.objects}`,\n details: counts,\n })\n }\n\n // Subagent edges pointing at sessions that don't exist (info-only).\n const orphanSubagents = bundle.db\n .prepare(\n `SELECT COUNT(*) AS n\n FROM edges e\n WHERE e.edge_type = 'spawned'\n AND e.dst_type = 'session'\n AND NOT EXISTS (SELECT 1 FROM sessions s WHERE s.session_id = e.dst_id)`,\n )\n .get() as { n: number }\n if (orphanSubagents.n > 0) {\n results.push({\n check: 'data.subagents',\n status: 'info',\n message: `${orphanSubagents.n} spawned-edge(s) point to sessions not in the bundle (subagent files not yet imported)`,\n details: { count: orphanSubagents.n },\n })\n } else {\n results.push({\n check: 'data.subagents',\n status: 'pass',\n message: 'no orphan subagent edges',\n })\n }\n\n return results\n}\n\n// -- Deep checks -------------------------------------------------------------\n\n/** Runs SQLite's full integrity_check for opt-in deep diagnostics. */\nfunction checkIntegrityFull(bundle: Bundle): CheckResult {\n const rows = bundle.db.prepare(`PRAGMA integrity_check`).all() as Array<Record<string, unknown>>\n const first = rows[0] ? Object.values(rows[0])[0] : null\n if (rows.length === 1 && first === 'ok') {\n return {\n check: 'deep.integrity_check',\n status: 'pass',\n message: 'integrity_check=ok',\n }\n }\n return {\n check: 'deep.integrity_check',\n status: 'fail',\n message: `integrity_check returned ${rows.length} issue(s)`,\n details: { issues: rows.slice(0, 20) },\n }\n}\n\n/** CAS object row sampled during deep hash verification. */\ninterface CasSampleRow {\n object_id: string\n hash: string\n compression: 'zstd' | 'none'\n storage_path: string\n size_bytes: number\n}\n\n/** Samples CAS files, verifying file existence and decoded blake3 hashes. */\nasync function checkCasSample(bundle: Bundle, sampleSize: number): Promise<CheckResult[]> {\n const rows = bundle.db\n .prepare(\n `SELECT object_id, hash, compression, storage_path, size_bytes\n FROM objects\n ORDER BY random()\n LIMIT ?`,\n )\n .all(sampleSize) as CasSampleRow[]\n\n if (rows.length === 0) {\n return [\n {\n check: 'deep.cas_file_exists',\n status: 'info',\n message: 'objects table empty; nothing to sample',\n },\n {\n check: 'deep.cas_hash_sample',\n status: 'info',\n message: 'objects table empty; nothing to sample',\n },\n ]\n }\n\n const missing: string[] = []\n const hashMismatches: string[] = []\n const readErrors: string[] = []\n let checked = 0\n\n // Rows in `objects` can live under either `objects/blake3/.../<hash>.<ext>`\n // (the CAS layout used by stage*/flushPendingObjects) or `raw/sources/<hash>.<ext>`\n // (source files registered by registerSourceFile). The on-disk path is always\n // stored verbatim in `storage_path` — trust that column rather than recomputing.\n for (const row of rows) {\n const abs = path.join(bundle.path, row.storage_path)\n try {\n await access(abs)\n } catch {\n missing.push(row.object_id)\n continue\n }\n try {\n const compressed = await readFile(abs)\n const plain = decompressBytes(compressed, row.compression)\n const recomputed = `blake3:${await blake3HexAsync(plain)}`\n if (recomputed !== row.object_id) {\n hashMismatches.push(`${row.object_id} (file decodes to ${recomputed})`)\n }\n checked++\n } catch (err) {\n readErrors.push(`${row.object_id}: ${getErrorMessage(err)}`)\n }\n }\n\n const results: CheckResult[] = []\n if (missing.length === 0) {\n results.push({\n check: 'deep.cas_file_exists',\n status: 'pass',\n message: `all ${rows.length} sampled objects have files on disk`,\n })\n } else {\n results.push({\n check: 'deep.cas_file_exists',\n status: 'fail',\n message: `${missing.length}/${rows.length} sampled objects have missing files`,\n hint: 'CAS files were deleted outside prosa; re-import the affected source files',\n details: { missing: missing.slice(0, 10) },\n })\n }\n\n if (hashMismatches.length === 0 && readErrors.length === 0) {\n results.push({\n check: 'deep.cas_hash_sample',\n status: 'pass',\n message: `re-hashed ${checked} sampled object(s); all match`,\n })\n } else if (hashMismatches.length > 0) {\n results.push({\n check: 'deep.cas_hash_sample',\n status: 'fail',\n message: `${hashMismatches.length} hash mismatch(es) in ${rows.length} sampled object(s)`,\n hint: 'silent corruption on disk; restore from backup',\n details: {\n mismatches: hashMismatches.slice(0, 10),\n read_errors: readErrors.slice(0, 5),\n },\n })\n } else {\n results.push({\n check: 'deep.cas_hash_sample',\n status: 'warn',\n message: `${readErrors.length} read error(s) while sampling CAS objects`,\n details: { read_errors: readErrors.slice(0, 10) },\n })\n }\n\n return results\n}\n\n// -- Helpers -----------------------------------------------------------------\n\n/** Formats byte counts for human-readable doctor messages. */\nfunction formatBytes(n: number): string {\n if (n < 1024) return `${n} B`\n const units = ['KiB', 'MiB', 'GiB', 'TiB']\n let v = n / 1024\n let i = 0\n while (v >= 1024 && i < units.length - 1) {\n v /= 1024\n i++\n }\n return `${v.toFixed(1)} ${units[i]}`\n}\n","import type { Bundle } from '../core/bundle.js'\nimport { clampLimit } from '../core/limits.js'\n\n/** Entity kinds surfaced by tool-call history queries. */\nexport type ToolCallEntity = 'tool_call' | 'artifact'\n\n/** Tool-call or artifact evidence row returned by file and command history queries. */\nexport interface ToolCallEvidence {\n /** Whether this row describes a tool call or a matching artifact. */\n entity_type: ToolCallEntity\n /** Session that owns the evidence. */\n session_id: string | null\n /** Tool call identifier when `entity_type` is `tool_call`. */\n tool_call_id: string | null\n /** Artifact identifier when `entity_type` is `artifact`. */\n artifact_id: string | null\n /** Native tool name. */\n tool_name: string | null\n /** Canonical tool category. */\n canonical_tool_type: string | null\n /** Command text, when the tool represents shell execution. */\n command: string | null\n /** File path associated with the tool call or artifact. */\n path: string | null\n /** Normalized tool call status. */\n status: string | null\n /** Tool call start timestamp or artifact creation timestamp. */\n timestamp_start: string | null\n /** SQLite boolean indicating an error result. */\n is_error: 0 | 1 | null\n /** Process exit code when available. */\n exit_code: number | null\n /** Human-sized result preview. */\n preview: string | null\n}\n\n/** Filters for tool-call history and file-history queries. */\nexport interface ToolCallFilters {\n /** Restrict evidence to one session. */\n sessionId?: string\n /** Restrict evidence to a native tool name. */\n toolName?: string\n /** Restrict evidence to a canonical tool category. */\n canonicalType?: string\n /** Match paths on tool calls and artifacts. */\n pathSubstring?: string\n /** Include only tool calls with error evidence. */\n errorsOnly?: boolean\n /** Inclusive lower bound for tool timestamps. */\n sinceIso?: string\n /** Exclusive upper bound for tool timestamps. */\n untilIso?: string\n /** Maximum rows to return, clamped by service limits. */\n limit?: number\n}\n\n/** Lists tool-call evidence, including artifacts when filtering by path substring. */\nexport function listToolCalls(bundle: Bundle, filters: ToolCallFilters = {}): ToolCallEvidence[] {\n const conds: string[] = []\n const params: unknown[] = []\n\n if (filters.toolName) {\n conds.push('tc.tool_name = ?')\n params.push(filters.toolName)\n }\n if (filters.canonicalType) {\n conds.push('tc.canonical_tool_type = ?')\n params.push(filters.canonicalType)\n }\n if (filters.sessionId) {\n conds.push('tc.session_id = ?')\n params.push(filters.sessionId)\n }\n if (filters.errorsOnly) {\n conds.push('(tr.is_error = 1 OR tc.status = ?)')\n params.push('error')\n }\n if (filters.pathSubstring) {\n conds.push('tc.path IS NOT NULL AND tc.path LIKE ?')\n params.push(`%${filters.pathSubstring}%`)\n }\n if (filters.sinceIso) {\n conds.push('(tc.timestamp_start IS NULL OR tc.timestamp_start >= ?)')\n params.push(filters.sinceIso)\n }\n if (filters.untilIso) {\n conds.push('(tc.timestamp_start IS NULL OR tc.timestamp_start < ?)')\n params.push(filters.untilIso)\n }\n\n const where = conds.length ? `WHERE ${conds.join(' AND ')}` : ''\n const limit = clampLimit(filters.limit, { max: 500, fallback: 100 })\n\n const toolCallSql = `\n SELECT 'tool_call' AS entity_type,\n tc.session_id,\n tc.tool_call_id,\n NULL AS artifact_id,\n tc.tool_name,\n tc.canonical_tool_type,\n tc.command,\n tc.path,\n tc.status,\n tc.timestamp_start,\n tr.is_error,\n tr.exit_code,\n tr.preview\n FROM tool_calls tc\n LEFT JOIN tool_results tr ON tr.tool_call_id = tc.tool_call_id\n ${where}\n `\n\n if (!filters.pathSubstring) {\n const sql = `${toolCallSql} ORDER BY tc.timestamp_start DESC LIMIT ${limit}`\n return bundle.db.prepare(sql).all(...params) as ToolCallEvidence[]\n }\n\n // path_substring is set: also surface artifacts with matching paths so\n // file-history queries return both tool_calls that touched a path and\n // artifacts produced for that path.\n const artifactSql = `\n SELECT 'artifact' AS entity_type,\n a.session_id,\n NULL AS tool_call_id,\n a.artifact_id,\n NULL AS tool_name,\n NULL AS canonical_tool_type,\n NULL AS command,\n a.path,\n NULL AS status,\n a.created_ts AS timestamp_start,\n NULL AS is_error,\n NULL AS exit_code,\n NULL AS preview\n FROM artifacts a\n WHERE a.path IS NOT NULL AND a.path LIKE ?\n `\n const sql = `\n ${toolCallSql}\n UNION ALL\n ${artifactSql}\n ORDER BY timestamp_start DESC\n LIMIT ${limit}\n `\n return bundle.db.prepare(sql).all(...params, `%${filters.pathSubstring}%`) as ToolCallEvidence[]\n}\n","import type { Bundle } from '../core/bundle.js'\nimport { getText } from '../core/cas/index.js'\nimport type { ObjectId } from '../core/cas/index.js'\nimport type { SessionRow } from './sessions.js'\n\n/** Default inline-text byte budget for block resolution. Larger blobs stay in CAS. */\nconst DEFAULT_MAX_INLINE_BYTES = 64 * 1024\n/** Default inline-text byte budget for tool-call args JSON. */\nconst DEFAULT_MAX_ARGS_INLINE_BYTES = 8 * 1024\n\n/** Matched `tool_results` row attached to its owning `TranscriptToolCall`. */\nexport interface TranscriptToolResult {\n toolResultId: string\n status: string | null\n isError: boolean\n exitCode: number | null\n durationMs: number | null\n preview: string | null\n /** Full stdout, if any, is in CAS; pass-through id so renderers can fetch on demand. */\n stdoutObjectId: string | null\n /** Full stderr, if any, is in CAS; pass-through id so renderers can fetch on demand. */\n stderrObjectId: string | null\n /** Full output, if any, is in CAS; pass-through id so renderers can fetch on demand. */\n outputObjectId: string | null\n}\n\n/** Tool invocation rendered alongside its owning turn (or as unattached). */\nexport interface TranscriptToolCall {\n toolCallId: string\n toolName: string\n canonicalToolType: string | null\n /** Resolved args JSON text when ≤ maxArgsInlineBytes; otherwise null. */\n argsInline: string | null\n /** Source CAS id for args. Kept so renderers can fetch on demand. */\n argsObjectId: string | null\n command: string | null\n path: string | null\n status: string | null\n timestampStart: string | null\n result: TranscriptToolResult | null\n}\n\n/** One content block in a message: text, thinking, tool_use, tool_result, etc. */\nexport interface TranscriptBlock {\n blockId: string\n blockType: 'text' | 'thinking' | 'tool_use' | 'tool_result' | string\n /** Resolved inline OR fetched from CAS when ≤ maxInlineBytes. Null for oversize. */\n text: string | null\n /** Source CAS id for text. Kept so renderers can fetch oversized blobs on demand. */\n textObjectId: string | null\n /** Mirrors `content_blocks.visibility = 'hidden_by_default'`. */\n hidden: boolean\n mimeType: string | null\n isError: boolean\n}\n\n/** One conversational turn: a message plus its blocks and outbound tool calls. */\nexport interface TranscriptTurn {\n messageId: string\n ordinal: number\n role: 'system_prompt' | 'developer' | 'user' | 'assistant' | 'tool' | 'operational'\n model: string | null\n timestamp: string | null\n blocks: TranscriptBlock[]\n toolCalls: TranscriptToolCall[]\n}\n\n/** Full structured transcript for one session. */\nexport interface SessionTranscript {\n session: SessionRow\n turns: TranscriptTurn[]\n /** Tool calls whose `message_id` is NULL (legacy / event-only imports). */\n unattachedToolCalls: TranscriptToolCall[]\n}\n\n/** Options controlling how aggressively the loader inlines CAS-backed text. */\nexport interface LoadTranscriptOptions {\n /** Maximum UTF-8 byte size to inline a block's text. Default 64KB. */\n maxInlineBytes?: number\n /** Maximum UTF-8 byte size to inline a tool-call's args JSON. Default 8KB. */\n maxArgsInlineBytes?: number\n}\n\ninterface MessageRow {\n message_id: string\n role: string\n timestamp: string | null\n ordinal: number\n model: string | null\n}\n\ninterface BlockRow {\n block_id: string\n message_id: string | null\n block_type: string\n text_object_id: string | null\n text_inline: string | null\n ordinal: number\n mime_type: string | null\n is_error: 0 | 1 | null\n visibility: 'default' | 'hidden_by_default' | 'audit_only'\n}\n\ninterface ToolCallRow {\n tool_call_id: string\n message_id: string | null\n tool_name: string\n canonical_tool_type: string | null\n args_object_id: string | null\n command: string | null\n path: string | null\n status: string | null\n timestamp_start: string | null\n}\n\ninterface ToolResultRow {\n tool_call_id: string | null\n tool_result_id: string\n status: string | null\n is_error: 0 | 1 | null\n exit_code: number | null\n duration_ms: number | null\n preview: string | null\n stdout_object_id: string | null\n stderr_object_id: string | null\n output_object_id: string | null\n}\n\n/**\n * Assemble a session's full conversation — messages, content blocks, and tool\n * calls with matched results — from the local bundle SQLite. Returns null\n * when the session is absent (callers handle \"not found\" themselves).\n *\n * Text bodies are resolved inline when small enough; oversize bodies surface\n * only as `textObjectId`/`argsObjectId` so renderers can fetch on demand.\n */\nexport async function loadTranscript(\n bundle: Bundle,\n sessionId: string,\n options: LoadTranscriptOptions = {},\n): Promise<SessionTranscript | null> {\n const maxInlineBytes = options.maxInlineBytes ?? DEFAULT_MAX_INLINE_BYTES\n const maxArgsInlineBytes = options.maxArgsInlineBytes ?? DEFAULT_MAX_ARGS_INLINE_BYTES\n\n const session = bundle.db\n .prepare<[string], SessionRow>(\n `SELECT s.session_id,\n s.source_tool,\n s.source_session_id,\n s.project_id,\n s.parent_session_id,\n s.is_subagent,\n s.title,\n s.start_ts,\n s.end_ts,\n s.cwd_initial,\n s.git_branch_initial,\n s.model_first,\n s.model_last,\n s.status,\n s.timeline_confidence,\n (SELECT count(*) FROM messages m WHERE m.session_id = s.session_id) AS message_count,\n (SELECT count(*) FROM tool_calls tc WHERE tc.session_id = s.session_id) AS tool_call_count\n FROM sessions s\n WHERE s.session_id = ?`,\n )\n .get(sessionId)\n\n if (!session) return null\n\n const messages = bundle.db\n .prepare<[string], MessageRow>(\n `SELECT message_id, role, timestamp, ordinal, model\n FROM messages WHERE session_id = ? ORDER BY ordinal`,\n )\n .all(sessionId)\n\n // Include hidden_by_default rows; the renderer decides whether to display\n // thinking blocks. audit_only stays excluded (privacy posture).\n const blocks = bundle.db\n .prepare<[string], BlockRow>(\n `SELECT block_id, message_id, block_type, text_object_id, text_inline,\n ordinal, mime_type, is_error, visibility\n FROM content_blocks\n WHERE session_id = ? AND visibility != 'audit_only'\n ORDER BY message_id, ordinal`,\n )\n .all(sessionId)\n\n const toolCalls = bundle.db\n .prepare<[string], ToolCallRow>(\n `SELECT tool_call_id, message_id, tool_name, canonical_tool_type, args_object_id,\n command, path, status, timestamp_start\n FROM tool_calls WHERE session_id = ?\n ORDER BY timestamp_start, tool_call_id`,\n )\n .all(sessionId)\n\n // LEFT JOIN equivalent: one query gets all results for the session, then we\n // group by tool_call_id below. Multiple results per call are possible in\n // theory; we keep the latest by tool_result_id ordering.\n const toolResults = bundle.db\n .prepare<[string], ToolResultRow>(\n `SELECT tool_call_id, tool_result_id, status, is_error, exit_code, duration_ms,\n preview, stdout_object_id, stderr_object_id, output_object_id\n FROM tool_results WHERE session_id = ?`,\n )\n .all(sessionId)\n\n const resultByCallId = new Map<string, ToolResultRow>()\n for (const r of toolResults) {\n if (!r.tool_call_id) continue\n resultByCallId.set(r.tool_call_id, r)\n }\n\n // Group blocks under their owning message_id; orphan blocks (event-only)\n // are dropped from the per-turn view but kept reachable via raw queries.\n const blocksByMessage = new Map<string, BlockRow[]>()\n for (const b of blocks) {\n if (!b.message_id) continue\n const list = blocksByMessage.get(b.message_id) ?? []\n list.push(b)\n blocksByMessage.set(b.message_id, list)\n }\n\n const callsByMessage = new Map<string, ToolCallRow[]>()\n const unattached: ToolCallRow[] = []\n for (const c of toolCalls) {\n if (c.message_id == null) {\n unattached.push(c)\n continue\n }\n const list = callsByMessage.get(c.message_id) ?? []\n list.push(c)\n callsByMessage.set(c.message_id, list)\n }\n\n const turns: TranscriptTurn[] = []\n for (const m of messages) {\n const mblocks = (blocksByMessage.get(m.message_id) ?? []).sort((a, b) => a.ordinal - b.ordinal)\n const renderedBlocks: TranscriptBlock[] = []\n for (const b of mblocks) {\n renderedBlocks.push(await renderBlock(bundle, b, maxInlineBytes))\n }\n\n const mcalls = (callsByMessage.get(m.message_id) ?? []).sort((a, b) => {\n const ta = a.timestamp_start ?? ''\n const tb = b.timestamp_start ?? ''\n if (ta !== tb) return ta < tb ? -1 : 1\n return a.tool_call_id < b.tool_call_id ? -1 : a.tool_call_id > b.tool_call_id ? 1 : 0\n })\n const renderedCalls: TranscriptToolCall[] = []\n for (const c of mcalls) {\n renderedCalls.push(\n await renderToolCall(bundle, c, resultByCallId.get(c.tool_call_id) ?? null, maxArgsInlineBytes),\n )\n }\n\n turns.push({\n messageId: m.message_id,\n ordinal: m.ordinal,\n role: m.role as TranscriptTurn['role'],\n model: m.model,\n timestamp: m.timestamp,\n blocks: renderedBlocks,\n toolCalls: renderedCalls,\n })\n }\n\n const unattachedRendered: TranscriptToolCall[] = []\n for (const c of unattached) {\n unattachedRendered.push(\n await renderToolCall(bundle, c, resultByCallId.get(c.tool_call_id) ?? null, maxArgsInlineBytes),\n )\n }\n\n return { session, turns, unattachedToolCalls: unattachedRendered }\n}\n\n/**\n * Resolve a block's printable text. Returns null when neither inline nor CAS\n * has a body; returns null `text` (but keeps `textObjectId`) when the CAS\n * blob exceeds `maxInlineBytes` so renderers can fetch on demand.\n *\n * Exported so the markdown exporter can share the same resolution path.\n */\nexport async function resolveBlockText(\n bundle: Bundle,\n block: { text_inline: string | null; text_object_id: string | null },\n maxInlineBytes: number = DEFAULT_MAX_INLINE_BYTES,\n): Promise<{ text: string | null; textObjectId: string | null; unavailable: boolean }> {\n if (block.text_inline != null) {\n return { text: block.text_inline, textObjectId: block.text_object_id, unavailable: false }\n }\n if (block.text_object_id) {\n try {\n const resolved = await getText(bundle, block.text_object_id)\n if (Buffer.byteLength(resolved, 'utf8') > maxInlineBytes) {\n return { text: null, textObjectId: block.text_object_id, unavailable: false }\n }\n return { text: resolved, textObjectId: block.text_object_id, unavailable: false }\n } catch {\n return { text: null, textObjectId: block.text_object_id, unavailable: true }\n }\n }\n return { text: null, textObjectId: null, unavailable: false }\n}\n\n/**\n * Resolve a tool call's args JSON. Returns null when the blob is missing or\n * exceeds `maxBytes`; the caller keeps the object id for \"show full\" UX.\n *\n * Exported so the markdown exporter can share the same resolution path.\n */\nexport async function resolveArgsText(\n bundle: Bundle,\n argsObjectId: ObjectId | null,\n maxBytes: number = DEFAULT_MAX_ARGS_INLINE_BYTES,\n): Promise<string | null> {\n if (!argsObjectId) return null\n try {\n const text = await getText(bundle, argsObjectId)\n if (Buffer.byteLength(text, 'utf8') > maxBytes) return null\n return text\n } catch {\n return null\n }\n}\n\nasync function renderBlock(bundle: Bundle, b: BlockRow, maxInlineBytes: number): Promise<TranscriptBlock> {\n const resolved = await resolveBlockText(bundle, b, maxInlineBytes)\n // Surface CAS-fetch failure as an explicit marker so renderers can decide\n // whether to dim or annotate the block; we keep textObjectId for retry.\n const text = resolved.unavailable ? `[content unavailable: ${b.text_object_id}]` : resolved.text\n return {\n blockId: b.block_id,\n blockType: b.block_type,\n text,\n textObjectId: resolved.textObjectId,\n hidden: b.visibility === 'hidden_by_default',\n mimeType: b.mime_type,\n isError: b.is_error === 1,\n }\n}\n\nasync function renderToolCall(\n bundle: Bundle,\n c: ToolCallRow,\n r: ToolResultRow | null,\n maxArgsInlineBytes: number,\n): Promise<TranscriptToolCall> {\n const argsInline = await resolveArgsText(bundle, c.args_object_id, maxArgsInlineBytes)\n return {\n toolCallId: c.tool_call_id,\n toolName: c.tool_name,\n canonicalToolType: c.canonical_tool_type,\n argsInline,\n argsObjectId: c.args_object_id,\n command: c.command,\n path: c.path,\n status: c.status,\n timestampStart: c.timestamp_start,\n result: r\n ? {\n toolResultId: r.tool_result_id,\n status: r.status,\n isError: r.is_error === 1,\n exitCode: r.exit_code,\n durationMs: r.duration_ms,\n preview: r.preview,\n stdoutObjectId: r.stdout_object_id,\n stderrObjectId: r.stderr_object_id,\n outputObjectId: r.output_object_id,\n }\n : null,\n }\n}\n","import type { Bundle } from '../../core/bundle.js'\nimport { loadTranscript } from '../transcript.js'\nimport type { TranscriptToolCall } from '../transcript.js'\n\n/**\n * Render a session into Markdown. Big tool outputs aren't dumped inline:\n * we show a preview line plus a `[object: blake3:…]` reference, leaving the\n * raw bytes in the CAS for downstream tools.\n *\n * Built on top of {@link loadTranscript} so the CLI's `session show --format\n * markdown` path and `prosa export session --format markdown` share one\n * resolution pipeline (inline + CAS text + tool result preview).\n */\nexport async function exportSessionMarkdown(bundle: Bundle, sessionId: string): Promise<string> {\n // We resolve full text bodies for markdown export so the dumped file is\n // self-contained; bump the inline budget high enough to avoid truncation\n // on the same blocks the previous renderer would have inlined.\n const transcript = await loadTranscript(bundle, sessionId, { maxInlineBytes: Number.MAX_SAFE_INTEGER })\n if (!transcript) {\n throw new Error(`session not found: ${sessionId}`)\n }\n\n const session = transcript.session\n const lines: string[] = []\n const title = session.title?.trim() || `${session.source_tool} session ${session.source_session_id}`\n lines.push(`# ${title}`, '')\n lines.push(`- **source**: ${session.source_tool}`)\n lines.push(`- **session_id**: \\`${session.session_id}\\``)\n lines.push(`- **source_session_id**: \\`${session.source_session_id}\\``)\n if (session.start_ts) lines.push(`- **start**: ${session.start_ts}`)\n if (session.end_ts) lines.push(`- **end**: ${session.end_ts}`)\n if (session.cwd_initial) lines.push(`- **cwd**: \\`${session.cwd_initial}\\``)\n if (session.git_branch_initial) lines.push(`- **git branch**: ${session.git_branch_initial}`)\n if (session.model_first || session.model_last) {\n lines.push(`- **models**: ${session.model_first ?? '?'} → ${session.model_last ?? session.model_first ?? '?'}`)\n }\n lines.push(`- **timeline confidence**: ${session.timeline_confidence}`)\n lines.push('')\n\n for (const turn of transcript.turns) {\n const ts = turn.timestamp ? ` · ${turn.timestamp}` : ''\n const model = turn.model ? ` · ${turn.model}` : ''\n lines.push(`## ${turn.role}${model}${ts}`, '')\n\n for (const block of turn.blocks) {\n // Preserve historical markdown behavior: skip blocks the old query\n // filtered out (`visibility='default'`-only) and drop blocks with no\n // resolved text payload.\n if (block.hidden) continue\n if (block.text == null) continue\n lines.push(block.text, '')\n }\n\n for (const call of turn.toolCalls) {\n lines.push(renderToolCallMarkdown(call), '')\n }\n }\n\n // Tool calls that didn't bind to any specific message (legacy / event-only).\n if (transcript.unattachedToolCalls.length > 0) {\n lines.push('## tool calls (unattached)', '')\n for (const call of transcript.unattachedToolCalls) {\n lines.push(renderToolCallMarkdown(call), '')\n }\n }\n\n return `${lines.join('\\n')}\\n`\n}\n\n/** Renders command, path, status, and preview for one Markdown tool-call block. */\nfunction renderToolCallMarkdown(c: TranscriptToolCall): string {\n const status = c.status ? ` · ${c.status}` : ''\n const errFlag = c.result?.isError ? ' · ERROR' : ''\n const lines: string[] = []\n lines.push(`### tool: ${c.toolName}${status}${errFlag}`)\n if (c.command) {\n lines.push('```sh', c.command, '```')\n }\n if (c.path) lines.push(`*path:* \\`${c.path}\\``)\n if (c.result?.preview) {\n lines.push('```')\n lines.push(c.result.preview)\n lines.push('```')\n }\n return lines.join('\\n')\n}\n","import type { SessionTranscript, TranscriptBlock, TranscriptToolCall, TranscriptTurn } from './transcript.js'\n\n/** Options controlling the textual transcript rendering. */\nexport interface FormatTranscriptTextOptions {\n /** When true, thinking blocks are rendered in full. Default false. */\n showThinking?: boolean\n /** Max preview/output lines to keep per tool result; over-long output is truncated. */\n maxOutputLines?: number\n /**\n * Accepted for source-compat with prior releases. Ignored: this formatter\n * always emits plain text (no ANSI escapes) so piped output stays clean.\n * Callers that want colored interactive output should use Ink directly\n * (apps/cli ships `renderTranscriptInk`).\n */\n color?: boolean\n}\n\nconst DEFAULT_MAX_OUTPUT_LINES = 40\n\n/**\n * Render a `SessionTranscript` as plaintext. Output is always ANSI-free so it\n * round-trips through pipes (`prosa session show --format text > file.txt`).\n *\n * Layout: a metadata header (title, ids, models, confidence), then one section\n * per turn with a role header and inline blocks/tool-call summaries. Thinking\n * blocks collapse to one line by default; tool outputs truncate at\n * `maxOutputLines` and surface CAS object ids for full retrieval downstream.\n */\nexport function formatTranscriptText(transcript: SessionTranscript, options: FormatTranscriptTextOptions = {}): string {\n const showThinking = options.showThinking ?? false\n const maxOutputLines = options.maxOutputLines ?? DEFAULT_MAX_OUTPUT_LINES\n\n const out: string[] = []\n out.push(...renderHeader(transcript))\n\n for (const turn of transcript.turns) {\n out.push('')\n out.push(...renderTurn(turn, { showThinking, maxOutputLines }))\n }\n\n if (transcript.unattachedToolCalls.length > 0) {\n out.push('')\n out.push('── tool calls (unattached) ──')\n for (const call of transcript.unattachedToolCalls) {\n out.push(...renderToolCallLines(call, '', { maxOutputLines }))\n }\n }\n\n return `${out.join('\\n')}\\n`\n}\n\nfunction renderHeader(transcript: SessionTranscript): string[] {\n const s = transcript.session\n const title = s.title?.trim() || `${s.source_tool} session ${s.source_session_id}`\n const lines: string[] = []\n lines.push(`# ${title}`)\n lines.push(`source: ${s.source_tool}`)\n lines.push(`session_id: ${s.session_id}`)\n lines.push(`source_id: ${s.source_session_id}`)\n if (s.start_ts) lines.push(`start: ${s.start_ts}`)\n if (s.end_ts) lines.push(`end: ${s.end_ts}`)\n if (s.model_first || s.model_last) {\n lines.push(`models: ${s.model_first ?? '?'} → ${s.model_last ?? s.model_first ?? '?'}`)\n }\n lines.push(`confidence: ${s.timeline_confidence}`)\n return lines\n}\n\nfunction renderTurn(turn: TranscriptTurn, ctx: { showThinking: boolean; maxOutputLines: number }): string[] {\n const lines: string[] = []\n const meta: string[] = []\n if (turn.model) meta.push(turn.model)\n if (turn.timestamp) meta.push(turn.timestamp)\n const metaSuffix = meta.length > 0 ? ` · ${meta.join(' · ')}` : ''\n lines.push(`[${turn.role}]${metaSuffix}`)\n\n for (const block of turn.blocks) {\n lines.push(...renderBlock(block, ctx))\n }\n for (const call of turn.toolCalls) {\n lines.push(...renderToolCallLines(call, ' ', { maxOutputLines: ctx.maxOutputLines }))\n }\n return lines\n}\n\nfunction renderBlock(block: TranscriptBlock, ctx: { showThinking: boolean; maxOutputLines: number }): string[] {\n const isThinking = block.hidden || block.blockType === 'thinking'\n if (isThinking && !ctx.showThinking) {\n const charCount = block.text ? block.text.length : 0\n return [` ▶ thinking (≈${charCount} chars)`]\n }\n\n if (block.text == null) {\n // Body wasn't inlined (oversize) or block has no text payload.\n if (block.textObjectId) {\n return [` ▶ ${block.blockType} (oversize; objectId=${block.textObjectId})`]\n }\n return []\n }\n\n return block.text.split('\\n').map((l) => ` ${l}`)\n}\n\nfunction renderToolCallLines(call: TranscriptToolCall, indent: string, ctx: { maxOutputLines: number }): string[] {\n const lines: string[] = []\n const statusBits: string[] = []\n if (call.status) statusBits.push(call.status)\n if (call.result?.isError) statusBits.push('ERROR')\n const statusSuffix = statusBits.length > 0 ? ` [${statusBits.join(' · ')}]` : ''\n lines.push(`${indent}▶ tool: ${call.toolName}${statusSuffix}`)\n\n if (call.command) {\n lines.push(`${indent} $ ${call.command}`)\n }\n if (call.path) {\n lines.push(`${indent} path: ${call.path}`)\n }\n if (call.argsInline) {\n const argsLines = call.argsInline.split('\\n')\n const shown = argsLines.slice(0, ctx.maxOutputLines)\n for (const l of shown) lines.push(`${indent} ${l}`)\n if (argsLines.length > ctx.maxOutputLines) {\n lines.push(\n `${indent} … (${argsLines.length - ctx.maxOutputLines} more lines; use --max-output-lines or open via objectId=${call.argsObjectId ?? '?'})`,\n )\n }\n } else if (call.argsObjectId) {\n lines.push(`${indent} args: objectId=${call.argsObjectId} (oversize)`)\n }\n\n if (call.result?.preview) {\n const previewLines = call.result.preview.split('\\n')\n const shown = previewLines.slice(0, ctx.maxOutputLines)\n lines.push(`${indent} ─ result ─`)\n for (const l of shown) lines.push(`${indent} ${l}`)\n if (previewLines.length > ctx.maxOutputLines) {\n const objectId = call.result.outputObjectId ?? call.result.stdoutObjectId ?? call.result.stderrObjectId\n lines.push(\n `${indent} … (${previewLines.length - ctx.maxOutputLines} more lines; use --max-output-lines or open via objectId=${objectId ?? '?'})`,\n )\n }\n } else if (call.result?.outputObjectId || call.result?.stdoutObjectId) {\n const objectId = call.result.outputObjectId ?? call.result.stdoutObjectId\n lines.push(`${indent} result objectId=${objectId}`)\n }\n\n return lines\n}\n","/** System instructions advertised by the MCP server to guide evidence-first use of prosa tools. */\nexport const PROSA_MCP_INSTRUCTIONS = `\nprosa is a local memory over local agent session histories. Use it to find prior work, commands,\ndecisions, file touches, transcripts, and analytical rollups before answering from memory.\n\nThere are six tools:\n- search: full-text over messages, commands, paths, diffs, and previews. Start here for open-ended\n questions with 2-5 concrete terms. Optional engine, field_kind, raw, since/until filters.\n- sessions: without session_id, lists candidates filtered by source/time/limit. With session_id,\n opens the session: format=detail (default) returns metadata + timeline, format=summary returns\n only the session row, format=markdown renders the full transcript.\n- tool_calls: audit commands and tool usage. Filters by tool_name, canonical_type, session_id,\n errors_only. When path_substring is set, also returns artifacts touching that path — use this for\n file-history questions.\n- analytics: built-in aggregate reports backed by SQLite views. Pick report=sessions|tools|errors|\n models|projects with the matching filters. Use report=sessions with session_id or\n source_path_substring for per-session metrics.\n- artifact: fetch full text for an artifact_id when previews are not enough. Binary artifacts return\n a placeholder.\n- compile: with no input, returns a status snapshot (search index health). With source (and\n optionally sessions_path), imports that provider into the bundle. Use status mode when search\n results look stale; use import mode when local sessions may not be indexed yet.\n\nWhen answering, cite concrete evidence: session_id, timestamp, tool/file path, and the relevant\nsnippet or event. Do not treat search snippets as the whole truth; open the session with\n\\`sessions session_id=… format=detail\\` when accuracy matters.\n`.trim()\n\n/** Prompt template for investigating prior sessions by topic. */\nexport const INVESTIGATE_PRIOR_WORK_PROMPT = `\nInvestigate prior work in prosa for the topic: {{topic}}\n\nUse this workflow:\n1. Call \\`search\\` with a short query built from the topic.\n2. If results are broad, search again with narrower terms from the best snippets.\n3. Open the most relevant session_ids with \\`sessions session_id=… format=detail\\`.\n4. Use \\`sessions session_id=… format=markdown\\` only for sessions that appear directly relevant.\n5. Answer with evidence: session_id, timestamp, and the decisive snippet or event.\n`.trim()\n\n/** Prompt template for tracing sessions and tool calls that touched a file or path. */\nexport const FIND_FILE_HISTORY_PROMPT = `\nInvestigate history for file/path: {{path}}\n\nUse this workflow:\n1. Call \\`tool_calls\\` with path_substring set to the path or its most distinctive suffix.\n2. Open returned session_ids with \\`sessions session_id=… format=detail\\`.\n3. Call \\`tool_calls\\` with session_id when you need command-level detail inside one session.\n4. Use \\`sessions session_id=… format=markdown\\` only for the most relevant session.\n5. Summarize what changed, who/what tool touched it, and cite session_id plus timestamp.\n`.trim()\n\n/** Prompt template for grouping failed tool calls and related context by likely cause. */\nexport const AUDIT_TOOL_FAILURES_PROMPT = `\nAudit tool failures in prosa{{query_clause}}.\n\nUse this workflow:\n1. For an aggregate report, call \\`analytics report=errors\\` (filter by source/since/until/tool_name\n as needed).\n2. For per-call evidence, call \\`tool_calls\\` with errors_only=true.\n3. If a query is provided, also call \\`search\\` for that query to find related context.\n4. Open relevant session_ids with \\`sessions session_id=… format=detail\\`.\n5. Group failures by tool_name, command/path, and likely cause.\n6. Answer with evidence: session_id, timestamp, command/path, exit code, and preview.\n`.trim()\n","import { randomUUID } from 'node:crypto'\nimport http from 'node:http'\nimport type { IncomingMessage, ServerResponse } from 'node:http'\nimport { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'\nimport { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js'\nimport type { Transport } from '@modelcontextprotocol/sdk/shared/transport.js'\nimport type { Bundle } from '../core/bundle.js'\nimport { getErrorMessage } from '../core/errors.js'\nimport { PROSA_PARSER_VERSION } from '../core/version.js'\nimport type { SearchEngine } from '../services/indexing.js'\nimport { PROSA_MCP_INSTRUCTIONS } from './guidance.js'\nimport { registerProsaTools } from './tools.js'\n\ninterface SessionEntry {\n server: McpServer\n transport: StreamableHTTPServerTransport\n}\n\n/** HTTP transport options for exposing a prosa bundle as an MCP server. */\nexport interface McpServerOptions {\n /** Hostname or IP address to bind. */\n host: string\n /** TCP port to bind. */\n port: number\n /** HTTP path that receives MCP Streamable HTTP requests. Defaults to `/mcp`. */\n path?: string\n /** Default search engine passed to MCP search tools. */\n searchEngine?: SearchEngine\n /** Bundle path reopened by long-lived tool handlers. Defaults to `bundle.path`. */\n storePath?: string\n}\n\n/** Handle returned by the HTTP MCP server listener. */\nexport interface RunningServer {\n /** Full URL clients should use for Streamable HTTP requests. */\n url: string\n /** Stop the HTTP listener and close all active MCP sessions. */\n close(): Promise<void>\n}\n\n/** Handle returned by the stdio MCP server listener. */\nexport interface RunningStdioServer {\n /** Close the MCP server and stdio transport. */\n close(): Promise<void>\n}\n\n/** Stdio transport options for exposing a prosa bundle as an MCP server. */\nexport interface McpStdioServerOptions {\n /** Default search engine passed to MCP search tools. */\n searchEngine?: SearchEngine\n /** Bundle path reopened by long-lived tool handlers. Defaults to `bundle.path`. */\n storePath?: string\n}\n\n/** Start a stdio MCP server backed by an already-open prosa bundle. */\nexport async function listenMcpStdioServer(\n bundle: Bundle,\n options: McpStdioServerOptions = {},\n): Promise<RunningStdioServer> {\n const server = createMcpServer(bundle, options.searchEngine ?? 'fts5', options.storePath)\n const transport = new StdioServerTransport()\n await server.connect(transport)\n\n return {\n close: async () => {\n await safeClose(server)\n await safeClose(transport)\n },\n }\n}\n\n/**\n * Bind an HTTP MCP server on `host:port` backed by `bundle`. Implements the\n * Streamable HTTP transport with stateful sessions (one McpServer per\n * `MCP-Session-Id`).\n *\n * - POST /mcp — JSON-RPC requests; opens a session if `MCP-Session-Id` is missing\n * - DELETE /mcp — close an existing session by header\n * - GET /mcp — 405 (we don't expose server-initiated SSE streams)\n */\nexport async function listenMcpServer(bundle: Bundle, options: McpServerOptions): Promise<RunningServer> {\n const mcpPath = options.path ?? '/mcp'\n const sessions = new Map<string, SessionEntry>()\n\n const searchEngine = options.searchEngine ?? 'fts5'\n const storePath = options.storePath ?? bundle.path\n\n const httpServer = http.createServer((req, res) => {\n handleRequest(req, res, mcpPath, sessions, bundle, searchEngine, storePath).catch((error: unknown) => {\n writeError(res, error)\n })\n })\n\n await new Promise<void>((resolve, reject) => {\n httpServer.once('error', reject)\n httpServer.listen(options.port, options.host, () => {\n httpServer.removeListener('error', reject)\n resolve()\n })\n })\n\n return {\n url: `http://${options.host}:${options.port}${mcpPath}`,\n close: async () => {\n await new Promise<void>((resolve, reject) => {\n httpServer.close((err) => (err ? reject(err) : resolve()))\n })\n for (const entry of sessions.values()) {\n await safeClose(entry.server)\n await safeClose(entry.transport)\n }\n sessions.clear()\n },\n }\n}\n\nasync function handleRequest(\n req: IncomingMessage,\n res: ServerResponse,\n mcpPath: string,\n sessions: Map<string, SessionEntry>,\n bundle: Bundle,\n searchEngine: SearchEngine,\n storePath: string,\n): Promise<void> {\n // Keep HTTP routing deliberately small: this listener owns exactly one MCP\n // endpoint and delegates protocol details to StreamableHTTPServerTransport.\n if (!req.url || !req.url.startsWith(mcpPath)) {\n res.writeHead(404).end()\n return\n }\n const method = req.method ?? 'GET'\n\n if (method === 'GET') {\n // Match the Sourcebot reference: we don't initiate SSE streams from the\n // server side, so GET is rejected per the MCP Streamable HTTP spec.\n res.writeHead(405, { Allow: 'POST, DELETE' }).end()\n return\n }\n if (method !== 'POST' && method !== 'DELETE') {\n res.writeHead(405, { Allow: 'POST, DELETE' }).end()\n return\n }\n\n const headerSessionId = req.headers['mcp-session-id']\n const sessionId =\n typeof headerSessionId === 'string'\n ? headerSessionId\n : Array.isArray(headerSessionId)\n ? headerSessionId[0]\n : undefined\n\n let entry: SessionEntry | undefined = sessionId ? sessions.get(sessionId) : undefined\n\n if (!entry) {\n if (method === 'DELETE') {\n res.writeHead(404).end()\n return\n }\n entry = await openSession(bundle, sessions, searchEngine, storePath)\n }\n\n const bodyText = await readBody(req)\n const body = bodyText.length > 0 ? safeJsonParse(bodyText) : undefined\n await entry.transport.handleRequest(req, res, body)\n}\n\n/** Create and connect a new MCP session, then let the transport register its generated id. */\nasync function openSession(\n bundle: Bundle,\n store: Map<string, SessionEntry>,\n searchEngine: SearchEngine,\n storePath: string,\n): Promise<SessionEntry> {\n // We need to assemble server + transport together because the transport's\n // `onsessioninitialized` callback wants to register both into the map.\n const server = createMcpServer(bundle, searchEngine, storePath)\n const transport = new StreamableHTTPServerTransport({\n sessionIdGenerator: () => randomUUID(),\n onsessioninitialized: (id: string) => {\n store.set(id, { server, transport })\n },\n onsessionclosed: async (id: string) => {\n const e = store.get(id)\n if (e) {\n await safeClose(e.server)\n await safeClose(e.transport)\n store.delete(id)\n }\n },\n })\n\n await server.connect(transport)\n return { server, transport }\n}\n\n/** Build a per-session MCP server instance with prosa instructions and tools attached. */\nfunction createMcpServer(bundle: Bundle, searchEngine: SearchEngine, storePath?: string): McpServer {\n const server = new McpServer(\n {\n name: 'prosa',\n version: PROSA_PARSER_VERSION,\n },\n { instructions: PROSA_MCP_INSTRUCTIONS },\n )\n registerProsaTools(server, bundle, { ensureStore: true, searchEngine, storePath })\n return server\n}\n\n/** Read a request body once so the MCP transport can consume a parsed JSON-RPC payload. */\nasync function readBody(req: IncomingMessage): Promise<string> {\n return new Promise((resolve, reject) => {\n const chunks: Buffer[] = []\n req.on('data', (chunk: Buffer) => chunks.push(chunk))\n req.on('end', () => resolve(Buffer.concat(chunks).toString('utf8')))\n req.on('error', reject)\n })\n}\n\n/** Parse optional JSON request bodies; invalid or empty bodies are passed through as undefined. */\nfunction safeJsonParse(text: string): unknown {\n try {\n return JSON.parse(text)\n } catch {\n return undefined\n }\n}\n\n/** Close transports and servers defensively during shutdown. */\nasync function safeClose(o: { close: () => Promise<void> | void } | Transport): Promise<void> {\n try {\n await o.close()\n } catch {\n /* ignore */\n }\n}\n\n/** Write a JSON-RPC internal error response when request handling fails before transport dispatch. */\nfunction writeError(res: ServerResponse, error: unknown): void {\n if (!res.headersSent) {\n res.writeHead(500, { 'Content-Type': 'application/json' })\n }\n res.end(\n JSON.stringify({\n jsonrpc: '2.0',\n error: { code: -32603, message: getErrorMessage(error) },\n id: null,\n }),\n )\n}\n","import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'\nimport { z } from 'zod'\nimport { type Bundle, closeBundle, openOrInitBundle } from '../core/bundle.js'\nimport { getText } from '../core/cas/index.js'\nimport { SOURCE_TOOLS } from '../core/domain/types.js'\nimport { getErrorMessage } from '../core/errors.js'\nimport { ANALYTICS_REPORTS, type AnalyticsReportFilters, runAnalyticsReportFromBundle } from '../services/analytics.js'\nimport { COMPILE_PROVIDERS, exportCompileParquet, getCompileProvider, runCompileImports } from '../services/compile.js'\nimport { exportSessionMarkdown } from '../services/export/markdown.js'\nimport { type SearchEngine, getSearchIndexStatuses } from '../services/indexing.js'\nimport { searchFullText } from '../services/search.js'\nimport { getSession, listSessions } from '../services/sessions.js'\nimport { listToolCalls } from '../services/tool_calls.js'\nimport { AUDIT_TOOL_FAILURES_PROMPT, FIND_FILE_HISTORY_PROMPT, INVESTIGATE_PRIOR_WORK_PROMPT } from './guidance.js'\n\n/** Options that tune how registered MCP tools open bundles and choose search backends. */\nexport interface ProsaToolOptions {\n /** Default search engine used when a `search` tool call does not specify one. */\n searchEngine?: SearchEngine\n /** Store path to reopen for each tool call when `ensureStore` is enabled. */\n storePath?: string\n /** Reopen or initialize the bundle per call instead of reusing the startup handle. */\n ensureStore?: boolean\n}\n\nconst CANONICAL_TOOL_TYPES = [\n 'shell',\n 'read_file',\n 'write_file',\n 'edit_file',\n 'search_file',\n 'web_search',\n 'mcp',\n 'subagent',\n 'patch',\n 'other',\n] as const\n\nconst FIELD_KINDS = [\n 'message_text',\n 'user_prompt',\n 'assistant_text',\n 'command',\n 'command_output_preview',\n 'error',\n 'file_path',\n 'diff',\n 'summary',\n 'artifact_text',\n 'tool_args',\n 'tool_result',\n] as const\n\n/**\n * Register the six prosa MCP tools on `server`. Five are read-only; `compile`\n * is dual-mode (no args = bundle status snapshot, with args = mutating import).\n */\nexport function registerProsaTools(server: McpServer, bundle: Bundle, options: ProsaToolOptions = {}): void {\n const searchEngine = options.searchEngine ?? 'fts5'\n const storePath = options.storePath ?? bundle.path\n const ensureStore = options.ensureStore ?? false\n registerProsaPrompts(server)\n\n server.registerTool(\n 'search',\n {\n title: 'Full-text search',\n description: `Search messages, commands, paths, diffs, and result previews using the server-selected ${searchEngine} engine. Start here for open-ended questions with 2-5 concrete terms; then call \\`sessions\\` for relevant hits.`,\n inputSchema: {\n query: z.string().min(1),\n engine: z.enum(['fts5', 'tantivy']).optional(),\n field_kind: z.enum(FIELD_KINDS).optional(),\n limit: z.number().int().min(1).max(500).optional().default(50),\n raw: z\n .boolean()\n .optional()\n .default(false)\n .describe('Pass query straight to FTS5 MATCH (allows OR/NEAR/prefixes).'),\n },\n annotations: { readOnlyHint: true, idempotentHint: true },\n },\n async ({ query, engine, field_kind, limit, raw }) =>\n withToolBundle(bundle, storePath, ensureStore, (activeBundle) => {\n const selectedEngine = engine ?? searchEngine\n const hits = searchFullText(activeBundle, {\n query,\n limit: limit ?? 50,\n raw,\n engine: selectedEngine,\n })\n const filtered = field_kind ? hits.filter((hit) => hit.field_kind === field_kind) : hits\n return {\n content: [\n {\n type: 'text',\n text: JSON.stringify(\n {\n query,\n engine: selectedEngine,\n field_kind: field_kind ?? null,\n count: filtered.length,\n hits: filtered,\n },\n null,\n 2,\n ),\n },\n ],\n }\n }),\n )\n\n server.registerTool(\n 'sessions',\n {\n title: 'List or open sessions',\n description:\n 'Without `session_id`, lists sessions filtered by source/time/limit. With `session_id`, opens that session: `format=detail` (default) returns metadata plus timeline events; `format=summary` returns only the session row; `format=markdown` renders the readable transcript. Call after `search` to get evidence behind a hit.',\n inputSchema: {\n session_id: z.string().min(1).optional(),\n format: z.enum(['summary', 'detail', 'markdown']).optional().default('detail'),\n source: z.enum(SOURCE_TOOLS).optional(),\n since: z.string().optional().describe('ISO timestamp lower bound (inclusive)'),\n until: z.string().optional().describe('ISO timestamp upper bound (exclusive)'),\n limit: z.number().int().min(1).max(500).optional().default(50),\n },\n annotations: { readOnlyHint: true, idempotentHint: true },\n },\n async ({ session_id, format, source, since, until, limit }) =>\n withToolBundle(bundle, storePath, ensureStore, async (activeBundle) => {\n if (!session_id) {\n const rows = listSessions(activeBundle, {\n sourceTool: source,\n sinceIso: since,\n untilIso: until,\n limit: limit ?? 50,\n })\n return {\n content: [{ type: 'text', text: JSON.stringify(rows, null, 2) }],\n }\n }\n\n if (format === 'markdown') {\n try {\n const md = await exportSessionMarkdown(activeBundle, session_id)\n return { content: [{ type: 'text', text: md }] }\n } catch (error) {\n return {\n content: [{ type: 'text', text: getErrorMessage(error) }],\n isError: true,\n }\n }\n }\n\n const detail = getSession(activeBundle, session_id)\n if (!detail) {\n return {\n content: [{ type: 'text', text: `session not found: ${session_id}` }],\n isError: true,\n }\n }\n const payload = format === 'summary' ? { session: detail.session } : detail\n return {\n content: [{ type: 'text', text: JSON.stringify(payload, null, 2) }],\n }\n }),\n )\n\n server.registerTool(\n 'tool_calls',\n {\n title: 'Audit tool calls and file touches',\n description:\n 'Audit commands and tool usage. Filter by tool_name, canonical_type, session_id, errors_only, or path_substring. When `path_substring` is set, also surfaces matching artifacts so file-history questions return both invocations and produced files.',\n inputSchema: {\n session_id: z.string().min(1).optional(),\n tool_name: z.string().optional(),\n canonical_type: z.enum(CANONICAL_TOOL_TYPES).optional(),\n path_substring: z\n .string()\n .min(1)\n .optional()\n .describe('Filter rows where tool_calls.path or artifacts.path contains this substring.'),\n errors_only: z.boolean().optional().default(false),\n since: z.string().optional().describe('ISO timestamp lower bound (inclusive)'),\n until: z.string().optional().describe('ISO timestamp upper bound (exclusive)'),\n limit: z.number().int().min(1).max(500).optional().default(100),\n },\n annotations: { readOnlyHint: true, idempotentHint: true },\n },\n async (input) =>\n withToolBundle(bundle, storePath, ensureStore, (activeBundle) => {\n const rows = listToolCalls(activeBundle, {\n sessionId: input.session_id,\n toolName: input.tool_name,\n canonicalType: input.canonical_type,\n pathSubstring: input.path_substring,\n errorsOnly: input.errors_only,\n sinceIso: input.since,\n untilIso: input.until,\n limit: input.limit ?? 100,\n })\n return {\n content: [{ type: 'text', text: JSON.stringify(rows, null, 2) }],\n }\n }),\n )\n\n server.registerTool(\n 'analytics',\n {\n title: 'Aggregate analytics reports',\n description:\n 'Run a built-in aggregation over the bundle: per-session metrics (`sessions`), tool usage rollup (`tools`), error timeline (`errors`), model usage (`models`), or project activity (`projects`). Backed by SQLite views; mirrors the `prosa analytics` CLI.',\n inputSchema: {\n report: z.enum(ANALYTICS_REPORTS),\n source: z.enum(SOURCE_TOOLS).optional(),\n since: z.string().optional().describe('ISO timestamp lower bound (inclusive)'),\n until: z.string().optional().describe('ISO timestamp upper bound (exclusive)'),\n limit: z.number().int().min(1).max(500).optional().default(50),\n session_id: z.string().min(1).optional().describe('Drill-down filter (applies to `sessions` report).'),\n source_path_substring: z\n .string()\n .min(1)\n .optional()\n .describe('Filter `sessions` rows by imported source file path substring.'),\n project: z.string().min(1).optional().describe('Filter by project id, name, or path substring.'),\n tool_name: z.string().min(1).optional().describe('Filter `tools`/`errors` rows by exact tool name.'),\n canonical_type: z.enum(CANONICAL_TOOL_TYPES).optional().describe('Filter `tools` rows by canonical tool type.'),\n errors_only: z.boolean().optional().describe('`tools` report: only error rows.'),\n category: z\n .string()\n .min(1)\n .optional()\n .describe('Filter `errors` by category: tool_result|import_error|uncertainty.'),\n model: z.string().min(1).optional().describe('Filter `models` rows by exact model name.'),\n },\n annotations: { readOnlyHint: true, idempotentHint: true },\n },\n async (input) =>\n withToolBundle(bundle, storePath, ensureStore, (activeBundle) => {\n const filters: AnalyticsReportFilters = {\n source: input.source,\n since: input.since,\n until: input.until,\n limit: input.limit,\n sessionId: input.session_id,\n sourcePathSubstring: input.source_path_substring,\n project: input.project,\n toolName: input.tool_name,\n canonicalType: input.canonical_type,\n errorsOnly: input.errors_only,\n category: input.category,\n model: input.model,\n }\n try {\n const result = runAnalyticsReportFromBundle({\n bundle: activeBundle,\n report: input.report,\n filters,\n })\n return {\n content: [\n {\n type: 'text',\n text: JSON.stringify({ report: input.report, count: result.rows.length, rows: result.rows }, null, 2),\n },\n ],\n }\n } catch (error) {\n return {\n content: [{ type: 'text', text: getErrorMessage(error) }],\n isError: true,\n }\n }\n }),\n )\n\n server.registerTool(\n 'artifact',\n {\n title: 'Get artifact bytes/text',\n description:\n 'Retrieve full text for an `artifact_id` referenced in a session, search hit, or tool_calls row. Use this when previews are not enough; binary artifacts return a placeholder.',\n inputSchema: {\n artifact_id: z.string().min(1),\n },\n annotations: { readOnlyHint: true, idempotentHint: true },\n },\n async ({ artifact_id }) =>\n withToolBundle(bundle, storePath, ensureStore, async (activeBundle) => {\n const row = activeBundle.db\n .prepare<[string], { text_object_id: string | null; object_id: string | null; mime_type: string | null }>(\n `SELECT text_object_id, object_id, mime_type FROM artifacts WHERE artifact_id = ?`,\n )\n .get(artifact_id)\n if (!row) {\n return {\n content: [{ type: 'text', text: `artifact not found: ${artifact_id}` }],\n isError: true,\n }\n }\n const objectId = row.text_object_id ?? row.object_id\n if (!objectId) {\n return { content: [{ type: 'text', text: '[no content stored]' }] }\n }\n try {\n const text = await getText(activeBundle, objectId)\n return { content: [{ type: 'text', text }] }\n } catch {\n return { content: [{ type: 'text', text: `[binary artifact: ${objectId}]` }] }\n }\n }),\n )\n\n server.registerTool(\n 'compile',\n {\n title: 'Compile sessions or report bundle status',\n description:\n 'Without input, returns a status snapshot (search index health, last batch, schema version) without mutating anything. With `source`, imports that provider; `sessions_path` may override its default. Pass `overwrite: true` to force a full rebuild of derived indexes (Tantivy from scratch). With neither `source` nor `sessions_path`, only status is returned.',\n inputSchema: {\n source: z.enum(SOURCE_TOOLS).optional(),\n sessions_path: z.string().min(1).optional(),\n overwrite: z.boolean().optional(),\n },\n annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: true },\n },\n async ({ source, sessions_path, overwrite }) =>\n withToolBundle(bundle, storePath, ensureStore, async (activeBundle) => {\n if (sessions_path && !source) {\n return {\n content: [\n {\n type: 'text',\n text: 'sessions_path requires source because providers use incompatible source layouts',\n },\n ],\n isError: true,\n }\n }\n\n if (!source && !sessions_path) {\n return {\n content: [\n {\n type: 'text',\n text: JSON.stringify({ mode: 'status', search_index: getSearchIndexStatuses(activeBundle) }, null, 2),\n },\n ],\n }\n }\n\n try {\n const result = await runCompileImports({\n bundle: activeBundle,\n providers: source ? [getCompileProvider(source)] : COMPILE_PROVIDERS,\n sessionsPath: sessions_path,\n overwrite,\n })\n const parquet = result.importedAny ? await exportCompileParquet({ storePath }) : null\n\n return {\n content: [\n {\n type: 'text',\n text: JSON.stringify(\n {\n mode: 'import',\n providers: result.providers.map((provider) => ({\n source: provider.source,\n source_path: provider.sourcePath,\n batch_id: provider.batchId,\n counts: provider.counts,\n })),\n imported_any: result.importedAny,\n tantivy: result.tantivy ? { indexed_doc_count: result.tantivy.indexedDocCount } : null,\n tantivy_error: result.tantivyError,\n fts5_error: result.fts5Error,\n parquet: parquet\n ? {\n out_dir: parquet.outDir,\n manifest_path: parquet.manifestPath,\n table_count: parquet.tableCount,\n files: parquet.files,\n counts: parquet.counts,\n }\n : null,\n search_index: getSearchIndexStatuses(activeBundle),\n },\n null,\n 2,\n ),\n },\n ],\n }\n } catch (error) {\n return {\n content: [{ type: 'text', text: getErrorMessage(error) }],\n isError: true,\n }\n }\n }),\n )\n}\n\nasync function withToolBundle<T>(\n fallbackBundle: Bundle,\n storePath: string,\n ensureStore: boolean,\n fn: (bundle: Bundle) => Promise<T> | T,\n): Promise<T> {\n // MCP servers can stay alive while the store is compiled elsewhere. Reopening\n // per call keeps schema/index changes visible without restarting the server.\n if (!ensureStore) {\n return await fn(fallbackBundle)\n }\n\n const bundle = await openOrInitBundle(storePath)\n try {\n return await fn(bundle)\n } finally {\n closeBundle(bundle)\n }\n}\n\n/** Register reusable MCP prompt templates alongside the callable prosa tools. */\nfunction registerProsaPrompts(server: McpServer): void {\n server.registerPrompt(\n 'investigate_prior_work',\n {\n title: 'Investigate prior work',\n description:\n 'Guide an agent through searching prosa for prior work on a topic, opening relevant sessions, and citing evidence.',\n argsSchema: {\n topic: z.string().min(1).describe('Topic, feature, error, command, or decision to investigate'),\n },\n },\n ({ topic }) => ({\n description: 'Search prosa for relevant prior work and answer with session evidence.',\n messages: [\n {\n role: 'user',\n content: {\n type: 'text',\n text: INVESTIGATE_PRIOR_WORK_PROMPT.replace('{{topic}}', topic),\n },\n },\n ],\n }),\n )\n\n server.registerPrompt(\n 'find_file_history',\n {\n title: 'Find file history',\n description:\n 'Guide an agent through finding sessions that touched a file/path and summarizing the relevant history.',\n argsSchema: {\n path: z.string().min(1).describe('File path, directory, or distinctive path suffix'),\n },\n },\n ({ path }) => ({\n description: 'Find sessions that touched a path and summarize the evidence.',\n messages: [\n {\n role: 'user',\n content: {\n type: 'text',\n text: FIND_FILE_HISTORY_PROMPT.replace('{{path}}', path),\n },\n },\n ],\n }),\n )\n\n server.registerPrompt(\n 'audit_tool_failures',\n {\n title: 'Audit tool failures',\n description: 'Guide an agent through finding failed tool calls and grouping them by likely cause.',\n argsSchema: {\n query: z.string().optional().describe('Optional topic, file, command, or error to narrow audit'),\n },\n },\n ({ query }) => ({\n description: 'Audit failed tool calls and cite operational evidence.',\n messages: [\n {\n role: 'user',\n content: {\n type: 'text',\n text: AUDIT_TOOL_FAILURES_PROMPT.replace('{{query_clause}}', query ? ` related to: ${query}` : ''),\n },\n },\n ],\n }),\n )\n}\n"],"mappings":"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","names":["constants","fsConstants","access","mkdir","readFile","stat","writeFile","os","path","Database","openDb","path","db","Database","pragma","closeDb","close","stmtCache","WeakMap","prepare","sql","cache","get","Map","set","stmt","transactional","fn","wrapped","transaction","SQL_001_INIT","String","raw","SQL_002_SEARCH_INDEX_STATUS","String","raw","SQL_003_ANALYTICS_VIEWS","String","raw","SQL_004_TANTIVY_CHECKPOINT","String","raw","SQL_005_OBJECT_TRANSPORT_HASH","String","raw","MIGRATIONS","version","name","sql","SQL_001_INIT","SQL_002_SEARCH_INDEX_STATUS","SQL_003_ANALYTICS_VIEWS","SQL_004_TANTIVY_CHECKPOINT","SQL_005_OBJECT_TRANSPORT_HASH","runMigrations","db","exec","applied","Set","prepare","all","map","row","newlyApplied","migration","has","tx","transaction","run","Date","toISOString","push","currentSchemaVersion","get","PROSA_PARSER_VERSION","packageJson","version","PROSA_SCHEMA_VERSION","BundleNotInitializedError","Error","bundlePath","reason","name","defaultBundlePath","env","process","PROSA_STORE","length","path","resolve","join","os","homedir","bundlePaths","rootPath","db","manifest","objects","rawSources","search","tantivy","exports","parquet","lock","exists","p","access","fsConstants","F_OK","initBundle","resolved","paths","mkdir","recursive","version","parser_version","PROSA_PARSER_VERSION","schema_version","PROSA_SCHEMA_VERSION","created_at","Date","toISOString","hash_alg","default_compression","writeFile","JSON","stringify","openDb","runMigrations","openBundle","dirStat","stat","catch","isDirectory","parse","readFile","currentVersion","currentSchemaVersion","closeDb","manifestDirty","openOrInitBundle","closeBundle","bundle","SOURCE_TOOLS","mkdir","readFile","writeFile","path","compress","zstdCompress","decompress","zstdDecompress","COMPRESS_THRESHOLD_BYTES","ZSTD_LEVEL","compressBytes","input","byteLength","bytes","Buffer","from","compression","out","zstdCompress","compressionLevel","decompressBytes","zstdDecompress","createHash","blake3","nobleBlake3","bytesToHex","wasmBlake3","blake3Hex","bytes","bytesToHex","nobleBlake3","blake3HexAsync","wasmBlake3","sha256Hex","createHash","update","digest","objectIdFromHash","hashHex","objectStoragePath","compression","ext","a","slice","b","ensuredDirs","Set","ensureDir","absoluteDir","has","mkdir","recursive","add","putBytes","bundle","bytes","options","hash","blake3HexAsync","objectId","objectIdFromHash","existing","prepare","db","get","stored","compression","compressBytes","storagePath","objectStoragePath","absolutePath","path","join","dirname","writeFile","run","byteLength","mimeType","encoding","Date","toISOString","putText","text","buf","Buffer","from","putJson","value","JSON","stringify","getBytes","meta","Error","readFile","storage_path","decompressBytes","getText","toString","getJson","parse","getObjectMeta","createPendingObjects","byId","Map","stageBytes","pending","isBuffer","blake3Hex","set","stageText","stageJson","flushPendingObjects","size","ids","keys","existingIds","queryExistingObjectIds","toWrite","obj","values","compressedBytes","push","staged","length","writeFilesParallel","transportHashes","Promise","all","map","p","insertObject","now","i","entries","found","CHUNK","start","slice","placeholders","rows","row","object_id","FS_WRITE_CONCURRENCY","tasks","cursor","workers","limit","Math","min","w","task","ID_PREFIX_BYTES","tupleId","parts","sha256Hex","join","slice","sourceFileId","sourceTool","absolutePath","contentHash","rawRecordId","ordinal","rawObjectId","String","sessionId","sourceSessionId","turnId","sourceTurnId","eventId","kind","messageId","sourceMsgId","blockId","messageOrEventId","toolCallId","sourceCallId","toolResultId","artifactId","key","projectId","sourceProjectId","importBatchId","startedAtIso","Math","random","emptyCounts","source_files_seen","source_files_imported","source_files_skipped","raw_records","sessions","turns","events","messages","content_blocks","tool_calls","tool_results","artifacts","edges","errors","startBatch","bundle","sourceTool","paths","startedAt","Date","toISOString","id","importBatchId","prepare","db","run","PROSA_PARSER_VERSION","JSON","stringify","batch_id","source_tool","parser_version","started_at","finishBatch","batch","counts","status","recordError","batchId","args","payloadObjectId","payload","undefined","putJson","sourceFileId","rawRecordId","kind","message","access","readFile","stat","writeFile","path","registerSourceFile","bundle","args","st","stat","absolutePath","size","mtime","toISOString","cheap","prepare","db","get","sourceTool","row","ensureSourceFilePreserved","alreadyKnown","buf","readFile","contentHash","sha256Hex","exact","objectId","preserveRawSourceBytes","id","sourceFileId","source_file_id","source_tool","path","file_kind","fileKind","size_bytes","content_hash","object_id","discovered_at","Date","workspace_hint","workspaceHint","run","bytes","sourceBytes","hash","blake3HexAsync","objectIdFromHash","stored","compression","compressBytes","storagePath","rawSourceStoragePath","join","ensureDir","dirname","fileExists","writeFile","existing","byteLength","hashHex","ext","filePath","access","clampLimit","value","opts","Math","max","min","fallback","sessionFilterWhere","filters","conds","params","sourceTool","push","sinceIso","untilIso","where","length","join","listSessions","bundle","limit","clampLimit","max","fallback","sql","db","prepare","all","countSessions","row","get","count","getSession","sessionId","rows","events","session","existsSync","createRequire","getErrorMessage","err","Error","message","String","createHash","existsSync","mkdir","rm","writeFile","path","SEARCH_INDEX_STATUS_COLUMNS","FTS5_TRIGGER_SQL","enableFts5Triggers","bundle","db","exec","disableFts5Triggers","getSearchIndexStatuses","ensureSearchIndexStatusRows","prepare","all","getSearchIndexStatus","engine","get","markIndexesAfterImport","options","changed","tantivy","status","updateSearchIndexStatus","sourceDocCount","countSearchDocs","indexedDocCount","indexed_doc_count","errorMessage","rebuildFts5Index","countFts5Docs","transactional","error","getErrorMessage","TANTIVY_SCHEMA_FIELDS","name","tokenizer","buildTantivySchema","builder","SchemaBuilder","field","addTextField","stored","tokenizerName","build","getCurrentTantivySchemaFingerprint","canonical","map","f","join","createHash","update","digest","tantivyIndexDirIsValid","dir","existsSync","path","makeTantivyDoc","row","doc","Document","addText","doc_id","entity_type","entity_id","session_id","project_id","timestamp","role","tool_name","canonical_tool_type","field_kind","text","SEARCH_DOCS_SELECT","rebuildTantivyIndex","prev","fingerprint","indexDirValid","paths","fingerprintMatches","schema_fingerprint","lastIndexedRowid","last_indexed_rowid","wantFullRebuild","overwrite","schema","index","rm","recursive","force","mkdir","Index","open","writer","select","addedDocCount","maxRowid","iterate","deleteDocumentsByTerm","addDocument","rowid","commit","reload","waitMergingThreads","countTantivyDocsBest","writeFile","JSON","stringify","source","built_at","Date","toISOString","mode","source_doc_count","schemaFingerprint","added","now","stmt","run","values","setClauses","params","undefined","push","n","require","createRequire","url","escapeFtsQuery","q","split","filter","t","length","map","replace","join","searchFullText","bundle","options","engine","searchTantivy","limit","clampLimit","max","fallback","sql","ftsQuery","raw","query","db","prepare","all","existsSync","paths","tantivy","Error","status","getSearchIndexStatus","queryText","trim","requireTantivy","index","Index","open","searcher","parseQuery","parseQueryLenient","undefined","text","result","search","snippets","SnippetGenerator","create","schema","setMaxNumChars","hits","hit","doc","docAddress","snippet","snippetFromDoc","getStoredText","renderedSnippet","fragment","highlightSnippet","highlighted","slice","doc_id","entity_type","entity_id","session_id","nullIfEmpty","timestamp","role","tool_name","field_kind","error","getErrorMessage","field","value","getFirst","Array","isArray","String","ranges","out","cursor","range","start","end","os","path","readFile","path","CANONICAL_TOOL_CALL_STATUSES","Set","normalizeSessionStatus","status","normalized","trim","toLowerCase","normalizeToolCallStatus","sourceTool","raw","has","readdir","path","discoverClaudeFiles","root","projectDirs","readdirSafe","project","isDirectory","projectRoot","path","join","name","walkProject","projectSlug","entries","entry","isFile","endsWith","filePath","isSubagent","parentSessionId","agentId","metaPath","subagentsDir","subagentEntries","sub","startsWith","slice","length","metaCandidate","metaExists","some","e","dir","readdir","withFileTypes","PREVIEW_MAX","compileClaude","bundle","root","options","logger","batch","startBatch","counts","emptyCounts","info","batch_id","file","discoverClaudeFiles","source_files_seen","debug","path","filePath","project_slug","projectSlug","is_subagent","isSubagent","fc","compileClaudeFile","addCounts","error","errors","warn","err","recordError","kind","message","getErrorMessage","payload","linkSubagentParents","finishBatch","db","exec","emptyFileCounts","source_files_imported","source_files_skipped","raw_records","sessions","turns","events","messages","content_blocks","tool_calls","tool_results","artifacts","edges","target","source","row","sourceFile","alreadyKnown","registerSourceFile","sourceTool","absolutePath","resolve","fileKind","workspaceHint","source_file_id","text","readFile","rawLines","split","lines","length","slice","meta","metaPath","readMeta","pending","rawRecords","session","blocks","toolCalls","Map","toolCallsList","toolResults","searchDocs","uuidToMessageId","objects","createPendingObjects","modelFirst","modelLast","messageOrdinal","sessionStartTs","sessionEndTs","cwdInitial","branchInitial","i","line","lineNo","ordinal","lineBytes","Buffer","from","rawObjectId","stageBytes","mimeType","encoding","parsed","parserStatus","JSON","parse","decodedObjectId","nativeId","uuid","rawRecordId","makeRawRecordId","push","raw_record_id","line_no","native_id","raw_object_id","decoded_json_object_id","parser_status","confidence","import_batch_id","ts","timestamp","cwd","gitBranch","sessionId","createSessionFromFirstRecord","parentSessionId","parentSid","makeSessionId","src_type","src_id","dst_type","dst_id","session_id","edge_type","parent_session_id_pending","basename","type","msgRole","role","inferRoleFromContent","msgOrdinal","messageId","makeMessageId","id","eventId","makeEventId","event_id","source_event_id","event_type","source_type","subtype","actor","payload_object_id","model","message_id","source_message_id","parent_message_id","parent_uuid","parentUuid","set","isSidechain","sourceToolAssistantUUID","content","block_id","blockId","block_type","text_object_id","text_inline","is_error","visibility","fullId","stageText","last","Array","isArray","bi","block","processContentBlock","progressType","data","attachment","isSnapshotUpdate","artifact_id","artifactId","snapshot","logical_path","object_id","mime_type","size_bytes","created_ts","m","has","parentId","get","start_ts","end_ts","cwd_initial","git_branch_initial","buildSearchDocs","flushPendingObjects","transactional","flushPending","sourceSid","composite","agentId","source_session_id","agent_role","agentType","agent_nickname","agentName","title","description","fallback","c","allToolResult","every","b","blockOrdinal","blkId","thinking","tu","sourceCallId","toolName","name","argsId","input","stageJson","command","inferCommandFromArgs","inferPathFromArgs","tcId","makeToolCallId","call","tool_call_id","source_call_id","tool_name","canonical_tool_type","canonicalToolType","args_object_id","query","timestamp_start","status","tr","tool_use_id","isError","stringifyOrNull","overflowId","matched","undefined","tool_result_id","makeToolResultId","normalizeToolCallStatus","exit_code","duration_ms","stdout_object_id","stderr_object_id","output_object_id","preview","lower","toLowerCase","startsWith","args","obj","cmd","file_path","absolute_path","value","stringify","blocksByMsg","list","blks","filter","map","join","trim","doc_id","entity_type","entity_id","field_kind","r","insertRaw","prepare","run","insertEvent","e","insertMessage","insertBlock","insertToolCall","insertToolResult","insertArtifact","a","insertEdge","insertSearch","d","readFile","path","readdir","path","discoverCodexSessions","root","walk","dir","entries","readdir","withFileTypes","entry","full","path","join","name","isDirectory","isFile","endsWith","PREVIEW_MAX","CODEX_PREPARE_CONCURRENCY","compileCodex","bundle","root","options","logger","batch","startBatch","counts","emptyCounts","info","batch_id","files","filePath","discoverCodexSessions","push","debug","path","source_files_seen","length","i","slice","processCodexBatch","linkSubagentParents","finishBatch","error","err","items","Promise","all","map","result","prepareCodexFile","prepared","fileCounts","prepareError","applyError","emptyFileCounts","item","transactional","db","applyCodexFile","errors","warn","recordError","kind","message","getErrorMessage","payload","addCounts","exec","source_files_imported","source_files_skipped","raw_records","sessions","turns","events","messages","content_blocks","tool_calls","tool_results","artifacts","edges","target","source","row","sourceFileRow","alreadyKnown","registerSourceFile","sourceTool","absolutePath","resolve","fileKind","source_file_id","text","readFile","rawLines","split","lines","pending","rawRecords","session","blocks","toolCalls","Map","toolCallsList","toolResults","searchDocs","objects","createPendingObjects","sessionStartTs","sessionEndTs","modelFirst","modelLast","messageOrdinal","turnOrdinal","line","lineNo","ordinal","lineBytes","Buffer","from","rawObjectId","stageBytes","mimeType","encoding","parsed","parserStatus","JSON","parse","decodedObjectId","nativeId","extractNativeId","rawRecordId","makeRawRecordId","raw_record_id","source_tool","record_kind","line_no","json_pointer","native_id","raw_object_id","decoded_json_object_id","parser_status","confidence","import_batch_id","ts","timestamp","type","meta","sourceSessionId","id","basename","sessionId","makeSessionId","sub","parseSubagent","parentSessionId","parent_thread_id","session_id","source_session_id","parent_session_id","is_subagent","agent_role","agent_nickname","title","start_ts","cwd_initial","cwd","git_branch_initial","git","branch","src_type","src_id","dst_type","dst_id","edge_type","tc","turnId","makeTurnId","turn_id","turn","source_turn_id","model","approval_policy","sandbox_policy","stringifyOrNull","effort","currentTurnId","ri","handleResponseItem","em","handleEventMsg","event_id","makeEventId","source_event_id","event_type","source_type","subtype","actor","payload_object_id","buildSearchDocs","flushPendingObjects","prep","flushPending","handleResponseItemMessage","ctx","payloadObjectId","nextMsgOrdinal","currentModel","role","mapMessageRole","msgOrdinal","messageId","makeMessageId","eventId","message_id","source_message_id","contentItems","Array","isArray","content","bi","blockType","block_id","blockId","block_type","text_object_id","text_inline","handleResponseItemFunctionCall","sourceCallId","call_id","toolName","name","toolCallId","makeToolCallId","argsObjectId","arguments","stageJson","command","inferCommandFromArgs","call","tool_call_id","source_call_id","tool_name","canonical_tool_type","canonicalToolType","args_object_id","inferPathFromArgs","query","timestamp_start","status","set","handleResponseItemFunctionCallOutput","outputText","output","outputObj","isRecord","isError","is_error","looksLikeError","matchedCall","get","undefined","tool_result_id","makeToolResultId","normalizeToolCallStatus","exit_code","duration_ms","stdout_object_id","stderr_object_id","output_object_id","preview","handleResponseItemPassthrough","RESPONSE_ITEM_HANDLERS","function_call","function_call_output","_bundle","handler","handleExecCommandEnd","stdoutId","stdout","stageText","stderrId","stderr","formatted_output","aggregated_output","exitCode","durationMs","duration","handlePatchApplyEnd","changes","Object","keys","artifact_id","artifactId","logical_path","object_id","mime_type","size_bytes","created_ts","handleMcpToolCallEnd","isMcpResultError","handleContextCompacted","handleEventMsgPassthrough","EVENT_MSG_HANDLERS","exec_command_end","patch_apply_end","mcp_tool_call_end","context_compacted","env","p","lower","toLowerCase","startsWith","args","obj","String","join","file_path","absolute_path","test","normalized","some","d","secs","nanos","Math","floor","value","stringify","subagent","thread_spawn","tso","parent","blocksByMsg","b","list","m","filter","doc_id","entity_type","entity_id","field_kind","c","r","insertRaw","prepare","run","insertSession","insertTurn","t","insertEvent","e","insertMessage","insertBlock","insertToolCall","insertToolResult","insertArtifact","a","insertEdge","insertSearch","path","Database","readdir","path","discoverCursorStores","root","workspaces","readdirSafe","ws","isDirectory","wsPath","path","join","name","agents","ag","dbPath","dbEntries","hasStoreDb","some","e","isFile","filePath","workspaceId","agentId","dir","readdir","withFileTypes","PREVIEW_MAX","compileCursor","bundle","root","options","logger","batch","startBatch","counts","emptyCounts","info","batch_id","store","discoverCursorStores","source_files_seen","debug","path","filePath","workspace_id","workspaceId","agent_id","agentId","fc","compileCursorStore","addCounts","error","errors","warn","err","recordError","kind","message","getErrorMessage","payload","finishBatch","emptyFileCounts","source_files_imported","source_files_skipped","raw_records","sessions","events","messages","content_blocks","tool_calls","tool_results","artifacts","edges","target","source","row","sourceFile","alreadyKnown","registerSourceFile","sourceTool","absolutePath","resolve","fileKind","workspaceHint","source_file_id","cdb","openCursorStoreReadOnly","pending","rawRecords","session","blocks","toolCalls","Map","toolCallsList","toolResults","searchDocs","objects","createPendingObjects","metaRow","prepare","get","meta","metaRawId","metaText","hexToUtf8","value","JSON","parse","metaObjId","stageBytes","Buffer","from","mimeType","encoding","makeRawRecordId","push","raw_record_id","ordinal","line_no","json_pointer","native_id","raw_object_id","decoded_json_object_id","parser_status","confidence","import_batch_id","record_kind","sourceSessionId","sessionPk","makeSessionId","startTs","createdAt","Date","toISOString","session_id","source_session_id","agent_role","mode","agent_nickname","name","title","start_ts","model","lastUsedModel","blobs","all","messageOrdinal","i","length","blob","blobObjectId","data","blobRawId","parsed","firstByte","looksJson","toString","id","stageJson","role","mapRole","messageId","makeMessageId","eventId","makeEventId","event_id","source_event_id","event_type","source_type","subtype","timestamp","actor","payload_object_id","message_id","source_message_id","content","pushTextBlock","Array","isArray","bi","item","processContentItem","reconcileUnfinishedToolCalls","buildSearchDocs","flushPendingObjects","transactional","db","flushPending","close","hex","blockType","text","rawRecordId","visibility","overflow","stageText","block_id","blockId","block_type","text_object_id","text_inline","slice","is_error","sessionId","t","type","sourceCallId","toolCallId","toolName","argsObjectId","args","tcId","makeToolCallId","call","tool_call_id","source_call_id","tool_name","canonical_tool_type","canonicalToolType","args_object_id","command","cwd","file_path","query","timestamp_start","status","set","stringifyOrNull","result","outputObjectId","isError","readIsError","matched","tool_result_id","makeToolResultId","normalizeToolCallStatus","output_object_id","preview","Database","fileMustExist","readonly","exp","experimental_content","lower","toLowerCase","startsWith","stringify","blocksByMsg","b","list","m","map","join","trim","doc_id","entity_type","entity_id","field_kind","tc","insertRaw","r","run","insertEvent","e","insertMsg","insertBlock","insertCall","c","insertResult","insertSearch","d","artifactId","readFile","path","readFile","readdir","path","discoverGeminiChats","root","entries","readdirSafe","entry","sort","a","b","name","localeCompare","isDirectory","projectRoot","readProjectRoot","path","join","chatsDir","chatEntries","c","isFile","startsWith","endsWith","filePath","projectDir","dir","text","readFile","replace","trim","readdir","withFileTypes","PREVIEW_MAX","compileGemini","bundle","root","options","logger","batch","startBatch","counts","emptyCounts","info","batch_id","file","discoverGeminiChats","source_files_seen","debug","path","filePath","project_dir","projectDir","project_root","projectRoot","fc","compileGeminiFile","addCounts","error","errors","warn","err","recordError","kind","message","getErrorMessage","payload","finishBatch","emptyFileCounts","source_files_imported","source_files_skipped","raw_records","sessions","events","messages","content_blocks","tool_calls","tool_results","artifacts","edges","target","source","row","sourceFile","alreadyKnown","registerSourceFile","sourceTool","absolutePath","resolve","fileKind","workspaceHint","source_file_id","text","readFile","parsed","JSON","parse","objects","createPendingObjects","fileObjectId","stageBytes","Buffer","from","mimeType","encoding","rootRawRecordId","makeRawRecordId","pending","rawRecords","raw_record_id","ordinal","line_no","json_pointer","native_id","sessionId","raw_object_id","decoded_json_object_id","parser_status","confidence","import_batch_id","record_kind","session","blocks","toolCallsList","toolResults","searchDocs","project","sourceSid","basename","sessionPk","makeSessionId","existingSession","prepare","db","get","session_id","source_session_id","sourceFileId","projectKey","projectHash","project_id","makeProjectId","canonical_path","source_project_id","start","startTime","end","lastUpdated","start_ts","end_ts","cwd_initial","title","summary","Array","isArray","i","length","msg","processMessage","buildSearchDocs","flushPendingObjects","transactional","flushPending","index","batchId","ts","timestamp","payloadId","stageJson","pointer","rawRecordId","push","id","type","role","messageId","makeMessageId","eventId","makeEventId","event_id","source_event_id","event_type","source_type","subtype","actor","payload_object_id","message_id","source_message_id","model","content","pushTextBlock","item","t","thoughts","th","subject","description","filter","Boolean","join","toolCalls","tc","processToolCall","blockOrdinal","blockType","visibility","overflowId","stageText","block_id","blockId","block_type","text_object_id","text_inline","slice","sourceCallId","toolName","name","toolCallId","makeToolCallId","argsObjectId","args","tool_call_id","source_call_id","tool_name","canonical_tool_type","canonicalToolType","args_object_id","command","cwd","dir_path","file_path","query","timestamp_start","status","normalizeToolCallStatus","isError","resultText","renderToolResultText","result","tool_result_id","makeToolResultId","is_error","output_object_id","preview","resultDisplay","rd","fileDiff","diffText","diffId","artifact_id","artifactId","logical_path","fileName","object_id","mime_type","size_bytes","created_ts","pushResultDisplayFileArtifact","field","suffix","objectId","byteLength","parts","r","functionResponse","response","rr","stringify","output","startsWith","blocksByMsg","Map","b","list","set","m","map","trim","doc_id","entity_type","entity_id","field_kind","tr","insertRaw","run","sha256Hex","Date","toISOString","insertEvent","e","insertMsg","insertBlock","insertCall","c","insertResult","insertArtifact","a","insertSearch","d","readFile","path","Database","access","readdir","path","discoverHermesSources","root","sessionsDir","path","resolve","stateDbCandidate","join","dirname","indexCandidate","entries","readdirSafe","jsonlFiles","jsonFiles","entry","isFile","full","name","endsWith","push","startsWith","stateDbPath","exists","indexPath","sort","filePath","access","dir","readdir","withFileTypes","PREVIEW_MAX","HIDDEN_BLOCK_ORDINAL_BASE","compileHermes","bundle","root","options","logger","batch","startBatch","counts","emptyCounts","info","batch_id","sources","discoverHermesSources","registered","candidates","stateDbPath","indexPath","jsonlFiles","length","jsonFiles","warn","sessionsDir","source_files_seen","sourceFile","registerHermesSourceFile","push","imported","debug","path","source_file_id","sourceFileId","readSqliteCandidates","error","recordHermesSourceError","err","filePath","readJsonlCandidate","readJsonCandidate","selection","selectCandidates","pending","buildPending","selected","rejected","filter","flushPendingObjects","objects","transactional","db","flushPending","raw_records","rawRecords","sessions","events","messages","content_blocks","blocks","tool_calls","toolCalls","tool_results","toolResults","artifacts","edges","finishBatch","errors","recordError","kind","message","getErrorMessage","payload","absolutePath","fileKind","row","alreadyKnown","registerSourceFile","sourceTool","resolve","source_files_skipped","source_files_imported","dbPath","Database","readonly","fileMustExist","prepare","all","messagesBySession","Map","list","get","session_id","set","map","session","source","sourceSessionId","id","model","systemPrompt","system_prompt","parentSessionId","parent_session_id","startTs","unixToIso","started_at","endTs","ended_at","status","end_reason","title","rawPayload","index","normalizeSqliteMessage","close","ordinal","sourceMessageId","String","role","content","decodeMaybeJson","timestamp","toolCallId","tool_call_id","toolName","tool_name","tokenCount","token_count","finishReason","finish_reason","reasoning","reasoningContent","reasoning_content","reasoningDetails","reasoning_details","codexReasoningItems","codex_reasoning_items","codexMessageItems","codex_message_items","lineNo","text","readFile","basename","lines","split","i","line","trim","parsed","JSON","parse","normalizeTranscriptMessage","firstString","at","replace","Array","isArray","platform","coerceTimestamp","session_start","last_updated","candidate","existing","values","importedSources","projects","searchDocs","createPendingObjects","candidateSourceIds","Set","has","objectId","stageJson","raw_record_id","makeRawRecordId","line_no","json_pointer","native_id","raw_object_id","decoded_json_object_id","parser_status","confidence","import_batch_id","record_kind","stageCandidate","stageRejectedCandidate","buildSearchDocs","payloadId","sessionPk","makeSessionId","sessionPayloadId","sessionRawId","projectId","makeProjectId","project_id","source_project_id","display_name","models","Boolean","source_session_id","is_subagent","start_ts","end_ts","model_first","model_last","normalizeSessionStatus","rawRecordId","messageId","makeMessageId","message_id","event_id","source_message_id","pushTextBlock","toolCallsBySourceId","stageMessage","batchId","makeEventId","source_event_id","event_type","source_type","subtype","actor","payload_object_id","mapRole","eventId","renderContentText","pushHiddenBlock","call","parseToolCalls","entries","sourceCallId","getToolCallSourceId","getToolName","args","getToolArgs","makeToolCallId","pendingCall","source_call_id","canonical_tool_type","canonicalToolType","args_object_id","command","stringField","query","timestamp_start","normalizeToolCallStatus","outputObjectId","stageText","normalizeToolResultStatus","tool_result_id","makeToolResultId","is_error","output_object_id","preview","slice","sessionId","blockType","visibility","block_id","blockId","block_type","text_object_id","text_inline","hidden","offset","value","projectIdBySession","block","join","doc_id","entity_type","entity_id","field_kind","result","insertRaw","record","run","existingSession","deleteSessionProjection","insertProject","project","Date","toISOString","insertSession","insertEvent","event","insertMessage","insertBlock","insertCall","insertResult","insertSearch","doc","Number","isFinite","isToolError","hasErrorMarker","test","some","isRecord","toLowerCase","type","trimmed","startsWith","item","stringify","decoded","fallback","fn","function","arguments","input","lowered","includes","key","find","mkdir","rm","writeFile","path","DuckDBConnection","PARQUET_TABLES","ANALYTICS_VIEWS","exportBundleParquet","options","snapshot","openBundleSnapshot","bundlePath","outDir","path","resolve","defaultOutDir","mkdir","recursive","files","Object","fromEntries","map","table","join","manifestPath","file","values","rm","force","connection","createDuckDbConnection","attachSqlite","dbPath","run","quoteIdentifier","sqlString","closeSync","manifest","exported_at","Date","toISOString","source_db","schema_version","schemaVersion","parser_version","parserVersion","tables","basename","rows","counts","writeFile","JSON","stringify","queryDuckDbParquet","parquetDir","createAnalyticsViews","reader","runAndReadAll","sql","columns","deduplicatedColumnNames","getRowObjectsJson","error","isMissingParquetError","Error","DuckDBConnection","create","getErrorMessage","bundle","openBundle","row","db","prepare","get","n","paths","parquet","closeBundle","value","replace","message","test","COMPILE_PROVIDERS","name","description","pathHelp","defaultSessionsPath","path","join","os","homedir","compile","compileCodex","compileClaude","compileGemini","compileCursor","compileHermes","getCompileProvider","source","provider","find","p","Error","resolveCompilePath","basePath","process","env","INIT_CWD","cwd","startsWith","slice","isAbsolute","resolve","runCompileImports","options","bundle","providers","logger","overwrite","importedAny","summaries","tantivy","tantivyError","fts5Error","sweep","db","prepare","run","changes","warn","batches_reaped","info","disableFts5Triggers","sourcePath","sessionsPath","providerLogger","child","source_tool","source_path","r","counts","source_files_imported","batch_id","batch","summary","batchId","push","onProviderComplete","shouldRebuildIndexes","changed","markIndexesAfterImport","rebuildFts5Index","error","getErrorMessage","err","status","rebuildTantivyIndex","indexedDocCount","indexed_doc_count","onTantivyComplete","enableFts5Triggers","exportCompileParquet","storePath","store_path","result","exportBundleParquet","bundlePath","outDir","manifestPath","tableCount","Object","keys","files","length","ANALYTICS_REPORTS","runAnalyticsReport","options","queryDuckDbParquet","parquetDir","sql","buildAnalyticsSql","report","filters","runAnalyticsReportFromBundle","stmt","bundle","db","prepare","rows","all","columns","map","column","name","dialect","buildSessionsSql","buildToolsSql","buildErrorsSql","buildModelsSql","buildProjectsSql","where","buildWhere","sourceFilter","timeFilter","projectFilter","sessionId","sqlString","sourcePathSubstring","escapeLike","limit","toolName","canonicalType","errorsOnly","category","rangeOverlapFilter","model","source","filtersSql","since","push","until","length","join","firstColumn","lastColumn","project","exact","like","op","active","filter","Boolean","value","Number","isFinite","undefined","clampLimit","max","fallback","replace","match","access","readFile","stat","path","VACUUM_THRESHOLD_PCT","WAL_WARN_BYTES","STUCK_BATCH_AGE_HOURS","RECENT_BATCHES_FOR_ERRORS","DEFAULT_DEEP_SAMPLE","shouldRecommendVacuum","freelistCount","pageCount","thresholdPct","pct","runDoctor","opts","storePath","path","resolve","defaultBundlePath","deep","deepSample","Math","max","filters","checks","filter","c","length","started","Date","now","results","push","result","matchesFilter","check","layout","checkBundleLayout","r","bundle","openError","canOpen","openBundle","err","status","message","getErrorMessage","hint","details","error","schemaResults","checkSchema","checkSqliteHealth","walResult","checkWalSize","liveCount","countSearchDocs","liveFts5","countFts5Docs","statuses","getSearchIndexStatuses","checkSearchIndexes","checkImports","checkData","checkIntegrityFull","checkCasSample","closeBundle","summary","pass","info","warn","fail","skipped","duration_ms","bundleOpened","some","f","startsWith","manifestParsed","dirStat","stat","catch","isDirectory","manifestPath","join","raw","readFile","JSON","parse","requiredFields","missing","version","schema_version","manifest","dbPath","dbStat","isFile","size","formatBytes","size_bytes","requiredDirs","key","rel","missingDirs","d","s","hash_alg","default_compression","dbVersion","currentSchemaVersion","db","manifestVersion","code","PROSA_SCHEMA_VERSION","parser_version","PROSA_PARSER_VERSION","quickRows","prepare","all","quickValue","Object","values","String","rows","fkRows","violations","slice","journalMode","get","journal_mode","pageSize","page_size","page_count","freelist_count","pctWaste","dbSizeBytes","toFixed","pct_waste","Number","db_size_bytes","walPath","paths","wal_size_bytes","liveDocCount","liveFts5Count","byEngine","Map","map","engine","fts5","fts5_count","source_count","statusDetails","error_message","tantivy","dirValid","tantivyIndexDirIsValid","currentFingerprint","getCurrentTantivySchemaFingerprint","fingerprintOk","schema_fingerprint","dir","stored","current","indexed_doc_count","drift","source_doc_count","live","diff","updated_at","stuckRows","batches","recentErrors","recentSamples","totalRecent","reduce","n","by_kind","samples","counts","sessions","messages","raw_records","objects","orphanSubagents","count","first","issues","sampleSize","hashMismatches","readErrors","checked","row","abs","storage_path","access","object_id","compressed","plain","decompressBytes","compression","recomputed","blake3HexAsync","mismatches","read_errors","units","v","i","listToolCalls","bundle","filters","conds","params","toolName","push","canonicalType","sessionId","errorsOnly","pathSubstring","sinceIso","untilIso","where","length","join","limit","clampLimit","max","fallback","toolCallSql","sql","db","prepare","all","artifactSql","DEFAULT_MAX_INLINE_BYTES","DEFAULT_MAX_ARGS_INLINE_BYTES","loadTranscript","bundle","sessionId","options","maxInlineBytes","maxArgsInlineBytes","session","db","prepare","get","messages","all","blocks","toolCalls","toolResults","resultByCallId","Map","r","tool_call_id","set","blocksByMessage","b","message_id","list","push","callsByMessage","unattached","c","turns","m","mblocks","sort","a","ordinal","renderedBlocks","renderBlock","mcalls","ta","timestamp_start","tb","renderedCalls","renderToolCall","messageId","role","model","timestamp","unattachedRendered","unattachedToolCalls","resolveBlockText","block","text_inline","text","textObjectId","text_object_id","unavailable","resolved","getText","Buffer","byteLength","resolveArgsText","argsObjectId","maxBytes","blockId","block_id","blockType","block_type","hidden","visibility","mimeType","mime_type","isError","is_error","argsInline","args_object_id","toolCallId","toolName","tool_name","canonicalToolType","canonical_tool_type","command","path","status","timestampStart","result","toolResultId","tool_result_id","exitCode","exit_code","durationMs","duration_ms","preview","stdoutObjectId","stdout_object_id","stderrObjectId","stderr_object_id","outputObjectId","output_object_id","exportSessionMarkdown","bundle","sessionId","transcript","loadTranscript","maxInlineBytes","Number","MAX_SAFE_INTEGER","Error","session","lines","title","trim","source_tool","source_session_id","push","session_id","start_ts","end_ts","cwd_initial","git_branch_initial","model_first","model_last","timeline_confidence","turn","turns","ts","timestamp","model","role","block","blocks","hidden","text","call","toolCalls","renderToolCallMarkdown","unattachedToolCalls","length","join","c","status","errFlag","result","isError","toolName","command","path","preview","DEFAULT_MAX_OUTPUT_LINES","formatTranscriptText","transcript","options","showThinking","maxOutputLines","out","push","renderHeader","turn","turns","renderTurn","unattachedToolCalls","length","call","renderToolCallLines","join","s","session","title","trim","source_tool","source_session_id","lines","session_id","start_ts","end_ts","model_first","model_last","timeline_confidence","ctx","meta","model","timestamp","metaSuffix","role","block","blocks","renderBlock","toolCalls","isThinking","hidden","blockType","charCount","text","textObjectId","split","map","l","indent","statusBits","status","result","isError","statusSuffix","toolName","command","path","argsInline","argsLines","shown","slice","argsObjectId","preview","previewLines","objectId","outputObjectId","stdoutObjectId","stderrObjectId","PROSA_MCP_INSTRUCTIONS","trim","INVESTIGATE_PRIOR_WORK_PROMPT","FIND_FILE_HISTORY_PROMPT","AUDIT_TOOL_FAILURES_PROMPT","randomUUID","http","McpServer","StdioServerTransport","StreamableHTTPServerTransport","z","CANONICAL_TOOL_TYPES","FIELD_KINDS","registerProsaTools","server","bundle","options","searchEngine","storePath","path","ensureStore","registerProsaPrompts","registerTool","title","description","inputSchema","query","z","string","min","engine","enum","optional","field_kind","limit","number","int","max","default","raw","boolean","describe","annotations","readOnlyHint","idempotentHint","withToolBundle","activeBundle","selectedEngine","hits","searchFullText","filtered","filter","hit","content","type","text","JSON","stringify","count","length","session_id","format","source","SOURCE_TOOLS","since","until","rows","listSessions","sourceTool","sinceIso","untilIso","md","exportSessionMarkdown","error","getErrorMessage","isError","detail","getSession","payload","session","tool_name","canonical_type","path_substring","errors_only","input","listToolCalls","sessionId","toolName","canonicalType","pathSubstring","errorsOnly","report","ANALYTICS_REPORTS","source_path_substring","project","category","model","filters","sourcePathSubstring","result","runAnalyticsReportFromBundle","artifact_id","row","db","prepare","get","objectId","text_object_id","object_id","getText","sessions_path","overwrite","destructiveHint","mode","search_index","getSearchIndexStatuses","runCompileImports","providers","getCompileProvider","COMPILE_PROVIDERS","sessionsPath","parquet","importedAny","exportCompileParquet","map","provider","source_path","sourcePath","batch_id","batchId","counts","imported_any","tantivy","indexed_doc_count","indexedDocCount","tantivy_error","tantivyError","fts5_error","fts5Error","out_dir","outDir","manifest_path","manifestPath","table_count","tableCount","files","fallbackBundle","fn","openOrInitBundle","closeBundle","registerPrompt","argsSchema","topic","messages","role","INVESTIGATE_PRIOR_WORK_PROMPT","replace","FIND_FILE_HISTORY_PROMPT","AUDIT_TOOL_FAILURES_PROMPT","listenMcpStdioServer","bundle","options","server","createMcpServer","searchEngine","storePath","transport","StdioServerTransport","connect","close","safeClose","listenMcpServer","mcpPath","path","sessions","Map","httpServer","http","createServer","req","res","handleRequest","catch","error","writeError","Promise","resolve","reject","once","listen","port","host","removeListener","url","err","entry","values","clear","startsWith","writeHead","end","method","Allow","headerSessionId","headers","sessionId","Array","isArray","undefined","get","openSession","bodyText","readBody","body","length","safeJsonParse","store","StreamableHTTPServerTransport","sessionIdGenerator","randomUUID","onsessioninitialized","id","set","onsessionclosed","e","delete","McpServer","name","version","PROSA_PARSER_VERSION","instructions","PROSA_MCP_INSTRUCTIONS","registerProsaTools","ensureStore","chunks","on","chunk","push","Buffer","concat","toString","text","JSON","parse","o","headersSent","stringify","jsonrpc","code","message","getErrorMessage"]}
|