@gotza02/smartagent 1.2.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 (75) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +422 -0
  3. package/dist/config/index.d.ts +72 -0
  4. package/dist/config/index.d.ts.map +1 -0
  5. package/dist/config/index.js +329 -0
  6. package/dist/config/index.js.map +1 -0
  7. package/dist/core/agent-manager.d.ts +116 -0
  8. package/dist/core/agent-manager.d.ts.map +1 -0
  9. package/dist/core/agent-manager.js +460 -0
  10. package/dist/core/agent-manager.js.map +1 -0
  11. package/dist/core/context-manager.d.ts +107 -0
  12. package/dist/core/context-manager.d.ts.map +1 -0
  13. package/dist/core/context-manager.js +467 -0
  14. package/dist/core/context-manager.js.map +1 -0
  15. package/dist/core/database.d.ts +82 -0
  16. package/dist/core/database.d.ts.map +1 -0
  17. package/dist/core/database.js +751 -0
  18. package/dist/core/database.js.map +1 -0
  19. package/dist/core/event-emitter.d.ts +110 -0
  20. package/dist/core/event-emitter.d.ts.map +1 -0
  21. package/dist/core/event-emitter.js +240 -0
  22. package/dist/core/event-emitter.js.map +1 -0
  23. package/dist/core/metrics.d.ts +108 -0
  24. package/dist/core/metrics.d.ts.map +1 -0
  25. package/dist/core/metrics.js +281 -0
  26. package/dist/core/metrics.js.map +1 -0
  27. package/dist/core/middleware.d.ts +63 -0
  28. package/dist/core/middleware.d.ts.map +1 -0
  29. package/dist/core/middleware.js +194 -0
  30. package/dist/core/middleware.js.map +1 -0
  31. package/dist/core/plugin-system.d.ts +86 -0
  32. package/dist/core/plugin-system.d.ts.map +1 -0
  33. package/dist/core/plugin-system.js +251 -0
  34. package/dist/core/plugin-system.js.map +1 -0
  35. package/dist/core/task-scheduler.d.ts +130 -0
  36. package/dist/core/task-scheduler.d.ts.map +1 -0
  37. package/dist/core/task-scheduler.js +401 -0
  38. package/dist/core/task-scheduler.js.map +1 -0
  39. package/dist/engines/auto-router.d.ts +76 -0
  40. package/dist/engines/auto-router.d.ts.map +1 -0
  41. package/dist/engines/auto-router.js +445 -0
  42. package/dist/engines/auto-router.js.map +1 -0
  43. package/dist/engines/parallel-execution.d.ts +104 -0
  44. package/dist/engines/parallel-execution.d.ts.map +1 -0
  45. package/dist/engines/parallel-execution.js +591 -0
  46. package/dist/engines/parallel-execution.js.map +1 -0
  47. package/dist/engines/sequential-thinking.d.ts +88 -0
  48. package/dist/engines/sequential-thinking.d.ts.map +1 -0
  49. package/dist/engines/sequential-thinking.js +406 -0
  50. package/dist/engines/sequential-thinking.js.map +1 -0
  51. package/dist/index.d.ts +12 -0
  52. package/dist/index.d.ts.map +1 -0
  53. package/dist/index.js +1101 -0
  54. package/dist/index.js.map +1 -0
  55. package/dist/security/validation.d.ts +87 -0
  56. package/dist/security/validation.d.ts.map +1 -0
  57. package/dist/security/validation.js +465 -0
  58. package/dist/security/validation.js.map +1 -0
  59. package/dist/tools/filesystem.d.ts +90 -0
  60. package/dist/tools/filesystem.d.ts.map +1 -0
  61. package/dist/tools/filesystem.js +292 -0
  62. package/dist/tools/filesystem.js.map +1 -0
  63. package/dist/tools/terminal.d.ts +99 -0
  64. package/dist/tools/terminal.d.ts.map +1 -0
  65. package/dist/tools/terminal.js +363 -0
  66. package/dist/tools/terminal.js.map +1 -0
  67. package/dist/types/index.d.ts +306 -0
  68. package/dist/types/index.d.ts.map +1 -0
  69. package/dist/types/index.js +54 -0
  70. package/dist/types/index.js.map +1 -0
  71. package/dist/utils/logger.d.ts +22 -0
  72. package/dist/utils/logger.d.ts.map +1 -0
  73. package/dist/utils/logger.js +189 -0
  74. package/dist/utils/logger.js.map +1 -0
  75. package/package.json +71 -0
