@tekmidian/pai 0.66.0 → 0.66.2
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/{aibroker-client-B8c42Lh8.mjs → aibroker-client-CHEEvJZW.mjs} +2 -2
- package/dist/{aibroker-client-C5Fw7DNz.mjs → aibroker-client-Dfv7j1Od.mjs} +3 -3
- package/dist/{aibroker-client-C5Fw7DNz.mjs.map → aibroker-client-Dfv7j1Od.mjs.map} +1 -1
- package/dist/{auto-route-o0BOsXn7.mjs → auto-route-BnizyALK.mjs} +65 -4
- package/dist/auto-route-BnizyALK.mjs.map +1 -0
- package/dist/auto-route-D6fW1Q8z.mjs +3 -0
- package/dist/{chain-D4PuQ2c-.mjs → chain-D5876UQX.mjs} +3 -4
- package/dist/{chain-D4PuQ2c-.mjs.map → chain-D5876UQX.mjs.map} +1 -1
- package/dist/cli/index.mjs +18 -23
- package/dist/cli/index.mjs.map +1 -1
- package/dist/cli/program.mjs +17 -22
- package/dist/{config-BbLFD7Uf.mjs → config-C-LiGlop.mjs} +2 -2
- package/dist/{config-BbLFD7Uf.mjs.map → config-C-LiGlop.mjs.map} +1 -1
- package/dist/{config-YinjgXEJ.mjs → config-DKIA7wgF.mjs} +1 -1
- package/dist/{context-handover-cache-pkHzmL3c.mjs → context-handover-cache-9PGvXRIw.mjs} +984 -10
- package/dist/context-handover-cache-9PGvXRIw.mjs.map +1 -0
- package/dist/daemon/index.mjs +17 -19
- package/dist/daemon/index.mjs.map +1 -1
- package/dist/daemon-BUgNvMUh.mjs +5029 -0
- package/dist/daemon-BUgNvMUh.mjs.map +1 -0
- package/dist/daemon-DL0eglMJ.mjs +18 -0
- package/dist/daemon-mcp/index.mjs +15 -10
- package/dist/daemon-mcp/index.mjs.map +1 -1
- package/dist/{embeddings-CcscYWwk.mjs → embeddings-CEBGrzwu.mjs} +1 -1
- package/dist/{embeddings-Bx3q0QOY.mjs → embeddings-DOLZnT1X.mjs} +1 -1
- package/dist/{embeddings-Bx3q0QOY.mjs.map → embeddings-DOLZnT1X.mjs.map} +1 -1
- package/dist/{env-JNEIrQWg.mjs → env-DiolswKQ.mjs} +1 -1
- package/dist/{env-JNEIrQWg.mjs.map → env-DiolswKQ.mjs.map} +1 -1
- package/dist/factory-DrBg24UT.mjs +8 -0
- package/dist/factory-Ypf8r0fK.mjs +2892 -0
- package/dist/factory-Ypf8r0fK.mjs.map +1 -0
- package/dist/{fallback-B5svk75f.mjs → fallback-D51R4shY.mjs} +27 -13
- package/dist/fallback-D51R4shY.mjs.map +1 -0
- package/dist/{chunker-BH4i-F2b.mjs → helpers-CZsi_49C.mjs} +221 -2
- package/dist/helpers-CZsi_49C.mjs.map +1 -0
- package/dist/hooks/block-sleep-poll.mjs.map +2 -2
- package/dist/hooks/load-project-context.mjs.map +2 -2
- package/dist/hooks/worker-guard.mjs +5 -0
- package/dist/hooks/worker-guard.mjs.map +2 -2
- package/dist/hooks/worker-status-line.mjs +1 -0
- package/dist/hooks/worker-status-line.mjs.map +2 -2
- package/dist/index.mjs +6 -7
- package/dist/{ipc-client-D16Xw6Uo.mjs → ipc-client-BLYX51nG.mjs} +2 -2
- package/dist/{ipc-client-D16Xw6Uo.mjs.map → ipc-client-BLYX51nG.mjs.map} +1 -1
- package/dist/main-resolver-BYgP86C1.mjs +7 -0
- package/dist/{main-resolver-DPPwHNtn.mjs → main-resolver-kVkMJZUD.mjs} +6 -6
- package/dist/{main-resolver-DPPwHNtn.mjs.map → main-resolver-kVkMJZUD.mjs.map} +1 -1
- package/dist/{migrate-BD7D8EEh.mjs → migrate-Bq0esMOa.mjs} +2 -2
- package/dist/{migrate-BD7D8EEh.mjs.map → migrate-Bq0esMOa.mjs.map} +1 -1
- package/dist/{pai-marker-D1MMswkz.mjs → pai-marker-DXVpFsYz.mjs} +1 -1
- package/dist/{pai-marker-D1MMswkz.mjs.map → pai-marker-DXVpFsYz.mjs.map} +1 -1
- package/dist/{planner-EJPZnnif.mjs → planner-D5yt0EfA.mjs} +10 -7
- package/dist/{planner-EJPZnnif.mjs.map → planner-D5yt0EfA.mjs.map} +1 -1
- package/dist/postgres-BmLr0MUm.mjs +5 -0
- package/dist/{postgres-Ceqsa64C.mjs → postgres-D3xc2RB4.mjs} +364 -9
- package/dist/postgres-D3xc2RB4.mjs.map +1 -0
- package/dist/{program-DSETzrWg.mjs → program-DIXRtAFy.mjs} +80 -70
- package/dist/program-DIXRtAFy.mjs.map +1 -0
- package/dist/{query-feedback-BIaZTTFO.mjs → query-feedback-B7FYE4JR.mjs} +1 -1
- package/dist/{query-feedback-BIaZTTFO.mjs.map → query-feedback-B7FYE4JR.mjs.map} +1 -1
- package/dist/{reranker-DKv80KO5.mjs → reranker-3lnggwgq.mjs} +1 -1
- package/dist/{reranker-DKv80KO5.mjs.map → reranker-3lnggwgq.mjs.map} +1 -1
- package/dist/{reranker-CFiEzHQu.mjs → reranker-CZ2mP4cf.mjs} +1 -1
- package/dist/router-BK-hFeQ6.mjs +3 -0
- package/dist/{router-a5G7q8_3.mjs → router-BaTbc9VX.mjs} +2 -2
- package/dist/{router-a5G7q8_3.mjs.map → router-BaTbc9VX.mjs.map} +1 -1
- package/dist/{run-Z4akoa8G.mjs → run-CLYTOm0x.mjs} +764 -25
- package/dist/run-CLYTOm0x.mjs.map +1 -0
- package/dist/{run-env-DRcp7A8K.mjs → run-env-Bnmf6bRI.mjs} +2 -2
- package/dist/{run-env-DRcp7A8K.mjs.map → run-env-Bnmf6bRI.mjs.map} +1 -1
- package/dist/{runtime-paths-CHTg3ywb.mjs → runtime-paths-D3FKAm69.mjs} +1 -1
- package/dist/{runtime-paths-CHTg3ywb.mjs.map → runtime-paths-D3FKAm69.mjs.map} +1 -1
- package/dist/{search-BOSphCJ1.mjs → search-CNAGTiJP.mjs} +2 -2
- package/dist/{search-BOSphCJ1.mjs.map → search-CNAGTiJP.mjs.map} +1 -1
- package/dist/{sources-CijVso3n.mjs → sources-CM2g-CLT.mjs} +2 -2
- package/dist/{sources-CijVso3n.mjs.map → sources-CM2g-CLT.mjs.map} +1 -1
- package/dist/{stop-words-BdQuaE9K.mjs → stop-words-DtxaTWU_.mjs} +1 -1
- package/dist/{stop-words-BdQuaE9K.mjs.map → stop-words-DtxaTWU_.mjs.map} +1 -1
- package/dist/{utils-C9HsYDpO.mjs → utils-DddRwMsG.mjs} +2 -2
- package/dist/{utils-C9HsYDpO.mjs.map → utils-DddRwMsG.mjs.map} +1 -1
- package/dist/{zettelkasten-CtGHQWPU.mjs → zettelkasten-BhZMvmoK.mjs} +149 -7
- package/dist/zettelkasten-BhZMvmoK.mjs.map +1 -0
- package/dist/zettelkasten-BwV1pluL.mjs +5 -0
- package/docs/commands/worker.md +2 -0
- package/package.json +1 -1
- package/src/hooks/ts/lib/worker-guard.test.ts +12 -0
- package/src/hooks/ts/lib/worker-guard.ts +9 -0
- package/dist/async-C2Bm_Lal.mjs +0 -300
- package/dist/async-C2Bm_Lal.mjs.map +0 -1
- package/dist/auto-route-o0BOsXn7.mjs.map +0 -1
- package/dist/chunker-BH4i-F2b.mjs.map +0 -1
- package/dist/clusters-BCtD3fbe.mjs +0 -169
- package/dist/clusters-BCtD3fbe.mjs.map +0 -1
- package/dist/context-handover-cache-pkHzmL3c.mjs.map +0 -1
- package/dist/daemon-BEoVgVfJ.mjs +0 -1741
- package/dist/daemon-BEoVgVfJ.mjs.map +0 -1
- package/dist/daemon-DPAYU9hp.mjs +0 -19
- package/dist/detector-BEPFsINR.mjs +0 -3
- package/dist/detector-BRTtAWrM.mjs +0 -65
- package/dist/detector-BRTtAWrM.mjs.map +0 -1
- package/dist/factory-CNpPQQ-5.mjs +0 -249
- package/dist/factory-CNpPQQ-5.mjs.map +0 -1
- package/dist/factory-DY7x73mE.mjs +0 -3
- package/dist/fallback-B5svk75f.mjs.map +0 -1
- package/dist/federation-db-BTyoufBh.mjs +0 -139
- package/dist/federation-db-BTyoufBh.mjs.map +0 -1
- package/dist/federation-db-HfIFc7FG.mjs +0 -3
- package/dist/helpers-BRCJg0G3.mjs +0 -223
- package/dist/helpers-BRCJg0G3.mjs.map +0 -1
- package/dist/indexer-backend-DFF2FrYx.mjs +0 -5
- package/dist/indexer-backend-isSLg6yE.mjs +0 -1
- package/dist/kg-entity-DCOcsVFD.mjs +0 -29
- package/dist/kg-entity-DCOcsVFD.mjs.map +0 -1
- package/dist/latent-ideas-wwAXquGe.mjs +0 -191
- package/dist/latent-ideas-wwAXquGe.mjs.map +0 -1
- package/dist/link-boost-CnI7UVMJ.mjs +0 -34
- package/dist/link-boost-CnI7UVMJ.mjs.map +0 -1
- package/dist/main-resolver-BKz_OuEh.mjs +0 -7
- package/dist/merge-2gqRPFu2.mjs +0 -3
- package/dist/merge-DgU9OgZy.mjs +0 -6
- package/dist/merge-DgU9OgZy.mjs.map +0 -1
- package/dist/module-paths-DdRzbkUI.mjs +0 -44
- package/dist/module-paths-DdRzbkUI.mjs.map +0 -1
- package/dist/neighborhood-2FsmzoxG.mjs +0 -114
- package/dist/neighborhood-2FsmzoxG.mjs.map +0 -1
- package/dist/note-context-De63k8na.mjs +0 -106
- package/dist/note-context-De63k8na.mjs.map +0 -1
- package/dist/postgres-Ceqsa64C.mjs.map +0 -1
- package/dist/program-DSETzrWg.mjs.map +0 -1
- package/dist/query-feedback-B_iigYj-.mjs +0 -3
- package/dist/registry-db-C7voqML9.mjs +0 -213
- package/dist/registry-db-C7voqML9.mjs.map +0 -1
- package/dist/registry-db-JHPhA8vF.mjs +0 -3
- package/dist/registry-postgres-nOfyBSIW.mjs +0 -795
- package/dist/registry-postgres-nOfyBSIW.mjs.map +0 -1
- package/dist/registry-sqlite-DrCW1aRK.mjs +0 -593
- package/dist/registry-sqlite-DrCW1aRK.mjs.map +0 -1
- package/dist/router-CXUGsv85.mjs +0 -3
- package/dist/run-Z4akoa8G.mjs.map +0 -1
- package/dist/search-Bf3Kub3F.mjs +0 -3
- package/dist/server-DgmAHyFK.mjs +0 -403
- package/dist/server-DgmAHyFK.mjs.map +0 -1
- package/dist/session-keepalive-BDhytXEo.mjs +0 -582
- package/dist/session-keepalive-BDhytXEo.mjs.map +0 -1
- package/dist/sqlite-CqsTy6xo.mjs +0 -936
- package/dist/sqlite-CqsTy6xo.mjs.map +0 -1
- package/dist/state-DW8zdweW.mjs +0 -3
- package/dist/state-HyjqTihC.mjs +0 -76
- package/dist/state-HyjqTihC.mjs.map +0 -1
- package/dist/themes-CTaOj3e1.mjs +0 -148
- package/dist/themes-CTaOj3e1.mjs.map +0 -1
- package/dist/tools-BcOKPBtg.mjs +0 -1489
- package/dist/tools-BcOKPBtg.mjs.map +0 -1
- package/dist/tools-C-_l0o8Z.mjs +0 -6
- package/dist/trace-CtV0RO6n.mjs +0 -137
- package/dist/trace-CtV0RO6n.mjs.map +0 -1
- package/dist/utils-BrX9FLeK.mjs +0 -3
- package/dist/vault-indexer-BG1sEVyM.mjs +0 -537
- package/dist/vault-indexer-BG1sEVyM.mjs.map +0 -1
- package/dist/wakeup-D8n33hYV.mjs +0 -335
- package/dist/wakeup-D8n33hYV.mjs.map +0 -1
- package/dist/work-queue-worker-4tLa5gpQ.mjs +0 -567
- package/dist/work-queue-worker-4tLa5gpQ.mjs.map +0 -1
- package/dist/work-queue-worker-rFZvTO3p.mjs +0 -11
- package/dist/zettelkasten-CtGHQWPU.mjs.map +0 -1
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"registry-sqlite-DrCW1aRK.mjs","names":[],"sources":["../src/storage/sqlite/registry-merge.ts","../src/storage/registry-sqlite.ts"],"sourcesContent":["/**\n * planMerge/applyMerge — fold one registered project into another without\n * losing anything, against a raw better-sqlite3 Database.\n *\n * Moved out of src/registry/merge.ts (which keeps only the pure MergePlan\n * type and MergeError class) so that the one place in the codebase touching\n * better-sqlite3 for this operation is under src/storage/. Wrapped by\n * SQLiteRegistryBackend.planProjectMerge/applyProjectMerge\n * (../registry-sqlite.ts).\n *\n * The registry accumulates rows that describe the same work twice: a project\n * registered under two spellings of one directory, a vault-notes twin of a code\n * project, a slug that collided and got a `-1`. Measured 2026-08-04 there were\n * six such rows, and between them they carried ten sessions.\n *\n * Those sessions are the only thing of value on the losing row, which is why\n * `archive` is the wrong remedy and a plain DELETE is worse. `pai project health`\n * suggested archiving for every unhealthy row, and archiving a duplicate leaves\n * the sessions attached to a row nobody will look at again.\n *\n * FIVE tables reference a project, and `PRAGMA foreign_keys` is 0 on this\n * database — so deleting a project row does not fail, it silently orphans rows in\n * sessions, project_tags, aliases, compaction_log and links. Anything that merges\n * by hand will miss at least one of them. Hence one function.\n *\n * Two constraints shape the implementation:\n *\n * sessions UNIQUE (project_id, number) — incoming sessions must be renumbered,\n * or the insert collides with the\n * target's own numbering\n * links UNIQUE (session_id, target_project_id)\n * project_tags PRIMARY KEY (project_id, tag_id)\n * — both can already hold the row we are\n * about to point at the target\n */\n\nimport type { Database } from \"better-sqlite3\";\nimport { MergeError, type MergePlan } from \"../../registry/merge.js\";\n\n/**\n * What a merge would do, without doing it.\n *\n * Built as a plan first because the session renumbering is the part a reader will\n * not predict, and printing \"0001 -> 0016\" is the difference between a command\n * that can be trusted and one that has to be taken on faith.\n */\nexport function planMerge(db: Database, fromSlug: string, intoSlug: string): MergePlan {\n if (fromSlug === intoSlug) {\n throw new MergeError(`Cannot merge ${fromSlug} into itself.`);\n }\n\n const from = db\n .prepare(\"SELECT id, slug FROM projects WHERE slug = ?\")\n .get(fromSlug) as { id: number; slug: string } | undefined;\n const into = db\n .prepare(\"SELECT id, slug FROM projects WHERE slug = ?\")\n .get(intoSlug) as { id: number; slug: string } | undefined;\n\n if (!from) throw new MergeError(`No project with slug \"${fromSlug}\".`);\n if (!into) throw new MergeError(`No project with slug \"${intoSlug}\".`);\n\n // Where the target's numbering currently ends. Incoming sessions continue from\n // there rather than keeping their own numbers, which would collide.\n const maxRow = db\n .prepare(\"SELECT COALESCE(MAX(number), 0) AS n FROM sessions WHERE project_id = ?\")\n .get(into.id) as { n: number };\n let next = maxRow.n;\n\n const incoming = db\n .prepare(\"SELECT id, number FROM sessions WHERE project_id = ? ORDER BY number ASC\")\n .all(from.id) as { id: number; number: number }[];\n\n const sessions = incoming.map((s) => ({ id: s.id, from: s.number, to: ++next }));\n\n const count = (sql: string, ...args: unknown[]): number =>\n (db.prepare(sql).get(...args) as { n: number }).n;\n\n // The losing slug becomes an alias of the winner, so anything that resolved by\n // that name keeps working — including a human who remembers the old name.\n const aliasTaken =\n count(\"SELECT COUNT(*) AS n FROM aliases WHERE alias = ?\", from.slug) > 0 ||\n count(\"SELECT COUNT(*) AS n FROM projects WHERE slug = ?\", from.slug) > 1;\n\n return {\n fromId: from.id,\n fromSlug: from.slug,\n intoId: into.id,\n intoSlug: into.slug,\n sessions,\n tags: count(\"SELECT COUNT(*) AS n FROM project_tags WHERE project_id = ?\", from.id),\n aliases: count(\"SELECT COUNT(*) AS n FROM aliases WHERE project_id = ?\", from.id),\n compactions: count(\n \"SELECT COUNT(*) AS n FROM compaction_log WHERE project_id = ?\",\n from.id\n ),\n links: count(\"SELECT COUNT(*) AS n FROM links WHERE target_project_id = ?\", from.id),\n aliasToAdd: aliasTaken ? undefined : from.slug,\n };\n}\n\n/**\n * Apply a plan. One transaction: either the whole row is folded in or nothing is.\n *\n * A half-merged project is the worst outcome available here — sessions moved but\n * the row still present, or the row gone and its tags orphaned — and with foreign\n * keys off nothing would complain.\n */\nexport function applyMerge(db: Database, plan: MergePlan): void {\n const run = db.transaction(() => {\n // Sessions, one at a time because each gets its own new number.\n const move = db.prepare(\n \"UPDATE sessions SET project_id = ?, number = ? WHERE id = ?\"\n );\n for (const s of plan.sessions) move.run(plan.intoId, s.to, s.id);\n\n // Tags: OR IGNORE because (project_id, tag_id) is the primary key and the\n // target may already carry the same tag.\n db.prepare(\n `INSERT OR IGNORE INTO project_tags (project_id, tag_id)\n SELECT ?, tag_id FROM project_tags WHERE project_id = ?`\n ).run(plan.intoId, plan.fromId);\n db.prepare(\"DELETE FROM project_tags WHERE project_id = ?\").run(plan.fromId);\n\n // Existing aliases of the loser now point at the winner.\n db.prepare(\"UPDATE aliases SET project_id = ? WHERE project_id = ?\").run(\n plan.intoId,\n plan.fromId\n );\n\n db.prepare(\"UPDATE compaction_log SET project_id = ? WHERE project_id = ?\").run(\n plan.intoId,\n plan.fromId\n );\n\n // Links: same collision shape as tags, plus one extra case — a session that\n // linked to the loser may now be linking to its own project, which is not a\n // relationship worth keeping.\n db.prepare(\n `UPDATE OR IGNORE links SET target_project_id = ? WHERE target_project_id = ?`\n ).run(plan.intoId, plan.fromId);\n db.prepare(\"DELETE FROM links WHERE target_project_id = ?\").run(plan.fromId);\n db.prepare(\n `DELETE FROM links WHERE target_project_id = ?\n AND session_id IN (SELECT id FROM sessions WHERE project_id = ?)`\n ).run(plan.intoId, plan.intoId);\n\n // And keep the old name resolvable.\n if (plan.aliasToAdd) {\n db.prepare(\"INSERT OR IGNORE INTO aliases (alias, project_id) VALUES (?, ?)\").run(\n plan.aliasToAdd,\n plan.intoId\n );\n }\n\n db.prepare(\"DELETE FROM projects WHERE id = ?\").run(plan.fromId);\n });\n\n run();\n}\n","/**\n * SQLiteRegistryBackend — wraps the existing better-sqlite3 registry.db\n * (src/registry/db.ts, src/registry/merge.ts) behind the RegistryBackend\n * interface.\n *\n * Thin adapter: every method is the same SQL the 64 direct callers run today,\n * just relocated here and wrapped in Promise.resolve(...) so the interface can\n * be async (matching StorageBackend, and Postgres in unit 4) without changing\n * SQLite behaviour.\n */\n\nimport type { Database } from \"better-sqlite3\";\nimport { planMerge, applyMerge } from \"./sqlite/registry-merge.js\";\nimport type {\n RegistryBackend,\n Project,\n ProjectWithSessionStats,\n Session,\n SessionWithProject,\n NewProject,\n NewProjectWithSlugRetry,\n NewSession,\n NewCompactionLogEntry,\n ListProjectsOptions,\n ListProjectsByPathLengthOptions,\n ListProjectsWithStatsOptions,\n ListNamedProjectsOptions,\n ListSessionsOptions,\n ListSessionsForProjectOptions,\n ProjectType,\n ProjectStatus,\n SessionStatus,\n LinkType,\n MergePlan,\n} from \"./registry-interface.js\";\n\nexport class SQLiteRegistryBackend implements RegistryBackend {\n readonly backendType = \"sqlite\" as const;\n\n private db: Database;\n\n constructor(db: Database) {\n this.db = db;\n }\n\n /** Expose the raw better-sqlite3 Database handle for not-yet-converted callers. */\n getRawDb(): Database {\n return this.db;\n }\n\n async close(): Promise<void> {\n try {\n this.db.close();\n } catch {\n // ignore\n }\n }\n\n async resetRegistry(): Promise<void> {\n const run = this.db.transaction(() => {\n this.db.prepare(\"DELETE FROM links\").run();\n this.db.prepare(\"DELETE FROM compaction_log\").run();\n this.db.prepare(\"DELETE FROM session_tags\").run();\n this.db.prepare(\"DELETE FROM project_tags\").run();\n this.db.prepare(\"DELETE FROM aliases\").run();\n this.db.prepare(\"DELETE FROM sessions\").run();\n this.db.prepare(\"DELETE FROM tags\").run();\n this.db.prepare(\"DELETE FROM projects\").run();\n });\n run();\n }\n\n // -------------------------------------------------------------------------\n // Projects — reads\n // -------------------------------------------------------------------------\n\n async getProjectById(id: number): Promise<Project | null> {\n const row = this.db.prepare(\"SELECT * FROM projects WHERE id = ?\").get(id) as Project | undefined;\n return row ?? null;\n }\n\n async getProjectBySlug(\n slug: string,\n opts: { caseInsensitive?: boolean; excludeId?: number } = {}\n ): Promise<Project | null> {\n let sql = opts.caseInsensitive\n ? \"SELECT * FROM projects WHERE lower(slug) = lower(?)\"\n : \"SELECT * FROM projects WHERE slug = ?\";\n const params: unknown[] = [slug];\n if (opts.excludeId !== undefined) {\n sql += \" AND id != ?\";\n params.push(opts.excludeId);\n }\n const row = this.db.prepare(sql).get(...params) as Project | undefined;\n return row ?? null;\n }\n\n async getProjectByAlias(\n alias: string,\n opts: { caseInsensitive?: boolean } = {}\n ): Promise<Project | null> {\n const sql = opts.caseInsensitive\n ? \"SELECT p.* FROM projects p JOIN aliases a ON a.project_id = p.id WHERE lower(a.alias) = lower(?)\"\n : \"SELECT p.* FROM projects p JOIN aliases a ON a.project_id = p.id WHERE a.alias = ?\";\n const row = this.db.prepare(sql).get(alias) as Project | undefined;\n return row ?? null;\n }\n\n async getProjectByRootPath(rootPath: string, opts: { excludeId?: number } = {}): Promise<Project | null> {\n let sql = \"SELECT * FROM projects WHERE root_path = ?\";\n const params: unknown[] = [rootPath];\n if (opts.excludeId !== undefined) {\n sql += \" AND id != ?\";\n params.push(opts.excludeId);\n }\n const row = this.db.prepare(sql).get(...params) as Project | undefined;\n return row ?? null;\n }\n\n async getProjectByEncodedDir(encodedDir: string, opts: { excludeId?: number } = {}): Promise<Project | null> {\n let sql = \"SELECT * FROM projects WHERE encoded_dir = ?\";\n const params: unknown[] = [encodedDir];\n if (opts.excludeId !== undefined) {\n sql += \" AND id != ?\";\n params.push(opts.excludeId);\n }\n const row = this.db.prepare(sql).get(...params) as Project | undefined;\n return row ?? null;\n }\n\n async findProjectByCwdPrefix(cwd: string): Promise<Project | null> {\n const row = this.db\n .prepare(\n `SELECT * FROM projects WHERE status = 'active' AND ? LIKE root_path || '%'\n ORDER BY length(root_path) DESC LIMIT 1`\n )\n .get(cwd) as Project | undefined;\n return row ?? null;\n }\n\n async listProjects(opts: ListProjectsOptions = {}): Promise<Project[]> {\n const where: string[] = [];\n const params: unknown[] = [];\n\n if (opts.status) {\n where.push(\"p.status = ?\");\n params.push(opts.status);\n }\n if (opts.excludeArchived) {\n where.push(\"p.status != 'archived'\");\n }\n if (opts.tagName) {\n where.push(\n \"p.id IN (SELECT pt.project_id FROM project_tags pt JOIN tags t ON pt.tag_id = t.id WHERE t.name = ?)\"\n );\n params.push(opts.tagName);\n }\n\n let sql = \"SELECT p.* FROM projects p\";\n if (where.length) sql += \" WHERE \" + where.join(\" AND \");\n\n switch (opts.orderBy) {\n case \"updated_desc\":\n sql += \" ORDER BY p.updated_at DESC\";\n break;\n case \"slug\":\n sql += \" ORDER BY p.slug ASC\";\n break;\n case \"id\":\n sql += \" ORDER BY p.id\";\n break;\n case \"status_updated\":\n default:\n sql += \" ORDER BY p.status ASC, p.updated_at DESC\";\n break;\n }\n if (opts.limit !== undefined) {\n sql += \" LIMIT ?\";\n params.push(opts.limit);\n }\n\n return this.db.prepare(sql).all(...params) as Project[];\n }\n\n async listProjectsByPathLengthDesc(opts: ListProjectsByPathLengthOptions = {}): Promise<Project[]> {\n const where = opts.excludeArchived ? \"WHERE status != 'archived'\" : \"\";\n return this.db\n .prepare(`SELECT * FROM projects ${where} ORDER BY LENGTH(root_path) DESC`)\n .all() as Project[];\n }\n\n async listProjectsWithSessionStats(\n opts: ListProjectsWithStatsOptions = {}\n ): Promise<ProjectWithSessionStats[]> {\n const where: string[] = [];\n const params: unknown[] = [];\n\n if (opts.status) {\n where.push(\"p.status = ?\");\n params.push(opts.status);\n }\n if (opts.tagId !== undefined) {\n where.push(\"p.id IN (SELECT project_id FROM project_tags WHERE tag_id = ?)\");\n params.push(opts.tagId);\n }\n\n let sql = `\n SELECT p.*,\n (SELECT COUNT(*) FROM sessions s WHERE s.project_id = p.id) AS session_count,\n (SELECT MAX(s.created_at) FROM sessions s WHERE s.project_id = p.id) AS last_active\n FROM projects p\n `;\n if (where.length) sql += \" WHERE \" + where.join(\" AND \");\n sql +=\n opts.orderBy === \"updated_desc\"\n ? \" ORDER BY p.updated_at DESC\"\n : \" ORDER BY p.status ASC, p.updated_at DESC\";\n\n return this.db.prepare(sql).all(...params) as ProjectWithSessionStats[];\n }\n\n async listNamedProjects(\n opts: ListNamedProjectsOptions = {}\n ): Promise<Array<ProjectWithSessionStats & { name: string | null }>> {\n const join = opts.includeUnnamed ? \"LEFT JOIN\" : \"JOIN\";\n const sql = `\n SELECT p.*, a.alias AS name,\n (SELECT COUNT(*) FROM sessions s WHERE s.project_id = p.id) AS session_count,\n (SELECT MAX(s.created_at) FROM sessions s WHERE s.project_id = p.id) AS last_active\n FROM projects p\n ${join} aliases a ON a.project_id = p.id\n WHERE p.status = 'active'\n ORDER BY p.updated_at DESC\n `;\n return this.db.prepare(sql).all() as Array<ProjectWithSessionStats & { name: string | null }>;\n }\n\n async searchProjects(query: string, limit = 20): Promise<Project[]> {\n const q = `%${query}%`;\n return this.db\n .prepare(\n `SELECT * FROM projects WHERE slug LIKE ? OR display_name LIKE ? OR root_path LIKE ?\n ORDER BY updated_at DESC LIMIT ?`\n )\n .all(q, q, q, limit) as Project[];\n }\n\n async countProjects(opts: { status?: ProjectStatus } = {}): Promise<number> {\n const sql = opts.status\n ? \"SELECT COUNT(*) AS n FROM projects WHERE status = ?\"\n : \"SELECT COUNT(*) AS n FROM projects\";\n const row = opts.status\n ? (this.db.prepare(sql).get(opts.status) as { n: number })\n : (this.db.prepare(sql).get() as { n: number });\n return row.n;\n }\n\n async getMostRecentProjectUpdatedAt(): Promise<number | null> {\n const row = this.db.prepare(\"SELECT updated_at FROM projects ORDER BY updated_at DESC LIMIT 1\").get() as\n | { updated_at: number }\n | undefined;\n return row?.updated_at ?? null;\n }\n\n async countChildProjects(parentId: number): Promise<number> {\n return (this.db.prepare(\"SELECT COUNT(*) AS n FROM projects WHERE parent_id = ?\").get(parentId) as {\n n: number;\n }).n;\n }\n\n async findSiblingProjectsBySlugPattern(\n excludeProjectId: number,\n slug: string,\n limit = 3\n ): Promise<Array<{ slug: string; root_path: string; session_count: number }>> {\n return this.db\n .prepare(\n `SELECT p.slug, p.root_path, COUNT(s.id) AS session_count\n FROM projects p LEFT JOIN sessions s ON s.project_id = p.id\n WHERE p.id != ? AND (p.slug = ? OR p.slug LIKE ? || '-%' OR ? LIKE p.slug || '-%')\n GROUP BY p.id HAVING session_count > 0 ORDER BY session_count DESC LIMIT ?`\n )\n .all(excludeProjectId, slug, slug, slug, limit) as Array<{\n slug: string;\n root_path: string;\n session_count: number;\n }>;\n }\n\n // -------------------------------------------------------------------------\n // Projects — writes\n // -------------------------------------------------------------------------\n\n async createProject(input: NewProject): Promise<Project> {\n const type: ProjectType = input.type ?? \"local\";\n const status: ProjectStatus = input.status ?? \"active\";\n const result = this.db\n .prepare(\n `INSERT INTO projects (slug, display_name, root_path, encoded_dir, type, status, created_at, updated_at)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?)`\n )\n .run(\n input.slug,\n input.displayName,\n input.rootPath,\n input.encodedDir,\n type,\n status,\n input.createdAt,\n input.updatedAt\n );\n return (await this.getProjectById(result.lastInsertRowid as number))!;\n }\n\n async createProjectWithSlugRetry(\n input: NewProjectWithSlugRetry\n ): Promise<{ id: number; slug: string; created: boolean }> {\n let slug = input.baseSlug;\n let attempt = 0;\n const insert = this.db.prepare(\n `INSERT OR IGNORE INTO projects (slug, display_name, root_path, encoded_dir, type, status, created_at, updated_at)\n VALUES (?, ?, ?, ?, 'local', 'active', ?, ?)`\n );\n\n // eslint-disable-next-line no-constant-condition\n while (true) {\n const info = insert.run(\n slug,\n input.displayName,\n input.rootPath,\n input.encodedDir,\n input.createdAt,\n input.updatedAt\n );\n if (info.changes > 0) {\n return { id: info.lastInsertRowid as number, slug, created: true };\n }\n\n const existing = this.db.prepare(\"SELECT id FROM projects WHERE root_path = ?\").get(input.rootPath) as\n | { id: number }\n | undefined;\n if (existing) {\n return { id: existing.id, slug, created: false };\n }\n\n attempt++;\n slug = `${input.baseSlug}-${attempt}`;\n }\n }\n\n async updateProjectPath(\n id: number,\n patch: { rootPath?: string; encodedDir?: string },\n updatedAt?: number\n ): Promise<void> {\n const sets: string[] = [];\n const params: unknown[] = [];\n if (patch.rootPath !== undefined) {\n sets.push(\"root_path = ?\");\n params.push(patch.rootPath);\n }\n if (patch.encodedDir !== undefined) {\n sets.push(\"encoded_dir = ?\");\n params.push(patch.encodedDir);\n }\n if (updatedAt !== undefined) {\n sets.push(\"updated_at = ?\");\n params.push(updatedAt);\n }\n if (!sets.length) return;\n params.push(id);\n this.db.prepare(`UPDATE projects SET ${sets.join(\", \")} WHERE id = ?`).run(...params);\n }\n\n async updateProjectStatus(\n id: number,\n status: ProjectStatus,\n opts: { archivedAt?: number | null; updatedAt?: number; requireCurrentStatus?: ProjectStatus } = {}\n ): Promise<void> {\n const sets: string[] = [\"status = ?\"];\n const params: unknown[] = [status];\n if (opts.archivedAt !== undefined) {\n sets.push(\"archived_at = ?\");\n params.push(opts.archivedAt);\n }\n if (opts.updatedAt !== undefined) {\n sets.push(\"updated_at = ?\");\n params.push(opts.updatedAt);\n }\n let sql = `UPDATE projects SET ${sets.join(\", \")} WHERE id = ?`;\n params.push(id);\n if (opts.requireCurrentStatus) {\n sql += \" AND status = ?\";\n params.push(opts.requireCurrentStatus);\n }\n this.db.prepare(sql).run(...params);\n }\n\n async updateProjectDisplayName(id: number, displayName: string, updatedAt?: number): Promise<void> {\n if (updatedAt !== undefined) {\n this.db\n .prepare(\"UPDATE projects SET display_name = ?, updated_at = ? WHERE id = ?\")\n .run(displayName, updatedAt, id);\n } else {\n this.db.prepare(\"UPDATE projects SET display_name = ? WHERE id = ?\").run(displayName, id);\n }\n }\n\n async updateProjectType(id: number, type: ProjectType, updatedAt?: number): Promise<void> {\n if (updatedAt !== undefined) {\n this.db.prepare(\"UPDATE projects SET type = ?, updated_at = ? WHERE id = ?\").run(type, updatedAt, id);\n } else {\n this.db.prepare(\"UPDATE projects SET type = ? WHERE id = ?\").run(type, id);\n }\n }\n\n async updateProjectSessionConfig(id: number, config: string | null, updatedAt?: number): Promise<void> {\n if (updatedAt !== undefined) {\n this.db\n .prepare(\"UPDATE projects SET session_config = ?, updated_at = ? WHERE id = ?\")\n .run(config, updatedAt, id);\n } else {\n this.db.prepare(\"UPDATE projects SET session_config = ? WHERE id = ?\").run(config, id);\n }\n }\n\n async updateProjectClaudeNotesDir(id: number, dir: string | null, updatedAt?: number): Promise<void> {\n if (updatedAt !== undefined) {\n this.db\n .prepare(\"UPDATE projects SET claude_notes_dir = ?, updated_at = ? WHERE id = ?\")\n .run(dir, updatedAt, id);\n } else {\n this.db.prepare(\"UPDATE projects SET claude_notes_dir = ? WHERE id = ?\").run(dir, id);\n }\n }\n\n async updateProjectObsidianLink(id: number, link: string | null, updatedAt?: number): Promise<void> {\n if (updatedAt !== undefined) {\n this.db\n .prepare(\"UPDATE projects SET obsidian_link = ?, updated_at = ? WHERE id = ?\")\n .run(link, updatedAt, id);\n } else {\n this.db.prepare(\"UPDATE projects SET obsidian_link = ? WHERE id = ?\").run(link, id);\n }\n }\n\n async updateProjectSlug(id: number, slug: string, updatedAt: number): Promise<void> {\n this.db.prepare(\"UPDATE projects SET slug = ?, updated_at = ? WHERE id = ?\").run(slug, updatedAt, id);\n }\n\n async reassignProjectParent(fromParentId: number, toParentId: number): Promise<number> {\n return this.db.prepare(\"UPDATE projects SET parent_id = ? WHERE parent_id = ?\").run(toParentId, fromParentId)\n .changes;\n }\n\n async deleteProject(id: number): Promise<void> {\n this.db.prepare(\"DELETE FROM projects WHERE id = ?\").run(id);\n }\n\n async deleteProjectCascade(id: number): Promise<void> {\n const run = this.db.transaction(() => {\n this.db.prepare(\"DELETE FROM links WHERE target_project_id = ?\").run(id);\n this.db\n .prepare(\"DELETE FROM links WHERE session_id IN (SELECT id FROM sessions WHERE project_id = ?)\")\n .run(id);\n this.db.prepare(\"DELETE FROM compaction_log WHERE project_id = ?\").run(id);\n this.db.prepare(\"DELETE FROM project_tags WHERE project_id = ?\").run(id);\n this.db.prepare(\"DELETE FROM aliases WHERE project_id = ?\").run(id);\n this.db.prepare(\"DELETE FROM sessions WHERE project_id = ?\").run(id);\n this.db.prepare(\"DELETE FROM projects WHERE id = ?\").run(id);\n });\n run();\n }\n\n // -------------------------------------------------------------------------\n // Tags\n // -------------------------------------------------------------------------\n\n async listTagsForProject(projectId: number): Promise<string[]> {\n const rows = this.db\n .prepare(\n \"SELECT t.name FROM tags t JOIN project_tags pt ON pt.tag_id = t.id WHERE pt.project_id = ? ORDER BY t.name\"\n )\n .all(projectId) as Array<{ name: string }>;\n return rows.map((r) => r.name);\n }\n\n async listAllTags(): Promise<Array<{ id: number; name: string }>> {\n return this.db.prepare(\"SELECT id, name FROM tags ORDER BY name\").all() as Array<{\n id: number;\n name: string;\n }>;\n }\n\n async upsertTag(name: string): Promise<number> {\n this.db.prepare(\"INSERT OR IGNORE INTO tags (name) VALUES (?)\").run(name);\n return (this.db.prepare(\"SELECT id FROM tags WHERE name = ?\").get(name) as { id: number }).id;\n }\n\n async addProjectTag(projectId: number, tagId: number): Promise<void> {\n this.db.prepare(\"INSERT INTO project_tags (project_id, tag_id) VALUES (?, ?)\").run(projectId, tagId);\n }\n\n async projectHasTag(projectId: number, tagId: number): Promise<boolean> {\n return !!this.db.prepare(\"SELECT 1 FROM project_tags WHERE project_id = ? AND tag_id = ?\").get(projectId, tagId);\n }\n\n async deleteProjectTag(projectId: number, tagId: number): Promise<void> {\n this.db.prepare(\"DELETE FROM project_tags WHERE project_id = ? AND tag_id = ?\").run(projectId, tagId);\n }\n\n async reassignProjectTag(fromProjectId: number, toProjectId: number, tagId: number): Promise<void> {\n this.db\n .prepare(\"UPDATE project_tags SET project_id = ? WHERE project_id = ? AND tag_id = ?\")\n .run(toProjectId, fromProjectId, tagId);\n }\n\n async listProjectTagIds(projectId: number): Promise<number[]> {\n const rows = this.db.prepare(\"SELECT tag_id FROM project_tags WHERE project_id = ?\").all(projectId) as Array<{\n tag_id: number;\n }>;\n return rows.map((r) => r.tag_id);\n }\n\n async countProjectTagsForProject(projectId: number): Promise<number> {\n return (this.db.prepare(\"SELECT COUNT(*) AS n FROM project_tags WHERE project_id = ?\").get(projectId) as {\n n: number;\n }).n;\n }\n\n async copyProjectTags(fromProjectId: number, toProjectId: number): Promise<void> {\n this.db\n .prepare(\n \"INSERT OR IGNORE INTO project_tags (project_id, tag_id) SELECT ?, tag_id FROM project_tags WHERE project_id = ?\"\n )\n .run(toProjectId, fromProjectId);\n }\n\n async deleteProjectTagsForProject(projectId: number): Promise<void> {\n this.db.prepare(\"DELETE FROM project_tags WHERE project_id = ?\").run(projectId);\n }\n\n // -------------------------------------------------------------------------\n // Aliases\n // -------------------------------------------------------------------------\n\n async resolveAlias(alias: string): Promise<number | null> {\n const row = this.db.prepare(\"SELECT project_id FROM aliases WHERE alias = ?\").get(alias) as\n | { project_id: number }\n | undefined;\n return row?.project_id ?? null;\n }\n\n async listAliasesForProject(projectId: number): Promise<string[]> {\n const rows = this.db.prepare(\"SELECT alias FROM aliases WHERE project_id = ? ORDER BY alias\").all(\n projectId\n ) as Array<{ alias: string }>;\n return rows.map((r) => r.alias);\n }\n\n async addAlias(alias: string, projectId: number): Promise<void> {\n this.db.prepare(\"INSERT INTO aliases (alias, project_id) VALUES (?, ?)\").run(alias, projectId);\n }\n\n async removeAlias(alias: string): Promise<void> {\n this.db.prepare(\"DELETE FROM aliases WHERE alias = ?\").run(alias);\n }\n\n async countAliasesForProject(projectId: number): Promise<number> {\n return (this.db.prepare(\"SELECT COUNT(*) AS n FROM aliases WHERE project_id = ?\").get(projectId) as {\n n: number;\n }).n;\n }\n\n async moveProjectAliases(fromProjectId: number, toProjectId: number): Promise<void> {\n this.db.prepare(\"UPDATE aliases SET project_id = ? WHERE project_id = ?\").run(toProjectId, fromProjectId);\n }\n\n async reassignAlias(alias: string, toProjectId: number): Promise<void> {\n this.db.prepare(\"UPDATE aliases SET project_id = ? WHERE alias = ?\").run(toProjectId, alias);\n }\n\n async listAliasMap(): Promise<Array<{ alias: string; slug: string; root_path: string }>> {\n return this.db\n .prepare(\n `SELECT a.alias AS alias, p.slug AS slug, p.root_path AS root_path\n FROM aliases a JOIN projects p ON p.id = a.project_id WHERE p.status != 'archived'`\n )\n .all() as Array<{ alias: string; slug: string; root_path: string }>;\n }\n\n // -------------------------------------------------------------------------\n // Sessions\n // -------------------------------------------------------------------------\n\n async getSessionById(id: number): Promise<Session | null> {\n const row = this.db.prepare(\"SELECT * FROM sessions WHERE id = ?\").get(id) as Session | undefined;\n return row ?? null;\n }\n\n async getSessionByNumber(projectId: number, number: number): Promise<Session | null> {\n const row = this.db.prepare(\"SELECT * FROM sessions WHERE project_id = ? AND number = ?\").get(\n projectId,\n number\n ) as Session | undefined;\n return row ?? null;\n }\n\n async getLatestSessionForProject(projectId: number): Promise<Session | null> {\n const row = this.db\n .prepare(\"SELECT * FROM sessions WHERE project_id = ? ORDER BY number DESC LIMIT 1\")\n .get(projectId) as Session | undefined;\n return row ?? null;\n }\n\n async getMaxSessionNumber(projectId: number): Promise<number> {\n const row = this.db.prepare(\"SELECT COALESCE(MAX(number), 0) AS n FROM sessions WHERE project_id = ?\").get(\n projectId\n ) as { n: number };\n return row.n;\n }\n\n async listSessionsForProject(\n projectId: number,\n opts: ListSessionsForProjectOptions = {}\n ): Promise<Session[]> {\n const orderBy = opts.orderBy === \"created_desc\" ? \"created_at DESC\" : \"number ASC\";\n let sql = `SELECT * FROM sessions WHERE project_id = ? ORDER BY ${orderBy}`;\n const params: unknown[] = [projectId];\n if (opts.limit !== undefined) {\n sql += \" LIMIT ?\";\n params.push(opts.limit);\n }\n return this.db.prepare(sql).all(...params) as Session[];\n }\n\n async listSessions(opts: ListSessionsOptions = {}): Promise<SessionWithProject[]> {\n const where: string[] = [];\n const params: unknown[] = [];\n if (opts.projectId !== undefined) {\n where.push(\"s.project_id = ?\");\n params.push(opts.projectId);\n }\n if (opts.status) {\n where.push(\"s.status = ?\");\n params.push(opts.status);\n }\n let sql = `\n SELECT s.*, p.slug AS project_slug, p.display_name AS project_name\n FROM sessions s JOIN projects p ON p.id = s.project_id\n `;\n if (where.length) sql += \" WHERE \" + where.join(\" AND \");\n sql += \" ORDER BY s.date DESC, s.number DESC\";\n const limit = opts.limit ?? 20;\n sql += ` LIMIT ${limit}`;\n return this.db.prepare(sql).all(...params) as SessionWithProject[];\n }\n\n async findSessionByFilename(projectId: number, filename: string): Promise<{ id: number } | null> {\n const row = this.db\n .prepare(\"SELECT id FROM sessions WHERE project_id = ? AND filename = ? LIMIT 1\")\n .get(projectId, filename) as { id: number } | undefined;\n return row ?? null;\n }\n\n async sessionNumberTaken(projectId: number, number: number): Promise<boolean> {\n return !!this.db.prepare(\"SELECT 1 FROM sessions WHERE project_id = ? AND number = ? LIMIT 1\").get(\n projectId,\n number\n );\n }\n\n async createSession(input: NewSession): Promise<Session> {\n const status = input.status ?? \"completed\";\n const result = this.db\n .prepare(\n `INSERT INTO sessions (project_id, number, date, slug, title, filename, status, created_at)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?)`\n )\n .run(input.projectId, input.number, input.date, input.slug, input.title, input.filename, status, input.createdAt);\n return (await this.getSessionById(result.lastInsertRowid as number))!;\n }\n\n async upsertSessionIfAbsent(input: NewSession): Promise<boolean> {\n const existing = this.db\n .prepare(\"SELECT id FROM sessions WHERE project_id = ? AND number = ?\")\n .get(input.projectId, input.number);\n if (existing) return false;\n\n const status = input.status ?? \"completed\";\n this.db\n .prepare(\n `INSERT INTO sessions (project_id, number, date, slug, title, filename, status, created_at)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?)`\n )\n .run(input.projectId, input.number, input.date, input.slug, input.title, input.filename, status, input.createdAt);\n return true;\n }\n\n async updateSessionMeta(\n id: number,\n patch: { slug?: string; title?: string; filename?: string }\n ): Promise<void> {\n const sets: string[] = [];\n const params: unknown[] = [];\n if (patch.slug !== undefined) {\n sets.push(\"slug = ?\");\n params.push(patch.slug);\n }\n if (patch.title !== undefined) {\n sets.push(\"title = ?\");\n params.push(patch.title);\n }\n if (patch.filename !== undefined) {\n sets.push(\"filename = ?\");\n params.push(patch.filename);\n }\n if (!sets.length) return;\n params.push(id);\n this.db.prepare(`UPDATE sessions SET ${sets.join(\", \")} WHERE id = ?`).run(...params);\n }\n\n async updateSessionNumber(id: number, number: number, opts: { filename?: string } = {}): Promise<void> {\n if (opts.filename !== undefined) {\n this.db.prepare(\"UPDATE sessions SET number = ?, filename = ? WHERE id = ?\").run(number, opts.filename, id);\n } else {\n this.db.prepare(\"UPDATE sessions SET number = ? WHERE id = ?\").run(number, id);\n }\n }\n\n async updateSessionFilename(id: number, filename: string): Promise<void> {\n this.db.prepare(\"UPDATE sessions SET filename = ? WHERE id = ?\").run(filename, id);\n }\n\n async updateSessionStatus(id: number, status: SessionStatus, opts: { closedAt?: number } = {}): Promise<void> {\n if (opts.closedAt !== undefined) {\n this.db.prepare(\"UPDATE sessions SET status = ?, closed_at = ? WHERE id = ?\").run(status, opts.closedAt, id);\n } else {\n this.db.prepare(\"UPDATE sessions SET status = ? WHERE id = ?\").run(status, id);\n }\n }\n\n async moveSessionToProject(id: number, projectId: number, opts: { number?: number } = {}): Promise<void> {\n if (opts.number !== undefined) {\n this.db.prepare(\"UPDATE sessions SET project_id = ?, number = ? WHERE id = ?\").run(\n projectId,\n opts.number,\n id\n );\n } else {\n this.db.prepare(\"UPDATE sessions SET project_id = ? WHERE id = ?\").run(projectId, id);\n }\n }\n\n async deleteSession(id: number): Promise<void> {\n this.db.prepare(\"DELETE FROM sessions WHERE id = ?\").run(id);\n }\n\n async backfillFoldedSession(keepId: number, dropId: number): Promise<void> {\n this.db\n .prepare(\n `UPDATE sessions SET\n claude_session_id = COALESCE(claude_session_id,\n (SELECT claude_session_id FROM sessions WHERE id = ?)),\n token_count = COALESCE(token_count,\n (SELECT token_count FROM sessions WHERE id = ?)),\n closed_at = COALESCE(closed_at,\n (SELECT closed_at FROM sessions WHERE id = ?)),\n status = CASE WHEN status = 'open'\n AND (SELECT status FROM sessions WHERE id = ?) != 'open'\n THEN (SELECT status FROM sessions WHERE id = ?)\n ELSE status END\n WHERE id = ?`\n )\n .run(dropId, dropId, dropId, dropId, dropId, keepId);\n }\n\n async countSessionsForProject(projectId: number): Promise<number> {\n return (this.db.prepare(\"SELECT COUNT(*) AS n FROM sessions WHERE project_id = ?\").get(projectId) as {\n n: number;\n }).n;\n }\n\n async countSessions(): Promise<number> {\n return (this.db.prepare(\"SELECT COUNT(*) AS n FROM sessions\").get() as { n: number }).n;\n }\n\n async getMostRecentSessionDate(projectId: number): Promise<string | null> {\n const row = this.db\n .prepare(\"SELECT date FROM sessions WHERE project_id = ? ORDER BY date DESC LIMIT 1\")\n .get(projectId) as { date: string } | undefined;\n return row?.date ?? null;\n }\n\n async getMostRecentSessionCreatedAt(): Promise<number | null> {\n const row = this.db.prepare(\"SELECT created_at FROM sessions ORDER BY created_at DESC LIMIT 1\").get() as\n | { created_at: number }\n | undefined;\n return row?.created_at ?? null;\n }\n\n // -------------------------------------------------------------------------\n // Session tags\n // -------------------------------------------------------------------------\n\n async listSessionTagIds(sessionId: number): Promise<number[]> {\n const rows = this.db.prepare(\"SELECT tag_id FROM session_tags WHERE session_id = ?\").all(sessionId) as Array<{\n tag_id: number;\n }>;\n return rows.map((r) => r.tag_id);\n }\n\n async sessionHasTag(sessionId: number, tagId: number): Promise<boolean> {\n return !!this.db.prepare(\"SELECT 1 FROM session_tags WHERE session_id = ? AND tag_id = ?\").get(\n sessionId,\n tagId\n );\n }\n\n async addSessionTag(sessionId: number, tagId: number): Promise<void> {\n this.db.prepare(\"INSERT INTO session_tags (session_id, tag_id) VALUES (?, ?)\").run(sessionId, tagId);\n }\n\n async deleteSessionTag(sessionId: number, tagId: number): Promise<void> {\n this.db.prepare(\"DELETE FROM session_tags WHERE session_id = ? AND tag_id = ?\").run(sessionId, tagId);\n }\n\n async reassignSessionTag(fromSessionId: number, toSessionId: number, tagId: number): Promise<void> {\n this.db\n .prepare(\"UPDATE session_tags SET session_id = ? WHERE session_id = ? AND tag_id = ?\")\n .run(toSessionId, fromSessionId, tagId);\n }\n\n async listTagsForSession(sessionId: number): Promise<string[]> {\n const rows = this.db\n .prepare(\n \"SELECT t.name FROM tags t JOIN session_tags st ON st.tag_id = t.id WHERE st.session_id = ? ORDER BY t.name\"\n )\n .all(sessionId) as Array<{ name: string }>;\n return rows.map((r) => r.name);\n }\n\n // -------------------------------------------------------------------------\n // Links\n // -------------------------------------------------------------------------\n\n async addLink(input: {\n sessionId: number;\n targetProjectId: number;\n linkType: LinkType;\n createdAt: number;\n }): Promise<void> {\n this.db\n .prepare(\"INSERT INTO links (session_id, target_project_id, link_type, created_at) VALUES (?, ?, ?, ?)\")\n .run(input.sessionId, input.targetProjectId, input.linkType, input.createdAt);\n }\n\n async listLinksForSession(sessionId: number): Promise<Array<{ id: number; target_project_id: number }>> {\n return this.db.prepare(\"SELECT id, target_project_id FROM links WHERE session_id = ?\").all(\n sessionId\n ) as Array<{ id: number; target_project_id: number }>;\n }\n\n async listLinksForProject(projectId: number): Promise<Array<{ id: number; session_id: number }>> {\n return this.db.prepare(\"SELECT id, session_id FROM links WHERE target_project_id = ?\").all(\n projectId\n ) as Array<{ id: number; session_id: number }>;\n }\n\n async linkExists(sessionId: number, targetProjectId: number): Promise<boolean> {\n return !!this.db.prepare(\"SELECT 1 FROM links WHERE session_id = ? AND target_project_id = ? LIMIT 1\").get(\n sessionId,\n targetProjectId\n );\n }\n\n async deleteLink(id: number): Promise<void> {\n this.db.prepare(\"DELETE FROM links WHERE id = ?\").run(id);\n }\n\n async deleteLinksTargetingProject(projectId: number): Promise<void> {\n this.db.prepare(\"DELETE FROM links WHERE target_project_id = ?\").run(projectId);\n }\n\n async deleteLinksFromProjectSessions(projectId: number): Promise<void> {\n this.db\n .prepare(\"DELETE FROM links WHERE session_id IN (SELECT id FROM sessions WHERE project_id = ?)\")\n .run(projectId);\n }\n\n async retargetLink(id: number, targetProjectId: number): Promise<void> {\n this.db.prepare(\"UPDATE links SET target_project_id = ? WHERE id = ?\").run(targetProjectId, id);\n }\n\n async moveLinkToSession(id: number, sessionId: number): Promise<void> {\n this.db.prepare(\"UPDATE links SET session_id = ? WHERE id = ?\").run(sessionId, id);\n }\n\n async reassignLinksTarget(fromProjectId: number, toProjectId: number): Promise<void> {\n this.db\n .prepare(\"UPDATE OR IGNORE links SET target_project_id = ? WHERE target_project_id = ?\")\n .run(toProjectId, fromProjectId);\n }\n\n async countLinksForProject(projectId: number): Promise<number> {\n return (this.db.prepare(\"SELECT COUNT(*) AS n FROM links WHERE target_project_id = ?\").get(projectId) as {\n n: number;\n }).n;\n }\n\n async deleteSelfLinksForProject(projectId: number): Promise<void> {\n this.db\n .prepare(\n `DELETE FROM links WHERE target_project_id = ?\n AND session_id IN (SELECT id FROM sessions WHERE project_id = ?)`\n )\n .run(projectId, projectId);\n }\n\n // -------------------------------------------------------------------------\n // Compaction log\n // -------------------------------------------------------------------------\n\n async appendCompactionLog(entry: NewCompactionLogEntry): Promise<void> {\n this.db\n .prepare(\n `INSERT INTO compaction_log (project_id, session_id, trigger, files_written, token_count, created_at)\n VALUES (?, ?, ?, ?, ?, ?)`\n )\n .run(entry.projectId, entry.sessionId, entry.trigger, entry.filesWritten, entry.tokenCount, entry.createdAt);\n }\n\n async countCompactionLogsForProject(projectId: number): Promise<number> {\n return (this.db.prepare(\"SELECT COUNT(*) AS n FROM compaction_log WHERE project_id = ?\").get(projectId) as {\n n: number;\n }).n;\n }\n\n async moveCompactionLogsByProject(fromProjectId: number, toProjectId: number): Promise<number> {\n return this.db\n .prepare(\"UPDATE compaction_log SET project_id = ? WHERE project_id = ?\")\n .run(toProjectId, fromProjectId).changes;\n }\n\n async moveCompactionLogsBySession(fromSessionId: number, toSessionId: number): Promise<void> {\n this.db\n .prepare(\"UPDATE compaction_log SET session_id = ? WHERE session_id = ?\")\n .run(toSessionId, fromSessionId);\n }\n\n async deleteCompactionLogsForProject(projectId: number): Promise<void> {\n this.db.prepare(\"DELETE FROM compaction_log WHERE project_id = ?\").run(projectId);\n }\n\n // -------------------------------------------------------------------------\n // Project merge\n // -------------------------------------------------------------------------\n\n async planProjectMerge(fromSlug: string, intoSlug: string): Promise<MergePlan> {\n return planMerge(this.db, fromSlug, intoSlug);\n }\n\n async applyProjectMerge(plan: MergePlan): Promise<void> {\n applyMerge(this.db, plan);\n }\n}\n"],"mappings":"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"}
|
package/dist/router-CXUGsv85.mjs
DELETED