claude-flow 2.0.0-alpha.99 → 2.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/.claude/agents/MIGRATION_SUMMARY.md +7 -0
- package/.claude/agents/README.md +7 -0
- package/.claude/agents/consensus/README.md +7 -0
- package/.claude/agents/flow-nexus/app-store.md +88 -0
- package/.claude/agents/flow-nexus/authentication.md +69 -0
- package/.claude/agents/flow-nexus/challenges.md +81 -0
- package/.claude/agents/flow-nexus/neural-network.md +88 -0
- package/.claude/agents/flow-nexus/payments.md +83 -0
- package/.claude/agents/flow-nexus/sandbox.md +76 -0
- package/.claude/agents/flow-nexus/swarm.md +76 -0
- package/.claude/agents/flow-nexus/user-tools.md +96 -0
- package/.claude/agents/flow-nexus/workflow.md +84 -0
- package/.claude/agents/optimization/README.md +7 -0
- package/.claude/agents/optimization/benchmark-suite.md +7 -0
- package/.claude/agents/optimization/load-balancer.md +7 -0
- package/.claude/agents/optimization/performance-monitor.md +7 -0
- package/.claude/agents/optimization/resource-allocator.md +7 -0
- package/.claude/agents/optimization/topology-optimizer.md +7 -0
- package/.claude/agents/swarm/README.md +7 -0
- package/.claude/checkpoints/1756227652.json +1 -0
- package/.claude/checkpoints/1756227653.json +1 -0
- package/.claude/checkpoints/1756227666.json +1 -0
- package/.claude/checkpoints/1756227668.json +1 -0
- package/.claude/checkpoints/1756227723.json +1 -0
- package/.claude/checkpoints/1756227725.json +1 -0
- package/.claude/checkpoints/1756227731.json +1 -0
- package/.claude/checkpoints/1756227733.json +1 -0
- package/.claude/checkpoints/1756231330.json +1 -0
- package/.claude/checkpoints/1756231331.json +1 -0
- package/.claude/checkpoints/1756231342.json +1 -0
- package/.claude/checkpoints/1756231344.json +1 -0
- package/.claude/checkpoints/1756231355.json +1 -0
- package/.claude/checkpoints/1756231357.json +1 -0
- package/.claude/checkpoints/1756231367.json +1 -0
- package/.claude/checkpoints/1756231368.json +1 -0
- package/.claude/checkpoints/1756231458.json +1 -0
- package/.claude/checkpoints/1756231459.json +1 -0
- package/.claude/checkpoints/1756231477.json +1 -0
- package/.claude/checkpoints/1756231479.json +1 -0
- package/.claude/checkpoints/1756233026.json +1 -0
- package/.claude/checkpoints/1756233028.json +1 -0
- package/.claude/checkpoints/1756233040.json +1 -0
- package/.claude/checkpoints/1756233041.json +1 -0
- package/.claude/checkpoints/1756233057.json +1 -0
- package/.claude/checkpoints/1756233059.json +1 -0
- package/.claude/checkpoints/1756233090.json +1 -0
- package/.claude/checkpoints/1756233092.json +1 -0
- package/.claude/checkpoints/1756233141.json +1 -0
- package/.claude/checkpoints/1756233143.json +1 -0
- package/.claude/checkpoints/1756475935.json +1 -0
- package/.claude/checkpoints/1756475936.json +1 -0
- package/.claude/checkpoints/1756475996.json +1 -0
- package/.claude/checkpoints/1756475998.json +1 -0
- package/.claude/checkpoints/1756476093.json +1 -0
- package/.claude/checkpoints/1756476098.json +1 -0
- package/.claude/checkpoints/1756476100.json +1 -0
- package/.claude/checkpoints/1756476101.json +1 -0
- package/.claude/checkpoints/1756476161.json +1 -0
- package/.claude/checkpoints/1756476163.json +1 -0
- package/.claude/checkpoints/1756476183.json +1 -0
- package/.claude/checkpoints/1756476184.json +1 -0
- package/.claude/checkpoints/1756476193.json +1 -0
- package/.claude/checkpoints/1756476194.json +1 -0
- package/.claude/checkpoints/1756476202.json +1 -0
- package/.claude/checkpoints/1756476204.json +1 -0
- package/.claude/checkpoints/1756476268.json +1 -0
- package/.claude/checkpoints/1756476269.json +1 -0
- package/.claude/checkpoints/1756476287.json +1 -0
- package/.claude/checkpoints/1756476288.json +1 -0
- package/.claude/checkpoints/1756997935.json +1 -0
- package/.claude/checkpoints/1756997937.json +1 -0
- package/.claude/checkpoints/1756997938.json +1 -0
- package/.claude/checkpoints/1756997940.json +1 -0
- package/.claude/checkpoints/1756997942.json +1 -0
- package/.claude/checkpoints/1756997944.json +1 -0
- package/.claude/checkpoints/1756997945.json +1 -0
- package/.claude/checkpoints/1756997947.json +1 -0
- package/.claude/checkpoints/1756997949.json +1 -0
- package/.claude/checkpoints/1756997951.json +1 -0
- package/.claude/checkpoints/1756997953.json +1 -0
- package/.claude/checkpoints/1756997955.json +1 -0
- package/.claude/checkpoints/1756997956.json +1 -0
- package/.claude/checkpoints/1756997958.json +1 -0
- package/.claude/checkpoints/1756997960.json +1 -0
- package/.claude/checkpoints/1756997962.json +1 -0
- package/.claude/checkpoints/1756997964.json +1 -0
- package/.claude/checkpoints/1756997966.json +1 -0
- package/.claude/checkpoints/1756997968.json +1 -0
- package/.claude/checkpoints/1756997970.json +1 -0
- package/.claude/checkpoints/1757190213.json +1 -0
- package/.claude/checkpoints/1757190215.json +1 -0
- package/.claude/checkpoints/1757190217.json +1 -0
- package/.claude/checkpoints/1757190219.json +1 -0
- package/.claude/checkpoints/1757190220.json +1 -0
- package/.claude/checkpoints/1757190222.json +1 -0
- package/.claude/checkpoints/1757190224.json +1 -0
- package/.claude/checkpoints/1757190225.json +1 -0
- package/.claude/checkpoints/1757190227.json +1 -0
- package/.claude/checkpoints/1757190229.json +1 -0
- package/.claude/checkpoints/1757190231.json +1 -0
- package/.claude/checkpoints/1757190232.json +1 -0
- package/.claude/checkpoints/1757190234.json +1 -0
- package/.claude/checkpoints/1757190236.json +1 -0
- package/.claude/checkpoints/1757190238.json +1 -0
- package/.claude/checkpoints/1757190240.json +1 -0
- package/.claude/checkpoints/1757190241.json +1 -0
- package/.claude/checkpoints/1757190243.json +1 -0
- package/.claude/checkpoints/1757190245.json +1 -0
- package/.claude/checkpoints/1757190247.json +1 -0
- package/.claude/checkpoints/1757190608.json +1 -0
- package/.claude/checkpoints/1757190610.json +1 -0
- package/.claude/checkpoints/1757190626.json +1 -0
- package/.claude/checkpoints/1757190628.json +1 -0
- package/.claude/checkpoints/1757190993.json +1 -0
- package/.claude/checkpoints/1757190997.json +1 -0
- package/.claude/checkpoints/1757191001.json +1 -0
- package/.claude/checkpoints/1757191004.json +1 -0
- package/.claude/checkpoints/1757191007.json +1 -0
- package/.claude/checkpoints/1757191009.json +1 -0
- package/.claude/checkpoints/1757191012.json +1 -0
- package/.claude/checkpoints/1757191014.json +1 -0
- package/.claude/checkpoints/1757191016.json +1 -0
- package/.claude/checkpoints/1757191019.json +1 -0
- package/.claude/checkpoints/1757191022.json +1 -0
- package/.claude/checkpoints/1757191024.json +1 -0
- package/.claude/checkpoints/1757191027.json +1 -0
- package/.claude/checkpoints/1757191029.json +1 -0
- package/.claude/checkpoints/1757191032.json +1 -0
- package/.claude/checkpoints/1757191034.json +1 -0
- package/.claude/checkpoints/1757191037.json +1 -0
- package/.claude/checkpoints/1757191040.json +1 -0
- package/.claude/checkpoints/1757191061.json +1 -0
- package/.claude/checkpoints/1757191063.json +1 -0
- package/.claude/checkpoints/1757191084.json +1 -0
- package/.claude/checkpoints/1757191086.json +1 -0
- package/.claude/checkpoints/1757192316.json +1 -0
- package/.claude/checkpoints/1757192318.json +1 -0
- package/.claude/checkpoints/1757192389.json +1 -0
- package/.claude/checkpoints/1757192391.json +1 -0
- package/.claude/checkpoints/1757192489.json +1 -0
- package/.claude/checkpoints/1757192491.json +1 -0
- package/.claude/checkpoints/1757192521.json +1 -0
- package/.claude/checkpoints/1757192523.json +1 -0
- package/.claude/checkpoints/1757192541.json +1 -0
- package/.claude/checkpoints/1757192543.json +1 -0
- package/.claude/checkpoints/1757193796.json +1 -0
- package/.claude/checkpoints/1757194415.json +1 -0
- package/.claude/checkpoints/1757194416.json +1 -0
- package/.claude/checkpoints/1757194435.json +1 -0
- package/.claude/checkpoints/1757194437.json +1 -0
- package/.claude/checkpoints/1757194468.json +1 -0
- package/.claude/checkpoints/1757194469.json +1 -0
- package/.claude/checkpoints/1757194554.json +1 -0
- package/.claude/checkpoints/1757194555.json +1 -0
- package/.claude/checkpoints/1757194606.json +1 -0
- package/.claude/checkpoints/1757194608.json +1 -0
- package/.claude/checkpoints/1757194817.json +1 -0
- package/.claude/checkpoints/1757194818.json +1 -0
- package/.claude/checkpoints/summary-session-20250826-165852.md +1351 -0
- package/.claude/checkpoints/summary-session-20250826-170402.md +1367 -0
- package/.claude/checkpoints/summary-session-20250826-175112.md +1327 -0
- package/.claude/checkpoints/summary-session-20250826-175609.md +1324 -0
- package/.claude/checkpoints/summary-session-20250826-175743.md +1327 -0
- package/.claude/checkpoints/summary-session-20250826-180554.md +1340 -0
- package/.claude/checkpoints/summary-session-20250826-181530.md +1344 -0
- package/.claude/checkpoints/summary-session-20250826-181633.md +1347 -0
- package/.claude/checkpoints/summary-session-20250826-182235.md +1350 -0
- package/.claude/checkpoints/summary-session-20250826-182618.md +1353 -0
- package/.claude/checkpoints/summary-session-20250826-183200.md +1372 -0
- package/.claude/checkpoints/summary-session-20250826-183232.md +1379 -0
- package/.claude/checkpoints/summary-session-20250829-133605.md +38 -0
- package/.claude/checkpoints/summary-session-20250829-134121.md +41 -0
- package/.claude/checkpoints/summary-session-20250829-134400.md +46 -0
- package/.claude/checkpoints/summary-session-20250829-134858.md +49 -0
- package/.claude/checkpoints/summary-session-20250829-135402.md +52 -0
- package/.claude/checkpoints/summary-session-20250829-135640.md +58 -0
- package/.claude/checkpoints/summary-session-20250829-135754.md +65 -0
- package/.claude/checkpoints/summary-session-20250829-135902.md +71 -0
- package/.claude/checkpoints/summary-session-20250829-140629.md +119 -0
- package/.claude/checkpoints/summary-session-20250829-140733.md +121 -0
- package/.claude/checkpoints/summary-session-20250902-190126.md +38 -0
- package/.claude/checkpoints/summary-session-20250904-150003.md +87 -0
- package/.claude/checkpoints/summary-session-20250906-202218.md +2757 -0
- package/.claude/checkpoints/summary-session-20250906-202622.md +2814 -0
- package/.claude/checkpoints/summary-session-20250906-203037.md +2826 -0
- package/.claude/checkpoints/task-1756227619.json +1 -0
- package/.claude/checkpoints/task-1756230633.json +1 -0
- package/.claude/checkpoints/task-1756230902.json +1 -0
- package/.claude/checkpoints/task-1756230993.json +1 -0
- package/.claude/checkpoints/task-1756231253.json +1 -0
- package/.claude/checkpoints/task-1756232070.json +1 -0
- package/.claude/checkpoints/task-1756232144.json +1 -0
- package/.claude/checkpoints/task-1756232251.json +1 -0
- package/.claude/checkpoints/task-1756232564.json +1 -0
- package/.claude/checkpoints/task-1756232982.json +1 -0
- package/.claude/checkpoints/task-1756233131.json +1 -0
- package/.claude/checkpoints/task-1756474562.json +1 -0
- package/.claude/checkpoints/task-1756474754.json +1 -0
- package/.claude/checkpoints/task-1756474922.json +1 -0
- package/.claude/checkpoints/task-1756475028.json +1 -0
- package/.claude/checkpoints/task-1756475307.json +1 -0
- package/.claude/checkpoints/task-1756475349.json +1 -0
- package/.claude/checkpoints/task-1756475699.json +1 -0
- package/.claude/checkpoints/task-1756475719.json +1 -0
- package/.claude/checkpoints/task-1756475828.json +1 -0
- package/.claude/checkpoints/task-1756475858.json +1 -0
- package/.claude/checkpoints/task-1756475868.json +1 -0
- package/.claude/checkpoints/task-1756476373.json +1 -0
- package/.claude/checkpoints/task-1756839595.json +1 -0
- package/.claude/checkpoints/task-1756997821.json +1 -0
- package/.claude/checkpoints/task-1757189936.json +1 -0
- package/.claude/checkpoints/task-1757190154.json +1 -0
- package/.claude/checkpoints/task-1757190301.json +1 -0
- package/.claude/checkpoints/task-1757190369.json +1 -0
- package/.claude/checkpoints/task-1757190483.json +1 -0
- package/.claude/checkpoints/task-1757190841.json +1 -0
- package/.claude/checkpoints/task-1757191219.json +1 -0
- package/.claude/checkpoints/task-1757192639.json +1 -0
- package/.claude/checkpoints/task-1757194091.json +1 -0
- package/.claude/checkpoints/task-1757194691.json +1 -0
- package/.claude/checkpoints/task-1757194856.json +1 -0
- package/.claude/commands/flow-nexus/app-store.md +124 -0
- package/.claude/commands/flow-nexus/challenges.md +120 -0
- package/.claude/commands/flow-nexus/login-registration.md +65 -0
- package/.claude/commands/flow-nexus/neural-network.md +134 -0
- package/.claude/commands/flow-nexus/payments.md +116 -0
- package/.claude/commands/flow-nexus/sandbox.md +83 -0
- package/.claude/commands/flow-nexus/swarm.md +87 -0
- package/.claude/commands/flow-nexus/user-tools.md +152 -0
- package/.claude/commands/flow-nexus/workflow.md +115 -0
- package/README.md +29 -1
- package/bin/claude-flow +1 -1
- package/package.json +1 -1
- package/src/api/auth-service.ts +644 -0
- package/src/api/database-schema.sql +366 -0
- package/src/api/database-service.ts +788 -0
- package/src/api/swarm-api.ts +741 -0
- package/src/cli/commands/index.ts +40 -1
- package/src/cli/simple-commands/hive-mind/session-manager.js +12 -0
- package/src/cli/simple-commands/init/agent-copier.js +129 -1
- package/src/cli/simple-commands/init/index.js +116 -1
- package/src/cli/simple-commands/init/templates/claude-md.js +295 -1
- package/src/core/version.js +1 -1
- package/src/ui/console/index.html +4 -0
- package/src/ui/console/js/real-time-dashboard.js +715 -0
- package/src/ui/console/js/swarm-integration.js +485 -0
- package/src/ui/console/js/swarm-visualizer.js +879 -0
- package/src/ui/console/styles/swarm-visualizer.css +487 -0
- package/src/cli/simple-commands/init/.claude-flow/metrics/agent-metrics.json +0 -1
- package/src/cli/simple-commands/init/.claude-flow/metrics/performance.json +0 -9
- package/src/cli/simple-commands/init/.claude-flow/metrics/task-metrics.json +0 -10
- package/src/cli/simple-commands/init/.swarm/memory.db +0 -0
|
@@ -0,0 +1,788 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Database service for swarm coordination system
|
|
3
|
+
* Provides data access layer with support for multiple database engines
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { ILogger } from '../core/logger.js';
|
|
7
|
+
import { ConfigManager } from '../config/config-manager.js';
|
|
8
|
+
import { SwarmError, DatabaseError } from '../utils/errors.js';
|
|
9
|
+
import { nanoid } from 'nanoid';
|
|
10
|
+
|
|
11
|
+
export interface DatabaseConfig {
|
|
12
|
+
type: 'sqlite' | 'mysql' | 'postgresql';
|
|
13
|
+
host?: string;
|
|
14
|
+
port?: number;
|
|
15
|
+
database: string;
|
|
16
|
+
username?: string;
|
|
17
|
+
password?: string;
|
|
18
|
+
ssl?: boolean;
|
|
19
|
+
poolSize?: number;
|
|
20
|
+
timeout?: number;
|
|
21
|
+
retryAttempts?: number;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export interface SwarmRecord {
|
|
25
|
+
id: string;
|
|
26
|
+
name: string;
|
|
27
|
+
topology: 'hierarchical' | 'mesh' | 'ring' | 'star';
|
|
28
|
+
maxAgents: number;
|
|
29
|
+
strategy: 'balanced' | 'specialized' | 'adaptive';
|
|
30
|
+
status: 'initializing' | 'active' | 'paused' | 'destroyed';
|
|
31
|
+
config?: Record<string, unknown>;
|
|
32
|
+
createdAt: Date;
|
|
33
|
+
updatedAt: Date;
|
|
34
|
+
destroyedAt?: Date;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export interface AgentRecord {
|
|
38
|
+
id: string;
|
|
39
|
+
swarmId: string;
|
|
40
|
+
type: string;
|
|
41
|
+
name?: string;
|
|
42
|
+
status: 'spawning' | 'idle' | 'busy' | 'error' | 'terminated';
|
|
43
|
+
capabilities?: string[];
|
|
44
|
+
config?: Record<string, unknown>;
|
|
45
|
+
metadata?: Record<string, unknown>;
|
|
46
|
+
createdAt: Date;
|
|
47
|
+
updatedAt: Date;
|
|
48
|
+
terminatedAt?: Date;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export interface TaskRecord {
|
|
52
|
+
id: string;
|
|
53
|
+
swarmId: string;
|
|
54
|
+
description: string;
|
|
55
|
+
priority: 'low' | 'medium' | 'high' | 'critical';
|
|
56
|
+
strategy: 'parallel' | 'sequential' | 'adaptive';
|
|
57
|
+
status: 'pending' | 'assigned' | 'running' | 'completed' | 'failed' | 'cancelled';
|
|
58
|
+
maxAgents?: number;
|
|
59
|
+
requirements?: string[];
|
|
60
|
+
metadata?: Record<string, unknown>;
|
|
61
|
+
result?: unknown;
|
|
62
|
+
errorMessage?: string;
|
|
63
|
+
assignedTo?: string;
|
|
64
|
+
createdAt: Date;
|
|
65
|
+
updatedAt: Date;
|
|
66
|
+
startedAt?: Date;
|
|
67
|
+
completedAt?: Date;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export interface MetricRecord {
|
|
71
|
+
id: string;
|
|
72
|
+
swarmId?: string;
|
|
73
|
+
agentId?: string;
|
|
74
|
+
metricType: string;
|
|
75
|
+
metricName: string;
|
|
76
|
+
metricValue: number;
|
|
77
|
+
unit?: string;
|
|
78
|
+
timestamp: Date;
|
|
79
|
+
metadata?: Record<string, unknown>;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export interface EventRecord {
|
|
83
|
+
id: string;
|
|
84
|
+
swarmId?: string;
|
|
85
|
+
agentId?: string;
|
|
86
|
+
eventType: string;
|
|
87
|
+
eventName: string;
|
|
88
|
+
eventData?: Record<string, unknown>;
|
|
89
|
+
severity: 'debug' | 'info' | 'warning' | 'error' | 'critical';
|
|
90
|
+
createdAt: Date;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Database service implementation
|
|
95
|
+
*/
|
|
96
|
+
export class DatabaseService {
|
|
97
|
+
private db: any; // Database connection instance
|
|
98
|
+
private initialized = false;
|
|
99
|
+
|
|
100
|
+
constructor(
|
|
101
|
+
private config: DatabaseConfig,
|
|
102
|
+
private logger: ILogger,
|
|
103
|
+
) {}
|
|
104
|
+
|
|
105
|
+
async initialize(): Promise<void> {
|
|
106
|
+
if (this.initialized) {
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
try {
|
|
111
|
+
this.logger.info('Initializing database service', {
|
|
112
|
+
type: this.config.type,
|
|
113
|
+
database: this.config.database,
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
// Initialize database connection based on type
|
|
117
|
+
switch (this.config.type) {
|
|
118
|
+
case 'sqlite':
|
|
119
|
+
await this.initializeSQLite();
|
|
120
|
+
break;
|
|
121
|
+
case 'mysql':
|
|
122
|
+
await this.initializeMySQL();
|
|
123
|
+
break;
|
|
124
|
+
case 'postgresql':
|
|
125
|
+
await this.initializePostgreSQL();
|
|
126
|
+
break;
|
|
127
|
+
default:
|
|
128
|
+
throw new DatabaseError(`Unsupported database type: ${this.config.type}`);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// Run migrations if needed
|
|
132
|
+
await this.runMigrations();
|
|
133
|
+
|
|
134
|
+
this.initialized = true;
|
|
135
|
+
this.logger.info('Database service initialized successfully');
|
|
136
|
+
} catch (error) {
|
|
137
|
+
this.logger.error('Failed to initialize database service', error);
|
|
138
|
+
throw new DatabaseError('Database initialization failed', { error });
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
async shutdown(): Promise<void> {
|
|
143
|
+
if (!this.initialized || !this.db) {
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
try {
|
|
148
|
+
if (this.config.type === 'sqlite') {
|
|
149
|
+
await this.db.close();
|
|
150
|
+
} else {
|
|
151
|
+
await this.db.end();
|
|
152
|
+
}
|
|
153
|
+
this.initialized = false;
|
|
154
|
+
this.logger.info('Database service shutdown complete');
|
|
155
|
+
} catch (error) {
|
|
156
|
+
this.logger.error('Error shutting down database service', error);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// Swarm operations
|
|
161
|
+
async createSwarm(swarm: Omit<SwarmRecord, 'id' | 'createdAt' | 'updatedAt'>): Promise<SwarmRecord> {
|
|
162
|
+
const id = `swarm_${Date.now()}_${nanoid(10)}`;
|
|
163
|
+
const now = new Date();
|
|
164
|
+
|
|
165
|
+
const record: SwarmRecord = {
|
|
166
|
+
id,
|
|
167
|
+
...swarm,
|
|
168
|
+
createdAt: now,
|
|
169
|
+
updatedAt: now,
|
|
170
|
+
};
|
|
171
|
+
|
|
172
|
+
try {
|
|
173
|
+
const query = `
|
|
174
|
+
INSERT INTO swarms (id, name, topology, max_agents, strategy, status, config, created_at, updated_at)
|
|
175
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
176
|
+
`;
|
|
177
|
+
const values = [
|
|
178
|
+
record.id,
|
|
179
|
+
record.name,
|
|
180
|
+
record.topology,
|
|
181
|
+
record.maxAgents,
|
|
182
|
+
record.strategy,
|
|
183
|
+
record.status,
|
|
184
|
+
JSON.stringify(record.config),
|
|
185
|
+
record.createdAt,
|
|
186
|
+
record.updatedAt,
|
|
187
|
+
];
|
|
188
|
+
|
|
189
|
+
await this.execute(query, values);
|
|
190
|
+
return record;
|
|
191
|
+
} catch (error) {
|
|
192
|
+
throw new DatabaseError('Failed to create swarm', { error, swarmId: id });
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
async getSwarm(id: string): Promise<SwarmRecord | null> {
|
|
197
|
+
try {
|
|
198
|
+
const query = 'SELECT * FROM swarms WHERE id = ?';
|
|
199
|
+
const rows = await this.query(query, [id]);
|
|
200
|
+
|
|
201
|
+
if (rows.length === 0) {
|
|
202
|
+
return null;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
return this.mapSwarmRow(rows[0]);
|
|
206
|
+
} catch (error) {
|
|
207
|
+
throw new DatabaseError('Failed to get swarm', { error, swarmId: id });
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
async updateSwarm(id: string, updates: Partial<SwarmRecord>): Promise<void> {
|
|
212
|
+
try {
|
|
213
|
+
const setClause = Object.keys(updates)
|
|
214
|
+
.filter(key => key !== 'id' && key !== 'createdAt')
|
|
215
|
+
.map(key => `${this.camelToSnake(key)} = ?`)
|
|
216
|
+
.join(', ');
|
|
217
|
+
|
|
218
|
+
const values = Object.entries(updates)
|
|
219
|
+
.filter(([key]) => key !== 'id' && key !== 'createdAt')
|
|
220
|
+
.map(([key, value]) => {
|
|
221
|
+
if (key === 'config' && typeof value === 'object') {
|
|
222
|
+
return JSON.stringify(value);
|
|
223
|
+
}
|
|
224
|
+
return value;
|
|
225
|
+
});
|
|
226
|
+
|
|
227
|
+
values.push(new Date()); // updated_at
|
|
228
|
+
values.push(id);
|
|
229
|
+
|
|
230
|
+
const query = `UPDATE swarms SET ${setClause}, updated_at = ? WHERE id = ?`;
|
|
231
|
+
await this.execute(query, values);
|
|
232
|
+
} catch (error) {
|
|
233
|
+
throw new DatabaseError('Failed to update swarm', { error, swarmId: id });
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
async deleteSwarm(id: string): Promise<void> {
|
|
238
|
+
try {
|
|
239
|
+
const query = 'UPDATE swarms SET status = ?, destroyed_at = ? WHERE id = ?';
|
|
240
|
+
await this.execute(query, ['destroyed', new Date(), id]);
|
|
241
|
+
} catch (error) {
|
|
242
|
+
throw new DatabaseError('Failed to delete swarm', { error, swarmId: id });
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
async listSwarms(filter?: { status?: string }): Promise<SwarmRecord[]> {
|
|
247
|
+
try {
|
|
248
|
+
let query = 'SELECT * FROM swarms';
|
|
249
|
+
const values: any[] = [];
|
|
250
|
+
|
|
251
|
+
if (filter?.status) {
|
|
252
|
+
query += ' WHERE status = ?';
|
|
253
|
+
values.push(filter.status);
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
query += ' ORDER BY created_at DESC';
|
|
257
|
+
const rows = await this.query(query, values);
|
|
258
|
+
|
|
259
|
+
return rows.map(row => this.mapSwarmRow(row));
|
|
260
|
+
} catch (error) {
|
|
261
|
+
throw new DatabaseError('Failed to list swarms', { error });
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
// Agent operations
|
|
266
|
+
async createAgent(agent: Omit<AgentRecord, 'id' | 'createdAt' | 'updatedAt'>): Promise<AgentRecord> {
|
|
267
|
+
const id = `agent_${Date.now()}_${nanoid(10)}`;
|
|
268
|
+
const now = new Date();
|
|
269
|
+
|
|
270
|
+
const record: AgentRecord = {
|
|
271
|
+
id,
|
|
272
|
+
...agent,
|
|
273
|
+
createdAt: now,
|
|
274
|
+
updatedAt: now,
|
|
275
|
+
};
|
|
276
|
+
|
|
277
|
+
try {
|
|
278
|
+
const query = `
|
|
279
|
+
INSERT INTO agents (id, swarm_id, type, name, status, capabilities, config, metadata, created_at, updated_at)
|
|
280
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
281
|
+
`;
|
|
282
|
+
const values = [
|
|
283
|
+
record.id,
|
|
284
|
+
record.swarmId,
|
|
285
|
+
record.type,
|
|
286
|
+
record.name,
|
|
287
|
+
record.status,
|
|
288
|
+
JSON.stringify(record.capabilities),
|
|
289
|
+
JSON.stringify(record.config),
|
|
290
|
+
JSON.stringify(record.metadata),
|
|
291
|
+
record.createdAt,
|
|
292
|
+
record.updatedAt,
|
|
293
|
+
];
|
|
294
|
+
|
|
295
|
+
await this.execute(query, values);
|
|
296
|
+
return record;
|
|
297
|
+
} catch (error) {
|
|
298
|
+
throw new DatabaseError('Failed to create agent', { error, agentId: id });
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
async getAgentsBySwarm(swarmId: string): Promise<AgentRecord[]> {
|
|
303
|
+
try {
|
|
304
|
+
const query = 'SELECT * FROM agents WHERE swarm_id = ? AND status != ? ORDER BY created_at';
|
|
305
|
+
const rows = await this.query(query, [swarmId, 'terminated']);
|
|
306
|
+
|
|
307
|
+
return rows.map(row => this.mapAgentRow(row));
|
|
308
|
+
} catch (error) {
|
|
309
|
+
throw new DatabaseError('Failed to get agents by swarm', { error, swarmId });
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
async updateAgent(id: string, updates: Partial<AgentRecord>): Promise<void> {
|
|
314
|
+
try {
|
|
315
|
+
const setClause = Object.keys(updates)
|
|
316
|
+
.filter(key => key !== 'id' && key !== 'createdAt')
|
|
317
|
+
.map(key => `${this.camelToSnake(key)} = ?`)
|
|
318
|
+
.join(', ');
|
|
319
|
+
|
|
320
|
+
const values = Object.entries(updates)
|
|
321
|
+
.filter(([key]) => key !== 'id' && key !== 'createdAt')
|
|
322
|
+
.map(([key, value]) => {
|
|
323
|
+
if (['capabilities', 'config', 'metadata'].includes(key) && typeof value === 'object') {
|
|
324
|
+
return JSON.stringify(value);
|
|
325
|
+
}
|
|
326
|
+
return value;
|
|
327
|
+
});
|
|
328
|
+
|
|
329
|
+
values.push(new Date()); // updated_at
|
|
330
|
+
values.push(id);
|
|
331
|
+
|
|
332
|
+
const query = `UPDATE agents SET ${setClause}, updated_at = ? WHERE id = ?`;
|
|
333
|
+
await this.execute(query, values);
|
|
334
|
+
} catch (error) {
|
|
335
|
+
throw new DatabaseError('Failed to update agent', { error, agentId: id });
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
// Task operations
|
|
340
|
+
async createTask(task: Omit<TaskRecord, 'id' | 'createdAt' | 'updatedAt'>): Promise<TaskRecord> {
|
|
341
|
+
const id = `task_${Date.now()}_${nanoid(10)}`;
|
|
342
|
+
const now = new Date();
|
|
343
|
+
|
|
344
|
+
const record: TaskRecord = {
|
|
345
|
+
id,
|
|
346
|
+
...task,
|
|
347
|
+
createdAt: now,
|
|
348
|
+
updatedAt: now,
|
|
349
|
+
};
|
|
350
|
+
|
|
351
|
+
try {
|
|
352
|
+
const query = `
|
|
353
|
+
INSERT INTO tasks (id, swarm_id, description, priority, strategy, status, max_agents, requirements, metadata, created_at, updated_at)
|
|
354
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
355
|
+
`;
|
|
356
|
+
const values = [
|
|
357
|
+
record.id,
|
|
358
|
+
record.swarmId,
|
|
359
|
+
record.description,
|
|
360
|
+
record.priority,
|
|
361
|
+
record.strategy,
|
|
362
|
+
record.status,
|
|
363
|
+
record.maxAgents,
|
|
364
|
+
JSON.stringify(record.requirements),
|
|
365
|
+
JSON.stringify(record.metadata),
|
|
366
|
+
record.createdAt,
|
|
367
|
+
record.updatedAt,
|
|
368
|
+
];
|
|
369
|
+
|
|
370
|
+
await this.execute(query, values);
|
|
371
|
+
return record;
|
|
372
|
+
} catch (error) {
|
|
373
|
+
throw new DatabaseError('Failed to create task', { error, taskId: id });
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
async getTasksBySwarm(swarmId: string): Promise<TaskRecord[]> {
|
|
378
|
+
try {
|
|
379
|
+
const query = 'SELECT * FROM tasks WHERE swarm_id = ? ORDER BY created_at DESC';
|
|
380
|
+
const rows = await this.query(query, [swarmId]);
|
|
381
|
+
|
|
382
|
+
return rows.map(row => this.mapTaskRow(row));
|
|
383
|
+
} catch (error) {
|
|
384
|
+
throw new DatabaseError('Failed to get tasks by swarm', { error, swarmId });
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
async updateTask(id: string, updates: Partial<TaskRecord>): Promise<void> {
|
|
389
|
+
try {
|
|
390
|
+
const setClause = Object.keys(updates)
|
|
391
|
+
.filter(key => key !== 'id' && key !== 'createdAt')
|
|
392
|
+
.map(key => `${this.camelToSnake(key)} = ?`)
|
|
393
|
+
.join(', ');
|
|
394
|
+
|
|
395
|
+
const values = Object.entries(updates)
|
|
396
|
+
.filter(([key]) => key !== 'id' && key !== 'createdAt')
|
|
397
|
+
.map(([key, value]) => {
|
|
398
|
+
if (['requirements', 'metadata', 'result'].includes(key) && typeof value === 'object') {
|
|
399
|
+
return JSON.stringify(value);
|
|
400
|
+
}
|
|
401
|
+
return value;
|
|
402
|
+
});
|
|
403
|
+
|
|
404
|
+
values.push(new Date()); // updated_at
|
|
405
|
+
values.push(id);
|
|
406
|
+
|
|
407
|
+
const query = `UPDATE tasks SET ${setClause}, updated_at = ? WHERE id = ?`;
|
|
408
|
+
await this.execute(query, values);
|
|
409
|
+
} catch (error) {
|
|
410
|
+
throw new DatabaseError('Failed to update task', { error, taskId: id });
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
// Metrics operations
|
|
415
|
+
async recordMetric(metric: Omit<MetricRecord, 'id' | 'timestamp'>): Promise<void> {
|
|
416
|
+
const id = `metric_${Date.now()}_${nanoid(8)}`;
|
|
417
|
+
const record = {
|
|
418
|
+
id,
|
|
419
|
+
...metric,
|
|
420
|
+
timestamp: new Date(),
|
|
421
|
+
};
|
|
422
|
+
|
|
423
|
+
try {
|
|
424
|
+
const query = `
|
|
425
|
+
INSERT INTO performance_metrics (id, swarm_id, agent_id, metric_type, metric_name, metric_value, unit, timestamp, metadata)
|
|
426
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
427
|
+
`;
|
|
428
|
+
const values = [
|
|
429
|
+
record.id,
|
|
430
|
+
record.swarmId,
|
|
431
|
+
record.agentId,
|
|
432
|
+
record.metricType,
|
|
433
|
+
record.metricName,
|
|
434
|
+
record.metricValue,
|
|
435
|
+
record.unit,
|
|
436
|
+
record.timestamp,
|
|
437
|
+
JSON.stringify(record.metadata),
|
|
438
|
+
];
|
|
439
|
+
|
|
440
|
+
await this.execute(query, values);
|
|
441
|
+
} catch (error) {
|
|
442
|
+
throw new DatabaseError('Failed to record metric', { error, metricId: id });
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
async getMetrics(filter: {
|
|
447
|
+
swarmId?: string;
|
|
448
|
+
agentId?: string;
|
|
449
|
+
metricType?: string;
|
|
450
|
+
startTime?: Date;
|
|
451
|
+
endTime?: Date;
|
|
452
|
+
limit?: number;
|
|
453
|
+
}): Promise<MetricRecord[]> {
|
|
454
|
+
try {
|
|
455
|
+
let query = 'SELECT * FROM performance_metrics WHERE 1=1';
|
|
456
|
+
const values: any[] = [];
|
|
457
|
+
|
|
458
|
+
if (filter.swarmId) {
|
|
459
|
+
query += ' AND swarm_id = ?';
|
|
460
|
+
values.push(filter.swarmId);
|
|
461
|
+
}
|
|
462
|
+
if (filter.agentId) {
|
|
463
|
+
query += ' AND agent_id = ?';
|
|
464
|
+
values.push(filter.agentId);
|
|
465
|
+
}
|
|
466
|
+
if (filter.metricType) {
|
|
467
|
+
query += ' AND metric_type = ?';
|
|
468
|
+
values.push(filter.metricType);
|
|
469
|
+
}
|
|
470
|
+
if (filter.startTime) {
|
|
471
|
+
query += ' AND timestamp >= ?';
|
|
472
|
+
values.push(filter.startTime);
|
|
473
|
+
}
|
|
474
|
+
if (filter.endTime) {
|
|
475
|
+
query += ' AND timestamp <= ?';
|
|
476
|
+
values.push(filter.endTime);
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
query += ' ORDER BY timestamp DESC';
|
|
480
|
+
|
|
481
|
+
if (filter.limit) {
|
|
482
|
+
query += ' LIMIT ?';
|
|
483
|
+
values.push(filter.limit);
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
const rows = await this.query(query, values);
|
|
487
|
+
return rows.map(row => this.mapMetricRow(row));
|
|
488
|
+
} catch (error) {
|
|
489
|
+
throw new DatabaseError('Failed to get metrics', { error });
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
// Event logging
|
|
494
|
+
async recordEvent(event: Omit<EventRecord, 'id' | 'createdAt'>): Promise<void> {
|
|
495
|
+
const id = `event_${Date.now()}_${nanoid(8)}`;
|
|
496
|
+
const record = {
|
|
497
|
+
id,
|
|
498
|
+
...event,
|
|
499
|
+
createdAt: new Date(),
|
|
500
|
+
};
|
|
501
|
+
|
|
502
|
+
try {
|
|
503
|
+
const query = `
|
|
504
|
+
INSERT INTO events (id, swarm_id, agent_id, event_type, event_name, event_data, severity, created_at)
|
|
505
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
|
506
|
+
`;
|
|
507
|
+
const values = [
|
|
508
|
+
record.id,
|
|
509
|
+
record.swarmId,
|
|
510
|
+
record.agentId,
|
|
511
|
+
record.eventType,
|
|
512
|
+
record.eventName,
|
|
513
|
+
JSON.stringify(record.eventData),
|
|
514
|
+
record.severity,
|
|
515
|
+
record.createdAt,
|
|
516
|
+
];
|
|
517
|
+
|
|
518
|
+
await this.execute(query, values);
|
|
519
|
+
} catch (error) {
|
|
520
|
+
// Don't throw for event logging failures, just log the error
|
|
521
|
+
this.logger.error('Failed to record event', { error, event: record });
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
// Health check
|
|
526
|
+
async getHealthStatus(): Promise<{
|
|
527
|
+
healthy: boolean;
|
|
528
|
+
error?: string;
|
|
529
|
+
metrics?: Record<string, number>;
|
|
530
|
+
}> {
|
|
531
|
+
try {
|
|
532
|
+
const query = 'SELECT 1 as test';
|
|
533
|
+
await this.query(query);
|
|
534
|
+
|
|
535
|
+
// Get basic metrics
|
|
536
|
+
const swarmCount = await this.query('SELECT COUNT(*) as count FROM swarms WHERE status != ?', ['destroyed']);
|
|
537
|
+
const agentCount = await this.query('SELECT COUNT(*) as count FROM agents WHERE status != ?', ['terminated']);
|
|
538
|
+
const activeTaskCount = await this.query('SELECT COUNT(*) as count FROM tasks WHERE status IN (?, ?, ?)', ['pending', 'assigned', 'running']);
|
|
539
|
+
|
|
540
|
+
return {
|
|
541
|
+
healthy: true,
|
|
542
|
+
metrics: {
|
|
543
|
+
totalSwarms: swarmCount[0]?.count || 0,
|
|
544
|
+
totalAgents: agentCount[0]?.count || 0,
|
|
545
|
+
activeTasks: activeTaskCount[0]?.count || 0,
|
|
546
|
+
},
|
|
547
|
+
};
|
|
548
|
+
} catch (error) {
|
|
549
|
+
return {
|
|
550
|
+
healthy: false,
|
|
551
|
+
error: error instanceof Error ? error.message : 'Unknown database error',
|
|
552
|
+
};
|
|
553
|
+
}
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
// Private helper methods
|
|
557
|
+
private async initializeSQLite(): Promise<void> {
|
|
558
|
+
try {
|
|
559
|
+
// Import better-sqlite3 dynamically
|
|
560
|
+
const Database = (await import('better-sqlite3')).default;
|
|
561
|
+
this.db = new Database(this.config.database);
|
|
562
|
+
|
|
563
|
+
// Enable WAL mode for better concurrency
|
|
564
|
+
this.db.pragma('journal_mode = WAL');
|
|
565
|
+
this.db.pragma('synchronous = NORMAL');
|
|
566
|
+
this.db.pragma('cache_size = 1000');
|
|
567
|
+
this.db.pragma('temp_store = memory');
|
|
568
|
+
} catch (error) {
|
|
569
|
+
throw new DatabaseError('Failed to initialize SQLite', { error });
|
|
570
|
+
}
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
private async initializeMySQL(): Promise<void> {
|
|
574
|
+
// MySQL initialization would go here
|
|
575
|
+
throw new DatabaseError('MySQL support not implemented yet');
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
private async initializePostgreSQL(): Promise<void> {
|
|
579
|
+
// PostgreSQL initialization would go here
|
|
580
|
+
throw new DatabaseError('PostgreSQL support not implemented yet');
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
private async runMigrations(): Promise<void> {
|
|
584
|
+
try {
|
|
585
|
+
// Check if migrations table exists
|
|
586
|
+
const migrationQuery = this.config.type === 'sqlite'
|
|
587
|
+
? "SELECT name FROM sqlite_master WHERE type='table' AND name='migrations'"
|
|
588
|
+
: "SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'migrations'";
|
|
589
|
+
|
|
590
|
+
const migrationTable = await this.query(migrationQuery);
|
|
591
|
+
|
|
592
|
+
if (migrationTable.length === 0) {
|
|
593
|
+
// Create migrations table and run initial schema
|
|
594
|
+
await this.execute(`
|
|
595
|
+
CREATE TABLE migrations (
|
|
596
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
597
|
+
filename VARCHAR(255) NOT NULL,
|
|
598
|
+
executed_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
|
599
|
+
)
|
|
600
|
+
`);
|
|
601
|
+
|
|
602
|
+
// Run schema creation (simplified for demo)
|
|
603
|
+
await this.createTables();
|
|
604
|
+
|
|
605
|
+
await this.execute(
|
|
606
|
+
"INSERT INTO migrations (filename) VALUES (?)",
|
|
607
|
+
['001_initial_schema.sql']
|
|
608
|
+
);
|
|
609
|
+
}
|
|
610
|
+
} catch (error) {
|
|
611
|
+
throw new DatabaseError('Failed to run migrations', { error });
|
|
612
|
+
}
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
private async createTables(): Promise<void> {
|
|
616
|
+
const tables = [
|
|
617
|
+
// Swarms table
|
|
618
|
+
`CREATE TABLE IF NOT EXISTS swarms (
|
|
619
|
+
id TEXT PRIMARY KEY,
|
|
620
|
+
name TEXT NOT NULL,
|
|
621
|
+
topology TEXT NOT NULL,
|
|
622
|
+
max_agents INTEGER DEFAULT 8,
|
|
623
|
+
strategy TEXT DEFAULT 'balanced',
|
|
624
|
+
status TEXT DEFAULT 'initializing',
|
|
625
|
+
config TEXT,
|
|
626
|
+
created_at TEXT DEFAULT CURRENT_TIMESTAMP,
|
|
627
|
+
updated_at TEXT DEFAULT CURRENT_TIMESTAMP,
|
|
628
|
+
destroyed_at TEXT
|
|
629
|
+
)`,
|
|
630
|
+
|
|
631
|
+
// Agents table
|
|
632
|
+
`CREATE TABLE IF NOT EXISTS agents (
|
|
633
|
+
id TEXT PRIMARY KEY,
|
|
634
|
+
swarm_id TEXT NOT NULL,
|
|
635
|
+
type TEXT NOT NULL,
|
|
636
|
+
name TEXT,
|
|
637
|
+
status TEXT DEFAULT 'spawning',
|
|
638
|
+
capabilities TEXT,
|
|
639
|
+
config TEXT,
|
|
640
|
+
metadata TEXT,
|
|
641
|
+
created_at TEXT DEFAULT CURRENT_TIMESTAMP,
|
|
642
|
+
updated_at TEXT DEFAULT CURRENT_TIMESTAMP,
|
|
643
|
+
terminated_at TEXT,
|
|
644
|
+
FOREIGN KEY (swarm_id) REFERENCES swarms(id)
|
|
645
|
+
)`,
|
|
646
|
+
|
|
647
|
+
// Tasks table
|
|
648
|
+
`CREATE TABLE IF NOT EXISTS tasks (
|
|
649
|
+
id TEXT PRIMARY KEY,
|
|
650
|
+
swarm_id TEXT NOT NULL,
|
|
651
|
+
description TEXT NOT NULL,
|
|
652
|
+
priority TEXT DEFAULT 'medium',
|
|
653
|
+
strategy TEXT DEFAULT 'adaptive',
|
|
654
|
+
status TEXT DEFAULT 'pending',
|
|
655
|
+
max_agents INTEGER,
|
|
656
|
+
requirements TEXT,
|
|
657
|
+
metadata TEXT,
|
|
658
|
+
result TEXT,
|
|
659
|
+
error_message TEXT,
|
|
660
|
+
assigned_to TEXT,
|
|
661
|
+
created_at TEXT DEFAULT CURRENT_TIMESTAMP,
|
|
662
|
+
updated_at TEXT DEFAULT CURRENT_TIMESTAMP,
|
|
663
|
+
started_at TEXT,
|
|
664
|
+
completed_at TEXT,
|
|
665
|
+
FOREIGN KEY (swarm_id) REFERENCES swarms(id)
|
|
666
|
+
)`,
|
|
667
|
+
|
|
668
|
+
// Performance metrics table
|
|
669
|
+
`CREATE TABLE IF NOT EXISTS performance_metrics (
|
|
670
|
+
id TEXT PRIMARY KEY,
|
|
671
|
+
swarm_id TEXT,
|
|
672
|
+
agent_id TEXT,
|
|
673
|
+
metric_type TEXT NOT NULL,
|
|
674
|
+
metric_name TEXT NOT NULL,
|
|
675
|
+
metric_value REAL NOT NULL,
|
|
676
|
+
unit TEXT,
|
|
677
|
+
timestamp TEXT DEFAULT CURRENT_TIMESTAMP,
|
|
678
|
+
metadata TEXT
|
|
679
|
+
)`,
|
|
680
|
+
|
|
681
|
+
// Events table
|
|
682
|
+
`CREATE TABLE IF NOT EXISTS events (
|
|
683
|
+
id TEXT PRIMARY KEY,
|
|
684
|
+
swarm_id TEXT,
|
|
685
|
+
agent_id TEXT,
|
|
686
|
+
event_type TEXT NOT NULL,
|
|
687
|
+
event_name TEXT NOT NULL,
|
|
688
|
+
event_data TEXT,
|
|
689
|
+
severity TEXT DEFAULT 'info',
|
|
690
|
+
created_at TEXT DEFAULT CURRENT_TIMESTAMP
|
|
691
|
+
)`,
|
|
692
|
+
];
|
|
693
|
+
|
|
694
|
+
for (const table of tables) {
|
|
695
|
+
await this.execute(table);
|
|
696
|
+
}
|
|
697
|
+
}
|
|
698
|
+
|
|
699
|
+
private async query(sql: string, params: any[] = []): Promise<any[]> {
|
|
700
|
+
if (this.config.type === 'sqlite') {
|
|
701
|
+
const stmt = this.db.prepare(sql);
|
|
702
|
+
return stmt.all(...params);
|
|
703
|
+
}
|
|
704
|
+
|
|
705
|
+
// Other database types would be handled here
|
|
706
|
+
throw new DatabaseError('Unsupported database operation');
|
|
707
|
+
}
|
|
708
|
+
|
|
709
|
+
private async execute(sql: string, params: any[] = []): Promise<any> {
|
|
710
|
+
if (this.config.type === 'sqlite') {
|
|
711
|
+
const stmt = this.db.prepare(sql);
|
|
712
|
+
return stmt.run(...params);
|
|
713
|
+
}
|
|
714
|
+
|
|
715
|
+
// Other database types would be handled here
|
|
716
|
+
throw new DatabaseError('Unsupported database operation');
|
|
717
|
+
}
|
|
718
|
+
|
|
719
|
+
private camelToSnake(str: string): string {
|
|
720
|
+
return str.replace(/[A-Z]/g, letter => `_${letter.toLowerCase()}`);
|
|
721
|
+
}
|
|
722
|
+
|
|
723
|
+
private mapSwarmRow(row: any): SwarmRecord {
|
|
724
|
+
return {
|
|
725
|
+
id: row.id,
|
|
726
|
+
name: row.name,
|
|
727
|
+
topology: row.topology,
|
|
728
|
+
maxAgents: row.max_agents,
|
|
729
|
+
strategy: row.strategy,
|
|
730
|
+
status: row.status,
|
|
731
|
+
config: row.config ? JSON.parse(row.config) : undefined,
|
|
732
|
+
createdAt: new Date(row.created_at),
|
|
733
|
+
updatedAt: new Date(row.updated_at),
|
|
734
|
+
destroyedAt: row.destroyed_at ? new Date(row.destroyed_at) : undefined,
|
|
735
|
+
};
|
|
736
|
+
}
|
|
737
|
+
|
|
738
|
+
private mapAgentRow(row: any): AgentRecord {
|
|
739
|
+
return {
|
|
740
|
+
id: row.id,
|
|
741
|
+
swarmId: row.swarm_id,
|
|
742
|
+
type: row.type,
|
|
743
|
+
name: row.name,
|
|
744
|
+
status: row.status,
|
|
745
|
+
capabilities: row.capabilities ? JSON.parse(row.capabilities) : undefined,
|
|
746
|
+
config: row.config ? JSON.parse(row.config) : undefined,
|
|
747
|
+
metadata: row.metadata ? JSON.parse(row.metadata) : undefined,
|
|
748
|
+
createdAt: new Date(row.created_at),
|
|
749
|
+
updatedAt: new Date(row.updated_at),
|
|
750
|
+
terminatedAt: row.terminated_at ? new Date(row.terminated_at) : undefined,
|
|
751
|
+
};
|
|
752
|
+
}
|
|
753
|
+
|
|
754
|
+
private mapTaskRow(row: any): TaskRecord {
|
|
755
|
+
return {
|
|
756
|
+
id: row.id,
|
|
757
|
+
swarmId: row.swarm_id,
|
|
758
|
+
description: row.description,
|
|
759
|
+
priority: row.priority,
|
|
760
|
+
strategy: row.strategy,
|
|
761
|
+
status: row.status,
|
|
762
|
+
maxAgents: row.max_agents,
|
|
763
|
+
requirements: row.requirements ? JSON.parse(row.requirements) : undefined,
|
|
764
|
+
metadata: row.metadata ? JSON.parse(row.metadata) : undefined,
|
|
765
|
+
result: row.result ? JSON.parse(row.result) : undefined,
|
|
766
|
+
errorMessage: row.error_message,
|
|
767
|
+
assignedTo: row.assigned_to,
|
|
768
|
+
createdAt: new Date(row.created_at),
|
|
769
|
+
updatedAt: new Date(row.updated_at),
|
|
770
|
+
startedAt: row.started_at ? new Date(row.started_at) : undefined,
|
|
771
|
+
completedAt: row.completed_at ? new Date(row.completed_at) : undefined,
|
|
772
|
+
};
|
|
773
|
+
}
|
|
774
|
+
|
|
775
|
+
private mapMetricRow(row: any): MetricRecord {
|
|
776
|
+
return {
|
|
777
|
+
id: row.id,
|
|
778
|
+
swarmId: row.swarm_id,
|
|
779
|
+
agentId: row.agent_id,
|
|
780
|
+
metricType: row.metric_type,
|
|
781
|
+
metricName: row.metric_name,
|
|
782
|
+
metricValue: row.metric_value,
|
|
783
|
+
unit: row.unit,
|
|
784
|
+
timestamp: new Date(row.timestamp),
|
|
785
|
+
metadata: row.metadata ? JSON.parse(row.metadata) : undefined,
|
|
786
|
+
};
|
|
787
|
+
}
|
|
788
|
+
}
|