@@ -0,0 +1,751 @@
1
+ /**
2
+ * Database Manager
3
+ * SQLite/libSQL database operations for context persistence
4
+ */
5
+ import { createClient } from "@libsql/client";
6
+ import { homedir } from "os";
7
+ import { join } from "path";
8
+ import { mkdirSync, existsSync } from "fs";
9
+ import { randomUUID } from "crypto";
10
+ import { logger } from "../utils/logger.js";
11
+ const SWARM_DIR = join(homedir(), ".swarm-mcp-enterprise");
12
+ const DB_PATH = `file:${join(SWARM_DIR, "swarm.db")}`;
13
+ /**
14
+ * Database Manager
15
+ * Handles all database operations
16
+ */
17
+ export class DatabaseManager {
18
+ client = null;
19
+ initialized = false;
20
+ /**
21
+ * Initialize database connection and schema
22
+ */
23
+ async initialize() {
24
+ if (this.initialized)
25
+ return;
26
+ // Create directory if not exists
27
+ if (!existsSync(SWARM_DIR)) {
28
+ mkdirSync(SWARM_DIR, { recursive: true });
29
+ }
30
+ // Create client
31
+ this.client = createClient({ url: DB_PATH });
32
+ // Create tables
33
+ await this.createSchema();
34
+ this.initialized = true;
35
+ // logger.info("Database initialized", { path: DB_PATH });
36
+ }
37
+ /**
38
+ * Create database schema
39
+ */
40
+ async createSchema() {
41
+ if (!this.client)
42
+ throw new Error("Database not initialized");
43
+ // Agents table
44
+ await this.client.execute(`
45
+ CREATE TABLE IF NOT EXISTS agents (
46
+ id TEXT PRIMARY KEY,
47
+ type TEXT NOT NULL,
48
+ name TEXT NOT NULL,
49
+ mode TEXT DEFAULT 'plan',
50
+ status TEXT DEFAULT 'idle',
51
+ current_task TEXT,
52
+ capabilities TEXT,
53
+ metadata TEXT,
54
+ created_at TEXT DEFAULT CURRENT_TIMESTAMP,
55
+ last_active_at TEXT DEFAULT CURRENT_TIMESTAMP,
56
+ health_check_at TEXT
57
+ )
58
+ `);
59
+ // Tasks table
60
+ await this.client.execute(`
61
+ CREATE TABLE IF NOT EXISTS tasks (
62
+ id TEXT PRIMARY KEY,
63
+ agent_id TEXT NOT NULL,
64
+ type TEXT NOT NULL,
65
+ description TEXT NOT NULL,
66
+ context TEXT,
67
+ status TEXT DEFAULT 'pending',
68
+ priority INTEGER DEFAULT 5,
69
+ result TEXT,
70
+ error TEXT,
71
+ created_at TEXT DEFAULT CURRENT_TIMESTAMP,
72
+ started_at TEXT,
73
+ completed_at TEXT,
74
+ timeout INTEGER DEFAULT 60,
75
+ FOREIGN KEY (agent_id) REFERENCES agents(id)
76
+ )
77
+ `);
78
+ // Thought chains table
79
+ await this.client.execute(`
80
+ CREATE TABLE IF NOT EXISTS thought_chains (
81
+ id TEXT PRIMARY KEY,
82
+ agent_id TEXT NOT NULL,
83
+ task_id TEXT NOT NULL,
84
+ title TEXT NOT NULL,
85
+ thoughts TEXT,
86
+ branches TEXT,
87
+ current_step INTEGER DEFAULT 0,
88
+ status TEXT DEFAULT 'active',
89
+ created_at TEXT DEFAULT CURRENT_TIMESTAMP,
90
+ updated_at TEXT DEFAULT CURRENT_TIMESTAMP,
91
+ FOREIGN KEY (agent_id) REFERENCES agents(id),
92
+ FOREIGN KEY (task_id) REFERENCES tasks(id)
93
+ )
94
+ `);
95
+ // Contexts table
96
+ await this.client.execute(`
97
+ CREATE TABLE IF NOT EXISTS contexts (
98
+ id TEXT PRIMARY KEY,
99
+ agent_id TEXT NOT NULL,
100
+ messages TEXT,
101
+ artifacts TEXT,
102
+ checkpoints TEXT,
103
+ summary TEXT,
104
+ token_count INTEGER DEFAULT 0,
105
+ max_tokens INTEGER DEFAULT 4000,
106
+ created_at TEXT DEFAULT CURRENT_TIMESTAMP,
107
+ updated_at TEXT DEFAULT CURRENT_TIMESTAMP,
108
+ FOREIGN KEY (agent_id) REFERENCES agents(id)
109
+ )
110
+ `);
111
+ // Handoffs table
112
+ await this.client.execute(`
113
+ CREATE TABLE IF NOT EXISTS handoffs (
114
+ id TEXT PRIMARY KEY,
115
+ from_agent_id TEXT NOT NULL,
116
+ to_agent_id TEXT NOT NULL,
117
+ task_id TEXT NOT NULL,
118
+ context_snapshot TEXT,
119
+ notes TEXT,
120
+ timestamp TEXT DEFAULT CURRENT_TIMESTAMP,
121
+ FOREIGN KEY (from_agent_id) REFERENCES agents(id),
122
+ FOREIGN KEY (to_agent_id) REFERENCES agents(id),
123
+ FOREIGN KEY (task_id) REFERENCES tasks(id)
124
+ )
125
+ `);
126
+ // Checkpoints table
127
+ await this.client.execute(`
128
+ CREATE TABLE IF NOT EXISTS checkpoints (
129
+ id TEXT PRIMARY KEY,
130
+ context_id TEXT NOT NULL,
131
+ sequence INTEGER NOT NULL,
132
+ messages TEXT,
133
+ artifacts TEXT,
134
+ thought_chain_id TEXT,
135
+ created_at TEXT DEFAULT CURRENT_TIMESTAMP,
136
+ FOREIGN KEY (context_id) REFERENCES contexts(id),
137
+ FOREIGN KEY (thought_chain_id) REFERENCES thought_chains(id)
138
+ )
139
+ `);
140
+ // Audit logs table
141
+ await this.client.execute(`
142
+ CREATE TABLE IF NOT EXISTS audit_logs (
143
+ id TEXT PRIMARY KEY,
144
+ timestamp TEXT DEFAULT CURRENT_TIMESTAMP,
145
+ level TEXT NOT NULL,
146
+ category TEXT NOT NULL,
147
+ agent_id TEXT,
148
+ task_id TEXT,
149
+ action TEXT NOT NULL,
150
+ details TEXT,
151
+ ip TEXT,
152
+ user_agent TEXT
153
+ )
154
+ `);
155
+ // Parallel executions table
156
+ await this.client.execute(`
157
+ CREATE TABLE IF NOT EXISTS parallel_executions (
158
+ id TEXT PRIMARY KEY,
159
+ batch_id TEXT NOT NULL,
160
+ tasks TEXT,
161
+ max_concurrency INTEGER DEFAULT 5,
162
+ status TEXT DEFAULT 'pending',
163
+ results TEXT,
164
+ aggregated_report TEXT,
165
+ created_at TEXT DEFAULT CURRENT_TIMESTAMP,
166
+ completed_at TEXT
167
+ )
168
+ `);
169
+ // Create indexes
170
+ await this.client.execute(`CREATE INDEX IF NOT EXISTS idx_agents_status ON agents(status)`);
171
+ await this.client.execute(`CREATE INDEX IF NOT EXISTS idx_agents_type ON agents(type)`);
172
+ await this.client.execute(`CREATE INDEX IF NOT EXISTS idx_tasks_agent_id ON tasks(agent_id)`);
173
+ await this.client.execute(`CREATE INDEX IF NOT EXISTS idx_tasks_status ON tasks(status)`);
174
+ await this.client.execute(`CREATE INDEX IF NOT EXISTS idx_thought_chains_agent ON thought_chains(agent_id)`);
175
+ await this.client.execute(`CREATE INDEX IF NOT EXISTS idx_contexts_agent ON contexts(agent_id)`);
176
+ await this.client.execute(`CREATE INDEX IF NOT EXISTS idx_audit_timestamp ON audit_logs(timestamp)`);
177
+ }
178
+ // ============================================
179
+ // Agent Operations
180
+ // ============================================
181
+ async saveAgent(agent) {
182
+ if (!this.client)
183
+ throw new Error("Database not initialized");
184
+ await this.client.execute({
185
+ sql: `
186
+ INSERT OR REPLACE INTO agents
187
+ (id, type, name, mode, status, current_task, capabilities, metadata, created_at, last_active_at, health_check_at)
188
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
189
+ `,
190
+ args: [
191
+ agent.id,
192
+ agent.type,
193
+ agent.name,
194
+ agent.mode,
195
+ agent.status,
196
+ agent.currentTask || null,
197
+ JSON.stringify(agent.capabilities),
198
+ JSON.stringify(agent.metadata),
199
+ agent.createdAt,
200
+ agent.lastActiveAt,
201
+ agent.healthCheckAt || null,
202
+ ],
203
+ });
204
+ }
205
+ async getAgent(agentId) {
206
+ if (!this.client)
207
+ throw new Error("Database not initialized");
208
+ const result = await this.client.execute({
209
+ sql: "SELECT * FROM agents WHERE id = ?",
210
+ args: [agentId],
211
+ });
212
+ if (result.rows.length === 0)
213
+ return null;
214
+ const row = result.rows[0];
215
+ return this.rowToAgent(row);
216
+ }
217
+ async getAllAgents() {
218
+ if (!this.client)
219
+ throw new Error("Database not initialized");
220
+ const result = await this.client.execute("SELECT * FROM agents");
221
+ return result.rows.map((row) => this.rowToAgent(row));
222
+ }
223
+ async getAgentsByType(type) {
224
+ if (!this.client)
225
+ throw new Error("Database not initialized");
226
+ const result = await this.client.execute({
227
+ sql: "SELECT * FROM agents WHERE type = ?",
228
+ args: [type],
229
+ });
230
+ return result.rows.map((row) => this.rowToAgent(row));
231
+ }
232
+ async getAgentsByStatus(status) {
233
+ if (!this.client)
234
+ throw new Error("Database not initialized");
235
+ const result = await this.client.execute({
236
+ sql: "SELECT * FROM agents WHERE status = ?",
237
+ args: [status],
238
+ });
239
+ return result.rows.map((row) => this.rowToAgent(row));
240
+ }
241
+ async deleteAgent(agentId) {
242
+ if (!this.client)
243
+ throw new Error("Database not initialized");
244
+ const result = await this.client.execute({
245
+ sql: "DELETE FROM agents WHERE id = ?",
246
+ args: [agentId],
247
+ });
248
+ return result.rowsAffected > 0;
249
+ }
250
+ // ============================================
251
+ // Task Operations
252
+ // ============================================
253
+ async saveTask(task) {
254
+ if (!this.client)
255
+ throw new Error("Database not initialized");
256
+ await this.client.execute({
257
+ sql: `
258
+ INSERT OR REPLACE INTO tasks
259
+ (id, agent_id, type, description, context, status, priority, result, error, created_at, started_at, completed_at, timeout)
260
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
261
+ `,
262
+ args: [
263
+ task.id,
264
+ task.agentId,
265
+ task.type,
266
+ task.description,
267
+ JSON.stringify(task.context),
268
+ task.status,
269
+ task.priority,
270
+ task.result ? JSON.stringify(task.result) : null,
271
+ task.error || null,
272
+ task.createdAt,
273
+ task.startedAt || null,
274
+ task.completedAt || null,
275
+ task.timeout,
276
+ ],
277
+ });
278
+ }
279
+ async getTask(taskId) {
280
+ if (!this.client)
281
+ throw new Error("Database not initialized");
282
+ const result = await this.client.execute({
283
+ sql: "SELECT * FROM tasks WHERE id = ?",
284
+ args: [taskId],
285
+ });
286
+ if (result.rows.length === 0)
287
+ return null;
288
+ return this.rowToTask(result.rows[0]);
289
+ }
290
+ async getTasksByAgent(agentId) {
291
+ if (!this.client)
292
+ throw new Error("Database not initialized");
293
+ const result = await this.client.execute({
294
+ sql: "SELECT * FROM tasks WHERE agent_id = ? ORDER BY created_at DESC",
295
+ args: [agentId],
296
+ });
297
+ return result.rows.map((row) => this.rowToTask(row));
298
+ }
299
+ async getTasksByStatus(status) {
300
+ if (!this.client)
301
+ throw new Error("Database not initialized");
302
+ const result = await this.client.execute({
303
+ sql: "SELECT * FROM tasks WHERE status = ?",
304
+ args: [status],
305
+ });
306
+ return result.rows.map((row) => this.rowToTask(row));
307
+ }
308
+ // ============================================
309
+ // Context Operations
310
+ // ============================================
311
+ async saveContext(context) {
312
+ if (!this.client)
313
+ throw new Error("Database not initialized");
314
+ await this.client.execute({
315
+ sql: `
316
+ INSERT OR REPLACE INTO contexts
317
+ (id, agent_id, messages, artifacts, checkpoints, summary, token_count, max_tokens, created_at, updated_at)
318
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
319
+ `,
320
+ args: [
321
+ context.id,
322
+ context.agentId,
323
+ JSON.stringify(context.messages),
324
+ JSON.stringify(context.artifacts),
325
+ JSON.stringify(context.checkpoints),
326
+ context.summary || null,
327
+ context.tokenCount,
328
+ context.maxTokens,
329
+ context.createdAt,
330
+ context.updatedAt,
331
+ ],
332
+ });
333
+ }
334
+ async getContext(contextId) {
335
+ if (!this.client)
336
+ throw new Error("Database not initialized");
337
+ const result = await this.client.execute({
338
+ sql: "SELECT * FROM contexts WHERE id = ?",
339
+ args: [contextId],
340
+ });
341
+ if (result.rows.length === 0)
342
+ return null;
343
+ return this.rowToContext(result.rows[0]);
344
+ }
345
+ async getContextByAgent(agentId) {
346
+ if (!this.client)
347
+ throw new Error("Database not initialized");
348
+ const result = await this.client.execute({
349
+ sql: "SELECT * FROM contexts WHERE agent_id = ? ORDER BY updated_at DESC LIMIT 1",
350
+ args: [agentId],
351
+ });
352
+ if (result.rows.length === 0)
353
+ return null;
354
+ return this.rowToContext(result.rows[0]);
355
+ }
356
+ // ============================================
357
+ // Checkpoint Operations
358
+ // ============================================
359
+ async saveCheckpoint(checkpoint) {
360
+ if (!this.client)
361
+ throw new Error("Database not initialized");
362
+ await this.client.execute({
363
+ sql: `
364
+ INSERT OR REPLACE INTO checkpoints
365
+ (id, context_id, sequence, messages, artifacts, thought_chain_id, created_at)
366
+ VALUES (?, ?, ?, ?, ?, ?, ?)
367
+ `,
368
+ args: [
369
+ checkpoint.id,
370
+ checkpoint.contextId,
371
+ checkpoint.sequence,
372
+ JSON.stringify(checkpoint.messages),
373
+ JSON.stringify(checkpoint.artifacts),
374
+ checkpoint.thoughtChainId || null,
375
+ checkpoint.createdAt,
376
+ ],
377
+ });
378
+ }
379
+ async getCheckpointsByContext(contextId) {
380
+ if (!this.client)
381
+ throw new Error("Database not initialized");
382
+ const result = await this.client.execute({
383
+ sql: "SELECT * FROM checkpoints WHERE context_id = ? ORDER BY sequence ASC",
384
+ args: [contextId],
385
+ });
386
+ return result.rows.map((row) => this.rowToCheckpoint(row));
387
+ }
388
+ // ============================================
389
+ // Handoff Operations
390
+ // ============================================
391
+ async saveHandoff(handoff) {
392
+ if (!this.client)
393
+ throw new Error("Database not initialized");
394
+ await this.client.execute({
395
+ sql: `
396
+ INSERT OR REPLACE INTO handoffs
397
+ (id, from_agent_id, to_agent_id, task_id, context_snapshot, notes, timestamp)
398
+ VALUES (?, ?, ?, ?, ?, ?, ?)
399
+ `,
400
+ args: [
401
+ handoff.id,
402
+ handoff.fromAgentId,
403
+ handoff.toAgentId,
404
+ handoff.taskId,
405
+ JSON.stringify(handoff.contextSnapshot),
406
+ handoff.notes || null,
407
+ handoff.timestamp,
408
+ ],
409
+ });
410
+ }
411
+ async getHandoffsByAgent(agentId) {
412
+ if (!this.client)
413
+ throw new Error("Database not initialized");
414
+ const result = await this.client.execute({
415
+ sql: `
416
+ SELECT * FROM handoffs
417
+ WHERE from_agent_id = ? OR to_agent_id = ?
418
+ ORDER BY timestamp DESC
419
+ `,
420
+ args: [agentId, agentId],
421
+ });
422
+ return result.rows.map((row) => this.rowToHandoff(row));
423
+ }
424
+ // ============================================
425
+ // Audit Log Operations
426
+ // ============================================
427
+ async saveAuditLog(log) {
428
+ if (!this.client)
429
+ throw new Error("Database not initialized");
430
+ await this.client.execute({
431
+ sql: `
432
+ INSERT INTO audit_logs
433
+ (id, timestamp, level, category, agent_id, task_id, action, details)
434
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?)
435
+ `,
436
+ args: [
437
+ randomUUID(),
438
+ new Date().toISOString(),
439
+ log.level,
440
+ log.category,
441
+ log.agentId || null,
442
+ log.taskId || null,
443
+ log.action,
444
+ log.details ? JSON.stringify(log.details) : null,
445
+ ],
446
+ });
447
+ }
448
+ async getAuditLogs(options = {}) {
449
+ if (!this.client)
450
+ throw new Error("Database not initialized");
451
+ let sql = "SELECT * FROM audit_logs WHERE 1=1";
452
+ const args = [];
453
+ if (options.level) {
454
+ sql += " AND level = ?";
455
+ args.push(options.level);
456
+ }
457
+ if (options.category) {
458
+ sql += " AND category = ?";
459
+ args.push(options.category);
460
+ }
461
+ if (options.agentId) {
462
+ sql += " AND agent_id = ?";
463
+ args.push(options.agentId);
464
+ }
465
+ if (options.since) {
466
+ sql += " AND timestamp > ?";
467
+ args.push(options.since.toISOString());
468
+ }
469
+ sql += " ORDER BY timestamp DESC";
470
+ if (options.limit) {
471
+ sql += " LIMIT ?";
472
+ args.push(options.limit);
473
+ }
474
+ const result = await this.client.execute({ sql, args: args });
475
+ return result.rows;
476
+ }
477
+ // ============================================
478
+ // Thought Chain Operations
479
+ // ============================================
480
+ async saveThoughtChain(chain) {
481
+ if (!this.client)
482
+ throw new Error("Database not initialized");
483
+ const branchesObj = {};
484
+ for (const [key, value] of chain.branches.entries()) {
485
+ branchesObj[key] = value;
486
+ }
487
+ await this.client.execute({
488
+ sql: `
489
+ INSERT OR REPLACE INTO thought_chains
490
+ (id, agent_id, task_id, title, thoughts, branches, current_step, status, created_at, updated_at)
491
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
492
+ `,
493
+ args: [
494
+ chain.id,
495
+ chain.agentId,
496
+ chain.taskId,
497
+ chain.title,
498
+ JSON.stringify(chain.thoughts),
499
+ JSON.stringify(branchesObj),
500
+ chain.currentStep,
501
+ chain.status,
502
+ chain.createdAt,
503
+ chain.updatedAt,
504
+ ],
505
+ });
506
+ }
507
+ async getThoughtChain(chainId) {
508
+ if (!this.client)
509
+ throw new Error("Database not initialized");
510
+ const result = await this.client.execute({
511
+ sql: "SELECT * FROM thought_chains WHERE id = ?",
512
+ args: [chainId],
513
+ });
514
+ if (result.rows.length === 0)
515
+ return null;
516
+ return this.rowToThoughtChain(result.rows[0]);
517
+ }
518
+ async getThoughtChainsByAgent(agentId) {
519
+ if (!this.client)
520
+ throw new Error("Database not initialized");
521
+ const result = await this.client.execute({
522
+ sql: "SELECT * FROM thought_chains WHERE agent_id = ? ORDER BY updated_at DESC",
523
+ args: [agentId],
524
+ });
525
+ return result.rows.map((row) => this.rowToThoughtChain(row));
526
+ }
527
+ // ============================================
528
+ // Parallel Execution Operations
529
+ // ============================================
530
+ async saveParallelExecution(execution) {
531
+ if (!this.client)
532
+ throw new Error("Database not initialized");
533
+ const resultsObj = {};
534
+ for (const [key, value] of execution.results.entries()) {
535
+ resultsObj[key] = value;
536
+ }
537
+ await this.client.execute({
538
+ sql: `
539
+ INSERT OR REPLACE INTO parallel_executions
540
+ (id, batch_id, tasks, max_concurrency, status, results, aggregated_report, created_at, completed_at)
541
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
542
+ `,
543
+ args: [
544
+ execution.id,
545
+ execution.batchId,
546
+ JSON.stringify(execution.tasks),
547
+ execution.maxConcurrency,
548
+ execution.status,
549
+ JSON.stringify(resultsObj),
550
+ execution.aggregatedReport || null,
551
+ execution.createdAt,
552
+ execution.completedAt || null,
553
+ ],
554
+ });
555
+ }
556
+ async getParallelExecution(executionId) {
557
+ if (!this.client)
558
+ throw new Error("Database not initialized");
559
+ const result = await this.client.execute({
560
+ sql: "SELECT * FROM parallel_executions WHERE id = ?",
561
+ args: [executionId],
562
+ });
563
+ if (result.rows.length === 0)
564
+ return null;
565
+ return this.rowToParallelExecution(result.rows[0]);
566
+ }
567
+ // ============================================
568
+ // Statistics
569
+ // ============================================
570
+ async getSystemStats() {
571
+ if (!this.client)
572
+ throw new Error("Database not initialized");
573
+ const [totalAgents, agentsByStatus, agentsByType, totalTasks, tasksByStatus, totalContexts, totalCheckpoints, totalHandoffs,] = await Promise.all([
574
+ this.client.execute("SELECT COUNT(*) as count FROM agents"),
575
+ this.client.execute("SELECT status, COUNT(*) as count FROM agents GROUP BY status"),
576
+ this.client.execute("SELECT type, COUNT(*) as count FROM agents GROUP BY type"),
577
+ this.client.execute("SELECT COUNT(*) as count FROM tasks"),
578
+ this.client.execute("SELECT status, COUNT(*) as count FROM tasks GROUP BY status"),
579
+ this.client.execute("SELECT COUNT(*) as count FROM contexts"),
580
+ this.client.execute("SELECT COUNT(*) as count FROM checkpoints"),
581
+ this.client.execute("SELECT COUNT(*) as count FROM handoffs"),
582
+ ]);
583
+ return {
584
+ totalAgents: totalAgents.rows[0]?.count ?? 0,
585
+ agentsByStatus: Object.fromEntries(agentsByStatus.rows.map((r) => [
586
+ r.status,
587
+ r.count,
588
+ ])),
589
+ agentsByType: Object.fromEntries(agentsByType.rows.map((r) => [
590
+ r.type,
591
+ r.count,
592
+ ])),
593
+ totalTasks: totalTasks.rows[0]?.count ?? 0,
594
+ tasksByStatus: Object.fromEntries(tasksByStatus.rows.map((r) => [
595
+ r.status,
596
+ r.count,
597
+ ])),
598
+ totalContexts: totalContexts.rows[0]?.count ?? 0,
599
+ totalCheckpoints: totalCheckpoints.rows[0]?.count ?? 0,
600
+ totalHandoffs: totalHandoffs.rows[0]?.count ?? 0,
601
+ };
602
+ }
603
+ // ============================================
604
+ // Safe JSON Parsing
605
+ // ============================================
606
+ safeJsonParse(json, defaultValue) {
607
+ if (!json)
608
+ return defaultValue;
609
+ try {
610
+ return JSON.parse(json);
611
+ }
612
+ catch (error) {
613
+ logger.error("Failed to parse JSON from database", {
614
+ error: error instanceof Error ? error.message : String(error),
615
+ json: json.substring(0, 200),
616
+ });
617
+ return defaultValue;
618
+ }
619
+ }
620
+ // ============================================
621
+ // Row Converters
622
+ // ============================================
623
+ rowToAgent(row) {
624
+ return {
625
+ id: row.id,
626
+ type: row.type,
627
+ name: row.name,
628
+ mode: row.mode || "plan",
629
+ status: row.status,
630
+ currentTask: row.current_task,
631
+ capabilities: this.safeJsonParse(row.capabilities, []),
632
+ metadata: this.safeJsonParse(row.metadata, {}),
633
+ createdAt: row.created_at,
634
+ lastActiveAt: row.last_active_at,
635
+ healthCheckAt: row.health_check_at,
636
+ };
637
+ }
638
+ rowToTask(row) {
639
+ return {
640
+ id: row.id,
641
+ agentId: row.agent_id,
642
+ type: row.type,
643
+ description: row.description,
644
+ context: this.safeJsonParse(row.context, {}),
645
+ status: row.status,
646
+ priority: row.priority || 5,
647
+ result: row.result ? this.safeJsonParse(row.result, undefined) : undefined,
648
+ error: row.error,
649
+ createdAt: row.created_at,
650
+ startedAt: row.started_at,
651
+ completedAt: row.completed_at,
652
+ timeout: row.timeout || 60,
653
+ };
654
+ }
655
+ rowToContext(row) {
656
+ return {
657
+ id: row.id,
658
+ agentId: row.agent_id,
659
+ messages: this.safeJsonParse(row.messages, []),
660
+ artifacts: this.safeJsonParse(row.artifacts, []),
661
+ checkpoints: this.safeJsonParse(row.checkpoints, []),
662
+ summary: row.summary,
663
+ tokenCount: row.token_count || 0,
664
+ maxTokens: row.max_tokens || 4000,
665
+ createdAt: row.created_at,
666
+ updatedAt: row.updated_at,
667
+ };
668
+ }
669
+ rowToCheckpoint(row) {
670
+ return {
671
+ id: row.id,
672
+ contextId: row.context_id,
673
+ sequence: row.sequence,
674
+ messages: this.safeJsonParse(row.messages, []),
675
+ artifacts: this.safeJsonParse(row.artifacts, []),
676
+ thoughtChainId: row.thought_chain_id,
677
+ createdAt: row.created_at,
678
+ };
679
+ }
680
+ rowToHandoff(row) {
681
+ return {
682
+ id: row.id,
683
+ fromAgentId: row.from_agent_id,
684
+ toAgentId: row.to_agent_id,
685
+ taskId: row.task_id,
686
+ contextSnapshot: this.safeJsonParse(row.context_snapshot, { messages: [], artifacts: [] }),
687
+ notes: row.notes,
688
+ timestamp: row.timestamp,
689
+ };
690
+ }
691
+ rowToThoughtChain(row) {
692
+ const branchesObj = this.safeJsonParse(row.branches, {});
693
+ const branches = new Map();
694
+ for (const [key, value] of Object.entries(branchesObj)) {
695
+ branches.set(key, value);
696
+ }
697
+ return {
698
+ id: row.id,
699
+ agentId: row.agent_id,
700
+ taskId: row.task_id,
701
+ title: row.title,
702
+ thoughts: this.safeJsonParse(row.thoughts, []),
703
+ branches,
704
+ currentStep: row.current_step || 0,
705
+ status: row.status || "active",
706
+ createdAt: row.created_at,
707
+ updatedAt: row.updated_at,
708
+ };
709
+ }
710
+ rowToParallelExecution(row) {
711
+ const resultsObj = this.safeJsonParse(row.results, {});
712
+ const results = new Map();
713
+ for (const [key, value] of Object.entries(resultsObj)) {
714
+ results.set(key, value);
715
+ }
716
+ return {
717
+ id: row.id,
718
+ batchId: row.batch_id,
719
+ tasks: this.safeJsonParse(row.tasks, []),
720
+ maxConcurrency: row.max_concurrency || 5,
721
+ status: row.status || "pending",
722
+ results,
723
+ aggregatedReport: row.aggregated_report,
724
+ createdAt: row.created_at,
725
+ completedAt: row.completed_at,
726
+ };
727
+ }
728
+ /**
729
+ * Close database connection
730
+ */
731
+ async close() {
732
+ if (this.client) {
733
+ try {
734
+ // Attempt to close the client if it has a close method
735
+ await this.client.close?.();
736
+ }
737
+ catch (error) {
738
+ // Log but don't throw - client might not have close method or already closed
739
+ logger.debug("Note during database close (non-critical)", {
740
+ error: error instanceof Error ? error.message : String(error),
741
+ });
742
+ }
743
+ this.client = null;
744
+ this.initialized = false;
745
+ logger.info("Database connection closed");
746
+ }
747
+ }
748
+ }
749
+ // Export singleton instance
750
+ export const database = new DatabaseManager();
751
+ //# sourceMappingURL=database.js.map