@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,593 +0,0 @@
|
|
|
1
|
-
import { t as MergeError } from "./merge-DgU9OgZy.mjs";
|
|
2
|
-
|
|
3
|
-
//#region src/storage/sqlite/registry-merge.ts
|
|
4
|
-
/**
|
|
5
|
-
* What a merge would do, without doing it.
|
|
6
|
-
*
|
|
7
|
-
* Built as a plan first because the session renumbering is the part a reader will
|
|
8
|
-
* not predict, and printing "0001 -> 0016" is the difference between a command
|
|
9
|
-
* that can be trusted and one that has to be taken on faith.
|
|
10
|
-
*/
|
|
11
|
-
function planMerge(db, fromSlug, intoSlug) {
|
|
12
|
-
if (fromSlug === intoSlug) throw new MergeError(`Cannot merge ${fromSlug} into itself.`);
|
|
13
|
-
const from = db.prepare("SELECT id, slug FROM projects WHERE slug = ?").get(fromSlug);
|
|
14
|
-
const into = db.prepare("SELECT id, slug FROM projects WHERE slug = ?").get(intoSlug);
|
|
15
|
-
if (!from) throw new MergeError(`No project with slug "${fromSlug}".`);
|
|
16
|
-
if (!into) throw new MergeError(`No project with slug "${intoSlug}".`);
|
|
17
|
-
let next = db.prepare("SELECT COALESCE(MAX(number), 0) AS n FROM sessions WHERE project_id = ?").get(into.id).n;
|
|
18
|
-
const sessions = db.prepare("SELECT id, number FROM sessions WHERE project_id = ? ORDER BY number ASC").all(from.id).map((s) => ({
|
|
19
|
-
id: s.id,
|
|
20
|
-
from: s.number,
|
|
21
|
-
to: ++next
|
|
22
|
-
}));
|
|
23
|
-
const count = (sql, ...args) => db.prepare(sql).get(...args).n;
|
|
24
|
-
const aliasTaken = count("SELECT COUNT(*) AS n FROM aliases WHERE alias = ?", from.slug) > 0 || count("SELECT COUNT(*) AS n FROM projects WHERE slug = ?", from.slug) > 1;
|
|
25
|
-
return {
|
|
26
|
-
fromId: from.id,
|
|
27
|
-
fromSlug: from.slug,
|
|
28
|
-
intoId: into.id,
|
|
29
|
-
intoSlug: into.slug,
|
|
30
|
-
sessions,
|
|
31
|
-
tags: count("SELECT COUNT(*) AS n FROM project_tags WHERE project_id = ?", from.id),
|
|
32
|
-
aliases: count("SELECT COUNT(*) AS n FROM aliases WHERE project_id = ?", from.id),
|
|
33
|
-
compactions: count("SELECT COUNT(*) AS n FROM compaction_log WHERE project_id = ?", from.id),
|
|
34
|
-
links: count("SELECT COUNT(*) AS n FROM links WHERE target_project_id = ?", from.id),
|
|
35
|
-
aliasToAdd: aliasTaken ? void 0 : from.slug
|
|
36
|
-
};
|
|
37
|
-
}
|
|
38
|
-
/**
|
|
39
|
-
* Apply a plan. One transaction: either the whole row is folded in or nothing is.
|
|
40
|
-
*
|
|
41
|
-
* A half-merged project is the worst outcome available here — sessions moved but
|
|
42
|
-
* the row still present, or the row gone and its tags orphaned — and with foreign
|
|
43
|
-
* keys off nothing would complain.
|
|
44
|
-
*/
|
|
45
|
-
function applyMerge(db, plan) {
|
|
46
|
-
db.transaction(() => {
|
|
47
|
-
const move = db.prepare("UPDATE sessions SET project_id = ?, number = ? WHERE id = ?");
|
|
48
|
-
for (const s of plan.sessions) move.run(plan.intoId, s.to, s.id);
|
|
49
|
-
db.prepare(`INSERT OR IGNORE INTO project_tags (project_id, tag_id)
|
|
50
|
-
SELECT ?, tag_id FROM project_tags WHERE project_id = ?`).run(plan.intoId, plan.fromId);
|
|
51
|
-
db.prepare("DELETE FROM project_tags WHERE project_id = ?").run(plan.fromId);
|
|
52
|
-
db.prepare("UPDATE aliases SET project_id = ? WHERE project_id = ?").run(plan.intoId, plan.fromId);
|
|
53
|
-
db.prepare("UPDATE compaction_log SET project_id = ? WHERE project_id = ?").run(plan.intoId, plan.fromId);
|
|
54
|
-
db.prepare(`UPDATE OR IGNORE links SET target_project_id = ? WHERE target_project_id = ?`).run(plan.intoId, plan.fromId);
|
|
55
|
-
db.prepare("DELETE FROM links WHERE target_project_id = ?").run(plan.fromId);
|
|
56
|
-
db.prepare(`DELETE FROM links WHERE target_project_id = ?
|
|
57
|
-
AND session_id IN (SELECT id FROM sessions WHERE project_id = ?)`).run(plan.intoId, plan.intoId);
|
|
58
|
-
if (plan.aliasToAdd) db.prepare("INSERT OR IGNORE INTO aliases (alias, project_id) VALUES (?, ?)").run(plan.aliasToAdd, plan.intoId);
|
|
59
|
-
db.prepare("DELETE FROM projects WHERE id = ?").run(plan.fromId);
|
|
60
|
-
})();
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
//#endregion
|
|
64
|
-
//#region src/storage/registry-sqlite.ts
|
|
65
|
-
var SQLiteRegistryBackend = class {
|
|
66
|
-
backendType = "sqlite";
|
|
67
|
-
db;
|
|
68
|
-
constructor(db) {
|
|
69
|
-
this.db = db;
|
|
70
|
-
}
|
|
71
|
-
/** Expose the raw better-sqlite3 Database handle for not-yet-converted callers. */
|
|
72
|
-
getRawDb() {
|
|
73
|
-
return this.db;
|
|
74
|
-
}
|
|
75
|
-
async close() {
|
|
76
|
-
try {
|
|
77
|
-
this.db.close();
|
|
78
|
-
} catch {}
|
|
79
|
-
}
|
|
80
|
-
async resetRegistry() {
|
|
81
|
-
this.db.transaction(() => {
|
|
82
|
-
this.db.prepare("DELETE FROM links").run();
|
|
83
|
-
this.db.prepare("DELETE FROM compaction_log").run();
|
|
84
|
-
this.db.prepare("DELETE FROM session_tags").run();
|
|
85
|
-
this.db.prepare("DELETE FROM project_tags").run();
|
|
86
|
-
this.db.prepare("DELETE FROM aliases").run();
|
|
87
|
-
this.db.prepare("DELETE FROM sessions").run();
|
|
88
|
-
this.db.prepare("DELETE FROM tags").run();
|
|
89
|
-
this.db.prepare("DELETE FROM projects").run();
|
|
90
|
-
})();
|
|
91
|
-
}
|
|
92
|
-
async getProjectById(id) {
|
|
93
|
-
return this.db.prepare("SELECT * FROM projects WHERE id = ?").get(id) ?? null;
|
|
94
|
-
}
|
|
95
|
-
async getProjectBySlug(slug, opts = {}) {
|
|
96
|
-
let sql = opts.caseInsensitive ? "SELECT * FROM projects WHERE lower(slug) = lower(?)" : "SELECT * FROM projects WHERE slug = ?";
|
|
97
|
-
const params = [slug];
|
|
98
|
-
if (opts.excludeId !== void 0) {
|
|
99
|
-
sql += " AND id != ?";
|
|
100
|
-
params.push(opts.excludeId);
|
|
101
|
-
}
|
|
102
|
-
return this.db.prepare(sql).get(...params) ?? null;
|
|
103
|
-
}
|
|
104
|
-
async getProjectByAlias(alias, opts = {}) {
|
|
105
|
-
const sql = opts.caseInsensitive ? "SELECT p.* FROM projects p JOIN aliases a ON a.project_id = p.id WHERE lower(a.alias) = lower(?)" : "SELECT p.* FROM projects p JOIN aliases a ON a.project_id = p.id WHERE a.alias = ?";
|
|
106
|
-
return this.db.prepare(sql).get(alias) ?? null;
|
|
107
|
-
}
|
|
108
|
-
async getProjectByRootPath(rootPath, opts = {}) {
|
|
109
|
-
let sql = "SELECT * FROM projects WHERE root_path = ?";
|
|
110
|
-
const params = [rootPath];
|
|
111
|
-
if (opts.excludeId !== void 0) {
|
|
112
|
-
sql += " AND id != ?";
|
|
113
|
-
params.push(opts.excludeId);
|
|
114
|
-
}
|
|
115
|
-
return this.db.prepare(sql).get(...params) ?? null;
|
|
116
|
-
}
|
|
117
|
-
async getProjectByEncodedDir(encodedDir, opts = {}) {
|
|
118
|
-
let sql = "SELECT * FROM projects WHERE encoded_dir = ?";
|
|
119
|
-
const params = [encodedDir];
|
|
120
|
-
if (opts.excludeId !== void 0) {
|
|
121
|
-
sql += " AND id != ?";
|
|
122
|
-
params.push(opts.excludeId);
|
|
123
|
-
}
|
|
124
|
-
return this.db.prepare(sql).get(...params) ?? null;
|
|
125
|
-
}
|
|
126
|
-
async findProjectByCwdPrefix(cwd) {
|
|
127
|
-
return this.db.prepare(`SELECT * FROM projects WHERE status = 'active' AND ? LIKE root_path || '%'
|
|
128
|
-
ORDER BY length(root_path) DESC LIMIT 1`).get(cwd) ?? null;
|
|
129
|
-
}
|
|
130
|
-
async listProjects(opts = {}) {
|
|
131
|
-
const where = [];
|
|
132
|
-
const params = [];
|
|
133
|
-
if (opts.status) {
|
|
134
|
-
where.push("p.status = ?");
|
|
135
|
-
params.push(opts.status);
|
|
136
|
-
}
|
|
137
|
-
if (opts.excludeArchived) where.push("p.status != 'archived'");
|
|
138
|
-
if (opts.tagName) {
|
|
139
|
-
where.push("p.id IN (SELECT pt.project_id FROM project_tags pt JOIN tags t ON pt.tag_id = t.id WHERE t.name = ?)");
|
|
140
|
-
params.push(opts.tagName);
|
|
141
|
-
}
|
|
142
|
-
let sql = "SELECT p.* FROM projects p";
|
|
143
|
-
if (where.length) sql += " WHERE " + where.join(" AND ");
|
|
144
|
-
switch (opts.orderBy) {
|
|
145
|
-
case "updated_desc":
|
|
146
|
-
sql += " ORDER BY p.updated_at DESC";
|
|
147
|
-
break;
|
|
148
|
-
case "slug":
|
|
149
|
-
sql += " ORDER BY p.slug ASC";
|
|
150
|
-
break;
|
|
151
|
-
case "id":
|
|
152
|
-
sql += " ORDER BY p.id";
|
|
153
|
-
break;
|
|
154
|
-
default:
|
|
155
|
-
sql += " ORDER BY p.status ASC, p.updated_at DESC";
|
|
156
|
-
break;
|
|
157
|
-
}
|
|
158
|
-
if (opts.limit !== void 0) {
|
|
159
|
-
sql += " LIMIT ?";
|
|
160
|
-
params.push(opts.limit);
|
|
161
|
-
}
|
|
162
|
-
return this.db.prepare(sql).all(...params);
|
|
163
|
-
}
|
|
164
|
-
async listProjectsByPathLengthDesc(opts = {}) {
|
|
165
|
-
const where = opts.excludeArchived ? "WHERE status != 'archived'" : "";
|
|
166
|
-
return this.db.prepare(`SELECT * FROM projects ${where} ORDER BY LENGTH(root_path) DESC`).all();
|
|
167
|
-
}
|
|
168
|
-
async listProjectsWithSessionStats(opts = {}) {
|
|
169
|
-
const where = [];
|
|
170
|
-
const params = [];
|
|
171
|
-
if (opts.status) {
|
|
172
|
-
where.push("p.status = ?");
|
|
173
|
-
params.push(opts.status);
|
|
174
|
-
}
|
|
175
|
-
if (opts.tagId !== void 0) {
|
|
176
|
-
where.push("p.id IN (SELECT project_id FROM project_tags WHERE tag_id = ?)");
|
|
177
|
-
params.push(opts.tagId);
|
|
178
|
-
}
|
|
179
|
-
let sql = `
|
|
180
|
-
SELECT p.*,
|
|
181
|
-
(SELECT COUNT(*) FROM sessions s WHERE s.project_id = p.id) AS session_count,
|
|
182
|
-
(SELECT MAX(s.created_at) FROM sessions s WHERE s.project_id = p.id) AS last_active
|
|
183
|
-
FROM projects p
|
|
184
|
-
`;
|
|
185
|
-
if (where.length) sql += " WHERE " + where.join(" AND ");
|
|
186
|
-
sql += opts.orderBy === "updated_desc" ? " ORDER BY p.updated_at DESC" : " ORDER BY p.status ASC, p.updated_at DESC";
|
|
187
|
-
return this.db.prepare(sql).all(...params);
|
|
188
|
-
}
|
|
189
|
-
async listNamedProjects(opts = {}) {
|
|
190
|
-
const sql = `
|
|
191
|
-
SELECT p.*, a.alias AS name,
|
|
192
|
-
(SELECT COUNT(*) FROM sessions s WHERE s.project_id = p.id) AS session_count,
|
|
193
|
-
(SELECT MAX(s.created_at) FROM sessions s WHERE s.project_id = p.id) AS last_active
|
|
194
|
-
FROM projects p
|
|
195
|
-
${opts.includeUnnamed ? "LEFT JOIN" : "JOIN"} aliases a ON a.project_id = p.id
|
|
196
|
-
WHERE p.status = 'active'
|
|
197
|
-
ORDER BY p.updated_at DESC
|
|
198
|
-
`;
|
|
199
|
-
return this.db.prepare(sql).all();
|
|
200
|
-
}
|
|
201
|
-
async searchProjects(query, limit = 20) {
|
|
202
|
-
const q = `%${query}%`;
|
|
203
|
-
return this.db.prepare(`SELECT * FROM projects WHERE slug LIKE ? OR display_name LIKE ? OR root_path LIKE ?
|
|
204
|
-
ORDER BY updated_at DESC LIMIT ?`).all(q, q, q, limit);
|
|
205
|
-
}
|
|
206
|
-
async countProjects(opts = {}) {
|
|
207
|
-
const sql = opts.status ? "SELECT COUNT(*) AS n FROM projects WHERE status = ?" : "SELECT COUNT(*) AS n FROM projects";
|
|
208
|
-
return (opts.status ? this.db.prepare(sql).get(opts.status) : this.db.prepare(sql).get()).n;
|
|
209
|
-
}
|
|
210
|
-
async getMostRecentProjectUpdatedAt() {
|
|
211
|
-
return this.db.prepare("SELECT updated_at FROM projects ORDER BY updated_at DESC LIMIT 1").get()?.updated_at ?? null;
|
|
212
|
-
}
|
|
213
|
-
async countChildProjects(parentId) {
|
|
214
|
-
return this.db.prepare("SELECT COUNT(*) AS n FROM projects WHERE parent_id = ?").get(parentId).n;
|
|
215
|
-
}
|
|
216
|
-
async findSiblingProjectsBySlugPattern(excludeProjectId, slug, limit = 3) {
|
|
217
|
-
return this.db.prepare(`SELECT p.slug, p.root_path, COUNT(s.id) AS session_count
|
|
218
|
-
FROM projects p LEFT JOIN sessions s ON s.project_id = p.id
|
|
219
|
-
WHERE p.id != ? AND (p.slug = ? OR p.slug LIKE ? || '-%' OR ? LIKE p.slug || '-%')
|
|
220
|
-
GROUP BY p.id HAVING session_count > 0 ORDER BY session_count DESC LIMIT ?`).all(excludeProjectId, slug, slug, slug, limit);
|
|
221
|
-
}
|
|
222
|
-
async createProject(input) {
|
|
223
|
-
const type = input.type ?? "local";
|
|
224
|
-
const status = input.status ?? "active";
|
|
225
|
-
const result = this.db.prepare(`INSERT INTO projects (slug, display_name, root_path, encoded_dir, type, status, created_at, updated_at)
|
|
226
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?)`).run(input.slug, input.displayName, input.rootPath, input.encodedDir, type, status, input.createdAt, input.updatedAt);
|
|
227
|
-
return await this.getProjectById(result.lastInsertRowid);
|
|
228
|
-
}
|
|
229
|
-
async createProjectWithSlugRetry(input) {
|
|
230
|
-
let slug = input.baseSlug;
|
|
231
|
-
let attempt = 0;
|
|
232
|
-
const insert = this.db.prepare(`INSERT OR IGNORE INTO projects (slug, display_name, root_path, encoded_dir, type, status, created_at, updated_at)
|
|
233
|
-
VALUES (?, ?, ?, ?, 'local', 'active', ?, ?)`);
|
|
234
|
-
while (true) {
|
|
235
|
-
const info = insert.run(slug, input.displayName, input.rootPath, input.encodedDir, input.createdAt, input.updatedAt);
|
|
236
|
-
if (info.changes > 0) return {
|
|
237
|
-
id: info.lastInsertRowid,
|
|
238
|
-
slug,
|
|
239
|
-
created: true
|
|
240
|
-
};
|
|
241
|
-
const existing = this.db.prepare("SELECT id FROM projects WHERE root_path = ?").get(input.rootPath);
|
|
242
|
-
if (existing) return {
|
|
243
|
-
id: existing.id,
|
|
244
|
-
slug,
|
|
245
|
-
created: false
|
|
246
|
-
};
|
|
247
|
-
attempt++;
|
|
248
|
-
slug = `${input.baseSlug}-${attempt}`;
|
|
249
|
-
}
|
|
250
|
-
}
|
|
251
|
-
async updateProjectPath(id, patch, updatedAt) {
|
|
252
|
-
const sets = [];
|
|
253
|
-
const params = [];
|
|
254
|
-
if (patch.rootPath !== void 0) {
|
|
255
|
-
sets.push("root_path = ?");
|
|
256
|
-
params.push(patch.rootPath);
|
|
257
|
-
}
|
|
258
|
-
if (patch.encodedDir !== void 0) {
|
|
259
|
-
sets.push("encoded_dir = ?");
|
|
260
|
-
params.push(patch.encodedDir);
|
|
261
|
-
}
|
|
262
|
-
if (updatedAt !== void 0) {
|
|
263
|
-
sets.push("updated_at = ?");
|
|
264
|
-
params.push(updatedAt);
|
|
265
|
-
}
|
|
266
|
-
if (!sets.length) return;
|
|
267
|
-
params.push(id);
|
|
268
|
-
this.db.prepare(`UPDATE projects SET ${sets.join(", ")} WHERE id = ?`).run(...params);
|
|
269
|
-
}
|
|
270
|
-
async updateProjectStatus(id, status, opts = {}) {
|
|
271
|
-
const sets = ["status = ?"];
|
|
272
|
-
const params = [status];
|
|
273
|
-
if (opts.archivedAt !== void 0) {
|
|
274
|
-
sets.push("archived_at = ?");
|
|
275
|
-
params.push(opts.archivedAt);
|
|
276
|
-
}
|
|
277
|
-
if (opts.updatedAt !== void 0) {
|
|
278
|
-
sets.push("updated_at = ?");
|
|
279
|
-
params.push(opts.updatedAt);
|
|
280
|
-
}
|
|
281
|
-
let sql = `UPDATE projects SET ${sets.join(", ")} WHERE id = ?`;
|
|
282
|
-
params.push(id);
|
|
283
|
-
if (opts.requireCurrentStatus) {
|
|
284
|
-
sql += " AND status = ?";
|
|
285
|
-
params.push(opts.requireCurrentStatus);
|
|
286
|
-
}
|
|
287
|
-
this.db.prepare(sql).run(...params);
|
|
288
|
-
}
|
|
289
|
-
async updateProjectDisplayName(id, displayName, updatedAt) {
|
|
290
|
-
if (updatedAt !== void 0) this.db.prepare("UPDATE projects SET display_name = ?, updated_at = ? WHERE id = ?").run(displayName, updatedAt, id);
|
|
291
|
-
else this.db.prepare("UPDATE projects SET display_name = ? WHERE id = ?").run(displayName, id);
|
|
292
|
-
}
|
|
293
|
-
async updateProjectType(id, type, updatedAt) {
|
|
294
|
-
if (updatedAt !== void 0) this.db.prepare("UPDATE projects SET type = ?, updated_at = ? WHERE id = ?").run(type, updatedAt, id);
|
|
295
|
-
else this.db.prepare("UPDATE projects SET type = ? WHERE id = ?").run(type, id);
|
|
296
|
-
}
|
|
297
|
-
async updateProjectSessionConfig(id, config, updatedAt) {
|
|
298
|
-
if (updatedAt !== void 0) this.db.prepare("UPDATE projects SET session_config = ?, updated_at = ? WHERE id = ?").run(config, updatedAt, id);
|
|
299
|
-
else this.db.prepare("UPDATE projects SET session_config = ? WHERE id = ?").run(config, id);
|
|
300
|
-
}
|
|
301
|
-
async updateProjectClaudeNotesDir(id, dir, updatedAt) {
|
|
302
|
-
if (updatedAt !== void 0) this.db.prepare("UPDATE projects SET claude_notes_dir = ?, updated_at = ? WHERE id = ?").run(dir, updatedAt, id);
|
|
303
|
-
else this.db.prepare("UPDATE projects SET claude_notes_dir = ? WHERE id = ?").run(dir, id);
|
|
304
|
-
}
|
|
305
|
-
async updateProjectObsidianLink(id, link, updatedAt) {
|
|
306
|
-
if (updatedAt !== void 0) this.db.prepare("UPDATE projects SET obsidian_link = ?, updated_at = ? WHERE id = ?").run(link, updatedAt, id);
|
|
307
|
-
else this.db.prepare("UPDATE projects SET obsidian_link = ? WHERE id = ?").run(link, id);
|
|
308
|
-
}
|
|
309
|
-
async updateProjectSlug(id, slug, updatedAt) {
|
|
310
|
-
this.db.prepare("UPDATE projects SET slug = ?, updated_at = ? WHERE id = ?").run(slug, updatedAt, id);
|
|
311
|
-
}
|
|
312
|
-
async reassignProjectParent(fromParentId, toParentId) {
|
|
313
|
-
return this.db.prepare("UPDATE projects SET parent_id = ? WHERE parent_id = ?").run(toParentId, fromParentId).changes;
|
|
314
|
-
}
|
|
315
|
-
async deleteProject(id) {
|
|
316
|
-
this.db.prepare("DELETE FROM projects WHERE id = ?").run(id);
|
|
317
|
-
}
|
|
318
|
-
async deleteProjectCascade(id) {
|
|
319
|
-
this.db.transaction(() => {
|
|
320
|
-
this.db.prepare("DELETE FROM links WHERE target_project_id = ?").run(id);
|
|
321
|
-
this.db.prepare("DELETE FROM links WHERE session_id IN (SELECT id FROM sessions WHERE project_id = ?)").run(id);
|
|
322
|
-
this.db.prepare("DELETE FROM compaction_log WHERE project_id = ?").run(id);
|
|
323
|
-
this.db.prepare("DELETE FROM project_tags WHERE project_id = ?").run(id);
|
|
324
|
-
this.db.prepare("DELETE FROM aliases WHERE project_id = ?").run(id);
|
|
325
|
-
this.db.prepare("DELETE FROM sessions WHERE project_id = ?").run(id);
|
|
326
|
-
this.db.prepare("DELETE FROM projects WHERE id = ?").run(id);
|
|
327
|
-
})();
|
|
328
|
-
}
|
|
329
|
-
async listTagsForProject(projectId) {
|
|
330
|
-
return this.db.prepare("SELECT t.name FROM tags t JOIN project_tags pt ON pt.tag_id = t.id WHERE pt.project_id = ? ORDER BY t.name").all(projectId).map((r) => r.name);
|
|
331
|
-
}
|
|
332
|
-
async listAllTags() {
|
|
333
|
-
return this.db.prepare("SELECT id, name FROM tags ORDER BY name").all();
|
|
334
|
-
}
|
|
335
|
-
async upsertTag(name) {
|
|
336
|
-
this.db.prepare("INSERT OR IGNORE INTO tags (name) VALUES (?)").run(name);
|
|
337
|
-
return this.db.prepare("SELECT id FROM tags WHERE name = ?").get(name).id;
|
|
338
|
-
}
|
|
339
|
-
async addProjectTag(projectId, tagId) {
|
|
340
|
-
this.db.prepare("INSERT INTO project_tags (project_id, tag_id) VALUES (?, ?)").run(projectId, tagId);
|
|
341
|
-
}
|
|
342
|
-
async projectHasTag(projectId, tagId) {
|
|
343
|
-
return !!this.db.prepare("SELECT 1 FROM project_tags WHERE project_id = ? AND tag_id = ?").get(projectId, tagId);
|
|
344
|
-
}
|
|
345
|
-
async deleteProjectTag(projectId, tagId) {
|
|
346
|
-
this.db.prepare("DELETE FROM project_tags WHERE project_id = ? AND tag_id = ?").run(projectId, tagId);
|
|
347
|
-
}
|
|
348
|
-
async reassignProjectTag(fromProjectId, toProjectId, tagId) {
|
|
349
|
-
this.db.prepare("UPDATE project_tags SET project_id = ? WHERE project_id = ? AND tag_id = ?").run(toProjectId, fromProjectId, tagId);
|
|
350
|
-
}
|
|
351
|
-
async listProjectTagIds(projectId) {
|
|
352
|
-
return this.db.prepare("SELECT tag_id FROM project_tags WHERE project_id = ?").all(projectId).map((r) => r.tag_id);
|
|
353
|
-
}
|
|
354
|
-
async countProjectTagsForProject(projectId) {
|
|
355
|
-
return this.db.prepare("SELECT COUNT(*) AS n FROM project_tags WHERE project_id = ?").get(projectId).n;
|
|
356
|
-
}
|
|
357
|
-
async copyProjectTags(fromProjectId, toProjectId) {
|
|
358
|
-
this.db.prepare("INSERT OR IGNORE INTO project_tags (project_id, tag_id) SELECT ?, tag_id FROM project_tags WHERE project_id = ?").run(toProjectId, fromProjectId);
|
|
359
|
-
}
|
|
360
|
-
async deleteProjectTagsForProject(projectId) {
|
|
361
|
-
this.db.prepare("DELETE FROM project_tags WHERE project_id = ?").run(projectId);
|
|
362
|
-
}
|
|
363
|
-
async resolveAlias(alias) {
|
|
364
|
-
return this.db.prepare("SELECT project_id FROM aliases WHERE alias = ?").get(alias)?.project_id ?? null;
|
|
365
|
-
}
|
|
366
|
-
async listAliasesForProject(projectId) {
|
|
367
|
-
return this.db.prepare("SELECT alias FROM aliases WHERE project_id = ? ORDER BY alias").all(projectId).map((r) => r.alias);
|
|
368
|
-
}
|
|
369
|
-
async addAlias(alias, projectId) {
|
|
370
|
-
this.db.prepare("INSERT INTO aliases (alias, project_id) VALUES (?, ?)").run(alias, projectId);
|
|
371
|
-
}
|
|
372
|
-
async removeAlias(alias) {
|
|
373
|
-
this.db.prepare("DELETE FROM aliases WHERE alias = ?").run(alias);
|
|
374
|
-
}
|
|
375
|
-
async countAliasesForProject(projectId) {
|
|
376
|
-
return this.db.prepare("SELECT COUNT(*) AS n FROM aliases WHERE project_id = ?").get(projectId).n;
|
|
377
|
-
}
|
|
378
|
-
async moveProjectAliases(fromProjectId, toProjectId) {
|
|
379
|
-
this.db.prepare("UPDATE aliases SET project_id = ? WHERE project_id = ?").run(toProjectId, fromProjectId);
|
|
380
|
-
}
|
|
381
|
-
async reassignAlias(alias, toProjectId) {
|
|
382
|
-
this.db.prepare("UPDATE aliases SET project_id = ? WHERE alias = ?").run(toProjectId, alias);
|
|
383
|
-
}
|
|
384
|
-
async listAliasMap() {
|
|
385
|
-
return this.db.prepare(`SELECT a.alias AS alias, p.slug AS slug, p.root_path AS root_path
|
|
386
|
-
FROM aliases a JOIN projects p ON p.id = a.project_id WHERE p.status != 'archived'`).all();
|
|
387
|
-
}
|
|
388
|
-
async getSessionById(id) {
|
|
389
|
-
return this.db.prepare("SELECT * FROM sessions WHERE id = ?").get(id) ?? null;
|
|
390
|
-
}
|
|
391
|
-
async getSessionByNumber(projectId, number) {
|
|
392
|
-
return this.db.prepare("SELECT * FROM sessions WHERE project_id = ? AND number = ?").get(projectId, number) ?? null;
|
|
393
|
-
}
|
|
394
|
-
async getLatestSessionForProject(projectId) {
|
|
395
|
-
return this.db.prepare("SELECT * FROM sessions WHERE project_id = ? ORDER BY number DESC LIMIT 1").get(projectId) ?? null;
|
|
396
|
-
}
|
|
397
|
-
async getMaxSessionNumber(projectId) {
|
|
398
|
-
return this.db.prepare("SELECT COALESCE(MAX(number), 0) AS n FROM sessions WHERE project_id = ?").get(projectId).n;
|
|
399
|
-
}
|
|
400
|
-
async listSessionsForProject(projectId, opts = {}) {
|
|
401
|
-
let sql = `SELECT * FROM sessions WHERE project_id = ? ORDER BY ${opts.orderBy === "created_desc" ? "created_at DESC" : "number ASC"}`;
|
|
402
|
-
const params = [projectId];
|
|
403
|
-
if (opts.limit !== void 0) {
|
|
404
|
-
sql += " LIMIT ?";
|
|
405
|
-
params.push(opts.limit);
|
|
406
|
-
}
|
|
407
|
-
return this.db.prepare(sql).all(...params);
|
|
408
|
-
}
|
|
409
|
-
async listSessions(opts = {}) {
|
|
410
|
-
const where = [];
|
|
411
|
-
const params = [];
|
|
412
|
-
if (opts.projectId !== void 0) {
|
|
413
|
-
where.push("s.project_id = ?");
|
|
414
|
-
params.push(opts.projectId);
|
|
415
|
-
}
|
|
416
|
-
if (opts.status) {
|
|
417
|
-
where.push("s.status = ?");
|
|
418
|
-
params.push(opts.status);
|
|
419
|
-
}
|
|
420
|
-
let sql = `
|
|
421
|
-
SELECT s.*, p.slug AS project_slug, p.display_name AS project_name
|
|
422
|
-
FROM sessions s JOIN projects p ON p.id = s.project_id
|
|
423
|
-
`;
|
|
424
|
-
if (where.length) sql += " WHERE " + where.join(" AND ");
|
|
425
|
-
sql += " ORDER BY s.date DESC, s.number DESC";
|
|
426
|
-
const limit = opts.limit ?? 20;
|
|
427
|
-
sql += ` LIMIT ${limit}`;
|
|
428
|
-
return this.db.prepare(sql).all(...params);
|
|
429
|
-
}
|
|
430
|
-
async findSessionByFilename(projectId, filename) {
|
|
431
|
-
return this.db.prepare("SELECT id FROM sessions WHERE project_id = ? AND filename = ? LIMIT 1").get(projectId, filename) ?? null;
|
|
432
|
-
}
|
|
433
|
-
async sessionNumberTaken(projectId, number) {
|
|
434
|
-
return !!this.db.prepare("SELECT 1 FROM sessions WHERE project_id = ? AND number = ? LIMIT 1").get(projectId, number);
|
|
435
|
-
}
|
|
436
|
-
async createSession(input) {
|
|
437
|
-
const status = input.status ?? "completed";
|
|
438
|
-
const result = this.db.prepare(`INSERT INTO sessions (project_id, number, date, slug, title, filename, status, created_at)
|
|
439
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?)`).run(input.projectId, input.number, input.date, input.slug, input.title, input.filename, status, input.createdAt);
|
|
440
|
-
return await this.getSessionById(result.lastInsertRowid);
|
|
441
|
-
}
|
|
442
|
-
async upsertSessionIfAbsent(input) {
|
|
443
|
-
if (this.db.prepare("SELECT id FROM sessions WHERE project_id = ? AND number = ?").get(input.projectId, input.number)) return false;
|
|
444
|
-
const status = input.status ?? "completed";
|
|
445
|
-
this.db.prepare(`INSERT INTO sessions (project_id, number, date, slug, title, filename, status, created_at)
|
|
446
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?)`).run(input.projectId, input.number, input.date, input.slug, input.title, input.filename, status, input.createdAt);
|
|
447
|
-
return true;
|
|
448
|
-
}
|
|
449
|
-
async updateSessionMeta(id, patch) {
|
|
450
|
-
const sets = [];
|
|
451
|
-
const params = [];
|
|
452
|
-
if (patch.slug !== void 0) {
|
|
453
|
-
sets.push("slug = ?");
|
|
454
|
-
params.push(patch.slug);
|
|
455
|
-
}
|
|
456
|
-
if (patch.title !== void 0) {
|
|
457
|
-
sets.push("title = ?");
|
|
458
|
-
params.push(patch.title);
|
|
459
|
-
}
|
|
460
|
-
if (patch.filename !== void 0) {
|
|
461
|
-
sets.push("filename = ?");
|
|
462
|
-
params.push(patch.filename);
|
|
463
|
-
}
|
|
464
|
-
if (!sets.length) return;
|
|
465
|
-
params.push(id);
|
|
466
|
-
this.db.prepare(`UPDATE sessions SET ${sets.join(", ")} WHERE id = ?`).run(...params);
|
|
467
|
-
}
|
|
468
|
-
async updateSessionNumber(id, number, opts = {}) {
|
|
469
|
-
if (opts.filename !== void 0) this.db.prepare("UPDATE sessions SET number = ?, filename = ? WHERE id = ?").run(number, opts.filename, id);
|
|
470
|
-
else this.db.prepare("UPDATE sessions SET number = ? WHERE id = ?").run(number, id);
|
|
471
|
-
}
|
|
472
|
-
async updateSessionFilename(id, filename) {
|
|
473
|
-
this.db.prepare("UPDATE sessions SET filename = ? WHERE id = ?").run(filename, id);
|
|
474
|
-
}
|
|
475
|
-
async updateSessionStatus(id, status, opts = {}) {
|
|
476
|
-
if (opts.closedAt !== void 0) this.db.prepare("UPDATE sessions SET status = ?, closed_at = ? WHERE id = ?").run(status, opts.closedAt, id);
|
|
477
|
-
else this.db.prepare("UPDATE sessions SET status = ? WHERE id = ?").run(status, id);
|
|
478
|
-
}
|
|
479
|
-
async moveSessionToProject(id, projectId, opts = {}) {
|
|
480
|
-
if (opts.number !== void 0) this.db.prepare("UPDATE sessions SET project_id = ?, number = ? WHERE id = ?").run(projectId, opts.number, id);
|
|
481
|
-
else this.db.prepare("UPDATE sessions SET project_id = ? WHERE id = ?").run(projectId, id);
|
|
482
|
-
}
|
|
483
|
-
async deleteSession(id) {
|
|
484
|
-
this.db.prepare("DELETE FROM sessions WHERE id = ?").run(id);
|
|
485
|
-
}
|
|
486
|
-
async backfillFoldedSession(keepId, dropId) {
|
|
487
|
-
this.db.prepare(`UPDATE sessions SET
|
|
488
|
-
claude_session_id = COALESCE(claude_session_id,
|
|
489
|
-
(SELECT claude_session_id FROM sessions WHERE id = ?)),
|
|
490
|
-
token_count = COALESCE(token_count,
|
|
491
|
-
(SELECT token_count FROM sessions WHERE id = ?)),
|
|
492
|
-
closed_at = COALESCE(closed_at,
|
|
493
|
-
(SELECT closed_at FROM sessions WHERE id = ?)),
|
|
494
|
-
status = CASE WHEN status = 'open'
|
|
495
|
-
AND (SELECT status FROM sessions WHERE id = ?) != 'open'
|
|
496
|
-
THEN (SELECT status FROM sessions WHERE id = ?)
|
|
497
|
-
ELSE status END
|
|
498
|
-
WHERE id = ?`).run(dropId, dropId, dropId, dropId, dropId, keepId);
|
|
499
|
-
}
|
|
500
|
-
async countSessionsForProject(projectId) {
|
|
501
|
-
return this.db.prepare("SELECT COUNT(*) AS n FROM sessions WHERE project_id = ?").get(projectId).n;
|
|
502
|
-
}
|
|
503
|
-
async countSessions() {
|
|
504
|
-
return this.db.prepare("SELECT COUNT(*) AS n FROM sessions").get().n;
|
|
505
|
-
}
|
|
506
|
-
async getMostRecentSessionDate(projectId) {
|
|
507
|
-
return this.db.prepare("SELECT date FROM sessions WHERE project_id = ? ORDER BY date DESC LIMIT 1").get(projectId)?.date ?? null;
|
|
508
|
-
}
|
|
509
|
-
async getMostRecentSessionCreatedAt() {
|
|
510
|
-
return this.db.prepare("SELECT created_at FROM sessions ORDER BY created_at DESC LIMIT 1").get()?.created_at ?? null;
|
|
511
|
-
}
|
|
512
|
-
async listSessionTagIds(sessionId) {
|
|
513
|
-
return this.db.prepare("SELECT tag_id FROM session_tags WHERE session_id = ?").all(sessionId).map((r) => r.tag_id);
|
|
514
|
-
}
|
|
515
|
-
async sessionHasTag(sessionId, tagId) {
|
|
516
|
-
return !!this.db.prepare("SELECT 1 FROM session_tags WHERE session_id = ? AND tag_id = ?").get(sessionId, tagId);
|
|
517
|
-
}
|
|
518
|
-
async addSessionTag(sessionId, tagId) {
|
|
519
|
-
this.db.prepare("INSERT INTO session_tags (session_id, tag_id) VALUES (?, ?)").run(sessionId, tagId);
|
|
520
|
-
}
|
|
521
|
-
async deleteSessionTag(sessionId, tagId) {
|
|
522
|
-
this.db.prepare("DELETE FROM session_tags WHERE session_id = ? AND tag_id = ?").run(sessionId, tagId);
|
|
523
|
-
}
|
|
524
|
-
async reassignSessionTag(fromSessionId, toSessionId, tagId) {
|
|
525
|
-
this.db.prepare("UPDATE session_tags SET session_id = ? WHERE session_id = ? AND tag_id = ?").run(toSessionId, fromSessionId, tagId);
|
|
526
|
-
}
|
|
527
|
-
async listTagsForSession(sessionId) {
|
|
528
|
-
return this.db.prepare("SELECT t.name FROM tags t JOIN session_tags st ON st.tag_id = t.id WHERE st.session_id = ? ORDER BY t.name").all(sessionId).map((r) => r.name);
|
|
529
|
-
}
|
|
530
|
-
async addLink(input) {
|
|
531
|
-
this.db.prepare("INSERT INTO links (session_id, target_project_id, link_type, created_at) VALUES (?, ?, ?, ?)").run(input.sessionId, input.targetProjectId, input.linkType, input.createdAt);
|
|
532
|
-
}
|
|
533
|
-
async listLinksForSession(sessionId) {
|
|
534
|
-
return this.db.prepare("SELECT id, target_project_id FROM links WHERE session_id = ?").all(sessionId);
|
|
535
|
-
}
|
|
536
|
-
async listLinksForProject(projectId) {
|
|
537
|
-
return this.db.prepare("SELECT id, session_id FROM links WHERE target_project_id = ?").all(projectId);
|
|
538
|
-
}
|
|
539
|
-
async linkExists(sessionId, targetProjectId) {
|
|
540
|
-
return !!this.db.prepare("SELECT 1 FROM links WHERE session_id = ? AND target_project_id = ? LIMIT 1").get(sessionId, targetProjectId);
|
|
541
|
-
}
|
|
542
|
-
async deleteLink(id) {
|
|
543
|
-
this.db.prepare("DELETE FROM links WHERE id = ?").run(id);
|
|
544
|
-
}
|
|
545
|
-
async deleteLinksTargetingProject(projectId) {
|
|
546
|
-
this.db.prepare("DELETE FROM links WHERE target_project_id = ?").run(projectId);
|
|
547
|
-
}
|
|
548
|
-
async deleteLinksFromProjectSessions(projectId) {
|
|
549
|
-
this.db.prepare("DELETE FROM links WHERE session_id IN (SELECT id FROM sessions WHERE project_id = ?)").run(projectId);
|
|
550
|
-
}
|
|
551
|
-
async retargetLink(id, targetProjectId) {
|
|
552
|
-
this.db.prepare("UPDATE links SET target_project_id = ? WHERE id = ?").run(targetProjectId, id);
|
|
553
|
-
}
|
|
554
|
-
async moveLinkToSession(id, sessionId) {
|
|
555
|
-
this.db.prepare("UPDATE links SET session_id = ? WHERE id = ?").run(sessionId, id);
|
|
556
|
-
}
|
|
557
|
-
async reassignLinksTarget(fromProjectId, toProjectId) {
|
|
558
|
-
this.db.prepare("UPDATE OR IGNORE links SET target_project_id = ? WHERE target_project_id = ?").run(toProjectId, fromProjectId);
|
|
559
|
-
}
|
|
560
|
-
async countLinksForProject(projectId) {
|
|
561
|
-
return this.db.prepare("SELECT COUNT(*) AS n FROM links WHERE target_project_id = ?").get(projectId).n;
|
|
562
|
-
}
|
|
563
|
-
async deleteSelfLinksForProject(projectId) {
|
|
564
|
-
this.db.prepare(`DELETE FROM links WHERE target_project_id = ?
|
|
565
|
-
AND session_id IN (SELECT id FROM sessions WHERE project_id = ?)`).run(projectId, projectId);
|
|
566
|
-
}
|
|
567
|
-
async appendCompactionLog(entry) {
|
|
568
|
-
this.db.prepare(`INSERT INTO compaction_log (project_id, session_id, trigger, files_written, token_count, created_at)
|
|
569
|
-
VALUES (?, ?, ?, ?, ?, ?)`).run(entry.projectId, entry.sessionId, entry.trigger, entry.filesWritten, entry.tokenCount, entry.createdAt);
|
|
570
|
-
}
|
|
571
|
-
async countCompactionLogsForProject(projectId) {
|
|
572
|
-
return this.db.prepare("SELECT COUNT(*) AS n FROM compaction_log WHERE project_id = ?").get(projectId).n;
|
|
573
|
-
}
|
|
574
|
-
async moveCompactionLogsByProject(fromProjectId, toProjectId) {
|
|
575
|
-
return this.db.prepare("UPDATE compaction_log SET project_id = ? WHERE project_id = ?").run(toProjectId, fromProjectId).changes;
|
|
576
|
-
}
|
|
577
|
-
async moveCompactionLogsBySession(fromSessionId, toSessionId) {
|
|
578
|
-
this.db.prepare("UPDATE compaction_log SET session_id = ? WHERE session_id = ?").run(toSessionId, fromSessionId);
|
|
579
|
-
}
|
|
580
|
-
async deleteCompactionLogsForProject(projectId) {
|
|
581
|
-
this.db.prepare("DELETE FROM compaction_log WHERE project_id = ?").run(projectId);
|
|
582
|
-
}
|
|
583
|
-
async planProjectMerge(fromSlug, intoSlug) {
|
|
584
|
-
return planMerge(this.db, fromSlug, intoSlug);
|
|
585
|
-
}
|
|
586
|
-
async applyProjectMerge(plan) {
|
|
587
|
-
applyMerge(this.db, plan);
|
|
588
|
-
}
|
|
589
|
-
};
|
|
590
|
-
|
|
591
|
-
//#endregion
|
|
592
|
-
export { SQLiteRegistryBackend };
|
|
593
|
-
//# sourceMappingURL=registry-sqlite-DrCW1aRK.mjs.map
|