chronicle-ai 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +132 -0
- package/package.json +86 -0
- package/packages/README.md +139 -0
- package/packages/cli/README.md +92 -0
- package/packages/cli/bin/chronicle.js +2 -0
- package/packages/cli/dist/commands/add.d.ts +2 -0
- package/packages/cli/dist/commands/add.d.ts.map +1 -0
- package/packages/cli/dist/commands/add.js +82 -0
- package/packages/cli/dist/commands/add.js.map +1 -0
- package/packages/cli/dist/commands/diff.d.ts +11 -0
- package/packages/cli/dist/commands/diff.d.ts.map +1 -0
- package/packages/cli/dist/commands/diff.js +164 -0
- package/packages/cli/dist/commands/diff.js.map +1 -0
- package/packages/cli/dist/commands/init.d.ts +2 -0
- package/packages/cli/dist/commands/init.d.ts.map +1 -0
- package/packages/cli/dist/commands/init.js +54 -0
- package/packages/cli/dist/commands/init.js.map +1 -0
- package/packages/cli/dist/commands/list.d.ts +2 -0
- package/packages/cli/dist/commands/list.d.ts.map +1 -0
- package/packages/cli/dist/commands/list.js +62 -0
- package/packages/cli/dist/commands/list.js.map +1 -0
- package/packages/cli/dist/commands/log.d.ts +4 -0
- package/packages/cli/dist/commands/log.d.ts.map +1 -0
- package/packages/cli/dist/commands/log.js +223 -0
- package/packages/cli/dist/commands/log.js.map +1 -0
- package/packages/cli/dist/commands/pause.d.ts +3 -0
- package/packages/cli/dist/commands/pause.d.ts.map +1 -0
- package/packages/cli/dist/commands/pause.js +49 -0
- package/packages/cli/dist/commands/pause.js.map +1 -0
- package/packages/cli/dist/commands/queue.d.ts +2 -0
- package/packages/cli/dist/commands/queue.d.ts.map +1 -0
- package/packages/cli/dist/commands/queue.js +96 -0
- package/packages/cli/dist/commands/queue.js.map +1 -0
- package/packages/cli/dist/commands/remove.d.ts +2 -0
- package/packages/cli/dist/commands/remove.d.ts.map +1 -0
- package/packages/cli/dist/commands/remove.js +80 -0
- package/packages/cli/dist/commands/remove.js.map +1 -0
- package/packages/cli/dist/commands/reset.d.ts +5 -0
- package/packages/cli/dist/commands/reset.d.ts.map +1 -0
- package/packages/cli/dist/commands/reset.js +90 -0
- package/packages/cli/dist/commands/reset.js.map +1 -0
- package/packages/cli/dist/commands/restart.d.ts +2 -0
- package/packages/cli/dist/commands/restart.d.ts.map +1 -0
- package/packages/cli/dist/commands/restart.js +72 -0
- package/packages/cli/dist/commands/restart.js.map +1 -0
- package/packages/cli/dist/commands/start.d.ts +2 -0
- package/packages/cli/dist/commands/start.d.ts.map +1 -0
- package/packages/cli/dist/commands/start.js +127 -0
- package/packages/cli/dist/commands/start.js.map +1 -0
- package/packages/cli/dist/commands/status.d.ts +2 -0
- package/packages/cli/dist/commands/status.d.ts.map +1 -0
- package/packages/cli/dist/commands/status.js +181 -0
- package/packages/cli/dist/commands/status.js.map +1 -0
- package/packages/cli/dist/commands/stop.d.ts +2 -0
- package/packages/cli/dist/commands/stop.d.ts.map +1 -0
- package/packages/cli/dist/commands/stop.js +64 -0
- package/packages/cli/dist/commands/stop.js.map +1 -0
- package/packages/cli/dist/index.d.ts +2 -0
- package/packages/cli/dist/index.d.ts.map +1 -0
- package/packages/cli/dist/index.js +85 -0
- package/packages/cli/dist/index.js.map +1 -0
- package/packages/cli/dist/utils/paths.d.ts +26 -0
- package/packages/cli/dist/utils/paths.d.ts.map +1 -0
- package/packages/cli/dist/utils/paths.js +183 -0
- package/packages/cli/dist/utils/paths.js.map +1 -0
- package/packages/cli/package.json +25 -0
- package/packages/daemon/README.md +83 -0
- package/packages/daemon/dist/ai_test.d.ts +2 -0
- package/packages/daemon/dist/ai_test.d.ts.map +1 -0
- package/packages/daemon/dist/ai_test.js +4 -0
- package/packages/daemon/dist/ai_test.js.map +1 -0
- package/packages/daemon/dist/index.d.ts +2 -0
- package/packages/daemon/dist/index.d.ts.map +1 -0
- package/packages/daemon/dist/index.js +147 -0
- package/packages/daemon/dist/index.js.map +1 -0
- package/packages/daemon/dist/jobs/AIProcessor.d.ts +6 -0
- package/packages/daemon/dist/jobs/AIProcessor.d.ts.map +1 -0
- package/packages/daemon/dist/jobs/AIProcessor.js +58 -0
- package/packages/daemon/dist/jobs/AIProcessor.js.map +1 -0
- package/packages/daemon/dist/jobs/DocProcessor.d.ts +8 -0
- package/packages/daemon/dist/jobs/DocProcessor.d.ts.map +1 -0
- package/packages/daemon/dist/jobs/DocProcessor.js +336 -0
- package/packages/daemon/dist/jobs/DocProcessor.js.map +1 -0
- package/packages/daemon/dist/jobs/FileProcessor.d.ts +7 -0
- package/packages/daemon/dist/jobs/FileProcessor.d.ts.map +1 -0
- package/packages/daemon/dist/jobs/FileProcessor.js +29 -0
- package/packages/daemon/dist/jobs/FileProcessor.js.map +1 -0
- package/packages/daemon/dist/jobs/SystemProcessor.d.ts +13 -0
- package/packages/daemon/dist/jobs/SystemProcessor.d.ts.map +1 -0
- package/packages/daemon/dist/jobs/SystemProcessor.js +38 -0
- package/packages/daemon/dist/jobs/SystemProcessor.js.map +1 -0
- package/packages/daemon/dist/jobs/UpdateProcessor.d.ts +21 -0
- package/packages/daemon/dist/jobs/UpdateProcessor.d.ts.map +1 -0
- package/packages/daemon/dist/jobs/UpdateProcessor.js +222 -0
- package/packages/daemon/dist/jobs/UpdateProcessor.js.map +1 -0
- package/packages/daemon/dist/services/AIService.d.ts +90 -0
- package/packages/daemon/dist/services/AIService.d.ts.map +1 -0
- package/packages/daemon/dist/services/AIService.js +451 -0
- package/packages/daemon/dist/services/AIService.js.map +1 -0
- package/packages/daemon/dist/services/ConfigService.d.ts +30 -0
- package/packages/daemon/dist/services/ConfigService.d.ts.map +1 -0
- package/packages/daemon/dist/services/ConfigService.js +69 -0
- package/packages/daemon/dist/services/ConfigService.js.map +1 -0
- package/packages/daemon/dist/services/DatabaseService.d.ts +204 -0
- package/packages/daemon/dist/services/DatabaseService.d.ts.map +1 -0
- package/packages/daemon/dist/services/DatabaseService.js +692 -0
- package/packages/daemon/dist/services/DatabaseService.js.map +1 -0
- package/packages/daemon/dist/services/GitService.d.ts +12 -0
- package/packages/daemon/dist/services/GitService.d.ts.map +1 -0
- package/packages/daemon/dist/services/GitService.js +68 -0
- package/packages/daemon/dist/services/GitService.js.map +1 -0
- package/packages/daemon/dist/services/QueueService.d.ts +16 -0
- package/packages/daemon/dist/services/QueueService.d.ts.map +1 -0
- package/packages/daemon/dist/services/QueueService.js +87 -0
- package/packages/daemon/dist/services/QueueService.js.map +1 -0
- package/packages/daemon/dist/services/TriggerService.d.ts +37 -0
- package/packages/daemon/dist/services/TriggerService.d.ts.map +1 -0
- package/packages/daemon/dist/services/TriggerService.js +150 -0
- package/packages/daemon/dist/services/TriggerService.js.map +1 -0
- package/packages/daemon/dist/services/WatcherService.d.ts +12 -0
- package/packages/daemon/dist/services/WatcherService.d.ts.map +1 -0
- package/packages/daemon/dist/services/WatcherService.js +77 -0
- package/packages/daemon/dist/services/WatcherService.js.map +1 -0
- package/packages/daemon/dist/services/index.d.ts +2 -0
- package/packages/daemon/dist/services/index.d.ts.map +1 -0
- package/packages/daemon/dist/services/index.js +18 -0
- package/packages/daemon/dist/services/index.js.map +1 -0
- package/packages/daemon/dist/test-ignore.js +0 -0
- package/packages/daemon/package.json +28 -0
- package/packages/ui/app/actions.ts +73 -0
- package/packages/ui/app/api/ai-activity/route.ts +14 -0
- package/packages/ui/app/globals.css +98 -0
- package/packages/ui/app/layout.tsx +29 -0
- package/packages/ui/app/page.tsx +109 -0
- package/packages/ui/components/AutoRefresh.tsx +18 -0
- package/packages/ui/components/DocumentationViewer.tsx +276 -0
- package/packages/ui/components/FileList.tsx +69 -0
- package/packages/ui/components/HeaderWithThinking.tsx +102 -0
- package/packages/ui/components/JobQueue.tsx +194 -0
- package/packages/ui/components/JobQueueWrapper.tsx +31 -0
- package/packages/ui/components/MermaidInit.tsx +24 -0
- package/packages/ui/components/ProjectContentArea.tsx +186 -0
- package/packages/ui/components/ProjectList.tsx +136 -0
- package/packages/ui/components/ThinkingDrawer.tsx +377 -0
- package/packages/ui/components/ThinkingPanel.tsx +63 -0
- package/packages/ui/components/TriggerSettings.tsx +185 -0
- package/packages/ui/components/VersionSelector.tsx +132 -0
- package/packages/ui/lib/db.ts +521 -0
- package/packages/ui/next-env.d.ts +5 -0
- package/packages/ui/next.config.js +4 -0
- package/packages/ui/package.json +32 -0
- package/packages/ui/postcss.config.js +6 -0
- package/packages/ui/public/logo.png +0 -0
- package/packages/ui/tailwind.config.ts +32 -0
- package/packages/ui/tsconfig.json +40 -0
|
@@ -0,0 +1,692 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.DatabaseService = void 0;
|
|
40
|
+
const better_sqlite3_1 = __importDefault(require("better-sqlite3"));
|
|
41
|
+
const path_1 = __importDefault(require("path"));
|
|
42
|
+
const fs_1 = __importDefault(require("fs"));
|
|
43
|
+
const sqliteVec = __importStar(require("sqlite-vec"));
|
|
44
|
+
class DatabaseService {
|
|
45
|
+
dataDir;
|
|
46
|
+
db;
|
|
47
|
+
constructor(dataDir = '.chronicle') {
|
|
48
|
+
this.dataDir = dataDir;
|
|
49
|
+
if (!fs_1.default.existsSync(dataDir)) {
|
|
50
|
+
fs_1.default.mkdirSync(dataDir, { recursive: true });
|
|
51
|
+
}
|
|
52
|
+
const dbPath = path_1.default.join(dataDir, 'db.sqlite');
|
|
53
|
+
this.db = new better_sqlite3_1.default(dbPath);
|
|
54
|
+
// Load sqlite-vec extension
|
|
55
|
+
try {
|
|
56
|
+
this.db.loadExtension(sqliteVec.getLoadablePath());
|
|
57
|
+
}
|
|
58
|
+
catch (e) {
|
|
59
|
+
console.warn('⚠️ Could not load sqlite-vec extension. Vector search will be disabled.', e);
|
|
60
|
+
}
|
|
61
|
+
this.initSchema();
|
|
62
|
+
}
|
|
63
|
+
initSchema() {
|
|
64
|
+
this.db.pragma('journal_mode = WAL');
|
|
65
|
+
// Structural Memory: Files
|
|
66
|
+
this.db.exec(`
|
|
67
|
+
CREATE TABLE IF NOT EXISTS files (
|
|
68
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
69
|
+
path TEXT UNIQUE NOT NULL,
|
|
70
|
+
hash TEXT,
|
|
71
|
+
last_modified INTEGER,
|
|
72
|
+
last_indexed INTEGER
|
|
73
|
+
);
|
|
74
|
+
`);
|
|
75
|
+
// Events: What happened
|
|
76
|
+
this.db.exec(`
|
|
77
|
+
CREATE TABLE IF NOT EXISTS events (
|
|
78
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
79
|
+
type TEXT NOT NULL,
|
|
80
|
+
payload TEXT,
|
|
81
|
+
created_at INTEGER DEFAULT (unixepoch())
|
|
82
|
+
);
|
|
83
|
+
`);
|
|
84
|
+
// Jobs: Persistent Queue
|
|
85
|
+
this.db.exec(`
|
|
86
|
+
CREATE TABLE IF NOT EXISTS jobs (
|
|
87
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
88
|
+
name TEXT NOT NULL,
|
|
89
|
+
data TEXT NOT NULL,
|
|
90
|
+
status TEXT DEFAULT 'pending', -- pending, processing, completed, failed
|
|
91
|
+
error TEXT,
|
|
92
|
+
created_at INTEGER DEFAULT (unixepoch()),
|
|
93
|
+
updated_at INTEGER DEFAULT (unixepoch())
|
|
94
|
+
);
|
|
95
|
+
`);
|
|
96
|
+
// Projects: Monitored Repositories
|
|
97
|
+
this.db.exec(`
|
|
98
|
+
CREATE TABLE IF NOT EXISTS projects (
|
|
99
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
100
|
+
path TEXT UNIQUE NOT NULL,
|
|
101
|
+
name TEXT,
|
|
102
|
+
type TEXT,
|
|
103
|
+
created_at INTEGER,
|
|
104
|
+
is_paused INTEGER DEFAULT 0
|
|
105
|
+
);
|
|
106
|
+
`);
|
|
107
|
+
// Migration: Add is_paused if missing
|
|
108
|
+
try {
|
|
109
|
+
this.db.exec('ALTER TABLE projects ADD COLUMN is_paused INTEGER DEFAULT 0');
|
|
110
|
+
}
|
|
111
|
+
catch (e) {
|
|
112
|
+
// Ignore if column exists
|
|
113
|
+
}
|
|
114
|
+
// Migration: Fix NULL timestamps in jobs table
|
|
115
|
+
try {
|
|
116
|
+
this.db.exec(`
|
|
117
|
+
UPDATE jobs SET created_at = unixepoch() WHERE created_at IS NULL OR created_at = 0;
|
|
118
|
+
UPDATE jobs SET updated_at = unixepoch() WHERE updated_at IS NULL OR updated_at = 0;
|
|
119
|
+
`);
|
|
120
|
+
}
|
|
121
|
+
catch (e) {
|
|
122
|
+
// Ignore errors
|
|
123
|
+
}
|
|
124
|
+
// Embeddings: Vector Store
|
|
125
|
+
try {
|
|
126
|
+
// 768 dimensions for Gemini Embeddings
|
|
127
|
+
this.db.exec(`
|
|
128
|
+
CREATE VIRTUAL TABLE IF NOT EXISTS embeddings USING vec0(
|
|
129
|
+
file_id INTEGER,
|
|
130
|
+
chunk_index INTEGER,
|
|
131
|
+
embedding FLOAT[768]
|
|
132
|
+
);
|
|
133
|
+
`);
|
|
134
|
+
}
|
|
135
|
+
catch (error) {
|
|
136
|
+
console.error('Failed to create embeddings table (sqlite-vec might be missing):', error);
|
|
137
|
+
}
|
|
138
|
+
// Doc Stages: Track multi-stage documentation progress
|
|
139
|
+
this.db.exec(`
|
|
140
|
+
CREATE TABLE IF NOT EXISTS doc_stages (
|
|
141
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
142
|
+
project_id INTEGER NOT NULL UNIQUE,
|
|
143
|
+
current_stage INTEGER DEFAULT 0,
|
|
144
|
+
total_stages INTEGER DEFAULT 4,
|
|
145
|
+
coverage_plan TEXT,
|
|
146
|
+
last_updated INTEGER DEFAULT (unixepoch()),
|
|
147
|
+
FOREIGN KEY (project_id) REFERENCES projects(id)
|
|
148
|
+
);
|
|
149
|
+
`);
|
|
150
|
+
// ===== Phase 1.5: Versioning Tables =====
|
|
151
|
+
// Doc Versions: Each generation run creates a version
|
|
152
|
+
this.db.exec(`
|
|
153
|
+
CREATE TABLE IF NOT EXISTS doc_versions (
|
|
154
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
155
|
+
project_id INTEGER NOT NULL,
|
|
156
|
+
version_number INTEGER NOT NULL,
|
|
157
|
+
trigger_type TEXT, -- 'init', 'on_change', 'on_commit', 'schedule', 'manual'
|
|
158
|
+
commit_hash TEXT,
|
|
159
|
+
status TEXT DEFAULT 'draft', -- draft, pending_review, active, archived
|
|
160
|
+
created_at INTEGER DEFAULT (unixepoch()),
|
|
161
|
+
FOREIGN KEY (project_id) REFERENCES projects(id)
|
|
162
|
+
);
|
|
163
|
+
`);
|
|
164
|
+
// Doc Files: Stores content for each version
|
|
165
|
+
this.db.exec(`
|
|
166
|
+
CREATE TABLE IF NOT EXISTS doc_files (
|
|
167
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
168
|
+
version_id INTEGER NOT NULL,
|
|
169
|
+
path TEXT NOT NULL,
|
|
170
|
+
content TEXT,
|
|
171
|
+
content_hash TEXT,
|
|
172
|
+
created_at INTEGER DEFAULT (unixepoch()),
|
|
173
|
+
FOREIGN KEY (version_id) REFERENCES doc_versions(id)
|
|
174
|
+
);
|
|
175
|
+
`);
|
|
176
|
+
// Thought Logs: Chain-of-thought for each doc file
|
|
177
|
+
this.db.exec(`
|
|
178
|
+
CREATE TABLE IF NOT EXISTS thought_logs (
|
|
179
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
180
|
+
version_id INTEGER NOT NULL,
|
|
181
|
+
doc_path TEXT,
|
|
182
|
+
thinking_summary TEXT,
|
|
183
|
+
created_at INTEGER DEFAULT (unixepoch()),
|
|
184
|
+
FOREIGN KEY (version_id) REFERENCES doc_versions(id)
|
|
185
|
+
);
|
|
186
|
+
`);
|
|
187
|
+
// Assumptions: Claims made in docs that need verification
|
|
188
|
+
this.db.exec(`
|
|
189
|
+
CREATE TABLE IF NOT EXISTS assumptions (
|
|
190
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
191
|
+
doc_file_id INTEGER NOT NULL,
|
|
192
|
+
claim TEXT NOT NULL,
|
|
193
|
+
verified INTEGER DEFAULT 0, -- 0 = unverified, 1 = verified, -1 = rejected
|
|
194
|
+
verification_method TEXT,
|
|
195
|
+
verified_at INTEGER,
|
|
196
|
+
FOREIGN KEY (doc_file_id) REFERENCES doc_files(id)
|
|
197
|
+
);
|
|
198
|
+
`);
|
|
199
|
+
// ===== Phase 1.6: AI Activity Logging =====
|
|
200
|
+
// AI Activity: Central log of all AI calls for the thinking platform
|
|
201
|
+
this.db.exec(`
|
|
202
|
+
CREATE TABLE IF NOT EXISTS ai_activity (
|
|
203
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
204
|
+
project_id INTEGER,
|
|
205
|
+
version_id INTEGER,
|
|
206
|
+
activity_type TEXT NOT NULL, -- 'analyze', 'generate', 'plan', 'embed', 'other'
|
|
207
|
+
prompt_summary TEXT,
|
|
208
|
+
response_preview TEXT,
|
|
209
|
+
thinking_summary TEXT,
|
|
210
|
+
tokens_used INTEGER,
|
|
211
|
+
duration_ms INTEGER,
|
|
212
|
+
status TEXT DEFAULT 'completed', -- 'running', 'completed', 'error'
|
|
213
|
+
created_at INTEGER DEFAULT (unixepoch() * 1000), -- Milliseconds for UI
|
|
214
|
+
FOREIGN KEY (project_id) REFERENCES projects(id),
|
|
215
|
+
FOREIGN KEY (version_id) REFERENCES doc_versions(id)
|
|
216
|
+
);
|
|
217
|
+
`);
|
|
218
|
+
// Create index for fast AI activity queries
|
|
219
|
+
this.db.exec(`
|
|
220
|
+
CREATE INDEX IF NOT EXISTS idx_ai_activity_created
|
|
221
|
+
ON ai_activity(created_at DESC);
|
|
222
|
+
`);
|
|
223
|
+
console.log('📦 Database initialized.');
|
|
224
|
+
}
|
|
225
|
+
init() {
|
|
226
|
+
// Public init for external use if needed
|
|
227
|
+
}
|
|
228
|
+
addProject(pathStr) {
|
|
229
|
+
const name = path_1.default.basename(pathStr);
|
|
230
|
+
return this.db.prepare(`
|
|
231
|
+
INSERT INTO projects (path, name, created_at)
|
|
232
|
+
VALUES (?, ?, unixepoch())
|
|
233
|
+
ON CONFLICT(path) DO NOTHING
|
|
234
|
+
`).run(pathStr, name);
|
|
235
|
+
}
|
|
236
|
+
removeProject(pathToRemove) {
|
|
237
|
+
// Normalize path - remove trailing slashes and resolve to absolute
|
|
238
|
+
let normalizedPath = pathToRemove.trim();
|
|
239
|
+
if (normalizedPath.endsWith('/') || normalizedPath.endsWith('\\')) {
|
|
240
|
+
normalizedPath = normalizedPath.slice(0, -1);
|
|
241
|
+
}
|
|
242
|
+
// Resolve to absolute path if not already absolute
|
|
243
|
+
if (!path_1.default.isAbsolute(normalizedPath)) {
|
|
244
|
+
normalizedPath = path_1.default.resolve(normalizedPath);
|
|
245
|
+
}
|
|
246
|
+
else {
|
|
247
|
+
normalizedPath = path_1.default.resolve(normalizedPath);
|
|
248
|
+
}
|
|
249
|
+
// Try exact match first
|
|
250
|
+
let result = this.db.prepare(`
|
|
251
|
+
DELETE FROM projects WHERE path = ?
|
|
252
|
+
`).run(normalizedPath);
|
|
253
|
+
// If no match, try to find by normalizing stored paths
|
|
254
|
+
if (result.changes === 0) {
|
|
255
|
+
const projects = this.getProjects();
|
|
256
|
+
for (const project of projects) {
|
|
257
|
+
let storedPath = project.path.trim();
|
|
258
|
+
if (storedPath.endsWith('/') || storedPath.endsWith('\\')) {
|
|
259
|
+
storedPath = storedPath.slice(0, -1);
|
|
260
|
+
}
|
|
261
|
+
storedPath = path_1.default.resolve(storedPath);
|
|
262
|
+
if (storedPath === normalizedPath) {
|
|
263
|
+
result = this.db.prepare(`
|
|
264
|
+
DELETE FROM projects WHERE id = ?
|
|
265
|
+
`).run(project.id);
|
|
266
|
+
console.log(`✅ Removed project by ID: ${project.id} (path matched after normalization)`);
|
|
267
|
+
break;
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
return result;
|
|
272
|
+
}
|
|
273
|
+
toggleProjectPaused(path, paused) {
|
|
274
|
+
return this.db.prepare(`
|
|
275
|
+
UPDATE projects SET is_paused = ? WHERE path = ?
|
|
276
|
+
`).run(paused ? 1 : 0, path);
|
|
277
|
+
}
|
|
278
|
+
getProjects() {
|
|
279
|
+
return this.db.prepare('SELECT * FROM projects').all();
|
|
280
|
+
}
|
|
281
|
+
getProjectByPath(path) {
|
|
282
|
+
return this.db.prepare('SELECT * FROM projects WHERE path = ?').get(path);
|
|
283
|
+
}
|
|
284
|
+
getFile(path) {
|
|
285
|
+
return this.db.prepare('SELECT * FROM files WHERE path = ?').get(path);
|
|
286
|
+
}
|
|
287
|
+
upsertFile(path, hash, mtime) {
|
|
288
|
+
return this.db.prepare(`
|
|
289
|
+
INSERT INTO files (path, hash, last_modified, last_indexed)
|
|
290
|
+
VALUES (?, ?, ?, unixepoch())
|
|
291
|
+
ON CONFLICT(path) DO UPDATE SET
|
|
292
|
+
hash = excluded.hash,
|
|
293
|
+
last_modified = excluded.last_modified,
|
|
294
|
+
last_indexed = unixepoch()
|
|
295
|
+
`).run(path, hash, mtime);
|
|
296
|
+
}
|
|
297
|
+
logEvent(type, payload) {
|
|
298
|
+
return this.db.prepare(`
|
|
299
|
+
INSERT INTO events (type, payload)
|
|
300
|
+
VALUES (?, ?)
|
|
301
|
+
`).run(type, JSON.stringify(payload));
|
|
302
|
+
}
|
|
303
|
+
raw() {
|
|
304
|
+
return this.db;
|
|
305
|
+
}
|
|
306
|
+
findSimilarSegments(vector, limit = 5) {
|
|
307
|
+
// vec0 search syntax:
|
|
308
|
+
// SELECT rowid, distance FROM embeddings WHERE embedding MATCH ? ORDER BY distance LIMIT ?
|
|
309
|
+
// Note: 'embedding' column in WHERE clause, standard pattern for virtual tables.
|
|
310
|
+
// Ensure vector is Float32Array
|
|
311
|
+
const floatVector = new Float32Array(vector);
|
|
312
|
+
const results = this.db.prepare(`
|
|
313
|
+
SELECT
|
|
314
|
+
e.file_id,
|
|
315
|
+
e.chunk_index,
|
|
316
|
+
distance
|
|
317
|
+
FROM embeddings e
|
|
318
|
+
WHERE embedding MATCH ?
|
|
319
|
+
ORDER BY distance
|
|
320
|
+
LIMIT ?
|
|
321
|
+
`).all(floatVector, limit);
|
|
322
|
+
// Hydrate with file info
|
|
323
|
+
return results.map(r => {
|
|
324
|
+
const file = this.db.prepare('SELECT path FROM files WHERE id = ?').get(r.file_id);
|
|
325
|
+
return {
|
|
326
|
+
filePath: file ? file.path : 'unknown',
|
|
327
|
+
score: r.distance, // lower is better in Euclidean? check sqlite-vec config. Default L2.
|
|
328
|
+
...r
|
|
329
|
+
};
|
|
330
|
+
});
|
|
331
|
+
}
|
|
332
|
+
// --- Job Queue Methods ---
|
|
333
|
+
enqueueJob(name, data) {
|
|
334
|
+
return this.db.prepare(`
|
|
335
|
+
INSERT INTO jobs (name, data, status)
|
|
336
|
+
VALUES (?, ?, 'pending')
|
|
337
|
+
`).run(name, JSON.stringify(data));
|
|
338
|
+
}
|
|
339
|
+
getNextPendingJob() {
|
|
340
|
+
// Simple FIFO: get oldest pending job
|
|
341
|
+
const job = this.db.prepare(`
|
|
342
|
+
SELECT * FROM jobs
|
|
343
|
+
WHERE status = 'pending'
|
|
344
|
+
ORDER BY created_at ASC
|
|
345
|
+
LIMIT 1
|
|
346
|
+
`).get();
|
|
347
|
+
return job ? { ...job, data: JSON.parse(job.data) } : null;
|
|
348
|
+
}
|
|
349
|
+
updateJobStatus(id, status, error) {
|
|
350
|
+
return this.db.prepare(`
|
|
351
|
+
UPDATE jobs
|
|
352
|
+
SET status = ?, error = ?, updated_at = unixepoch()
|
|
353
|
+
WHERE id = ?
|
|
354
|
+
`).run(status, error || null, id);
|
|
355
|
+
}
|
|
356
|
+
resetProcessingJobs() {
|
|
357
|
+
// On startup, reset 'processing' jobs to 'pending' so they aren't lost
|
|
358
|
+
return this.db.prepare(`
|
|
359
|
+
UPDATE jobs
|
|
360
|
+
SET status = 'pending'
|
|
361
|
+
WHERE status = 'processing'
|
|
362
|
+
`).run();
|
|
363
|
+
}
|
|
364
|
+
/**
|
|
365
|
+
* Clears all pending jobs from the queue.
|
|
366
|
+
*/
|
|
367
|
+
clearPendingJobs() {
|
|
368
|
+
return this.db.prepare(`
|
|
369
|
+
DELETE FROM jobs WHERE status = 'pending'
|
|
370
|
+
`).run();
|
|
371
|
+
}
|
|
372
|
+
/**
|
|
373
|
+
* Cancels (marks as failed) the currently processing job.
|
|
374
|
+
*/
|
|
375
|
+
cancelCurrentJob() {
|
|
376
|
+
return this.db.prepare(`
|
|
377
|
+
UPDATE jobs
|
|
378
|
+
SET status = 'failed', error = 'Cancelled by user', updated_at = unixepoch()
|
|
379
|
+
WHERE status = 'processing'
|
|
380
|
+
`).run();
|
|
381
|
+
}
|
|
382
|
+
/**
|
|
383
|
+
* Clears the entire queue (pending jobs) and cancels current job.
|
|
384
|
+
*/
|
|
385
|
+
clearQueue() {
|
|
386
|
+
this.cancelCurrentJob();
|
|
387
|
+
return this.clearPendingJobs();
|
|
388
|
+
}
|
|
389
|
+
/**
|
|
390
|
+
* Gets count of pending jobs.
|
|
391
|
+
*/
|
|
392
|
+
getPendingJobCount() {
|
|
393
|
+
const result = this.db.prepare(`SELECT COUNT(*) as count FROM jobs WHERE status = 'pending'`).get();
|
|
394
|
+
return result.count;
|
|
395
|
+
}
|
|
396
|
+
// ===== Doc Stage Management =====
|
|
397
|
+
/**
|
|
398
|
+
* Gets the documentation stage for a project.
|
|
399
|
+
*/
|
|
400
|
+
getDocStage(projectId) {
|
|
401
|
+
const result = this.db.prepare(`
|
|
402
|
+
SELECT current_stage, total_stages, coverage_plan FROM doc_stages WHERE project_id = ?
|
|
403
|
+
`).get(projectId);
|
|
404
|
+
if (!result)
|
|
405
|
+
return null;
|
|
406
|
+
return {
|
|
407
|
+
currentStage: result.current_stage,
|
|
408
|
+
totalStages: result.total_stages,
|
|
409
|
+
coveragePlan: result.coverage_plan
|
|
410
|
+
};
|
|
411
|
+
}
|
|
412
|
+
/**
|
|
413
|
+
* Creates or resets doc stage for a project.
|
|
414
|
+
*/
|
|
415
|
+
setDocStage(projectId, coveragePlan, totalStages = 4) {
|
|
416
|
+
this.db.prepare(`
|
|
417
|
+
INSERT INTO doc_stages (project_id, current_stage, total_stages, coverage_plan, last_updated)
|
|
418
|
+
VALUES (?, 0, ?, ?, unixepoch())
|
|
419
|
+
ON CONFLICT(project_id) DO UPDATE SET
|
|
420
|
+
current_stage = 0,
|
|
421
|
+
total_stages = excluded.total_stages,
|
|
422
|
+
coverage_plan = excluded.coverage_plan,
|
|
423
|
+
last_updated = unixepoch()
|
|
424
|
+
`).run(projectId, totalStages, coveragePlan);
|
|
425
|
+
}
|
|
426
|
+
/**
|
|
427
|
+
* Updates the current stage for a project.
|
|
428
|
+
*/
|
|
429
|
+
updateDocStage(projectId, stage) {
|
|
430
|
+
this.db.prepare(`
|
|
431
|
+
UPDATE doc_stages SET current_stage = ?, last_updated = unixepoch() WHERE project_id = ?
|
|
432
|
+
`).run(stage, projectId);
|
|
433
|
+
}
|
|
434
|
+
/**
|
|
435
|
+
* Resets the doc stage to 0 (hides the stage counter in UI).
|
|
436
|
+
*/
|
|
437
|
+
resetDocStage(projectId) {
|
|
438
|
+
this.db.prepare(`
|
|
439
|
+
UPDATE doc_stages SET current_stage = 0, last_updated = unixepoch() WHERE project_id = ?
|
|
440
|
+
`).run(projectId);
|
|
441
|
+
}
|
|
442
|
+
/**
|
|
443
|
+
* Gets coverage plan JSON for a project.
|
|
444
|
+
*/
|
|
445
|
+
getDocCoveragePlan(projectId) {
|
|
446
|
+
const result = this.db.prepare(`
|
|
447
|
+
SELECT coverage_plan FROM doc_stages WHERE project_id = ?
|
|
448
|
+
`).get(projectId);
|
|
449
|
+
if (!result || !result.coverage_plan)
|
|
450
|
+
return null;
|
|
451
|
+
try {
|
|
452
|
+
return JSON.parse(result.coverage_plan);
|
|
453
|
+
}
|
|
454
|
+
catch {
|
|
455
|
+
return null;
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
// ===== Doc Version Management =====
|
|
459
|
+
/**
|
|
460
|
+
* Creates a new doc version for a project.
|
|
461
|
+
*/
|
|
462
|
+
createDocVersion(projectId, triggerType, commitHash) {
|
|
463
|
+
// Get next version number
|
|
464
|
+
const latest = this.db.prepare(`
|
|
465
|
+
SELECT MAX(version_number) as max_version FROM doc_versions WHERE project_id = ?
|
|
466
|
+
`).get(projectId);
|
|
467
|
+
const nextVersion = (latest?.max_version ?? 0) + 1;
|
|
468
|
+
const result = this.db.prepare(`
|
|
469
|
+
INSERT INTO doc_versions (project_id, version_number, trigger_type, commit_hash, status)
|
|
470
|
+
VALUES (?, ?, ?, ?, 'draft')
|
|
471
|
+
`).run(projectId, nextVersion, triggerType, commitHash || null);
|
|
472
|
+
return Number(result.lastInsertRowid);
|
|
473
|
+
}
|
|
474
|
+
/**
|
|
475
|
+
* Adds a doc file to a version.
|
|
476
|
+
*/
|
|
477
|
+
addDocFile(versionId, path, content) {
|
|
478
|
+
const hash = require('crypto').createHash('md5').update(content).digest('hex');
|
|
479
|
+
const result = this.db.prepare(`
|
|
480
|
+
INSERT INTO doc_files (version_id, path, content, content_hash)
|
|
481
|
+
VALUES (?, ?, ?, ?)
|
|
482
|
+
`).run(versionId, path, content, hash);
|
|
483
|
+
return Number(result.lastInsertRowid);
|
|
484
|
+
}
|
|
485
|
+
/**
|
|
486
|
+
* Adds a thought log entry for a version.
|
|
487
|
+
*/
|
|
488
|
+
addThoughtLog(versionId, docPath, thinkingSummary) {
|
|
489
|
+
this.db.prepare(`
|
|
490
|
+
INSERT INTO thought_logs (version_id, doc_path, thinking_summary)
|
|
491
|
+
VALUES (?, ?, ?)
|
|
492
|
+
`).run(versionId, docPath, thinkingSummary);
|
|
493
|
+
}
|
|
494
|
+
/**
|
|
495
|
+
* Adds an assumption to a doc file.
|
|
496
|
+
*/
|
|
497
|
+
addAssumption(docFileId, claim) {
|
|
498
|
+
const result = this.db.prepare(`
|
|
499
|
+
INSERT INTO assumptions (doc_file_id, claim, verified)
|
|
500
|
+
VALUES (?, ?, 0)
|
|
501
|
+
`).run(docFileId, claim);
|
|
502
|
+
return Number(result.lastInsertRowid);
|
|
503
|
+
}
|
|
504
|
+
/**
|
|
505
|
+
* Updates assumption verification status.
|
|
506
|
+
*/
|
|
507
|
+
verifyAssumption(assumptionId, verified, method) {
|
|
508
|
+
this.db.prepare(`
|
|
509
|
+
UPDATE assumptions
|
|
510
|
+
SET verified = ?, verification_method = ?, verified_at = unixepoch()
|
|
511
|
+
WHERE id = ?
|
|
512
|
+
`).run(verified ? 1 : -1, method || null, assumptionId);
|
|
513
|
+
}
|
|
514
|
+
/**
|
|
515
|
+
* Gets all versions for a project.
|
|
516
|
+
*/
|
|
517
|
+
getDocVersions(projectId) {
|
|
518
|
+
return this.db.prepare(`
|
|
519
|
+
SELECT id, version_number, trigger_type, status, created_at
|
|
520
|
+
FROM doc_versions
|
|
521
|
+
WHERE project_id = ?
|
|
522
|
+
ORDER BY version_number DESC
|
|
523
|
+
`).all(projectId);
|
|
524
|
+
}
|
|
525
|
+
/**
|
|
526
|
+
* Gets the active version for a project.
|
|
527
|
+
*/
|
|
528
|
+
getActiveDocVersion(projectId) {
|
|
529
|
+
return this.db.prepare(`
|
|
530
|
+
SELECT id, version_number FROM doc_versions
|
|
531
|
+
WHERE project_id = ? AND status = 'active'
|
|
532
|
+
`).get(projectId) || null;
|
|
533
|
+
}
|
|
534
|
+
/**
|
|
535
|
+
* Activates a version (sets it as current, archives others).
|
|
536
|
+
*/
|
|
537
|
+
activateDocVersion(versionId, projectId) {
|
|
538
|
+
// Archive current active
|
|
539
|
+
this.db.prepare(`
|
|
540
|
+
UPDATE doc_versions SET status = 'archived'
|
|
541
|
+
WHERE project_id = ? AND status = 'active'
|
|
542
|
+
`).run(projectId);
|
|
543
|
+
// Activate new version
|
|
544
|
+
this.db.prepare(`
|
|
545
|
+
UPDATE doc_versions SET status = 'active' WHERE id = ?
|
|
546
|
+
`).run(versionId);
|
|
547
|
+
}
|
|
548
|
+
/**
|
|
549
|
+
* Updates version status.
|
|
550
|
+
*/
|
|
551
|
+
updateDocVersionStatus(versionId, status) {
|
|
552
|
+
this.db.prepare(`
|
|
553
|
+
UPDATE doc_versions SET status = ? WHERE id = ?
|
|
554
|
+
`).run(status, versionId);
|
|
555
|
+
}
|
|
556
|
+
/**
|
|
557
|
+
* Gets doc files for a version.
|
|
558
|
+
*/
|
|
559
|
+
getDocFiles(versionId) {
|
|
560
|
+
return this.db.prepare(`
|
|
561
|
+
SELECT id, path, content FROM doc_files WHERE version_id = ?
|
|
562
|
+
`).all(versionId);
|
|
563
|
+
}
|
|
564
|
+
/**
|
|
565
|
+
* Gets thought logs for a version.
|
|
566
|
+
*/
|
|
567
|
+
getThoughtLogs(versionId) {
|
|
568
|
+
return this.db.prepare(`
|
|
569
|
+
SELECT doc_path, thinking_summary FROM thought_logs WHERE version_id = ?
|
|
570
|
+
`).all(versionId);
|
|
571
|
+
}
|
|
572
|
+
/**
|
|
573
|
+
* Gets assumptions for a doc file.
|
|
574
|
+
*/
|
|
575
|
+
getAssumptions(docFileId) {
|
|
576
|
+
return this.db.prepare(`
|
|
577
|
+
SELECT id, claim, verified FROM assumptions WHERE doc_file_id = ?
|
|
578
|
+
`).all(docFileId);
|
|
579
|
+
}
|
|
580
|
+
/**
|
|
581
|
+
* Gets unverified assumptions for a version.
|
|
582
|
+
*/
|
|
583
|
+
getUnverifiedAssumptions(versionId) {
|
|
584
|
+
return this.db.prepare(`
|
|
585
|
+
SELECT a.id, a.claim, df.path as doc_path
|
|
586
|
+
FROM assumptions a
|
|
587
|
+
JOIN doc_files df ON a.doc_file_id = df.id
|
|
588
|
+
WHERE df.version_id = ? AND a.verified = 0
|
|
589
|
+
`).all(versionId);
|
|
590
|
+
}
|
|
591
|
+
// ===== AI Activity Methods (Phase 1.6) =====
|
|
592
|
+
/**
|
|
593
|
+
* Logs an AI activity for the central thinking platform.
|
|
594
|
+
*/
|
|
595
|
+
logAIActivity(data) {
|
|
596
|
+
const stmt = this.db.prepare(`
|
|
597
|
+
INSERT INTO ai_activity (
|
|
598
|
+
project_id, version_id, activity_type, prompt_summary,
|
|
599
|
+
response_preview, thinking_summary, tokens_used, duration_ms, status, created_at
|
|
600
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
601
|
+
`);
|
|
602
|
+
const result = stmt.run(data.projectId || null, data.versionId || null, data.activityType, data.promptSummary?.slice(0, 200) || null, // Truncate for storage
|
|
603
|
+
data.responsePreview?.slice(0, 500) || null, data.thinkingSummary || null, data.tokensUsed || null, data.durationMs || null, data.status || 'completed', Date.now() // Use JS timestamp (milliseconds)
|
|
604
|
+
);
|
|
605
|
+
return result.lastInsertRowid;
|
|
606
|
+
}
|
|
607
|
+
/**
|
|
608
|
+
* Updates an existing AI activity (e.g., when it completes).
|
|
609
|
+
*/
|
|
610
|
+
updateAIActivity(id, data) {
|
|
611
|
+
const updates = [];
|
|
612
|
+
const values = [];
|
|
613
|
+
if (data.responsePreview !== undefined) {
|
|
614
|
+
updates.push('response_preview = ?');
|
|
615
|
+
values.push(data.responsePreview.slice(0, 500));
|
|
616
|
+
}
|
|
617
|
+
if (data.thinkingSummary !== undefined) {
|
|
618
|
+
updates.push('thinking_summary = ?');
|
|
619
|
+
values.push(data.thinkingSummary);
|
|
620
|
+
}
|
|
621
|
+
if (data.tokensUsed !== undefined) {
|
|
622
|
+
updates.push('tokens_used = ?');
|
|
623
|
+
values.push(data.tokensUsed);
|
|
624
|
+
}
|
|
625
|
+
if (data.durationMs !== undefined) {
|
|
626
|
+
updates.push('duration_ms = ?');
|
|
627
|
+
values.push(data.durationMs);
|
|
628
|
+
}
|
|
629
|
+
if (data.status !== undefined) {
|
|
630
|
+
updates.push('status = ?');
|
|
631
|
+
values.push(data.status);
|
|
632
|
+
}
|
|
633
|
+
if (updates.length > 0) {
|
|
634
|
+
values.push(id);
|
|
635
|
+
this.db.prepare(`UPDATE ai_activity SET ${updates.join(', ')} WHERE id = ?`).run(...values);
|
|
636
|
+
}
|
|
637
|
+
}
|
|
638
|
+
/**
|
|
639
|
+
* Gets recent AI activity (for live thinking panel).
|
|
640
|
+
*/
|
|
641
|
+
getRecentAIActivity(limit = 20) {
|
|
642
|
+
return this.db.prepare(`
|
|
643
|
+
SELECT
|
|
644
|
+
a.*,
|
|
645
|
+
p.path as project_path
|
|
646
|
+
FROM ai_activity a
|
|
647
|
+
LEFT JOIN projects p ON a.project_id = p.id
|
|
648
|
+
ORDER BY a.created_at DESC
|
|
649
|
+
LIMIT ?
|
|
650
|
+
`).all(limit);
|
|
651
|
+
}
|
|
652
|
+
/**
|
|
653
|
+
* Gets AI activity for a specific version.
|
|
654
|
+
*/
|
|
655
|
+
getActivityForVersion(versionId) {
|
|
656
|
+
return this.db.prepare(`
|
|
657
|
+
SELECT * FROM ai_activity
|
|
658
|
+
WHERE version_id = ?
|
|
659
|
+
ORDER BY created_at ASC
|
|
660
|
+
`).all(versionId);
|
|
661
|
+
}
|
|
662
|
+
/**
|
|
663
|
+
* Updates assumption status.
|
|
664
|
+
* verified: 0=unverified, 1=verified, -1=rejected
|
|
665
|
+
*/
|
|
666
|
+
updateAssumptionStatus(id, verified, method) {
|
|
667
|
+
this.db.prepare(`
|
|
668
|
+
UPDATE assumptions
|
|
669
|
+
SET verified = ?, verification_method = ?, verified_at = (unixepoch() * 1000)
|
|
670
|
+
WHERE id = ?
|
|
671
|
+
`).run(verified, method, id);
|
|
672
|
+
}
|
|
673
|
+
/**
|
|
674
|
+
* Gets doc file ID by version and path.
|
|
675
|
+
*/
|
|
676
|
+
getDocFileId(versionId, docPath) {
|
|
677
|
+
const result = this.db.prepare(`
|
|
678
|
+
SELECT id FROM doc_files WHERE version_id = ? AND path = ?
|
|
679
|
+
`).get(versionId, docPath);
|
|
680
|
+
return result?.id || null;
|
|
681
|
+
}
|
|
682
|
+
/**
|
|
683
|
+
* Updates doc file content (correction).
|
|
684
|
+
*/
|
|
685
|
+
updateDocFileContent(id, content) {
|
|
686
|
+
this.db.prepare(`
|
|
687
|
+
UPDATE doc_files SET content = ? WHERE id = ?
|
|
688
|
+
`).run(content, id);
|
|
689
|
+
}
|
|
690
|
+
}
|
|
691
|
+
exports.DatabaseService = DatabaseService;
|
|
692
|
+
//# sourceMappingURL=DatabaseService.js.map
|