bbb-mcp-server 0.1.0

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.
Files changed (66) hide show
  1. package/README.md +112 -0
  2. package/dist/api.d.ts +9 -0
  3. package/dist/api.d.ts.map +1 -0
  4. package/dist/api.js +276 -0
  5. package/dist/api.js.map +1 -0
  6. package/dist/config.d.ts +10 -0
  7. package/dist/config.d.ts.map +1 -0
  8. package/dist/config.js +38 -0
  9. package/dist/config.js.map +1 -0
  10. package/dist/db/index.d.ts +6 -0
  11. package/dist/db/index.d.ts.map +1 -0
  12. package/dist/db/index.js +31 -0
  13. package/dist/db/index.js.map +1 -0
  14. package/dist/db/migrations.d.ts +9 -0
  15. package/dist/db/migrations.d.ts.map +1 -0
  16. package/dist/db/migrations.js +205 -0
  17. package/dist/db/migrations.js.map +1 -0
  18. package/dist/handlers/artifact.d.ts +30 -0
  19. package/dist/handlers/artifact.d.ts.map +1 -0
  20. package/dist/handlers/artifact.js +80 -0
  21. package/dist/handlers/artifact.js.map +1 -0
  22. package/dist/handlers/context.d.ts +28 -0
  23. package/dist/handlers/context.d.ts.map +1 -0
  24. package/dist/handlers/context.js +247 -0
  25. package/dist/handlers/context.js.map +1 -0
  26. package/dist/handlers/memory.d.ts +42 -0
  27. package/dist/handlers/memory.d.ts.map +1 -0
  28. package/dist/handlers/memory.js +97 -0
  29. package/dist/handlers/memory.js.map +1 -0
  30. package/dist/handlers/project.d.ts +22 -0
  31. package/dist/handlers/project.d.ts.map +1 -0
  32. package/dist/handlers/project.js +139 -0
  33. package/dist/handlers/project.js.map +1 -0
  34. package/dist/handlers/session.d.ts +25 -0
  35. package/dist/handlers/session.d.ts.map +1 -0
  36. package/dist/handlers/session.js +155 -0
  37. package/dist/handlers/session.js.map +1 -0
  38. package/dist/handlers/task.d.ts +41 -0
  39. package/dist/handlers/task.d.ts.map +1 -0
  40. package/dist/handlers/task.js +76 -0
  41. package/dist/handlers/task.js.map +1 -0
  42. package/dist/index.d.ts +3 -0
  43. package/dist/index.d.ts.map +1 -0
  44. package/dist/index.js +45 -0
  45. package/dist/index.js.map +1 -0
  46. package/dist/server.d.ts +4 -0
  47. package/dist/server.d.ts.map +1 -0
  48. package/dist/server.js +307 -0
  49. package/dist/server.js.map +1 -0
  50. package/dist/utils/hash.d.ts +2 -0
  51. package/dist/utils/hash.d.ts.map +1 -0
  52. package/dist/utils/hash.js +5 -0
  53. package/dist/utils/hash.js.map +1 -0
  54. package/dist/utils/schemas.d.ts +6 -0
  55. package/dist/utils/schemas.d.ts.map +1 -0
  56. package/dist/utils/schemas.js +88 -0
  57. package/dist/utils/schemas.js.map +1 -0
  58. package/dist/utils/templates.d.ts +25 -0
  59. package/dist/utils/templates.d.ts.map +1 -0
  60. package/dist/utils/templates.js +138 -0
  61. package/dist/utils/templates.js.map +1 -0
  62. package/dist/utils/tokens.d.ts +6 -0
  63. package/dist/utils/tokens.d.ts.map +1 -0
  64. package/dist/utils/tokens.js +8 -0
  65. package/dist/utils/tokens.js.map +1 -0
  66. package/package.json +58 -0
