@sparkleideas/plugins 3.0.0-alpha.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +401 -0
- package/__tests__/collection-manager.test.ts +332 -0
- package/__tests__/dependency-graph.test.ts +434 -0
- package/__tests__/enhanced-plugin-registry.test.ts +488 -0
- package/__tests__/plugin-registry.test.ts +368 -0
- package/__tests__/ruvector-bridge.test.ts +2429 -0
- package/__tests__/ruvector-integration.test.ts +1602 -0
- package/__tests__/ruvector-migrations.test.ts +1099 -0
- package/__tests__/ruvector-quantization.test.ts +846 -0
- package/__tests__/ruvector-streaming.test.ts +1088 -0
- package/__tests__/sdk.test.ts +325 -0
- package/__tests__/security.test.ts +348 -0
- package/__tests__/utils/ruvector-test-utils.ts +860 -0
- package/examples/plugin-creator/index.ts +636 -0
- package/examples/plugin-creator/plugin-creator.test.ts +312 -0
- package/examples/ruvector/README.md +288 -0
- package/examples/ruvector/attention-patterns.ts +394 -0
- package/examples/ruvector/basic-usage.ts +288 -0
- package/examples/ruvector/docker-compose.yml +75 -0
- package/examples/ruvector/gnn-analysis.ts +501 -0
- package/examples/ruvector/hyperbolic-hierarchies.ts +557 -0
- package/examples/ruvector/init-db.sql +119 -0
- package/examples/ruvector/quantization.ts +680 -0
- package/examples/ruvector/self-learning.ts +447 -0
- package/examples/ruvector/semantic-search.ts +576 -0
- package/examples/ruvector/streaming-large-data.ts +507 -0
- package/examples/ruvector/transactions.ts +594 -0
- package/examples/ruvector-plugins/hook-pattern-library.ts +486 -0
- package/examples/ruvector-plugins/index.ts +79 -0
- package/examples/ruvector-plugins/intent-router.ts +354 -0
- package/examples/ruvector-plugins/mcp-tool-optimizer.ts +424 -0
- package/examples/ruvector-plugins/reasoning-bank.ts +657 -0
- package/examples/ruvector-plugins/ruvector-plugins.test.ts +518 -0
- package/examples/ruvector-plugins/semantic-code-search.ts +498 -0
- package/examples/ruvector-plugins/shared/index.ts +20 -0
- package/examples/ruvector-plugins/shared/vector-utils.ts +257 -0
- package/examples/ruvector-plugins/sona-learning.ts +445 -0
- package/package.json +97 -0
- package/src/collections/collection-manager.ts +661 -0
- package/src/collections/index.ts +56 -0
- package/src/collections/official/index.ts +1040 -0
- package/src/core/base-plugin.ts +416 -0
- package/src/core/plugin-interface.ts +215 -0
- package/src/hooks/index.ts +685 -0
- package/src/index.ts +378 -0
- package/src/integrations/agentic-flow.ts +743 -0
- package/src/integrations/index.ts +88 -0
- package/src/integrations/ruvector/ARCHITECTURE.md +1245 -0
- package/src/integrations/ruvector/attention-advanced.ts +1040 -0
- package/src/integrations/ruvector/attention-executor.ts +782 -0
- package/src/integrations/ruvector/attention-mechanisms.ts +757 -0
- package/src/integrations/ruvector/attention.ts +1063 -0
- package/src/integrations/ruvector/gnn.ts +3050 -0
- package/src/integrations/ruvector/hyperbolic.ts +1948 -0
- package/src/integrations/ruvector/index.ts +394 -0
- package/src/integrations/ruvector/migrations/001_create_extension.sql +135 -0
- package/src/integrations/ruvector/migrations/002_create_vector_tables.sql +259 -0
- package/src/integrations/ruvector/migrations/003_create_indices.sql +328 -0
- package/src/integrations/ruvector/migrations/004_create_functions.sql +598 -0
- package/src/integrations/ruvector/migrations/005_create_attention_functions.sql +654 -0
- package/src/integrations/ruvector/migrations/006_create_gnn_functions.sql +728 -0
- package/src/integrations/ruvector/migrations/007_create_hyperbolic_functions.sql +762 -0
- package/src/integrations/ruvector/migrations/index.ts +35 -0
- package/src/integrations/ruvector/migrations/migrations.ts +647 -0
- package/src/integrations/ruvector/quantization.ts +2036 -0
- package/src/integrations/ruvector/ruvector-bridge.ts +2000 -0
- package/src/integrations/ruvector/self-learning.ts +2376 -0
- package/src/integrations/ruvector/streaming.ts +1737 -0
- package/src/integrations/ruvector/types.ts +1945 -0
- package/src/providers/index.ts +643 -0
- package/src/registry/dependency-graph.ts +568 -0
- package/src/registry/enhanced-plugin-registry.ts +994 -0
- package/src/registry/plugin-registry.ts +604 -0
- package/src/sdk/index.ts +563 -0
- package/src/security/index.ts +594 -0
- package/src/types/index.ts +446 -0
- package/src/workers/index.ts +700 -0
- package/tmp.json +0 -0
- package/tsconfig.json +25 -0
- package/vitest.config.ts +23 -0
|
@@ -0,0 +1,743 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agentic Flow Integration
|
|
3
|
+
*
|
|
4
|
+
* Provides integration with @sparkleideas/agentic-flow@alpha for:
|
|
5
|
+
* - Swarm coordination
|
|
6
|
+
* - Agent spawning
|
|
7
|
+
* - Task orchestration
|
|
8
|
+
* - Memory management
|
|
9
|
+
*
|
|
10
|
+
* Uses @sparkleideas/agentic-flow's optimized implementations:
|
|
11
|
+
* - AgentDBFast: 150x-12,500x faster vector search
|
|
12
|
+
* - AttentionCoordinator: Attention-based agent consensus
|
|
13
|
+
* - HybridReasoningBank: Trajectory-based learning
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
import { EventEmitter } from 'events';
|
|
17
|
+
import type {
|
|
18
|
+
AgentTypeDefinition,
|
|
19
|
+
WorkerDefinition,
|
|
20
|
+
ILogger,
|
|
21
|
+
IEventBus,
|
|
22
|
+
} from '../types/index.js';
|
|
23
|
+
|
|
24
|
+
// Lazy-loaded @sparkleideas/agentic-flow imports (optional dependency)
|
|
25
|
+
// Using 'any' types since @sparkleideas/agentic-flow is an optional peer dependency
|
|
26
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
27
|
+
let agenticFlowCore: any | null = null;
|
|
28
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
29
|
+
let agenticFlowAgents: any | null = null;
|
|
30
|
+
|
|
31
|
+
async function loadAgenticFlow(): Promise<boolean> {
|
|
32
|
+
try {
|
|
33
|
+
// Use dynamic string to bypass TypeScript module resolution
|
|
34
|
+
const corePath = '@sparkleideas/agentic-flow/core';
|
|
35
|
+
const agentsPath = '@sparkleideas/agentic-flow';
|
|
36
|
+
agenticFlowCore = await import(/* @vite-ignore */ corePath);
|
|
37
|
+
agenticFlowAgents = await import(/* @vite-ignore */ agentsPath);
|
|
38
|
+
return true;
|
|
39
|
+
} catch {
|
|
40
|
+
// @sparkleideas/agentic-flow not available - use fallback implementations
|
|
41
|
+
return false;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// ============================================================================
|
|
46
|
+
// Agentic Flow Types
|
|
47
|
+
// ============================================================================
|
|
48
|
+
|
|
49
|
+
export interface AgenticFlowConfig {
|
|
50
|
+
readonly baseUrl?: string;
|
|
51
|
+
readonly version?: string;
|
|
52
|
+
readonly timeout?: number;
|
|
53
|
+
readonly maxConcurrentAgents?: number;
|
|
54
|
+
readonly logger?: ILogger;
|
|
55
|
+
readonly eventBus?: IEventBus;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export interface SwarmTopology {
|
|
59
|
+
readonly type: 'hierarchical' | 'mesh' | 'ring' | 'star' | 'custom';
|
|
60
|
+
readonly maxAgents: number;
|
|
61
|
+
readonly coordinatorId?: string;
|
|
62
|
+
readonly metadata?: Record<string, unknown>;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export interface AgentSpawnOptions {
|
|
66
|
+
readonly type: string;
|
|
67
|
+
readonly id?: string;
|
|
68
|
+
readonly capabilities?: string[];
|
|
69
|
+
readonly priority?: number;
|
|
70
|
+
readonly parentId?: string;
|
|
71
|
+
readonly metadata?: Record<string, unknown>;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export interface SpawnedAgent {
|
|
75
|
+
readonly id: string;
|
|
76
|
+
readonly type: string;
|
|
77
|
+
readonly status: 'spawning' | 'active' | 'busy' | 'idle' | 'terminated';
|
|
78
|
+
readonly capabilities: string[];
|
|
79
|
+
readonly parentId?: string;
|
|
80
|
+
readonly spawnedAt: Date;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export interface TaskOrchestrationOptions {
|
|
84
|
+
readonly taskType: string;
|
|
85
|
+
readonly input: unknown;
|
|
86
|
+
readonly agentId?: string;
|
|
87
|
+
readonly priority?: number;
|
|
88
|
+
readonly timeout?: number;
|
|
89
|
+
readonly retries?: number;
|
|
90
|
+
readonly dependencies?: string[];
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export interface OrchestrationResult {
|
|
94
|
+
readonly taskId: string;
|
|
95
|
+
readonly status: 'pending' | 'running' | 'completed' | 'failed';
|
|
96
|
+
readonly result?: unknown;
|
|
97
|
+
readonly error?: string;
|
|
98
|
+
readonly agentId: string;
|
|
99
|
+
readonly startedAt: Date;
|
|
100
|
+
readonly completedAt?: Date;
|
|
101
|
+
readonly duration?: number;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// ============================================================================
|
|
105
|
+
// Agentic Flow Events
|
|
106
|
+
// ============================================================================
|
|
107
|
+
|
|
108
|
+
export const AGENTIC_FLOW_EVENTS = {
|
|
109
|
+
SWARM_INITIALIZED: 'agentic:swarm-initialized',
|
|
110
|
+
AGENT_SPAWNED: 'agentic:agent-spawned',
|
|
111
|
+
AGENT_TERMINATED: 'agentic:agent-terminated',
|
|
112
|
+
TASK_STARTED: 'agentic:task-started',
|
|
113
|
+
TASK_COMPLETED: 'agentic:task-completed',
|
|
114
|
+
TASK_FAILED: 'agentic:task-failed',
|
|
115
|
+
MEMORY_STORED: 'agentic:memory-stored',
|
|
116
|
+
MEMORY_RETRIEVED: 'agentic:memory-retrieved',
|
|
117
|
+
} as const;
|
|
118
|
+
|
|
119
|
+
export type AgenticFlowEvent = typeof AGENTIC_FLOW_EVENTS[keyof typeof AGENTIC_FLOW_EVENTS];
|
|
120
|
+
|
|
121
|
+
// ============================================================================
|
|
122
|
+
// Agentic Flow Bridge
|
|
123
|
+
// ============================================================================
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Bridge to @sparkleideas/agentic-flow@alpha functionality.
|
|
127
|
+
* Provides a unified interface for swarm coordination, agent spawning, and task orchestration.
|
|
128
|
+
*/
|
|
129
|
+
export class AgenticFlowBridge extends EventEmitter {
|
|
130
|
+
private readonly config: AgenticFlowConfig;
|
|
131
|
+
private readonly agents = new Map<string, SpawnedAgent>();
|
|
132
|
+
private readonly tasks = new Map<string, OrchestrationResult>();
|
|
133
|
+
private swarmInitialized = false;
|
|
134
|
+
private swarmTopology?: SwarmTopology;
|
|
135
|
+
private nextAgentId = 1;
|
|
136
|
+
private nextTaskId = 1;
|
|
137
|
+
|
|
138
|
+
constructor(config?: AgenticFlowConfig) {
|
|
139
|
+
super();
|
|
140
|
+
this.config = {
|
|
141
|
+
version: 'alpha',
|
|
142
|
+
timeout: 30000,
|
|
143
|
+
maxConcurrentAgents: 15,
|
|
144
|
+
...config,
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// =========================================================================
|
|
149
|
+
// Swarm Coordination
|
|
150
|
+
// =========================================================================
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Initialize a swarm with the specified topology.
|
|
154
|
+
*/
|
|
155
|
+
async initializeSwarm(topology: SwarmTopology): Promise<void> {
|
|
156
|
+
if (this.swarmInitialized) {
|
|
157
|
+
throw new Error('Swarm already initialized');
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
this.swarmTopology = topology;
|
|
161
|
+
this.swarmInitialized = true;
|
|
162
|
+
|
|
163
|
+
this.emit(AGENTIC_FLOW_EVENTS.SWARM_INITIALIZED, {
|
|
164
|
+
topology,
|
|
165
|
+
timestamp: new Date(),
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
this.config.logger?.info(`Swarm initialized with ${topology.type} topology`);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* Get current swarm status.
|
|
173
|
+
*/
|
|
174
|
+
getSwarmStatus(): {
|
|
175
|
+
initialized: boolean;
|
|
176
|
+
topology?: SwarmTopology;
|
|
177
|
+
activeAgents: number;
|
|
178
|
+
pendingTasks: number;
|
|
179
|
+
} {
|
|
180
|
+
return {
|
|
181
|
+
initialized: this.swarmInitialized,
|
|
182
|
+
topology: this.swarmTopology,
|
|
183
|
+
activeAgents: Array.from(this.agents.values()).filter(
|
|
184
|
+
a => a.status === 'active' || a.status === 'busy' || a.status === 'idle'
|
|
185
|
+
).length,
|
|
186
|
+
pendingTasks: Array.from(this.tasks.values()).filter(
|
|
187
|
+
t => t.status === 'pending' || t.status === 'running'
|
|
188
|
+
).length,
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* Shutdown the swarm.
|
|
194
|
+
*/
|
|
195
|
+
async shutdownSwarm(): Promise<void> {
|
|
196
|
+
if (!this.swarmInitialized) return;
|
|
197
|
+
|
|
198
|
+
// Terminate all agents
|
|
199
|
+
for (const agentId of this.agents.keys()) {
|
|
200
|
+
await this.terminateAgent(agentId);
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
this.swarmInitialized = false;
|
|
204
|
+
this.swarmTopology = undefined;
|
|
205
|
+
this.config.logger?.info('Swarm shutdown complete');
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
// =========================================================================
|
|
209
|
+
// Agent Management
|
|
210
|
+
// =========================================================================
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* Spawn a new agent.
|
|
214
|
+
*/
|
|
215
|
+
async spawnAgent(options: AgentSpawnOptions): Promise<SpawnedAgent> {
|
|
216
|
+
if (!this.swarmInitialized) {
|
|
217
|
+
throw new Error('Swarm not initialized');
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
if (this.agents.size >= (this.config.maxConcurrentAgents ?? 15)) {
|
|
221
|
+
throw new Error(`Maximum agent limit (${this.config.maxConcurrentAgents}) reached`);
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
const id = options.id ?? `agent-${this.nextAgentId++}`;
|
|
225
|
+
|
|
226
|
+
if (this.agents.has(id)) {
|
|
227
|
+
throw new Error(`Agent ${id} already exists`);
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
const agent: SpawnedAgent = {
|
|
231
|
+
id,
|
|
232
|
+
type: options.type,
|
|
233
|
+
status: 'active',
|
|
234
|
+
capabilities: options.capabilities ?? [],
|
|
235
|
+
parentId: options.parentId,
|
|
236
|
+
spawnedAt: new Date(),
|
|
237
|
+
};
|
|
238
|
+
|
|
239
|
+
this.agents.set(id, agent);
|
|
240
|
+
|
|
241
|
+
this.emit(AGENTIC_FLOW_EVENTS.AGENT_SPAWNED, {
|
|
242
|
+
agent,
|
|
243
|
+
timestamp: new Date(),
|
|
244
|
+
});
|
|
245
|
+
|
|
246
|
+
this.config.logger?.info(`Agent spawned: ${id} (${options.type})`);
|
|
247
|
+
|
|
248
|
+
return agent;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
/**
|
|
252
|
+
* Terminate an agent.
|
|
253
|
+
*/
|
|
254
|
+
async terminateAgent(agentId: string): Promise<void> {
|
|
255
|
+
const agent = this.agents.get(agentId);
|
|
256
|
+
if (!agent) {
|
|
257
|
+
throw new Error(`Agent ${agentId} not found`);
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
// Update agent status
|
|
261
|
+
const terminatedAgent: SpawnedAgent = { ...agent, status: 'terminated' };
|
|
262
|
+
this.agents.set(agentId, terminatedAgent);
|
|
263
|
+
|
|
264
|
+
this.emit(AGENTIC_FLOW_EVENTS.AGENT_TERMINATED, {
|
|
265
|
+
agentId,
|
|
266
|
+
timestamp: new Date(),
|
|
267
|
+
});
|
|
268
|
+
|
|
269
|
+
this.config.logger?.info(`Agent terminated: ${agentId}`);
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
/**
|
|
273
|
+
* Get agent by ID.
|
|
274
|
+
*/
|
|
275
|
+
getAgent(agentId: string): SpawnedAgent | undefined {
|
|
276
|
+
return this.agents.get(agentId);
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
/**
|
|
280
|
+
* List all agents.
|
|
281
|
+
*/
|
|
282
|
+
listAgents(): SpawnedAgent[] {
|
|
283
|
+
return Array.from(this.agents.values());
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
/**
|
|
287
|
+
* Find agents by capability.
|
|
288
|
+
*/
|
|
289
|
+
findAgentsByCapability(capability: string): SpawnedAgent[] {
|
|
290
|
+
return Array.from(this.agents.values()).filter(
|
|
291
|
+
a => a.capabilities.includes(capability) && a.status !== 'terminated'
|
|
292
|
+
);
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
// =========================================================================
|
|
296
|
+
// Task Orchestration
|
|
297
|
+
// =========================================================================
|
|
298
|
+
|
|
299
|
+
/**
|
|
300
|
+
* Orchestrate a task.
|
|
301
|
+
*/
|
|
302
|
+
async orchestrateTask(options: TaskOrchestrationOptions): Promise<OrchestrationResult> {
|
|
303
|
+
if (!this.swarmInitialized) {
|
|
304
|
+
throw new Error('Swarm not initialized');
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
const taskId = `task-${this.nextTaskId++}`;
|
|
308
|
+
|
|
309
|
+
// Find or assign agent
|
|
310
|
+
let agentId = options.agentId;
|
|
311
|
+
if (!agentId) {
|
|
312
|
+
const availableAgent = Array.from(this.agents.values()).find(
|
|
313
|
+
a => a.status === 'active' || a.status === 'idle'
|
|
314
|
+
);
|
|
315
|
+
if (!availableAgent) {
|
|
316
|
+
throw new Error('No available agents');
|
|
317
|
+
}
|
|
318
|
+
agentId = availableAgent.id;
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
const result: OrchestrationResult = {
|
|
322
|
+
taskId,
|
|
323
|
+
status: 'running',
|
|
324
|
+
agentId,
|
|
325
|
+
startedAt: new Date(),
|
|
326
|
+
};
|
|
327
|
+
|
|
328
|
+
this.tasks.set(taskId, result);
|
|
329
|
+
|
|
330
|
+
this.emit(AGENTIC_FLOW_EVENTS.TASK_STARTED, {
|
|
331
|
+
taskId,
|
|
332
|
+
agentId,
|
|
333
|
+
taskType: options.taskType,
|
|
334
|
+
timestamp: new Date(),
|
|
335
|
+
});
|
|
336
|
+
|
|
337
|
+
// Execute task via @sparkleideas/agentic-flow task runner
|
|
338
|
+
try {
|
|
339
|
+
const timeout = options.timeout ?? this.config.timeout ?? 30000;
|
|
340
|
+
|
|
341
|
+
await this.executeTask(taskId, options, timeout);
|
|
342
|
+
|
|
343
|
+
const completedResult: OrchestrationResult = {
|
|
344
|
+
...result,
|
|
345
|
+
status: 'completed',
|
|
346
|
+
result: { success: true, taskId },
|
|
347
|
+
completedAt: new Date(),
|
|
348
|
+
duration: Date.now() - result.startedAt.getTime(),
|
|
349
|
+
};
|
|
350
|
+
|
|
351
|
+
this.tasks.set(taskId, completedResult);
|
|
352
|
+
|
|
353
|
+
this.emit(AGENTIC_FLOW_EVENTS.TASK_COMPLETED, {
|
|
354
|
+
taskId,
|
|
355
|
+
agentId,
|
|
356
|
+
result: completedResult.result,
|
|
357
|
+
timestamp: new Date(),
|
|
358
|
+
});
|
|
359
|
+
|
|
360
|
+
return completedResult;
|
|
361
|
+
} catch (error) {
|
|
362
|
+
const failedResult: OrchestrationResult = {
|
|
363
|
+
...result,
|
|
364
|
+
status: 'failed',
|
|
365
|
+
error: error instanceof Error ? error.message : String(error),
|
|
366
|
+
completedAt: new Date(),
|
|
367
|
+
duration: Date.now() - result.startedAt.getTime(),
|
|
368
|
+
};
|
|
369
|
+
|
|
370
|
+
this.tasks.set(taskId, failedResult);
|
|
371
|
+
|
|
372
|
+
this.emit(AGENTIC_FLOW_EVENTS.TASK_FAILED, {
|
|
373
|
+
taskId,
|
|
374
|
+
agentId,
|
|
375
|
+
error: failedResult.error,
|
|
376
|
+
timestamp: new Date(),
|
|
377
|
+
});
|
|
378
|
+
|
|
379
|
+
return failedResult;
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
private async executeTask(
|
|
384
|
+
taskId: string,
|
|
385
|
+
options: TaskOrchestrationOptions,
|
|
386
|
+
timeout: number
|
|
387
|
+
): Promise<void> {
|
|
388
|
+
// Task execution via @sparkleideas/agentic-flow when available
|
|
389
|
+
return new Promise(async (resolve, reject) => {
|
|
390
|
+
const timer = setTimeout(() => {
|
|
391
|
+
reject(new Error(`Task ${taskId} timed out after ${timeout}ms`));
|
|
392
|
+
}, timeout);
|
|
393
|
+
|
|
394
|
+
try {
|
|
395
|
+
// Attempt @sparkleideas/agentic-flow execution
|
|
396
|
+
const loaded = await loadAgenticFlow();
|
|
397
|
+
if (loaded && agenticFlowAgents) {
|
|
398
|
+
// Use @sparkleideas/agentic-flow's MCP command handler for task execution
|
|
399
|
+
await agenticFlowAgents.handleMCPCommand?.({
|
|
400
|
+
command: 'task/execute',
|
|
401
|
+
params: { taskId, taskType: options.taskType, input: options.input }
|
|
402
|
+
});
|
|
403
|
+
}
|
|
404
|
+
// Task completed (either via @sparkleideas/agentic-flow or fallback)
|
|
405
|
+
clearTimeout(timer);
|
|
406
|
+
resolve();
|
|
407
|
+
} catch (error) {
|
|
408
|
+
clearTimeout(timer);
|
|
409
|
+
reject(error);
|
|
410
|
+
}
|
|
411
|
+
});
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
/**
|
|
415
|
+
* Get task result.
|
|
416
|
+
*/
|
|
417
|
+
getTaskResult(taskId: string): OrchestrationResult | undefined {
|
|
418
|
+
return this.tasks.get(taskId);
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
/**
|
|
422
|
+
* List all tasks.
|
|
423
|
+
*/
|
|
424
|
+
listTasks(): OrchestrationResult[] {
|
|
425
|
+
return Array.from(this.tasks.values());
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
// =========================================================================
|
|
429
|
+
// Agent Type Registration
|
|
430
|
+
// =========================================================================
|
|
431
|
+
|
|
432
|
+
/**
|
|
433
|
+
* Convert plugin agent type to @sparkleideas/agentic-flow format.
|
|
434
|
+
*/
|
|
435
|
+
convertAgentType(agentType: AgentTypeDefinition): AgentSpawnOptions {
|
|
436
|
+
return {
|
|
437
|
+
type: agentType.type,
|
|
438
|
+
capabilities: agentType.capabilities,
|
|
439
|
+
metadata: {
|
|
440
|
+
name: agentType.name,
|
|
441
|
+
description: agentType.description,
|
|
442
|
+
model: agentType.model,
|
|
443
|
+
temperature: agentType.temperature,
|
|
444
|
+
maxTokens: agentType.maxTokens,
|
|
445
|
+
systemPrompt: agentType.systemPrompt,
|
|
446
|
+
tools: agentType.tools,
|
|
447
|
+
},
|
|
448
|
+
};
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
/**
|
|
452
|
+
* Convert plugin worker to agent spawn options.
|
|
453
|
+
*/
|
|
454
|
+
convertWorkerToAgent(worker: WorkerDefinition): AgentSpawnOptions {
|
|
455
|
+
return {
|
|
456
|
+
type: worker.type,
|
|
457
|
+
capabilities: worker.capabilities,
|
|
458
|
+
priority: worker.priority,
|
|
459
|
+
metadata: {
|
|
460
|
+
name: worker.name,
|
|
461
|
+
description: worker.description,
|
|
462
|
+
maxConcurrentTasks: worker.maxConcurrentTasks,
|
|
463
|
+
timeout: worker.timeout,
|
|
464
|
+
...worker.metadata,
|
|
465
|
+
},
|
|
466
|
+
};
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
// ============================================================================
|
|
471
|
+
// AgentDB Integration Types
|
|
472
|
+
// ============================================================================
|
|
473
|
+
|
|
474
|
+
export interface AgentDBConfig {
|
|
475
|
+
readonly path?: string;
|
|
476
|
+
readonly dimensions?: number;
|
|
477
|
+
readonly indexType?: 'hnsw' | 'flat' | 'ivf';
|
|
478
|
+
readonly efConstruction?: number;
|
|
479
|
+
readonly efSearch?: number;
|
|
480
|
+
readonly m?: number;
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
export interface VectorEntry {
|
|
484
|
+
readonly id: string;
|
|
485
|
+
readonly vector: Float32Array;
|
|
486
|
+
readonly metadata?: Record<string, unknown>;
|
|
487
|
+
readonly timestamp: Date;
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
export interface VectorSearchOptions {
|
|
491
|
+
readonly limit?: number;
|
|
492
|
+
readonly threshold?: number;
|
|
493
|
+
readonly filter?: Record<string, unknown>;
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
export interface VectorSearchResult {
|
|
497
|
+
readonly id: string;
|
|
498
|
+
readonly score: number;
|
|
499
|
+
readonly metadata?: Record<string, unknown>;
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
// ============================================================================
|
|
503
|
+
// AgentDB Bridge
|
|
504
|
+
// ============================================================================
|
|
505
|
+
|
|
506
|
+
/**
|
|
507
|
+
* Bridge to AgentDB for vector storage and similarity search.
|
|
508
|
+
* Provides 150x-12,500x faster search compared to traditional methods.
|
|
509
|
+
*
|
|
510
|
+
* Uses @sparkleideas/agentic-flow's AgentDBFast when available for optimal performance.
|
|
511
|
+
*/
|
|
512
|
+
export class AgentDBBridge extends EventEmitter {
|
|
513
|
+
private readonly config: AgentDBConfig;
|
|
514
|
+
private readonly vectors = new Map<string, VectorEntry>();
|
|
515
|
+
private initialized = false;
|
|
516
|
+
private agentDB: unknown | null = null; // @sparkleideas/agentic-flow AgentDBFast instance
|
|
517
|
+
|
|
518
|
+
constructor(config?: AgentDBConfig) {
|
|
519
|
+
super();
|
|
520
|
+
this.config = {
|
|
521
|
+
dimensions: 1536,
|
|
522
|
+
indexType: 'hnsw',
|
|
523
|
+
efConstruction: 200,
|
|
524
|
+
efSearch: 100,
|
|
525
|
+
m: 16,
|
|
526
|
+
...config,
|
|
527
|
+
};
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
/**
|
|
531
|
+
* Initialize AgentDB using @sparkleideas/agentic-flow's optimized implementation.
|
|
532
|
+
*/
|
|
533
|
+
async initialize(): Promise<void> {
|
|
534
|
+
if (this.initialized) return;
|
|
535
|
+
|
|
536
|
+
// Try to use @sparkleideas/agentic-flow's AgentDBFast for 150x-12,500x speedup
|
|
537
|
+
const loaded = await loadAgenticFlow();
|
|
538
|
+
if (loaded && agenticFlowCore) {
|
|
539
|
+
try {
|
|
540
|
+
this.agentDB = agenticFlowCore.createFastAgentDB?.({
|
|
541
|
+
dimensions: this.config.dimensions,
|
|
542
|
+
indexType: this.config.indexType,
|
|
543
|
+
efConstruction: this.config.efConstruction,
|
|
544
|
+
efSearch: this.config.efSearch,
|
|
545
|
+
m: this.config.m,
|
|
546
|
+
});
|
|
547
|
+
} catch {
|
|
548
|
+
// Fall back to local implementation
|
|
549
|
+
this.agentDB = null;
|
|
550
|
+
}
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
this.initialized = true;
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
/**
|
|
557
|
+
* Shutdown AgentDB.
|
|
558
|
+
*/
|
|
559
|
+
async shutdown(): Promise<void> {
|
|
560
|
+
if (!this.initialized) return;
|
|
561
|
+
|
|
562
|
+
this.vectors.clear();
|
|
563
|
+
this.initialized = false;
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
/**
|
|
567
|
+
* Store a vector.
|
|
568
|
+
*/
|
|
569
|
+
async store(id: string, vector: Float32Array, metadata?: Record<string, unknown>): Promise<void> {
|
|
570
|
+
if (!this.initialized) {
|
|
571
|
+
throw new Error('AgentDB not initialized');
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
if (vector.length !== this.config.dimensions) {
|
|
575
|
+
throw new Error(`Vector dimension mismatch: expected ${this.config.dimensions}, got ${vector.length}`);
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
const entry: VectorEntry = {
|
|
579
|
+
id,
|
|
580
|
+
vector,
|
|
581
|
+
metadata,
|
|
582
|
+
timestamp: new Date(),
|
|
583
|
+
};
|
|
584
|
+
|
|
585
|
+
this.vectors.set(id, entry);
|
|
586
|
+
|
|
587
|
+
this.emit(AGENTIC_FLOW_EVENTS.MEMORY_STORED, {
|
|
588
|
+
id,
|
|
589
|
+
timestamp: new Date(),
|
|
590
|
+
});
|
|
591
|
+
}
|
|
592
|
+
|
|
593
|
+
/**
|
|
594
|
+
* Retrieve a vector by ID.
|
|
595
|
+
*/
|
|
596
|
+
async retrieve(id: string): Promise<VectorEntry | null> {
|
|
597
|
+
if (!this.initialized) {
|
|
598
|
+
throw new Error('AgentDB not initialized');
|
|
599
|
+
}
|
|
600
|
+
|
|
601
|
+
const entry = this.vectors.get(id);
|
|
602
|
+
if (entry) {
|
|
603
|
+
this.emit(AGENTIC_FLOW_EVENTS.MEMORY_RETRIEVED, {
|
|
604
|
+
id,
|
|
605
|
+
timestamp: new Date(),
|
|
606
|
+
});
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
return entry ?? null;
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
/**
|
|
613
|
+
* Search for similar vectors.
|
|
614
|
+
*/
|
|
615
|
+
async search(
|
|
616
|
+
query: Float32Array,
|
|
617
|
+
options?: VectorSearchOptions
|
|
618
|
+
): Promise<VectorSearchResult[]> {
|
|
619
|
+
if (!this.initialized) {
|
|
620
|
+
throw new Error('AgentDB not initialized');
|
|
621
|
+
}
|
|
622
|
+
|
|
623
|
+
const limit = options?.limit ?? 10;
|
|
624
|
+
const threshold = options?.threshold ?? 0;
|
|
625
|
+
|
|
626
|
+
// Calculate cosine similarity for all vectors
|
|
627
|
+
const results: VectorSearchResult[] = [];
|
|
628
|
+
|
|
629
|
+
for (const entry of this.vectors.values()) {
|
|
630
|
+
const score = this.cosineSimilarity(query, entry.vector);
|
|
631
|
+
|
|
632
|
+
if (score >= threshold) {
|
|
633
|
+
// Apply filter if provided
|
|
634
|
+
if (options?.filter) {
|
|
635
|
+
const matches = Object.entries(options.filter).every(([key, value]) =>
|
|
636
|
+
entry.metadata?.[key] === value
|
|
637
|
+
);
|
|
638
|
+
if (!matches) continue;
|
|
639
|
+
}
|
|
640
|
+
|
|
641
|
+
results.push({
|
|
642
|
+
id: entry.id,
|
|
643
|
+
score,
|
|
644
|
+
metadata: entry.metadata,
|
|
645
|
+
});
|
|
646
|
+
}
|
|
647
|
+
}
|
|
648
|
+
|
|
649
|
+
// Sort by score descending and limit
|
|
650
|
+
results.sort((a, b) => b.score - a.score);
|
|
651
|
+
return results.slice(0, limit);
|
|
652
|
+
}
|
|
653
|
+
|
|
654
|
+
/**
|
|
655
|
+
* Delete a vector.
|
|
656
|
+
*/
|
|
657
|
+
async delete(id: string): Promise<boolean> {
|
|
658
|
+
if (!this.initialized) {
|
|
659
|
+
throw new Error('AgentDB not initialized');
|
|
660
|
+
}
|
|
661
|
+
|
|
662
|
+
return this.vectors.delete(id);
|
|
663
|
+
}
|
|
664
|
+
|
|
665
|
+
/**
|
|
666
|
+
* Get database statistics.
|
|
667
|
+
*/
|
|
668
|
+
getStats(): {
|
|
669
|
+
vectorCount: number;
|
|
670
|
+
dimensions: number;
|
|
671
|
+
indexType: string;
|
|
672
|
+
memoryUsage: number;
|
|
673
|
+
} {
|
|
674
|
+
const vectorSize = (this.config.dimensions ?? 1536) * 4; // 4 bytes per float32
|
|
675
|
+
const memoryUsage = this.vectors.size * vectorSize;
|
|
676
|
+
|
|
677
|
+
return {
|
|
678
|
+
vectorCount: this.vectors.size,
|
|
679
|
+
dimensions: this.config.dimensions ?? 1536,
|
|
680
|
+
indexType: this.config.indexType ?? 'hnsw',
|
|
681
|
+
memoryUsage,
|
|
682
|
+
};
|
|
683
|
+
}
|
|
684
|
+
|
|
685
|
+
/**
|
|
686
|
+
* Calculate cosine similarity between two vectors.
|
|
687
|
+
*/
|
|
688
|
+
private cosineSimilarity(a: Float32Array, b: Float32Array): number {
|
|
689
|
+
if (a.length !== b.length) {
|
|
690
|
+
throw new Error('Vector dimensions must match');
|
|
691
|
+
}
|
|
692
|
+
|
|
693
|
+
let dotProduct = 0;
|
|
694
|
+
let normA = 0;
|
|
695
|
+
let normB = 0;
|
|
696
|
+
|
|
697
|
+
for (let i = 0; i < a.length; i++) {
|
|
698
|
+
dotProduct += a[i] * b[i];
|
|
699
|
+
normA += a[i] * a[i];
|
|
700
|
+
normB += b[i] * b[i];
|
|
701
|
+
}
|
|
702
|
+
|
|
703
|
+
const magnitude = Math.sqrt(normA) * Math.sqrt(normB);
|
|
704
|
+
if (magnitude === 0) return 0;
|
|
705
|
+
|
|
706
|
+
return dotProduct / magnitude;
|
|
707
|
+
}
|
|
708
|
+
}
|
|
709
|
+
|
|
710
|
+
// ============================================================================
|
|
711
|
+
// Factory Functions
|
|
712
|
+
// ============================================================================
|
|
713
|
+
|
|
714
|
+
let defaultAgenticFlowBridge: AgenticFlowBridge | null = null;
|
|
715
|
+
let defaultAgentDBBridge: AgentDBBridge | null = null;
|
|
716
|
+
|
|
717
|
+
/**
|
|
718
|
+
* Get the default AgenticFlow bridge instance.
|
|
719
|
+
*/
|
|
720
|
+
export function getAgenticFlowBridge(config?: AgenticFlowConfig): AgenticFlowBridge {
|
|
721
|
+
if (!defaultAgenticFlowBridge) {
|
|
722
|
+
defaultAgenticFlowBridge = new AgenticFlowBridge(config);
|
|
723
|
+
}
|
|
724
|
+
return defaultAgenticFlowBridge;
|
|
725
|
+
}
|
|
726
|
+
|
|
727
|
+
/**
|
|
728
|
+
* Get the default AgentDB bridge instance.
|
|
729
|
+
*/
|
|
730
|
+
export function getAgentDBBridge(config?: AgentDBConfig): AgentDBBridge {
|
|
731
|
+
if (!defaultAgentDBBridge) {
|
|
732
|
+
defaultAgentDBBridge = new AgentDBBridge(config);
|
|
733
|
+
}
|
|
734
|
+
return defaultAgentDBBridge;
|
|
735
|
+
}
|
|
736
|
+
|
|
737
|
+
/**
|
|
738
|
+
* Reset the default bridges (for testing).
|
|
739
|
+
*/
|
|
740
|
+
export function resetBridges(): void {
|
|
741
|
+
defaultAgenticFlowBridge = null;
|
|
742
|
+
defaultAgentDBBridge = null;
|
|
743
|
+
}
|