claude-flow-novice 2.0.3 → 2.0.4
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/dist/src/cli/commands/guidance.js +487 -668
- package/dist/src/cli/commands/index-validate.js +18 -29
- package/dist/src/cli/commands/mcp-troubleshoot.js +230 -282
- package/dist/src/cli/commands/neural-goal-init.js +92 -125
- package/dist/src/cli/commands/swarm-exec.js +317 -393
- package/dist/src/cli/commands/swarm.js +1 -1
- package/dist/src/cli/commands/validate-framework.js +983 -1100
- package/dist/src/cli/commands/validate.js +144 -223
- package/dist/src/cli/simple-commands/__tests__/agent.test.js +265 -277
- package/dist/src/cli/simple-commands/__tests__/memory.test.js +6 -7
- package/dist/src/cli/simple-commands/__tests__/swarm.test.js +373 -356
- package/dist/src/cli/simple-commands/__tests__/task.test.js +6 -7
- package/dist/src/cli/simple-commands/agent.js +157 -193
- package/dist/src/cli/simple-commands/analysis.js +336 -446
- package/dist/src/cli/simple-commands/automation-executor.js +1095 -1339
- package/dist/src/cli/simple-commands/automation.js +481 -469
- package/dist/src/cli/simple-commands/batch-manager.js +261 -313
- package/dist/src/cli/simple-commands/claude-telemetry.js +241 -267
- package/dist/src/cli/simple-commands/claude-track.js +68 -90
- package/dist/src/cli/simple-commands/concurrent-display.js +266 -320
- package/dist/src/cli/simple-commands/config.js +245 -290
- package/dist/src/cli/simple-commands/coordination.js +182 -234
- package/dist/src/cli/simple-commands/enhanced-ui-views.js +812 -615
- package/dist/src/cli/simple-commands/enhanced-webui-complete.js +922 -981
- package/dist/src/cli/simple-commands/fix-hook-variables.js +274 -294
- package/dist/src/cli/simple-commands/github/gh-coordinator.js +378 -457
- package/dist/src/cli/simple-commands/github/github-api.js +535 -574
- package/dist/src/cli/simple-commands/github/init.js +276 -303
- package/dist/src/cli/simple-commands/github.js +222 -247
- package/dist/src/cli/simple-commands/goal.js +51 -63
- package/dist/src/cli/simple-commands/hive-mind/auto-save-middleware.js +208 -278
- package/dist/src/cli/simple-commands/hive-mind/communication.js +601 -696
- package/dist/src/cli/simple-commands/hive-mind/core.js +907 -979
- package/dist/src/cli/simple-commands/hive-mind/db-optimizer.js +406 -655
- package/dist/src/cli/simple-commands/hive-mind/mcp-wrapper.js +1125 -1245
- package/dist/src/cli/simple-commands/hive-mind/memory.js +854 -1090
- package/dist/src/cli/simple-commands/hive-mind/performance-optimizer.js +459 -574
- package/dist/src/cli/simple-commands/hive-mind/performance-test.js +263 -347
- package/dist/src/cli/simple-commands/hive-mind/queen.js +727 -768
- package/dist/src/cli/simple-commands/hive-mind/session-manager.js +745 -1049
- package/dist/src/cli/simple-commands/hive-mind-optimize.js +227 -283
- package/dist/src/cli/simple-commands/hive-mind-wizard.js +174 -217
- package/dist/src/cli/simple-commands/hive-mind.js +1842 -2283
- package/dist/src/cli/simple-commands/hive.js +90 -79
- package/dist/src/cli/simple-commands/hook-safety.js +431 -521
- package/dist/src/cli/simple-commands/hooks/session-start-soul.js +203 -254
- package/dist/src/cli/simple-commands/hooks.js +1064 -1204
- package/dist/src/cli/simple-commands/init/agent-copier.js +294 -319
- package/dist/src/cli/simple-commands/init/batch-init.js +496 -562
- package/dist/src/cli/simple-commands/init/claude-commands/claude-flow-commands.js +13 -19
- package/dist/src/cli/simple-commands/init/claude-commands/optimized-claude-flow-commands.js +13 -19
- package/dist/src/cli/simple-commands/init/claude-commands/optimized-slash-commands.js +61 -88
- package/dist/src/cli/simple-commands/init/claude-commands/optimized-sparc-commands.js +125 -150
- package/dist/src/cli/simple-commands/init/claude-commands/slash-commands.js +42 -49
- package/dist/src/cli/simple-commands/init/claude-commands/sparc-commands.js +43 -61
- package/dist/src/cli/simple-commands/init/copy-revised-templates.js +141 -147
- package/dist/src/cli/simple-commands/init/executable-wrapper.js +31 -44
- package/dist/src/cli/simple-commands/init/gitignore-updater.js +64 -90
- package/dist/src/cli/simple-commands/init/help.js +104 -107
- package/dist/src/cli/simple-commands/init/hive-mind-init.js +509 -528
- package/dist/src/cli/simple-commands/init/index.js +1510 -1759
- package/dist/src/cli/simple-commands/init/performance-monitor.js +234 -317
- package/dist/src/cli/simple-commands/init/rollback/backup-manager.js +441 -504
- package/dist/src/cli/simple-commands/init/rollback/index.js +289 -364
- package/dist/src/cli/simple-commands/init/rollback/recovery-manager.js +652 -728
- package/dist/src/cli/simple-commands/init/rollback/rollback-executor.js +416 -481
- package/dist/src/cli/simple-commands/init/rollback/state-tracker.js +369 -448
- package/dist/src/cli/simple-commands/init/sparc/roo-readme.js +1 -2
- package/dist/src/cli/simple-commands/init/sparc/roomodes-config.js +122 -99
- package/dist/src/cli/simple-commands/init/sparc/workflows.js +32 -37
- package/dist/src/cli/simple-commands/init/sparc-structure.js +55 -62
- package/dist/src/cli/simple-commands/init/template-copier.js +421 -533
- package/dist/src/cli/simple-commands/init/templates/coordination-md.js +3 -6
- package/dist/src/cli/simple-commands/init/templates/enhanced-templates.js +344 -318
- package/dist/src/cli/simple-commands/init/templates/github-safe-enhanced.js +173 -218
- package/dist/src/cli/simple-commands/init/templates/github-safe.js +65 -75
- package/dist/src/cli/simple-commands/init/templates/memory-bank-md.js +3 -6
- package/dist/src/cli/simple-commands/init/templates/readme-files.js +2 -4
- package/dist/src/cli/simple-commands/init/templates/safe-hook-patterns.js +187 -230
- package/dist/src/cli/simple-commands/init/templates/sparc-modes.js +53 -80
- package/dist/src/cli/simple-commands/init/templates/verification-claude-md.js +101 -85
- package/dist/src/cli/simple-commands/init/validation/config-validator.js +283 -330
- package/dist/src/cli/simple-commands/init/validation/health-checker.js +495 -561
- package/dist/src/cli/simple-commands/init/validation/index.js +302 -358
- package/dist/src/cli/simple-commands/init/validation/mode-validator.js +308 -359
- package/dist/src/cli/simple-commands/init/validation/post-init-validator.js +389 -366
- package/dist/src/cli/simple-commands/init/validation/pre-init-validator.js +270 -268
- package/dist/src/cli/simple-commands/init/validation/test-runner.js +427 -447
- package/dist/src/cli/simple-commands/init.js +1 -2
- package/dist/src/cli/simple-commands/mcp-health.js +131 -158
- package/dist/src/cli/simple-commands/mcp-integration-layer.js +533 -634
- package/dist/src/cli/simple-commands/mcp.js +345 -400
- package/dist/src/cli/simple-commands/memory-consolidation.js +426 -537
- package/dist/src/cli/simple-commands/memory.js +247 -311
- package/dist/src/cli/simple-commands/migrate-hooks.js +39 -46
- package/dist/src/cli/simple-commands/monitor.js +294 -363
- package/dist/src/cli/simple-commands/neural.js +51 -65
- package/dist/src/cli/simple-commands/pair-autofix-only.js +538 -662
- package/dist/src/cli/simple-commands/pair-basic.js +528 -656
- package/dist/src/cli/simple-commands/pair-old.js +430 -543
- package/dist/src/cli/simple-commands/pair-working.js +615 -751
- package/dist/src/cli/simple-commands/pair.js +615 -751
- package/dist/src/cli/simple-commands/performance-hooks.js +83 -111
- package/dist/src/cli/simple-commands/performance-metrics.js +348 -433
- package/dist/src/cli/simple-commands/process-ui-enhanced.js +708 -787
- package/dist/src/cli/simple-commands/process-ui.js +230 -254
- package/dist/src/cli/simple-commands/realtime-update-system.js +525 -611
- package/dist/src/cli/simple-commands/sparc/architecture.js +1704 -1530
- package/dist/src/cli/simple-commands/sparc/commands.js +438 -516
- package/dist/src/cli/simple-commands/sparc/completion.js +1224 -1481
- package/dist/src/cli/simple-commands/sparc/coordinator.js +913 -978
- package/dist/src/cli/simple-commands/sparc/index.js +241 -298
- package/dist/src/cli/simple-commands/sparc/phase-base.js +314 -390
- package/dist/src/cli/simple-commands/sparc/pseudocode.js +965 -869
- package/dist/src/cli/simple-commands/sparc/refinement.js +980 -1273
- package/dist/src/cli/simple-commands/sparc/specification.js +559 -645
- package/dist/src/cli/simple-commands/sparc-modes/architect.js +1 -1
- package/dist/src/cli/simple-commands/sparc-modes/ask.js +1 -1
- package/dist/src/cli/simple-commands/sparc-modes/code.js +1 -1
- package/dist/src/cli/simple-commands/sparc-modes/debug.js +1 -1
- package/dist/src/cli/simple-commands/sparc-modes/devops.js +1 -1
- package/dist/src/cli/simple-commands/sparc-modes/docs-writer.js +1 -1
- package/dist/src/cli/simple-commands/sparc-modes/generic.js +1 -1
- package/dist/src/cli/simple-commands/sparc-modes/index.js +47 -55
- package/dist/src/cli/simple-commands/sparc-modes/integration.js +1 -1
- package/dist/src/cli/simple-commands/sparc-modes/mcp.js +1 -1
- package/dist/src/cli/simple-commands/sparc-modes/monitoring.js +1 -1
- package/dist/src/cli/simple-commands/sparc-modes/optimization.js +1 -1
- package/dist/src/cli/simple-commands/sparc-modes/security-review.js +1 -1
- package/dist/src/cli/simple-commands/sparc-modes/sparc-orchestrator.js +1 -1
- package/dist/src/cli/simple-commands/sparc-modes/spec-pseudocode.js +1 -1
- package/dist/src/cli/simple-commands/sparc-modes/supabase-admin.js +1 -1
- package/dist/src/cli/simple-commands/sparc-modes/swarm.js +101 -87
- package/dist/src/cli/simple-commands/sparc-modes/tdd.js +1 -1
- package/dist/src/cli/simple-commands/sparc-modes/tutorial.js +1 -1
- package/dist/src/cli/simple-commands/sparc.js +465 -493
- package/dist/src/cli/simple-commands/start-ui.js +108 -132
- package/dist/src/cli/simple-commands/start-wrapper.js +240 -268
- package/dist/src/cli/simple-commands/start.js +1 -1
- package/dist/src/cli/simple-commands/status.js +254 -275
- package/dist/src/cli/simple-commands/stream-chain-clean.js +128 -171
- package/dist/src/cli/simple-commands/stream-chain-fixed.js +61 -82
- package/dist/src/cli/simple-commands/stream-chain-real.js +267 -331
- package/dist/src/cli/simple-commands/stream-chain-working.js +211 -263
- package/dist/src/cli/simple-commands/stream-chain.js +260 -318
- package/dist/src/cli/simple-commands/stream-processor.js +290 -315
- package/dist/src/cli/simple-commands/swarm-executor.js +189 -222
- package/dist/src/cli/simple-commands/swarm-metrics-integration.js +208 -300
- package/dist/src/cli/simple-commands/swarm-ui.js +623 -703
- package/dist/src/cli/simple-commands/swarm-webui-integration.js +258 -286
- package/dist/src/cli/simple-commands/swarm.js +887 -1082
- package/dist/src/cli/simple-commands/task.js +161 -206
- package/dist/src/cli/simple-commands/timestamp-fix.js +59 -89
- package/dist/src/cli/simple-commands/token-tracker.js +258 -316
- package/dist/src/cli/simple-commands/tool-execution-framework.js +433 -519
- package/dist/src/cli/simple-commands/train-and-stream.js +275 -331
- package/dist/src/cli/simple-commands/training-pipeline.js +619 -725
- package/dist/src/cli/simple-commands/training.js +170 -227
- package/dist/src/cli/simple-commands/verification-hooks.js +261 -284
- package/dist/src/cli/simple-commands/verification-integration.js +389 -417
- package/dist/src/cli/simple-commands/verification-training-integration.js +486 -606
- package/dist/src/cli/simple-commands/verification.js +493 -513
- package/dist/src/cli/simple-commands/web-server.js +766 -836
- package/dist/src/cli/simple-commands/webui-validator.js +106 -124
- package/dist/src/coordination/event-bus/demo-wasm-integration.js +212 -251
- package/dist/src/coordination/event-bus/qe-event-bus.js +608 -748
- package/dist/src/coordination/event-bus/qe-event-bus.test.js +379 -454
- package/dist/src/coordination/iteration-tracker.js +363 -454
- package/dist/src/enterprise/analytics-manager.js +1135 -0
- package/dist/src/enterprise/audit-manager.js +1115 -0
- package/dist/src/enterprise/cloud-manager.js +891 -0
- package/dist/src/enterprise/deployment-manager.js +966 -0
- package/dist/src/enterprise/index.js +6 -0
- package/dist/src/enterprise/project-manager.js +584 -0
- package/dist/src/enterprise/security-manager.js +991 -0
- package/dist/src/index.js +1 -1
- package/dist/src/mcp/DEPRECATED.js +46 -60
- package/dist/src/mcp/fixes/mcp-error-fixes.js +115 -134
- package/dist/src/mcp/implementations/agent-tracker.js +114 -128
- package/dist/src/mcp/implementations/daa-tools.js +292 -350
- package/dist/src/mcp/implementations/workflow-tools.js +329 -361
- package/dist/src/mcp/mcp-config-manager.js +1183 -1331
- package/dist/src/mcp/mcp-server-novice-simplified.js +11 -17
- package/dist/src/mcp/mcp-server-novice.js +11 -17
- package/dist/src/mcp/mcp-server-sdk.js +11 -17
- package/dist/src/mcp/mcp-server.js +1620 -1484
- package/dist/src/mcp/ruv-swarm-wrapper.js +209 -239
- package/dist/src/memory/advanced-serializer.js +609 -589
- package/dist/src/memory/enhanced-examples.js +220 -305
- package/dist/src/memory/enhanced-memory.js +295 -336
- package/dist/src/memory/enhanced-session-serializer.js +408 -492
- package/dist/src/memory/fallback-memory-system.js +900 -1021
- package/dist/src/memory/fallback-store.js +93 -131
- package/dist/src/memory/high-performance-serialization.js +592 -730
- package/dist/src/memory/in-memory-store.js +161 -213
- package/dist/src/memory/index.js +123 -157
- package/dist/src/memory/lock-free-structures.js +578 -764
- package/dist/src/memory/memory-mapped-persistence.js +585 -766
- package/dist/src/memory/memory-pressure-manager.js +569 -707
- package/dist/src/memory/migration.js +358 -445
- package/dist/src/memory/shared-memory.js +641 -768
- package/dist/src/memory/sqlite-store.js +245 -325
- package/dist/src/memory/sqlite-wrapper.js +122 -151
- package/dist/src/memory/swarm-memory.js +470 -603
- package/dist/src/memory/test-example.js +126 -134
- package/dist/src/memory/ultra-fast-memory-store.js +622 -821
- package/dist/src/memory/unified-memory-manager.js +356 -437
- package/dist/src/migration/index.js +92 -0
- package/dist/src/migration/logger.js +121 -0
- package/dist/src/migration/migration-analyzer.js +268 -0
- package/dist/src/migration/migration-runner.js +522 -0
- package/dist/src/migration/migration-validator.js +285 -0
- package/dist/src/migration/progress-reporter.js +150 -0
- package/dist/src/migration/rollback-manager.js +321 -0
- package/dist/src/migration/tests/migration-system.test.js +7 -0
- package/dist/src/migration/types.js +3 -0
- package/dist/src/swarm/CodeRefactoringSwarm.js +777 -952
- package/dist/src/swarm/__tests__/integration.test.js +227 -0
- package/dist/src/swarm/__tests__/prompt-copier.test.js +344 -0
- package/dist/src/swarm/advanced-orchestrator.js +1095 -0
- package/dist/src/swarm/claude-code-interface.js +961 -0
- package/dist/src/swarm/claude-flow-executor.js +229 -0
- package/dist/src/swarm/consensus-coordinator.js +475 -0
- package/dist/src/swarm/coordinator.js +2993 -0
- package/dist/src/swarm/direct-executor.js +1180 -0
- package/dist/src/swarm/error-recovery/advanced-error-detection.js +691 -0
- package/dist/src/swarm/error-recovery/automated-recovery-workflows.js +998 -0
- package/dist/src/swarm/error-recovery/error-recovery-coordinator.js +1197 -0
- package/dist/src/swarm/error-recovery/recovery-monitoring.js +772 -0
- package/dist/src/swarm/error-recovery/resilience-architecture.js +714 -0
- package/dist/src/swarm/error-recovery/self-healing-mechanisms.js +1319 -0
- package/dist/src/swarm/error-recovery/test-error-recovery-effectiveness.js +808 -0
- package/dist/src/swarm/executor-v2.js +322 -0
- package/dist/src/swarm/executor.js +815 -0
- package/dist/src/swarm/hive-mind-integration.js +703 -0
- package/dist/src/swarm/index.js +41 -0
- package/dist/src/swarm/json-output-aggregator.js +267 -0
- package/dist/src/swarm/large-scale-coordinator.js +542 -0
- package/dist/src/swarm/mcp-integration-wrapper.js +628 -0
- package/dist/src/swarm/memory.js +1117 -0
- package/dist/src/swarm/optimizations/__tests__/optimization.test.js +348 -0
- package/dist/src/swarm/optimizations/async-file-manager.js +285 -0
- package/dist/src/swarm/optimizations/circular-buffer.js +162 -0
- package/dist/src/swarm/optimizations/connection-pool.js +244 -0
- package/dist/src/swarm/optimizations/index.js +28 -0
- package/dist/src/swarm/optimizations/optimized-executor.js +320 -0
- package/dist/src/swarm/optimizations/ttl-map.js +234 -0
- package/dist/src/swarm/prompt-cli.js +200 -0
- package/dist/src/swarm/prompt-copier-enhanced.js +202 -0
- package/dist/src/swarm/prompt-copier.js +381 -0
- package/dist/src/swarm/prompt-manager.js +295 -0
- package/dist/src/swarm/prompt-utils.js +310 -0
- package/dist/src/swarm/result-aggregator.js +718 -0
- package/dist/src/swarm/sparc-executor.js +1568 -0
- package/dist/src/swarm/strategies/auto.js +758 -0
- package/dist/src/swarm/strategies/base.js +128 -0
- package/dist/src/swarm/strategies/research.js +914 -0
- package/dist/src/swarm/strategies/strategy-metrics-patch.js +2 -0
- package/dist/src/swarm/types.js +52 -0
- package/dist/src/swarm/workers/copy-worker.js +56 -0
- package/dist/src/utils/__tests__/github-cli-safety-wrapper.test.js +332 -400
- package/dist/src/utils/github-cli-safe.js +56 -64
- package/dist/src/utils/github-cli-safety-wrapper.js +451 -546
- package/dist/src/utils/npx-isolated-cache.js +104 -119
- package/dist/src/utils/preference-manager.js +622 -652
- package/dist/src/utils/timezone-utils.js +86 -105
- package/dist/src/validators/epic-config-schema.js +214 -0
- package/dist/src/validators/index.js +10 -0
- package/dist/src/validators/swarm-init-validator.js +259 -0
- package/dist/src/validators/todowrite-batching-validator.js +215 -0
- package/dist/src/validators/todowrite-integration.js +187 -0
- package/package.json +2 -2
|
@@ -0,0 +1,961 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Claude Code Coordination Interface
|
|
3
|
+
*
|
|
4
|
+
* This module provides the interface layer for coordinating with Claude Code
|
|
5
|
+
* instances, managing agent spawning through the claude CLI, handling process
|
|
6
|
+
* lifecycle, and enabling seamless communication between the swarm system
|
|
7
|
+
* and individual Claude agents.
|
|
8
|
+
*/ function _define_property(obj, key, value) {
|
|
9
|
+
if (key in obj) {
|
|
10
|
+
Object.defineProperty(obj, key, {
|
|
11
|
+
value: value,
|
|
12
|
+
enumerable: true,
|
|
13
|
+
configurable: true,
|
|
14
|
+
writable: true
|
|
15
|
+
});
|
|
16
|
+
} else {
|
|
17
|
+
obj[key] = value;
|
|
18
|
+
}
|
|
19
|
+
return obj;
|
|
20
|
+
}
|
|
21
|
+
import { EventEmitter } from "node:events";
|
|
22
|
+
import { spawn } from "node:child_process";
|
|
23
|
+
import { performance } from "node:perf_hooks";
|
|
24
|
+
import * as path from "node:path";
|
|
25
|
+
import { Logger } from "../core/logger.js";
|
|
26
|
+
import { generateId } from "../utils/helpers.js";
|
|
27
|
+
import TaskExecutor from "./executor.js";
|
|
28
|
+
export class ClaudeCodeInterface extends EventEmitter {
|
|
29
|
+
/**
|
|
30
|
+
* Initialize the Claude Code interface
|
|
31
|
+
*/ async initialize() {
|
|
32
|
+
if (this.isInitialized) {
|
|
33
|
+
this.logger.warn('Claude Code interface already initialized');
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
this.logger.info('Initializing Claude Code interface...');
|
|
37
|
+
try {
|
|
38
|
+
// Verify Claude executable exists
|
|
39
|
+
await this.verifyClaudeExecutable();
|
|
40
|
+
// Initialize task executor
|
|
41
|
+
await this.taskExecutor.initialize();
|
|
42
|
+
// Pre-warm agent pool if configured
|
|
43
|
+
if (this.config.agentPoolSize > 0) {
|
|
44
|
+
await this.prewarmAgentPool();
|
|
45
|
+
}
|
|
46
|
+
// Start health checks
|
|
47
|
+
this.startHealthChecks();
|
|
48
|
+
this.isInitialized = true;
|
|
49
|
+
this.logger.info('Claude Code interface initialized successfully', {
|
|
50
|
+
poolSize: this.processPool.idle.length,
|
|
51
|
+
maxConcurrent: this.config.maxConcurrentAgents
|
|
52
|
+
});
|
|
53
|
+
this.emit('initialized');
|
|
54
|
+
} catch (error) {
|
|
55
|
+
this.logger.error('Failed to initialize Claude Code interface', error);
|
|
56
|
+
throw error;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Shutdown the interface gracefully
|
|
61
|
+
*/ async shutdown() {
|
|
62
|
+
if (!this.isInitialized) return;
|
|
63
|
+
this.logger.info('Shutting down Claude Code interface...');
|
|
64
|
+
try {
|
|
65
|
+
// Stop health checks
|
|
66
|
+
if (this.healthCheckInterval) {
|
|
67
|
+
clearInterval(this.healthCheckInterval);
|
|
68
|
+
}
|
|
69
|
+
// Cancel active executions
|
|
70
|
+
const cancellationPromises = Array.from(this.activeExecutions.keys()).map((executionId)=>this.cancelExecution(executionId, 'Interface shutdown'));
|
|
71
|
+
await Promise.allSettled(cancellationPromises);
|
|
72
|
+
// Terminate all agents
|
|
73
|
+
await this.terminateAllAgents();
|
|
74
|
+
// Shutdown task executor
|
|
75
|
+
await this.taskExecutor.shutdown();
|
|
76
|
+
this.isInitialized = false;
|
|
77
|
+
this.logger.info('Claude Code interface shut down successfully');
|
|
78
|
+
this.emit('shutdown');
|
|
79
|
+
} catch (error) {
|
|
80
|
+
this.logger.error('Error during Claude Code interface shutdown', error);
|
|
81
|
+
throw error;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Spawn a new Claude agent with specified configuration
|
|
86
|
+
*/ async spawnAgent(options) {
|
|
87
|
+
this.logger.info('Spawning Claude agent', {
|
|
88
|
+
type: options.type,
|
|
89
|
+
name: options.name,
|
|
90
|
+
capabilities: options.capabilities
|
|
91
|
+
});
|
|
92
|
+
try {
|
|
93
|
+
// Check if we can spawn more agents
|
|
94
|
+
if (this.getTotalActiveAgents() >= this.config.maxConcurrentAgents) {
|
|
95
|
+
throw new Error('Maximum concurrent agents limit reached');
|
|
96
|
+
}
|
|
97
|
+
// Build Claude command
|
|
98
|
+
const command = this.buildClaudeCommand(options);
|
|
99
|
+
// Spawn process
|
|
100
|
+
const process1 = spawn(command.executable, command.args, {
|
|
101
|
+
cwd: options.workingDirectory || this.config.workingDirectory,
|
|
102
|
+
env: {
|
|
103
|
+
...process1.env,
|
|
104
|
+
...this.config.environmentVariables,
|
|
105
|
+
...options.environment
|
|
106
|
+
},
|
|
107
|
+
stdio: [
|
|
108
|
+
'pipe',
|
|
109
|
+
'pipe',
|
|
110
|
+
'pipe'
|
|
111
|
+
],
|
|
112
|
+
detached: false
|
|
113
|
+
});
|
|
114
|
+
if (!process1.pid) {
|
|
115
|
+
throw new Error('Failed to spawn Claude process');
|
|
116
|
+
}
|
|
117
|
+
// Create agent record
|
|
118
|
+
const agentId = generateId('claude-agent');
|
|
119
|
+
const agent = {
|
|
120
|
+
id: agentId,
|
|
121
|
+
processId: process1.pid,
|
|
122
|
+
process: process1,
|
|
123
|
+
type: options.type,
|
|
124
|
+
capabilities: options.capabilities || [],
|
|
125
|
+
status: 'initializing',
|
|
126
|
+
spawnedAt: new Date(),
|
|
127
|
+
lastActivity: new Date(),
|
|
128
|
+
totalTasks: 0,
|
|
129
|
+
totalDuration: 0,
|
|
130
|
+
metrics: this.initializeAgentMetrics()
|
|
131
|
+
};
|
|
132
|
+
this.agents.set(agentId, agent);
|
|
133
|
+
this.processPool.idle.push(agent);
|
|
134
|
+
this.processPool.totalSpawned++;
|
|
135
|
+
// Setup process event handlers
|
|
136
|
+
this.setupProcessEventHandlers(agent);
|
|
137
|
+
// Wait for agent to be ready
|
|
138
|
+
await this.waitForAgentReady(agent);
|
|
139
|
+
agent.status = 'idle';
|
|
140
|
+
agent.lastActivity = new Date();
|
|
141
|
+
this.logger.info('Claude agent spawned successfully', {
|
|
142
|
+
agentId,
|
|
143
|
+
processId: process1.pid,
|
|
144
|
+
type: options.type
|
|
145
|
+
});
|
|
146
|
+
this.emit('agent:spawned', {
|
|
147
|
+
agentId,
|
|
148
|
+
type: options.type,
|
|
149
|
+
processId: process1.pid
|
|
150
|
+
});
|
|
151
|
+
return agentId;
|
|
152
|
+
} catch (error) {
|
|
153
|
+
this.logger.error('Failed to spawn Claude agent', {
|
|
154
|
+
type: options.type,
|
|
155
|
+
error: error instanceof Error ? error.message : String(error)
|
|
156
|
+
});
|
|
157
|
+
throw error;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Execute a task using a Claude agent
|
|
162
|
+
*/ async executeTask(taskDefinition, agentId, options = {}) {
|
|
163
|
+
const executionId = generateId('claude-execution');
|
|
164
|
+
this.logger.info('Executing task with Claude agent', {
|
|
165
|
+
executionId,
|
|
166
|
+
taskId: taskDefinition.id.id,
|
|
167
|
+
agentId
|
|
168
|
+
});
|
|
169
|
+
try {
|
|
170
|
+
// Get or select agent
|
|
171
|
+
const agent = agentId ? this.agents.get(agentId) : await this.selectOptimalAgent(taskDefinition);
|
|
172
|
+
if (!agent) {
|
|
173
|
+
throw new Error(agentId ? `Agent not found: ${agentId}` : 'No suitable agent available');
|
|
174
|
+
}
|
|
175
|
+
if (agent.status !== 'idle') {
|
|
176
|
+
throw new Error(`Agent ${agent.id} is not available (status: ${agent.status})`);
|
|
177
|
+
}
|
|
178
|
+
// Create execution record
|
|
179
|
+
const execution = {
|
|
180
|
+
id: executionId,
|
|
181
|
+
taskId: taskDefinition.id.id,
|
|
182
|
+
agentId: agent.id,
|
|
183
|
+
startTime: new Date(),
|
|
184
|
+
status: 'queued',
|
|
185
|
+
input: {
|
|
186
|
+
task: taskDefinition,
|
|
187
|
+
options
|
|
188
|
+
},
|
|
189
|
+
retryCount: 0,
|
|
190
|
+
maxRetries: options.maxRetries || 3
|
|
191
|
+
};
|
|
192
|
+
this.activeExecutions.set(executionId, execution);
|
|
193
|
+
// Update agent status
|
|
194
|
+
agent.status = 'busy';
|
|
195
|
+
agent.currentTask = executionId;
|
|
196
|
+
agent.lastActivity = new Date();
|
|
197
|
+
// Move agent from idle to busy pool
|
|
198
|
+
this.moveAgentToBusyPool(agent);
|
|
199
|
+
// Execute task
|
|
200
|
+
execution.status = 'running';
|
|
201
|
+
const result = await this.executeTaskWithAgent(agent, taskDefinition, options);
|
|
202
|
+
// Update execution record
|
|
203
|
+
execution.endTime = new Date();
|
|
204
|
+
execution.duration = execution.endTime.getTime() - execution.startTime.getTime();
|
|
205
|
+
execution.output = result.result;
|
|
206
|
+
execution.tokensUsed = result.metadata?.tokensUsed;
|
|
207
|
+
if (result.success) {
|
|
208
|
+
execution.status = 'completed';
|
|
209
|
+
agent.metrics.tasksCompleted++;
|
|
210
|
+
} else {
|
|
211
|
+
execution.status = 'failed';
|
|
212
|
+
execution.error = result.error;
|
|
213
|
+
agent.metrics.tasksFailed++;
|
|
214
|
+
}
|
|
215
|
+
// Update agent metrics
|
|
216
|
+
this.updateAgentMetrics(agent, execution);
|
|
217
|
+
// Return agent to idle pool
|
|
218
|
+
this.returnAgentToIdlePool(agent);
|
|
219
|
+
this.logger.info('Task execution completed', {
|
|
220
|
+
executionId,
|
|
221
|
+
success: result.success,
|
|
222
|
+
duration: execution.duration,
|
|
223
|
+
tokensUsed: execution.tokensUsed
|
|
224
|
+
});
|
|
225
|
+
this.emit('task:completed', {
|
|
226
|
+
executionId,
|
|
227
|
+
taskId: taskDefinition.id.id,
|
|
228
|
+
agentId: agent.id,
|
|
229
|
+
success: result.success,
|
|
230
|
+
duration: execution.duration
|
|
231
|
+
});
|
|
232
|
+
return execution;
|
|
233
|
+
} catch (error) {
|
|
234
|
+
const execution = this.activeExecutions.get(executionId);
|
|
235
|
+
if (execution) {
|
|
236
|
+
execution.status = 'failed';
|
|
237
|
+
execution.error = error instanceof Error ? error.message : String(error);
|
|
238
|
+
execution.endTime = new Date();
|
|
239
|
+
execution.duration = execution.endTime.getTime() - execution.startTime.getTime();
|
|
240
|
+
// Return agent to pool if it was assigned
|
|
241
|
+
const agent = this.agents.get(execution.agentId);
|
|
242
|
+
if (agent) {
|
|
243
|
+
this.returnAgentToIdlePool(agent);
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
this.logger.error('Task execution failed', {
|
|
247
|
+
executionId,
|
|
248
|
+
error: error instanceof Error ? error.message : String(error)
|
|
249
|
+
});
|
|
250
|
+
throw error;
|
|
251
|
+
} finally{
|
|
252
|
+
this.activeExecutions.delete(executionId);
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
/**
|
|
256
|
+
* Cancel a running task execution
|
|
257
|
+
*/ async cancelExecution(executionId, reason) {
|
|
258
|
+
const execution = this.activeExecutions.get(executionId);
|
|
259
|
+
if (!execution) {
|
|
260
|
+
throw new Error(`Execution not found: ${executionId}`);
|
|
261
|
+
}
|
|
262
|
+
this.logger.info('Cancelling task execution', {
|
|
263
|
+
executionId,
|
|
264
|
+
reason,
|
|
265
|
+
taskId: execution.taskId,
|
|
266
|
+
agentId: execution.agentId
|
|
267
|
+
});
|
|
268
|
+
try {
|
|
269
|
+
execution.status = 'cancelled';
|
|
270
|
+
execution.error = reason;
|
|
271
|
+
execution.endTime = new Date();
|
|
272
|
+
execution.duration = execution.endTime.getTime() - execution.startTime.getTime();
|
|
273
|
+
// Cancel agent task if running
|
|
274
|
+
const agent = this.agents.get(execution.agentId);
|
|
275
|
+
if (agent && agent.currentTask === executionId) {
|
|
276
|
+
await this.cancelAgentTask(agent);
|
|
277
|
+
this.returnAgentToIdlePool(agent);
|
|
278
|
+
}
|
|
279
|
+
this.emit('task:cancelled', {
|
|
280
|
+
executionId,
|
|
281
|
+
reason,
|
|
282
|
+
taskId: execution.taskId,
|
|
283
|
+
agentId: execution.agentId
|
|
284
|
+
});
|
|
285
|
+
} finally{
|
|
286
|
+
this.activeExecutions.delete(executionId);
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
/**
|
|
290
|
+
* Terminate a specific agent
|
|
291
|
+
*/ async terminateAgent(agentId, reason = 'Manual termination') {
|
|
292
|
+
const agent = this.agents.get(agentId);
|
|
293
|
+
if (!agent) {
|
|
294
|
+
throw new Error(`Agent not found: ${agentId}`);
|
|
295
|
+
}
|
|
296
|
+
this.logger.info('Terminating Claude agent', {
|
|
297
|
+
agentId,
|
|
298
|
+
processId: agent.processId,
|
|
299
|
+
reason
|
|
300
|
+
});
|
|
301
|
+
try {
|
|
302
|
+
// Cancel current task if any
|
|
303
|
+
if (agent.currentTask) {
|
|
304
|
+
await this.cancelExecution(agent.currentTask, 'Agent termination');
|
|
305
|
+
}
|
|
306
|
+
// Update status
|
|
307
|
+
agent.status = 'terminated';
|
|
308
|
+
// Terminate process
|
|
309
|
+
await this.terminateProcess(agent.process);
|
|
310
|
+
// Remove from pools and agents map
|
|
311
|
+
this.removeAgentFromPools(agent);
|
|
312
|
+
this.agents.delete(agentId);
|
|
313
|
+
this.processPool.totalTerminated++;
|
|
314
|
+
this.logger.info('Claude agent terminated successfully', {
|
|
315
|
+
agentId,
|
|
316
|
+
reason,
|
|
317
|
+
totalTasks: agent.totalTasks,
|
|
318
|
+
totalDuration: agent.totalDuration
|
|
319
|
+
});
|
|
320
|
+
this.emit('agent:terminated', {
|
|
321
|
+
agentId,
|
|
322
|
+
reason,
|
|
323
|
+
metrics: agent.metrics
|
|
324
|
+
});
|
|
325
|
+
} catch (error) {
|
|
326
|
+
this.logger.error('Error terminating agent', {
|
|
327
|
+
agentId,
|
|
328
|
+
error: error instanceof Error ? error.message : String(error)
|
|
329
|
+
});
|
|
330
|
+
throw error;
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
/**
|
|
334
|
+
* Get agent status and metrics
|
|
335
|
+
*/ getAgentStatus(agentId) {
|
|
336
|
+
return this.agents.get(agentId) || null;
|
|
337
|
+
}
|
|
338
|
+
/**
|
|
339
|
+
* Get all active agents
|
|
340
|
+
*/ getAllAgents() {
|
|
341
|
+
return Array.from(this.agents.values());
|
|
342
|
+
}
|
|
343
|
+
/**
|
|
344
|
+
* Get execution status
|
|
345
|
+
*/ getExecutionStatus(executionId) {
|
|
346
|
+
return this.activeExecutions.get(executionId) || null;
|
|
347
|
+
}
|
|
348
|
+
/**
|
|
349
|
+
* Get comprehensive interface metrics
|
|
350
|
+
*/ getInterfaceMetrics() {
|
|
351
|
+
const agents = Array.from(this.agents.values());
|
|
352
|
+
const executions = Array.from(this.activeExecutions.values());
|
|
353
|
+
const totalCompleted = agents.reduce((sum, a)=>sum + a.metrics.tasksCompleted, 0);
|
|
354
|
+
const totalFailed = agents.reduce((sum, a)=>sum + a.metrics.tasksFailed, 0);
|
|
355
|
+
const totalTokens = agents.reduce((sum, a)=>sum + a.metrics.totalTokensUsed, 0);
|
|
356
|
+
const avgResponseTime = agents.length > 0 ? agents.reduce((sum, a)=>sum + a.metrics.averageResponseTime, 0) / agents.length : 0;
|
|
357
|
+
return {
|
|
358
|
+
agents: {
|
|
359
|
+
total: agents.length,
|
|
360
|
+
idle: this.processPool.idle.length,
|
|
361
|
+
busy: this.processPool.busy.length,
|
|
362
|
+
failed: this.processPool.failed.length,
|
|
363
|
+
terminated: this.processPool.totalTerminated
|
|
364
|
+
},
|
|
365
|
+
executions: {
|
|
366
|
+
active: executions.filter((e)=>e.status === 'running').length,
|
|
367
|
+
completed: totalCompleted,
|
|
368
|
+
failed: totalFailed,
|
|
369
|
+
cancelled: executions.filter((e)=>e.status === 'cancelled').length
|
|
370
|
+
},
|
|
371
|
+
performance: {
|
|
372
|
+
averageResponseTime: avgResponseTime,
|
|
373
|
+
totalTokensUsed: totalTokens,
|
|
374
|
+
successRate: totalCompleted + totalFailed > 0 ? totalCompleted / (totalCompleted + totalFailed) : 0,
|
|
375
|
+
throughput: this.calculateThroughput()
|
|
376
|
+
},
|
|
377
|
+
pool: {
|
|
378
|
+
totalSpawned: this.processPool.totalSpawned,
|
|
379
|
+
totalTerminated: this.processPool.totalTerminated,
|
|
380
|
+
recyclingEnabled: this.processPool.recyclingEnabled,
|
|
381
|
+
poolUtilization: this.calculatePoolUtilization()
|
|
382
|
+
}
|
|
383
|
+
};
|
|
384
|
+
}
|
|
385
|
+
// Private methods
|
|
386
|
+
async verifyClaudeExecutable() {
|
|
387
|
+
try {
|
|
388
|
+
const { spawn } = await import("node:child_process");
|
|
389
|
+
const process1 = spawn(this.config.claudeExecutablePath, [
|
|
390
|
+
'--version'
|
|
391
|
+
], {
|
|
392
|
+
stdio: [
|
|
393
|
+
'ignore',
|
|
394
|
+
'pipe',
|
|
395
|
+
'pipe'
|
|
396
|
+
]
|
|
397
|
+
});
|
|
398
|
+
return new Promise((resolve, reject)=>{
|
|
399
|
+
let output = '';
|
|
400
|
+
process1.stdout?.on('data', (data)=>{
|
|
401
|
+
output += data.toString();
|
|
402
|
+
});
|
|
403
|
+
process1.on('close', (code)=>{
|
|
404
|
+
if (code === 0) {
|
|
405
|
+
this.logger.info('Claude executable verified', {
|
|
406
|
+
path: this.config.claudeExecutablePath,
|
|
407
|
+
version: output.trim()
|
|
408
|
+
});
|
|
409
|
+
resolve();
|
|
410
|
+
} else {
|
|
411
|
+
reject(new Error(`Claude executable verification failed with code ${code}`));
|
|
412
|
+
}
|
|
413
|
+
});
|
|
414
|
+
process1.on('error', reject);
|
|
415
|
+
});
|
|
416
|
+
} catch (error) {
|
|
417
|
+
throw new Error(`Claude executable not found: ${this.config.claudeExecutablePath}`);
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
async prewarmAgentPool() {
|
|
421
|
+
this.logger.info('Pre-warming agent pool', {
|
|
422
|
+
targetSize: this.config.agentPoolSize
|
|
423
|
+
});
|
|
424
|
+
const promises = [];
|
|
425
|
+
for(let i = 0; i < this.config.agentPoolSize; i++){
|
|
426
|
+
promises.push(this.spawnAgent({
|
|
427
|
+
type: 'general',
|
|
428
|
+
name: `pool-agent-${i}`,
|
|
429
|
+
capabilities: [
|
|
430
|
+
'general'
|
|
431
|
+
]
|
|
432
|
+
}));
|
|
433
|
+
}
|
|
434
|
+
const results = await Promise.allSettled(promises);
|
|
435
|
+
const successful = results.filter((r)=>r.status === 'fulfilled').length;
|
|
436
|
+
const failed = results.filter((r)=>r.status === 'rejected').length;
|
|
437
|
+
this.logger.info('Agent pool pre-warming completed', {
|
|
438
|
+
successful,
|
|
439
|
+
failed,
|
|
440
|
+
targetSize: this.config.agentPoolSize
|
|
441
|
+
});
|
|
442
|
+
}
|
|
443
|
+
buildClaudeCommand(options) {
|
|
444
|
+
const args = [];
|
|
445
|
+
// Add model
|
|
446
|
+
args.push('--model', options.model || this.config.defaultModel);
|
|
447
|
+
// Add max tokens
|
|
448
|
+
args.push('--max-tokens', String(options.maxTokens || this.config.maxTokens));
|
|
449
|
+
// Add temperature
|
|
450
|
+
args.push('--temperature', String(options.temperature || this.config.temperature));
|
|
451
|
+
// Add system prompt if provided
|
|
452
|
+
if (options.systemPrompt) {
|
|
453
|
+
args.push('--system', options.systemPrompt);
|
|
454
|
+
}
|
|
455
|
+
// Add tools if specified
|
|
456
|
+
if (options.tools && options.tools.length > 0) {
|
|
457
|
+
args.push('--allowedTools', options.tools.join(','));
|
|
458
|
+
}
|
|
459
|
+
// Enable streaming if configured
|
|
460
|
+
if (this.config.enableStreaming) {
|
|
461
|
+
args.push('--stream');
|
|
462
|
+
}
|
|
463
|
+
// Skip permissions for swarm execution
|
|
464
|
+
args.push('--dangerously-skip-permissions');
|
|
465
|
+
return {
|
|
466
|
+
executable: this.config.claudeExecutablePath,
|
|
467
|
+
args
|
|
468
|
+
};
|
|
469
|
+
}
|
|
470
|
+
setupProcessEventHandlers(agent) {
|
|
471
|
+
const { process: process1 } = agent;
|
|
472
|
+
process1.on('exit', (code, signal)=>{
|
|
473
|
+
this.logger.info('Claude agent process exited', {
|
|
474
|
+
agentId: agent.id,
|
|
475
|
+
processId: agent.processId,
|
|
476
|
+
code,
|
|
477
|
+
signal
|
|
478
|
+
});
|
|
479
|
+
if (agent.status !== 'terminated') {
|
|
480
|
+
agent.status = 'error';
|
|
481
|
+
this.moveAgentToFailedPool(agent);
|
|
482
|
+
}
|
|
483
|
+
this.emit('agent:exited', {
|
|
484
|
+
agentId: agent.id,
|
|
485
|
+
code,
|
|
486
|
+
signal
|
|
487
|
+
});
|
|
488
|
+
});
|
|
489
|
+
process1.on('error', (error)=>{
|
|
490
|
+
this.logger.error('Claude agent process error', {
|
|
491
|
+
agentId: agent.id,
|
|
492
|
+
processId: agent.processId,
|
|
493
|
+
error: error.message
|
|
494
|
+
});
|
|
495
|
+
agent.status = 'error';
|
|
496
|
+
this.moveAgentToFailedPool(agent);
|
|
497
|
+
this.emit('agent:error', {
|
|
498
|
+
agentId: agent.id,
|
|
499
|
+
error: error.message
|
|
500
|
+
});
|
|
501
|
+
});
|
|
502
|
+
// Handle stdout/stderr if needed
|
|
503
|
+
if (this.config.enableLogging) {
|
|
504
|
+
process1.stdout?.on('data', (data)=>{
|
|
505
|
+
this.logger.debug('Agent stdout', {
|
|
506
|
+
agentId: agent.id,
|
|
507
|
+
data: data.toString().trim()
|
|
508
|
+
});
|
|
509
|
+
});
|
|
510
|
+
process1.stderr?.on('data', (data)=>{
|
|
511
|
+
this.logger.debug('Agent stderr', {
|
|
512
|
+
agentId: agent.id,
|
|
513
|
+
data: data.toString().trim()
|
|
514
|
+
});
|
|
515
|
+
});
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
async waitForAgentReady(agent, timeout = 30000) {
|
|
519
|
+
return new Promise((resolve, reject)=>{
|
|
520
|
+
const startTime = Date.now();
|
|
521
|
+
const checkInterval = 1000; // 1 second
|
|
522
|
+
const checkReady = ()=>{
|
|
523
|
+
const elapsed = Date.now() - startTime;
|
|
524
|
+
if (elapsed > timeout) {
|
|
525
|
+
reject(new Error(`Agent ${agent.id} failed to become ready within ${timeout}ms`));
|
|
526
|
+
return;
|
|
527
|
+
}
|
|
528
|
+
// Check if process is still running
|
|
529
|
+
if (agent.process.killed || agent.process.exitCode !== null) {
|
|
530
|
+
reject(new Error(`Agent ${agent.id} process terminated during initialization`));
|
|
531
|
+
return;
|
|
532
|
+
}
|
|
533
|
+
// For now, assume agent is ready after a short delay
|
|
534
|
+
// In a real implementation, you might check for specific output or response
|
|
535
|
+
if (elapsed > 2000) {
|
|
536
|
+
// 2 seconds
|
|
537
|
+
resolve();
|
|
538
|
+
} else {
|
|
539
|
+
setTimeout(checkReady, checkInterval);
|
|
540
|
+
}
|
|
541
|
+
};
|
|
542
|
+
checkReady();
|
|
543
|
+
});
|
|
544
|
+
}
|
|
545
|
+
async selectOptimalAgent(taskDefinition) {
|
|
546
|
+
const availableAgents = this.processPool.idle.filter((agent)=>agent.status === 'idle');
|
|
547
|
+
if (availableAgents.length === 0) {
|
|
548
|
+
// Try to spawn a new agent if under limit
|
|
549
|
+
if (this.getTotalActiveAgents() < this.config.maxConcurrentAgents) {
|
|
550
|
+
const agentId = await this.spawnAgent({
|
|
551
|
+
type: 'task-specific',
|
|
552
|
+
capabilities: taskDefinition.requirements.capabilities
|
|
553
|
+
});
|
|
554
|
+
return this.agents.get(agentId) || null;
|
|
555
|
+
}
|
|
556
|
+
return null;
|
|
557
|
+
}
|
|
558
|
+
// Select agent based on capabilities and performance
|
|
559
|
+
const scoredAgents = availableAgents.map((agent)=>({
|
|
560
|
+
agent,
|
|
561
|
+
score: this.calculateAgentScore(agent, taskDefinition)
|
|
562
|
+
}));
|
|
563
|
+
scoredAgents.sort((a, b)=>b.score - a.score);
|
|
564
|
+
return scoredAgents[0].agent;
|
|
565
|
+
}
|
|
566
|
+
calculateAgentScore(agent, taskDefinition) {
|
|
567
|
+
let score = 0;
|
|
568
|
+
// Capability match
|
|
569
|
+
const requiredCapabilities = taskDefinition.requirements.capabilities;
|
|
570
|
+
const matchingCapabilities = agent.capabilities.filter((cap)=>requiredCapabilities.includes(cap));
|
|
571
|
+
score += matchingCapabilities.length / requiredCapabilities.length * 100;
|
|
572
|
+
// Performance metrics
|
|
573
|
+
score += agent.metrics.successRate * 50;
|
|
574
|
+
score += Math.max(0, 50 - agent.metrics.averageResponseTime / 1000) * 10; // Prefer faster agents
|
|
575
|
+
// Load balancing - prefer agents with fewer completed tasks
|
|
576
|
+
const maxTasks = Math.max(...this.processPool.idle.map((a)=>a.totalTasks), 1);
|
|
577
|
+
score += (1 - agent.totalTasks / maxTasks) * 20;
|
|
578
|
+
return score;
|
|
579
|
+
}
|
|
580
|
+
async executeTaskWithAgent(agent, taskDefinition, options) {
|
|
581
|
+
const startTime = performance.now();
|
|
582
|
+
try {
|
|
583
|
+
// Create execution context for the agent
|
|
584
|
+
const context = {
|
|
585
|
+
task: taskDefinition,
|
|
586
|
+
agent: this.convertToAgentState(agent),
|
|
587
|
+
workingDirectory: options.workingDirectory || this.config.workingDirectory,
|
|
588
|
+
tempDirectory: path.join(this.config.workingDirectory, 'temp', agent.id),
|
|
589
|
+
logDirectory: path.join(this.config.workingDirectory, 'logs', agent.id),
|
|
590
|
+
environment: {
|
|
591
|
+
...this.config.environmentVariables,
|
|
592
|
+
CLAUDE_AGENT_ID: agent.id,
|
|
593
|
+
CLAUDE_TASK_ID: taskDefinition.id.id
|
|
594
|
+
},
|
|
595
|
+
resources: {
|
|
596
|
+
maxMemory: taskDefinition.requirements.memoryRequired || 512 * 1024 * 1024,
|
|
597
|
+
maxCpuTime: taskDefinition.requirements.maxDuration || 300000,
|
|
598
|
+
maxDiskSpace: 1024 * 1024 * 1024,
|
|
599
|
+
maxNetworkConnections: 10,
|
|
600
|
+
maxFileHandles: 100,
|
|
601
|
+
priority: 1
|
|
602
|
+
}
|
|
603
|
+
};
|
|
604
|
+
// Execute using task executor
|
|
605
|
+
const result = await this.taskExecutor.executeClaudeTask(taskDefinition, context.agent, {
|
|
606
|
+
model: options.model || this.config.defaultModel,
|
|
607
|
+
maxTokens: options.maxTokens || this.config.maxTokens,
|
|
608
|
+
temperature: options.temperature || this.config.temperature,
|
|
609
|
+
timeout: options.timeout || this.config.timeout,
|
|
610
|
+
claudePath: this.config.claudeExecutablePath,
|
|
611
|
+
...options
|
|
612
|
+
});
|
|
613
|
+
const duration = performance.now() - startTime;
|
|
614
|
+
// Update agent activity
|
|
615
|
+
agent.lastActivity = new Date();
|
|
616
|
+
agent.totalTasks++;
|
|
617
|
+
agent.totalDuration += duration;
|
|
618
|
+
return result;
|
|
619
|
+
} catch (error) {
|
|
620
|
+
const duration = performance.now() - startTime;
|
|
621
|
+
agent.totalDuration += duration;
|
|
622
|
+
throw error;
|
|
623
|
+
}
|
|
624
|
+
}
|
|
625
|
+
convertToAgentState(agent) {
|
|
626
|
+
// Convert ClaudeAgent to AgentState for compatibility
|
|
627
|
+
return {
|
|
628
|
+
id: {
|
|
629
|
+
id: agent.id,
|
|
630
|
+
swarmId: 'claude-interface',
|
|
631
|
+
type: agent.type,
|
|
632
|
+
instance: 1
|
|
633
|
+
},
|
|
634
|
+
name: `Claude-${agent.id}`,
|
|
635
|
+
type: agent.type,
|
|
636
|
+
status: agent.status,
|
|
637
|
+
capabilities: this.createAgentCapabilities(agent.capabilities),
|
|
638
|
+
metrics: {
|
|
639
|
+
tasksCompleted: agent.metrics.tasksCompleted,
|
|
640
|
+
tasksFailed: agent.metrics.tasksFailed,
|
|
641
|
+
averageExecutionTime: agent.metrics.averageResponseTime,
|
|
642
|
+
successRate: agent.metrics.successRate,
|
|
643
|
+
cpuUsage: agent.metrics.cpuUsage,
|
|
644
|
+
memoryUsage: agent.metrics.memoryUsage,
|
|
645
|
+
diskUsage: 0,
|
|
646
|
+
networkUsage: 0,
|
|
647
|
+
codeQuality: 0.8,
|
|
648
|
+
testCoverage: 0.7,
|
|
649
|
+
bugRate: 0.1,
|
|
650
|
+
userSatisfaction: 0.9,
|
|
651
|
+
totalUptime: Date.now() - agent.spawnedAt.getTime(),
|
|
652
|
+
lastActivity: agent.lastActivity,
|
|
653
|
+
responseTime: agent.metrics.averageResponseTime
|
|
654
|
+
},
|
|
655
|
+
currentTask: agent.currentTask ? {
|
|
656
|
+
id: agent.currentTask,
|
|
657
|
+
swarmId: 'claude-interface',
|
|
658
|
+
sequence: 0,
|
|
659
|
+
priority: 1
|
|
660
|
+
} : undefined,
|
|
661
|
+
workload: agent.status === 'busy' ? 1 : 0,
|
|
662
|
+
health: agent.status === 'error' ? 0 : 1,
|
|
663
|
+
config: {
|
|
664
|
+
autonomyLevel: 0.8,
|
|
665
|
+
learningEnabled: false,
|
|
666
|
+
adaptationEnabled: false,
|
|
667
|
+
maxTasksPerHour: 60,
|
|
668
|
+
maxConcurrentTasks: 1,
|
|
669
|
+
timeoutThreshold: this.config.timeout,
|
|
670
|
+
reportingInterval: 10000,
|
|
671
|
+
heartbeatInterval: 5000,
|
|
672
|
+
permissions: [
|
|
673
|
+
'read',
|
|
674
|
+
'write',
|
|
675
|
+
'execute'
|
|
676
|
+
],
|
|
677
|
+
trustedAgents: [],
|
|
678
|
+
expertise: {},
|
|
679
|
+
preferences: {}
|
|
680
|
+
},
|
|
681
|
+
environment: {
|
|
682
|
+
runtime: 'claude',
|
|
683
|
+
version: '1.0.0',
|
|
684
|
+
workingDirectory: this.config.workingDirectory,
|
|
685
|
+
tempDirectory: path.join(this.config.workingDirectory, 'temp', agent.id),
|
|
686
|
+
logDirectory: path.join(this.config.workingDirectory, 'logs', agent.id),
|
|
687
|
+
apiEndpoints: {},
|
|
688
|
+
credentials: {},
|
|
689
|
+
availableTools: agent.capabilities,
|
|
690
|
+
toolConfigs: {}
|
|
691
|
+
},
|
|
692
|
+
endpoints: [],
|
|
693
|
+
lastHeartbeat: agent.lastActivity,
|
|
694
|
+
taskHistory: [],
|
|
695
|
+
errorHistory: [],
|
|
696
|
+
parentAgent: undefined,
|
|
697
|
+
childAgents: [],
|
|
698
|
+
collaborators: []
|
|
699
|
+
};
|
|
700
|
+
}
|
|
701
|
+
createAgentCapabilities(capabilities) {
|
|
702
|
+
return {
|
|
703
|
+
codeGeneration: capabilities.includes('coding') || capabilities.includes('codeGeneration'),
|
|
704
|
+
codeReview: capabilities.includes('review') || capabilities.includes('codeReview'),
|
|
705
|
+
testing: capabilities.includes('testing'),
|
|
706
|
+
documentation: capabilities.includes('documentation'),
|
|
707
|
+
research: capabilities.includes('research'),
|
|
708
|
+
analysis: capabilities.includes('analysis'),
|
|
709
|
+
webSearch: capabilities.includes('webSearch'),
|
|
710
|
+
apiIntegration: capabilities.includes('apiIntegration'),
|
|
711
|
+
fileSystem: capabilities.includes('fileSystem'),
|
|
712
|
+
terminalAccess: capabilities.includes('terminal'),
|
|
713
|
+
languages: capabilities.filter((c)=>[
|
|
714
|
+
'javascript',
|
|
715
|
+
'typescript',
|
|
716
|
+
'python',
|
|
717
|
+
'java'
|
|
718
|
+
].includes(c)),
|
|
719
|
+
frameworks: capabilities.filter((c)=>[
|
|
720
|
+
'react',
|
|
721
|
+
'node',
|
|
722
|
+
'express'
|
|
723
|
+
].includes(c)),
|
|
724
|
+
domains: capabilities.filter((c)=>[
|
|
725
|
+
'web',
|
|
726
|
+
'api',
|
|
727
|
+
'database'
|
|
728
|
+
].includes(c)),
|
|
729
|
+
tools: capabilities.filter((c)=>[
|
|
730
|
+
'bash',
|
|
731
|
+
'git',
|
|
732
|
+
'npm'
|
|
733
|
+
].includes(c)),
|
|
734
|
+
maxConcurrentTasks: 1,
|
|
735
|
+
maxMemoryUsage: 512 * 1024 * 1024,
|
|
736
|
+
maxExecutionTime: this.config.timeout,
|
|
737
|
+
reliability: 0.9,
|
|
738
|
+
speed: 1.0,
|
|
739
|
+
quality: 0.8
|
|
740
|
+
};
|
|
741
|
+
}
|
|
742
|
+
async cancelAgentTask(agent) {
|
|
743
|
+
if (agent.process && !agent.process.killed) {
|
|
744
|
+
// Send interrupt signal
|
|
745
|
+
agent.process.kill('SIGINT');
|
|
746
|
+
// Wait briefly for graceful shutdown
|
|
747
|
+
await new Promise((resolve)=>setTimeout(resolve, 1000));
|
|
748
|
+
// Force kill if still running
|
|
749
|
+
if (!agent.process.killed) {
|
|
750
|
+
agent.process.kill('SIGKILL');
|
|
751
|
+
}
|
|
752
|
+
}
|
|
753
|
+
agent.currentTask = undefined;
|
|
754
|
+
agent.status = 'idle';
|
|
755
|
+
agent.lastActivity = new Date();
|
|
756
|
+
}
|
|
757
|
+
async terminateProcess(process1) {
|
|
758
|
+
if (process1.killed || process1.exitCode !== null) {
|
|
759
|
+
return;
|
|
760
|
+
}
|
|
761
|
+
// Send termination signal
|
|
762
|
+
process1.kill('SIGTERM');
|
|
763
|
+
// Wait for graceful shutdown
|
|
764
|
+
await new Promise((resolve)=>setTimeout(resolve, 2000));
|
|
765
|
+
// Force kill if still running
|
|
766
|
+
if (!process1.killed && process1.exitCode === null) {
|
|
767
|
+
process1.kill('SIGKILL');
|
|
768
|
+
}
|
|
769
|
+
}
|
|
770
|
+
async terminateAllAgents() {
|
|
771
|
+
const terminationPromises = Array.from(this.agents.keys()).map((agentId)=>this.terminateAgent(agentId, 'Interface shutdown'));
|
|
772
|
+
await Promise.allSettled(terminationPromises);
|
|
773
|
+
}
|
|
774
|
+
moveAgentToBusyPool(agent) {
|
|
775
|
+
const idleIndex = this.processPool.idle.indexOf(agent);
|
|
776
|
+
if (idleIndex !== -1) {
|
|
777
|
+
this.processPool.idle.splice(idleIndex, 1);
|
|
778
|
+
this.processPool.busy.push(agent);
|
|
779
|
+
}
|
|
780
|
+
}
|
|
781
|
+
returnAgentToIdlePool(agent) {
|
|
782
|
+
agent.status = 'idle';
|
|
783
|
+
agent.currentTask = undefined;
|
|
784
|
+
agent.lastActivity = new Date();
|
|
785
|
+
const busyIndex = this.processPool.busy.indexOf(agent);
|
|
786
|
+
if (busyIndex !== -1) {
|
|
787
|
+
this.processPool.busy.splice(busyIndex, 1);
|
|
788
|
+
this.processPool.idle.push(agent);
|
|
789
|
+
}
|
|
790
|
+
}
|
|
791
|
+
moveAgentToFailedPool(agent) {
|
|
792
|
+
// Remove from other pools
|
|
793
|
+
this.removeAgentFromPools(agent);
|
|
794
|
+
this.processPool.failed.push(agent);
|
|
795
|
+
}
|
|
796
|
+
removeAgentFromPools(agent) {
|
|
797
|
+
const idleIndex = this.processPool.idle.indexOf(agent);
|
|
798
|
+
if (idleIndex !== -1) {
|
|
799
|
+
this.processPool.idle.splice(idleIndex, 1);
|
|
800
|
+
}
|
|
801
|
+
const busyIndex = this.processPool.busy.indexOf(agent);
|
|
802
|
+
if (busyIndex !== -1) {
|
|
803
|
+
this.processPool.busy.splice(busyIndex, 1);
|
|
804
|
+
}
|
|
805
|
+
const failedIndex = this.processPool.failed.indexOf(agent);
|
|
806
|
+
if (failedIndex !== -1) {
|
|
807
|
+
this.processPool.failed.splice(failedIndex, 1);
|
|
808
|
+
}
|
|
809
|
+
}
|
|
810
|
+
updateAgentMetrics(agent, execution) {
|
|
811
|
+
const metrics = agent.metrics;
|
|
812
|
+
// Update averages
|
|
813
|
+
const totalTasks = metrics.tasksCompleted + metrics.tasksFailed;
|
|
814
|
+
if (execution.duration) {
|
|
815
|
+
metrics.averageResponseTime = totalTasks > 0 ? (metrics.averageResponseTime * (totalTasks - 1) + execution.duration) / totalTasks : execution.duration;
|
|
816
|
+
}
|
|
817
|
+
// Update success rate
|
|
818
|
+
metrics.successRate = totalTasks > 0 ? metrics.tasksCompleted / totalTasks : 0;
|
|
819
|
+
// Update error rate
|
|
820
|
+
metrics.errorRate = 1 - metrics.successRate;
|
|
821
|
+
// Update token usage if available
|
|
822
|
+
if (execution.tokensUsed) {
|
|
823
|
+
metrics.totalTokensUsed += execution.tokensUsed;
|
|
824
|
+
}
|
|
825
|
+
}
|
|
826
|
+
getTotalActiveAgents() {
|
|
827
|
+
return this.processPool.idle.length + this.processPool.busy.length;
|
|
828
|
+
}
|
|
829
|
+
calculateThroughput() {
|
|
830
|
+
const agents = Array.from(this.agents.values());
|
|
831
|
+
const totalTasks = agents.reduce((sum, a)=>sum + a.totalTasks, 0);
|
|
832
|
+
const totalTime = agents.reduce((sum, a)=>sum + a.totalDuration, 0);
|
|
833
|
+
return totalTime > 0 ? totalTasks / totalTime * 60000 : 0; // tasks per minute
|
|
834
|
+
}
|
|
835
|
+
calculatePoolUtilization() {
|
|
836
|
+
const total = this.getTotalActiveAgents();
|
|
837
|
+
const busy = this.processPool.busy.length;
|
|
838
|
+
return total > 0 ? busy / total : 0;
|
|
839
|
+
}
|
|
840
|
+
startHealthChecks() {
|
|
841
|
+
this.healthCheckInterval = setInterval(()=>{
|
|
842
|
+
this.performHealthCheck();
|
|
843
|
+
}, this.config.healthCheckInterval);
|
|
844
|
+
}
|
|
845
|
+
performHealthCheck() {
|
|
846
|
+
const now = Date.now();
|
|
847
|
+
for (const agent of this.agents.values()){
|
|
848
|
+
// Check for stalled agents
|
|
849
|
+
const inactiveTime = now - agent.lastActivity.getTime();
|
|
850
|
+
if (agent.status === 'busy' && inactiveTime > this.config.timeout * 2) {
|
|
851
|
+
this.logger.warn('Agent appears stalled', {
|
|
852
|
+
agentId: agent.id,
|
|
853
|
+
inactiveTime,
|
|
854
|
+
currentTask: agent.currentTask
|
|
855
|
+
});
|
|
856
|
+
// Try to recover the agent
|
|
857
|
+
this.recoverStalledAgent(agent);
|
|
858
|
+
}
|
|
859
|
+
// Check for failed processes
|
|
860
|
+
if (agent.process.killed || agent.process.exitCode !== null) {
|
|
861
|
+
if (agent.status !== 'terminated') {
|
|
862
|
+
this.logger.warn('Agent process died unexpectedly', {
|
|
863
|
+
agentId: agent.id,
|
|
864
|
+
exitCode: agent.process.exitCode
|
|
865
|
+
});
|
|
866
|
+
agent.status = 'error';
|
|
867
|
+
this.moveAgentToFailedPool(agent);
|
|
868
|
+
}
|
|
869
|
+
}
|
|
870
|
+
}
|
|
871
|
+
}
|
|
872
|
+
async recoverStalledAgent(agent) {
|
|
873
|
+
try {
|
|
874
|
+
if (agent.currentTask) {
|
|
875
|
+
await this.cancelExecution(agent.currentTask, 'Agent recovery');
|
|
876
|
+
}
|
|
877
|
+
this.returnAgentToIdlePool(agent);
|
|
878
|
+
this.logger.info('Agent recovered from stalled state', {
|
|
879
|
+
agentId: agent.id
|
|
880
|
+
});
|
|
881
|
+
} catch (error) {
|
|
882
|
+
this.logger.error('Failed to recover stalled agent', {
|
|
883
|
+
agentId: agent.id,
|
|
884
|
+
error: error instanceof Error ? error.message : String(error)
|
|
885
|
+
});
|
|
886
|
+
// Terminate the problematic agent
|
|
887
|
+
await this.terminateAgent(agent.id, 'Recovery failed');
|
|
888
|
+
}
|
|
889
|
+
}
|
|
890
|
+
initializeProcessPool() {
|
|
891
|
+
return {
|
|
892
|
+
idle: [],
|
|
893
|
+
busy: [],
|
|
894
|
+
failed: [],
|
|
895
|
+
totalSpawned: 0,
|
|
896
|
+
totalTerminated: 0,
|
|
897
|
+
recyclingEnabled: this.config.processRecycling,
|
|
898
|
+
maxAge: 3600000,
|
|
899
|
+
maxTasks: 100
|
|
900
|
+
};
|
|
901
|
+
}
|
|
902
|
+
initializeAgentMetrics() {
|
|
903
|
+
return {
|
|
904
|
+
tasksCompleted: 0,
|
|
905
|
+
tasksFailed: 0,
|
|
906
|
+
averageResponseTime: 0,
|
|
907
|
+
totalTokensUsed: 0,
|
|
908
|
+
memoryUsage: 0,
|
|
909
|
+
cpuUsage: 0,
|
|
910
|
+
errorRate: 0,
|
|
911
|
+
successRate: 0
|
|
912
|
+
};
|
|
913
|
+
}
|
|
914
|
+
createDefaultConfig(config) {
|
|
915
|
+
return {
|
|
916
|
+
claudeExecutablePath: 'claude',
|
|
917
|
+
defaultModel: 'sonnet',
|
|
918
|
+
maxTokens: 4096,
|
|
919
|
+
temperature: 0.7,
|
|
920
|
+
timeout: 300000,
|
|
921
|
+
maxConcurrentAgents: 10,
|
|
922
|
+
enableStreaming: false,
|
|
923
|
+
enableLogging: true,
|
|
924
|
+
workingDirectory: process.cwd(),
|
|
925
|
+
environmentVariables: {},
|
|
926
|
+
agentPoolSize: 0,
|
|
927
|
+
processRecycling: true,
|
|
928
|
+
healthCheckInterval: 30000,
|
|
929
|
+
...config
|
|
930
|
+
};
|
|
931
|
+
}
|
|
932
|
+
setupEventHandlers() {
|
|
933
|
+
this.on('agent:spawned', (data)=>{
|
|
934
|
+
this.logger.info('Agent spawned event', data);
|
|
935
|
+
});
|
|
936
|
+
this.on('agent:terminated', (data)=>{
|
|
937
|
+
this.logger.info('Agent terminated event', data);
|
|
938
|
+
});
|
|
939
|
+
this.on('task:completed', (data)=>{
|
|
940
|
+
this.logger.info('Task completed event', data);
|
|
941
|
+
});
|
|
942
|
+
this.on('task:cancelled', (data)=>{
|
|
943
|
+
this.logger.warn('Task cancelled event', data);
|
|
944
|
+
});
|
|
945
|
+
}
|
|
946
|
+
constructor(config = {}, memoryManager){
|
|
947
|
+
super(), _define_property(this, "logger", void 0), _define_property(this, "config", void 0), _define_property(this, "memoryManager", void 0), _define_property(this, "processPool", void 0), _define_property(this, "activeExecutions", new Map()), _define_property(this, "agents", new Map()), _define_property(this, "taskExecutor", void 0), _define_property(this, "healthCheckInterval", void 0), _define_property(this, "isInitialized", false);
|
|
948
|
+
this.logger = new Logger('ClaudeCodeInterface');
|
|
949
|
+
this.config = this.createDefaultConfig(config);
|
|
950
|
+
this.memoryManager = memoryManager;
|
|
951
|
+
this.processPool = this.initializeProcessPool();
|
|
952
|
+
this.taskExecutor = new TaskExecutor({
|
|
953
|
+
timeoutMs: this.config.timeout,
|
|
954
|
+
enableMetrics: true,
|
|
955
|
+
captureOutput: true,
|
|
956
|
+
streamOutput: this.config.enableStreaming
|
|
957
|
+
});
|
|
958
|
+
this.setupEventHandlers();
|
|
959
|
+
}
|
|
960
|
+
}
|
|
961
|
+
export default ClaudeCodeInterface;
|