@@ -0,0 +1,42 @@
1
+ import type Database from "better-sqlite3";
2
+ export declare function memoryPut(db: Database.Database, projectId: string, params: {
3
+ category: string;
4
+ title: string;
5
+ content: string;
6
+ tags?: string[];
7
+ source?: string;
8
+ source_ref?: string;
9
+ confidence?: number;
10
+ }): {
11
+ id: `${string}-${string}-${string}-${string}-${string}`;
12
+ version: number;
13
+ };
14
+ export declare function memoryQuery(db: Database.Database, projectId: string, params: {
15
+ query: string;
16
+ category?: string;
17
+ tags?: string[];
18
+ limit?: number;
19
+ }): (Record<string, unknown> & {
20
+ rank: number;
21
+ })[];
22
+ export declare function memoryList(db: Database.Database, projectId: string, params: {
23
+ category?: string;
24
+ tags?: string[];
25
+ limit?: number;
26
+ offset?: number;
27
+ }): Record<string, unknown>[];
28
+ export declare function memoryUpdate(db: Database.Database, projectId: string, params: {
29
+ memory_id: string;
30
+ title?: string;
31
+ content?: string;
32
+ tags?: string[];
33
+ category?: string;
34
+ }): {
35
+ id: `${string}-${string}-${string}-${string}-${string}`;
36
+ version: number;
37
+ supersedes: string;
38
+ };
39
+ export declare function memoryDelete(db: Database.Database, projectId: string, memoryId: string): {
40
+ deleted: string;
41
+ };
42
+ //# sourceMappingURL=memory.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"memory.d.ts","sourceRoot":"","sources":["../../src/handlers/memory.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,QAAQ,MAAM,gBAAgB,CAAC;AAsB3C,wBAAgB,SAAS,CACvB,EAAE,EAAE,QAAQ,CAAC,QAAQ,EACrB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE;IACN,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;;;EA0BF;AAED,wBAAgB,WAAW,CACzB,EAAE,EAAE,QAAQ,CAAC,QAAQ,EACrB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE;IACN,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;UAuBmC,MAAM;KAW3C;AAED,wBAAgB,UAAU,CACxB,EAAE,EAAE,QAAQ,CAAC,QAAQ,EACrB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE;IACN,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,6BAwBF;AAED,wBAAgB,YAAY,CAC1B,EAAE,EAAE,QAAQ,CAAC,QAAQ,EACrB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE;IACN,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;;;;EAyCF;AAED,wBAAgB,YAAY,CAC1B,EAAE,EAAE,QAAQ,CAAC,QAAQ,EACrB,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM;;EAejB"}
@@ -0,0 +1,97 @@
1
+ import { randomUUID } from "node:crypto";
2
+ import { contentHash } from "../utils/hash.js";
3
+ function createAuditEvent(db, projectId, eventType, entityType, entityId, details, prevHash) {
4
+ const id = randomUUID();
5
+ const hash = contentHash(JSON.stringify({ eventType, entityId, details }));
6
+ db.prepare(`INSERT INTO audit_events (id, project_id, event_type, actor, entity_type, entity_id, details, hash, prev_hash)
7
+ VALUES (?, ?, ?, 'mcp-client', ?, ?, ?, ?, ?)`).run(id, projectId, eventType, entityType, entityId, JSON.stringify(details), hash, prevHash ?? null);
8
+ return hash;
9
+ }
10
+ export function memoryPut(db, projectId, params) {
11
+ const id = randomUUID();
12
+ const tags = JSON.stringify(params.tags ?? []);
13
+ db.prepare(`INSERT INTO memories (id, project_id, category, title, content, tags, source, source_ref, confidence)
14
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(id, projectId, params.category, params.title, params.content, tags, params.source ?? null, params.source_ref ?? null, params.confidence ?? 1.0);
15
+ createAuditEvent(db, projectId, "memory_created", "memory", id, {
16
+ category: params.category,
17
+ title: params.title,
18
+ });
19
+ return { id, version: 1 };
20
+ }
21
+ export function memoryQuery(db, projectId, params) {
22
+ const limit = params.limit ?? 10;
23
+ let sql = `
24
+ SELECT m.*, bm25(memories_fts) AS rank
25
+ FROM memories_fts fts
26
+ JOIN memories m ON m.rowid = fts.rowid
27
+ WHERE memories_fts MATCH ?
28
+ AND m.project_id = ?
29
+ AND m.superseded_by IS NULL
30
+ `;
31
+ const sqlParams = [params.query, projectId];
32
+ if (params.category) {
33
+ sql += ` AND m.category = ?`;
34
+ sqlParams.push(params.category);
35
+ }
36
+ sql += ` ORDER BY rank LIMIT ?`;
37
+ sqlParams.push(limit);
38
+ const rows = db.prepare(sql).all(...sqlParams);
39
+ if (params.tags?.length) {
40
+ return rows.filter((row) => {
41
+ const rowTags = JSON.parse(row.tags);
42
+ return params.tags.some((t) => rowTags.includes(t));
43
+ });
44
+ }
45
+ return rows;
46
+ }
47
+ export function memoryList(db, projectId, params) {
48
+ let sql = `SELECT * FROM memories WHERE project_id = ? AND superseded_by IS NULL`;
49
+ const sqlParams = [projectId];
50
+ if (params.category) {
51
+ sql += ` AND category = ?`;
52
+ sqlParams.push(params.category);
53
+ }
54
+ sql += ` ORDER BY updated_at DESC LIMIT ? OFFSET ?`;
55
+ sqlParams.push(params.limit ?? 50);
56
+ sqlParams.push(params.offset ?? 0);
57
+ let rows = db.prepare(sql).all(...sqlParams);
58
+ if (params.tags?.length) {
59
+ rows = rows.filter((row) => {
60
+ const rowTags = JSON.parse(row.tags);
61
+ return params.tags.some((t) => rowTags.includes(t));
62
+ });
63
+ }
64
+ return rows;
65
+ }
66
+ export function memoryUpdate(db, projectId, params) {
67
+ const existing = db
68
+ .prepare(`SELECT * FROM memories WHERE id = ? AND project_id = ?`)
69
+ .get(params.memory_id, projectId);
70
+ if (!existing) {
71
+ throw new Error(`Memory not found: ${params.memory_id}`);
72
+ }
73
+ const newVersion = existing.version + 1;
74
+ const newId = randomUUID();
75
+ // Insert new version
76
+ db.prepare(`INSERT INTO memories (id, project_id, category, title, content, tags, source, source_ref, confidence, version)
77
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(newId, projectId, params.category ?? existing.category, params.title ?? existing.title, params.content ?? existing.content, params.tags ? JSON.stringify(params.tags) : existing.tags, existing.source, existing.source_ref, existing.confidence, newVersion);
78
+ // Mark old version as superseded
79
+ db.prepare(`UPDATE memories SET superseded_by = ?, updated_at = datetime('now') WHERE id = ?`).run(newId, params.memory_id);
80
+ createAuditEvent(db, projectId, "memory_updated", "memory", newId, {
81
+ previous_id: params.memory_id,
82
+ version: newVersion,
83
+ });
84
+ return { id: newId, version: newVersion, supersedes: params.memory_id };
85
+ }
86
+ export function memoryDelete(db, projectId, memoryId) {
87
+ const existing = db
88
+ .prepare(`SELECT id FROM memories WHERE id = ? AND project_id = ?`)
89
+ .get(memoryId, projectId);
90
+ if (!existing) {
91
+ throw new Error(`Memory not found: ${memoryId}`);
92
+ }
93
+ db.prepare(`DELETE FROM memories WHERE id = ?`).run(memoryId);
94
+ createAuditEvent(db, projectId, "memory_deleted", "memory", memoryId, {});
95
+ return { deleted: memoryId };
96
+ }
97
+ //# sourceMappingURL=memory.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"memory.js","sourceRoot":"","sources":["../../src/handlers/memory.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ import type Database from "better-sqlite3";
2
+ export declare function projectInit(db: Database.Database, params: {
3
+ name: string;
4
+ slug: string;
5
+ description?: string;
6
+ }): {
7
+ id: string;
8
+ slug: string;
9
+ status: string;
10
+ };
11
+ export declare function projectIngest(db: Database.Database, projectId: string, params: {
12
+ path: string;
13
+ file_types?: string[];
14
+ exclude?: string[];
15
+ }): {
16
+ files_scanned: number;
17
+ files_indexed: number;
18
+ files_skipped: number;
19
+ chunks_created: number;
20
+ total_tokens: number;
21
+ };
22
+ //# sourceMappingURL=project.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"project.d.ts","sourceRoot":"","sources":["../../src/handlers/project.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,QAAQ,MAAM,gBAAgB,CAAC;AAO3C,wBAAgB,WAAW,CACzB,EAAE,EAAE,QAAQ,CAAC,QAAQ,EACrB,MAAM,EAAE;IACN,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;;;;EAkBF;AAiFD,wBAAgB,aAAa,CAC3B,EAAE,EAAE,QAAQ,CAAC,QAAQ,EACrB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE;IACN,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;CACpB;;;;;;EAwEF"}
@@ -0,0 +1,139 @@
1
+ import { randomUUID } from "node:crypto";
2
+ import { existsSync, readFileSync, readdirSync, statSync } from "node:fs";
3
+ import { extname, join, relative } from "node:path";
4
+ import { contentHash } from "../utils/hash.js";
5
+ import { estimateTokens } from "../utils/tokens.js";
6
+ export function projectInit(db, params) {
7
+ const id = randomUUID();
8
+ // Check if project already exists
9
+ const existing = db
10
+ .prepare(`SELECT id FROM projects WHERE slug = ?`)
11
+ .get(params.slug);
12
+ if (existing) {
13
+ return { id: existing.id, slug: params.slug, status: "already_exists" };
14
+ }
15
+ db.prepare(`INSERT INTO projects (id, name, slug, description) VALUES (?, ?, ?, ?)`).run(id, params.name, params.slug, params.description ?? null);
16
+ return { id, slug: params.slug, status: "created" };
17
+ }
18
+ const DEFAULT_EXCLUDES = [
19
+ "node_modules",
20
+ ".git",
21
+ "dist",
22
+ "build",
23
+ ".next",
24
+ "__pycache__",
25
+ ".venv",
26
+ "venv",
27
+ ".env",
28
+ "coverage",
29
+ ".nyc_output",
30
+ ".cache",
31
+ ".turbo",
32
+ ];
33
+ const BINARY_EXTENSIONS = new Set([
34
+ ".png", ".jpg", ".jpeg", ".gif", ".bmp", ".ico", ".svg",
35
+ ".woff", ".woff2", ".ttf", ".eot",
36
+ ".zip", ".tar", ".gz", ".bz2",
37
+ ".pdf", ".doc", ".docx",
38
+ ".mp3", ".mp4", ".wav", ".avi",
39
+ ".exe", ".dll", ".so", ".dylib",
40
+ ".db", ".sqlite", ".sqlite3",
41
+ ]);
42
+ function walkDir(dir, fileTypes, exclude) {
43
+ const files = [];
44
+ let entries;
45
+ try {
46
+ entries = readdirSync(dir);
47
+ }
48
+ catch {
49
+ return files;
50
+ }
51
+ for (const entry of entries) {
52
+ if (exclude.some((e) => entry === e || entry.startsWith(e)))
53
+ continue;
54
+ const fullPath = join(dir, entry);
55
+ let stat;
56
+ try {
57
+ stat = statSync(fullPath);
58
+ }
59
+ catch {
60
+ continue;
61
+ }
62
+ if (stat.isDirectory()) {
63
+ files.push(...walkDir(fullPath, fileTypes, exclude));
64
+ }
65
+ else if (stat.isFile()) {
66
+ const ext = extname(entry).toLowerCase();
67
+ if (BINARY_EXTENSIONS.has(ext))
68
+ continue;
69
+ if (fileTypes?.length && !fileTypes.includes(ext))
70
+ continue;
71
+ if (stat.size > 1_000_000)
72
+ continue; // Skip files > 1MB
73
+ files.push(fullPath);
74
+ }
75
+ }
76
+ return files;
77
+ }
78
+ function chunkContent(content, chunkSize = 256, overlap = 50) {
79
+ const words = content.split(/\s+/);
80
+ const chunks = [];
81
+ const wordsPerChunk = chunkSize; // ~1 token per word approximation
82
+ for (let i = 0; i < words.length; i += wordsPerChunk - overlap) {
83
+ const chunk = words.slice(i, i + wordsPerChunk).join(" ");
84
+ if (chunk.trim())
85
+ chunks.push(chunk);
86
+ if (i + wordsPerChunk >= words.length)
87
+ break;
88
+ }
89
+ return chunks;
90
+ }
91
+ export function projectIngest(db, projectId, params) {
92
+ if (!existsSync(params.path)) {
93
+ throw new Error(`Path does not exist: ${params.path}`);
94
+ }
95
+ const exclude = [...DEFAULT_EXCLUDES, ...(params.exclude ?? [])];
96
+ const files = walkDir(params.path, params.file_types, exclude);
97
+ let filesIndexed = 0;
98
+ let filesSkipped = 0;
99
+ let chunksCreated = 0;
100
+ let totalTokens = 0;
101
+ const insertStmt = db.prepare(`INSERT OR REPLACE INTO codebase_files (id, project_id, file_path, file_type, content_hash, chunks)
102
+ VALUES (?, ?, ?, ?, ?, ?)`);
103
+ const checkStmt = db.prepare(`SELECT content_hash FROM codebase_files WHERE project_id = ? AND file_path = ?`);
104
+ const ingestAll = db.transaction(() => {
105
+ for (const filePath of files) {
106
+ let content;
107
+ try {
108
+ content = readFileSync(filePath, "utf8");
109
+ }
110
+ catch {
111
+ filesSkipped++;
112
+ continue;
113
+ }
114
+ const hash = contentHash(content);
115
+ const relPath = relative(params.path, filePath);
116
+ // Check if already indexed with same hash
117
+ const existing = checkStmt.get(projectId, relPath);
118
+ if (existing?.content_hash === hash) {
119
+ filesSkipped++;
120
+ continue;
121
+ }
122
+ const ext = extname(filePath).toLowerCase();
123
+ const chunks = chunkContent(content);
124
+ insertStmt.run(randomUUID(), projectId, relPath, ext, hash, JSON.stringify(chunks));
125
+ filesIndexed++;
126
+ chunksCreated += chunks.length;
127
+ totalTokens += estimateTokens(content);
128
+ }
129
+ });
130
+ ingestAll();
131
+ return {
132
+ files_scanned: files.length,
133
+ files_indexed: filesIndexed,
134
+ files_skipped: filesSkipped,
135
+ chunks_created: chunksCreated,
136
+ total_tokens: totalTokens,
137
+ };
138
+ }
139
+ //# sourceMappingURL=project.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"project.js","sourceRoot":"","sources":["../../src/handlers/project.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ import type Database from "better-sqlite3";
2
+ export declare function sessionSnapshot(db: Database.Database, projectId: string, snapshotsPath: string, params: {
3
+ label: string;
4
+ include_env?: boolean;
5
+ }): {
6
+ id: `${string}-${string}-${string}-${string}-${string}`;
7
+ label: string;
8
+ memories_count: number;
9
+ artifacts_count: number;
10
+ env_vars_count: number;
11
+ size_mb: string;
12
+ path: string;
13
+ };
14
+ export declare function sessionRehydrate(db: Database.Database, projectId: string, snapshotsPath: string, params: {
15
+ snapshot_id: string;
16
+ target_tool: string;
17
+ }): {
18
+ label: string;
19
+ memories_restored: number;
20
+ artifacts_restored: number;
21
+ env_vars_restored: number;
22
+ config_content: string;
23
+ target_tool: string;
24
+ };
25
+ //# sourceMappingURL=session.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../../src/handlers/session.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,QAAQ,MAAM,gBAAgB,CAAC;AAoB3C,wBAAgB,eAAe,CAC7B,EAAE,EAAE,QAAQ,CAAC,QAAQ,EACrB,SAAS,EAAE,MAAM,EACjB,aAAa,EAAE,MAAM,EACrB,MAAM,EAAE;IACN,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;;;;;;;;EA8FF;AAED,wBAAgB,gBAAgB,CAC9B,EAAE,EAAE,QAAQ,CAAC,QAAQ,EACrB,SAAS,EAAE,MAAM,EACjB,aAAa,EAAE,MAAM,EACrB,MAAM,EAAE;IACN,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;CACrB;;;;;;;EA+HF"}
@@ -0,0 +1,155 @@
1
+ import { randomUUID } from "node:crypto";
2
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
3
+ import { hostname } from "node:os";
4
+ import { join } from "node:path";
5
+ import { generateConfig } from "../utils/templates.js";
6
+ export function sessionSnapshot(db, projectId, snapshotsPath, params) {
7
+ const snapId = randomUUID();
8
+ // Gather memories
9
+ const memories = db
10
+ .prepare(`SELECT * FROM memories WHERE project_id = ? AND superseded_by IS NULL`)
11
+ .all(projectId);
12
+ // Gather artifacts
13
+ const artifacts = db
14
+ .prepare(`SELECT * FROM artifacts WHERE project_id = ? AND status = 'active'`)
15
+ .all(projectId);
16
+ // Gather env vars
17
+ const env = {};
18
+ if (params.include_env !== false) {
19
+ for (const [key, value] of Object.entries(process.env)) {
20
+ if (key.startsWith("BBB_") && value) {
21
+ env[key] = value;
22
+ }
23
+ }
24
+ }
25
+ // Gather project config
26
+ const configRows = db
27
+ .prepare(`SELECT key, value FROM project_config`)
28
+ .all();
29
+ const config = {};
30
+ for (const row of configRows) {
31
+ try {
32
+ config[row.key] = JSON.parse(row.value);
33
+ }
34
+ catch {
35
+ config[row.key] = row.value;
36
+ }
37
+ }
38
+ // Gather active tasks
39
+ const activeTasks = db
40
+ .prepare(`SELECT id, title, status FROM tasks WHERE project_id = ? AND status != 'done'`)
41
+ .all(projectId);
42
+ const snapshotData = {
43
+ id: snapId,
44
+ label: params.label,
45
+ project: projectId,
46
+ tool: "mcp-client",
47
+ machine: hostname(),
48
+ created_at: new Date().toISOString(),
49
+ memories,
50
+ artifacts,
51
+ env,
52
+ config,
53
+ };
54
+ // Save to DB
55
+ db.prepare(`INSERT INTO session_snapshots (id, project_id, snapshot_name, context_summary, active_tasks, working_memory, source_tool, snapshot_data)
56
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?)`).run(snapId, projectId, params.label, `Snapshot: ${params.label} — ${memories.length} memories, ${artifacts.length} artifacts`, JSON.stringify(activeTasks), JSON.stringify(memories.map((m) => ({ id: m.id, title: m.title, category: m.category }))), "mcp-client", JSON.stringify(snapshotData));
57
+ // Save to filesystem
58
+ if (!existsSync(snapshotsPath)) {
59
+ mkdirSync(snapshotsPath, { recursive: true });
60
+ }
61
+ const snapshotPath = join(snapshotsPath, `${snapId}.json`);
62
+ writeFileSync(snapshotPath, JSON.stringify(snapshotData, null, 2));
63
+ const sizeMb = (Buffer.byteLength(JSON.stringify(snapshotData)) / (1024 * 1024)).toFixed(2);
64
+ return {
65
+ id: snapId,
66
+ label: params.label,
67
+ memories_count: memories.length,
68
+ artifacts_count: artifacts.length,
69
+ env_vars_count: Object.keys(env).length,
70
+ size_mb: sizeMb,
71
+ path: snapshotPath,
72
+ };
73
+ }
74
+ export function sessionRehydrate(db, projectId, snapshotsPath, params) {
75
+ // Try loading from DB first
76
+ let snapshotData = null;
77
+ const dbRow = db
78
+ .prepare(`SELECT snapshot_data FROM session_snapshots WHERE id = ?`)
79
+ .get(params.snapshot_id);
80
+ if (dbRow) {
81
+ snapshotData = JSON.parse(dbRow.snapshot_data);
82
+ }
83
+ else {
84
+ // Try filesystem
85
+ const filePath = join(snapshotsPath, `${params.snapshot_id}.json`);
86
+ if (existsSync(filePath)) {
87
+ snapshotData = JSON.parse(readFileSync(filePath, "utf8"));
88
+ }
89
+ }
90
+ if (!snapshotData) {
91
+ throw new Error(`Snapshot not found: ${params.snapshot_id}`);
92
+ }
93
+ // UPSERT memories — merge by updated_at
94
+ const upsertMemory = db.prepare(`INSERT INTO memories (id, project_id, category, title, content, tags, source, source_ref, confidence, version, created_at, updated_at)
95
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
96
+ ON CONFLICT(id) DO UPDATE SET
97
+ title = CASE WHEN excluded.updated_at > memories.updated_at THEN excluded.title ELSE memories.title END,
98
+ content = CASE WHEN excluded.updated_at > memories.updated_at THEN excluded.content ELSE memories.content END,
99
+ tags = CASE WHEN excluded.updated_at > memories.updated_at THEN excluded.tags ELSE memories.tags END,
100
+ updated_at = MAX(excluded.updated_at, memories.updated_at)`);
101
+ const upsertArtifact = db.prepare(`INSERT INTO artifacts (id, project_id, type, schema_id, title, content, payload, version, hash, status, tags, source_refs, created_at, updated_at)
102
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
103
+ ON CONFLICT(id) DO UPDATE SET
104
+ title = CASE WHEN excluded.version >= artifacts.version THEN excluded.title ELSE artifacts.title END,
105
+ content = CASE WHEN excluded.version >= artifacts.version THEN excluded.content ELSE artifacts.content END,
106
+ version = MAX(excluded.version, artifacts.version),
107
+ updated_at = MAX(excluded.updated_at, artifacts.updated_at)`);
108
+ const restoreAll = db.transaction(() => {
109
+ for (const m of snapshotData.memories) {
110
+ upsertMemory.run(m.id, projectId, m.category, m.title, m.content, m.tags ?? "[]", m.source ?? null, m.source_ref ?? null, m.confidence ?? 1.0, m.version ?? 1, m.created_at, m.updated_at);
111
+ }
112
+ for (const a of snapshotData.artifacts) {
113
+ upsertArtifact.run(a.id, projectId, a.type, a.schema_id ?? null, a.title, a.content ?? null, a.payload ?? "{}", a.version ?? 1, a.hash ?? null, a.status ?? "active", a.tags ?? "[]", a.source_refs ?? "[]", a.created_at, a.updated_at);
114
+ }
115
+ // Restore project_config
116
+ const upsertConfig = db.prepare(`INSERT OR REPLACE INTO project_config (key, value) VALUES (?, ?)`);
117
+ for (const [key, value] of Object.entries(snapshotData.config)) {
118
+ upsertConfig.run(key, JSON.stringify(value));
119
+ }
120
+ });
121
+ restoreAll();
122
+ // Get project info for template
123
+ const project = db
124
+ .prepare(`SELECT * FROM projects WHERE id = ? OR slug = ?`)
125
+ .get(projectId, projectId);
126
+ // Generate target tool config
127
+ const templateData = {
128
+ project: project?.slug ?? projectId,
129
+ description: project?.description ?? undefined,
130
+ snapshotId: params.snapshot_id,
131
+ snapshotLabel: snapshotData.label,
132
+ date: new Date().toISOString(),
133
+ memories: snapshotData.memories.map((m) => ({
134
+ category: m.category,
135
+ title: m.title,
136
+ content: m.content,
137
+ })),
138
+ artifacts: snapshotData.artifacts.map((a) => ({
139
+ type: a.type,
140
+ title: a.title,
141
+ content: a.content ?? "",
142
+ })),
143
+ env: snapshotData.env,
144
+ };
145
+ const configContent = generateConfig(params.target_tool, templateData);
146
+ return {
147
+ label: snapshotData.label,
148
+ memories_restored: snapshotData.memories.length,
149
+ artifacts_restored: snapshotData.artifacts.length,
150
+ env_vars_restored: Object.keys(snapshotData.env).length,
151
+ config_content: configContent,
152
+ target_tool: params.target_tool,
153
+ };
154
+ }
155
+ //# sourceMappingURL=session.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session.js","sourceRoot":"","sources":["../../src/handlers/session.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,41 @@
1
+ import type Database from "better-sqlite3";
2
+ export declare function taskCreate(db: Database.Database, projectId: string, params: {
3
+ title: string;
4
+ description?: string;
5
+ status?: string;
6
+ owner_role?: string;
7
+ acceptance_criteria?: string[];
8
+ linked_artifacts?: string[];
9
+ dependencies?: string[];
10
+ }): {
11
+ id: `${string}-${string}-${string}-${string}-${string}`;
12
+ status: string;
13
+ };
14
+ export declare function taskUpdate(db: Database.Database, projectId: string, params: {
15
+ task_id: string;
16
+ title?: string;
17
+ description?: string;
18
+ status?: string;
19
+ owner_role?: string;
20
+ acceptance_criteria?: string[];
21
+ linked_artifacts?: string[];
22
+ dependencies?: string[];
23
+ }): {
24
+ id: string;
25
+ updated: boolean;
26
+ };
27
+ export declare function taskGetDag(db: Database.Database, projectId: string, params: {
28
+ status?: string;
29
+ }): {
30
+ id: string;
31
+ title: string;
32
+ description: string | null;
33
+ status: string;
34
+ owner_role: string | null;
35
+ created_at: string;
36
+ updated_at: string;
37
+ dependencies: string[];
38
+ linked_artifacts: string[];
39
+ acceptance_criteria: string[];
40
+ }[];
41
+ //# sourceMappingURL=task.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"task.d.ts","sourceRoot":"","sources":["../../src/handlers/task.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,QAAQ,MAAM,gBAAgB,CAAC;AAG3C,wBAAgB,UAAU,CACxB,EAAE,EAAE,QAAQ,CAAC,QAAQ,EACrB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE;IACN,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,mBAAmB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC/B,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC5B,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;CACzB;;;EAoBF;AAED,wBAAgB,UAAU,CACxB,EAAE,EAAE,QAAQ,CAAC,QAAQ,EACrB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE;IACN,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,mBAAmB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC/B,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC5B,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;CACzB;;;EAoDF;AAED,wBAAgB,UAAU,CACxB,EAAE,EAAE,QAAQ,CAAC,QAAQ,EACrB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE;IACN,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;QAkBgB,MAAM;WACA,MAAM;iBACM,MAAM,GAAG,IAAI;YACvB,MAAM;gBACE,MAAM,GAAG,IAAI;gBACb,MAAM;gBACN,MAAM;kBAC8B,MAAM,EAAE;sBACA,MAAM,EAAE;yBACF,MAAM,EAAE;IAI5F"}
@@ -0,0 +1,76 @@
1
+ import { randomUUID } from "node:crypto";
2
+ export function taskCreate(db, projectId, params) {
3
+ const id = randomUUID();
4
+ db.prepare(`INSERT INTO tasks (id, project_id, title, description, status, owner_role, acceptance_criteria, linked_artifacts, dependencies)
5
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(id, projectId, params.title, params.description ?? null, params.status ?? "pending", params.owner_role ?? null, JSON.stringify(params.acceptance_criteria ?? []), JSON.stringify(params.linked_artifacts ?? []), JSON.stringify(params.dependencies ?? []));
6
+ return { id, status: params.status ?? "pending" };
7
+ }
8
+ export function taskUpdate(db, projectId, params) {
9
+ const existing = db
10
+ .prepare(`SELECT * FROM tasks WHERE id = ? AND project_id = ?`)
11
+ .get(params.task_id, projectId);
12
+ if (!existing) {
13
+ throw new Error(`Task not found: ${params.task_id}`);
14
+ }
15
+ const sets = [];
16
+ const values = [];
17
+ if (params.title !== undefined) {
18
+ sets.push("title = ?");
19
+ values.push(params.title);
20
+ }
21
+ if (params.description !== undefined) {
22
+ sets.push("description = ?");
23
+ values.push(params.description);
24
+ }
25
+ if (params.status !== undefined) {
26
+ sets.push("status = ?");
27
+ values.push(params.status);
28
+ }
29
+ if (params.owner_role !== undefined) {
30
+ sets.push("owner_role = ?");
31
+ values.push(params.owner_role);
32
+ }
33
+ if (params.acceptance_criteria !== undefined) {
34
+ sets.push("acceptance_criteria = ?");
35
+ values.push(JSON.stringify(params.acceptance_criteria));
36
+ }
37
+ if (params.linked_artifacts !== undefined) {
38
+ sets.push("linked_artifacts = ?");
39
+ values.push(JSON.stringify(params.linked_artifacts));
40
+ }
41
+ if (params.dependencies !== undefined) {
42
+ sets.push("dependencies = ?");
43
+ values.push(JSON.stringify(params.dependencies));
44
+ }
45
+ if (sets.length === 0)
46
+ return { id: params.task_id, updated: false };
47
+ sets.push("updated_at = datetime('now')");
48
+ values.push(params.task_id, projectId);
49
+ db.prepare(`UPDATE tasks SET ${sets.join(", ")} WHERE id = ? AND project_id = ?`).run(...values);
50
+ return { id: params.task_id, updated: true };
51
+ }
52
+ export function taskGetDag(db, projectId, params) {
53
+ let sql = `SELECT * FROM tasks WHERE project_id = ?`;
54
+ const sqlParams = [projectId];
55
+ if (params.status) {
56
+ sql += ` AND status = ?`;
57
+ sqlParams.push(params.status);
58
+ }
59
+ sql += ` ORDER BY created_at ASC`;
60
+ const tasks = db.prepare(sql).all(...sqlParams);
61
+ // Build dependency graph
62
+ const graph = tasks.map((task) => ({
63
+ id: task.id,
64
+ title: task.title,
65
+ description: task.description,
66
+ status: task.status,
67
+ owner_role: task.owner_role,
68
+ created_at: task.created_at,
69
+ updated_at: task.updated_at,
70
+ dependencies: JSON.parse(task.dependencies || "[]"),
71
+ linked_artifacts: JSON.parse(task.linked_artifacts || "[]"),
72
+ acceptance_criteria: JSON.parse(task.acceptance_criteria || "[]"),
73
+ }));
74
+ return graph;
75
+ }
76
+ //# sourceMappingURL=task.js.map