@farazirfan/costar-server-executor 1.7.54 → 1.7.56
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/cron/local-run-log.d.ts +35 -0
- package/dist/cron/local-run-log.d.ts.map +1 -0
- package/dist/cron/local-run-log.js +153 -0
- package/dist/cron/local-run-log.js.map +1 -0
- package/dist/cron/local-store.d.ts +86 -0
- package/dist/cron/local-store.d.ts.map +1 -0
- package/dist/cron/local-store.js +199 -0
- package/dist/cron/local-store.js.map +1 -0
- package/dist/db/local-database.d.ts +134 -0
- package/dist/db/local-database.d.ts.map +1 -0
- package/dist/db/local-database.js +419 -0
- package/dist/db/local-database.js.map +1 -0
- package/dist/middleware/auth.d.ts +13 -0
- package/dist/middleware/auth.d.ts.map +1 -0
- package/dist/middleware/auth.js +67 -0
- package/dist/middleware/auth.js.map +1 -0
- package/dist/routes/db-ops.d.ts +11 -0
- package/dist/routes/db-ops.d.ts.map +1 -0
- package/dist/routes/db-ops.js +266 -0
- package/dist/routes/db-ops.js.map +1 -0
- package/dist/routes/sandbox-ops.d.ts +15 -0
- package/dist/routes/sandbox-ops.d.ts.map +1 -0
- package/dist/routes/sandbox-ops.js +306 -0
- package/dist/routes/sandbox-ops.js.map +1 -0
- package/dist/server.d.ts +2 -0
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +61 -1
- package/dist/server.js.map +1 -1
- package/dist/services/backup-service.d.ts +49 -0
- package/dist/services/backup-service.d.ts.map +1 -0
- package/dist/services/backup-service.js +113 -0
- package/dist/services/backup-service.js.map +1 -0
- package/dist/services/s3-file-watcher.d.ts +79 -0
- package/dist/services/s3-file-watcher.d.ts.map +1 -0
- package/dist/services/s3-file-watcher.js +191 -0
- package/dist/services/s3-file-watcher.js.map +1 -0
- package/dist/startup/migrate.d.ts +32 -0
- package/dist/startup/migrate.d.ts.map +1 -0
- package/dist/startup/migrate.js +180 -0
- package/dist/startup/migrate.js.map +1 -0
- package/dist/web-server.d.ts +7 -0
- package/dist/web-server.d.ts.map +1 -1
- package/dist/web-server.js +59 -18
- package/dist/web-server.js.map +1 -1
- package/package.json +2 -1
- package/public/index.html +607 -2
|
@@ -0,0 +1,419 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Local SQLite Database — Activity, Assets, Projects
|
|
3
|
+
* Replaces Supabase for structured data. Runs on each sandbox.
|
|
4
|
+
* Part of Phase 4: Direct Client → Sandbox Architecture.
|
|
5
|
+
*
|
|
6
|
+
* Uses better-sqlite3 for synchronous, fast queries.
|
|
7
|
+
* Vector search via sqlite-vec for embeddings.
|
|
8
|
+
*/
|
|
9
|
+
import path from "node:path";
|
|
10
|
+
import fs from "node:fs";
|
|
11
|
+
import { resolveCoStarDir } from "../cli/paths.js";
|
|
12
|
+
let db = null;
|
|
13
|
+
/**
|
|
14
|
+
* Get the database file path.
|
|
15
|
+
*/
|
|
16
|
+
function getDbPath() {
|
|
17
|
+
return path.join(resolveCoStarDir(), "costar.db");
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Generate a random hex ID (UUID-like, 32 chars).
|
|
21
|
+
*/
|
|
22
|
+
function generateId() {
|
|
23
|
+
const bytes = new Uint8Array(16);
|
|
24
|
+
crypto.getRandomValues(bytes);
|
|
25
|
+
return Array.from(bytes)
|
|
26
|
+
.map((b) => b.toString(16).padStart(2, "0"))
|
|
27
|
+
.join("");
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Initialize the database. Creates tables if they don't exist.
|
|
31
|
+
*/
|
|
32
|
+
export async function initDatabase() {
|
|
33
|
+
if (db)
|
|
34
|
+
return;
|
|
35
|
+
const dbPath = getDbPath();
|
|
36
|
+
const dir = path.dirname(dbPath);
|
|
37
|
+
if (!fs.existsSync(dir)) {
|
|
38
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
39
|
+
}
|
|
40
|
+
try {
|
|
41
|
+
// Dynamic import — better-sqlite3 is a native module (optional dep)
|
|
42
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
43
|
+
const moduleName = "better-sqlite3";
|
|
44
|
+
const BetterSqlite3 = (await import(/* webpackIgnore: true */ moduleName)).default;
|
|
45
|
+
db = new BetterSqlite3(dbPath);
|
|
46
|
+
// Enable WAL mode for better concurrency
|
|
47
|
+
db.pragma("journal_mode = WAL");
|
|
48
|
+
// Create tables
|
|
49
|
+
db.exec(`
|
|
50
|
+
CREATE TABLE IF NOT EXISTS agent_activity (
|
|
51
|
+
id TEXT PRIMARY KEY DEFAULT (lower(hex(randomblob(16)))),
|
|
52
|
+
user_id TEXT NOT NULL,
|
|
53
|
+
request TEXT,
|
|
54
|
+
response TEXT,
|
|
55
|
+
status TEXT DEFAULT 'pending',
|
|
56
|
+
executor TEXT DEFAULT 'server',
|
|
57
|
+
source TEXT,
|
|
58
|
+
tool_calls INTEGER DEFAULT 0,
|
|
59
|
+
duration INTEGER,
|
|
60
|
+
error TEXT,
|
|
61
|
+
keywords TEXT,
|
|
62
|
+
categories TEXT,
|
|
63
|
+
sandbox_id TEXT,
|
|
64
|
+
created_at TEXT DEFAULT (datetime('now')),
|
|
65
|
+
updated_at TEXT DEFAULT (datetime('now'))
|
|
66
|
+
);
|
|
67
|
+
|
|
68
|
+
CREATE INDEX IF NOT EXISTS idx_activity_user_id ON agent_activity(user_id);
|
|
69
|
+
CREATE INDEX IF NOT EXISTS idx_activity_status ON agent_activity(status);
|
|
70
|
+
CREATE INDEX IF NOT EXISTS idx_activity_created_at ON agent_activity(created_at);
|
|
71
|
+
CREATE INDEX IF NOT EXISTS idx_activity_executor ON agent_activity(executor);
|
|
72
|
+
|
|
73
|
+
CREATE TABLE IF NOT EXISTS assets (
|
|
74
|
+
id TEXT PRIMARY KEY DEFAULT (lower(hex(randomblob(16)))),
|
|
75
|
+
user_id TEXT NOT NULL,
|
|
76
|
+
name TEXT,
|
|
77
|
+
type TEXT,
|
|
78
|
+
local_file_path TEXT,
|
|
79
|
+
remote_url TEXT UNIQUE,
|
|
80
|
+
description TEXT,
|
|
81
|
+
sandbox_id TEXT,
|
|
82
|
+
created_at TEXT DEFAULT (datetime('now')),
|
|
83
|
+
updated_at TEXT DEFAULT (datetime('now'))
|
|
84
|
+
);
|
|
85
|
+
|
|
86
|
+
CREATE INDEX IF NOT EXISTS idx_assets_user_id ON assets(user_id);
|
|
87
|
+
|
|
88
|
+
CREATE TABLE IF NOT EXISTS projects (
|
|
89
|
+
id TEXT PRIMARY KEY DEFAULT (lower(hex(randomblob(16)))),
|
|
90
|
+
user_id TEXT NOT NULL,
|
|
91
|
+
name TEXT,
|
|
92
|
+
description TEXT,
|
|
93
|
+
sandbox_id TEXT,
|
|
94
|
+
project_path TEXT,
|
|
95
|
+
convo_summary TEXT,
|
|
96
|
+
is_active INTEGER DEFAULT 0,
|
|
97
|
+
created_at TEXT DEFAULT (datetime('now')),
|
|
98
|
+
updated_at TEXT DEFAULT (datetime('now'))
|
|
99
|
+
);
|
|
100
|
+
|
|
101
|
+
CREATE INDEX IF NOT EXISTS idx_projects_user_id ON projects(user_id);
|
|
102
|
+
|
|
103
|
+
CREATE TABLE IF NOT EXISTS request_assets (
|
|
104
|
+
id TEXT PRIMARY KEY DEFAULT (lower(hex(randomblob(16)))),
|
|
105
|
+
request_id TEXT REFERENCES agent_activity(id),
|
|
106
|
+
asset_id TEXT REFERENCES assets(id),
|
|
107
|
+
action TEXT,
|
|
108
|
+
created_at TEXT DEFAULT (datetime('now'))
|
|
109
|
+
);
|
|
110
|
+
|
|
111
|
+
CREATE INDEX IF NOT EXISTS idx_req_assets_request ON request_assets(request_id);
|
|
112
|
+
CREATE INDEX IF NOT EXISTS idx_req_assets_asset ON request_assets(asset_id);
|
|
113
|
+
|
|
114
|
+
CREATE TABLE IF NOT EXISTS request_projects (
|
|
115
|
+
id TEXT PRIMARY KEY DEFAULT (lower(hex(randomblob(16)))),
|
|
116
|
+
request_id TEXT REFERENCES agent_activity(id),
|
|
117
|
+
project_id TEXT REFERENCES projects(id),
|
|
118
|
+
action TEXT,
|
|
119
|
+
created_at TEXT DEFAULT (datetime('now'))
|
|
120
|
+
);
|
|
121
|
+
|
|
122
|
+
CREATE INDEX IF NOT EXISTS idx_req_projects_request ON request_projects(request_id);
|
|
123
|
+
CREATE INDEX IF NOT EXISTS idx_req_projects_project ON request_projects(project_id);
|
|
124
|
+
`);
|
|
125
|
+
// Try to load sqlite-vec for vector search (optional — graceful fallback)
|
|
126
|
+
try {
|
|
127
|
+
const vecModuleName = "sqlite-vec";
|
|
128
|
+
const sqliteVec = await import(/* webpackIgnore: true */ vecModuleName);
|
|
129
|
+
sqliteVec.load(db);
|
|
130
|
+
db.exec(`
|
|
131
|
+
CREATE VIRTUAL TABLE IF NOT EXISTS activity_embeddings USING vec0(
|
|
132
|
+
activity_id TEXT PRIMARY KEY,
|
|
133
|
+
embedding FLOAT[1536]
|
|
134
|
+
);
|
|
135
|
+
`);
|
|
136
|
+
console.log("[DB] sqlite-vec loaded — vector search enabled");
|
|
137
|
+
}
|
|
138
|
+
catch {
|
|
139
|
+
console.log("[DB] sqlite-vec not available — vector search disabled (keyword search only)");
|
|
140
|
+
}
|
|
141
|
+
console.log(`[DB] Database initialized at ${dbPath}`);
|
|
142
|
+
}
|
|
143
|
+
catch (error) {
|
|
144
|
+
console.error("[DB] Failed to initialize database:", error);
|
|
145
|
+
throw error;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Get the database instance. Throws if not initialized.
|
|
150
|
+
*/
|
|
151
|
+
function getDb() {
|
|
152
|
+
if (!db)
|
|
153
|
+
throw new Error("Database not initialized. Call initDatabase() first.");
|
|
154
|
+
return db;
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Close the database connection.
|
|
158
|
+
*/
|
|
159
|
+
export function closeDatabase() {
|
|
160
|
+
if (db) {
|
|
161
|
+
db.close();
|
|
162
|
+
db = null;
|
|
163
|
+
console.log("[DB] Database closed");
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
export function createActivity(params) {
|
|
167
|
+
const d = getDb();
|
|
168
|
+
const id = generateId();
|
|
169
|
+
const now = new Date().toISOString();
|
|
170
|
+
d.prepare(`
|
|
171
|
+
INSERT INTO agent_activity (id, user_id, request, executor, source, sandbox_id, status, created_at, updated_at)
|
|
172
|
+
VALUES (?, ?, ?, ?, ?, ?, 'pending', ?, ?)
|
|
173
|
+
`).run(id, params.userId, params.request, params.executor, params.source ?? null, params.sandboxId ?? null, now, now);
|
|
174
|
+
// Store embedding if provided
|
|
175
|
+
if (params.embedding && params.embedding.length === 1536) {
|
|
176
|
+
try {
|
|
177
|
+
d.prepare(`INSERT INTO activity_embeddings (activity_id, embedding) VALUES (?, ?)`).run(id, new Float32Array(params.embedding).buffer);
|
|
178
|
+
}
|
|
179
|
+
catch {
|
|
180
|
+
// sqlite-vec not loaded — silently skip
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
return d.prepare(`SELECT * FROM agent_activity WHERE id = ?`).get(id);
|
|
184
|
+
}
|
|
185
|
+
export function completeActivity(params) {
|
|
186
|
+
const d = getDb();
|
|
187
|
+
const now = new Date().toISOString();
|
|
188
|
+
const fields = ["response = ?", "status = 'completed'", "updated_at = ?"];
|
|
189
|
+
const values = [params.response, now];
|
|
190
|
+
if (params.request !== undefined) {
|
|
191
|
+
fields.push("request = ?");
|
|
192
|
+
values.push(params.request);
|
|
193
|
+
}
|
|
194
|
+
if (params.toolCalls !== undefined) {
|
|
195
|
+
fields.push("tool_calls = ?");
|
|
196
|
+
values.push(params.toolCalls);
|
|
197
|
+
}
|
|
198
|
+
if (params.duration !== undefined) {
|
|
199
|
+
fields.push("duration = ?");
|
|
200
|
+
values.push(params.duration);
|
|
201
|
+
}
|
|
202
|
+
if (params.keywords !== undefined) {
|
|
203
|
+
fields.push("keywords = ?");
|
|
204
|
+
values.push(params.keywords);
|
|
205
|
+
}
|
|
206
|
+
if (params.categories !== undefined) {
|
|
207
|
+
fields.push("categories = ?");
|
|
208
|
+
values.push(JSON.stringify(params.categories));
|
|
209
|
+
}
|
|
210
|
+
values.push(params.activityId);
|
|
211
|
+
d.prepare(`UPDATE agent_activity SET ${fields.join(", ")} WHERE id = ?`).run(...values);
|
|
212
|
+
// Update embedding if provided
|
|
213
|
+
if (params.embedding && params.embedding.length === 1536) {
|
|
214
|
+
try {
|
|
215
|
+
d.prepare(`INSERT OR REPLACE INTO activity_embeddings (activity_id, embedding) VALUES (?, ?)`).run(params.activityId, new Float32Array(params.embedding).buffer);
|
|
216
|
+
}
|
|
217
|
+
catch {
|
|
218
|
+
// sqlite-vec not loaded
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
return d.prepare(`SELECT * FROM agent_activity WHERE id = ?`).get(params.activityId);
|
|
222
|
+
}
|
|
223
|
+
export function failActivity(params) {
|
|
224
|
+
const d = getDb();
|
|
225
|
+
const now = new Date().toISOString();
|
|
226
|
+
d.prepare(`
|
|
227
|
+
UPDATE agent_activity SET status = 'failed', error = ?, duration = ?, updated_at = ? WHERE id = ?
|
|
228
|
+
`).run(params.error, params.duration ?? null, now, params.activityId);
|
|
229
|
+
return d.prepare(`SELECT * FROM agent_activity WHERE id = ?`).get(params.activityId);
|
|
230
|
+
}
|
|
231
|
+
export function getActivityById(activityId) {
|
|
232
|
+
const d = getDb();
|
|
233
|
+
return d.prepare(`SELECT * FROM agent_activity WHERE id = ?`).get(activityId) ?? null;
|
|
234
|
+
}
|
|
235
|
+
export function getRecentActivity(userId, limit = 50) {
|
|
236
|
+
const d = getDb();
|
|
237
|
+
return d.prepare(`
|
|
238
|
+
SELECT * FROM agent_activity WHERE user_id = ? ORDER BY created_at DESC LIMIT ?
|
|
239
|
+
`).all(userId, limit);
|
|
240
|
+
}
|
|
241
|
+
export function getActivityByStatus(userId, status, limit = 50) {
|
|
242
|
+
const d = getDb();
|
|
243
|
+
return d.prepare(`
|
|
244
|
+
SELECT * FROM agent_activity WHERE user_id = ? AND status = ? ORDER BY created_at DESC LIMIT ?
|
|
245
|
+
`).all(userId, status, limit);
|
|
246
|
+
}
|
|
247
|
+
export function getNewClientActivitySince(userId, afterTimestamp, limit = 30) {
|
|
248
|
+
const d = getDb();
|
|
249
|
+
if (afterTimestamp) {
|
|
250
|
+
return d.prepare(`
|
|
251
|
+
SELECT * FROM agent_activity
|
|
252
|
+
WHERE user_id = ? AND status = 'completed' AND executor = 'client' AND created_at > ?
|
|
253
|
+
ORDER BY created_at ASC LIMIT ?
|
|
254
|
+
`).all(userId, afterTimestamp, limit);
|
|
255
|
+
}
|
|
256
|
+
return d.prepare(`
|
|
257
|
+
SELECT * FROM agent_activity
|
|
258
|
+
WHERE user_id = ? AND status = 'completed' AND executor = 'client'
|
|
259
|
+
ORDER BY created_at ASC LIMIT ?
|
|
260
|
+
`).all(userId, limit);
|
|
261
|
+
}
|
|
262
|
+
export function searchActivityByKeywords(userId, query, limit = 10) {
|
|
263
|
+
const d = getDb();
|
|
264
|
+
const pattern = `%${query}%`;
|
|
265
|
+
return d.prepare(`
|
|
266
|
+
SELECT * FROM agent_activity
|
|
267
|
+
WHERE user_id = ? AND status = 'completed'
|
|
268
|
+
AND (request LIKE ? OR response LIKE ? OR keywords LIKE ?)
|
|
269
|
+
ORDER BY created_at DESC LIMIT ?
|
|
270
|
+
`).all(userId, pattern, pattern, pattern, limit);
|
|
271
|
+
}
|
|
272
|
+
/**
|
|
273
|
+
* Semantic vector search via sqlite-vec.
|
|
274
|
+
* Falls back to empty results if sqlite-vec not loaded.
|
|
275
|
+
*/
|
|
276
|
+
export function searchActivityByEmbedding(embedding, userId, limit = 10, threshold = 0.7) {
|
|
277
|
+
const d = getDb();
|
|
278
|
+
try {
|
|
279
|
+
// sqlite-vec KNN search
|
|
280
|
+
const embeddingBuf = new Float32Array(embedding).buffer;
|
|
281
|
+
const rows = d.prepare(`
|
|
282
|
+
SELECT ae.activity_id, distance
|
|
283
|
+
FROM activity_embeddings ae
|
|
284
|
+
WHERE embedding MATCH ? AND k = ?
|
|
285
|
+
ORDER BY distance ASC
|
|
286
|
+
`).all(embeddingBuf, limit * 2);
|
|
287
|
+
// Convert distance to similarity (cosine distance → similarity)
|
|
288
|
+
const results = [];
|
|
289
|
+
for (const row of rows) {
|
|
290
|
+
const similarity = 1 - row.distance;
|
|
291
|
+
if (similarity < threshold)
|
|
292
|
+
continue;
|
|
293
|
+
const activity = d.prepare(`
|
|
294
|
+
SELECT * FROM agent_activity WHERE id = ? AND user_id = ?
|
|
295
|
+
`).get(row.activity_id, userId);
|
|
296
|
+
if (activity) {
|
|
297
|
+
results.push({ ...activity, similarity });
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
return results.slice(0, limit);
|
|
301
|
+
}
|
|
302
|
+
catch {
|
|
303
|
+
// sqlite-vec not loaded
|
|
304
|
+
return [];
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
export function getActivityStats(userId) {
|
|
308
|
+
const d = getDb();
|
|
309
|
+
const rows = d.prepare(`
|
|
310
|
+
SELECT status, duration, tool_calls FROM agent_activity WHERE user_id = ?
|
|
311
|
+
`).all(userId);
|
|
312
|
+
let total = 0, pending = 0, completed = 0, failed = 0;
|
|
313
|
+
let totalDuration = 0, durationCount = 0;
|
|
314
|
+
let totalToolCalls = 0, toolCallsCount = 0;
|
|
315
|
+
for (const row of rows) {
|
|
316
|
+
total++;
|
|
317
|
+
if (row.status === "pending")
|
|
318
|
+
pending++;
|
|
319
|
+
if (row.status === "completed")
|
|
320
|
+
completed++;
|
|
321
|
+
if (row.status === "failed")
|
|
322
|
+
failed++;
|
|
323
|
+
if (row.duration !== null) {
|
|
324
|
+
totalDuration += row.duration;
|
|
325
|
+
durationCount++;
|
|
326
|
+
}
|
|
327
|
+
if (row.tool_calls !== null) {
|
|
328
|
+
totalToolCalls += row.tool_calls;
|
|
329
|
+
toolCallsCount++;
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
return {
|
|
333
|
+
total,
|
|
334
|
+
pending,
|
|
335
|
+
completed,
|
|
336
|
+
failed,
|
|
337
|
+
avgDuration: durationCount > 0 ? Math.round(totalDuration / durationCount) : undefined,
|
|
338
|
+
avgToolCalls: toolCallsCount > 0 ? Math.round((totalToolCalls / toolCallsCount) * 10) / 10 : undefined,
|
|
339
|
+
};
|
|
340
|
+
}
|
|
341
|
+
export function upsertAsset(params) {
|
|
342
|
+
const d = getDb();
|
|
343
|
+
const now = new Date().toISOString();
|
|
344
|
+
// Try to find existing asset by remote_url (unique constraint)
|
|
345
|
+
if (params.remoteUrl) {
|
|
346
|
+
const existing = d.prepare(`SELECT * FROM assets WHERE remote_url = ?`).get(params.remoteUrl);
|
|
347
|
+
if (existing) {
|
|
348
|
+
d.prepare(`
|
|
349
|
+
UPDATE assets SET name = ?, type = ?, local_file_path = ?, description = ?, updated_at = ?
|
|
350
|
+
WHERE id = ?
|
|
351
|
+
`).run(params.name ?? existing.name, params.type ?? existing.type, params.localFilePath ?? existing.local_file_path, params.description ?? existing.description, now, existing.id);
|
|
352
|
+
return d.prepare(`SELECT * FROM assets WHERE id = ?`).get(existing.id);
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
const id = generateId();
|
|
356
|
+
d.prepare(`
|
|
357
|
+
INSERT INTO assets (id, user_id, name, type, local_file_path, remote_url, description, sandbox_id, created_at, updated_at)
|
|
358
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
359
|
+
`).run(id, params.userId, params.name ?? null, params.type ?? null, params.localFilePath ?? null, params.remoteUrl ?? null, params.description ?? null, params.sandboxId ?? null, now, now);
|
|
360
|
+
return d.prepare(`SELECT * FROM assets WHERE id = ?`).get(id);
|
|
361
|
+
}
|
|
362
|
+
export function getAssets(userId, limit = 100) {
|
|
363
|
+
const d = getDb();
|
|
364
|
+
return d.prepare(`
|
|
365
|
+
SELECT * FROM assets WHERE user_id = ? ORDER BY created_at DESC LIMIT ?
|
|
366
|
+
`).all(userId, limit);
|
|
367
|
+
}
|
|
368
|
+
export function getAssetById(assetId) {
|
|
369
|
+
const d = getDb();
|
|
370
|
+
return d.prepare(`SELECT * FROM assets WHERE id = ?`).get(assetId) ?? null;
|
|
371
|
+
}
|
|
372
|
+
export function linkAssetToActivity(params) {
|
|
373
|
+
const d = getDb();
|
|
374
|
+
const id = generateId();
|
|
375
|
+
d.prepare(`
|
|
376
|
+
INSERT INTO request_assets (id, request_id, asset_id, action, created_at)
|
|
377
|
+
VALUES (?, ?, ?, ?, ?)
|
|
378
|
+
`).run(id, params.requestId, params.assetId, params.action ?? null, new Date().toISOString());
|
|
379
|
+
}
|
|
380
|
+
export function upsertProject(params) {
|
|
381
|
+
const d = getDb();
|
|
382
|
+
const now = new Date().toISOString();
|
|
383
|
+
// Update existing if ID provided
|
|
384
|
+
if (params.id) {
|
|
385
|
+
const existing = d.prepare(`SELECT * FROM projects WHERE id = ?`).get(params.id);
|
|
386
|
+
if (existing) {
|
|
387
|
+
d.prepare(`
|
|
388
|
+
UPDATE projects SET name = ?, description = ?, project_path = ?, convo_summary = ?, is_active = ?, updated_at = ?
|
|
389
|
+
WHERE id = ?
|
|
390
|
+
`).run(params.name ?? existing.name, params.description ?? existing.description, params.projectPath ?? existing.project_path, params.convoSummary ?? existing.convo_summary, params.isActive !== undefined ? (params.isActive ? 1 : 0) : existing.is_active, now, params.id);
|
|
391
|
+
return d.prepare(`SELECT * FROM projects WHERE id = ?`).get(params.id);
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
const id = params.id || generateId();
|
|
395
|
+
d.prepare(`
|
|
396
|
+
INSERT INTO projects (id, user_id, name, description, sandbox_id, project_path, convo_summary, is_active, created_at, updated_at)
|
|
397
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
398
|
+
`).run(id, params.userId, params.name ?? null, params.description ?? null, params.sandboxId ?? null, params.projectPath ?? null, params.convoSummary ?? null, params.isActive ? 1 : 0, now, now);
|
|
399
|
+
return d.prepare(`SELECT * FROM projects WHERE id = ?`).get(id);
|
|
400
|
+
}
|
|
401
|
+
export function getProjects(userId, limit = 100) {
|
|
402
|
+
const d = getDb();
|
|
403
|
+
return d.prepare(`
|
|
404
|
+
SELECT * FROM projects WHERE user_id = ? ORDER BY created_at DESC LIMIT ?
|
|
405
|
+
`).all(userId, limit);
|
|
406
|
+
}
|
|
407
|
+
export function getProjectById(projectId) {
|
|
408
|
+
const d = getDb();
|
|
409
|
+
return d.prepare(`SELECT * FROM projects WHERE id = ?`).get(projectId) ?? null;
|
|
410
|
+
}
|
|
411
|
+
export function linkProjectToActivity(params) {
|
|
412
|
+
const d = getDb();
|
|
413
|
+
const id = generateId();
|
|
414
|
+
d.prepare(`
|
|
415
|
+
INSERT INTO request_projects (id, request_id, project_id, action, created_at)
|
|
416
|
+
VALUES (?, ?, ?, ?, ?)
|
|
417
|
+
`).run(id, params.requestId, params.projectId, params.action ?? null, new Date().toISOString());
|
|
418
|
+
}
|
|
419
|
+
//# sourceMappingURL=local-database.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"local-database.js","sourceRoot":"","sources":["../../src/db/local-database.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Auth Middleware — Bearer Token Authentication
|
|
3
|
+
* Validates CLIENT_API_TOKEN for all non-public endpoints.
|
|
4
|
+
* Part of Phase 1B: Direct Client → Sandbox Architecture.
|
|
5
|
+
*/
|
|
6
|
+
import type { Request, Response, NextFunction } from "express";
|
|
7
|
+
/**
|
|
8
|
+
* Create auth middleware that validates Bearer tokens.
|
|
9
|
+
*
|
|
10
|
+
* @param clientApiToken - The expected token. If empty, ALL non-public requests are rejected.
|
|
11
|
+
*/
|
|
12
|
+
export declare function createAuthMiddleware(clientApiToken: string): (req: Request, res: Response, next: NextFunction) => void;
|
|
13
|
+
//# sourceMappingURL=auth.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/middleware/auth.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAgB/D;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,cAAc,EAAE,MAAM,IACjD,KAAK,OAAO,EAAE,KAAK,QAAQ,EAAE,MAAM,YAAY,KAAG,IAAI,CAiD/D"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Auth Middleware — Bearer Token Authentication
|
|
3
|
+
* Validates CLIENT_API_TOKEN for all non-public endpoints.
|
|
4
|
+
* Part of Phase 1B: Direct Client → Sandbox Architecture.
|
|
5
|
+
*/
|
|
6
|
+
/** Paths that skip auth (public endpoints) */
|
|
7
|
+
const PUBLIC_PATHS = new Set([
|
|
8
|
+
"/api/health",
|
|
9
|
+
"/api/version",
|
|
10
|
+
"/",
|
|
11
|
+
]);
|
|
12
|
+
/** Path prefixes that skip auth (static files, dashboard) */
|
|
13
|
+
const PUBLIC_PREFIXES = [
|
|
14
|
+
"/assets/",
|
|
15
|
+
"/public/",
|
|
16
|
+
"/favicon",
|
|
17
|
+
];
|
|
18
|
+
/**
|
|
19
|
+
* Create auth middleware that validates Bearer tokens.
|
|
20
|
+
*
|
|
21
|
+
* @param clientApiToken - The expected token. If empty, ALL non-public requests are rejected.
|
|
22
|
+
*/
|
|
23
|
+
export function createAuthMiddleware(clientApiToken) {
|
|
24
|
+
return (req, res, next) => {
|
|
25
|
+
// Skip auth for public paths
|
|
26
|
+
if (PUBLIC_PATHS.has(req.path)) {
|
|
27
|
+
next();
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
// Skip auth for public prefixes (static files)
|
|
31
|
+
if (PUBLIC_PREFIXES.some((prefix) => req.path.startsWith(prefix))) {
|
|
32
|
+
next();
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
// Skip auth for HTML page requests (dashboard SPA)
|
|
36
|
+
if (req.accepts("html") && !req.path.startsWith("/api/")) {
|
|
37
|
+
next();
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
// If no token configured, reject all API requests
|
|
41
|
+
if (!clientApiToken) {
|
|
42
|
+
res.status(403).json({
|
|
43
|
+
error: "No CLIENT_API_TOKEN configured. Set CLIENT_API_TOKEN in .env to enable API access.",
|
|
44
|
+
});
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
// Validate Bearer token
|
|
48
|
+
const authHeader = req.headers.authorization;
|
|
49
|
+
if (!authHeader) {
|
|
50
|
+
res.status(401).json({ error: "Missing Authorization header" });
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
const parts = authHeader.split(" ");
|
|
54
|
+
if (parts.length !== 2 || parts[0] !== "Bearer") {
|
|
55
|
+
res.status(401).json({ error: "Invalid Authorization format. Expected: Bearer <token>" });
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
const token = parts[1];
|
|
59
|
+
if (token !== clientApiToken) {
|
|
60
|
+
res.status(403).json({ error: "Invalid token" });
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
// Token valid — proceed
|
|
64
|
+
next();
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=auth.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/middleware/auth.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,8CAA8C;AAC9C,MAAM,YAAY,GAAG,IAAI,GAAG,CAAC;IAC3B,aAAa;IACb,cAAc;IACd,GAAG;CACJ,CAAC,CAAC;AAEH,6DAA6D;AAC7D,MAAM,eAAe,GAAG;IACtB,UAAU;IACV,UAAU;IACV,UAAU;CACX,CAAC;AAEF;;;;GAIG;AACH,MAAM,UAAU,oBAAoB,CAAC,cAAsB;IACzD,OAAO,CAAC,GAAY,EAAE,GAAa,EAAE,IAAkB,EAAQ,EAAE;QAC/D,6BAA6B;QAC7B,IAAI,YAAY,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;YAC/B,IAAI,EAAE,CAAC;YACP,OAAO;QACT,CAAC;QAED,+CAA+C;QAC/C,IAAI,eAAe,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC;YAClE,IAAI,EAAE,CAAC;YACP,OAAO;QACT,CAAC;QAED,mDAAmD;QACnD,IAAI,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;YACzD,IAAI,EAAE,CAAC;YACP,OAAO;QACT,CAAC;QAED,kDAAkD;QAClD,IAAI,CAAC,cAAc,EAAE,CAAC;YACpB,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC;gBACnB,KAAK,EAAE,oFAAoF;aAC5F,CAAC,CAAC;YACH,OAAO;QACT,CAAC;QAED,wBAAwB;QACxB,MAAM,UAAU,GAAG,GAAG,CAAC,OAAO,CAAC,aAAa,CAAC;QAC7C,IAAI,CAAC,UAAU,EAAE,CAAC;YAChB,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,8BAA8B,EAAE,CAAC,CAAC;YAChE,OAAO;QACT,CAAC;QAED,MAAM,KAAK,GAAG,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QACpC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,QAAQ,EAAE,CAAC;YAChD,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,wDAAwD,EAAE,CAAC,CAAC;YAC1F,OAAO;QACT,CAAC;QAED,MAAM,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;QACvB,IAAI,KAAK,KAAK,cAAc,EAAE,CAAC;YAC7B,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,eAAe,EAAE,CAAC,CAAC;YACjD,OAAO;QACT,CAAC;QAED,wBAAwB;QACxB,IAAI,EAAE,CAAC;IACT,CAAC,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Database API Routes — Local SQLite CRUD
|
|
3
|
+
* Activity, Assets, Projects, and vector search endpoints.
|
|
4
|
+
* Part of Phase 4: Direct Client → Sandbox Architecture.
|
|
5
|
+
*/
|
|
6
|
+
import { Router } from "express";
|
|
7
|
+
export type DbOpsDeps = {
|
|
8
|
+
userId: string;
|
|
9
|
+
};
|
|
10
|
+
export declare function createDbOpsRouter(deps: DbOpsDeps): Router;
|
|
11
|
+
//# sourceMappingURL=db-ops.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"db-ops.d.ts","sourceRoot":"","sources":["../../src/routes/db-ops.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAsBjC,MAAM,MAAM,SAAS,GAAG;IACtB,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,SAAS,GAAG,MAAM,CA+RzD"}
|