@sparkleideas/shared 3.0.0-alpha.7
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 +323 -0
- package/__tests__/hooks/bash-safety.test.ts +289 -0
- package/__tests__/hooks/file-organization.test.ts +335 -0
- package/__tests__/hooks/git-commit.test.ts +336 -0
- package/__tests__/hooks/index.ts +23 -0
- package/__tests__/hooks/session-hooks.test.ts +357 -0
- package/__tests__/hooks/task-hooks.test.ts +193 -0
- package/docs/EVENTS_IMPLEMENTATION_SUMMARY.md +388 -0
- package/docs/EVENTS_QUICK_REFERENCE.md +470 -0
- package/docs/EVENTS_README.md +352 -0
- package/package.json +39 -0
- package/src/core/config/defaults.ts +207 -0
- package/src/core/config/index.ts +15 -0
- package/src/core/config/loader.ts +271 -0
- package/src/core/config/schema.ts +188 -0
- package/src/core/config/validator.ts +209 -0
- package/src/core/event-bus.ts +236 -0
- package/src/core/index.ts +22 -0
- package/src/core/interfaces/agent.interface.ts +251 -0
- package/src/core/interfaces/coordinator.interface.ts +363 -0
- package/src/core/interfaces/event.interface.ts +267 -0
- package/src/core/interfaces/index.ts +19 -0
- package/src/core/interfaces/memory.interface.ts +332 -0
- package/src/core/interfaces/task.interface.ts +223 -0
- package/src/core/orchestrator/event-coordinator.ts +122 -0
- package/src/core/orchestrator/health-monitor.ts +214 -0
- package/src/core/orchestrator/index.ts +89 -0
- package/src/core/orchestrator/lifecycle-manager.ts +263 -0
- package/src/core/orchestrator/session-manager.ts +279 -0
- package/src/core/orchestrator/task-manager.ts +317 -0
- package/src/events/domain-events.ts +584 -0
- package/src/events/event-store.test.ts +387 -0
- package/src/events/event-store.ts +588 -0
- package/src/events/example-usage.ts +293 -0
- package/src/events/index.ts +90 -0
- package/src/events/projections.ts +561 -0
- package/src/events/state-reconstructor.ts +349 -0
- package/src/events.ts +367 -0
- package/src/hooks/INTEGRATION.md +658 -0
- package/src/hooks/README.md +532 -0
- package/src/hooks/example-usage.ts +499 -0
- package/src/hooks/executor.ts +379 -0
- package/src/hooks/hooks.test.ts +421 -0
- package/src/hooks/index.ts +131 -0
- package/src/hooks/registry.ts +333 -0
- package/src/hooks/safety/bash-safety.ts +604 -0
- package/src/hooks/safety/file-organization.ts +473 -0
- package/src/hooks/safety/git-commit.ts +623 -0
- package/src/hooks/safety/index.ts +46 -0
- package/src/hooks/session-hooks.ts +559 -0
- package/src/hooks/task-hooks.ts +513 -0
- package/src/hooks/types.ts +357 -0
- package/src/hooks/verify-exports.test.ts +125 -0
- package/src/index.ts +195 -0
- package/src/mcp/connection-pool.ts +438 -0
- package/src/mcp/index.ts +183 -0
- package/src/mcp/server.ts +774 -0
- package/src/mcp/session-manager.ts +428 -0
- package/src/mcp/tool-registry.ts +566 -0
- package/src/mcp/transport/http.ts +557 -0
- package/src/mcp/transport/index.ts +294 -0
- package/src/mcp/transport/stdio.ts +324 -0
- package/src/mcp/transport/websocket.ts +484 -0
- package/src/mcp/types.ts +565 -0
- package/src/plugin-interface.ts +663 -0
- package/src/plugin-loader.ts +638 -0
- package/src/plugin-registry.ts +604 -0
- package/src/plugins/index.ts +34 -0
- package/src/plugins/official/hive-mind-plugin.ts +330 -0
- package/src/plugins/official/index.ts +24 -0
- package/src/plugins/official/maestro-plugin.ts +508 -0
- package/src/plugins/types.ts +108 -0
- package/src/resilience/bulkhead.ts +277 -0
- package/src/resilience/circuit-breaker.ts +326 -0
- package/src/resilience/index.ts +26 -0
- package/src/resilience/rate-limiter.ts +420 -0
- package/src/resilience/retry.ts +224 -0
- package/src/security/index.ts +39 -0
- package/src/security/input-validation.ts +265 -0
- package/src/security/secure-random.ts +159 -0
- package/src/services/index.ts +16 -0
- package/src/services/v3-progress.service.ts +505 -0
- package/src/types/agent.types.ts +144 -0
- package/src/types/index.ts +22 -0
- package/src/types/mcp.types.ts +300 -0
- package/src/types/memory.types.ts +263 -0
- package/src/types/swarm.types.ts +255 -0
- package/src/types/task.types.ts +205 -0
- package/src/types.ts +367 -0
- package/src/utils/secure-logger.d.ts +69 -0
- package/src/utils/secure-logger.d.ts.map +1 -0
- package/src/utils/secure-logger.js +208 -0
- package/src/utils/secure-logger.js.map +1 -0
- package/src/utils/secure-logger.ts +257 -0
- package/tmp.json +0 -0
- package/tsconfig.json +9 -0
|
@@ -0,0 +1,604 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* V3 Plugin Registry
|
|
3
|
+
* Domain-Driven Design - Plugin-Based Architecture (ADR-004)
|
|
4
|
+
*
|
|
5
|
+
* Central registry for tracking plugin state, metadata, and registrations
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import type {
|
|
9
|
+
ClaudeFlowPlugin,
|
|
10
|
+
PluginInfo,
|
|
11
|
+
PluginLifecycleState,
|
|
12
|
+
PluginContext,
|
|
13
|
+
AgentTypeDefinition,
|
|
14
|
+
TaskTypeDefinition,
|
|
15
|
+
MCPToolDefinition,
|
|
16
|
+
CLICommandDefinition,
|
|
17
|
+
MemoryBackendFactory,
|
|
18
|
+
} from './plugin-interface.js';
|
|
19
|
+
import { PluginError } from './plugin-interface.js';
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Plugin registry for managing plugin lifecycle and registrations
|
|
23
|
+
*/
|
|
24
|
+
export class PluginRegistry {
|
|
25
|
+
private plugins = new Map<string, PluginInfo>();
|
|
26
|
+
private agentTypes = new Map<string, { plugin: string; definition: AgentTypeDefinition }>();
|
|
27
|
+
private taskTypes = new Map<string, { plugin: string; definition: TaskTypeDefinition }>();
|
|
28
|
+
private mcpTools = new Map<string, { plugin: string; definition: MCPToolDefinition }>();
|
|
29
|
+
private cliCommands = new Map<string, { plugin: string; definition: CLICommandDefinition }>();
|
|
30
|
+
private memoryBackends = new Map<string, { plugin: string; factory: MemoryBackendFactory }>();
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Register a plugin in the registry
|
|
34
|
+
*/
|
|
35
|
+
registerPlugin(
|
|
36
|
+
plugin: ClaudeFlowPlugin,
|
|
37
|
+
initialState: PluginLifecycleState,
|
|
38
|
+
context: PluginContext
|
|
39
|
+
): void {
|
|
40
|
+
if (this.plugins.has(plugin.name)) {
|
|
41
|
+
throw new PluginError(
|
|
42
|
+
`Plugin '${plugin.name}' is already registered`,
|
|
43
|
+
plugin.name,
|
|
44
|
+
'DUPLICATE_PLUGIN'
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const info: PluginInfo = {
|
|
49
|
+
plugin,
|
|
50
|
+
state: initialState,
|
|
51
|
+
context,
|
|
52
|
+
metrics: {
|
|
53
|
+
agentTypesRegistered: 0,
|
|
54
|
+
taskTypesRegistered: 0,
|
|
55
|
+
mcpToolsRegistered: 0,
|
|
56
|
+
cliCommandsRegistered: 0,
|
|
57
|
+
memoryBackendsRegistered: 0,
|
|
58
|
+
},
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
this.plugins.set(plugin.name, info);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Unregister a plugin from the registry
|
|
66
|
+
*/
|
|
67
|
+
unregisterPlugin(pluginName: string): boolean {
|
|
68
|
+
const info = this.plugins.get(pluginName);
|
|
69
|
+
if (!info) {
|
|
70
|
+
return false;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// Unregister all plugin's registrations
|
|
74
|
+
this.unregisterPluginAgentTypes(pluginName);
|
|
75
|
+
this.unregisterPluginTaskTypes(pluginName);
|
|
76
|
+
this.unregisterPluginMCPTools(pluginName);
|
|
77
|
+
this.unregisterPluginCLICommands(pluginName);
|
|
78
|
+
this.unregisterPluginMemoryBackends(pluginName);
|
|
79
|
+
|
|
80
|
+
// Remove plugin
|
|
81
|
+
return this.plugins.delete(pluginName);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Get a plugin by name
|
|
86
|
+
*/
|
|
87
|
+
getPlugin(pluginName: string): PluginInfo | undefined {
|
|
88
|
+
return this.plugins.get(pluginName);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Get all registered plugins
|
|
93
|
+
*/
|
|
94
|
+
getAllPlugins(): Map<string, PluginInfo> {
|
|
95
|
+
return new Map(this.plugins);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Get all plugin names
|
|
100
|
+
*/
|
|
101
|
+
getPluginNames(): string[] {
|
|
102
|
+
return Array.from(this.plugins.keys());
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Check if a plugin is registered
|
|
107
|
+
*/
|
|
108
|
+
hasPlugin(pluginName: string): boolean {
|
|
109
|
+
return this.plugins.has(pluginName);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Get plugins by state
|
|
114
|
+
*/
|
|
115
|
+
getPluginsByState(state: PluginLifecycleState): PluginInfo[] {
|
|
116
|
+
return Array.from(this.plugins.values()).filter((info) => info.state === state);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Get plugin count
|
|
121
|
+
*/
|
|
122
|
+
getPluginCount(): number {
|
|
123
|
+
return this.plugins.size;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Update plugin state
|
|
128
|
+
*/
|
|
129
|
+
updatePluginState(pluginName: string, state: PluginLifecycleState, error?: Error): void {
|
|
130
|
+
const info = this.plugins.get(pluginName);
|
|
131
|
+
if (!info) {
|
|
132
|
+
throw new PluginError(
|
|
133
|
+
`Plugin '${pluginName}' not found`,
|
|
134
|
+
pluginName,
|
|
135
|
+
'INVALID_PLUGIN'
|
|
136
|
+
);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
info.state = state;
|
|
140
|
+
|
|
141
|
+
if (state === 'initialized') {
|
|
142
|
+
info.initializedAt = new Date();
|
|
143
|
+
} else if (state === 'shutdown') {
|
|
144
|
+
info.shutdownAt = new Date();
|
|
145
|
+
} else if (state === 'error') {
|
|
146
|
+
info.error = error;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Collect and update plugin metrics
|
|
152
|
+
*/
|
|
153
|
+
collectPluginMetrics(pluginName: string): void {
|
|
154
|
+
const info = this.plugins.get(pluginName);
|
|
155
|
+
if (!info || !info.metrics) {
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
const plugin = info.plugin;
|
|
160
|
+
|
|
161
|
+
// Count registered items
|
|
162
|
+
info.metrics.agentTypesRegistered = plugin.registerAgentTypes?.()?.length || 0;
|
|
163
|
+
info.metrics.taskTypesRegistered = plugin.registerTaskTypes?.()?.length || 0;
|
|
164
|
+
info.metrics.mcpToolsRegistered = plugin.registerMCPTools?.()?.length || 0;
|
|
165
|
+
info.metrics.cliCommandsRegistered = plugin.registerCLICommands?.()?.length || 0;
|
|
166
|
+
info.metrics.memoryBackendsRegistered = plugin.registerMemoryBackends?.()?.length || 0;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* Get plugin status summary
|
|
171
|
+
*/
|
|
172
|
+
getStatusSummary(): PluginRegistryStatus {
|
|
173
|
+
const states = Array.from(this.plugins.values()).reduce((acc, info) => {
|
|
174
|
+
acc[info.state] = (acc[info.state] || 0) + 1;
|
|
175
|
+
return acc;
|
|
176
|
+
}, {} as Record<PluginLifecycleState, number>);
|
|
177
|
+
|
|
178
|
+
return {
|
|
179
|
+
totalPlugins: this.plugins.size,
|
|
180
|
+
states,
|
|
181
|
+
agentTypesRegistered: this.agentTypes.size,
|
|
182
|
+
taskTypesRegistered: this.taskTypes.size,
|
|
183
|
+
mcpToolsRegistered: this.mcpTools.size,
|
|
184
|
+
cliCommandsRegistered: this.cliCommands.size,
|
|
185
|
+
memoryBackendsRegistered: this.memoryBackends.size,
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
// =============================================================================
|
|
190
|
+
// Agent Type Registry
|
|
191
|
+
// =============================================================================
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* Register agent types from a plugin
|
|
195
|
+
*/
|
|
196
|
+
registerAgentTypes(pluginName: string): void {
|
|
197
|
+
const info = this.plugins.get(pluginName);
|
|
198
|
+
if (!info) {
|
|
199
|
+
throw new PluginError(
|
|
200
|
+
`Plugin '${pluginName}' not found`,
|
|
201
|
+
pluginName,
|
|
202
|
+
'INVALID_PLUGIN'
|
|
203
|
+
);
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
const agentTypes = info.plugin.registerAgentTypes?.();
|
|
207
|
+
if (!agentTypes || agentTypes.length === 0) {
|
|
208
|
+
return;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
for (const definition of agentTypes) {
|
|
212
|
+
if (this.agentTypes.has(definition.type)) {
|
|
213
|
+
throw new PluginError(
|
|
214
|
+
`Agent type '${definition.type}' is already registered by plugin '${this.agentTypes.get(definition.type)?.plugin}'`,
|
|
215
|
+
pluginName,
|
|
216
|
+
'DUPLICATE_PLUGIN'
|
|
217
|
+
);
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
this.agentTypes.set(definition.type, { plugin: pluginName, definition });
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
/**
|
|
225
|
+
* Unregister agent types from a plugin
|
|
226
|
+
*/
|
|
227
|
+
unregisterPluginAgentTypes(pluginName: string): void {
|
|
228
|
+
for (const [type, entry] of Array.from(this.agentTypes.entries())) {
|
|
229
|
+
if (entry.plugin === pluginName) {
|
|
230
|
+
this.agentTypes.delete(type);
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
/**
|
|
236
|
+
* Get agent type definition
|
|
237
|
+
*/
|
|
238
|
+
getAgentType(type: string): AgentTypeDefinition | undefined {
|
|
239
|
+
return this.agentTypes.get(type)?.definition;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
/**
|
|
243
|
+
* Get all agent types
|
|
244
|
+
*/
|
|
245
|
+
getAllAgentTypes(): AgentTypeDefinition[] {
|
|
246
|
+
return Array.from(this.agentTypes.values()).map((entry) => entry.definition);
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
/**
|
|
250
|
+
* Get agent types by plugin
|
|
251
|
+
*/
|
|
252
|
+
getAgentTypesByPlugin(pluginName: string): AgentTypeDefinition[] {
|
|
253
|
+
return Array.from(this.agentTypes.values())
|
|
254
|
+
.filter((entry) => entry.plugin === pluginName)
|
|
255
|
+
.map((entry) => entry.definition);
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
// =============================================================================
|
|
259
|
+
// Task Type Registry
|
|
260
|
+
// =============================================================================
|
|
261
|
+
|
|
262
|
+
/**
|
|
263
|
+
* Register task types from a plugin
|
|
264
|
+
*/
|
|
265
|
+
registerTaskTypes(pluginName: string): void {
|
|
266
|
+
const info = this.plugins.get(pluginName);
|
|
267
|
+
if (!info) {
|
|
268
|
+
throw new PluginError(
|
|
269
|
+
`Plugin '${pluginName}' not found`,
|
|
270
|
+
pluginName,
|
|
271
|
+
'INVALID_PLUGIN'
|
|
272
|
+
);
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
const taskTypes = info.plugin.registerTaskTypes?.();
|
|
276
|
+
if (!taskTypes || taskTypes.length === 0) {
|
|
277
|
+
return;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
for (const definition of taskTypes) {
|
|
281
|
+
if (this.taskTypes.has(definition.type)) {
|
|
282
|
+
throw new PluginError(
|
|
283
|
+
`Task type '${definition.type}' is already registered by plugin '${this.taskTypes.get(definition.type)?.plugin}'`,
|
|
284
|
+
pluginName,
|
|
285
|
+
'DUPLICATE_PLUGIN'
|
|
286
|
+
);
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
this.taskTypes.set(definition.type, { plugin: pluginName, definition });
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
/**
|
|
294
|
+
* Unregister task types from a plugin
|
|
295
|
+
*/
|
|
296
|
+
unregisterPluginTaskTypes(pluginName: string): void {
|
|
297
|
+
for (const [type, entry] of Array.from(this.taskTypes.entries())) {
|
|
298
|
+
if (entry.plugin === pluginName) {
|
|
299
|
+
this.taskTypes.delete(type);
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
/**
|
|
305
|
+
* Get task type definition
|
|
306
|
+
*/
|
|
307
|
+
getTaskType(type: string): TaskTypeDefinition | undefined {
|
|
308
|
+
return this.taskTypes.get(type)?.definition;
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
/**
|
|
312
|
+
* Get all task types
|
|
313
|
+
*/
|
|
314
|
+
getAllTaskTypes(): TaskTypeDefinition[] {
|
|
315
|
+
return Array.from(this.taskTypes.values()).map((entry) => entry.definition);
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
/**
|
|
319
|
+
* Get task types by plugin
|
|
320
|
+
*/
|
|
321
|
+
getTaskTypesByPlugin(pluginName: string): TaskTypeDefinition[] {
|
|
322
|
+
return Array.from(this.taskTypes.values())
|
|
323
|
+
.filter((entry) => entry.plugin === pluginName)
|
|
324
|
+
.map((entry) => entry.definition);
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
// =============================================================================
|
|
328
|
+
// MCP Tool Registry
|
|
329
|
+
// =============================================================================
|
|
330
|
+
|
|
331
|
+
/**
|
|
332
|
+
* Register MCP tools from a plugin
|
|
333
|
+
*/
|
|
334
|
+
registerMCPTools(pluginName: string): void {
|
|
335
|
+
const info = this.plugins.get(pluginName);
|
|
336
|
+
if (!info) {
|
|
337
|
+
throw new PluginError(
|
|
338
|
+
`Plugin '${pluginName}' not found`,
|
|
339
|
+
pluginName,
|
|
340
|
+
'INVALID_PLUGIN'
|
|
341
|
+
);
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
const mcpTools = info.plugin.registerMCPTools?.();
|
|
345
|
+
if (!mcpTools || mcpTools.length === 0) {
|
|
346
|
+
return;
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
for (const definition of mcpTools) {
|
|
350
|
+
if (this.mcpTools.has(definition.name)) {
|
|
351
|
+
throw new PluginError(
|
|
352
|
+
`MCP tool '${definition.name}' is already registered by plugin '${this.mcpTools.get(definition.name)?.plugin}'`,
|
|
353
|
+
pluginName,
|
|
354
|
+
'DUPLICATE_PLUGIN'
|
|
355
|
+
);
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
// Add plugin metadata
|
|
359
|
+
definition.pluginName = pluginName;
|
|
360
|
+
|
|
361
|
+
this.mcpTools.set(definition.name, { plugin: pluginName, definition });
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
/**
|
|
366
|
+
* Unregister MCP tools from a plugin
|
|
367
|
+
*/
|
|
368
|
+
unregisterPluginMCPTools(pluginName: string): void {
|
|
369
|
+
for (const [name, entry] of Array.from(this.mcpTools.entries())) {
|
|
370
|
+
if (entry.plugin === pluginName) {
|
|
371
|
+
this.mcpTools.delete(name);
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
/**
|
|
377
|
+
* Get MCP tool definition
|
|
378
|
+
*/
|
|
379
|
+
getMCPTool(name: string): MCPToolDefinition | undefined {
|
|
380
|
+
return this.mcpTools.get(name)?.definition;
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
/**
|
|
384
|
+
* Get all MCP tools
|
|
385
|
+
*/
|
|
386
|
+
getAllMCPTools(): MCPToolDefinition[] {
|
|
387
|
+
return Array.from(this.mcpTools.values()).map((entry) => entry.definition);
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
/**
|
|
391
|
+
* Get MCP tools by plugin
|
|
392
|
+
*/
|
|
393
|
+
getMCPToolsByPlugin(pluginName: string): MCPToolDefinition[] {
|
|
394
|
+
return Array.from(this.mcpTools.values())
|
|
395
|
+
.filter((entry) => entry.plugin === pluginName)
|
|
396
|
+
.map((entry) => entry.definition);
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
// =============================================================================
|
|
400
|
+
// CLI Command Registry
|
|
401
|
+
// =============================================================================
|
|
402
|
+
|
|
403
|
+
/**
|
|
404
|
+
* Register CLI commands from a plugin
|
|
405
|
+
*/
|
|
406
|
+
registerCLICommands(pluginName: string): void {
|
|
407
|
+
const info = this.plugins.get(pluginName);
|
|
408
|
+
if (!info) {
|
|
409
|
+
throw new PluginError(
|
|
410
|
+
`Plugin '${pluginName}' not found`,
|
|
411
|
+
pluginName,
|
|
412
|
+
'INVALID_PLUGIN'
|
|
413
|
+
);
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
const cliCommands = info.plugin.registerCLICommands?.();
|
|
417
|
+
if (!cliCommands || cliCommands.length === 0) {
|
|
418
|
+
return;
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
for (const definition of cliCommands) {
|
|
422
|
+
if (this.cliCommands.has(definition.name)) {
|
|
423
|
+
throw new PluginError(
|
|
424
|
+
`CLI command '${definition.name}' is already registered by plugin '${this.cliCommands.get(definition.name)?.plugin}'`,
|
|
425
|
+
pluginName,
|
|
426
|
+
'DUPLICATE_PLUGIN'
|
|
427
|
+
);
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
this.cliCommands.set(definition.name, { plugin: pluginName, definition });
|
|
431
|
+
|
|
432
|
+
// Register aliases
|
|
433
|
+
if (definition.aliases) {
|
|
434
|
+
for (const alias of definition.aliases) {
|
|
435
|
+
if (this.cliCommands.has(alias)) {
|
|
436
|
+
throw new PluginError(
|
|
437
|
+
`CLI command alias '${alias}' is already registered`,
|
|
438
|
+
pluginName,
|
|
439
|
+
'DUPLICATE_PLUGIN'
|
|
440
|
+
);
|
|
441
|
+
}
|
|
442
|
+
this.cliCommands.set(alias, { plugin: pluginName, definition });
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
/**
|
|
449
|
+
* Unregister CLI commands from a plugin
|
|
450
|
+
*/
|
|
451
|
+
unregisterPluginCLICommands(pluginName: string): void {
|
|
452
|
+
for (const [name, entry] of Array.from(this.cliCommands.entries())) {
|
|
453
|
+
if (entry.plugin === pluginName) {
|
|
454
|
+
this.cliCommands.delete(name);
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
/**
|
|
460
|
+
* Get CLI command definition
|
|
461
|
+
*/
|
|
462
|
+
getCLICommand(name: string): CLICommandDefinition | undefined {
|
|
463
|
+
return this.cliCommands.get(name)?.definition;
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
/**
|
|
467
|
+
* Get all CLI commands
|
|
468
|
+
*/
|
|
469
|
+
getAllCLICommands(): CLICommandDefinition[] {
|
|
470
|
+
const seen = new Set<CLICommandDefinition>();
|
|
471
|
+
return Array.from(this.cliCommands.values())
|
|
472
|
+
.map((entry) => entry.definition)
|
|
473
|
+
.filter((def) => {
|
|
474
|
+
if (seen.has(def)) return false;
|
|
475
|
+
seen.add(def);
|
|
476
|
+
return true;
|
|
477
|
+
});
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
/**
|
|
481
|
+
* Get CLI commands by plugin
|
|
482
|
+
*/
|
|
483
|
+
getCLICommandsByPlugin(pluginName: string): CLICommandDefinition[] {
|
|
484
|
+
const seen = new Set<CLICommandDefinition>();
|
|
485
|
+
return Array.from(this.cliCommands.values())
|
|
486
|
+
.filter((entry) => entry.plugin === pluginName)
|
|
487
|
+
.map((entry) => entry.definition)
|
|
488
|
+
.filter((def) => {
|
|
489
|
+
if (seen.has(def)) return false;
|
|
490
|
+
seen.add(def);
|
|
491
|
+
return true;
|
|
492
|
+
});
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
// =============================================================================
|
|
496
|
+
// Memory Backend Registry
|
|
497
|
+
// =============================================================================
|
|
498
|
+
|
|
499
|
+
/**
|
|
500
|
+
* Register memory backends from a plugin
|
|
501
|
+
*/
|
|
502
|
+
registerMemoryBackends(pluginName: string): void {
|
|
503
|
+
const info = this.plugins.get(pluginName);
|
|
504
|
+
if (!info) {
|
|
505
|
+
throw new PluginError(
|
|
506
|
+
`Plugin '${pluginName}' not found`,
|
|
507
|
+
pluginName,
|
|
508
|
+
'INVALID_PLUGIN'
|
|
509
|
+
);
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
const memoryBackends = info.plugin.registerMemoryBackends?.();
|
|
513
|
+
if (!memoryBackends || memoryBackends.length === 0) {
|
|
514
|
+
return;
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
for (const factory of memoryBackends) {
|
|
518
|
+
if (this.memoryBackends.has(factory.name)) {
|
|
519
|
+
throw new PluginError(
|
|
520
|
+
`Memory backend '${factory.name}' is already registered by plugin '${this.memoryBackends.get(factory.name)?.plugin}'`,
|
|
521
|
+
pluginName,
|
|
522
|
+
'DUPLICATE_PLUGIN'
|
|
523
|
+
);
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
this.memoryBackends.set(factory.name, { plugin: pluginName, factory });
|
|
527
|
+
}
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
/**
|
|
531
|
+
* Unregister memory backends from a plugin
|
|
532
|
+
*/
|
|
533
|
+
unregisterPluginMemoryBackends(pluginName: string): void {
|
|
534
|
+
for (const [name, entry] of Array.from(this.memoryBackends.entries())) {
|
|
535
|
+
if (entry.plugin === pluginName) {
|
|
536
|
+
this.memoryBackends.delete(name);
|
|
537
|
+
}
|
|
538
|
+
}
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
/**
|
|
542
|
+
* Get memory backend factory
|
|
543
|
+
*/
|
|
544
|
+
getMemoryBackend(name: string): MemoryBackendFactory | undefined {
|
|
545
|
+
return this.memoryBackends.get(name)?.factory;
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
/**
|
|
549
|
+
* Get all memory backends
|
|
550
|
+
*/
|
|
551
|
+
getAllMemoryBackends(): MemoryBackendFactory[] {
|
|
552
|
+
return Array.from(this.memoryBackends.values()).map((entry) => entry.factory);
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
/**
|
|
556
|
+
* Get memory backends by plugin
|
|
557
|
+
*/
|
|
558
|
+
getMemoryBackendsByPlugin(pluginName: string): MemoryBackendFactory[] {
|
|
559
|
+
return Array.from(this.memoryBackends.values())
|
|
560
|
+
.filter((entry) => entry.plugin === pluginName)
|
|
561
|
+
.map((entry) => entry.factory);
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
// =============================================================================
|
|
565
|
+
// Bulk Registration
|
|
566
|
+
// =============================================================================
|
|
567
|
+
|
|
568
|
+
/**
|
|
569
|
+
* Register all extension points from a plugin
|
|
570
|
+
*/
|
|
571
|
+
registerAllFromPlugin(pluginName: string): void {
|
|
572
|
+
this.registerAgentTypes(pluginName);
|
|
573
|
+
this.registerTaskTypes(pluginName);
|
|
574
|
+
this.registerMCPTools(pluginName);
|
|
575
|
+
this.registerCLICommands(pluginName);
|
|
576
|
+
this.registerMemoryBackends(pluginName);
|
|
577
|
+
this.collectPluginMetrics(pluginName);
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
/**
|
|
581
|
+
* Clear all registrations (for testing)
|
|
582
|
+
*/
|
|
583
|
+
clear(): void {
|
|
584
|
+
this.plugins.clear();
|
|
585
|
+
this.agentTypes.clear();
|
|
586
|
+
this.taskTypes.clear();
|
|
587
|
+
this.mcpTools.clear();
|
|
588
|
+
this.cliCommands.clear();
|
|
589
|
+
this.memoryBackends.clear();
|
|
590
|
+
}
|
|
591
|
+
}
|
|
592
|
+
|
|
593
|
+
/**
|
|
594
|
+
* Plugin registry status summary
|
|
595
|
+
*/
|
|
596
|
+
export interface PluginRegistryStatus {
|
|
597
|
+
totalPlugins: number;
|
|
598
|
+
states: Record<PluginLifecycleState, number>;
|
|
599
|
+
agentTypesRegistered: number;
|
|
600
|
+
taskTypesRegistered: number;
|
|
601
|
+
mcpToolsRegistered: number;
|
|
602
|
+
cliCommandsRegistered: number;
|
|
603
|
+
memoryBackendsRegistered: number;
|
|
604
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Plugins System - ADR-004 Implementation
|
|
3
|
+
*
|
|
4
|
+
* Plugin architecture for extending Claude Flow functionality.
|
|
5
|
+
*
|
|
6
|
+
* @module v3/shared/plugins
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
// Types
|
|
10
|
+
export type {
|
|
11
|
+
PluginConfig,
|
|
12
|
+
PluginContext,
|
|
13
|
+
PluginEvent,
|
|
14
|
+
PluginEventHandler,
|
|
15
|
+
ClaudeFlowPlugin,
|
|
16
|
+
PluginMetadata,
|
|
17
|
+
IPluginRegistry,
|
|
18
|
+
IPluginLoader,
|
|
19
|
+
} from './types.js';
|
|
20
|
+
|
|
21
|
+
// Official Plugins
|
|
22
|
+
export {
|
|
23
|
+
HiveMindPlugin,
|
|
24
|
+
createHiveMindPlugin,
|
|
25
|
+
type HiveMindConfig,
|
|
26
|
+
type CollectiveDecision,
|
|
27
|
+
type EmergentPattern,
|
|
28
|
+
MaestroPlugin,
|
|
29
|
+
createMaestroPlugin,
|
|
30
|
+
type MaestroConfig,
|
|
31
|
+
type WorkflowStep,
|
|
32
|
+
type Workflow,
|
|
33
|
+
type OrchestrationResult,
|
|
34
|
+
} from './official/index.js';
|