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,455 @@
1
+ import { EventEmitter } from 'events';
2
+ /**
3
+ * In-memory message queue implementation
4
+ * Can be replaced with Kafka/RabbitMQ for production
5
+ */
6
+ export class MessageQueue extends EventEmitter {
7
+ constructor(config = {}) {
8
+ super();
9
+ this.queues = new Map();
10
+ this.processing = new Map();
11
+ this.deadLetterQueue = [];
12
+ this.stats = new Map();
13
+ this.handlers = new Map();
14
+ this.config = {
15
+ maxSize: 10000,
16
+ maxRetries: 3,
17
+ retryDelay: 1000,
18
+ batchSize: 10,
19
+ flushInterval: 100,
20
+ deadLetterQueue: true,
21
+ ...config
22
+ };
23
+ this.startFlushTimer();
24
+ }
25
+ /**
26
+ * Send a message to a topic
27
+ */
28
+ async send(topic, payload, options = {}) {
29
+ const messageId = this.generateMessageId();
30
+ const message = {
31
+ id: messageId,
32
+ topic,
33
+ payload,
34
+ timestamp: Date.now(),
35
+ retryCount: 0,
36
+ maxRetries: options.maxRetries || this.config.maxRetries,
37
+ priority: options.priority || 'normal',
38
+ headers: options.headers
39
+ };
40
+ // Check queue size limit
41
+ const queue = this.getQueue(topic);
42
+ if (queue.length >= this.config.maxSize) {
43
+ throw new Error(`Queue ${topic} is full (max: ${this.config.maxSize})`);
44
+ }
45
+ // Add to queue based on priority
46
+ this.addToQueue(topic, message);
47
+ this.emit('message-sent', { topic, messageId });
48
+ // Update stats
49
+ this.updateStats(topic, 'pending', 1);
50
+ return messageId;
51
+ }
52
+ /**
53
+ * Send a batch of messages
54
+ */
55
+ async sendBatch(topic, payloads, options = {}) {
56
+ const messageIds = [];
57
+ for (const payload of payloads) {
58
+ const id = await this.send(topic, payload, options);
59
+ messageIds.push(id);
60
+ }
61
+ return messageIds;
62
+ }
63
+ /**
64
+ * Subscribe to a topic
65
+ */
66
+ subscribe(topic, handler) {
67
+ if (!this.handlers.has(topic)) {
68
+ this.handlers.set(topic, []);
69
+ }
70
+ this.handlers.get(topic).push(handler);
71
+ this.emit('subscription-added', { topic });
72
+ // Process any pending messages
73
+ this.processQueue(topic);
74
+ }
75
+ /**
76
+ * Process messages in a queue
77
+ */
78
+ async processQueue(topic) {
79
+ const queue = this.getQueue(topic);
80
+ const handlers = this.handlers.get(topic) || [];
81
+ if (queue.length === 0 || handlers.length === 0) {
82
+ return;
83
+ }
84
+ // Get batch of messages
85
+ const batch = this.getNextBatch(topic);
86
+ for (const message of batch) {
87
+ // Skip if already processing
88
+ if (this.isProcessing(topic, message.id)) {
89
+ continue;
90
+ }
91
+ this.markProcessing(topic, message.id);
92
+ // Process message with all handlers
93
+ this.processMessage(topic, message, handlers);
94
+ }
95
+ }
96
+ /**
97
+ * Process a single message
98
+ */
99
+ async processMessage(topic, message, handlers) {
100
+ const startTime = Date.now();
101
+ try {
102
+ // Execute all handlers in parallel
103
+ const results = await Promise.allSettled(handlers.map(handler => handler(message)));
104
+ // Check if any handler failed
105
+ const failures = results.filter(r => r.status === 'rejected');
106
+ if (failures.length > 0) {
107
+ throw new Error(`${failures.length} handlers failed`);
108
+ }
109
+ // Success - remove from queue
110
+ this.removeFromQueue(topic, message.id);
111
+ this.markComplete(topic, message.id);
112
+ // Update stats
113
+ const processingTime = Date.now() - startTime;
114
+ this.updateStats(topic, 'completed', 1);
115
+ this.updateProcessingTime(topic, processingTime);
116
+ this.emit('message-processed', { topic, messageId: message.id, processingTime });
117
+ }
118
+ catch (error) {
119
+ // Handle failure
120
+ await this.handleFailure(topic, message, error);
121
+ }
122
+ }
123
+ /**
124
+ * Handle message processing failure
125
+ */
126
+ async handleFailure(topic, message, error) {
127
+ message.retryCount++;
128
+ this.markComplete(topic, message.id); // Remove from processing
129
+ if (message.retryCount < message.maxRetries) {
130
+ // Retry with delay
131
+ setTimeout(() => {
132
+ this.addToQueue(topic, message);
133
+ this.emit('message-retry', {
134
+ topic,
135
+ messageId: message.id,
136
+ retryCount: message.retryCount
137
+ });
138
+ }, this.config.retryDelay * message.retryCount);
139
+ }
140
+ else {
141
+ // Move to dead letter queue
142
+ if (this.config.deadLetterQueue) {
143
+ this.deadLetterQueue.push(message);
144
+ this.updateStats(topic, 'deadLetter', 1);
145
+ this.emit('message-dead-letter', {
146
+ topic,
147
+ messageId: message.id,
148
+ error: error.message
149
+ });
150
+ }
151
+ else {
152
+ this.updateStats(topic, 'failed', 1);
153
+ this.emit('message-failed', {
154
+ topic,
155
+ messageId: message.id,
156
+ error: error.message
157
+ });
158
+ }
159
+ // Remove from queue
160
+ this.removeFromQueue(topic, message.id);
161
+ }
162
+ }
163
+ /**
164
+ * Get next batch of messages to process
165
+ */
166
+ getNextBatch(topic) {
167
+ const queue = this.getQueue(topic);
168
+ // Sort by priority and timestamp
169
+ const sorted = queue.sort((a, b) => {
170
+ const priorityOrder = { critical: 0, high: 1, normal: 2, low: 3 };
171
+ const priorityDiff = priorityOrder[a.priority] - priorityOrder[b.priority];
172
+ if (priorityDiff !== 0)
173
+ return priorityDiff;
174
+ return a.timestamp - b.timestamp;
175
+ });
176
+ return sorted.slice(0, this.config.batchSize);
177
+ }
178
+ /**
179
+ * Add message to queue based on priority
180
+ */
181
+ addToQueue(topic, message) {
182
+ const queue = this.getQueue(topic);
183
+ if (message.priority === 'critical' || message.priority === 'high') {
184
+ // Add to front for high priority
185
+ queue.unshift(message);
186
+ }
187
+ else {
188
+ // Add to back for normal/low priority
189
+ queue.push(message);
190
+ }
191
+ }
192
+ /**
193
+ * Remove message from queue
194
+ */
195
+ removeFromQueue(topic, messageId) {
196
+ const queue = this.getQueue(topic);
197
+ const index = queue.findIndex(m => m.id === messageId);
198
+ if (index >= 0) {
199
+ queue.splice(index, 1);
200
+ }
201
+ }
202
+ /**
203
+ * Get or create queue for topic
204
+ */
205
+ getQueue(topic) {
206
+ if (!this.queues.has(topic)) {
207
+ this.queues.set(topic, []);
208
+ this.processing.set(topic, new Set());
209
+ this.initStats(topic);
210
+ }
211
+ return this.queues.get(topic);
212
+ }
213
+ /**
214
+ * Check if message is being processed
215
+ */
216
+ isProcessing(topic, messageId) {
217
+ return this.processing.get(topic)?.has(messageId) || false;
218
+ }
219
+ /**
220
+ * Mark message as processing
221
+ */
222
+ markProcessing(topic, messageId) {
223
+ if (!this.processing.has(topic)) {
224
+ this.processing.set(topic, new Set());
225
+ }
226
+ this.processing.get(topic).add(messageId);
227
+ this.updateStats(topic, 'processing', 1);
228
+ this.updateStats(topic, 'pending', -1);
229
+ }
230
+ /**
231
+ * Mark message as complete
232
+ */
233
+ markComplete(topic, messageId) {
234
+ this.processing.get(topic)?.delete(messageId);
235
+ this.updateStats(topic, 'processing', -1);
236
+ }
237
+ /**
238
+ * Start flush timer to process queues periodically
239
+ */
240
+ startFlushTimer() {
241
+ this.flushTimer = setInterval(() => {
242
+ for (const topic of this.queues.keys()) {
243
+ this.processQueue(topic);
244
+ }
245
+ }, this.config.flushInterval);
246
+ }
247
+ /**
248
+ * Generate unique message ID
249
+ */
250
+ generateMessageId() {
251
+ return `msg-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
252
+ }
253
+ /**
254
+ * Initialize stats for a topic
255
+ */
256
+ initStats(topic) {
257
+ this.stats.set(topic, {
258
+ pending: 0,
259
+ processing: 0,
260
+ completed: 0,
261
+ failed: 0,
262
+ deadLetter: 0,
263
+ avgProcessingTime: 0,
264
+ throughput: 0
265
+ });
266
+ }
267
+ /**
268
+ * Update stats for a topic
269
+ */
270
+ updateStats(topic, field, delta) {
271
+ const stats = this.stats.get(topic);
272
+ if (stats) {
273
+ stats[field] += delta;
274
+ }
275
+ }
276
+ /**
277
+ * Update processing time stats
278
+ */
279
+ updateProcessingTime(topic, time) {
280
+ const stats = this.stats.get(topic);
281
+ if (stats) {
282
+ // Calculate moving average
283
+ const alpha = 0.1; // Smoothing factor
284
+ stats.avgProcessingTime = alpha * time + (1 - alpha) * stats.avgProcessingTime;
285
+ // Calculate throughput (messages per second)
286
+ stats.throughput = 1000 / stats.avgProcessingTime;
287
+ }
288
+ }
289
+ /**
290
+ * Get stats for a topic
291
+ */
292
+ getStats(topic) {
293
+ if (topic) {
294
+ return this.stats.get(topic) || this.initStats(topic) || this.stats.get(topic);
295
+ }
296
+ return new Map(this.stats);
297
+ }
298
+ /**
299
+ * Get dead letter queue
300
+ */
301
+ getDeadLetterQueue() {
302
+ return [...this.deadLetterQueue];
303
+ }
304
+ /**
305
+ * Retry dead letter messages
306
+ */
307
+ async retryDeadLetters(topic) {
308
+ const messages = topic
309
+ ? this.deadLetterQueue.filter(m => m.topic === topic)
310
+ : [...this.deadLetterQueue];
311
+ let retried = 0;
312
+ for (const message of messages) {
313
+ message.retryCount = 0; // Reset retry count
314
+ this.addToQueue(message.topic, message);
315
+ // Remove from dead letter queue
316
+ const index = this.deadLetterQueue.indexOf(message);
317
+ if (index >= 0) {
318
+ this.deadLetterQueue.splice(index, 1);
319
+ }
320
+ retried++;
321
+ }
322
+ this.emit('dead-letters-retried', { count: retried, topic });
323
+ return retried;
324
+ }
325
+ /**
326
+ * Clear a queue
327
+ */
328
+ clearQueue(topic) {
329
+ this.queues.set(topic, []);
330
+ this.processing.set(topic, new Set());
331
+ this.initStats(topic);
332
+ this.emit('queue-cleared', { topic });
333
+ }
334
+ /**
335
+ * Cleanup and stop processing
336
+ */
337
+ cleanup() {
338
+ if (this.flushTimer) {
339
+ clearInterval(this.flushTimer);
340
+ }
341
+ // Clear all queues
342
+ for (const topic of this.queues.keys()) {
343
+ this.clearQueue(topic);
344
+ }
345
+ this.deadLetterQueue = [];
346
+ this.removeAllListeners();
347
+ }
348
+ }
349
+ /**
350
+ * Message Queue Orchestrator for Claude → Subagent communication
351
+ */
352
+ export class MessageQueueOrchestrator extends EventEmitter {
353
+ constructor(queueConfig) {
354
+ super();
355
+ this.pendingRequests = new Map();
356
+ this.queue = new MessageQueue(queueConfig);
357
+ this.setupResponseHandler();
358
+ }
359
+ /**
360
+ * Delegate task to subagent via message queue
361
+ */
362
+ async delegateToSubagent(request) {
363
+ const timeout = request.timeout || 30000;
364
+ return new Promise((resolve, reject) => {
365
+ // Store pending request
366
+ const timeoutHandle = setTimeout(() => {
367
+ this.pendingRequests.delete(request.id);
368
+ reject(new Error(`Subagent request ${request.id} timed out after ${timeout}ms`));
369
+ }, timeout);
370
+ this.pendingRequests.set(request.id, { resolve, reject, timeout: timeoutHandle });
371
+ // Send to message queue
372
+ this.queue.send('subagent-requests', request, {
373
+ priority: 'normal',
374
+ headers: {
375
+ 'request-id': request.id,
376
+ 'request-type': request.type,
377
+ 'timeout': timeout.toString()
378
+ }
379
+ }).catch(error => {
380
+ this.pendingRequests.delete(request.id);
381
+ clearTimeout(timeoutHandle);
382
+ reject(error);
383
+ });
384
+ });
385
+ }
386
+ /**
387
+ * Spawn ephemeral subagent
388
+ */
389
+ async spawnEphemeralSubagent(type, config) {
390
+ const subagentId = `${type}-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
391
+ const request = {
392
+ id: this.generateRequestId(),
393
+ type: 'spawn-subagent',
394
+ config: {
395
+ subagentId,
396
+ type,
397
+ ...config
398
+ },
399
+ payload: {}
400
+ };
401
+ const response = await this.delegateToSubagent(request);
402
+ if (response.error) {
403
+ throw new Error(`Failed to spawn subagent: ${response.error}`);
404
+ }
405
+ return subagentId;
406
+ }
407
+ /**
408
+ * Setup response handler
409
+ */
410
+ setupResponseHandler() {
411
+ this.queue.subscribe('subagent-responses', async (message) => {
412
+ const response = message.payload;
413
+ const pending = this.pendingRequests.get(response.requestId);
414
+ if (pending) {
415
+ clearTimeout(pending.timeout);
416
+ this.pendingRequests.delete(response.requestId);
417
+ if (response.error) {
418
+ pending.reject(new Error(response.error));
419
+ }
420
+ else {
421
+ pending.resolve(response);
422
+ }
423
+ }
424
+ });
425
+ }
426
+ /**
427
+ * Generate unique request ID
428
+ */
429
+ generateRequestId() {
430
+ return `req-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
431
+ }
432
+ /**
433
+ * Get queue statistics
434
+ */
435
+ getStats() {
436
+ return this.queue.getStats();
437
+ }
438
+ /**
439
+ * Cleanup
440
+ */
441
+ cleanup() {
442
+ // Clear pending requests
443
+ for (const [id, pending] of this.pendingRequests.entries()) {
444
+ clearTimeout(pending.timeout);
445
+ pending.reject(new Error('Orchestrator shutting down'));
446
+ }
447
+ this.pendingRequests.clear();
448
+ // Cleanup queue
449
+ this.queue.cleanup();
450
+ this.removeAllListeners();
451
+ }
452
+ }
453
+ // Export singleton instances
454
+ export const messageQueue = new MessageQueue();
455
+ export const mqOrchestrator = new MessageQueueOrchestrator();
@@ -0,0 +1,189 @@
1
+ export class ModelRouter {
2
+ constructor() {
3
+ this.models = new Map([
4
+ ['claude-code', {
5
+ id: 'claude-code',
6
+ cost: 0,
7
+ quality: 10,
8
+ speed: 8,
9
+ reasoning: 10,
10
+ useFor: ['primary reasoning', 'code', 'analysis']
11
+ }],
12
+ ['gemini-2.5-pro', {
13
+ id: 'gemini-2.5-pro',
14
+ cost: 10,
15
+ quality: 9,
16
+ speed: 7,
17
+ reasoning: 9,
18
+ context: '1M tokens',
19
+ useFor: ['deep reasoning', 'complex analysis', 'when quality matters']
20
+ }],
21
+ ['gemini-2.5-flash', {
22
+ id: 'gemini-2.5-flash',
23
+ cost: 2,
24
+ quality: 7,
25
+ speed: 10,
26
+ reasoning: 7,
27
+ context: '1M tokens',
28
+ useFor: ['scout mode', 'quick analysis', 'high-volume tasks']
29
+ }],
30
+ ['perplexity-sonar-pro', {
31
+ id: 'perplexity-sonar-pro',
32
+ cost: 6,
33
+ quality: 9,
34
+ speed: 7,
35
+ reasoning: 8,
36
+ useFor: ['web search', 'fact-checking', 'citations']
37
+ }],
38
+ ['perplexity-sonar-reasoning', {
39
+ id: 'perplexity-sonar-reasoning',
40
+ cost: 10,
41
+ quality: 10,
42
+ speed: 5,
43
+ reasoning: 10,
44
+ useFor: ['complex reasoning with evidence']
45
+ }],
46
+ ['grok-4', {
47
+ id: 'grok-4',
48
+ cost: 9,
49
+ quality: 9,
50
+ speed: 6,
51
+ reasoning: 9,
52
+ useFor: ['first-principles', 'architecture', 'challenging assumptions']
53
+ }],
54
+ ['grok-4-heavy', {
55
+ id: 'grok-4-heavy',
56
+ cost: 12,
57
+ quality: 10,
58
+ speed: 4,
59
+ reasoning: 10,
60
+ useFor: ['deep reasoning', 'complex problems']
61
+ }],
62
+ ['gpt5', {
63
+ id: 'gpt5',
64
+ cost: 12,
65
+ quality: 10,
66
+ speed: 7,
67
+ reasoning: 10,
68
+ useFor: ['primary reasoning', 'complex analysis', 'critical workflows']
69
+ }],
70
+ ['gpt5_mini', {
71
+ id: 'gpt5_mini',
72
+ cost: 8,
73
+ quality: 9,
74
+ speed: 9,
75
+ reasoning: 9,
76
+ useFor: ['fallback reasoning', 'challenger mode', 'cost-aware reasoning']
77
+ }],
78
+ ['gpt5_reason', {
79
+ id: 'gpt5_reason',
80
+ cost: 12,
81
+ quality: 10,
82
+ speed: 7,
83
+ reasoning: 10,
84
+ useFor: ['deep research', 'complex reasoning']
85
+ }],
86
+ ['qwen3-coder-480b', {
87
+ id: 'qwen3-coder-480b',
88
+ cost: 12,
89
+ quality: 10,
90
+ speed: 4,
91
+ reasoning: 8,
92
+ useFor: ['code generation', 'code analysis', 'refactoring']
93
+ }],
94
+ ['qwq-32b', {
95
+ id: 'qwq-32b',
96
+ cost: 10,
97
+ quality: 9,
98
+ speed: 5,
99
+ reasoning: 10,
100
+ useFor: ['mathematical reasoning', 'step-by-step logic']
101
+ }],
102
+ ['qwen3-30b', {
103
+ id: 'qwen3-30b',
104
+ cost: 6,
105
+ quality: 8,
106
+ speed: 7,
107
+ reasoning: 8,
108
+ useFor: ['general tasks', 'cheaper alternative']
109
+ }],
110
+ ['think', {
111
+ id: 'think',
112
+ cost: 0,
113
+ quality: 6,
114
+ speed: 10,
115
+ reasoning: 6,
116
+ useFor: ['synthesis', 'internal reasoning', 'combining insights']
117
+ }]
118
+ ]);
119
+ }
120
+ selectModel(task, constraints = {}) {
121
+ if (task.needsCurrentInfo || task.type === 'facts' || task.type === 'research') {
122
+ return 'perplexity-sonar-pro';
123
+ }
124
+ if (task.complexity > 0.8 && !constraints.budget) {
125
+ return constraints.budget !== undefined && constraints.budget < 10 ? 'gpt5_mini' : 'gpt5';
126
+ }
127
+ if (task.complexity < 0.2 && task.type === 'format') {
128
+ return 'gemini-2.5-flash';
129
+ }
130
+ if (task.type === 'synthesis') {
131
+ return 'think';
132
+ }
133
+ if (constraints.local) {
134
+ return 'lmstudio-local';
135
+ }
136
+ const taskTypeMap = {
137
+ 'code': task.complexity > 0.7 ? 'qwen3-coder-480b' : 'gemini-2.5-flash',
138
+ 'research': 'perplexity-sonar-pro',
139
+ 'reasoning': task.complexity > 0.5 ? 'gpt5' : 'gpt5_mini',
140
+ 'scout': 'multi-model',
141
+ 'verifier': task.complexity > 0.5 ? 'gpt5' : 'gpt5_mini',
142
+ 'challenger': 'gpt5_mini',
143
+ 'auditor': 'perplexity-sonar-pro',
144
+ 'architect': 'grok-4',
145
+ 'commit_guardian': 'gemini-2.5-flash'
146
+ };
147
+ return taskTypeMap[task.type] || this.selectByConstraints(task, constraints);
148
+ }
149
+ selectByConstraints(task, constraints) {
150
+ let candidates = Array.from(this.models.values());
151
+ if (constraints.budget !== undefined) {
152
+ candidates = candidates.filter(m => m.cost <= constraints.budget);
153
+ }
154
+ if (constraints.speed) {
155
+ candidates.sort((a, b) => b.speed - a.speed);
156
+ }
157
+ else if (constraints.quality) {
158
+ candidates.sort((a, b) => b.quality - a.quality);
159
+ }
160
+ else {
161
+ candidates.sort((a, b) => {
162
+ const scoreA = (a.quality * 0.4 + a.speed * 0.3 + a.reasoning * 0.3) / a.cost;
163
+ const scoreB = (b.quality * 0.4 + b.speed * 0.3 + b.reasoning * 0.3) / b.cost;
164
+ return scoreB - scoreA;
165
+ });
166
+ }
167
+ return candidates[0]?.id || 'gpt5_mini';
168
+ }
169
+ getModelInfo(modelId) {
170
+ return this.models.get(modelId);
171
+ }
172
+ estimateCost(modelId, tokens) {
173
+ const model = this.models.get(modelId);
174
+ if (!model)
175
+ return 0;
176
+ const costPerMillion = model.cost;
177
+ return (tokens / 1000000) * costPerMillion;
178
+ }
179
+ selectModelsForVerification(variant) {
180
+ const variants = {
181
+ 'quick_verify': ['gpt5_mini', 'gemini-2.5-flash', 'qwen3-30b'],
182
+ 'deep_verify': ['gpt5', 'qwq-32b', 'gpt5_reason', 'gemini-2.5-pro', 'qwen3-coder-480b'],
183
+ 'fact_check': ['perplexity-sonar-pro', 'gpt5', 'gemini-2.5-pro'],
184
+ 'code_verify': ['qwen3-coder-480b', 'gpt5', 'gemini-2.5-pro'],
185
+ 'security_verify': ['gpt5', 'qwen3-coder-480b', 'grok-4']
186
+ };
187
+ return variants[variant] || variants['quick_verify'];
188
+ }
189
+ }