@claude-flow/shared 3.0.0-alpha.1 → 3.0.0-alpha.8
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-flow/daemon-state.json +135 -0
- package/.claude-flow/data/pending-insights.jsonl +2 -0
- package/.claude-flow/data/ranked-context.json +5 -0
- package/.claude-flow/logs/daemon.log +45 -0
- package/.claude-flow/logs/headless/audit_1777379186972_h5un5x_prompt.log +3210 -0
- package/.claude-flow/logs/headless/audit_1777379186972_h5un5x_result.log +117 -0
- package/.claude-flow/logs/headless/audit_1777379816437_w0eaul_prompt.log +3210 -0
- package/.claude-flow/logs/headless/audit_1777379816437_w0eaul_result.log +53 -0
- package/.claude-flow/logs/headless/audit_1777380440097_621y8m_prompt.log +3210 -0
- package/.claude-flow/logs/headless/audit_1777380440097_621y8m_result.log +75 -0
- package/.claude-flow/logs/headless/optimize_1777379306973_an4lmy_prompt.log +3504 -0
- package/.claude-flow/logs/headless/optimize_1777379306973_an4lmy_result.log +166 -0
- package/.claude-flow/logs/headless/optimize_1777380274732_apxz3s_prompt.log +3504 -0
- package/.claude-flow/logs/headless/optimize_1777380274732_apxz3s_result.log +219 -0
- package/.claude-flow/logs/headless/testgaps_1777379546969_dvf2a1_prompt.log +3189 -0
- package/.claude-flow/logs/headless/testgaps_1777379546969_dvf2a1_result.log +155 -0
- package/.claude-flow/metrics/codebase-map.json +11 -0
- package/.claude-flow/metrics/consolidation.json +6 -0
- package/.claude-flow/sessions/current.json +13 -0
- package/.swarm/hnsw.index +0 -0
- package/.swarm/hnsw.metadata.json +1 -0
- package/.swarm/memory.db +0 -0
- package/.swarm/memory.db-shm +0 -0
- package/.swarm/memory.db-wal +0 -0
- package/.swarm/schema.sql +305 -0
- package/dist/core/config/loader.d.ts.map +1 -1
- package/dist/core/config/loader.js +17 -1
- package/dist/core/config/loader.js.map +1 -1
- package/dist/core/config/schema.d.ts +697 -103
- package/dist/core/config/schema.d.ts.map +1 -1
- package/dist/core/config/schema.js +3 -1
- package/dist/core/config/schema.js.map +1 -1
- package/dist/events/event-store.d.ts.map +1 -1
- package/dist/events/event-store.js +20 -9
- package/dist/events/event-store.js.map +1 -1
- package/dist/events/example-usage.js +1 -1
- package/dist/events/example-usage.js.map +1 -1
- package/dist/events/index.d.ts +2 -0
- package/dist/events/index.d.ts.map +1 -1
- package/dist/events/index.js +2 -0
- package/dist/events/index.js.map +1 -1
- package/dist/events/rvf-event-log.d.ts +82 -0
- package/dist/events/rvf-event-log.d.ts.map +1 -0
- package/dist/events/rvf-event-log.js +340 -0
- package/dist/events/rvf-event-log.js.map +1 -0
- package/dist/hooks/example-usage.js +3 -3
- package/dist/hooks/example-usage.js.map +1 -1
- package/dist/hooks/executor.d.ts.map +1 -1
- package/dist/hooks/executor.js +7 -4
- package/dist/hooks/executor.js.map +1 -1
- package/dist/hooks/verify-exports.test.js +6 -6
- package/dist/hooks/verify-exports.test.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/dist/mcp/server.d.ts.map +1 -1
- package/dist/mcp/server.js +3 -6
- package/dist/mcp/server.js.map +1 -1
- package/dist/mcp/types.d.ts +4 -6
- package/dist/mcp/types.d.ts.map +1 -1
- package/dist/mcp/types.js.map +1 -1
- package/dist/plugins/official/hive-mind-plugin.js +2 -2
- package/dist/plugins/official/hive-mind-plugin.js.map +1 -1
- package/dist/plugins/official/maestro-plugin.js +3 -3
- package/dist/plugins/official/maestro-plugin.js.map +1 -1
- package/dist/services/index.d.ts +7 -0
- package/dist/services/index.d.ts.map +1 -0
- package/dist/services/index.js +7 -0
- package/dist/services/index.js.map +1 -0
- package/dist/services/v3-progress.service.d.ts +124 -0
- package/dist/services/v3-progress.service.d.ts.map +1 -0
- package/dist/services/v3-progress.service.js +402 -0
- package/dist/services/v3-progress.service.js.map +1 -0
- package/package.json +12 -3
- package/ruvector.db +0 -0
- package/src/core/config/loader.ts +17 -1
- package/src/core/config/schema.ts +3 -1
- package/src/events/event-store.ts +18 -9
- package/src/events/example-usage.ts +1 -1
- package/src/events/index.ts +4 -0
- package/src/events/rvf-event-log.ts +427 -0
- package/src/hooks/example-usage.ts +3 -3
- package/src/hooks/executor.ts +7 -5
- package/src/hooks/verify-exports.test.ts +6 -6
- package/src/index.ts +5 -0
- package/src/mcp/server.ts +3 -6
- package/src/mcp/types.ts +4 -6
- package/src/plugins/official/hive-mind-plugin.ts +2 -2
- package/src/plugins/official/maestro-plugin.ts +3 -3
- package/src/services/index.ts +16 -0
- package/src/services/v3-progress.service.ts +505 -0
- package/tmp.json +0 -0
- package/tsconfig.tsbuildinfo +1 -1
- package/.agentic-flow/intelligence.json +0 -16
- package/__tests__/coverage/base.css +0 -224
- package/__tests__/coverage/block-navigation.js +0 -87
- package/__tests__/coverage/coverage-final.json +0 -50
- package/__tests__/coverage/favicon.png +0 -0
- package/__tests__/coverage/index.html +0 -326
- package/__tests__/coverage/lcov-report/base.css +0 -224
- package/__tests__/coverage/lcov-report/block-navigation.js +0 -87
- package/__tests__/coverage/lcov-report/favicon.png +0 -0
- package/__tests__/coverage/lcov-report/index.html +0 -326
- package/__tests__/coverage/lcov-report/prettify.css +0 -1
- package/__tests__/coverage/lcov-report/prettify.js +0 -2
- package/__tests__/coverage/lcov-report/sort-arrow-sprite.png +0 -0
- package/__tests__/coverage/lcov-report/sorter.js +0 -210
- package/__tests__/coverage/lcov-report/src/core/config/defaults.ts.html +0 -706
- package/__tests__/coverage/lcov-report/src/core/config/index.html +0 -161
- package/__tests__/coverage/lcov-report/src/core/config/loader.ts.html +0 -898
- package/__tests__/coverage/lcov-report/src/core/config/schema.ts.html +0 -649
- package/__tests__/coverage/lcov-report/src/core/config/validator.ts.html +0 -712
- package/__tests__/coverage/lcov-report/src/core/event-bus.ts.html +0 -793
- package/__tests__/coverage/lcov-report/src/core/index.html +0 -116
- package/__tests__/coverage/lcov-report/src/core/interfaces/event.interface.ts.html +0 -886
- package/__tests__/coverage/lcov-report/src/core/interfaces/index.html +0 -116
- package/__tests__/coverage/lcov-report/src/core/orchestrator/event-coordinator.ts.html +0 -451
- package/__tests__/coverage/lcov-report/src/core/orchestrator/health-monitor.ts.html +0 -727
- package/__tests__/coverage/lcov-report/src/core/orchestrator/index.html +0 -176
- package/__tests__/coverage/lcov-report/src/core/orchestrator/lifecycle-manager.ts.html +0 -874
- package/__tests__/coverage/lcov-report/src/core/orchestrator/session-manager.ts.html +0 -922
- package/__tests__/coverage/lcov-report/src/core/orchestrator/task-manager.ts.html +0 -1036
- package/__tests__/coverage/lcov-report/src/events/domain-events.ts.html +0 -1837
- package/__tests__/coverage/lcov-report/src/events/event-store.ts.html +0 -1849
- package/__tests__/coverage/lcov-report/src/events/example-usage.ts.html +0 -964
- package/__tests__/coverage/lcov-report/src/events/index.html +0 -176
- package/__tests__/coverage/lcov-report/src/events/projections.ts.html +0 -1768
- package/__tests__/coverage/lcov-report/src/events/state-reconstructor.ts.html +0 -1132
- package/__tests__/coverage/lcov-report/src/events.ts.html +0 -1186
- package/__tests__/coverage/lcov-report/src/hooks/example-usage.ts.html +0 -1582
- package/__tests__/coverage/lcov-report/src/hooks/executor.ts.html +0 -1222
- package/__tests__/coverage/lcov-report/src/hooks/index.html +0 -191
- package/__tests__/coverage/lcov-report/src/hooks/registry.ts.html +0 -1084
- package/__tests__/coverage/lcov-report/src/hooks/safety/bash-safety.ts.html +0 -1897
- package/__tests__/coverage/lcov-report/src/hooks/safety/file-organization.ts.html +0 -1504
- package/__tests__/coverage/lcov-report/src/hooks/safety/git-commit.ts.html +0 -1954
- package/__tests__/coverage/lcov-report/src/hooks/safety/index.html +0 -146
- package/__tests__/coverage/lcov-report/src/hooks/session-hooks.ts.html +0 -1762
- package/__tests__/coverage/lcov-report/src/hooks/task-hooks.ts.html +0 -1624
- package/__tests__/coverage/lcov-report/src/hooks/types.ts.html +0 -1156
- package/__tests__/coverage/lcov-report/src/index.html +0 -176
- package/__tests__/coverage/lcov-report/src/mcp/connection-pool.ts.html +0 -1399
- package/__tests__/coverage/lcov-report/src/mcp/index.html +0 -176
- package/__tests__/coverage/lcov-report/src/mcp/server.ts.html +0 -2407
- package/__tests__/coverage/lcov-report/src/mcp/session-manager.ts.html +0 -1369
- package/__tests__/coverage/lcov-report/src/mcp/tool-registry.ts.html +0 -1783
- package/__tests__/coverage/lcov-report/src/mcp/transport/http.ts.html +0 -1756
- package/__tests__/coverage/lcov-report/src/mcp/transport/index.html +0 -146
- package/__tests__/coverage/lcov-report/src/mcp/transport/stdio.ts.html +0 -1057
- package/__tests__/coverage/lcov-report/src/mcp/transport/websocket.ts.html +0 -1537
- package/__tests__/coverage/lcov-report/src/mcp/types.ts.html +0 -1780
- package/__tests__/coverage/lcov-report/src/plugin-interface.ts.html +0 -2074
- package/__tests__/coverage/lcov-report/src/plugin-loader.ts.html +0 -1999
- package/__tests__/coverage/lcov-report/src/plugin-registry.ts.html +0 -1897
- package/__tests__/coverage/lcov-report/src/plugins/official/hive-mind-plugin.ts.html +0 -1075
- package/__tests__/coverage/lcov-report/src/plugins/official/index.html +0 -131
- package/__tests__/coverage/lcov-report/src/plugins/official/maestro-plugin.ts.html +0 -1609
- package/__tests__/coverage/lcov-report/src/resilience/bulkhead.ts.html +0 -916
- package/__tests__/coverage/lcov-report/src/resilience/circuit-breaker.ts.html +0 -1063
- package/__tests__/coverage/lcov-report/src/resilience/index.html +0 -161
- package/__tests__/coverage/lcov-report/src/resilience/rate-limiter.ts.html +0 -1345
- package/__tests__/coverage/lcov-report/src/resilience/retry.ts.html +0 -757
- package/__tests__/coverage/lcov-report/src/security/index.html +0 -131
- package/__tests__/coverage/lcov-report/src/security/input-validation.ts.html +0 -880
- package/__tests__/coverage/lcov-report/src/security/secure-random.ts.html +0 -562
- package/__tests__/coverage/lcov-report/src/types/index.html +0 -131
- package/__tests__/coverage/lcov-report/src/types/swarm.types.ts.html +0 -850
- package/__tests__/coverage/lcov-report/src/types/task.types.ts.html +0 -700
- package/__tests__/coverage/lcov-report/src/types.ts.html +0 -1186
- package/__tests__/coverage/lcov-report/src/utils/index.html +0 -116
- package/__tests__/coverage/lcov-report/src/utils/secure-logger.ts.html +0 -856
- package/__tests__/coverage/lcov.info +0 -19877
- package/__tests__/coverage/prettify.css +0 -1
- package/__tests__/coverage/prettify.js +0 -2
- package/__tests__/coverage/sort-arrow-sprite.png +0 -0
- package/__tests__/coverage/sorter.js +0 -210
- package/__tests__/coverage/src/core/config/defaults.ts.html +0 -706
- package/__tests__/coverage/src/core/config/index.html +0 -161
- package/__tests__/coverage/src/core/config/loader.ts.html +0 -898
- package/__tests__/coverage/src/core/config/schema.ts.html +0 -649
- package/__tests__/coverage/src/core/config/validator.ts.html +0 -712
- package/__tests__/coverage/src/core/event-bus.ts.html +0 -793
- package/__tests__/coverage/src/core/index.html +0 -116
- package/__tests__/coverage/src/core/interfaces/event.interface.ts.html +0 -886
- package/__tests__/coverage/src/core/interfaces/index.html +0 -116
- package/__tests__/coverage/src/core/orchestrator/event-coordinator.ts.html +0 -451
- package/__tests__/coverage/src/core/orchestrator/health-monitor.ts.html +0 -727
- package/__tests__/coverage/src/core/orchestrator/index.html +0 -176
- package/__tests__/coverage/src/core/orchestrator/lifecycle-manager.ts.html +0 -874
- package/__tests__/coverage/src/core/orchestrator/session-manager.ts.html +0 -922
- package/__tests__/coverage/src/core/orchestrator/task-manager.ts.html +0 -1036
- package/__tests__/coverage/src/events/domain-events.ts.html +0 -1837
- package/__tests__/coverage/src/events/event-store.ts.html +0 -1849
- package/__tests__/coverage/src/events/example-usage.ts.html +0 -964
- package/__tests__/coverage/src/events/index.html +0 -176
- package/__tests__/coverage/src/events/projections.ts.html +0 -1768
- package/__tests__/coverage/src/events/state-reconstructor.ts.html +0 -1132
- package/__tests__/coverage/src/events.ts.html +0 -1186
- package/__tests__/coverage/src/hooks/example-usage.ts.html +0 -1582
- package/__tests__/coverage/src/hooks/executor.ts.html +0 -1222
- package/__tests__/coverage/src/hooks/index.html +0 -191
- package/__tests__/coverage/src/hooks/registry.ts.html +0 -1084
- package/__tests__/coverage/src/hooks/safety/bash-safety.ts.html +0 -1897
- package/__tests__/coverage/src/hooks/safety/file-organization.ts.html +0 -1504
- package/__tests__/coverage/src/hooks/safety/git-commit.ts.html +0 -1954
- package/__tests__/coverage/src/hooks/safety/index.html +0 -146
- package/__tests__/coverage/src/hooks/session-hooks.ts.html +0 -1762
- package/__tests__/coverage/src/hooks/task-hooks.ts.html +0 -1624
- package/__tests__/coverage/src/hooks/types.ts.html +0 -1156
- package/__tests__/coverage/src/index.html +0 -176
- package/__tests__/coverage/src/mcp/connection-pool.ts.html +0 -1399
- package/__tests__/coverage/src/mcp/index.html +0 -176
- package/__tests__/coverage/src/mcp/server.ts.html +0 -2407
- package/__tests__/coverage/src/mcp/session-manager.ts.html +0 -1369
- package/__tests__/coverage/src/mcp/tool-registry.ts.html +0 -1783
- package/__tests__/coverage/src/mcp/transport/http.ts.html +0 -1756
- package/__tests__/coverage/src/mcp/transport/index.html +0 -146
- package/__tests__/coverage/src/mcp/transport/stdio.ts.html +0 -1057
- package/__tests__/coverage/src/mcp/transport/websocket.ts.html +0 -1537
- package/__tests__/coverage/src/mcp/types.ts.html +0 -1780
- package/__tests__/coverage/src/plugin-interface.ts.html +0 -2074
- package/__tests__/coverage/src/plugin-loader.ts.html +0 -1999
- package/__tests__/coverage/src/plugin-registry.ts.html +0 -1897
- package/__tests__/coverage/src/plugins/official/hive-mind-plugin.ts.html +0 -1075
- package/__tests__/coverage/src/plugins/official/index.html +0 -131
- package/__tests__/coverage/src/plugins/official/maestro-plugin.ts.html +0 -1609
- package/__tests__/coverage/src/resilience/bulkhead.ts.html +0 -916
- package/__tests__/coverage/src/resilience/circuit-breaker.ts.html +0 -1063
- package/__tests__/coverage/src/resilience/index.html +0 -161
- package/__tests__/coverage/src/resilience/rate-limiter.ts.html +0 -1345
- package/__tests__/coverage/src/resilience/retry.ts.html +0 -757
- package/__tests__/coverage/src/security/index.html +0 -131
- package/__tests__/coverage/src/security/input-validation.ts.html +0 -880
- package/__tests__/coverage/src/security/secure-random.ts.html +0 -562
- package/__tests__/coverage/src/types/index.html +0 -131
- package/__tests__/coverage/src/types/swarm.types.ts.html +0 -850
- package/__tests__/coverage/src/types/task.types.ts.html +0 -700
- package/__tests__/coverage/src/types.ts.html +0 -1186
- package/__tests__/coverage/src/utils/index.html +0 -116
- package/__tests__/coverage/src/utils/secure-logger.ts.html +0 -856
|
@@ -0,0 +1,3504 @@
|
|
|
1
|
+
[2026-04-28T12:44:34.736Z] PROMPT
|
|
2
|
+
============================================================
|
|
3
|
+
Analyze this codebase for performance optimizations:
|
|
4
|
+
- Identify N+1 query patterns
|
|
5
|
+
- Find unnecessary re-renders in React
|
|
6
|
+
- Suggest caching opportunities
|
|
7
|
+
- Identify memory leaks
|
|
8
|
+
- Find redundant computations
|
|
9
|
+
|
|
10
|
+
Provide actionable suggestions with code examples.
|
|
11
|
+
|
|
12
|
+
## Codebase Context
|
|
13
|
+
|
|
14
|
+
--- src/core/config/defaults.ts ---
|
|
15
|
+
/**
|
|
16
|
+
* V3 Default Configuration Values
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
import type {
|
|
20
|
+
AgentConfig,
|
|
21
|
+
TaskConfig,
|
|
22
|
+
SwarmConfig,
|
|
23
|
+
MemoryConfig,
|
|
24
|
+
MCPServerConfig,
|
|
25
|
+
OrchestratorConfig,
|
|
26
|
+
SystemConfig,
|
|
27
|
+
} from './schema.js';
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Default agent configuration
|
|
31
|
+
*/
|
|
32
|
+
export const defaultAgentConfig: Partial<AgentConfig> = {
|
|
33
|
+
capabilities: [],
|
|
34
|
+
maxConcurrentTasks: 5,
|
|
35
|
+
priority: 50,
|
|
36
|
+
retryPolicy: {
|
|
37
|
+
maxRetries: 3,
|
|
38
|
+
backoffMs: 1000,
|
|
39
|
+
backoffMultiplier: 2,
|
|
40
|
+
},
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Default task configuration
|
|
45
|
+
*/
|
|
46
|
+
export const defaultTaskConfig: Partial<TaskConfig> = {
|
|
47
|
+
priority: 50,
|
|
48
|
+
metadata: {
|
|
49
|
+
maxRetries: 3,
|
|
50
|
+
},
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Default swarm configuration (core version)
|
|
55
|
+
*/
|
|
56
|
+
export const defaultSwarmConfigCore: SwarmConfig = {
|
|
57
|
+
topology: 'hierarchical-mesh',
|
|
58
|
+
maxAgents: 20,
|
|
59
|
+
autoScale: {
|
|
60
|
+
enabled: false,
|
|
61
|
+
minAgents: 1,
|
|
62
|
+
maxAgents: 20,
|
|
63
|
+
scaleUpThreshold: 0.8,
|
|
64
|
+
scaleDownThreshold: 0.3,
|
|
65
|
+
},
|
|
66
|
+
coordination: {
|
|
67
|
+
consensusRequired: false,
|
|
68
|
+
timeoutMs: 10000,
|
|
69
|
+
retryPolicy: {
|
|
70
|
+
maxRetries: 3,
|
|
71
|
+
backoffMs: 500,
|
|
72
|
+
},
|
|
73
|
+
},
|
|
74
|
+
communication: {
|
|
75
|
+
protocol: 'events',
|
|
76
|
+
batchSize: 10,
|
|
77
|
+
flushIntervalMs: 100,
|
|
78
|
+
},
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Default memory configuration (hybrid backend - ADR-009)
|
|
83
|
+
*/
|
|
84
|
+
export const defaultMemoryConfig: MemoryConfig = {
|
|
85
|
+
type: 'hybrid',
|
|
86
|
+
path: './data/memory',
|
|
87
|
+
sqlite: {
|
|
88
|
+
inMemory: false,
|
|
89
|
+
wal: true,
|
|
90
|
+
},
|
|
91
|
+
agentdb: {
|
|
92
|
+
dimensions: 1536,
|
|
93
|
+
indexType: 'hnsw',
|
|
94
|
+
efConstruction: 200,
|
|
95
|
+
m: 16,
|
|
96
|
+
quantization: 'none',
|
|
97
|
+
},
|
|
98
|
+
hybrid: {
|
|
99
|
+
vectorThreshold: 100,
|
|
100
|
+
},
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Default MCP server configuration
|
|
105
|
+
*/
|
|
106
|
+
export const defaultMCPServerConfig: MCPServerConfig = {
|
|
107
|
+
name: 'claude-flow',
|
|
108
|
+
version: '3.0.0',
|
|
109
|
+
transport: {
|
|
110
|
+
type: 'stdio',
|
|
111
|
+
},
|
|
112
|
+
capabilities: {
|
|
113
|
+
tools: true,
|
|
114
|
+
resources: true,
|
|
115
|
+
prompts: true,
|
|
116
|
+
logging: true,
|
|
117
|
+
},
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Default orchestrator configuration
|
|
122
|
+
*/
|
|
123
|
+
export const defaultOrchestratorConfig: OrchestratorConfig = {
|
|
124
|
+
session: {
|
|
125
|
+
persistSessions: true,
|
|
126
|
+
dataDir: './data',
|
|
127
|
+
sessionRetentionMs: 3600000, // 1 hour
|
|
128
|
+
},
|
|
129
|
+
health: {
|
|
130
|
+
checkInterval: 30000, // 30 seconds
|
|
131
|
+
historyLimit: 100,
|
|
132
|
+
degradedThreshold: 1,
|
|
133
|
+
unhealthyThreshold: 2,
|
|
134
|
+
},
|
|
135
|
+
lifecycle: {
|
|
136
|
+
maxConcurrentAgents: 20,
|
|
137
|
+
spawnTimeout: 30000, // 30 seconds
|
|
138
|
+
terminateTimeout: 10000, // 10 seconds
|
|
139
|
+
maxSpawnRetries: 3,
|
|
140
|
+
},
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Default full system configuration
|
|
145
|
+
*/
|
|
146
|
+
export const defaultSystemConfig: SystemConfig = {
|
|
147
|
+
orchestrator: defaultOrchestratorConfig,
|
|
148
|
+
memory: defaultMemoryConfig,
|
|
149
|
+
mcp: defaultMCPServerConfig,
|
|
150
|
+
swarm: defaultSwarmConfigCore,
|
|
151
|
+
};
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Agent type presets
|
|
155
|
+
*/
|
|
156
|
+
export const agentTypePresets: Record<string, Partial<AgentConfig>> = {
|
|
157
|
+
coder: {
|
|
158
|
+
type: 'coder',
|
|
159
|
+
capabilities: ['code', 'debug', 'refactor', 'test'],
|
|
160
|
+
maxConcurrentTasks: 3,
|
|
161
|
+
priority: 70,
|
|
162
|
+
},
|
|
163
|
+
reviewer: {
|
|
164
|
+
type: 'reviewer',
|
|
165
|
+
capabilities: ['review', 'analyze', 'suggest'],
|
|
166
|
+
maxConcurrentTasks: 5,
|
|
167
|
+
priority: 60,
|
|
168
|
+
},
|
|
169
|
+
tester: {
|
|
170
|
+
type: 'tester',
|
|
171
|
+
capabilities: ['test', 'validate', 'benchmark'],
|
|
172
|
+
maxConcurrentTasks: 4,
|
|
173
|
+
priority: 65,
|
|
174
|
+
},
|
|
175
|
+
researcher: {
|
|
176
|
+
type: 'researcher',
|
|
177
|
+
capabilities: ['research', 'analyze', 'summarize'],
|
|
178
|
+
maxConcurrentTasks: 3,
|
|
179
|
+
priority: 50,
|
|
180
|
+
},
|
|
181
|
+
planner: {
|
|
182
|
+
type: 'planner',
|
|
183
|
+
capabilities: ['plan', 'organize', 'decompose'],
|
|
184
|
+
maxConcurrentTasks: 2,
|
|
185
|
+
priority: 80,
|
|
186
|
+
},
|
|
187
|
+
architect: {
|
|
188
|
+
type: 'architect',
|
|
189
|
+
capabilities: ['design', 'architecture', 'patterns'],
|
|
190
|
+
maxConcurrentTasks: 2,
|
|
191
|
+
priority: 85,
|
|
192
|
+
},
|
|
193
|
+
coordinator: {
|
|
194
|
+
type: 'coordinator',
|
|
195
|
+
capabilities: ['coordinate', 'delegate', 'monitor'],
|
|
196
|
+
maxConcurrentTasks: 10,
|
|
197
|
+
priority: 90,
|
|
198
|
+
},
|
|
199
|
+
security: {
|
|
200
|
+
type: 'security',
|
|
201
|
+
capabilities: ['audit', 'scan', 'validate', 'secure'],
|
|
202
|
+
maxConcurrentTasks: 3,
|
|
203
|
+
priority: 95,
|
|
204
|
+
},
|
|
205
|
+
performance: {
|
|
206
|
+
type: 'performance',
|
|
207
|
+
capabilities: ['benchmark', 'optimize', 'profile'],
|
|
208
|
+
maxConcurrentTasks: 2,
|
|
209
|
+
priority: 70,
|
|
210
|
+
},
|
|
211
|
+
};
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* Get merged configuration with defaults
|
|
215
|
+
*/
|
|
216
|
+
export function mergeWithDefaults<T extends Record<string, unknown>>(
|
|
217
|
+
config: Partial<T>,
|
|
218
|
+
defaults: T,
|
|
219
|
+
): T {
|
|
220
|
+
return { ...defaults, ...config } as T;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
|
|
224
|
+
--- src/core/config/index.ts ---
|
|
225
|
+
/**
|
|
226
|
+
* V3 Configuration - Public API
|
|
227
|
+
*/
|
|
228
|
+
|
|
229
|
+
// Schemas
|
|
230
|
+
export * from './schema.js';
|
|
231
|
+
|
|
232
|
+
// Validation
|
|
233
|
+
export * from './validator.js';
|
|
234
|
+
|
|
235
|
+
// Defaults
|
|
236
|
+
export * from './defaults.js';
|
|
237
|
+
|
|
238
|
+
// Loader
|
|
239
|
+
export * from './loader.js';
|
|
240
|
+
|
|
241
|
+
|
|
242
|
+
--- src/core/config/loader.ts (truncated) ---
|
|
243
|
+
/**
|
|
244
|
+
* V3 Configuration Loader
|
|
245
|
+
* Load configuration from various sources
|
|
246
|
+
*/
|
|
247
|
+
|
|
248
|
+
import { readFile } from 'fs/promises';
|
|
249
|
+
import { join, resolve } from 'path';
|
|
250
|
+
import { existsSync } from 'fs';
|
|
251
|
+
import type { SystemConfig } from './schema.js';
|
|
252
|
+
import { validateSystemConfig, type ValidationResult } from './validator.js';
|
|
253
|
+
import { defaultSystemConfig, mergeWithDefaults } from './defaults.js';
|
|
254
|
+
|
|
255
|
+
/**
|
|
256
|
+
* Configuration source type
|
|
257
|
+
*/
|
|
258
|
+
export type ConfigSource = 'file' | 'env' | 'default' | 'merged';
|
|
259
|
+
|
|
260
|
+
/**
|
|
261
|
+
* Loaded configuration with metadata
|
|
262
|
+
*/
|
|
263
|
+
export interface LoadedConfig {
|
|
264
|
+
config: SystemConfig;
|
|
265
|
+
source: ConfigSource;
|
|
266
|
+
path?: string;
|
|
267
|
+
warnings?: string[];
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
/**
|
|
271
|
+
* Configuration file names to search for
|
|
272
|
+
*/
|
|
273
|
+
const CONFIG_FILE_NAMES = [
|
|
274
|
+
'claude-flow.config.json',
|
|
275
|
+
'claude-flow.config.js',
|
|
276
|
+
'claude-flow.json',
|
|
277
|
+
'.claude-flow.json',
|
|
278
|
+
];
|
|
279
|
+
|
|
280
|
+
/**
|
|
281
|
+
* Find configuration file in directory
|
|
282
|
+
*/
|
|
283
|
+
async function findConfigFile(directory: string): Promise<string | null> {
|
|
284
|
+
for (const name of CONFIG_FILE_NAMES) {
|
|
285
|
+
const path = join(directory, name);
|
|
286
|
+
if (existsSync(path)) {
|
|
287
|
+
return path;
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
return null;
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
/**
|
|
294
|
+
* Load configuration from JSON file
|
|
295
|
+
*/
|
|
296
|
+
async function loadJsonConfig(path: string): Promise<unknown> {
|
|
297
|
+
const content = await readFile(path, 'utf8');
|
|
298
|
+
return JSON.parse(content);
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
/**
|
|
302
|
+
* Load configuration from environment variables
|
|
303
|
+
*/
|
|
304
|
+
function loadEnvConfig(): Partial<SystemConfig> {
|
|
305
|
+
const config: Partial<SystemConfig> = {};
|
|
306
|
+
|
|
307
|
+
// Orchestrator settings
|
|
308
|
+
if (process.env.CLAUDE_FLOW_MAX_AGENTS) {
|
|
309
|
+
config.orchestrator = {
|
|
310
|
+
...defaultSystemConfig.orchestrator,
|
|
311
|
+
lifecycle: {
|
|
312
|
+
...defaultSystemConfig.orchestrator.lifecycle,
|
|
313
|
+
maxConcurrentAgents: parseInt(process.env.CLAUDE_FLOW_MAX_AGENTS, 10),
|
|
314
|
+
},
|
|
315
|
+
};
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
// Data directory
|
|
319
|
+
if (process.env.CLAUDE_FLOW_DATA_DIR) {
|
|
320
|
+
config.orchestrator = {
|
|
321
|
+
...config.orchestrator,
|
|
322
|
+
...defaultSystemConfig.orchestrator,
|
|
323
|
+
session: {
|
|
324
|
+
...defaultSystemConfig.orchestrator.session,
|
|
325
|
+
dataDir: process.env.CLAUDE_FLOW_DATA_DIR,
|
|
326
|
+
},
|
|
327
|
+
};
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
// Memory type
|
|
331
|
+
if (process.env.CLAUDE_FLOW_MEMORY_TYPE) {
|
|
332
|
+
const memoryType = process.env.CLAUDE_FLOW_MEMORY_TYPE as NonNullable<SystemConfig['memory']>['type'];
|
|
333
|
+
if (['sqlite', 'agentdb', 'hybrid', 'redis', 'memory'].includes(memoryType)) {
|
|
334
|
+
config.memory = {
|
|
335
|
+
...(defaultSystemConfig.memory ?? { type: 'hybrid' }),
|
|
336
|
+
type: memoryType,
|
|
337
|
+
};
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
// MCP transport
|
|
342
|
+
const defaultMcp = defaultSystemConfig.mcp ?? { name: 'claude-flow', version: '3.0.0', transport: { type: 'stdio' as const } };
|
|
343
|
+
if (process.env.CLAUDE_FLOW_MCP_TRANSPORT) {
|
|
344
|
+
const transport = process.env.CLAUDE_FLOW_MCP_TRANSPORT as 'stdio' | 'http' | 'websocket';
|
|
345
|
+
if (['stdio', 'http', 'websocket'].includes(transport)) {
|
|
346
|
+
config.mcp = {
|
|
347
|
+
...defaultMcp,
|
|
348
|
+
transport: {
|
|
349
|
+
...defaultMcp.transport,
|
|
350
|
+
type: transport,
|
|
351
|
+
},
|
|
352
|
+
};
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
if (process.env.CLAUDE_FLOW_MCP_PORT) {
|
|
357
|
+
config.mcp = {
|
|
358
|
+
...config.mcp,
|
|
359
|
+
...defaultMcp,
|
|
360
|
+
transport: {
|
|
361
|
+
...config.mcp?.transport,
|
|
362
|
+
...defaultMcp.transport,
|
|
363
|
+
port: parseInt(process.env.CLAUDE_FLOW_MCP_PORT, 10),
|
|
364
|
+
},
|
|
365
|
+
};
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
// Swarm topology
|
|
369
|
+
const defaultSwarm = defaultSystemConfig.swarm ?? { topology: 'hierarchical-mesh' as const, maxAgents: 20 };
|
|
370
|
+
if (process.env.CLAUDE_FLOW_SWARM_TOPOLOGY) {
|
|
371
|
+
const topology = process.env.CLAUDE_FLOW_SWARM_TOPOLOGY as NonNullable<SystemConfig['swarm']>['topology'];
|
|
372
|
+
if (['hierarchical', 'mesh', 'ring', 'star', 'adaptive', 'hierarchical-mesh'].includes(topology)) {
|
|
373
|
+
config.swarm = {
|
|
374
|
+
...defaultSwarm,
|
|
375
|
+
topology,
|
|
376
|
+
};
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
return config;
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
/**
|
|
384
|
+
* Configuration loader class
|
|
385
|
+
*/
|
|
386
|
+
export class ConfigLoader {
|
|
387
|
+
private searchPaths: string[] = [];
|
|
388
|
+
|
|
389
|
+
constructor(additionalPaths?: string[]) {
|
|
390
|
+
// Default search paths
|
|
391
|
+
this.searchPaths = [
|
|
392
|
+
process.cwd(),
|
|
393
|
+
resolve(process.cwd(), '..'),
|
|
394
|
+
resolve(process.env.HOME ?? '', '.claude-flow'),
|
|
395
|
+
];
|
|
396
|
+
|
|
397
|
+
if (additionalPaths) {
|
|
398
|
+
this.searchPaths.push(...additionalPaths);
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
/**
|
|
403
|
+
* Load configuration from all sources
|
|
404
|
+
*/
|
|
405
|
+
async load(): Promise<LoadedConfig> {
|
|
406
|
+
const warnings: string[] = [];
|
|
407
|
+
|
|
408
|
+
// Start with defaults
|
|
409
|
+
let config: SystemConfig = { ...defaultSystemConfig };
|
|
410
|
+
let source: ConfigSource = 'default';
|
|
411
|
+
let path: string | undefined;
|
|
412
|
+
|
|
413
|
+
// Try to load from file
|
|
414
|
+
for (const searchPath of this.searchPaths) {
|
|
415
|
+
const configPath = await findConfigFile(searchPath);
|
|
416
|
+
if (configPath) {
|
|
417
|
+
try {
|
|
418
|
+
const fileConfig = await loadJsonConfig(configPath);
|
|
419
|
+
const validation = validateSystemConfig(fileConfig);
|
|
420
|
+
|
|
421
|
+
if (validation.success) {
|
|
422
|
+
config = mergeWithDefaults(validation.data!, defaultSystemConfig) as SystemConfig;
|
|
423
|
+
source = 'file';
|
|
424
|
+
path = configPath;
|
|
425
|
+
break;
|
|
426
|
+
} else {
|
|
427
|
+
|
|
428
|
+
|
|
429
|
+
--- src/core/config/schema.ts (truncated) ---
|
|
430
|
+
/**
|
|
431
|
+
* V3 Configuration Schemas
|
|
432
|
+
* Zod schemas for all configuration types
|
|
433
|
+
*/
|
|
434
|
+
|
|
435
|
+
import { z } from 'zod';
|
|
436
|
+
|
|
437
|
+
/**
|
|
438
|
+
* Agent configuration schema
|
|
439
|
+
*/
|
|
440
|
+
export const AgentConfigSchema = z.object({
|
|
441
|
+
id: z.string().min(1),
|
|
442
|
+
name: z.string().min(1),
|
|
443
|
+
type: z.string().min(1),
|
|
444
|
+
capabilities: z.array(z.string()).default([]),
|
|
445
|
+
maxConcurrentTasks: z.number().int().min(1).default(5),
|
|
446
|
+
priority: z.number().int().min(0).max(100).default(50),
|
|
447
|
+
timeout: z.number().int().positive().optional(),
|
|
448
|
+
retryPolicy: z.object({
|
|
449
|
+
maxRetries: z.number().int().min(0).default(3),
|
|
450
|
+
backoffMs: z.number().int().positive().default(1000),
|
|
451
|
+
backoffMultiplier: z.number().positive().default(2),
|
|
452
|
+
}).optional(),
|
|
453
|
+
resources: z.object({
|
|
454
|
+
maxMemoryMb: z.number().int().positive().optional(),
|
|
455
|
+
maxCpuPercent: z.number().min(0).max(100).optional(),
|
|
456
|
+
}).optional(),
|
|
457
|
+
metadata: z.record(z.unknown()).optional(),
|
|
458
|
+
});
|
|
459
|
+
|
|
460
|
+
/**
|
|
461
|
+
* Task configuration schema
|
|
462
|
+
*/
|
|
463
|
+
export const TaskConfigSchema = z.object({
|
|
464
|
+
type: z.string().min(1),
|
|
465
|
+
description: z.string().min(1),
|
|
466
|
+
priority: z.number().int().min(0).max(100).default(50),
|
|
467
|
+
timeout: z.number().int().positive().optional(),
|
|
468
|
+
assignedAgent: z.string().optional(),
|
|
469
|
+
input: z.record(z.unknown()).optional(),
|
|
470
|
+
metadata: z.object({
|
|
471
|
+
requiredCapabilities: z.array(z.string()).optional(),
|
|
472
|
+
retryCount: z.number().int().min(0).optional(),
|
|
473
|
+
maxRetries: z.number().int().min(0).optional(),
|
|
474
|
+
critical: z.boolean().optional(),
|
|
475
|
+
parentTaskId: z.string().optional(),
|
|
476
|
+
childTaskIds: z.array(z.string()).optional(),
|
|
477
|
+
tags: z.array(z.string()).optional(),
|
|
478
|
+
}).optional(),
|
|
479
|
+
});
|
|
480
|
+
|
|
481
|
+
/**
|
|
482
|
+
* Swarm configuration schema
|
|
483
|
+
*/
|
|
484
|
+
export const SwarmConfigSchema = z.object({
|
|
485
|
+
topology: z.enum(['hierarchical', 'mesh', 'ring', 'star', 'adaptive', 'hierarchical-mesh']),
|
|
486
|
+
maxAgents: z.number().int().positive().default(20),
|
|
487
|
+
autoScale: z.object({
|
|
488
|
+
enabled: z.boolean().default(false),
|
|
489
|
+
minAgents: z.number().int().min(0).default(1),
|
|
490
|
+
maxAgents: z.number().int().positive().default(20),
|
|
491
|
+
scaleUpThreshold: z.number().min(0).max(1).default(0.8),
|
|
492
|
+
scaleDownThreshold: z.number().min(0).max(1).default(0.3),
|
|
493
|
+
}).optional(),
|
|
494
|
+
coordination: z.object({
|
|
495
|
+
consensusRequired: z.boolean().default(false),
|
|
496
|
+
timeoutMs: z.number().int().positive().default(10000),
|
|
497
|
+
retryPolicy: z.object({
|
|
498
|
+
maxRetries: z.number().int().min(0).default(3),
|
|
499
|
+
backoffMs: z.number().int().positive().default(500),
|
|
500
|
+
}),
|
|
501
|
+
}).optional(),
|
|
502
|
+
communication: z.object({
|
|
503
|
+
protocol: z.enum(['events', 'messages', 'shared-memory']).default('events'),
|
|
504
|
+
batchSize: z.number().int().positive().default(10),
|
|
505
|
+
flushIntervalMs: z.number().int().positive().default(100),
|
|
506
|
+
}).optional(),
|
|
507
|
+
metadata: z.record(z.unknown()).optional(),
|
|
508
|
+
});
|
|
509
|
+
|
|
510
|
+
/**
|
|
511
|
+
* Memory configuration schema
|
|
512
|
+
*/
|
|
513
|
+
export const MemoryConfigSchema = z.object({
|
|
514
|
+
type: z.enum(['sqlite', 'agentdb', 'hybrid', 'redis', 'memory']).default('hybrid'),
|
|
515
|
+
path: z.string().optional(),
|
|
516
|
+
maxSize: z.number().int().positive().optional(),
|
|
517
|
+
ttlMs: z.number().int().positive().optional(),
|
|
518
|
+
sqlite: z.object({
|
|
519
|
+
filename: z.string().optional(),
|
|
520
|
+
inMemory: z.boolean().default(false),
|
|
521
|
+
wal: z.boolean().default(true),
|
|
522
|
+
}).optional(),
|
|
523
|
+
agentdb: z.object({
|
|
524
|
+
dimensions: z.number().int().positive().default(1536),
|
|
525
|
+
indexType: z.enum(['hnsw', 'flat', 'ivf']).default('hnsw'),
|
|
526
|
+
efConstruction: z.number().int().positive().default(200),
|
|
527
|
+
m: z.number().int().positive().default(16),
|
|
528
|
+
quantization: z.enum(['none', 'scalar', 'product']).default('none'),
|
|
529
|
+
}).optional(),
|
|
530
|
+
redis: z.object({
|
|
531
|
+
host: z.string().default('localhost'),
|
|
532
|
+
port: z.number().int().positive().default(6379),
|
|
533
|
+
password: z.string().optional(),
|
|
534
|
+
db: z.number().int().min(0).default(0),
|
|
535
|
+
keyPrefix: z.string().default('claude-flow:'),
|
|
536
|
+
}).optional(),
|
|
537
|
+
hybrid: z.object({
|
|
538
|
+
vectorThreshold: z.number().int().positive().default(100),
|
|
539
|
+
}).optional(),
|
|
540
|
+
});
|
|
541
|
+
|
|
542
|
+
/**
|
|
543
|
+
* MCP server configuration schema
|
|
544
|
+
*/
|
|
545
|
+
export const MCPServerConfigSchema = z.object({
|
|
546
|
+
name: z.string().min(1).default('claude-flow'),
|
|
547
|
+
version: z.string().min(1).default('3.0.0'),
|
|
548
|
+
transport: z.object({
|
|
549
|
+
type: z.enum(['stdio', 'http', 'websocket']).default('stdio'),
|
|
550
|
+
port: z.number().int().positive().optional(),
|
|
551
|
+
host: z.string().optional(),
|
|
552
|
+
path: z.string().optional(),
|
|
553
|
+
}),
|
|
554
|
+
capabilities: z.object({
|
|
555
|
+
tools: z.boolean().default(true),
|
|
556
|
+
resources: z.boolean().default(true),
|
|
557
|
+
prompts: z.boolean().default(true),
|
|
558
|
+
logging: z.boolean().default(true),
|
|
559
|
+
experimental: z.record(z.boolean()).optional(),
|
|
560
|
+
}).optional(),
|
|
561
|
+
});
|
|
562
|
+
|
|
563
|
+
/**
|
|
564
|
+
* Orchestrator configuration schema
|
|
565
|
+
*/
|
|
566
|
+
export const OrchestratorConfigSchema = z.object({
|
|
567
|
+
session: z.object({
|
|
568
|
+
persistSessions: z.boolean().default(true),
|
|
569
|
+
dataDir: z.string().default('./data'),
|
|
570
|
+
sessionRetentionMs: z.number().int().positive().default(3600000),
|
|
571
|
+
}),
|
|
572
|
+
health: z.object({
|
|
573
|
+
checkInterval: z.number().int().positive().default(30000),
|
|
574
|
+
historyLimit: z.number().int().positive()
|
|
575
|
+
|
|
576
|
+
--- src/core/config/validator.ts ---
|
|
577
|
+
/**
|
|
578
|
+
* V3 Configuration Validator
|
|
579
|
+
* Validation logic using Zod schemas
|
|
580
|
+
*/
|
|
581
|
+
|
|
582
|
+
import { z, type ZodError } from 'zod';
|
|
583
|
+
import {
|
|
584
|
+
AgentConfigSchema,
|
|
585
|
+
TaskConfigSchema,
|
|
586
|
+
SwarmConfigSchema,
|
|
587
|
+
MemoryConfigSchema,
|
|
588
|
+
MCPServerConfigSchema,
|
|
589
|
+
OrchestratorConfigSchema,
|
|
590
|
+
SystemConfigSchema,
|
|
591
|
+
type AgentConfig,
|
|
592
|
+
type TaskConfig,
|
|
593
|
+
type SwarmConfig,
|
|
594
|
+
type MemoryConfig,
|
|
595
|
+
type MCPServerConfig,
|
|
596
|
+
type OrchestratorConfig,
|
|
597
|
+
type SystemConfig,
|
|
598
|
+
} from './schema.js';
|
|
599
|
+
|
|
600
|
+
/**
|
|
601
|
+
* Validation result
|
|
602
|
+
*/
|
|
603
|
+
export interface ValidationResult<T> {
|
|
604
|
+
success: boolean;
|
|
605
|
+
data?: T;
|
|
606
|
+
errors?: ValidationError[];
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
/**
|
|
610
|
+
* Validation error
|
|
611
|
+
*/
|
|
612
|
+
export interface ValidationError {
|
|
613
|
+
path: string;
|
|
614
|
+
message: string;
|
|
615
|
+
code: string;
|
|
616
|
+
}
|
|
617
|
+
|
|
618
|
+
/**
|
|
619
|
+
* Convert Zod error to validation errors
|
|
620
|
+
*/
|
|
621
|
+
function zodErrorToValidationErrors(error: ZodError): ValidationError[] {
|
|
622
|
+
return error.errors.map((e) => ({
|
|
623
|
+
path: e.path.join('.'),
|
|
624
|
+
message: e.message,
|
|
625
|
+
code: e.code,
|
|
626
|
+
}));
|
|
627
|
+
}
|
|
628
|
+
|
|
629
|
+
/**
|
|
630
|
+
* Generic validation function
|
|
631
|
+
* Uses parse + try/catch to get output types with defaults applied
|
|
632
|
+
*/
|
|
633
|
+
function validate<TInput, TOutput>(
|
|
634
|
+
schema: z.ZodType<TOutput, z.ZodTypeDef, TInput>,
|
|
635
|
+
data: unknown
|
|
636
|
+
): ValidationResult<TOutput> {
|
|
637
|
+
try {
|
|
638
|
+
const parsed = schema.parse(data);
|
|
639
|
+
return {
|
|
640
|
+
success: true,
|
|
641
|
+
data: parsed,
|
|
642
|
+
};
|
|
643
|
+
} catch (error) {
|
|
644
|
+
if (error instanceof z.ZodError) {
|
|
645
|
+
return {
|
|
646
|
+
success: false,
|
|
647
|
+
errors: zodErrorToValidationErrors(error),
|
|
648
|
+
};
|
|
649
|
+
}
|
|
650
|
+
throw error;
|
|
651
|
+
}
|
|
652
|
+
}
|
|
653
|
+
|
|
654
|
+
/**
|
|
655
|
+
* Validate agent configuration
|
|
656
|
+
*/
|
|
657
|
+
export function validateAgentConfig(data: unknown): ValidationResult<AgentConfig> {
|
|
658
|
+
return validate(AgentConfigSchema, data);
|
|
659
|
+
}
|
|
660
|
+
|
|
661
|
+
/**
|
|
662
|
+
* Validate task configuration
|
|
663
|
+
*/
|
|
664
|
+
export function validateTaskConfig(data: unknown): ValidationResult<TaskConfig> {
|
|
665
|
+
return validate(TaskConfigSchema, data);
|
|
666
|
+
}
|
|
667
|
+
|
|
668
|
+
/**
|
|
669
|
+
* Validate swarm configuration
|
|
670
|
+
*/
|
|
671
|
+
export function validateSwarmConfig(data: unknown): ValidationResult<SwarmConfig> {
|
|
672
|
+
return validate(SwarmConfigSchema, data);
|
|
673
|
+
}
|
|
674
|
+
|
|
675
|
+
/**
|
|
676
|
+
* Validate memory configuration
|
|
677
|
+
*/
|
|
678
|
+
export function validateMemoryConfig(data: unknown): ValidationResult<MemoryConfig> {
|
|
679
|
+
return validate(MemoryConfigSchema, data);
|
|
680
|
+
}
|
|
681
|
+
|
|
682
|
+
/**
|
|
683
|
+
* Validate MCP server configuration
|
|
684
|
+
*/
|
|
685
|
+
export function validateMCPServerConfig(data: unknown): ValidationResult<MCPServerConfig> {
|
|
686
|
+
return validate(MCPServerConfigSchema, data);
|
|
687
|
+
}
|
|
688
|
+
|
|
689
|
+
/**
|
|
690
|
+
* Validate orchestrator configuration
|
|
691
|
+
*/
|
|
692
|
+
export function validateOrchestratorConfig(data: unknown): ValidationResult<OrchestratorConfig> {
|
|
693
|
+
return validate(OrchestratorConfigSchema, data);
|
|
694
|
+
}
|
|
695
|
+
|
|
696
|
+
/**
|
|
697
|
+
* Validate full system configuration
|
|
698
|
+
*/
|
|
699
|
+
export function validateSystemConfig(data: unknown): ValidationResult<SystemConfig> {
|
|
700
|
+
return validate(SystemConfigSchema, data);
|
|
701
|
+
}
|
|
702
|
+
|
|
703
|
+
/**
|
|
704
|
+
* Configuration validator class
|
|
705
|
+
*/
|
|
706
|
+
export class ConfigValidator {
|
|
707
|
+
/**
|
|
708
|
+
* Validate and throw on error
|
|
709
|
+
*/
|
|
710
|
+
static validateOrThrow<TInput, TOutput>(
|
|
711
|
+
schema: z.ZodType<TOutput, z.ZodTypeDef, TInput>,
|
|
712
|
+
data: unknown,
|
|
713
|
+
configName: string
|
|
714
|
+
): TOutput {
|
|
715
|
+
const result = validate(schema, data);
|
|
716
|
+
|
|
717
|
+
if (!result.success) {
|
|
718
|
+
const errorMessages = result.errors
|
|
719
|
+
?.map((e) => ` - ${e.path}: ${e.message}`)
|
|
720
|
+
.join('\n');
|
|
721
|
+
throw new Error(`Invalid ${configName} configuration:\n${errorMessages}`);
|
|
722
|
+
}
|
|
723
|
+
|
|
724
|
+
return result.data!;
|
|
725
|
+
}
|
|
726
|
+
|
|
727
|
+
/**
|
|
728
|
+
* Validate agent config or throw
|
|
729
|
+
*/
|
|
730
|
+
static validateAgentOrThrow(data: unknown): AgentConfig {
|
|
731
|
+
return this.validateOrThrow(AgentConfigSchema, data, 'agent');
|
|
732
|
+
}
|
|
733
|
+
|
|
734
|
+
/**
|
|
735
|
+
* Validate task config or throw
|
|
736
|
+
*/
|
|
737
|
+
static validateTaskOrThrow(data: unknown): TaskConfig {
|
|
738
|
+
return this.validateOrThrow(TaskConfigSchema, data, 'task');
|
|
739
|
+
}
|
|
740
|
+
|
|
741
|
+
/**
|
|
742
|
+
* Validate swarm config or throw
|
|
743
|
+
*/
|
|
744
|
+
static validateSwarmOrThrow(data: unknown): SwarmConfig {
|
|
745
|
+
return this.validateOrThrow(SwarmConfigSchema, data, 'swarm');
|
|
746
|
+
}
|
|
747
|
+
|
|
748
|
+
/**
|
|
749
|
+
* Validate memory config or throw
|
|
750
|
+
*/
|
|
751
|
+
static validateMemoryOrThrow(data: unknown): MemoryConfig {
|
|
752
|
+
return this.validateOrThrow(MemoryConfigSchema, data, 'memory');
|
|
753
|
+
}
|
|
754
|
+
|
|
755
|
+
/**
|
|
756
|
+
* Validate MCP server config or throw
|
|
757
|
+
*/
|
|
758
|
+
static validateMCPServerOrThrow(data: unknown): MCPServerConfig {
|
|
759
|
+
return this.validateOrThrow(MCPServerConfigSchema, data, 'MCP server');
|
|
760
|
+
}
|
|
761
|
+
|
|
762
|
+
/**
|
|
763
|
+
* Validate orchestrator config or throw
|
|
764
|
+
*/
|
|
765
|
+
static validateOrchestratorOrThrow(data: unknown): OrchestratorConfig {
|
|
766
|
+
return this.validateOrThrow(OrchestratorConfigSchema, data, 'orchestrator');
|
|
767
|
+
}
|
|
768
|
+
|
|
769
|
+
/**
|
|
770
|
+
* Validate system config or throw
|
|
771
|
+
*/
|
|
772
|
+
static validateSystemOrThrow(data: unknown): SystemConfig {
|
|
773
|
+
return this.validateOrThrow(SystemConfigSchema, data, 'system');
|
|
774
|
+
}
|
|
775
|
+
|
|
776
|
+
/**
|
|
777
|
+
* Check if data matches schema
|
|
778
|
+
*/
|
|
779
|
+
static isValid<TInput, TOutput>(
|
|
780
|
+
schema: z.ZodType<TOutput, z.ZodTypeDef, TInput>,
|
|
781
|
+
data: unknown
|
|
782
|
+
): boolean {
|
|
783
|
+
return validate(schema, data).success;
|
|
784
|
+
}
|
|
785
|
+
}
|
|
786
|
+
|
|
787
|
+
|
|
788
|
+
--- src/core/event-bus.ts (truncated) ---
|
|
789
|
+
/**
|
|
790
|
+
* V3 Event Bus
|
|
791
|
+
* Core event pub/sub implementation
|
|
792
|
+
*/
|
|
793
|
+
|
|
794
|
+
import type {
|
|
795
|
+
IEvent,
|
|
796
|
+
IEventBus,
|
|
797
|
+
IEventCreate,
|
|
798
|
+
IEventHandler,
|
|
799
|
+
IEventSubscription,
|
|
800
|
+
IEventFilter,
|
|
801
|
+
} from './interfaces/event.interface.js';
|
|
802
|
+
import { randomBytes } from 'crypto';
|
|
803
|
+
|
|
804
|
+
// Secure event ID generation
|
|
805
|
+
function generateSecureEventId(): string {
|
|
806
|
+
const timestamp = Date.now().toString(36);
|
|
807
|
+
const random = randomBytes(12).toString('hex');
|
|
808
|
+
return `evt_${timestamp}_${random}`;
|
|
809
|
+
}
|
|
810
|
+
|
|
811
|
+
/**
|
|
812
|
+
* Event subscription implementation
|
|
813
|
+
*/
|
|
814
|
+
class EventSubscription implements IEventSubscription {
|
|
815
|
+
private active = true;
|
|
816
|
+
private paused = false;
|
|
817
|
+
|
|
818
|
+
constructor(
|
|
819
|
+
readonly id: string,
|
|
820
|
+
readonly filter: IEventFilter,
|
|
821
|
+
private removeCallback: () => void,
|
|
822
|
+
) {}
|
|
823
|
+
|
|
824
|
+
unsubscribe(): void {
|
|
825
|
+
this.active = false;
|
|
826
|
+
this.removeCallback();
|
|
827
|
+
}
|
|
828
|
+
|
|
829
|
+
pause(): void {
|
|
830
|
+
this.paused = true;
|
|
831
|
+
}
|
|
832
|
+
|
|
833
|
+
resume(): void {
|
|
834
|
+
this.paused = false;
|
|
835
|
+
}
|
|
836
|
+
|
|
837
|
+
isActive(): boolean {
|
|
838
|
+
return this.active && !this.paused;
|
|
839
|
+
}
|
|
840
|
+
}
|
|
841
|
+
|
|
842
|
+
/**
|
|
843
|
+
* Event bus implementation
|
|
844
|
+
*/
|
|
845
|
+
export class EventBus implements IEventBus {
|
|
846
|
+
private handlers = new Map<string, Set<IEventHandler>>();
|
|
847
|
+
private subscriptions = new Map<string, { filter: IEventFilter; handler: IEventHandler; subscription: EventSubscription }>();
|
|
848
|
+
private subscriptionId = 0;
|
|
849
|
+
|
|
850
|
+
emit<T = unknown>(type: string, payload: T, options?: Partial<IEventCreate<T>>): void {
|
|
851
|
+
const event = this.createEvent(type, payload, options);
|
|
852
|
+
this.dispatchEvent(event);
|
|
853
|
+
}
|
|
854
|
+
|
|
855
|
+
async emitAsync<T = unknown>(type: string, payload: T, options?: Partial<IEventCreate<T>>): Promise<void> {
|
|
856
|
+
const event = this.createEvent(type, payload, options);
|
|
857
|
+
await this.dispatchEventAsync(event);
|
|
858
|
+
}
|
|
859
|
+
|
|
860
|
+
on<T = unknown>(type: string, handler: IEventHandler<T>): IEventSubscription {
|
|
861
|
+
return this.subscribe({ types: [type] }, handler);
|
|
862
|
+
}
|
|
863
|
+
|
|
864
|
+
subscribe<T = unknown>(filter: IEventFilter, handler: IEventHandler<T>): IEventSubscription {
|
|
865
|
+
const id = `sub_${++this.subscriptionId}`;
|
|
866
|
+
|
|
867
|
+
// Register for all matching types
|
|
868
|
+
const types = filter.types ?? ['*'];
|
|
869
|
+
for (const type of types) {
|
|
870
|
+
let handlers = this.handlers.get(type);
|
|
871
|
+
if (!handlers) {
|
|
872
|
+
handlers = new Set();
|
|
873
|
+
this.handlers.set(type, handlers);
|
|
874
|
+
}
|
|
875
|
+
handlers.add(handler as IEventHandler);
|
|
876
|
+
}
|
|
877
|
+
|
|
878
|
+
const subscription = new EventSubscription(id, filter, () => {
|
|
879
|
+
this.removeSubscription(id);
|
|
880
|
+
});
|
|
881
|
+
|
|
882
|
+
this.subscriptions.set(id, { filter, handler: handler as IEventHandler, subscription });
|
|
883
|
+
|
|
884
|
+
return subscription;
|
|
885
|
+
}
|
|
886
|
+
|
|
887
|
+
once<T = unknown>(type: string, handler: IEventHandler<T>): IEventSubscription {
|
|
888
|
+
const wrappedHandler: IEventHandler<T> = async (event) => {
|
|
889
|
+
subscription.unsubscribe();
|
|
890
|
+
await handler(event);
|
|
891
|
+
};
|
|
892
|
+
|
|
893
|
+
const subscription = this.on(type, wrappedHandler);
|
|
894
|
+
return subscription;
|
|
895
|
+
}
|
|
896
|
+
|
|
897
|
+
off(type: string, handler: IEventHandler): void {
|
|
898
|
+
const handlers = this.handlers.get(type);
|
|
899
|
+
if (handlers) {
|
|
900
|
+
handlers.delete(handler);
|
|
901
|
+
if (handlers.size === 0) {
|
|
902
|
+
this.handlers.delete(type);
|
|
903
|
+
}
|
|
904
|
+
}
|
|
905
|
+
}
|
|
906
|
+
|
|
907
|
+
removeAllListeners(type?: string): void {
|
|
908
|
+
if (type) {
|
|
909
|
+
this.handlers.delete(type);
|
|
910
|
+
} else {
|
|
911
|
+
this.handlers.clear();
|
|
912
|
+
}
|
|
913
|
+
}
|
|
914
|
+
|
|
915
|
+
listenerCount(type: string): number {
|
|
916
|
+
return this.handlers.get(type)?.size ?? 0;
|
|
917
|
+
}
|
|
918
|
+
|
|
919
|
+
eventNames(): string[] {
|
|
920
|
+
return Array.from(this.handlers.keys());
|
|
921
|
+
}
|
|
922
|
+
|
|
923
|
+
private createEvent<T>(type: string, payload: T, options?: Partial<IEventCreate<T>>): IEvent<T> {
|
|
924
|
+
return {
|
|
925
|
+
id: generateSecureEventId(),
|
|
926
|
+
type,
|
|
927
|
+
timestamp: new Date(),
|
|
928
|
+
source: options?.source ?? 'event-bus',
|
|
929
|
+
payload,
|
|
930
|
+
priority: options?.priority,
|
|
931
|
+
correlationId: options?.correlationId,
|
|
932
|
+
causationId: options?.causationId,
|
|
933
|
+
metadata: options?.metadata,
|
|
934
|
+
};
|
|
935
|
+
}
|
|
936
|
+
|
|
937
|
+
private dispatchEvent<T>(event: IEvent<T>): void {
|
|
938
|
+
// Get handlers for specific type
|
|
939
|
+
const typeHandlers = this.handlers.get(event.type);
|
|
940
|
+
|
|
941
|
+
// Get wildcard handlers
|
|
942
|
+
const wildcardHandlers = this.handlers.get('*');
|
|
943
|
+
|
|
944
|
+
const allHandlers = new Set<IEventHandler>();
|
|
945
|
+
|
|
946
|
+
if (typeHandlers) {
|
|
947
|
+
for (const handler of typeHandlers) {
|
|
948
|
+
allHandlers.add(handler);
|
|
949
|
+
}
|
|
950
|
+
}
|
|
951
|
+
|
|
952
|
+
if (wildcardHandlers) {
|
|
953
|
+
for (const handler of wildcardHandlers) {
|
|
954
|
+
allHandlers.add(handler);
|
|
955
|
+
}
|
|
956
|
+
}
|
|
957
|
+
|
|
958
|
+
for (const handler of allHandlers) {
|
|
959
|
+
try {
|
|
960
|
+
const result = handler(event);
|
|
961
|
+
if (result instanceof Promise) {
|
|
962
|
+
result.catch((error) => {
|
|
963
|
+
console.error(`Error in async event handler for ${event.type}:`, error);
|
|
964
|
+
});
|
|
965
|
+
}
|
|
966
|
+
} catch (error) {
|
|
967
|
+
console.error(`Error in event handler for ${event.type}:`, error);
|
|
968
|
+
}
|
|
969
|
+
}
|
|
970
|
+
}
|
|
971
|
+
|
|
972
|
+
private async dispatchEventAsync<T>(event: IEvent<T>): Promise<void> {
|
|
973
|
+
const typeHandlers = this.handlers.get(event.type);
|
|
974
|
+
const wildcardHandlers = this.handlers.get('*');
|
|
975
|
+
|
|
976
|
+
const allHandlers = new Set<IEventHandler>();
|
|
977
|
+
|
|
978
|
+
if (typeHandlers) {
|
|
979
|
+
for (const handler
|
|
980
|
+
|
|
981
|
+
--- src/core/index.ts ---
|
|
982
|
+
/**
|
|
983
|
+
* V3 Core Module - Public API
|
|
984
|
+
* Domain-Driven Design with Clean Architecture
|
|
985
|
+
*
|
|
986
|
+
* This module provides the core architecture for claude-flow v3:
|
|
987
|
+
* - Decomposed orchestrator (task, session, health, lifecycle management)
|
|
988
|
+
* - Event-driven architecture with event bus and coordinator
|
|
989
|
+
* - Type-safe configuration with Zod validation
|
|
990
|
+
* - Clean interfaces following DDD principles
|
|
991
|
+
*/
|
|
992
|
+
|
|
993
|
+
// Interfaces (Domain contracts)
|
|
994
|
+
export * from './interfaces/index.js';
|
|
995
|
+
|
|
996
|
+
// Event system
|
|
997
|
+
export { EventBus, createEventBus } from './event-bus.js';
|
|
998
|
+
|
|
999
|
+
// Orchestrator components (decomposed)
|
|
1000
|
+
export * from './orchestrator/index.js';
|
|
1001
|
+
|
|
1002
|
+
// Configuration
|
|
1003
|
+
export * from './config/index.js';
|
|
1004
|
+
|
|
1005
|
+
|
|
1006
|
+
--- src/core/interfaces/agent.interface.ts ---
|
|
1007
|
+
/**
|
|
1008
|
+
* V3 Agent Interfaces
|
|
1009
|
+
* Domain-Driven Design - Agent Lifecycle Bounded Context
|
|
1010
|
+
*/
|
|
1011
|
+
|
|
1012
|
+
/**
|
|
1013
|
+
* Agent status in the system
|
|
1014
|
+
*/
|
|
1015
|
+
export type AgentStatus = 'spawning' | 'active' | 'idle' | 'busy' | 'error' | 'terminated';
|
|
1016
|
+
|
|
1017
|
+
/**
|
|
1018
|
+
* Agent type classification
|
|
1019
|
+
*/
|
|
1020
|
+
export type AgentType =
|
|
1021
|
+
| 'coder'
|
|
1022
|
+
| 'reviewer'
|
|
1023
|
+
| 'tester'
|
|
1024
|
+
| 'researcher'
|
|
1025
|
+
| 'planner'
|
|
1026
|
+
| 'architect'
|
|
1027
|
+
| 'coordinator'
|
|
1028
|
+
| 'security'
|
|
1029
|
+
| 'performance'
|
|
1030
|
+
| 'custom';
|
|
1031
|
+
|
|
1032
|
+
/**
|
|
1033
|
+
* Agent capability declaration
|
|
1034
|
+
*/
|
|
1035
|
+
export interface IAgentCapability {
|
|
1036
|
+
name: string;
|
|
1037
|
+
level: 'basic' | 'intermediate' | 'advanced' | 'expert';
|
|
1038
|
+
description?: string;
|
|
1039
|
+
}
|
|
1040
|
+
|
|
1041
|
+
/**
|
|
1042
|
+
* Agent configuration for spawning
|
|
1043
|
+
*/
|
|
1044
|
+
export interface IAgentConfig {
|
|
1045
|
+
readonly id: string;
|
|
1046
|
+
readonly name: string;
|
|
1047
|
+
readonly type: AgentType | string;
|
|
1048
|
+
|
|
1049
|
+
capabilities: string[];
|
|
1050
|
+
maxConcurrentTasks: number;
|
|
1051
|
+
priority: number;
|
|
1052
|
+
|
|
1053
|
+
timeout?: number;
|
|
1054
|
+
retryPolicy?: {
|
|
1055
|
+
maxRetries: number;
|
|
1056
|
+
backoffMs: number;
|
|
1057
|
+
backoffMultiplier: number;
|
|
1058
|
+
};
|
|
1059
|
+
|
|
1060
|
+
resources?: {
|
|
1061
|
+
maxMemoryMb?: number;
|
|
1062
|
+
maxCpuPercent?: number;
|
|
1063
|
+
};
|
|
1064
|
+
|
|
1065
|
+
metadata?: Record<string, unknown>;
|
|
1066
|
+
}
|
|
1067
|
+
|
|
1068
|
+
/**
|
|
1069
|
+
* Core agent entity
|
|
1070
|
+
*/
|
|
1071
|
+
export interface IAgent {
|
|
1072
|
+
readonly id: string;
|
|
1073
|
+
readonly name: string;
|
|
1074
|
+
readonly type: AgentType | string;
|
|
1075
|
+
readonly config: IAgentConfig;
|
|
1076
|
+
readonly createdAt: Date;
|
|
1077
|
+
|
|
1078
|
+
status: AgentStatus;
|
|
1079
|
+
currentTaskCount: number;
|
|
1080
|
+
lastActivity: Date;
|
|
1081
|
+
|
|
1082
|
+
sessionId?: string;
|
|
1083
|
+
terminalId?: string;
|
|
1084
|
+
memoryBankId?: string;
|
|
1085
|
+
|
|
1086
|
+
metrics?: {
|
|
1087
|
+
tasksCompleted: number;
|
|
1088
|
+
tasksFailed: number;
|
|
1089
|
+
avgTaskDuration: number;
|
|
1090
|
+
errorCount: number;
|
|
1091
|
+
uptime: number;
|
|
1092
|
+
};
|
|
1093
|
+
|
|
1094
|
+
health?: {
|
|
1095
|
+
status: 'healthy' | 'degraded' | 'unhealthy';
|
|
1096
|
+
lastCheck: Date;
|
|
1097
|
+
issues?: string[];
|
|
1098
|
+
};
|
|
1099
|
+
}
|
|
1100
|
+
|
|
1101
|
+
/**
|
|
1102
|
+
* Agent session for tracking active work
|
|
1103
|
+
*/
|
|
1104
|
+
export interface IAgentSession {
|
|
1105
|
+
readonly id: string;
|
|
1106
|
+
readonly agentId: string;
|
|
1107
|
+
readonly startTime: Date;
|
|
1108
|
+
|
|
1109
|
+
status: 'active' | 'idle' | 'terminated';
|
|
1110
|
+
terminalId: string;
|
|
1111
|
+
memoryBankId: string;
|
|
1112
|
+
|
|
1113
|
+
lastActivity: Date;
|
|
1114
|
+
endTime?: Date;
|
|
1115
|
+
|
|
1116
|
+
metadata?: Record<string, unknown>;
|
|
1117
|
+
}
|
|
1118
|
+
|
|
1119
|
+
/**
|
|
1120
|
+
* Agent pool for managing multiple agents
|
|
1121
|
+
*/
|
|
1122
|
+
export interface IAgentPool {
|
|
1123
|
+
/**
|
|
1124
|
+
* Add an agent to the pool
|
|
1125
|
+
*/
|
|
1126
|
+
add(agent: IAgent): void;
|
|
1127
|
+
|
|
1128
|
+
/**
|
|
1129
|
+
* Remove an agent from the pool
|
|
1130
|
+
*/
|
|
1131
|
+
remove(agentId: string): boolean;
|
|
1132
|
+
|
|
1133
|
+
/**
|
|
1134
|
+
* Get an agent by ID
|
|
1135
|
+
*/
|
|
1136
|
+
get(agentId: string): IAgent | undefined;
|
|
1137
|
+
|
|
1138
|
+
/**
|
|
1139
|
+
* Get all agents in the pool
|
|
1140
|
+
*/
|
|
1141
|
+
getAll(): IAgent[];
|
|
1142
|
+
|
|
1143
|
+
/**
|
|
1144
|
+
* Get agents by status
|
|
1145
|
+
*/
|
|
1146
|
+
getByStatus(status: AgentStatus): IAgent[];
|
|
1147
|
+
|
|
1148
|
+
/**
|
|
1149
|
+
* Get agents by type
|
|
1150
|
+
*/
|
|
1151
|
+
getByType(type: AgentType | string): IAgent[];
|
|
1152
|
+
|
|
1153
|
+
/**
|
|
1154
|
+
* Get available agents (can accept more tasks)
|
|
1155
|
+
*/
|
|
1156
|
+
getAvailable(): IAgent[];
|
|
1157
|
+
|
|
1158
|
+
/**
|
|
1159
|
+
* Get pool size
|
|
1160
|
+
*/
|
|
1161
|
+
size(): number;
|
|
1162
|
+
|
|
1163
|
+
/**
|
|
1164
|
+
* Check if pool has capacity
|
|
1165
|
+
*/
|
|
1166
|
+
hasCapacity(maxSize: number): boolean;
|
|
1167
|
+
|
|
1168
|
+
/**
|
|
1169
|
+
* Clear all agents
|
|
1170
|
+
*/
|
|
1171
|
+
clear(): void;
|
|
1172
|
+
}
|
|
1173
|
+
|
|
1174
|
+
/**
|
|
1175
|
+
* Agent lifecycle manager interface
|
|
1176
|
+
*/
|
|
1177
|
+
export interface IAgentLifecycleManager {
|
|
1178
|
+
/**
|
|
1179
|
+
* Spawn a new agent
|
|
1180
|
+
*/
|
|
1181
|
+
spawn(config: IAgentConfig): Promise<IAgent>;
|
|
1182
|
+
|
|
1183
|
+
/**
|
|
1184
|
+
* Spawn multiple agents in parallel
|
|
1185
|
+
*/
|
|
1186
|
+
spawnBatch(configs: IAgentConfig[]): Promise<Map<string, IAgent>>;
|
|
1187
|
+
|
|
1188
|
+
/**
|
|
1189
|
+
* Terminate an agent
|
|
1190
|
+
*/
|
|
1191
|
+
terminate(agentId: string, reason?: string): Promise<void>;
|
|
1192
|
+
|
|
1193
|
+
/**
|
|
1194
|
+
* Terminate all agents
|
|
1195
|
+
*/
|
|
1196
|
+
terminateAll(reason?: string): Promise<void>;
|
|
1197
|
+
|
|
1198
|
+
/**
|
|
1199
|
+
* Restart an agent
|
|
1200
|
+
*/
|
|
1201
|
+
restart(agentId: string): Promise<IAgent>;
|
|
1202
|
+
|
|
1203
|
+
/**
|
|
1204
|
+
* Update agent configuration
|
|
1205
|
+
*/
|
|
1206
|
+
updateConfig(agentId: string, config: Partial<IAgentConfig>): Promise<void>;
|
|
1207
|
+
|
|
1208
|
+
/**
|
|
1209
|
+
* Get agent by ID
|
|
1210
|
+
*/
|
|
1211
|
+
getAgent(agentId: string): IAgent | undefined;
|
|
1212
|
+
|
|
1213
|
+
/**
|
|
1214
|
+
* Get all agents
|
|
1215
|
+
*/
|
|
1216
|
+
getAllAgents(): IAgent[];
|
|
1217
|
+
|
|
1218
|
+
/**
|
|
1219
|
+
* Get active agents count
|
|
1220
|
+
*/
|
|
1221
|
+
getActiveCount(): number;
|
|
1222
|
+
|
|
1223
|
+
/**
|
|
1224
|
+
* Check agent health
|
|
1225
|
+
*/
|
|
1226
|
+
checkHealth(agentId: string): Promise<IAgent['health']>;
|
|
1227
|
+
}
|
|
1228
|
+
|
|
1229
|
+
/**
|
|
1230
|
+
* Agent registry for type definitions
|
|
1231
|
+
*/
|
|
1232
|
+
export interface IAgentRegistry {
|
|
1233
|
+
/**
|
|
1234
|
+
* Register an agent type with default config
|
|
1235
|
+
*/
|
|
1236
|
+
register(type: string, defaultConfig: Partial<IAgentConfig>): void;
|
|
1237
|
+
|
|
1238
|
+
/**
|
|
1239
|
+
* Unregister an agent type
|
|
1240
|
+
*/
|
|
1241
|
+
unregister(type: string): boolean;
|
|
1242
|
+
|
|
1243
|
+
/**
|
|
1244
|
+
* Get default config for a type
|
|
1245
|
+
*/
|
|
1246
|
+
getDefaultConfig(type: string): Partial<IAgentConfig> | undefined;
|
|
1247
|
+
|
|
1248
|
+
/**
|
|
1249
|
+
* Get all registered types
|
|
1250
|
+
*/
|
|
1251
|
+
getRegisteredTypes(): string[];
|
|
1252
|
+
|
|
1253
|
+
/**
|
|
1254
|
+
* Check if a type is registered
|
|
1255
|
+
*/
|
|
1256
|
+
isRegistered(type: string): boolean;
|
|
1257
|
+
}
|
|
1258
|
+
|
|
1259
|
+
|
|
1260
|
+
--- src/core/interfaces/coordinator.interface.ts (truncated) ---
|
|
1261
|
+
/**
|
|
1262
|
+
* V3 Coordinator Interfaces
|
|
1263
|
+
* Domain-Driven Design - Coordination Bounded Context
|
|
1264
|
+
* Aligned with ADR-003 (Single Coordination Engine)
|
|
1265
|
+
*/
|
|
1266
|
+
|
|
1267
|
+
import type { ITask, ITaskResult } from './task.interface.js';
|
|
1268
|
+
import type { IAgent, IAgentConfig } from './agent.interface.js';
|
|
1269
|
+
|
|
1270
|
+
/**
|
|
1271
|
+
* Swarm topology types
|
|
1272
|
+
*/
|
|
1273
|
+
export type SwarmTopology =
|
|
1274
|
+
| 'hierarchical'
|
|
1275
|
+
| 'mesh'
|
|
1276
|
+
| 'ring'
|
|
1277
|
+
| 'star'
|
|
1278
|
+
| 'adaptive'
|
|
1279
|
+
| 'hierarchical-mesh';
|
|
1280
|
+
|
|
1281
|
+
/**
|
|
1282
|
+
* Coordination status
|
|
1283
|
+
*/
|
|
1284
|
+
export type CoordinationStatus =
|
|
1285
|
+
| 'initializing'
|
|
1286
|
+
| 'ready'
|
|
1287
|
+
| 'coordinating'
|
|
1288
|
+
| 'degraded'
|
|
1289
|
+
| 'error'
|
|
1290
|
+
| 'shutdown';
|
|
1291
|
+
|
|
1292
|
+
/**
|
|
1293
|
+
* Swarm configuration
|
|
1294
|
+
*/
|
|
1295
|
+
export interface ISwarmConfig {
|
|
1296
|
+
topology: SwarmTopology;
|
|
1297
|
+
maxAgents: number;
|
|
1298
|
+
|
|
1299
|
+
autoScale?: {
|
|
1300
|
+
enabled: boolean;
|
|
1301
|
+
minAgents: number;
|
|
1302
|
+
maxAgents: number;
|
|
1303
|
+
scaleUpThreshold: number;
|
|
1304
|
+
scaleDownThreshold: number;
|
|
1305
|
+
};
|
|
1306
|
+
|
|
1307
|
+
coordination?: {
|
|
1308
|
+
consensusRequired: boolean;
|
|
1309
|
+
timeoutMs: number;
|
|
1310
|
+
retryPolicy: {
|
|
1311
|
+
maxRetries: number;
|
|
1312
|
+
backoffMs: number;
|
|
1313
|
+
};
|
|
1314
|
+
};
|
|
1315
|
+
|
|
1316
|
+
communication?: {
|
|
1317
|
+
protocol: 'events' | 'messages' | 'shared-memory';
|
|
1318
|
+
batchSize: number;
|
|
1319
|
+
flushIntervalMs: number;
|
|
1320
|
+
};
|
|
1321
|
+
|
|
1322
|
+
metadata?: Record<string, unknown>;
|
|
1323
|
+
}
|
|
1324
|
+
|
|
1325
|
+
/**
|
|
1326
|
+
* Swarm state
|
|
1327
|
+
*/
|
|
1328
|
+
export interface ISwarmState {
|
|
1329
|
+
readonly id: string;
|
|
1330
|
+
readonly topology: SwarmTopology;
|
|
1331
|
+
readonly createdAt: Date;
|
|
1332
|
+
|
|
1333
|
+
status: CoordinationStatus;
|
|
1334
|
+
agentCount: number;
|
|
1335
|
+
taskCount: number;
|
|
1336
|
+
|
|
1337
|
+
metrics?: {
|
|
1338
|
+
throughput: number;
|
|
1339
|
+
latencyMs: number;
|
|
1340
|
+
successRate: number;
|
|
1341
|
+
resourceUtilization: number;
|
|
1342
|
+
};
|
|
1343
|
+
}
|
|
1344
|
+
|
|
1345
|
+
/**
|
|
1346
|
+
* Coordinator interface - unified coordination engine
|
|
1347
|
+
*/
|
|
1348
|
+
export interface ICoordinator {
|
|
1349
|
+
/**
|
|
1350
|
+
* Initialize the coordinator
|
|
1351
|
+
*/
|
|
1352
|
+
initialize(): Promise<void>;
|
|
1353
|
+
|
|
1354
|
+
/**
|
|
1355
|
+
* Shutdown the coordinator
|
|
1356
|
+
*/
|
|
1357
|
+
shutdown(): Promise<void>;
|
|
1358
|
+
|
|
1359
|
+
/**
|
|
1360
|
+
* Initialize a swarm with configuration
|
|
1361
|
+
*/
|
|
1362
|
+
initializeSwarm(config: ISwarmConfig): Promise<ISwarmState>;
|
|
1363
|
+
|
|
1364
|
+
/**
|
|
1365
|
+
* Get swarm state
|
|
1366
|
+
*/
|
|
1367
|
+
getSwarmState(): ISwarmState | undefined;
|
|
1368
|
+
|
|
1369
|
+
/**
|
|
1370
|
+
* Assign a task to an agent
|
|
1371
|
+
*/
|
|
1372
|
+
assignTask(task: ITask, agentId: string): Promise<void>;
|
|
1373
|
+
|
|
1374
|
+
/**
|
|
1375
|
+
* Get tasks assigned to an agent
|
|
1376
|
+
*/
|
|
1377
|
+
getAgentTasks(agentId: string): Promise<ITask[]>;
|
|
1378
|
+
|
|
1379
|
+
/**
|
|
1380
|
+
* Get task count for an agent
|
|
1381
|
+
*/
|
|
1382
|
+
getAgentTaskCount(agentId: string): Promise<number>;
|
|
1383
|
+
|
|
1384
|
+
/**
|
|
1385
|
+
* Cancel a task
|
|
1386
|
+
*/
|
|
1387
|
+
cancelTask(taskId: string): Promise<void>;
|
|
1388
|
+
|
|
1389
|
+
/**
|
|
1390
|
+
* Report task completion
|
|
1391
|
+
*/
|
|
1392
|
+
reportTaskComplete(taskId: string, result: ITaskResult): Promise<void>;
|
|
1393
|
+
|
|
1394
|
+
/**
|
|
1395
|
+
* Get coordination health status
|
|
1396
|
+
*/
|
|
1397
|
+
getHealthStatus(): Promise<{ healthy: boolean; error?: string; metrics?: Record<string, number> }>;
|
|
1398
|
+
|
|
1399
|
+
/**
|
|
1400
|
+
* Perform maintenance tasks
|
|
1401
|
+
*/
|
|
1402
|
+
performMaintenance(): Promise<void>;
|
|
1403
|
+
}
|
|
1404
|
+
|
|
1405
|
+
/**
|
|
1406
|
+
* Coordination manager interface - higher-level orchestration
|
|
1407
|
+
*/
|
|
1408
|
+
export interface ICoordinationManager extends ICoordinator {
|
|
1409
|
+
/**
|
|
1410
|
+
* Register an agent with the coordinator
|
|
1411
|
+
*/
|
|
1412
|
+
registerAgent(agent: IAgent): Promise<void>;
|
|
1413
|
+
|
|
1414
|
+
/**
|
|
1415
|
+
* Unregister an agent
|
|
1416
|
+
*/
|
|
1417
|
+
unregisterAgent(agentId: string): Promise<void>;
|
|
1418
|
+
|
|
1419
|
+
/**
|
|
1420
|
+
* Get all registered agents
|
|
1421
|
+
*/
|
|
1422
|
+
getRegisteredAgents(): IAgent[];
|
|
1423
|
+
|
|
1424
|
+
/**
|
|
1425
|
+
* Request agent consensus on a decision
|
|
1426
|
+
*/
|
|
1427
|
+
requestConsensus(topic: string, options: unknown[], timeout?: number): Promise<unknown>;
|
|
1428
|
+
|
|
1429
|
+
/**
|
|
1430
|
+
* Broadcast message to all agents
|
|
1431
|
+
*/
|
|
1432
|
+
broadcast(message: unknown): Promise<void>;
|
|
1433
|
+
|
|
1434
|
+
/**
|
|
1435
|
+
* Send message to specific agent
|
|
1436
|
+
*/
|
|
1437
|
+
sendToAgent(agentId: string, message: unknown): Promise<void>;
|
|
1438
|
+
|
|
1439
|
+
/**
|
|
1440
|
+
* Acquire a distributed lock
|
|
1441
|
+
*/
|
|
1442
|
+
acquireLock(resourceId: string, agentId: string, timeout?: number): Promise<boolean>;
|
|
1443
|
+
|
|
1444
|
+
/**
|
|
1445
|
+
* Release a distributed lock
|
|
1446
|
+
*/
|
|
1447
|
+
releaseLock(resourceId: string, agentId: string): Promise<void>;
|
|
1448
|
+
|
|
1449
|
+
/**
|
|
1450
|
+
* Check for deadlocks
|
|
1451
|
+
*/
|
|
1452
|
+
detectDeadlocks(): Promise<{ detected: boolean; agents?: string[]; resources?: string[] }>;
|
|
1453
|
+
}
|
|
1454
|
+
|
|
1455
|
+
/**
|
|
1456
|
+
* Health status for components
|
|
1457
|
+
*/
|
|
1458
|
+
export interface IHealthStatus {
|
|
1459
|
+
status: 'healthy' | 'degraded' | 'unhealthy';
|
|
1460
|
+
components: Record<string, IComponentHealth>;
|
|
1461
|
+
timestamp: Date;
|
|
1462
|
+
}
|
|
1463
|
+
|
|
1464
|
+
/**
|
|
1465
|
+
* Component health details
|
|
1466
|
+
*/
|
|
1467
|
+
export interface IComponentHealth {
|
|
1468
|
+
name: string;
|
|
1469
|
+
status: 'healthy' | 'degraded' | 'unhealthy';
|
|
1470
|
+
lastCheck: Date;
|
|
1471
|
+
error?: string;
|
|
1472
|
+
metrics?: Record<string, number>;
|
|
1473
|
+
}
|
|
1474
|
+
|
|
1475
|
+
/**
|
|
1476
|
+
* Health monitor interface
|
|
1477
|
+
*/
|
|
1478
|
+
export interface IHealthMonitor {
|
|
1479
|
+
/**
|
|
1480
|
+
* Start health monitoring
|
|
1481
|
+
*/
|
|
1482
|
+
start(): void;
|
|
1483
|
+
|
|
1484
|
+
/**
|
|
1485
|
+
* Stop health monitoring
|
|
1486
|
+
*/
|
|
1487
|
+
stop(): void;
|
|
1488
|
+
|
|
1489
|
+
/**
|
|
1490
|
+
* Get current health status
|
|
1491
|
+
*/
|
|
1492
|
+
getStatus(): Promise<IHealthStatus>;
|
|
1493
|
+
|
|
1494
|
+
/**
|
|
1495
|
+
* Register a health check
|
|
1496
|
+
*/
|
|
1497
|
+
registerCheck(
|
|
1498
|
+
name: string,
|
|
1499
|
+
check: () => Promise<{ healthy: boolean; error?: string; metrics?: Record<string, number> }>
|
|
1500
|
+
): void;
|
|
1501
|
+
|
|
1502
|
+
/**
|
|
1503
|
+
* Unregister a health check
|
|
1504
|
+
*/
|
|
1505
|
+
unregisterCheck(name: string): void;
|
|
1506
|
+
|
|
1507
|
+
/**
|
|
1508
|
+
* Get health history
|
|
1509
|
+
*/
|
|
1510
|
+
getHistory(limit?: number): IHealthStatus[];
|
|
1511
|
+
|
|
1512
|
+
/**
|
|
1513
|
+
* Subscribe to health changes
|
|
1514
|
+
*/
|
|
1515
|
+
onHealthChange(callback: (status: IHealthStatus) => void): () => void;
|
|
1516
|
+
}
|
|
1517
|
+
|
|
1518
|
+
/**
|
|
1519
|
+
* Metrics co
|
|
1520
|
+
|
|
1521
|
+
--- src/core/interfaces/event.interface.ts (truncated) ---
|
|
1522
|
+
/**
|
|
1523
|
+
* V3 Event Interfaces
|
|
1524
|
+
* Domain-Driven Design - Event Sourcing Pattern (ADR-007)
|
|
1525
|
+
*/
|
|
1526
|
+
|
|
1527
|
+
/**
|
|
1528
|
+
* Event priority levels
|
|
1529
|
+
*/
|
|
1530
|
+
export type EventPriority = 'critical' | 'high' | 'normal' | 'low';
|
|
1531
|
+
|
|
1532
|
+
/**
|
|
1533
|
+
* Core event structure
|
|
1534
|
+
*/
|
|
1535
|
+
export interface IEvent<T = unknown> {
|
|
1536
|
+
readonly id: string;
|
|
1537
|
+
readonly type: string;
|
|
1538
|
+
readonly timestamp: Date;
|
|
1539
|
+
readonly source: string;
|
|
1540
|
+
|
|
1541
|
+
payload: T;
|
|
1542
|
+
priority?: EventPriority;
|
|
1543
|
+
correlationId?: string;
|
|
1544
|
+
causationId?: string;
|
|
1545
|
+
|
|
1546
|
+
metadata?: {
|
|
1547
|
+
version?: number;
|
|
1548
|
+
userId?: string;
|
|
1549
|
+
sessionId?: string;
|
|
1550
|
+
[key: string]: unknown;
|
|
1551
|
+
};
|
|
1552
|
+
}
|
|
1553
|
+
|
|
1554
|
+
/**
|
|
1555
|
+
* Event creation parameters
|
|
1556
|
+
*/
|
|
1557
|
+
export interface IEventCreate<T = unknown> {
|
|
1558
|
+
type: string;
|
|
1559
|
+
payload: T;
|
|
1560
|
+
source?: string;
|
|
1561
|
+
priority?: EventPriority;
|
|
1562
|
+
correlationId?: string;
|
|
1563
|
+
causationId?: string;
|
|
1564
|
+
metadata?: IEvent['metadata'];
|
|
1565
|
+
}
|
|
1566
|
+
|
|
1567
|
+
/**
|
|
1568
|
+
* Event handler function type
|
|
1569
|
+
*/
|
|
1570
|
+
export type IEventHandler<T = unknown> = (event: IEvent<T>) => void | Promise<void>;
|
|
1571
|
+
|
|
1572
|
+
/**
|
|
1573
|
+
* Event filter for subscriptions
|
|
1574
|
+
*/
|
|
1575
|
+
export interface IEventFilter {
|
|
1576
|
+
types?: string[];
|
|
1577
|
+
sources?: string[];
|
|
1578
|
+
priority?: EventPriority[];
|
|
1579
|
+
correlationId?: string;
|
|
1580
|
+
}
|
|
1581
|
+
|
|
1582
|
+
/**
|
|
1583
|
+
* Event subscription handle
|
|
1584
|
+
*/
|
|
1585
|
+
export interface IEventSubscription {
|
|
1586
|
+
readonly id: string;
|
|
1587
|
+
readonly filter: IEventFilter;
|
|
1588
|
+
|
|
1589
|
+
/**
|
|
1590
|
+
* Unsubscribe from events
|
|
1591
|
+
*/
|
|
1592
|
+
unsubscribe(): void;
|
|
1593
|
+
|
|
1594
|
+
/**
|
|
1595
|
+
* Pause subscription
|
|
1596
|
+
*/
|
|
1597
|
+
pause(): void;
|
|
1598
|
+
|
|
1599
|
+
/**
|
|
1600
|
+
* Resume subscription
|
|
1601
|
+
*/
|
|
1602
|
+
resume(): void;
|
|
1603
|
+
|
|
1604
|
+
/**
|
|
1605
|
+
* Check if subscription is active
|
|
1606
|
+
*/
|
|
1607
|
+
isActive(): boolean;
|
|
1608
|
+
}
|
|
1609
|
+
|
|
1610
|
+
/**
|
|
1611
|
+
* Event bus interface for pub/sub communication
|
|
1612
|
+
*/
|
|
1613
|
+
export interface IEventBus {
|
|
1614
|
+
/**
|
|
1615
|
+
* Emit an event to all subscribers
|
|
1616
|
+
*/
|
|
1617
|
+
emit<T = unknown>(type: string, payload: T, options?: Partial<IEventCreate<T>>): void;
|
|
1618
|
+
|
|
1619
|
+
/**
|
|
1620
|
+
* Emit an event and wait for all handlers
|
|
1621
|
+
*/
|
|
1622
|
+
emitAsync<T = unknown>(type: string, payload: T, options?: Partial<IEventCreate<T>>): Promise<void>;
|
|
1623
|
+
|
|
1624
|
+
/**
|
|
1625
|
+
* Subscribe to events matching a type pattern
|
|
1626
|
+
*/
|
|
1627
|
+
on<T = unknown>(type: string, handler: IEventHandler<T>): IEventSubscription;
|
|
1628
|
+
|
|
1629
|
+
/**
|
|
1630
|
+
* Subscribe to events with filter
|
|
1631
|
+
*/
|
|
1632
|
+
subscribe<T = unknown>(filter: IEventFilter, handler: IEventHandler<T>): IEventSubscription;
|
|
1633
|
+
|
|
1634
|
+
/**
|
|
1635
|
+
* Subscribe to a single event occurrence
|
|
1636
|
+
*/
|
|
1637
|
+
once<T = unknown>(type: string, handler: IEventHandler<T>): IEventSubscription;
|
|
1638
|
+
|
|
1639
|
+
/**
|
|
1640
|
+
* Remove a specific handler
|
|
1641
|
+
*/
|
|
1642
|
+
off(type: string, handler: IEventHandler): void;
|
|
1643
|
+
|
|
1644
|
+
/**
|
|
1645
|
+
* Remove all handlers for a type
|
|
1646
|
+
*/
|
|
1647
|
+
removeAllListeners(type?: string): void;
|
|
1648
|
+
|
|
1649
|
+
/**
|
|
1650
|
+
* Get count of listeners for a type
|
|
1651
|
+
*/
|
|
1652
|
+
listenerCount(type: string): number;
|
|
1653
|
+
|
|
1654
|
+
/**
|
|
1655
|
+
* Get all event types with active listeners
|
|
1656
|
+
*/
|
|
1657
|
+
eventNames(): string[];
|
|
1658
|
+
}
|
|
1659
|
+
|
|
1660
|
+
/**
|
|
1661
|
+
* System event types enumeration
|
|
1662
|
+
*/
|
|
1663
|
+
export const SystemEventTypes = {
|
|
1664
|
+
// System lifecycle
|
|
1665
|
+
SYSTEM_READY: 'system:ready',
|
|
1666
|
+
SYSTEM_SHUTDOWN: 'system:shutdown',
|
|
1667
|
+
SYSTEM_ERROR: 'system:error',
|
|
1668
|
+
SYSTEM_HEALTHCHECK: 'system:healthcheck',
|
|
1669
|
+
|
|
1670
|
+
// Agent lifecycle
|
|
1671
|
+
AGENT_SPAWNED: 'agent:spawned',
|
|
1672
|
+
AGENT_TERMINATED: 'agent:terminated',
|
|
1673
|
+
AGENT_ERROR: 'agent:error',
|
|
1674
|
+
AGENT_IDLE: 'agent:idle',
|
|
1675
|
+
AGENT_BUSY: 'agent:busy',
|
|
1676
|
+
AGENT_HEALTH_CHANGED: 'agent:health:changed',
|
|
1677
|
+
|
|
1678
|
+
// Task lifecycle
|
|
1679
|
+
TASK_CREATED: 'task:created',
|
|
1680
|
+
TASK_ASSIGNED: 'task:assigned',
|
|
1681
|
+
TASK_STARTED: 'task:started',
|
|
1682
|
+
TASK_COMPLETED: 'task:completed',
|
|
1683
|
+
TASK_FAILED: 'task:failed',
|
|
1684
|
+
TASK_CANCELLED: 'task:cancelled',
|
|
1685
|
+
TASK_TIMEOUT: 'task:timeout',
|
|
1686
|
+
TASK_RETRY: 'task:retry',
|
|
1687
|
+
|
|
1688
|
+
// Session lifecycle
|
|
1689
|
+
SESSION_CREATED: 'session:created',
|
|
1690
|
+
SESSION_RESTORED: 'session:restored',
|
|
1691
|
+
SESSION_TERMINATED: 'session:terminated',
|
|
1692
|
+
SESSION_PERSISTED: 'session:persisted',
|
|
1693
|
+
|
|
1694
|
+
// Memory events
|
|
1695
|
+
MEMORY_STORED: 'memory:stored',
|
|
1696
|
+
MEMORY_RETRIEVED: 'memory:retrieved',
|
|
1697
|
+
MEMORY_CLEARED: 'memory:cleared',
|
|
1698
|
+
|
|
1699
|
+
// Coordination events
|
|
1700
|
+
COORDINATION_STARTED: 'coordination:started',
|
|
1701
|
+
COORDINATION_COMPLETED: 'coordination:completed',
|
|
1702
|
+
DEADLOCK_DETECTED: 'coordination:deadlock',
|
|
1703
|
+
|
|
1704
|
+
// Metrics events
|
|
1705
|
+
METRICS_COLLECTED: 'metrics:collected',
|
|
1706
|
+
} as const;
|
|
1707
|
+
|
|
1708
|
+
export type SystemEventType = typeof SystemEventTypes[keyof typeof SystemEventTypes];
|
|
1709
|
+
|
|
1710
|
+
/**
|
|
1711
|
+
* Event store interface for event sourcing
|
|
1712
|
+
*/
|
|
1713
|
+
export interface IEventStore {
|
|
1714
|
+
/**
|
|
1715
|
+
* Append an event to the store
|
|
1716
|
+
*/
|
|
1717
|
+
append(event: IEvent): Promise<void>;
|
|
1718
|
+
|
|
1719
|
+
/**
|
|
1720
|
+
* Get events by aggregate ID
|
|
1721
|
+
*/
|
|
1722
|
+
getByAggregateId(aggregateId: string, fromVersion?: number): Promise<IEvent[]>;
|
|
1723
|
+
|
|
1724
|
+
/**
|
|
1725
|
+
* Get events by type
|
|
1726
|
+
*/
|
|
1727
|
+
getByType(type: string, options?: { limit?: number; offset?: number }): Promise<IEvent[]>;
|
|
1728
|
+
|
|
1729
|
+
/**
|
|
1730
|
+
* Get events in time range
|
|
1731
|
+
*/
|
|
1732
|
+
getByTimeRange(start: Date, end: Date): Promise<IEvent[]>;
|
|
1733
|
+
|
|
1734
|
+
/**
|
|
1735
|
+
* Get events by correlation ID
|
|
1736
|
+
*/
|
|
1737
|
+
getByCorrelationId(correlationId: string): Promise<IEvent[]>;
|
|
1738
|
+
|
|
1739
|
+
/**
|
|
1740
|
+
* Get all events (paginated)
|
|
1741
|
+
*/
|
|
1742
|
+
getAll(options?: { limit?: number; offset?: number }): Promise<IEvent[]>;
|
|
1743
|
+
|
|
1744
|
+
/**
|
|
1745
|
+
* Get event count
|
|
1746
|
+
*/
|
|
1747
|
+
count(filter?: IEventFilter): Promise<number>;
|
|
1748
|
+
|
|
1749
|
+
/**
|
|
1750
|
+
* Clear old events
|
|
1751
|
+
*/
|
|
1752
|
+
prune(olderThan: Date): P
|
|
1753
|
+
|
|
1754
|
+
--- src/core/interfaces/index.ts ---
|
|
1755
|
+
/**
|
|
1756
|
+
* V3 Core Interfaces - Public API
|
|
1757
|
+
* Domain-Driven Design with Clean Architecture
|
|
1758
|
+
*/
|
|
1759
|
+
|
|
1760
|
+
// Task interfaces
|
|
1761
|
+
export * from './task.interface.js';
|
|
1762
|
+
|
|
1763
|
+
// Agent interfaces
|
|
1764
|
+
export * from './agent.interface.js';
|
|
1765
|
+
|
|
1766
|
+
// Event interfaces
|
|
1767
|
+
export * from './event.interface.js';
|
|
1768
|
+
|
|
1769
|
+
// Memory interfaces
|
|
1770
|
+
export * from './memory.interface.js';
|
|
1771
|
+
|
|
1772
|
+
// Coordinator interfaces
|
|
1773
|
+
export * from './coordinator.interface.js';
|
|
1774
|
+
|
|
1775
|
+
|
|
1776
|
+
--- src/core/interfaces/memory.interface.ts (truncated) ---
|
|
1777
|
+
/**
|
|
1778
|
+
* V3 Memory Interfaces
|
|
1779
|
+
* Domain-Driven Design - Memory Management Bounded Context
|
|
1780
|
+
* Aligned with ADR-006 (Unified Memory Service) and ADR-009 (Hybrid Memory Backend)
|
|
1781
|
+
*/
|
|
1782
|
+
|
|
1783
|
+
/**
|
|
1784
|
+
* Memory entry types
|
|
1785
|
+
*/
|
|
1786
|
+
export type MemoryType = 'session' | 'persistent' | 'vector' | 'cache' | 'pattern';
|
|
1787
|
+
|
|
1788
|
+
/**
|
|
1789
|
+
* Memory entry structure
|
|
1790
|
+
*/
|
|
1791
|
+
export interface IMemoryEntry {
|
|
1792
|
+
readonly id: string;
|
|
1793
|
+
readonly key: string;
|
|
1794
|
+
readonly type: MemoryType;
|
|
1795
|
+
readonly createdAt: Date;
|
|
1796
|
+
|
|
1797
|
+
value: unknown;
|
|
1798
|
+
updatedAt: Date;
|
|
1799
|
+
expiresAt?: Date;
|
|
1800
|
+
|
|
1801
|
+
metadata?: {
|
|
1802
|
+
source?: string;
|
|
1803
|
+
agentId?: string;
|
|
1804
|
+
sessionId?: string;
|
|
1805
|
+
version?: number;
|
|
1806
|
+
tags?: string[];
|
|
1807
|
+
embedding?: number[];
|
|
1808
|
+
[key: string]: unknown;
|
|
1809
|
+
};
|
|
1810
|
+
}
|
|
1811
|
+
|
|
1812
|
+
/**
|
|
1813
|
+
* Memory entry creation parameters
|
|
1814
|
+
*/
|
|
1815
|
+
export interface IMemoryEntryCreate {
|
|
1816
|
+
key: string;
|
|
1817
|
+
value: unknown;
|
|
1818
|
+
type?: MemoryType;
|
|
1819
|
+
expiresAt?: Date;
|
|
1820
|
+
ttlMs?: number;
|
|
1821
|
+
metadata?: IMemoryEntry['metadata'];
|
|
1822
|
+
}
|
|
1823
|
+
|
|
1824
|
+
/**
|
|
1825
|
+
* Vector search parameters
|
|
1826
|
+
*/
|
|
1827
|
+
export interface IVectorSearchParams {
|
|
1828
|
+
embedding: number[];
|
|
1829
|
+
k?: number;
|
|
1830
|
+
threshold?: number;
|
|
1831
|
+
filter?: {
|
|
1832
|
+
type?: MemoryType;
|
|
1833
|
+
tags?: string[];
|
|
1834
|
+
agentId?: string;
|
|
1835
|
+
};
|
|
1836
|
+
}
|
|
1837
|
+
|
|
1838
|
+
/**
|
|
1839
|
+
* Vector search result
|
|
1840
|
+
*/
|
|
1841
|
+
export interface IVectorSearchResult {
|
|
1842
|
+
entry: IMemoryEntry;
|
|
1843
|
+
score: number;
|
|
1844
|
+
distance: number;
|
|
1845
|
+
}
|
|
1846
|
+
|
|
1847
|
+
/**
|
|
1848
|
+
* Memory backend interface for storage operations
|
|
1849
|
+
*/
|
|
1850
|
+
export interface IMemoryBackend {
|
|
1851
|
+
/**
|
|
1852
|
+
* Initialize the backend
|
|
1853
|
+
*/
|
|
1854
|
+
initialize(): Promise<void>;
|
|
1855
|
+
|
|
1856
|
+
/**
|
|
1857
|
+
* Shutdown the backend
|
|
1858
|
+
*/
|
|
1859
|
+
shutdown(): Promise<void>;
|
|
1860
|
+
|
|
1861
|
+
/**
|
|
1862
|
+
* Store a memory entry
|
|
1863
|
+
*/
|
|
1864
|
+
store(entry: IMemoryEntryCreate): Promise<IMemoryEntry>;
|
|
1865
|
+
|
|
1866
|
+
/**
|
|
1867
|
+
* Retrieve a memory entry by key
|
|
1868
|
+
*/
|
|
1869
|
+
retrieve(key: string): Promise<IMemoryEntry | undefined>;
|
|
1870
|
+
|
|
1871
|
+
/**
|
|
1872
|
+
* Retrieve by ID
|
|
1873
|
+
*/
|
|
1874
|
+
retrieveById(id: string): Promise<IMemoryEntry | undefined>;
|
|
1875
|
+
|
|
1876
|
+
/**
|
|
1877
|
+
* Update a memory entry
|
|
1878
|
+
*/
|
|
1879
|
+
update(key: string, value: unknown, metadata?: Partial<IMemoryEntry['metadata']>): Promise<IMemoryEntry | undefined>;
|
|
1880
|
+
|
|
1881
|
+
/**
|
|
1882
|
+
* Delete a memory entry
|
|
1883
|
+
*/
|
|
1884
|
+
delete(key: string): Promise<boolean>;
|
|
1885
|
+
|
|
1886
|
+
/**
|
|
1887
|
+
* Check if a key exists
|
|
1888
|
+
*/
|
|
1889
|
+
exists(key: string): Promise<boolean>;
|
|
1890
|
+
|
|
1891
|
+
/**
|
|
1892
|
+
* List all keys matching a pattern
|
|
1893
|
+
*/
|
|
1894
|
+
keys(pattern?: string): Promise<string[]>;
|
|
1895
|
+
|
|
1896
|
+
/**
|
|
1897
|
+
* Get all entries matching filter
|
|
1898
|
+
*/
|
|
1899
|
+
list(filter?: { type?: MemoryType; tags?: string[] }): Promise<IMemoryEntry[]>;
|
|
1900
|
+
|
|
1901
|
+
/**
|
|
1902
|
+
* Clear all entries
|
|
1903
|
+
*/
|
|
1904
|
+
clear(): Promise<void>;
|
|
1905
|
+
|
|
1906
|
+
/**
|
|
1907
|
+
* Get entry count
|
|
1908
|
+
*/
|
|
1909
|
+
count(): Promise<number>;
|
|
1910
|
+
|
|
1911
|
+
/**
|
|
1912
|
+
* Prune expired entries
|
|
1913
|
+
*/
|
|
1914
|
+
prune(): Promise<number>;
|
|
1915
|
+
|
|
1916
|
+
/**
|
|
1917
|
+
* Get health status
|
|
1918
|
+
*/
|
|
1919
|
+
getHealthStatus(): Promise<{ healthy: boolean; error?: string; metrics?: Record<string, number> }>;
|
|
1920
|
+
}
|
|
1921
|
+
|
|
1922
|
+
/**
|
|
1923
|
+
* Vector memory backend for similarity search
|
|
1924
|
+
*/
|
|
1925
|
+
export interface IVectorMemoryBackend extends IMemoryBackend {
|
|
1926
|
+
/**
|
|
1927
|
+
* Store with embedding
|
|
1928
|
+
*/
|
|
1929
|
+
storeVector(entry: IMemoryEntryCreate & { embedding: number[] }): Promise<IMemoryEntry>;
|
|
1930
|
+
|
|
1931
|
+
/**
|
|
1932
|
+
* Search by vector similarity
|
|
1933
|
+
*/
|
|
1934
|
+
search(params: IVectorSearchParams): Promise<IVectorSearchResult[]>;
|
|
1935
|
+
|
|
1936
|
+
/**
|
|
1937
|
+
* Update embedding for an entry
|
|
1938
|
+
*/
|
|
1939
|
+
updateEmbedding(key: string, embedding: number[]): Promise<boolean>;
|
|
1940
|
+
|
|
1941
|
+
/**
|
|
1942
|
+
* Build or rebuild index
|
|
1943
|
+
*/
|
|
1944
|
+
buildIndex(): Promise<void>;
|
|
1945
|
+
|
|
1946
|
+
/**
|
|
1947
|
+
* Get index statistics
|
|
1948
|
+
*/
|
|
1949
|
+
getIndexStats(): Promise<{
|
|
1950
|
+
vectorCount: number;
|
|
1951
|
+
dimensions: number;
|
|
1952
|
+
indexType: string;
|
|
1953
|
+
memoryUsageMb: number;
|
|
1954
|
+
}>;
|
|
1955
|
+
}
|
|
1956
|
+
|
|
1957
|
+
/**
|
|
1958
|
+
* Memory bank for agent-specific storage
|
|
1959
|
+
*/
|
|
1960
|
+
export interface IMemoryBank {
|
|
1961
|
+
readonly id: string;
|
|
1962
|
+
readonly agentId: string;
|
|
1963
|
+
readonly createdAt: Date;
|
|
1964
|
+
|
|
1965
|
+
/**
|
|
1966
|
+
* Store in bank
|
|
1967
|
+
*/
|
|
1968
|
+
store(key: string, value: unknown, options?: Partial<IMemoryEntryCreate>): Promise<IMemoryEntry>;
|
|
1969
|
+
|
|
1970
|
+
/**
|
|
1971
|
+
* Retrieve from bank
|
|
1972
|
+
*/
|
|
1973
|
+
retrieve(key: string): Promise<IMemoryEntry | undefined>;
|
|
1974
|
+
|
|
1975
|
+
/**
|
|
1976
|
+
* Delete from bank
|
|
1977
|
+
*/
|
|
1978
|
+
delete(key: string): Promise<boolean>;
|
|
1979
|
+
|
|
1980
|
+
/**
|
|
1981
|
+
* List all entries in bank
|
|
1982
|
+
*/
|
|
1983
|
+
list(): Promise<IMemoryEntry[]>;
|
|
1984
|
+
|
|
1985
|
+
/**
|
|
1986
|
+
* Clear all entries in bank
|
|
1987
|
+
*/
|
|
1988
|
+
clear(): Promise<void>;
|
|
1989
|
+
|
|
1990
|
+
/**
|
|
1991
|
+
* Get bank size
|
|
1992
|
+
*/
|
|
1993
|
+
size(): Promise<number>;
|
|
1994
|
+
|
|
1995
|
+
/**
|
|
1996
|
+
* Close the bank
|
|
1997
|
+
*/
|
|
1998
|
+
close(): Promise<void>;
|
|
1999
|
+
}
|
|
2000
|
+
|
|
2001
|
+
/**
|
|
2002
|
+
* Memory manager interface
|
|
2003
|
+
*/
|
|
2004
|
+
export interface IMemoryManager {
|
|
2005
|
+
/**
|
|
2006
|
+
* Initialize the manager
|
|
2007
|
+
*/
|
|
2008
|
+
initialize(): Promise<void>;
|
|
2009
|
+
|
|
2010
|
+
/**
|
|
2011
|
+
* Shutdown the manager
|
|
2012
|
+
*/
|
|
2013
|
+
shutdown(): Promise<void>;
|
|
2014
|
+
|
|
2015
|
+
/**
|
|
2016
|
+
* Create a memory bank for an agent
|
|
2017
|
+
*/
|
|
2018
|
+
createBank(agentId: string): Promise<string>;
|
|
2019
|
+
|
|
2020
|
+
/**
|
|
2021
|
+
* Get a memory bank
|
|
2022
|
+
*/
|
|
2023
|
+
getBank(bankId: string): IMemoryBank | undefined;
|
|
2024
|
+
|
|
2025
|
+
/**
|
|
2026
|
+
* Close a memory bank
|
|
2027
|
+
*/
|
|
2028
|
+
closeBank(bankId: string): Promise<void>;
|
|
2029
|
+
|
|
2030
|
+
/**
|
|
2031
|
+
* Store in global memory
|
|
2032
|
+
*/
|
|
2033
|
+
store(entry: IMemoryEntryCreate): Promise<IMemoryEntry>;
|
|
2034
|
+
|
|
2035
|
+
/**
|
|
2036
|
+
* Retrieve from global memory
|
|
2037
|
+
*/
|
|
2038
|
+
retrieve(key: string): Promise<IMemoryEntry | undefined>;
|
|
2039
|
+
|
|
2040
|
+
/**
|
|
2041
|
+
* Search vectors (if vector backend available)
|
|
2042
|
+
*/
|
|
2043
|
+
searchVectors?(params: IVectorSearchParams): Promise<IVectorSearchResult[]>;
|
|
2044
|
+
|
|
2045
|
+
/**
|
|
2046
|
+
|
|
2047
|
+
|
|
2048
|
+
--- src/core/interfaces/task.interface.ts ---
|
|
2049
|
+
/**
|
|
2050
|
+
* V3 Task Interfaces
|
|
2051
|
+
* Domain-Driven Design - Task Bounded Context
|
|
2052
|
+
*/
|
|
2053
|
+
|
|
2054
|
+
/**
|
|
2055
|
+
* Task priority levels
|
|
2056
|
+
*/
|
|
2057
|
+
export type TaskPriority = 'critical' | 'high' | 'medium' | 'low';
|
|
2058
|
+
|
|
2059
|
+
/**
|
|
2060
|
+
* Task status throughout its lifecycle
|
|
2061
|
+
*/
|
|
2062
|
+
export type TaskStatus =
|
|
2063
|
+
| 'pending'
|
|
2064
|
+
| 'queued'
|
|
2065
|
+
| 'assigned'
|
|
2066
|
+
| 'running'
|
|
2067
|
+
| 'completed'
|
|
2068
|
+
| 'failed'
|
|
2069
|
+
| 'cancelled'
|
|
2070
|
+
| 'timeout';
|
|
2071
|
+
|
|
2072
|
+
/**
|
|
2073
|
+
* Core task entity
|
|
2074
|
+
*/
|
|
2075
|
+
export interface ITask {
|
|
2076
|
+
readonly id: string;
|
|
2077
|
+
readonly type: string;
|
|
2078
|
+
readonly description: string;
|
|
2079
|
+
readonly priority: number;
|
|
2080
|
+
readonly createdAt: Date;
|
|
2081
|
+
|
|
2082
|
+
status: TaskStatus;
|
|
2083
|
+
assignedAgent?: string;
|
|
2084
|
+
startedAt?: Date;
|
|
2085
|
+
completedAt?: Date;
|
|
2086
|
+
timeout?: number;
|
|
2087
|
+
|
|
2088
|
+
input?: Record<string, unknown>;
|
|
2089
|
+
output?: Record<string, unknown>;
|
|
2090
|
+
error?: Error;
|
|
2091
|
+
|
|
2092
|
+
metadata?: {
|
|
2093
|
+
requiredCapabilities?: string[];
|
|
2094
|
+
retryCount?: number;
|
|
2095
|
+
maxRetries?: number;
|
|
2096
|
+
critical?: boolean;
|
|
2097
|
+
parentTaskId?: string;
|
|
2098
|
+
childTaskIds?: string[];
|
|
2099
|
+
tags?: string[];
|
|
2100
|
+
[key: string]: unknown;
|
|
2101
|
+
};
|
|
2102
|
+
}
|
|
2103
|
+
|
|
2104
|
+
/**
|
|
2105
|
+
* Task creation parameters
|
|
2106
|
+
*/
|
|
2107
|
+
export interface ITaskCreate {
|
|
2108
|
+
type: string;
|
|
2109
|
+
description: string;
|
|
2110
|
+
priority?: number;
|
|
2111
|
+
timeout?: number;
|
|
2112
|
+
assignedAgent?: string;
|
|
2113
|
+
input?: Record<string, unknown>;
|
|
2114
|
+
metadata?: ITask['metadata'];
|
|
2115
|
+
}
|
|
2116
|
+
|
|
2117
|
+
/**
|
|
2118
|
+
* Task result after completion
|
|
2119
|
+
*/
|
|
2120
|
+
export interface ITaskResult {
|
|
2121
|
+
taskId: string;
|
|
2122
|
+
success: boolean;
|
|
2123
|
+
output?: Record<string, unknown>;
|
|
2124
|
+
error?: Error;
|
|
2125
|
+
duration: number;
|
|
2126
|
+
agentId?: string;
|
|
2127
|
+
metrics?: {
|
|
2128
|
+
tokensUsed?: number;
|
|
2129
|
+
memoryPeakMb?: number;
|
|
2130
|
+
retryCount?: number;
|
|
2131
|
+
};
|
|
2132
|
+
}
|
|
2133
|
+
|
|
2134
|
+
/**
|
|
2135
|
+
* Task queue interface for managing task ordering and processing
|
|
2136
|
+
*/
|
|
2137
|
+
export interface ITaskQueue {
|
|
2138
|
+
/**
|
|
2139
|
+
* Add a task to the queue
|
|
2140
|
+
*/
|
|
2141
|
+
enqueue(task: ITask): Promise<void>;
|
|
2142
|
+
|
|
2143
|
+
/**
|
|
2144
|
+
* Remove and return the highest priority task
|
|
2145
|
+
*/
|
|
2146
|
+
dequeue(): Promise<ITask | undefined>;
|
|
2147
|
+
|
|
2148
|
+
/**
|
|
2149
|
+
* Peek at the next task without removing it
|
|
2150
|
+
*/
|
|
2151
|
+
peek(): Promise<ITask | undefined>;
|
|
2152
|
+
|
|
2153
|
+
/**
|
|
2154
|
+
* Get the current queue size
|
|
2155
|
+
*/
|
|
2156
|
+
size(): number;
|
|
2157
|
+
|
|
2158
|
+
/**
|
|
2159
|
+
* Check if the queue is empty
|
|
2160
|
+
*/
|
|
2161
|
+
isEmpty(): boolean;
|
|
2162
|
+
|
|
2163
|
+
/**
|
|
2164
|
+
* Clear all tasks from the queue
|
|
2165
|
+
*/
|
|
2166
|
+
clear(): Promise<void>;
|
|
2167
|
+
|
|
2168
|
+
/**
|
|
2169
|
+
* Get all queued tasks (for inspection)
|
|
2170
|
+
*/
|
|
2171
|
+
getAll(): Promise<ITask[]>;
|
|
2172
|
+
|
|
2173
|
+
/**
|
|
2174
|
+
* Remove a specific task by ID
|
|
2175
|
+
*/
|
|
2176
|
+
remove(taskId: string): Promise<boolean>;
|
|
2177
|
+
|
|
2178
|
+
/**
|
|
2179
|
+
* Update task priority
|
|
2180
|
+
*/
|
|
2181
|
+
updatePriority(taskId: string, priority: number): Promise<boolean>;
|
|
2182
|
+
}
|
|
2183
|
+
|
|
2184
|
+
/**
|
|
2185
|
+
* Task manager interface for lifecycle management
|
|
2186
|
+
*/
|
|
2187
|
+
export interface ITaskManager {
|
|
2188
|
+
/**
|
|
2189
|
+
* Create a new task
|
|
2190
|
+
*/
|
|
2191
|
+
createTask(params: ITaskCreate): Promise<ITask>;
|
|
2192
|
+
|
|
2193
|
+
/**
|
|
2194
|
+
* Get a task by ID
|
|
2195
|
+
*/
|
|
2196
|
+
getTask(taskId: string): ITask | undefined;
|
|
2197
|
+
|
|
2198
|
+
/**
|
|
2199
|
+
* Get all tasks matching optional filter
|
|
2200
|
+
*/
|
|
2201
|
+
getTasks(filter?: Partial<Pick<ITask, 'status' | 'type' | 'assignedAgent'>>): ITask[];
|
|
2202
|
+
|
|
2203
|
+
/**
|
|
2204
|
+
* Assign a task to an agent
|
|
2205
|
+
*/
|
|
2206
|
+
assignTask(taskId: string, agentId: string): Promise<void>;
|
|
2207
|
+
|
|
2208
|
+
/**
|
|
2209
|
+
* Start task execution
|
|
2210
|
+
*/
|
|
2211
|
+
startTask(taskId: string): Promise<void>;
|
|
2212
|
+
|
|
2213
|
+
/**
|
|
2214
|
+
* Complete a task with result
|
|
2215
|
+
*/
|
|
2216
|
+
completeTask(taskId: string, result: ITaskResult): Promise<void>;
|
|
2217
|
+
|
|
2218
|
+
/**
|
|
2219
|
+
* Fail a task with error
|
|
2220
|
+
*/
|
|
2221
|
+
failTask(taskId: string, error: Error): Promise<void>;
|
|
2222
|
+
|
|
2223
|
+
/**
|
|
2224
|
+
* Cancel a task
|
|
2225
|
+
*/
|
|
2226
|
+
cancelTask(taskId: string, reason?: string): Promise<void>;
|
|
2227
|
+
|
|
2228
|
+
/**
|
|
2229
|
+
* Retry a failed task
|
|
2230
|
+
*/
|
|
2231
|
+
retryTask(taskId: string): Promise<void>;
|
|
2232
|
+
|
|
2233
|
+
/**
|
|
2234
|
+
* Get task metrics
|
|
2235
|
+
*/
|
|
2236
|
+
getMetrics(): TaskManagerMetrics;
|
|
2237
|
+
|
|
2238
|
+
/**
|
|
2239
|
+
* Clean up old completed/failed tasks
|
|
2240
|
+
*/
|
|
2241
|
+
cleanup(olderThan: Date): Promise<number>;
|
|
2242
|
+
}
|
|
2243
|
+
|
|
2244
|
+
/**
|
|
2245
|
+
* Task manager metrics
|
|
2246
|
+
*/
|
|
2247
|
+
export interface TaskManagerMetrics {
|
|
2248
|
+
totalTasks: number;
|
|
2249
|
+
pendingTasks: number;
|
|
2250
|
+
runningTasks: number;
|
|
2251
|
+
completedTasks: number;
|
|
2252
|
+
failedTasks: number;
|
|
2253
|
+
cancelledTasks: number;
|
|
2254
|
+
avgDuration: number;
|
|
2255
|
+
avgWaitTime: number;
|
|
2256
|
+
}
|
|
2257
|
+
|
|
2258
|
+
/**
|
|
2259
|
+
* Task assignment strategy interface
|
|
2260
|
+
*/
|
|
2261
|
+
export interface ITaskAssignmentStrategy {
|
|
2262
|
+
/**
|
|
2263
|
+
* Select the best agent for a task
|
|
2264
|
+
*/
|
|
2265
|
+
selectAgent(task: ITask, availableAgents: string[]): Promise<string | undefined>;
|
|
2266
|
+
|
|
2267
|
+
/**
|
|
2268
|
+
* Score an agent for a task (higher is better)
|
|
2269
|
+
*/
|
|
2270
|
+
scoreAgent(task: ITask, agentId: string): Promise<number>;
|
|
2271
|
+
}
|
|
2272
|
+
|
|
2273
|
+
|
|
2274
|
+
--- src/core/orchestrator/event-coordinator.ts ---
|
|
2275
|
+
/**
|
|
2276
|
+
* V3 Event Coordinator
|
|
2277
|
+
* Decomposed from orchestrator.ts - Event routing
|
|
2278
|
+
* ~100 lines (target achieved)
|
|
2279
|
+
*/
|
|
2280
|
+
|
|
2281
|
+
import type {
|
|
2282
|
+
IEvent,
|
|
2283
|
+
IEventBus,
|
|
2284
|
+
IEventHandler,
|
|
2285
|
+
IEventCoordinator,
|
|
2286
|
+
} from '../interfaces/event.interface.js';
|
|
2287
|
+
import { SystemEventTypes } from '../interfaces/event.interface.js';
|
|
2288
|
+
|
|
2289
|
+
/**
|
|
2290
|
+
* Event coordinator implementation
|
|
2291
|
+
*/
|
|
2292
|
+
export class EventCoordinator implements IEventCoordinator {
|
|
2293
|
+
private handlers = new Map<string, Set<IEventHandler>>();
|
|
2294
|
+
private initialized = false;
|
|
2295
|
+
|
|
2296
|
+
constructor(private eventBus: IEventBus) {}
|
|
2297
|
+
|
|
2298
|
+
async initialize(): Promise<void> {
|
|
2299
|
+
if (this.initialized) {
|
|
2300
|
+
return;
|
|
2301
|
+
}
|
|
2302
|
+
|
|
2303
|
+
// Register default system event handlers
|
|
2304
|
+
this.registerSystemHandlers();
|
|
2305
|
+
|
|
2306
|
+
this.initialized = true;
|
|
2307
|
+
}
|
|
2308
|
+
|
|
2309
|
+
async shutdown(): Promise<void> {
|
|
2310
|
+
// Clear all handlers
|
|
2311
|
+
this.handlers.clear();
|
|
2312
|
+
this.initialized = false;
|
|
2313
|
+
}
|
|
2314
|
+
|
|
2315
|
+
async route(event: IEvent): Promise<void> {
|
|
2316
|
+
const handlers = this.handlers.get(event.type);
|
|
2317
|
+
if (!handlers || handlers.size === 0) {
|
|
2318
|
+
return;
|
|
2319
|
+
}
|
|
2320
|
+
|
|
2321
|
+
const handlerPromises = Array.from(handlers).map(async handler => {
|
|
2322
|
+
try {
|
|
2323
|
+
await handler(event);
|
|
2324
|
+
} catch (error) {
|
|
2325
|
+
// Log error but don't throw
|
|
2326
|
+
console.error(`Error in event handler for ${event.type}:`, error);
|
|
2327
|
+
}
|
|
2328
|
+
});
|
|
2329
|
+
|
|
2330
|
+
await Promise.allSettled(handlerPromises);
|
|
2331
|
+
}
|
|
2332
|
+
|
|
2333
|
+
registerHandler(type: string, handler: IEventHandler): void {
|
|
2334
|
+
let handlers = this.handlers.get(type);
|
|
2335
|
+
if (!handlers) {
|
|
2336
|
+
handlers = new Set();
|
|
2337
|
+
this.handlers.set(type, handlers);
|
|
2338
|
+
}
|
|
2339
|
+
handlers.add(handler);
|
|
2340
|
+
|
|
2341
|
+
// Also register with event bus
|
|
2342
|
+
this.eventBus.on(type, handler);
|
|
2343
|
+
}
|
|
2344
|
+
|
|
2345
|
+
unregisterHandler(type: string, handler: IEventHandler): void {
|
|
2346
|
+
const handlers = this.handlers.get(type);
|
|
2347
|
+
if (handlers) {
|
|
2348
|
+
handlers.delete(handler);
|
|
2349
|
+
if (handlers.size === 0) {
|
|
2350
|
+
this.handlers.delete(type);
|
|
2351
|
+
}
|
|
2352
|
+
}
|
|
2353
|
+
|
|
2354
|
+
// Also unregister from event bus
|
|
2355
|
+
this.eventBus.off(type, handler);
|
|
2356
|
+
}
|
|
2357
|
+
|
|
2358
|
+
getEventBus(): IEventBus {
|
|
2359
|
+
return this.eventBus;
|
|
2360
|
+
}
|
|
2361
|
+
|
|
2362
|
+
private registerSystemHandlers(): void {
|
|
2363
|
+
// Error handling
|
|
2364
|
+
this.eventBus.on(SystemEventTypes.SYSTEM_ERROR, (event: IEvent) => {
|
|
2365
|
+
const { error, component } = event.payload as { error: Error; component: string };
|
|
2366
|
+
console.error(`System error in ${component}:`, error);
|
|
2367
|
+
});
|
|
2368
|
+
|
|
2369
|
+
// Deadlock detection
|
|
2370
|
+
this.eventBus.on(SystemEventTypes.DEADLOCK_DETECTED, (event: IEvent) => {
|
|
2371
|
+
const { agents, resources } = event.payload as { agents: string[]; resources: string[] };
|
|
2372
|
+
console.warn('Deadlock detected:', { agents, resources });
|
|
2373
|
+
});
|
|
2374
|
+
}
|
|
2375
|
+
|
|
2376
|
+
/**
|
|
2377
|
+
* Get registered handler count for a type
|
|
2378
|
+
*/
|
|
2379
|
+
getHandlerCount(type: string): number {
|
|
2380
|
+
return this.handlers.get(type)?.size ?? 0;
|
|
2381
|
+
}
|
|
2382
|
+
|
|
2383
|
+
/**
|
|
2384
|
+
* Get all registered event types
|
|
2385
|
+
*/
|
|
2386
|
+
getRegisteredTypes(): string[] {
|
|
2387
|
+
return Array.from(this.handlers.keys());
|
|
2388
|
+
}
|
|
2389
|
+
|
|
2390
|
+
/**
|
|
2391
|
+
* Check if coordinator is initialized
|
|
2392
|
+
*/
|
|
2393
|
+
isInitialized(): boolean {
|
|
2394
|
+
return this.initialized;
|
|
2395
|
+
}
|
|
2396
|
+
}
|
|
2397
|
+
|
|
2398
|
+
|
|
2399
|
+
--- src/core/orchestrator/health-monitor.ts (truncated) ---
|
|
2400
|
+
/**
|
|
2401
|
+
* V3 Health Monitor
|
|
2402
|
+
* Decomposed from orchestrator.ts - Agent health checks
|
|
2403
|
+
* ~150 lines (target achieved)
|
|
2404
|
+
*/
|
|
2405
|
+
|
|
2406
|
+
import type {
|
|
2407
|
+
IHealthMonitor,
|
|
2408
|
+
IHealthStatus,
|
|
2409
|
+
IComponentHealth,
|
|
2410
|
+
} from '../interfaces/coordinator.interface.js';
|
|
2411
|
+
import type { IEventBus } from '../interfaces/event.interface.js';
|
|
2412
|
+
import { SystemEventTypes } from '../interfaces/event.interface.js';
|
|
2413
|
+
|
|
2414
|
+
/**
|
|
2415
|
+
* Health check function type
|
|
2416
|
+
*/
|
|
2417
|
+
export type HealthCheckFn = () => Promise<{
|
|
2418
|
+
healthy: boolean;
|
|
2419
|
+
error?: string;
|
|
2420
|
+
metrics?: Record<string, number>;
|
|
2421
|
+
}>;
|
|
2422
|
+
|
|
2423
|
+
/**
|
|
2424
|
+
* Health monitor configuration
|
|
2425
|
+
*/
|
|
2426
|
+
export interface HealthMonitorConfig {
|
|
2427
|
+
checkInterval: number;
|
|
2428
|
+
historyLimit: number;
|
|
2429
|
+
degradedThreshold: number;
|
|
2430
|
+
unhealthyThreshold: number;
|
|
2431
|
+
}
|
|
2432
|
+
|
|
2433
|
+
/**
|
|
2434
|
+
* Health monitor implementation
|
|
2435
|
+
*/
|
|
2436
|
+
export class HealthMonitor implements IHealthMonitor {
|
|
2437
|
+
private checks = new Map<string, HealthCheckFn>();
|
|
2438
|
+
private history: IHealthStatus[] = [];
|
|
2439
|
+
private interval?: ReturnType<typeof setInterval>;
|
|
2440
|
+
private listeners: Array<(status: IHealthStatus) => void> = [];
|
|
2441
|
+
private running = false;
|
|
2442
|
+
|
|
2443
|
+
constructor(
|
|
2444
|
+
private eventBus: IEventBus,
|
|
2445
|
+
private config: HealthMonitorConfig = {
|
|
2446
|
+
checkInterval: 30000,
|
|
2447
|
+
historyLimit: 100,
|
|
2448
|
+
degradedThreshold: 1,
|
|
2449
|
+
unhealthyThreshold: 2,
|
|
2450
|
+
},
|
|
2451
|
+
) {}
|
|
2452
|
+
|
|
2453
|
+
start(): void {
|
|
2454
|
+
if (this.running) {
|
|
2455
|
+
return;
|
|
2456
|
+
}
|
|
2457
|
+
|
|
2458
|
+
this.running = true;
|
|
2459
|
+
this.interval = setInterval(async () => {
|
|
2460
|
+
const status = await this.getStatus();
|
|
2461
|
+
this.addToHistory(status);
|
|
2462
|
+
this.notifyListeners(status);
|
|
2463
|
+
this.eventBus.emit(SystemEventTypes.SYSTEM_HEALTHCHECK, { status });
|
|
2464
|
+
}, this.config.checkInterval);
|
|
2465
|
+
}
|
|
2466
|
+
|
|
2467
|
+
stop(): void {
|
|
2468
|
+
if (this.interval) {
|
|
2469
|
+
clearInterval(this.interval);
|
|
2470
|
+
this.interval = undefined;
|
|
2471
|
+
}
|
|
2472
|
+
this.running = false;
|
|
2473
|
+
}
|
|
2474
|
+
|
|
2475
|
+
async getStatus(): Promise<IHealthStatus> {
|
|
2476
|
+
const components: Record<string, IComponentHealth> = {};
|
|
2477
|
+
let unhealthyCount = 0;
|
|
2478
|
+
let degradedCount = 0;
|
|
2479
|
+
|
|
2480
|
+
const checkPromises = Array.from(this.checks.entries()).map(
|
|
2481
|
+
async ([name, check]) => {
|
|
2482
|
+
try {
|
|
2483
|
+
const result = await Promise.race([
|
|
2484
|
+
check(),
|
|
2485
|
+
this.timeout(5000, 'Health check timeout'),
|
|
2486
|
+
]);
|
|
2487
|
+
|
|
2488
|
+
const health: IComponentHealth = {
|
|
2489
|
+
name,
|
|
2490
|
+
status: result.healthy ? 'healthy' : 'unhealthy',
|
|
2491
|
+
lastCheck: new Date(),
|
|
2492
|
+
error: result.error,
|
|
2493
|
+
metrics: result.metrics,
|
|
2494
|
+
};
|
|
2495
|
+
|
|
2496
|
+
return { name, health };
|
|
2497
|
+
} catch (error) {
|
|
2498
|
+
return {
|
|
2499
|
+
name,
|
|
2500
|
+
health: {
|
|
2501
|
+
name,
|
|
2502
|
+
status: 'unhealthy' as const,
|
|
2503
|
+
lastCheck: new Date(),
|
|
2504
|
+
error: error instanceof Error ? error.message : 'Unknown error',
|
|
2505
|
+
},
|
|
2506
|
+
};
|
|
2507
|
+
}
|
|
2508
|
+
},
|
|
2509
|
+
);
|
|
2510
|
+
|
|
2511
|
+
const results = await Promise.allSettled(checkPromises);
|
|
2512
|
+
|
|
2513
|
+
for (const result of results) {
|
|
2514
|
+
if (result.status === 'fulfilled') {
|
|
2515
|
+
const { name, health } = result.value;
|
|
2516
|
+
components[name] = health;
|
|
2517
|
+
|
|
2518
|
+
if (health.status === 'unhealthy') {
|
|
2519
|
+
unhealthyCount++;
|
|
2520
|
+
} else if (health.status === 'degraded') {
|
|
2521
|
+
degradedCount++;
|
|
2522
|
+
}
|
|
2523
|
+
}
|
|
2524
|
+
}
|
|
2525
|
+
|
|
2526
|
+
let overallStatus: IHealthStatus['status'] = 'healthy';
|
|
2527
|
+
if (unhealthyCount >= this.config.unhealthyThreshold) {
|
|
2528
|
+
overallStatus = 'unhealthy';
|
|
2529
|
+
} else if (
|
|
2530
|
+
unhealthyCount > 0 ||
|
|
2531
|
+
degradedCount >= this.config.degradedThreshold
|
|
2532
|
+
) {
|
|
2533
|
+
overallStatus = 'degraded';
|
|
2534
|
+
}
|
|
2535
|
+
|
|
2536
|
+
return {
|
|
2537
|
+
status: overallStatus,
|
|
2538
|
+
components,
|
|
2539
|
+
timestamp: new Date(),
|
|
2540
|
+
};
|
|
2541
|
+
}
|
|
2542
|
+
|
|
2543
|
+
registerCheck(name: string, check: HealthCheckFn): void {
|
|
2544
|
+
this.checks.set(name, check);
|
|
2545
|
+
}
|
|
2546
|
+
|
|
2547
|
+
unregisterCheck(name: string): void {
|
|
2548
|
+
this.checks.delete(name);
|
|
2549
|
+
}
|
|
2550
|
+
|
|
2551
|
+
getHistory(limit?: number): IHealthStatus[] {
|
|
2552
|
+
const count = limit ?? this.config.historyLimit;
|
|
2553
|
+
return this.history.slice(-count);
|
|
2554
|
+
}
|
|
2555
|
+
|
|
2556
|
+
onHealthChange(callback: (status: IHealthStatus) => void): () => void {
|
|
2557
|
+
this.listeners.push(callback);
|
|
2558
|
+
return () => {
|
|
2559
|
+
const index = this.listeners.indexOf(callback);
|
|
2560
|
+
if (index !== -1) {
|
|
2561
|
+
this.listeners.splice(index, 1);
|
|
2562
|
+
}
|
|
2563
|
+
};
|
|
2564
|
+
}
|
|
2565
|
+
|
|
2566
|
+
private addToHistory(status: IHealthStatus): void {
|
|
2567
|
+
this.history.push(status);
|
|
2568
|
+
|
|
2569
|
+
// Trim history to limit
|
|
2570
|
+
if (this.history.length > this.config.historyLimit) {
|
|
2571
|
+
this.history = this.history.slice(-this.config.historyLimit);
|
|
2572
|
+
}
|
|
2573
|
+
}
|
|
2574
|
+
|
|
2575
|
+
private notifyListeners(status: IHealthStatus): void {
|
|
2576
|
+
for (const listener of this.listeners) {
|
|
2577
|
+
try {
|
|
2578
|
+
listener(status);
|
|
2579
|
+
} catch {
|
|
2580
|
+
// Ignore listener errors
|
|
2581
|
+
}
|
|
2582
|
+
}
|
|
2583
|
+
}
|
|
2584
|
+
|
|
2585
|
+
private timeout(ms: number, message: string): Promise<never> {
|
|
2586
|
+
return new Promise((_, reject) => {
|
|
2587
|
+
setTimeout(() => reject(new Error(message)), ms);
|
|
2588
|
+
});
|
|
2589
|
+
}
|
|
2590
|
+
|
|
2591
|
+
/**
|
|
2592
|
+
* Get component health by name
|
|
2593
|
+
*/
|
|
2594
|
+
async getComponentHealth(name: string): Promise<IComponentHealth | undefined> {
|
|
2595
|
+
const status = await this.getStatus();
|
|
2596
|
+
|
|
2597
|
+
|
|
2598
|
+
--- src/core/orchestrator/index.ts ---
|
|
2599
|
+
/**
|
|
2600
|
+
* V3 Orchestrator Facade
|
|
2601
|
+
* Unified interface to decomposed orchestrator components
|
|
2602
|
+
* ~50 lines (target achieved)
|
|
2603
|
+
*/
|
|
2604
|
+
|
|
2605
|
+
import type { IOrchestrator, IHealthStatus, IOrchestratorMetrics } from '../interfaces/coordinator.interface.js';
|
|
2606
|
+
import type { ITask, ITaskCreate, ITaskResult } from '../interfaces/task.interface.js';
|
|
2607
|
+
import type { IAgent, IAgentConfig } from '../interfaces/agent.interface.js';
|
|
2608
|
+
import type { IEventBus } from '../interfaces/event.interface.js';
|
|
2609
|
+
|
|
2610
|
+
import { TaskManager } from './task-manager.js';
|
|
2611
|
+
import { SessionManager, type ISessionManager, type SessionManagerConfig } from './session-manager.js';
|
|
2612
|
+
import { HealthMonitor, type HealthMonitorConfig } from './health-monitor.js';
|
|
2613
|
+
import { LifecycleManager, type LifecycleManagerConfig } from './lifecycle-manager.js';
|
|
2614
|
+
import { EventCoordinator } from './event-coordinator.js';
|
|
2615
|
+
import { EventBus } from '../event-bus.js';
|
|
2616
|
+
|
|
2617
|
+
export * from './task-manager.js';
|
|
2618
|
+
export * from './session-manager.js';
|
|
2619
|
+
export * from './health-monitor.js';
|
|
2620
|
+
export * from './lifecycle-manager.js';
|
|
2621
|
+
export * from './event-coordinator.js';
|
|
2622
|
+
|
|
2623
|
+
/**
|
|
2624
|
+
* Orchestrator facade configuration
|
|
2625
|
+
* (Note: For schema-validated config, use OrchestratorConfig from config/schema.ts)
|
|
2626
|
+
*/
|
|
2627
|
+
export interface OrchestratorFacadeConfig {
|
|
2628
|
+
session: SessionManagerConfig;
|
|
2629
|
+
health: HealthMonitorConfig;
|
|
2630
|
+
lifecycle: LifecycleManagerConfig;
|
|
2631
|
+
}
|
|
2632
|
+
|
|
2633
|
+
/**
|
|
2634
|
+
* Default orchestrator facade configuration
|
|
2635
|
+
*/
|
|
2636
|
+
export const defaultOrchestratorFacadeConfig: OrchestratorFacadeConfig = {
|
|
2637
|
+
session: {
|
|
2638
|
+
persistSessions: true,
|
|
2639
|
+
dataDir: './data',
|
|
2640
|
+
sessionRetentionMs: 3600000,
|
|
2641
|
+
},
|
|
2642
|
+
health: {
|
|
2643
|
+
checkInterval: 30000,
|
|
2644
|
+
historyLimit: 100,
|
|
2645
|
+
degradedThreshold: 1,
|
|
2646
|
+
unhealthyThreshold: 2,
|
|
2647
|
+
},
|
|
2648
|
+
lifecycle: {
|
|
2649
|
+
maxConcurrentAgents: 20,
|
|
2650
|
+
spawnTimeout: 30000,
|
|
2651
|
+
terminateTimeout: 10000,
|
|
2652
|
+
maxSpawnRetries: 3,
|
|
2653
|
+
},
|
|
2654
|
+
};
|
|
2655
|
+
|
|
2656
|
+
/**
|
|
2657
|
+
* Create orchestrator components
|
|
2658
|
+
*/
|
|
2659
|
+
export function createOrchestrator(config: Partial<OrchestratorFacadeConfig> = {}) {
|
|
2660
|
+
const mergedConfig: OrchestratorFacadeConfig = {
|
|
2661
|
+
session: { ...defaultOrchestratorFacadeConfig.session, ...config.session },
|
|
2662
|
+
health: { ...defaultOrchestratorFacadeConfig.health, ...config.health },
|
|
2663
|
+
lifecycle: { ...defaultOrchestratorFacadeConfig.lifecycle, ...config.lifecycle },
|
|
2664
|
+
};
|
|
2665
|
+
|
|
2666
|
+
const eventBus = new EventBus();
|
|
2667
|
+
const taskManager = new TaskManager(eventBus);
|
|
2668
|
+
const sessionManager = new SessionManager(eventBus, mergedConfig.session);
|
|
2669
|
+
const healthMonitor = new HealthMonitor(eventBus, mergedConfig.health);
|
|
2670
|
+
const lifecycleManager = new LifecycleManager(eventBus, mergedConfig.lifecycle);
|
|
2671
|
+
const eventCoordinator = new EventCoordinator(eventBus);
|
|
2672
|
+
|
|
2673
|
+
return {
|
|
2674
|
+
eventBus,
|
|
2675
|
+
taskManager,
|
|
2676
|
+
sessionManager,
|
|
2677
|
+
healthMonitor,
|
|
2678
|
+
lifecycleManager,
|
|
2679
|
+
eventCoordinator,
|
|
2680
|
+
config: mergedConfig,
|
|
2681
|
+
};
|
|
2682
|
+
}
|
|
2683
|
+
|
|
2684
|
+
/**
|
|
2685
|
+
* Orchestrator type for facade
|
|
2686
|
+
*/
|
|
2687
|
+
export type OrchestratorComponents = ReturnType<typeof createOrchestrator>;
|
|
2688
|
+
|
|
2689
|
+
|
|
2690
|
+
--- src/core/orchestrator/lifecycle-manager.ts (truncated) ---
|
|
2691
|
+
/**
|
|
2692
|
+
* V3 Lifecycle Manager
|
|
2693
|
+
* Decomposed from orchestrator.ts - Agent spawn/terminate
|
|
2694
|
+
* ~150 lines (target achieved)
|
|
2695
|
+
*/
|
|
2696
|
+
|
|
2697
|
+
import type {
|
|
2698
|
+
IAgent,
|
|
2699
|
+
IAgentConfig,
|
|
2700
|
+
IAgentLifecycleManager,
|
|
2701
|
+
IAgentPool,
|
|
2702
|
+
AgentStatus,
|
|
2703
|
+
} from '../interfaces/agent.interface.js';
|
|
2704
|
+
import type { IEventBus } from '../interfaces/event.interface.js';
|
|
2705
|
+
import { SystemEventTypes } from '../interfaces/event.interface.js';
|
|
2706
|
+
|
|
2707
|
+
/**
|
|
2708
|
+
* Agent pool implementation
|
|
2709
|
+
*/
|
|
2710
|
+
export class AgentPool implements IAgentPool {
|
|
2711
|
+
private agents = new Map<string, IAgent>();
|
|
2712
|
+
|
|
2713
|
+
add(agent: IAgent): void {
|
|
2714
|
+
this.agents.set(agent.id, agent);
|
|
2715
|
+
}
|
|
2716
|
+
|
|
2717
|
+
remove(agentId: string): boolean {
|
|
2718
|
+
return this.agents.delete(agentId);
|
|
2719
|
+
}
|
|
2720
|
+
|
|
2721
|
+
get(agentId: string): IAgent | undefined {
|
|
2722
|
+
return this.agents.get(agentId);
|
|
2723
|
+
}
|
|
2724
|
+
|
|
2725
|
+
getAll(): IAgent[] {
|
|
2726
|
+
return Array.from(this.agents.values());
|
|
2727
|
+
}
|
|
2728
|
+
|
|
2729
|
+
getByStatus(status: AgentStatus): IAgent[] {
|
|
2730
|
+
return this.getAll().filter(agent => agent.status === status);
|
|
2731
|
+
}
|
|
2732
|
+
|
|
2733
|
+
getByType(type: string): IAgent[] {
|
|
2734
|
+
return this.getAll().filter(agent => agent.type === type);
|
|
2735
|
+
}
|
|
2736
|
+
|
|
2737
|
+
getAvailable(): IAgent[] {
|
|
2738
|
+
return this.getAll().filter(
|
|
2739
|
+
agent =>
|
|
2740
|
+
(agent.status === 'active' || agent.status === 'idle') &&
|
|
2741
|
+
agent.currentTaskCount < agent.config.maxConcurrentTasks,
|
|
2742
|
+
);
|
|
2743
|
+
}
|
|
2744
|
+
|
|
2745
|
+
size(): number {
|
|
2746
|
+
return this.agents.size;
|
|
2747
|
+
}
|
|
2748
|
+
|
|
2749
|
+
hasCapacity(maxSize: number): boolean {
|
|
2750
|
+
return this.agents.size < maxSize;
|
|
2751
|
+
}
|
|
2752
|
+
|
|
2753
|
+
clear(): void {
|
|
2754
|
+
this.agents.clear();
|
|
2755
|
+
}
|
|
2756
|
+
}
|
|
2757
|
+
|
|
2758
|
+
/**
|
|
2759
|
+
* Lifecycle manager configuration
|
|
2760
|
+
*/
|
|
2761
|
+
export interface LifecycleManagerConfig {
|
|
2762
|
+
maxConcurrentAgents: number;
|
|
2763
|
+
spawnTimeout: number;
|
|
2764
|
+
terminateTimeout: number;
|
|
2765
|
+
maxSpawnRetries: number;
|
|
2766
|
+
}
|
|
2767
|
+
|
|
2768
|
+
/**
|
|
2769
|
+
* Lifecycle manager implementation
|
|
2770
|
+
*/
|
|
2771
|
+
export class LifecycleManager implements IAgentLifecycleManager {
|
|
2772
|
+
private pool: IAgentPool;
|
|
2773
|
+
|
|
2774
|
+
constructor(
|
|
2775
|
+
private eventBus: IEventBus,
|
|
2776
|
+
private config: LifecycleManagerConfig,
|
|
2777
|
+
pool?: IAgentPool,
|
|
2778
|
+
) {
|
|
2779
|
+
this.pool = pool ?? new AgentPool();
|
|
2780
|
+
}
|
|
2781
|
+
|
|
2782
|
+
async spawn(config: IAgentConfig): Promise<IAgent> {
|
|
2783
|
+
// Validate capacity
|
|
2784
|
+
if (!this.pool.hasCapacity(this.config.maxConcurrentAgents)) {
|
|
2785
|
+
throw new Error('Maximum concurrent agents reached');
|
|
2786
|
+
}
|
|
2787
|
+
|
|
2788
|
+
// Validate agent doesn't already exist
|
|
2789
|
+
if (this.pool.get(config.id)) {
|
|
2790
|
+
throw new Error(`Agent with ID ${config.id} already exists`);
|
|
2791
|
+
}
|
|
2792
|
+
|
|
2793
|
+
const agent: IAgent = {
|
|
2794
|
+
id: config.id,
|
|
2795
|
+
name: config.name,
|
|
2796
|
+
type: config.type,
|
|
2797
|
+
config,
|
|
2798
|
+
createdAt: new Date(),
|
|
2799
|
+
status: 'spawning',
|
|
2800
|
+
currentTaskCount: 0,
|
|
2801
|
+
lastActivity: new Date(),
|
|
2802
|
+
metrics: {
|
|
2803
|
+
tasksCompleted: 0,
|
|
2804
|
+
tasksFailed: 0,
|
|
2805
|
+
avgTaskDuration: 0,
|
|
2806
|
+
errorCount: 0,
|
|
2807
|
+
uptime: 0,
|
|
2808
|
+
},
|
|
2809
|
+
};
|
|
2810
|
+
|
|
2811
|
+
// Add to pool
|
|
2812
|
+
this.pool.add(agent);
|
|
2813
|
+
|
|
2814
|
+
// Mark as active
|
|
2815
|
+
agent.status = 'active';
|
|
2816
|
+
|
|
2817
|
+
this.eventBus.emit(SystemEventTypes.AGENT_SPAWNED, {
|
|
2818
|
+
agentId: agent.id,
|
|
2819
|
+
profile: config,
|
|
2820
|
+
sessionId: undefined,
|
|
2821
|
+
});
|
|
2822
|
+
|
|
2823
|
+
return agent;
|
|
2824
|
+
}
|
|
2825
|
+
|
|
2826
|
+
async spawnBatch(configs: IAgentConfig[]): Promise<Map<string, IAgent>> {
|
|
2827
|
+
const results = new Map<string, IAgent>();
|
|
2828
|
+
|
|
2829
|
+
// Check total capacity
|
|
2830
|
+
if (this.pool.size() + configs.length > this.config.maxConcurrentAgents) {
|
|
2831
|
+
throw new Error('Batch would exceed maximum concurrent agents');
|
|
2832
|
+
}
|
|
2833
|
+
|
|
2834
|
+
// Spawn in parallel
|
|
2835
|
+
const spawnPromises = configs.map(async config => {
|
|
2836
|
+
try {
|
|
2837
|
+
const agent = await this.spawn(config);
|
|
2838
|
+
return { id: config.id, agent, error: null };
|
|
2839
|
+
} catch (error) {
|
|
2840
|
+
return { id: config.id, agent: null, error };
|
|
2841
|
+
}
|
|
2842
|
+
});
|
|
2843
|
+
|
|
2844
|
+
const settled = await Promise.allSettled(spawnPromises);
|
|
2845
|
+
|
|
2846
|
+
for (const result of settled) {
|
|
2847
|
+
if (result.status === 'fulfilled' && result.value.agent) {
|
|
2848
|
+
results.set(result.value.id, result.value.agent);
|
|
2849
|
+
}
|
|
2850
|
+
}
|
|
2851
|
+
|
|
2852
|
+
return results;
|
|
2853
|
+
}
|
|
2854
|
+
|
|
2855
|
+
async terminate(agentId: string, reason?: string): Promise<void> {
|
|
2856
|
+
const agent = this.pool.get(agentId);
|
|
2857
|
+
if (!agent) {
|
|
2858
|
+
throw new Error(`Agent not found: ${agentId}`);
|
|
2859
|
+
}
|
|
2860
|
+
|
|
2861
|
+
agent.status = 'terminated';
|
|
2862
|
+
|
|
2863
|
+
// Remove from pool
|
|
2864
|
+
this.pool.remove(agentId);
|
|
2865
|
+
|
|
2866
|
+
this.eventBus.emit(SystemEventTypes.AGENT_TERMINATED, {
|
|
2867
|
+
agentId,
|
|
2868
|
+
reason: reason ?? 'User requested',
|
|
2869
|
+
});
|
|
2870
|
+
}
|
|
2871
|
+
|
|
2872
|
+
async terminateAll(reason?: string): Promise<void> {
|
|
2873
|
+
const agents = this.pool.getAll();
|
|
2874
|
+
await Promise.allSettled(
|
|
2875
|
+
agents.map(agent => this.terminate(agent.id, reason)),
|
|
2876
|
+
);
|
|
2877
|
+
}
|
|
2878
|
+
|
|
2879
|
+
async restart(agentId: string): Promise<IAgent> {
|
|
2880
|
+
const agent = this.pool.get(agentId);
|
|
2881
|
+
if (!agent) {
|
|
2882
|
+
throw new Error(`Agent not found: ${agentId}`);
|
|
2883
|
+
}
|
|
2884
|
+
|
|
2885
|
+
const config = agent.config;
|
|
2886
|
+
await this.terminate(agentId, 'Restart requested');
|
|
2887
|
+
return this.spawn(config);
|
|
2888
|
+
}
|
|
2889
|
+
|
|
2890
|
+
async updateConfig(agentId: string, config: Partial<IAgentConfig>): Promise<void> {
|
|
2891
|
+
const agent = this.pool.get(agentId);
|
|
2892
|
+
if (!agent) {
|
|
2893
|
+
throw new Error(`Agent not found: ${agentId}`);
|
|
2894
|
+
}
|
|
2895
|
+
|
|
2896
|
+
Object.assign(agent.config,
|
|
2897
|
+
|
|
2898
|
+
--- src/core/orchestrator/session-manager.ts (truncated) ---
|
|
2899
|
+
/**
|
|
2900
|
+
* V3 Session Manager
|
|
2901
|
+
* Decomposed from orchestrator.ts - Session handling
|
|
2902
|
+
* ~200 lines (target achieved)
|
|
2903
|
+
*/
|
|
2904
|
+
|
|
2905
|
+
import type { IAgentSession } from '../interfaces/agent.interface.js';
|
|
2906
|
+
import type { IEventBus } from '../interfaces/event.interface.js';
|
|
2907
|
+
import { SystemEventTypes } from '../interfaces/event.interface.js';
|
|
2908
|
+
import type { AgentProfile } from '../../types/agent.types.js';
|
|
2909
|
+
import { mkdir, writeFile, readFile } from 'fs/promises';
|
|
2910
|
+
import { join, dirname } from 'path';
|
|
2911
|
+
import { randomBytes } from 'crypto';
|
|
2912
|
+
|
|
2913
|
+
// Secure session ID generation
|
|
2914
|
+
function generateSecureSessionId(): string {
|
|
2915
|
+
const timestamp = Date.now().toString(36);
|
|
2916
|
+
const random = randomBytes(12).toString('hex');
|
|
2917
|
+
return `session_${timestamp}_${random}`;
|
|
2918
|
+
}
|
|
2919
|
+
|
|
2920
|
+
/**
|
|
2921
|
+
* Session persistence structure
|
|
2922
|
+
*/
|
|
2923
|
+
export interface SessionPersistence {
|
|
2924
|
+
sessions: Array<IAgentSession & { profile: AgentProfile }>;
|
|
2925
|
+
metrics: {
|
|
2926
|
+
completedTasks: number;
|
|
2927
|
+
failedTasks: number;
|
|
2928
|
+
totalTaskDuration: number;
|
|
2929
|
+
};
|
|
2930
|
+
savedAt: Date;
|
|
2931
|
+
}
|
|
2932
|
+
|
|
2933
|
+
/**
|
|
2934
|
+
* Session manager configuration
|
|
2935
|
+
*/
|
|
2936
|
+
export interface SessionManagerConfig {
|
|
2937
|
+
persistSessions: boolean;
|
|
2938
|
+
dataDir: string;
|
|
2939
|
+
sessionRetentionMs?: number;
|
|
2940
|
+
}
|
|
2941
|
+
|
|
2942
|
+
/**
|
|
2943
|
+
* Session manager interface
|
|
2944
|
+
*/
|
|
2945
|
+
export interface ISessionManager {
|
|
2946
|
+
createSession(profile: AgentProfile, terminalId: string, memoryBankId: string): Promise<IAgentSession>;
|
|
2947
|
+
getSession(sessionId: string): IAgentSession | undefined;
|
|
2948
|
+
getActiveSessions(): IAgentSession[];
|
|
2949
|
+
getSessionsByAgent(agentId: string): IAgentSession[];
|
|
2950
|
+
terminateSession(sessionId: string): Promise<void>;
|
|
2951
|
+
terminateAllSessions(): Promise<void>;
|
|
2952
|
+
persistSessions(): Promise<void>;
|
|
2953
|
+
restoreSessions(): Promise<SessionPersistence | null>;
|
|
2954
|
+
removeSession(sessionId: string): void;
|
|
2955
|
+
updateSessionActivity(sessionId: string): void;
|
|
2956
|
+
}
|
|
2957
|
+
|
|
2958
|
+
/**
|
|
2959
|
+
* Session manager implementation
|
|
2960
|
+
*/
|
|
2961
|
+
export class SessionManager implements ISessionManager {
|
|
2962
|
+
private sessions = new Map<string, IAgentSession>();
|
|
2963
|
+
private sessionProfiles = new Map<string, AgentProfile>();
|
|
2964
|
+
private persistencePath: string;
|
|
2965
|
+
|
|
2966
|
+
constructor(
|
|
2967
|
+
private eventBus: IEventBus,
|
|
2968
|
+
private config: SessionManagerConfig,
|
|
2969
|
+
) {
|
|
2970
|
+
this.persistencePath = join(config.dataDir || './data', 'sessions.json');
|
|
2971
|
+
}
|
|
2972
|
+
|
|
2973
|
+
async createSession(
|
|
2974
|
+
profile: AgentProfile,
|
|
2975
|
+
terminalId: string,
|
|
2976
|
+
memoryBankId: string,
|
|
2977
|
+
): Promise<IAgentSession> {
|
|
2978
|
+
const session: IAgentSession = {
|
|
2979
|
+
id: generateSecureSessionId(),
|
|
2980
|
+
agentId: profile.id,
|
|
2981
|
+
terminalId,
|
|
2982
|
+
startTime: new Date(),
|
|
2983
|
+
status: 'active',
|
|
2984
|
+
lastActivity: new Date(),
|
|
2985
|
+
memoryBankId,
|
|
2986
|
+
};
|
|
2987
|
+
|
|
2988
|
+
this.sessions.set(session.id, session);
|
|
2989
|
+
this.sessionProfiles.set(session.id, profile);
|
|
2990
|
+
|
|
2991
|
+
this.eventBus.emit(SystemEventTypes.SESSION_CREATED, {
|
|
2992
|
+
sessionId: session.id,
|
|
2993
|
+
agentId: profile.id,
|
|
2994
|
+
terminalId,
|
|
2995
|
+
memoryBankId,
|
|
2996
|
+
});
|
|
2997
|
+
|
|
2998
|
+
// Persist sessions asynchronously
|
|
2999
|
+
this.persistSessions().catch(() => {
|
|
3000
|
+
// Silently ignore persistence errors
|
|
3001
|
+
});
|
|
3002
|
+
|
|
3003
|
+
return session;
|
|
3004
|
+
}
|
|
3005
|
+
|
|
3006
|
+
getSession(sessionId: string): IAgentSession | undefined {
|
|
3007
|
+
return this.sessions.get(sessionId);
|
|
3008
|
+
}
|
|
3009
|
+
|
|
3010
|
+
getActiveSessions(): IAgentSession[] {
|
|
3011
|
+
return Array.from(this.sessions.values()).filter(
|
|
3012
|
+
session => session.status === 'active' || session.status === 'idle',
|
|
3013
|
+
);
|
|
3014
|
+
}
|
|
3015
|
+
|
|
3016
|
+
getSessionsByAgent(agentId: string): IAgentSession[] {
|
|
3017
|
+
return Array.from(this.sessions.values()).filter(
|
|
3018
|
+
session => session.agentId === agentId,
|
|
3019
|
+
);
|
|
3020
|
+
}
|
|
3021
|
+
|
|
3022
|
+
async terminateSession(sessionId: string): Promise<void> {
|
|
3023
|
+
const session = this.sessions.get(sessionId);
|
|
3024
|
+
if (!session) {
|
|
3025
|
+
throw new Error(`Session not found: ${sessionId}`);
|
|
3026
|
+
}
|
|
3027
|
+
|
|
3028
|
+
session.status = 'terminated';
|
|
3029
|
+
session.endTime = new Date();
|
|
3030
|
+
|
|
3031
|
+
const duration = session.endTime.getTime() - session.startTime.getTime();
|
|
3032
|
+
|
|
3033
|
+
this.eventBus.emit(SystemEventTypes.SESSION_TERMINATED, {
|
|
3034
|
+
sessionId,
|
|
3035
|
+
agentId: session.agentId,
|
|
3036
|
+
duration,
|
|
3037
|
+
});
|
|
3038
|
+
|
|
3039
|
+
// Clean up profile reference
|
|
3040
|
+
this.sessionProfiles.delete(sessionId);
|
|
3041
|
+
|
|
3042
|
+
// Persist sessions asynchronously
|
|
3043
|
+
this.persistSessions().catch(() => {
|
|
3044
|
+
// Silently ignore persistence errors
|
|
3045
|
+
});
|
|
3046
|
+
}
|
|
3047
|
+
|
|
3048
|
+
async terminateAllSessions(): Promise<void> {
|
|
3049
|
+
const sessions = this.getActiveSessions();
|
|
3050
|
+
const batchSize = 5;
|
|
3051
|
+
|
|
3052
|
+
for (let i = 0; i < sessions.length; i += batchSize) {
|
|
3053
|
+
const batch = sessions.slice(i, i + batchSize);
|
|
3054
|
+
await Promise.allSettled(
|
|
3055
|
+
batch.map(session => this.terminateSession(session.id)),
|
|
3056
|
+
);
|
|
3057
|
+
}
|
|
3058
|
+
}
|
|
3059
|
+
|
|
3060
|
+
removeSession(sessionId: string): void {
|
|
3061
|
+
this.sessions.delete(sessionId);
|
|
3062
|
+
this.sessionProfiles.delete(sessionId);
|
|
3063
|
+
}
|
|
3064
|
+
|
|
3065
|
+
updateSessionActivity(sessionId: string): void {
|
|
3066
|
+
const session = this.sessions.get(sessionId);
|
|
3067
|
+
if (session) {
|
|
3068
|
+
session.lastActivity = new Date();
|
|
3069
|
+
}
|
|
3070
|
+
}
|
|
3071
|
+
|
|
3072
|
+
async persistSessions(): Promise<void> {
|
|
3073
|
+
if (!this.config.persistSessions) {
|
|
3074
|
+
return;
|
|
3075
|
+
}
|
|
3076
|
+
|
|
3077
|
+
try {
|
|
3078
|
+
const data: SessionPersistence = {
|
|
3079
|
+
sessions: Array.from(this.sessions.valu
|
|
3080
|
+
|
|
3081
|
+
--- src/core/orchestrator/task-manager.ts (truncated) ---
|
|
3082
|
+
/**
|
|
3083
|
+
* V3 Task Manager
|
|
3084
|
+
* Decomposed from orchestrator.ts - Task lifecycle management
|
|
3085
|
+
* ~200 lines (target achieved)
|
|
3086
|
+
*/
|
|
3087
|
+
|
|
3088
|
+
import type {
|
|
3089
|
+
ITask,
|
|
3090
|
+
ITaskCreate,
|
|
3091
|
+
ITaskResult,
|
|
3092
|
+
ITaskManager,
|
|
3093
|
+
ITaskQueue,
|
|
3094
|
+
TaskManagerMetrics,
|
|
3095
|
+
TaskStatus,
|
|
3096
|
+
} from '../interfaces/task.interface.js';
|
|
3097
|
+
import type { IEventBus, SystemEventType } from '../interfaces/event.interface.js';
|
|
3098
|
+
import { SystemEventTypes } from '../interfaces/event.interface.js';
|
|
3099
|
+
import { randomBytes } from 'crypto';
|
|
3100
|
+
|
|
3101
|
+
// Secure task ID generation
|
|
3102
|
+
function generateSecureTaskId(): string {
|
|
3103
|
+
const timestamp = Date.now().toString(36);
|
|
3104
|
+
const random = randomBytes(12).toString('hex');
|
|
3105
|
+
return `task_${timestamp}_${random}`;
|
|
3106
|
+
}
|
|
3107
|
+
|
|
3108
|
+
/**
|
|
3109
|
+
* Priority queue implementation for tasks
|
|
3110
|
+
*/
|
|
3111
|
+
export class TaskQueue implements ITaskQueue {
|
|
3112
|
+
private tasks: ITask[] = [];
|
|
3113
|
+
|
|
3114
|
+
async enqueue(task: ITask): Promise<void> {
|
|
3115
|
+
this.tasks.push(task);
|
|
3116
|
+
this.tasks.sort((a, b) => b.priority - a.priority);
|
|
3117
|
+
}
|
|
3118
|
+
|
|
3119
|
+
async dequeue(): Promise<ITask | undefined> {
|
|
3120
|
+
return this.tasks.shift();
|
|
3121
|
+
}
|
|
3122
|
+
|
|
3123
|
+
async peek(): Promise<ITask | undefined> {
|
|
3124
|
+
return this.tasks[0];
|
|
3125
|
+
}
|
|
3126
|
+
|
|
3127
|
+
size(): number {
|
|
3128
|
+
return this.tasks.length;
|
|
3129
|
+
}
|
|
3130
|
+
|
|
3131
|
+
isEmpty(): boolean {
|
|
3132
|
+
return this.tasks.length === 0;
|
|
3133
|
+
}
|
|
3134
|
+
|
|
3135
|
+
async clear(): Promise<void> {
|
|
3136
|
+
this.tasks = [];
|
|
3137
|
+
}
|
|
3138
|
+
|
|
3139
|
+
async getAll(): Promise<ITask[]> {
|
|
3140
|
+
return [...this.tasks];
|
|
3141
|
+
}
|
|
3142
|
+
|
|
3143
|
+
async remove(taskId: string): Promise<boolean> {
|
|
3144
|
+
const index = this.tasks.findIndex(t => t.id === taskId);
|
|
3145
|
+
if (index !== -1) {
|
|
3146
|
+
this.tasks.splice(index, 1);
|
|
3147
|
+
return true;
|
|
3148
|
+
}
|
|
3149
|
+
return false;
|
|
3150
|
+
}
|
|
3151
|
+
|
|
3152
|
+
async updatePriority(taskId: string, priority: number): Promise<boolean> {
|
|
3153
|
+
const task = this.tasks.find(t => t.id === taskId);
|
|
3154
|
+
if (task) {
|
|
3155
|
+
(task as { priority: number }).priority = priority;
|
|
3156
|
+
this.tasks.sort((a, b) => b.priority - a.priority);
|
|
3157
|
+
return true;
|
|
3158
|
+
}
|
|
3159
|
+
return false;
|
|
3160
|
+
}
|
|
3161
|
+
}
|
|
3162
|
+
|
|
3163
|
+
/**
|
|
3164
|
+
* Task manager implementation
|
|
3165
|
+
*/
|
|
3166
|
+
export class TaskManager implements ITaskManager {
|
|
3167
|
+
private tasks = new Map<string, ITask>();
|
|
3168
|
+
private queue: ITaskQueue;
|
|
3169
|
+
private metrics = {
|
|
3170
|
+
totalTasks: 0,
|
|
3171
|
+
completedTasks: 0,
|
|
3172
|
+
failedTasks: 0,
|
|
3173
|
+
cancelledTasks: 0,
|
|
3174
|
+
totalDuration: 0,
|
|
3175
|
+
totalWaitTime: 0,
|
|
3176
|
+
};
|
|
3177
|
+
|
|
3178
|
+
constructor(
|
|
3179
|
+
private eventBus: IEventBus,
|
|
3180
|
+
queue?: ITaskQueue,
|
|
3181
|
+
) {
|
|
3182
|
+
this.queue = queue ?? new TaskQueue();
|
|
3183
|
+
}
|
|
3184
|
+
|
|
3185
|
+
async createTask(params: ITaskCreate): Promise<ITask> {
|
|
3186
|
+
const task: ITask = {
|
|
3187
|
+
id: generateSecureTaskId(),
|
|
3188
|
+
type: params.type,
|
|
3189
|
+
description: params.description,
|
|
3190
|
+
priority: params.priority ?? 50,
|
|
3191
|
+
createdAt: new Date(),
|
|
3192
|
+
status: 'pending',
|
|
3193
|
+
timeout: params.timeout,
|
|
3194
|
+
assignedAgent: params.assignedAgent,
|
|
3195
|
+
input: params.input,
|
|
3196
|
+
metadata: params.metadata,
|
|
3197
|
+
};
|
|
3198
|
+
|
|
3199
|
+
this.tasks.set(task.id, task);
|
|
3200
|
+
this.metrics.totalTasks++;
|
|
3201
|
+
|
|
3202
|
+
this.eventBus.emit(SystemEventTypes.TASK_CREATED, { task });
|
|
3203
|
+
|
|
3204
|
+
return task;
|
|
3205
|
+
}
|
|
3206
|
+
|
|
3207
|
+
getTask(taskId: string): ITask | undefined {
|
|
3208
|
+
return this.tasks.get(taskId);
|
|
3209
|
+
}
|
|
3210
|
+
|
|
3211
|
+
getTasks(filter?: Partial<Pick<ITask, 'status' | 'type' | 'assignedAgent'>>): ITask[] {
|
|
3212
|
+
let tasks = Array.from(this.tasks.values());
|
|
3213
|
+
|
|
3214
|
+
if (filter) {
|
|
3215
|
+
if (filter.status) {
|
|
3216
|
+
tasks = tasks.filter(t => t.status === filter.status);
|
|
3217
|
+
}
|
|
3218
|
+
if (filter.type) {
|
|
3219
|
+
tasks = tasks.filter(t => t.type === filter.type);
|
|
3220
|
+
}
|
|
3221
|
+
if (filter.assignedAgent) {
|
|
3222
|
+
tasks = tasks.filter(t => t.assignedAgent === filter.assignedAgent);
|
|
3223
|
+
}
|
|
3224
|
+
}
|
|
3225
|
+
|
|
3226
|
+
return tasks;
|
|
3227
|
+
}
|
|
3228
|
+
|
|
3229
|
+
async assignTask(taskId: string, agentId: string): Promise<void> {
|
|
3230
|
+
const task = this.tasks.get(taskId);
|
|
3231
|
+
if (!task) {
|
|
3232
|
+
throw new Error(`Task not found: ${taskId}`);
|
|
3233
|
+
}
|
|
3234
|
+
|
|
3235
|
+
task.assignedAgent = agentId;
|
|
3236
|
+
task.status = 'assigned';
|
|
3237
|
+
|
|
3238
|
+
this.eventBus.emit(SystemEventTypes.TASK_ASSIGNED, {
|
|
3239
|
+
taskId,
|
|
3240
|
+
agentId,
|
|
3241
|
+
});
|
|
3242
|
+
}
|
|
3243
|
+
|
|
3244
|
+
async startTask(taskId: string): Promise<void> {
|
|
3245
|
+
const task = this.tasks.get(taskId);
|
|
3246
|
+
if (!task) {
|
|
3247
|
+
throw new Error(`Task not found: ${taskId}`);
|
|
3248
|
+
}
|
|
3249
|
+
|
|
3250
|
+
task.status = 'running';
|
|
3251
|
+
task.startedAt = new Date();
|
|
3252
|
+
|
|
3253
|
+
// Calculate wait time
|
|
3254
|
+
const waitTime = task.startedAt.getTime() - task.createdAt.getTime();
|
|
3255
|
+
this.metrics.totalWaitTime += waitTime;
|
|
3256
|
+
|
|
3257
|
+
this.eventBus.emit(SystemEventTypes.TASK_STARTED, {
|
|
3258
|
+
taskId,
|
|
3259
|
+
agentId: task.assignedAgent,
|
|
3260
|
+
startTime: task.startedAt,
|
|
3261
|
+
});
|
|
3262
|
+
}
|
|
3263
|
+
|
|
3264
|
+
async completeTask(taskId: string, result: ITaskResult): Promise<void> {
|
|
3265
|
+
const task = this.tasks.get(taskId);
|
|
3266
|
+
if (!task) {
|
|
3267
|
+
throw new Error(`Task not found: ${taskId}`);
|
|
3268
|
+
}
|
|
3269
|
+
|
|
3270
|
+
task.status = 'completed';
|
|
3271
|
+
task.completedAt = new Date();
|
|
3272
|
+
task.output = result.output;
|
|
3273
|
+
|
|
3274
|
+
this.metrics.completedTasks++;
|
|
3275
|
+
this.metrics.totalDuration += result.duration;
|
|
3276
|
+
|
|
3277
|
+
this.eventBus.emit(SystemEventTypes.TASK_COMPLETED, {
|
|
3278
|
+
taskId,
|
|
3279
|
+
result,
|
|
3280
|
+
});
|
|
3281
|
+
}
|
|
3282
|
+
|
|
3283
|
+
async failTask(taskId: string, error: Error): Promise<void> {
|
|
3284
|
+
const task = this.tasks.get(taskId);
|
|
3285
|
+
if (!task) {
|
|
3286
|
+
throw new Error(`Task n
|
|
3287
|
+
|
|
3288
|
+
--- src/events/domain-events.ts (truncated) ---
|
|
3289
|
+
/**
|
|
3290
|
+
* Domain Events for Event Sourcing (ADR-007)
|
|
3291
|
+
*
|
|
3292
|
+
* Defines all domain events for the V3 system:
|
|
3293
|
+
* - Agent lifecycle events (spawned, started, stopped, failed)
|
|
3294
|
+
* - Task execution events (created, started, completed, failed)
|
|
3295
|
+
* - Memory operations events (stored, retrieved, deleted)
|
|
3296
|
+
* - Swarm coordination events (initialized, scaled, terminated)
|
|
3297
|
+
*
|
|
3298
|
+
* @module v3/shared/events/domain-events
|
|
3299
|
+
*/
|
|
3300
|
+
|
|
3301
|
+
import { AgentId, TaskId, EventType, SwarmEvent } from '../types.js';
|
|
3302
|
+
|
|
3303
|
+
// =============================================================================
|
|
3304
|
+
// Base Domain Event Interface
|
|
3305
|
+
// =============================================================================
|
|
3306
|
+
|
|
3307
|
+
export interface DomainEvent {
|
|
3308
|
+
/** Unique event identifier */
|
|
3309
|
+
id: string;
|
|
3310
|
+
|
|
3311
|
+
/** Event type discriminator */
|
|
3312
|
+
type: string;
|
|
3313
|
+
|
|
3314
|
+
/** Aggregate ID (entity the event belongs to) */
|
|
3315
|
+
aggregateId: string;
|
|
3316
|
+
|
|
3317
|
+
/** Aggregate type (agent, task, memory, swarm) */
|
|
3318
|
+
aggregateType: 'agent' | 'task' | 'memory' | 'swarm';
|
|
3319
|
+
|
|
3320
|
+
/** Event version for ordering */
|
|
3321
|
+
version: number;
|
|
3322
|
+
|
|
3323
|
+
/** Timestamp when event occurred */
|
|
3324
|
+
timestamp: number;
|
|
3325
|
+
|
|
3326
|
+
/** Event source (agent or swarm system) */
|
|
3327
|
+
source: AgentId | 'swarm';
|
|
3328
|
+
|
|
3329
|
+
/** Event payload data */
|
|
3330
|
+
payload: Record<string, unknown>;
|
|
3331
|
+
|
|
3332
|
+
/** Optional metadata */
|
|
3333
|
+
metadata?: Record<string, unknown>;
|
|
3334
|
+
|
|
3335
|
+
/** Optional causation ID (event that caused this event) */
|
|
3336
|
+
causationId?: string;
|
|
3337
|
+
|
|
3338
|
+
/** Optional correlation ID (groups related events) */
|
|
3339
|
+
correlationId?: string;
|
|
3340
|
+
}
|
|
3341
|
+
|
|
3342
|
+
// =============================================================================
|
|
3343
|
+
// Agent Lifecycle Events
|
|
3344
|
+
// =============================================================================
|
|
3345
|
+
|
|
3346
|
+
export interface AgentSpawnedEvent extends DomainEvent {
|
|
3347
|
+
type: 'agent:spawned';
|
|
3348
|
+
aggregateType: 'agent';
|
|
3349
|
+
payload: {
|
|
3350
|
+
agentId: AgentId;
|
|
3351
|
+
role: string;
|
|
3352
|
+
domain: string;
|
|
3353
|
+
capabilities: string[];
|
|
3354
|
+
};
|
|
3355
|
+
}
|
|
3356
|
+
|
|
3357
|
+
export interface AgentStartedEvent extends DomainEvent {
|
|
3358
|
+
type: 'agent:started';
|
|
3359
|
+
aggregateType: 'agent';
|
|
3360
|
+
payload: {
|
|
3361
|
+
agentId: AgentId;
|
|
3362
|
+
startedAt: number;
|
|
3363
|
+
};
|
|
3364
|
+
}
|
|
3365
|
+
|
|
3366
|
+
export interface AgentStoppedEvent extends DomainEvent {
|
|
3367
|
+
type: 'agent:stopped';
|
|
3368
|
+
aggregateType: 'agent';
|
|
3369
|
+
payload: {
|
|
3370
|
+
agentId: AgentId;
|
|
3371
|
+
reason: string;
|
|
3372
|
+
stoppedAt: number;
|
|
3373
|
+
};
|
|
3374
|
+
}
|
|
3375
|
+
|
|
3376
|
+
export interface AgentFailedEvent extends DomainEvent {
|
|
3377
|
+
type: 'agent:failed';
|
|
3378
|
+
aggregateType: 'agent';
|
|
3379
|
+
payload: {
|
|
3380
|
+
agentId: AgentId;
|
|
3381
|
+
error: string;
|
|
3382
|
+
stack?: string;
|
|
3383
|
+
failedAt: number;
|
|
3384
|
+
};
|
|
3385
|
+
}
|
|
3386
|
+
|
|
3387
|
+
export interface AgentStatusChangedEvent extends DomainEvent {
|
|
3388
|
+
type: 'agent:status-changed';
|
|
3389
|
+
aggregateType: 'agent';
|
|
3390
|
+
payload: {
|
|
3391
|
+
agentId: AgentId;
|
|
3392
|
+
previousStatus: string;
|
|
3393
|
+
newStatus: string;
|
|
3394
|
+
};
|
|
3395
|
+
}
|
|
3396
|
+
|
|
3397
|
+
export interface AgentTaskAssignedEvent extends DomainEvent {
|
|
3398
|
+
type: 'agent:task-assigned';
|
|
3399
|
+
aggregateType: 'agent';
|
|
3400
|
+
payload: {
|
|
3401
|
+
agentId: AgentId;
|
|
3402
|
+
taskId: TaskId;
|
|
3403
|
+
assignedAt: number;
|
|
3404
|
+
};
|
|
3405
|
+
}
|
|
3406
|
+
|
|
3407
|
+
export interface AgentTaskCompletedEvent extends DomainEvent {
|
|
3408
|
+
type: 'agent:task-completed';
|
|
3409
|
+
aggregateType: 'agent';
|
|
3410
|
+
payload: {
|
|
3411
|
+
agentId: AgentId;
|
|
3412
|
+
taskId: TaskId;
|
|
3413
|
+
result: unknown;
|
|
3414
|
+
completedAt: number;
|
|
3415
|
+
duration: number;
|
|
3416
|
+
};
|
|
3417
|
+
}
|
|
3418
|
+
|
|
3419
|
+
// =============================================================================
|
|
3420
|
+
// Task Execution Events
|
|
3421
|
+
// =============================================================================
|
|
3422
|
+
|
|
3423
|
+
export interface TaskCreatedEvent extends DomainEvent {
|
|
3424
|
+
type: 'task:created';
|
|
3425
|
+
aggregateType: 'task';
|
|
3426
|
+
payload: {
|
|
3427
|
+
taskId: TaskId;
|
|
3428
|
+
taskType: string;
|
|
3429
|
+
title: string;
|
|
3430
|
+
description: string;
|
|
3431
|
+
priority: string;
|
|
3432
|
+
dependencies: TaskId[];
|
|
3433
|
+
createdAt: number;
|
|
3434
|
+
};
|
|
3435
|
+
}
|
|
3436
|
+
|
|
3437
|
+
export interface TaskStartedEvent extends DomainEvent {
|
|
3438
|
+
type: 'task:started';
|
|
3439
|
+
aggregateType: 'task';
|
|
3440
|
+
payload: {
|
|
3441
|
+
taskId: TaskId;
|
|
3442
|
+
agentId: AgentId;
|
|
3443
|
+
startedAt: number;
|
|
3444
|
+
};
|
|
3445
|
+
}
|
|
3446
|
+
|
|
3447
|
+
export interface TaskCompletedEvent extends DomainEvent {
|
|
3448
|
+
type: 'task:completed';
|
|
3449
|
+
aggregateType: 'task';
|
|
3450
|
+
payload: {
|
|
3451
|
+
taskId: TaskId;
|
|
3452
|
+
result: unknown;
|
|
3453
|
+
completedAt: number;
|
|
3454
|
+
duration: number;
|
|
3455
|
+
};
|
|
3456
|
+
}
|
|
3457
|
+
|
|
3458
|
+
export interface TaskFailedEvent extends DomainEvent {
|
|
3459
|
+
type: 'task:failed';
|
|
3460
|
+
aggregateType: 'task';
|
|
3461
|
+
payload: {
|
|
3462
|
+
taskId: TaskId;
|
|
3463
|
+
error: string;
|
|
3464
|
+
stack?: string;
|
|
3465
|
+
failedAt: number;
|
|
3466
|
+
retryCount: number;
|
|
3467
|
+
};
|
|
3468
|
+
}
|
|
3469
|
+
|
|
3470
|
+
export interface TaskBlockedEvent extends DomainEvent {
|
|
3471
|
+
type: 'task:blocked';
|
|
3472
|
+
aggregateType: 'task';
|
|
3473
|
+
payload: {
|
|
3474
|
+
taskId: TaskId;
|
|
3475
|
+
blockedBy: TaskId[];
|
|
3476
|
+
blockedAt: number;
|
|
3477
|
+
};
|
|
3478
|
+
}
|
|
3479
|
+
|
|
3480
|
+
export interface TaskQueuedEvent extends DomainEvent {
|
|
3481
|
+
type: 'task:queued';
|
|
3482
|
+
aggregateType: 'task';
|
|
3483
|
+
payload: {
|
|
3484
|
+
taskId: TaskId;
|
|
3485
|
+
priority: string;
|
|
3486
|
+
queuedAt: number;
|
|
3487
|
+
};
|
|
3488
|
+
}
|
|
3489
|
+
|
|
3490
|
+
// =============================================================================
|
|
3491
|
+
// Memory Operations Events
|
|
3492
|
+
// =============================================================================
|
|
3493
|
+
|
|
3494
|
+
export interface MemoryStoredEvent extends DomainEvent {
|
|
3495
|
+
type: 'memory:stored';
|
|
3496
|
+
aggregateType: 'memory';
|
|
3497
|
+
payload: {
|
|
3498
|
+
memoryId: string;
|
|
3499
|
+
namespace: string;
|
|
3500
|
+
key: s
|
|
3501
|
+
|
|
3502
|
+
## Instructions
|
|
3503
|
+
|
|
3504
|
+
Analyze the above codebase context and provide your response following the format specified in the task.
|