tachibot-mcp 2.0.2

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.
Files changed (214) hide show
  1. package/.env.example +260 -0
  2. package/CHANGELOG.md +54 -0
  3. package/CODE_OF_CONDUCT.md +56 -0
  4. package/CONTRIBUTING.md +54 -0
  5. package/Dockerfile +36 -0
  6. package/LICENSE +644 -0
  7. package/README.md +201 -0
  8. package/SECURITY.md +95 -0
  9. package/dist/personality/komaai-expressions.js +12 -0
  10. package/dist/profiles/balanced.json +33 -0
  11. package/dist/profiles/code_focus.json +33 -0
  12. package/dist/profiles/full.json +33 -0
  13. package/dist/profiles/minimal.json +33 -0
  14. package/dist/profiles/research_power.json +33 -0
  15. package/dist/scripts/build-profiles.js +46 -0
  16. package/dist/src/application/services/focus/FocusModeRegistry.js +46 -0
  17. package/dist/src/application/services/focus/FocusTool.service.js +109 -0
  18. package/dist/src/application/services/focus/ModeRegistry.js +46 -0
  19. package/dist/src/application/services/focus/modes/focus-deep.mode.js +27 -0
  20. package/dist/src/application/services/focus/modes/status.mode.js +50 -0
  21. package/dist/src/application/services/focus/modes/tachibot-status.mode.js +50 -0
  22. package/dist/src/collaborative-orchestrator.js +391 -0
  23. package/dist/src/config/model-constants.js +188 -0
  24. package/dist/src/config/model-defaults.js +57 -0
  25. package/dist/src/config/model-preferences.js +382 -0
  26. package/dist/src/config/timeout-config.js +130 -0
  27. package/dist/src/config.js +173 -0
  28. package/dist/src/domain/interfaces/IFocusMode.js +5 -0
  29. package/dist/src/domain/interfaces/IProvider.js +6 -0
  30. package/dist/src/domain/interfaces/ITool.js +5 -0
  31. package/dist/src/focus-deep.js +245 -0
  32. package/dist/src/infrastructure/ascii/art/robots.ascii.js +16 -0
  33. package/dist/src/mcp-client.js +90 -0
  34. package/dist/src/memory/index.js +17 -0
  35. package/dist/src/memory/memory-config.js +135 -0
  36. package/dist/src/memory/memory-interface.js +174 -0
  37. package/dist/src/memory/memory-manager.js +383 -0
  38. package/dist/src/memory/providers/devlog-provider.js +385 -0
  39. package/dist/src/memory/providers/hybrid-provider.js +399 -0
  40. package/dist/src/memory/providers/local-provider.js +388 -0
  41. package/dist/src/memory/providers/mem0-provider.js +337 -0
  42. package/dist/src/modes/architect.js +477 -0
  43. package/dist/src/modes/auditor.js +362 -0
  44. package/dist/src/modes/challenger.js +841 -0
  45. package/dist/src/modes/code-reviewer.js +382 -0
  46. package/dist/src/modes/commit-guardian.js +424 -0
  47. package/dist/src/modes/documentation-writer.js +572 -0
  48. package/dist/src/modes/scout.js +587 -0
  49. package/dist/src/modes/shared/helpers/challenger-helpers.js +454 -0
  50. package/dist/src/modes/shared/helpers/index.js +17 -0
  51. package/dist/src/modes/shared/helpers/scout-helpers.js +270 -0
  52. package/dist/src/modes/shared/helpers/verifier-helpers.js +332 -0
  53. package/dist/src/modes/test-architect.js +767 -0
  54. package/dist/src/modes/verifier.js +378 -0
  55. package/dist/src/monitoring/performance-monitor.js +435 -0
  56. package/dist/src/optimization/batch-executor.js +121 -0
  57. package/dist/src/optimization/context-pruner.js +196 -0
  58. package/dist/src/optimization/cost-monitor.js +338 -0
  59. package/dist/src/optimization/index.js +65 -0
  60. package/dist/src/optimization/model-router.js +264 -0
  61. package/dist/src/optimization/result-cache.js +114 -0
  62. package/dist/src/optimization/token-optimizer.js +257 -0
  63. package/dist/src/optimization/token-tracker.js +118 -0
  64. package/dist/src/orchestrator-instructions.js +128 -0
  65. package/dist/src/orchestrator-lite.js +139 -0
  66. package/dist/src/orchestrator.js +191 -0
  67. package/dist/src/orchestrators/collaborative/interfaces/IToolExecutionEngine.js +1 -0
  68. package/dist/src/orchestrators/collaborative/interfaces/IToolExecutionStrategy.js +5 -0
  69. package/dist/src/orchestrators/collaborative/interfaces/IVisualizationRenderer.js +1 -0
  70. package/dist/src/orchestrators/collaborative/registries/ModelProviderRegistry.js +95 -0
  71. package/dist/src/orchestrators/collaborative/registries/ToolAdapterRegistry.js +64 -0
  72. package/dist/src/orchestrators/collaborative/services/tool-execution/ToolExecutionService.js +502 -0
  73. package/dist/src/orchestrators/collaborative/services/visualization/VisualizationService.js +206 -0
  74. package/dist/src/orchestrators/collaborative/types/session-types.js +5 -0
  75. package/dist/src/profiles/balanced.js +37 -0
  76. package/dist/src/profiles/code_focus.js +37 -0
  77. package/dist/src/profiles/debug_intensive.js +59 -0
  78. package/dist/src/profiles/full.js +37 -0
  79. package/dist/src/profiles/minimal.js +37 -0
  80. package/dist/src/profiles/research_code.js +59 -0
  81. package/dist/src/profiles/research_power.js +37 -0
  82. package/dist/src/profiles/types.js +5 -0
  83. package/dist/src/profiles/workflow_builder.js +53 -0
  84. package/dist/src/prompt-engineer-lite.js +78 -0
  85. package/dist/src/prompt-engineer.js +399 -0
  86. package/dist/src/reasoning-chain.js +508 -0
  87. package/dist/src/sequential-thinking.js +291 -0
  88. package/dist/src/server-diagnostic.js +74 -0
  89. package/dist/src/server-raw.js +158 -0
  90. package/dist/src/server-simple.js +58 -0
  91. package/dist/src/server.js +514 -0
  92. package/dist/src/session/session-logger.js +617 -0
  93. package/dist/src/session/session-manager.js +571 -0
  94. package/dist/src/session/session-tools.js +400 -0
  95. package/dist/src/tools/advanced-modes.js +200 -0
  96. package/dist/src/tools/claude-integration.js +356 -0
  97. package/dist/src/tools/consolidated/ai-router.js +174 -0
  98. package/dist/src/tools/consolidated/ai-tool.js +48 -0
  99. package/dist/src/tools/consolidated/brainstorm-tool.js +87 -0
  100. package/dist/src/tools/consolidated/environment-detector.js +80 -0
  101. package/dist/src/tools/consolidated/index.js +50 -0
  102. package/dist/src/tools/consolidated/search-tool.js +110 -0
  103. package/dist/src/tools/consolidated/workflow-tool.js +238 -0
  104. package/dist/src/tools/gemini-tools.js +329 -0
  105. package/dist/src/tools/grok-enhanced.js +376 -0
  106. package/dist/src/tools/grok-tools.js +299 -0
  107. package/dist/src/tools/lmstudio-tools.js +223 -0
  108. package/dist/src/tools/openai-tools.js +498 -0
  109. package/dist/src/tools/openrouter-tools.js +317 -0
  110. package/dist/src/tools/optimized-wrapper.js +204 -0
  111. package/dist/src/tools/perplexity-tools.js +294 -0
  112. package/dist/src/tools/pingpong-tool.js +343 -0
  113. package/dist/src/tools/qwen-wrapper.js +74 -0
  114. package/dist/src/tools/tool-router.js +444 -0
  115. package/dist/src/tools/unified-ai-provider.js +260 -0
  116. package/dist/src/tools/workflow-runner.js +425 -0
  117. package/dist/src/tools/workflow-validator-tool.js +107 -0
  118. package/dist/src/types.js +23 -0
  119. package/dist/src/utils/input-validator.js +130 -0
  120. package/dist/src/utils/model-router.js +91 -0
  121. package/dist/src/utils/progress-stream.js +255 -0
  122. package/dist/src/utils/provider-router.js +88 -0
  123. package/dist/src/utils/smart-api-client.js +146 -0
  124. package/dist/src/utils/table-builder.js +218 -0
  125. package/dist/src/utils/timestamp-formatter.js +134 -0
  126. package/dist/src/utils/tool-compressor.js +257 -0
  127. package/dist/src/utils/tool-config.js +201 -0
  128. package/dist/src/validators/dependency-graph-validator.js +147 -0
  129. package/dist/src/validators/interpolation-validator.js +222 -0
  130. package/dist/src/validators/output-usage-validator.js +151 -0
  131. package/dist/src/validators/syntax-validator.js +102 -0
  132. package/dist/src/validators/tool-registry-validator.js +123 -0
  133. package/dist/src/validators/tool-types.js +97 -0
  134. package/dist/src/validators/types.js +8 -0
  135. package/dist/src/validators/workflow-validator.js +134 -0
  136. package/dist/src/visualizer-lite.js +42 -0
  137. package/dist/src/visualizer.js +179 -0
  138. package/dist/src/workflows/circuit-breaker.js +199 -0
  139. package/dist/src/workflows/custom-workflows.js +451 -0
  140. package/dist/src/workflows/engine/AutoSynthesizer.js +97 -0
  141. package/dist/src/workflows/engine/StepParameterResolver.js +74 -0
  142. package/dist/src/workflows/engine/VariableInterpolator.js +123 -0
  143. package/dist/src/workflows/engine/WorkflowDiscovery.js +125 -0
  144. package/dist/src/workflows/engine/WorkflowExecutionEngine.js +485 -0
  145. package/dist/src/workflows/engine/WorkflowExecutor.js +113 -0
  146. package/dist/src/workflows/engine/WorkflowFileManager.js +244 -0
  147. package/dist/src/workflows/engine/WorkflowHelpers.js +114 -0
  148. package/dist/src/workflows/engine/WorkflowOutputFormatter.js +83 -0
  149. package/dist/src/workflows/engine/events/WorkflowEventBus.js +132 -0
  150. package/dist/src/workflows/engine/events/interfaces/IEventBus.js +5 -0
  151. package/dist/src/workflows/engine/handlers/ErrorRecoveryHandler.js +162 -0
  152. package/dist/src/workflows/engine/handlers/PromptEnhancementHandler.js +115 -0
  153. package/dist/src/workflows/engine/handlers/SessionPersistenceHandler.js +167 -0
  154. package/dist/src/workflows/engine/handlers/StepExecutionHandler.js +231 -0
  155. package/dist/src/workflows/engine/handlers/ToolInvocationHandler.js +46 -0
  156. package/dist/src/workflows/engine/interfaces/IAutoSynthesizer.js +5 -0
  157. package/dist/src/workflows/engine/interfaces/IStepParameterResolver.js +5 -0
  158. package/dist/src/workflows/engine/interfaces/IVariableInterpolator.js +5 -0
  159. package/dist/src/workflows/engine/interfaces/IWorkflowDiscovery.js +4 -0
  160. package/dist/src/workflows/engine/interfaces/IWorkflowFileManager.js +5 -0
  161. package/dist/src/workflows/engine/interfaces/IWorkflowOutputFormatter.js +5 -0
  162. package/dist/src/workflows/engine/state/WorkflowStateMachine.js +194 -0
  163. package/dist/src/workflows/engine/state/interfaces/IStateMachine.js +17 -0
  164. package/dist/src/workflows/fallback-strategies.js +373 -0
  165. package/dist/src/workflows/message-queue.js +455 -0
  166. package/dist/src/workflows/model-router.js +189 -0
  167. package/dist/src/workflows/orchestrator-examples.js +174 -0
  168. package/dist/src/workflows/orchestrator-integration.js +200 -0
  169. package/dist/src/workflows/self-healing.js +524 -0
  170. package/dist/src/workflows/tool-mapper.js +407 -0
  171. package/dist/src/workflows/tool-orchestrator.js +796 -0
  172. package/dist/src/workflows/workflow-engine.js +573 -0
  173. package/dist/src/workflows/workflow-parser.js +283 -0
  174. package/dist/src/workflows/workflow-types.js +95 -0
  175. package/dist/src/workflows.js +568 -0
  176. package/dist/test-workflow-file-output.js +93 -0
  177. package/docs/API_KEYS.md +570 -0
  178. package/docs/CLAUDE_CODE_SETUP.md +181 -0
  179. package/docs/CLAUDE_DESKTOP_MANUAL.md +127 -0
  180. package/docs/CONFIGURATION.md +745 -0
  181. package/docs/FOCUS_MODES.md +240 -0
  182. package/docs/INSTALLATION_BOTH.md +145 -0
  183. package/docs/TERMS.md +352 -0
  184. package/docs/TOOLS_REFERENCE.md +1622 -0
  185. package/docs/TOOL_PARAMETERS.md +496 -0
  186. package/docs/TOOL_PROFILES.md +236 -0
  187. package/docs/WORKFLOWS.md +987 -0
  188. package/docs/WORKFLOW_OUTPUT.md +198 -0
  189. package/docs/WORKFLOW_PROGRESS_TRACKING.md +305 -0
  190. package/docs/workflows/design-brainstorm.md +335 -0
  191. package/package.json +97 -0
  192. package/profiles/balanced.json +37 -0
  193. package/profiles/code_focus.json +37 -0
  194. package/profiles/debug_intensive.json +34 -0
  195. package/profiles/full.json +37 -0
  196. package/profiles/minimal.json +37 -0
  197. package/profiles/research_power.json +37 -0
  198. package/profiles/workflow_builder.json +37 -0
  199. package/smithery.yaml +66 -0
  200. package/start.sh +8 -0
  201. package/tools.config.json +81 -0
  202. package/tsconfig.json +18 -0
  203. package/workflows/accessibility-code-audit.yaml +92 -0
  204. package/workflows/code-architecture-review.yaml +202 -0
  205. package/workflows/code-review.yaml +142 -0
  206. package/workflows/core/iterative-problem-solver.yaml +283 -0
  207. package/workflows/creative-brainstorm-yaml.yaml +215 -0
  208. package/workflows/pingpong.yaml +141 -0
  209. package/workflows/system/README.md +412 -0
  210. package/workflows/system/challenger.yaml +175 -0
  211. package/workflows/system/scout.yaml +164 -0
  212. package/workflows/system/verifier.yaml +133 -0
  213. package/workflows/ultra-creative-brainstorm.yaml +318 -0
  214. package/workflows/ux-research-flow.yaml +92 -0
@@ -0,0 +1,435 @@
1
+ import { EventEmitter } from 'events';
2
+ /**
3
+ * Performance monitoring for workflow execution
4
+ */
5
+ export class PerformanceMonitor extends EventEmitter {
6
+ constructor() {
7
+ super();
8
+ this.metrics = [];
9
+ this.systemMetrics = [];
10
+ this.costModels = new Map();
11
+ this.activeRequests = new Map();
12
+ this.metricsRetention = 3600000; // 1 hour default
13
+ this.initializeCostModels();
14
+ this.startAggregation();
15
+ this.startSystemMonitoring();
16
+ }
17
+ /**
18
+ * Initialize cost models for different AI providers
19
+ */
20
+ initializeCostModels() {
21
+ // GPT-5 flagship
22
+ this.costModels.set('gpt5', {
23
+ model: 'gpt5',
24
+ inputTokenCost: 0.00125,
25
+ outputTokenCost: 0.01
26
+ });
27
+ // Gemini 2.5 Pro
28
+ this.costModels.set('gemini_25_pro', {
29
+ model: 'gemini_25_pro',
30
+ inputTokenCost: 0.00125,
31
+ outputTokenCost: 0.005
32
+ });
33
+ // GPT-5-mini (cost-effective, balanced)
34
+ this.costModels.set('gpt5_mini', {
35
+ model: 'gpt5_mini',
36
+ inputTokenCost: 0.00075,
37
+ outputTokenCost: 0.003
38
+ });
39
+ // Perplexity
40
+ this.costModels.set('perplexity', {
41
+ model: 'perplexity',
42
+ inputTokenCost: 0.001,
43
+ outputTokenCost: 0.001
44
+ });
45
+ // Focus deep reasoning (expensive)
46
+ this.costModels.set('focus', {
47
+ model: 'focus',
48
+ inputTokenCost: 0.005,
49
+ outputTokenCost: 0.02,
50
+ baseCost: 0.01
51
+ });
52
+ }
53
+ /**
54
+ * Start tracking a request
55
+ */
56
+ startRequest(requestId, tool) {
57
+ this.activeRequests.set(requestId, {
58
+ start: Date.now(),
59
+ tool
60
+ });
61
+ this.emit('request-started', { requestId, tool });
62
+ }
63
+ /**
64
+ * Complete tracking a request
65
+ */
66
+ completeRequest(requestId, success, tokensUsed, error, metadata) {
67
+ const request = this.activeRequests.get(requestId);
68
+ if (!request)
69
+ return;
70
+ const duration = Date.now() - request.start;
71
+ const cost = this.calculateCost(request.tool, tokensUsed);
72
+ const metric = {
73
+ timestamp: Date.now(),
74
+ requestId,
75
+ tool: request.tool,
76
+ duration,
77
+ tokensUsed: {
78
+ input: tokensUsed?.input || 0,
79
+ output: tokensUsed?.output || 0,
80
+ total: (tokensUsed?.input || 0) + (tokensUsed?.output || 0)
81
+ },
82
+ cost,
83
+ success,
84
+ error,
85
+ metadata
86
+ };
87
+ this.metrics.push(metric);
88
+ this.activeRequests.delete(requestId);
89
+ // Clean old metrics
90
+ this.cleanOldMetrics();
91
+ // Emit events
92
+ this.emit('request-completed', metric);
93
+ // Check for performance issues
94
+ this.checkPerformanceAlerts(metric);
95
+ }
96
+ /**
97
+ * Calculate cost based on token usage
98
+ */
99
+ calculateCost(tool, tokensUsed) {
100
+ if (!tokensUsed)
101
+ return 0;
102
+ const costModel = this.costModels.get(tool);
103
+ if (!costModel)
104
+ return 0;
105
+ const inputCost = (tokensUsed.input / 1000) * costModel.inputTokenCost;
106
+ const outputCost = (tokensUsed.output / 1000) * costModel.outputTokenCost;
107
+ const baseCost = costModel.baseCost || 0;
108
+ return inputCost + outputCost + baseCost;
109
+ }
110
+ /**
111
+ * Check for performance alerts
112
+ */
113
+ checkPerformanceAlerts(metric) {
114
+ // Slow response alert
115
+ if (metric.duration > 30000) {
116
+ this.emit('slow-response-alert', {
117
+ tool: metric.tool,
118
+ duration: metric.duration,
119
+ requestId: metric.requestId
120
+ });
121
+ }
122
+ // High cost alert
123
+ if (metric.cost > 0.1) {
124
+ this.emit('high-cost-alert', {
125
+ tool: metric.tool,
126
+ cost: metric.cost,
127
+ tokens: metric.tokensUsed.total,
128
+ requestId: metric.requestId
129
+ });
130
+ }
131
+ // High token usage alert (potential 25k limit issue)
132
+ if (metric.tokensUsed.total > 20000) {
133
+ this.emit('high-token-alert', {
134
+ tool: metric.tool,
135
+ tokens: metric.tokensUsed.total,
136
+ requestId: metric.requestId,
137
+ warning: 'Approaching 25k token limit'
138
+ });
139
+ }
140
+ // Error rate alert
141
+ if (!metric.success) {
142
+ const recentErrors = this.getRecentErrorRate();
143
+ if (recentErrors > 0.3) {
144
+ this.emit('high-error-rate', {
145
+ errorRate: recentErrors,
146
+ tool: metric.tool
147
+ });
148
+ }
149
+ }
150
+ }
151
+ /**
152
+ * Get recent error rate
153
+ */
154
+ getRecentErrorRate() {
155
+ const recent = this.getRecentMetrics(5); // Last 5 minutes
156
+ if (recent.length === 0)
157
+ return 0;
158
+ const errors = recent.filter(m => !m.success).length;
159
+ return errors / recent.length;
160
+ }
161
+ /**
162
+ * Get recent metrics
163
+ */
164
+ getRecentMetrics(minutes) {
165
+ const cutoff = Date.now() - (minutes * 60 * 1000);
166
+ return this.metrics.filter(m => m.timestamp > cutoff);
167
+ }
168
+ /**
169
+ * Start aggregation interval
170
+ */
171
+ startAggregation() {
172
+ this.aggregationInterval = setInterval(() => {
173
+ const aggregated = this.aggregateMetrics();
174
+ this.emit('metrics-aggregated', aggregated);
175
+ }, 60000); // Every minute
176
+ }
177
+ /**
178
+ * Start system monitoring
179
+ */
180
+ startSystemMonitoring() {
181
+ this.systemMonitorInterval = setInterval(() => {
182
+ const metrics = this.collectSystemMetrics();
183
+ this.systemMetrics.push(metrics);
184
+ this.emit('system-metrics', metrics);
185
+ // Clean old system metrics
186
+ const cutoff = Date.now() - this.metricsRetention;
187
+ this.systemMetrics = this.systemMetrics.filter(m => m.timestamp > cutoff);
188
+ }, 10000); // Every 10 seconds
189
+ }
190
+ /**
191
+ * Collect system metrics
192
+ */
193
+ collectSystemMetrics() {
194
+ const memUsage = process.memoryUsage();
195
+ const cpuUsage = process.cpuUsage();
196
+ return {
197
+ timestamp: Date.now(),
198
+ activeTasks: this.activeRequests.size,
199
+ queuedTasks: 0, // Would come from message queue
200
+ memoryUsage: memUsage.heapUsed / 1024 / 1024, // MB
201
+ cpuUsage: (cpuUsage.user + cpuUsage.system) / 1000000, // seconds
202
+ networkLatency: 0, // Would need actual measurement
203
+ errorRate: this.getRecentErrorRate(),
204
+ systemHealth: this.calculateSystemHealth()
205
+ };
206
+ }
207
+ /**
208
+ * Calculate system health score
209
+ */
210
+ calculateSystemHealth() {
211
+ let health = 1.0;
212
+ // Deduct for high error rate
213
+ const errorRate = this.getRecentErrorRate();
214
+ if (errorRate > 0.1)
215
+ health -= 0.3;
216
+ if (errorRate > 0.3)
217
+ health -= 0.3;
218
+ // Deduct for slow responses
219
+ const recent = this.getRecentMetrics(5);
220
+ const avgDuration = recent.length > 0
221
+ ? recent.reduce((sum, m) => sum + m.duration, 0) / recent.length
222
+ : 0;
223
+ if (avgDuration > 10000)
224
+ health -= 0.2;
225
+ if (avgDuration > 30000)
226
+ health -= 0.2;
227
+ // Deduct for high memory usage
228
+ const memUsage = process.memoryUsage().heapUsed / 1024 / 1024;
229
+ if (memUsage > 500)
230
+ health -= 0.1;
231
+ if (memUsage > 1000)
232
+ health -= 0.2;
233
+ return Math.max(health, 0);
234
+ }
235
+ /**
236
+ * Aggregate metrics by tool
237
+ */
238
+ aggregateMetrics() {
239
+ const aggregated = new Map();
240
+ const recent = this.getRecentMetrics(60); // Last hour
241
+ // Group by tool
242
+ const byTool = new Map();
243
+ for (const metric of recent) {
244
+ if (!byTool.has(metric.tool)) {
245
+ byTool.set(metric.tool, []);
246
+ }
247
+ byTool.get(metric.tool).push(metric);
248
+ }
249
+ // Aggregate each tool
250
+ for (const [tool, metrics] of byTool.entries()) {
251
+ const durations = metrics.map(m => m.duration).sort((a, b) => a - b);
252
+ const successful = metrics.filter(m => m.success).length;
253
+ const agg = {
254
+ tool,
255
+ totalRequests: metrics.length,
256
+ successRate: successful / metrics.length,
257
+ avgDuration: durations.reduce((a, b) => a + b, 0) / durations.length,
258
+ p50Duration: this.percentile(durations, 0.5),
259
+ p95Duration: this.percentile(durations, 0.95),
260
+ p99Duration: this.percentile(durations, 0.99),
261
+ totalTokens: metrics.reduce((sum, m) => sum + m.tokensUsed.total, 0),
262
+ totalCost: metrics.reduce((sum, m) => sum + m.cost, 0),
263
+ avgTokensPerRequest: 0,
264
+ avgCostPerRequest: 0,
265
+ throughput: 0
266
+ };
267
+ agg.avgTokensPerRequest = agg.totalTokens / metrics.length;
268
+ agg.avgCostPerRequest = agg.totalCost / metrics.length;
269
+ // Calculate throughput (requests per second)
270
+ if (metrics.length > 1) {
271
+ const timeSpan = metrics[metrics.length - 1].timestamp - metrics[0].timestamp;
272
+ agg.throughput = (metrics.length / timeSpan) * 1000;
273
+ }
274
+ aggregated.set(tool, agg);
275
+ }
276
+ return aggregated;
277
+ }
278
+ /**
279
+ * Calculate percentile
280
+ */
281
+ percentile(sorted, p) {
282
+ if (sorted.length === 0)
283
+ return 0;
284
+ const index = Math.ceil(sorted.length * p) - 1;
285
+ return sorted[Math.max(0, Math.min(index, sorted.length - 1))];
286
+ }
287
+ /**
288
+ * Clean old metrics
289
+ */
290
+ cleanOldMetrics() {
291
+ const cutoff = Date.now() - this.metricsRetention;
292
+ this.metrics = this.metrics.filter(m => m.timestamp > cutoff);
293
+ }
294
+ /**
295
+ * Get dashboard data
296
+ */
297
+ getDashboardData() {
298
+ const aggregated = this.aggregateMetrics();
299
+ const recent = this.getRecentMetrics(5);
300
+ const latestSystem = this.systemMetrics[this.systemMetrics.length - 1] || null;
301
+ // Calculate cost breakdown
302
+ const costBreakdown = [];
303
+ let totalCost = 0;
304
+ for (const [tool, metrics] of aggregated.entries()) {
305
+ totalCost += metrics.totalCost;
306
+ costBreakdown.push({
307
+ tool,
308
+ cost: metrics.totalCost,
309
+ percentage: 0
310
+ });
311
+ }
312
+ // Calculate percentages
313
+ for (const item of costBreakdown) {
314
+ item.percentage = totalCost > 0 ? (item.cost / totalCost) * 100 : 0;
315
+ }
316
+ // Sort by cost
317
+ costBreakdown.sort((a, b) => b.cost - a.cost);
318
+ // Generate alerts
319
+ const alerts = [];
320
+ if (latestSystem) {
321
+ if (latestSystem.errorRate > 0.3) {
322
+ alerts.push(`High error rate: ${(latestSystem.errorRate * 100).toFixed(1)}%`);
323
+ }
324
+ if (latestSystem.systemHealth < 0.5) {
325
+ alerts.push(`Low system health: ${(latestSystem.systemHealth * 100).toFixed(0)}%`);
326
+ }
327
+ if (latestSystem.memoryUsage > 1000) {
328
+ alerts.push(`High memory usage: ${latestSystem.memoryUsage.toFixed(0)}MB`);
329
+ }
330
+ }
331
+ // Check for expensive tools
332
+ for (const [tool, metrics] of aggregated.entries()) {
333
+ if (metrics.avgCostPerRequest > 0.05) {
334
+ alerts.push(`High cost for ${tool}: $${metrics.avgCostPerRequest.toFixed(3)}/request`);
335
+ }
336
+ }
337
+ return {
338
+ currentRequests: this.activeRequests.size,
339
+ recentMetrics: recent,
340
+ aggregatedMetrics: aggregated,
341
+ systemMetrics: latestSystem,
342
+ costBreakdown,
343
+ performanceAlerts: alerts
344
+ };
345
+ }
346
+ /**
347
+ * Get cost optimization recommendations
348
+ */
349
+ getCostOptimizationRecommendations() {
350
+ const recommendations = [];
351
+ const aggregated = this.aggregateMetrics();
352
+ for (const [tool, metrics] of aggregated.entries()) {
353
+ // Check for high token usage
354
+ if (metrics.avgTokensPerRequest > 10000) {
355
+ recommendations.push(`${tool}: High token usage (${metrics.avgTokensPerRequest.toFixed(0)} avg). Consider chunking or summarization.`);
356
+ }
357
+ // Check for low success rate
358
+ if (metrics.successRate < 0.8) {
359
+ recommendations.push(`${tool}: Low success rate (${(metrics.successRate * 100).toFixed(1)}%). Consider fallback strategies.`);
360
+ }
361
+ // Check for slow performance
362
+ if (metrics.avgDuration > 20000) {
363
+ recommendations.push(`${tool}: Slow performance (${(metrics.avgDuration / 1000).toFixed(1)}s avg). Consider timeout or alternative.`);
364
+ }
365
+ }
366
+ // General recommendations
367
+ if (this.getRecentErrorRate() > 0.2) {
368
+ recommendations.push('High overall error rate. Enable circuit breakers and fallback strategies.');
369
+ }
370
+ const totalCost = Array.from(aggregated.values())
371
+ .reduce((sum, m) => sum + m.totalCost, 0);
372
+ if (totalCost > 10) {
373
+ recommendations.push(`High cost in last hour: $${totalCost.toFixed(2)}. Review workflow efficiency.`);
374
+ }
375
+ return recommendations;
376
+ }
377
+ /**
378
+ * Export metrics for analysis
379
+ */
380
+ exportMetrics(format = 'json') {
381
+ if (format === 'json') {
382
+ return JSON.stringify({
383
+ metrics: this.metrics,
384
+ systemMetrics: this.systemMetrics,
385
+ aggregated: Object.fromEntries(this.aggregateMetrics()),
386
+ exported: new Date().toISOString()
387
+ }, null, 2);
388
+ }
389
+ else {
390
+ // CSV format
391
+ const headers = [
392
+ 'timestamp', 'requestId', 'tool', 'duration',
393
+ 'inputTokens', 'outputTokens', 'totalTokens',
394
+ 'cost', 'success', 'error'
395
+ ].join(',');
396
+ const rows = this.metrics.map(m => [
397
+ m.timestamp,
398
+ m.requestId,
399
+ m.tool,
400
+ m.duration,
401
+ m.tokensUsed.input,
402
+ m.tokensUsed.output,
403
+ m.tokensUsed.total,
404
+ m.cost.toFixed(4),
405
+ m.success,
406
+ m.error || ''
407
+ ].join(','));
408
+ return [headers, ...rows].join('\n');
409
+ }
410
+ }
411
+ /**
412
+ * Set metrics retention period
413
+ */
414
+ setRetention(milliseconds) {
415
+ this.metricsRetention = milliseconds;
416
+ this.cleanOldMetrics();
417
+ }
418
+ /**
419
+ * Cleanup
420
+ */
421
+ cleanup() {
422
+ if (this.aggregationInterval) {
423
+ clearInterval(this.aggregationInterval);
424
+ }
425
+ if (this.systemMonitorInterval) {
426
+ clearInterval(this.systemMonitorInterval);
427
+ }
428
+ this.metrics = [];
429
+ this.systemMetrics = [];
430
+ this.activeRequests.clear();
431
+ this.removeAllListeners();
432
+ }
433
+ }
434
+ // Export singleton instance
435
+ export const performanceMonitor = new PerformanceMonitor();
@@ -0,0 +1,121 @@
1
+ export class BatchExecutor {
2
+ constructor(maxConcurrency, defaultTimeout) {
3
+ this.maxConcurrency = 5;
4
+ this.defaultTimeout = 30000;
5
+ if (maxConcurrency)
6
+ this.maxConcurrency = maxConcurrency;
7
+ if (defaultTimeout)
8
+ this.defaultTimeout = defaultTimeout;
9
+ }
10
+ async execute(tasks) {
11
+ const groups = this.groupTasksByDependencies(tasks);
12
+ const results = [];
13
+ for (const group of groups) {
14
+ const groupResults = await this.executeGroup(group);
15
+ results.push(...groupResults);
16
+ }
17
+ return results;
18
+ }
19
+ async executeParallel(tasks, maxConcurrency) {
20
+ const concurrency = maxConcurrency || this.maxConcurrency;
21
+ const results = [];
22
+ const queue = [...tasks].sort((a, b) => (b.priority || 0) - (a.priority || 0));
23
+ while (queue.length > 0) {
24
+ const batch = queue.splice(0, concurrency);
25
+ const batchResults = await Promise.all(batch.map(task => this.executeTask(task)));
26
+ results.push(...batchResults);
27
+ }
28
+ return results;
29
+ }
30
+ async executeGroup(tasks) {
31
+ const promises = tasks.map(task => this.executeTask(task));
32
+ return Promise.all(promises);
33
+ }
34
+ async executeTask(task) {
35
+ const startTime = Date.now();
36
+ const timeout = task.timeout || this.defaultTimeout;
37
+ try {
38
+ const result = await Promise.race([
39
+ task.fn(),
40
+ new Promise((_, reject) => setTimeout(() => reject(new Error('Timeout')), timeout))
41
+ ]);
42
+ return {
43
+ id: task.id,
44
+ result,
45
+ duration: Date.now() - startTime,
46
+ status: 'success'
47
+ };
48
+ }
49
+ catch (error) {
50
+ const isTimeout = error instanceof Error && error.message === 'Timeout';
51
+ return {
52
+ id: task.id,
53
+ error: error,
54
+ duration: Date.now() - startTime,
55
+ status: isTimeout ? 'timeout' : 'error'
56
+ };
57
+ }
58
+ }
59
+ groupTasksByDependencies(tasks) {
60
+ const groups = [];
61
+ const completed = new Set();
62
+ const remaining = [...tasks];
63
+ while (remaining.length > 0) {
64
+ const group = [];
65
+ for (let i = remaining.length - 1; i >= 0; i--) {
66
+ const task = remaining[i];
67
+ const ready = !task.dependencies ||
68
+ task.dependencies.every(dep => completed.has(dep));
69
+ if (ready) {
70
+ group.push(task);
71
+ remaining.splice(i, 1);
72
+ }
73
+ }
74
+ if (group.length === 0 && remaining.length > 0) {
75
+ throw new Error('Circular dependency detected in batch tasks');
76
+ }
77
+ groups.push(group);
78
+ group.forEach(task => completed.add(task.id));
79
+ }
80
+ return groups;
81
+ }
82
+ generateReport(results) {
83
+ const successful = results.filter(r => r.status === 'success').length;
84
+ const failed = results.filter(r => r.status === 'error').length;
85
+ const timeouts = results.filter(r => r.status === 'timeout').length;
86
+ const totalDuration = Math.max(...results.map(r => r.duration));
87
+ return {
88
+ totalTasks: results.length,
89
+ successful,
90
+ failed,
91
+ timeouts,
92
+ totalDuration,
93
+ parallelGroups: Math.ceil(results.length / this.maxConcurrency)
94
+ };
95
+ }
96
+ async executeWithRetry(task, maxRetries = 3, backoff = 1000) {
97
+ let lastError;
98
+ for (let attempt = 0; attempt < maxRetries; attempt++) {
99
+ if (attempt > 0) {
100
+ await new Promise(resolve => setTimeout(resolve, backoff * attempt));
101
+ }
102
+ const result = await this.executeTask(task);
103
+ if (result.status === 'success') {
104
+ return result;
105
+ }
106
+ lastError = result.error;
107
+ }
108
+ return {
109
+ id: task.id,
110
+ error: lastError || new Error('Max retries exceeded'),
111
+ duration: 0,
112
+ status: 'error'
113
+ };
114
+ }
115
+ setMaxConcurrency(max) {
116
+ this.maxConcurrency = max;
117
+ }
118
+ setDefaultTimeout(timeout) {
119
+ this.defaultTimeout = timeout;
120
+ }
121
+ }