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,97 @@
1
+ /**
2
+ * Tool type system using TypeScript's infer and conditional types
3
+ * NO 'any' - uses 'unknown' where type is truly unknown
4
+ */
5
+ // ============================================================================
6
+ // TOOL REGISTRY - Single source of truth for all tools
7
+ // ============================================================================
8
+ /**
9
+ * Known tool names - this is the ONLY place we list tools
10
+ * Validators check against this list
11
+ */
12
+ export const KNOWN_TOOLS = [
13
+ // Core
14
+ 'think',
15
+ 'focus',
16
+ // Perplexity
17
+ 'perplexity_ask',
18
+ 'perplexity_reason',
19
+ 'perplexity_research',
20
+ 'perplexity_code_search',
21
+ // Grok
22
+ 'grok_reason',
23
+ 'grok_code',
24
+ 'grok_debug',
25
+ 'grok_brainstorm',
26
+ 'grok_search',
27
+ 'grok_heavy',
28
+ // OpenAI
29
+ 'openai_brainstorm',
30
+ 'openai_analyze',
31
+ 'openai_reason',
32
+ 'openai_compare',
33
+ 'gpt5',
34
+ 'gpt5_mini',
35
+ 'gpt5_nano',
36
+ // Gemini
37
+ 'gemini_query',
38
+ 'gemini_brainstorm',
39
+ 'gemini_analyze_code',
40
+ 'gemini_analyze_text',
41
+ // Qwen
42
+ 'qwen_coder',
43
+ 'qwq_reason',
44
+ // Advanced modes
45
+ 'verifier',
46
+ 'challenger',
47
+ 'scout',
48
+ 'auditor',
49
+ 'architect',
50
+ 'commit_guardian',
51
+ // Meta tools
52
+ 'code_reviewer',
53
+ 'test_architect',
54
+ 'documentation_writer',
55
+ // Workflow
56
+ 'workflow',
57
+ 'pingpong',
58
+ ];
59
+ /**
60
+ * Type guard to check if string is a valid tool name
61
+ */
62
+ export function isValidToolName(name) {
63
+ return KNOWN_TOOLS.includes(name);
64
+ }
65
+ /**
66
+ * Type guard to narrow Step to TypedStep<T>
67
+ */
68
+ export function isTypedStep(step, toolName) {
69
+ return step.tool === toolName;
70
+ }
71
+ // ============================================================================
72
+ // HELPER FUNCTIONS
73
+ // ============================================================================
74
+ /**
75
+ * Get all step names from workflow (for interpolation validation)
76
+ */
77
+ export function getStepNames(workflow) {
78
+ return new Set(workflow.steps.map(s => s.name));
79
+ }
80
+ /**
81
+ * Check if a reference is a step name or variable
82
+ */
83
+ export function isStepReference(reference, stepNames) {
84
+ // Remove .output suffix if present
85
+ const baseName = reference.includes('.')
86
+ ? reference.split('.')[0]
87
+ : reference;
88
+ return stepNames.has(baseName);
89
+ }
90
+ /**
91
+ * Extract all interpolation references from a string
92
+ */
93
+ export function extractInterpolations(text) {
94
+ const regex = /\$\{([^}]+)\}/g;
95
+ const matches = text.matchAll(regex);
96
+ return Array.from(matches, m => m[1]);
97
+ }
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Workflow validator type definitions
3
+ *
4
+ * NOTE: This file now re-exports from tool-types.ts which uses proper
5
+ * TypeScript inference and conditional types without 'any'
6
+ */
7
+ // Re-export all types from tool-types for backward compatibility
8
+ export * from './tool-types.js';
@@ -0,0 +1,134 @@
1
+ /**
2
+ * Main workflow validator - orchestrates all validation checks
3
+ */
4
+ import { SyntaxValidator } from './syntax-validator.js';
5
+ import { InterpolationValidator } from './interpolation-validator.js';
6
+ import { ToolRegistryValidator } from './tool-registry-validator.js';
7
+ import { DependencyGraphValidator } from './dependency-graph-validator.js';
8
+ import { OutputUsageValidator } from './output-usage-validator.js';
9
+ import { getEnabledTools } from '../utils/tool-config.js';
10
+ export class WorkflowValidator {
11
+ constructor() {
12
+ this.syntaxValidator = new SyntaxValidator();
13
+ this.interpolationValidator = new InterpolationValidator();
14
+ this.toolValidator = new ToolRegistryValidator();
15
+ this.dependencyValidator = new DependencyGraphValidator();
16
+ this.outputUsageValidator = new OutputUsageValidator();
17
+ }
18
+ /**
19
+ * Validate a workflow from YAML/JSON content
20
+ */
21
+ async validate(workflowContent, isJson = false, enabledToolsOverride) {
22
+ const allErrors = [];
23
+ // Step 1: Syntax validation
24
+ const syntaxResult = this.syntaxValidator.validate(workflowContent, isJson);
25
+ allErrors.push(...syntaxResult.errors);
26
+ // If syntax validation failed, can't proceed
27
+ if (!syntaxResult.valid || !syntaxResult.workflow) {
28
+ return {
29
+ valid: false,
30
+ errors: allErrors.filter(e => e.severity === 'error'),
31
+ warnings: allErrors.filter(e => e.severity === 'warning')
32
+ };
33
+ }
34
+ // Step 2: Build validation context
35
+ // If override provided, it contains ALL known tools
36
+ // Otherwise, get from config (which may be empty if config not loaded)
37
+ const allKnownTools = enabledToolsOverride || new Set(getEnabledTools());
38
+ const enabledTools = new Set(getEnabledTools());
39
+ const context = {
40
+ workflow: syntaxResult.workflow,
41
+ allKnownTools,
42
+ enabledTools: enabledTools.size > 0 ? enabledTools : allKnownTools, // Fallback to all if none enabled
43
+ sourceMap: new Map() // TODO: Implement source mapping for line numbers
44
+ };
45
+ // Step 3: Run all validators in parallel
46
+ const [interpolationErrors, toolErrors, dependencyErrors, outputUsageErrors] = await Promise.all([
47
+ Promise.resolve(this.interpolationValidator.validate(context)),
48
+ Promise.resolve(this.toolValidator.validate(context)),
49
+ Promise.resolve(this.dependencyValidator.validate(context)),
50
+ Promise.resolve(this.outputUsageValidator.validate(context))
51
+ ]);
52
+ allErrors.push(...interpolationErrors);
53
+ allErrors.push(...toolErrors);
54
+ allErrors.push(...dependencyErrors);
55
+ allErrors.push(...outputUsageErrors);
56
+ // Separate errors and warnings
57
+ const errors = allErrors.filter(e => e.severity === 'error');
58
+ const warnings = allErrors.filter(e => e.severity === 'warning');
59
+ return {
60
+ valid: errors.length === 0,
61
+ errors,
62
+ warnings
63
+ };
64
+ }
65
+ /**
66
+ * Validate a workflow from a file path
67
+ */
68
+ async validateFile(filePath, enabledToolsOverride) {
69
+ const fs = await import('fs');
70
+ const path = await import('path');
71
+ try {
72
+ const content = fs.readFileSync(filePath, 'utf-8');
73
+ const isJson = path.extname(filePath).toLowerCase() === '.json';
74
+ return this.validate(content, isJson, enabledToolsOverride);
75
+ }
76
+ catch (error) {
77
+ return {
78
+ valid: false,
79
+ errors: [{
80
+ type: 'syntax',
81
+ severity: 'error',
82
+ message: `Failed to read file: ${error.message}`,
83
+ path: '$'
84
+ }],
85
+ warnings: []
86
+ };
87
+ }
88
+ }
89
+ /**
90
+ * Format validation results as human-readable text
91
+ */
92
+ formatResults(result) {
93
+ const lines = [];
94
+ if (result.valid) {
95
+ lines.push('✅ Workflow validation passed!');
96
+ if (result.warnings.length > 0) {
97
+ lines.push(`\n⚠️ ${result.warnings.length} warning(s):\n`);
98
+ result.warnings.forEach((warning, i) => {
99
+ lines.push(this.formatError(warning, i + 1));
100
+ });
101
+ }
102
+ }
103
+ else {
104
+ lines.push(`❌ Workflow validation failed with ${result.errors.length} error(s)!\n`);
105
+ result.errors.forEach((error, i) => {
106
+ lines.push(this.formatError(error, i + 1));
107
+ });
108
+ if (result.warnings.length > 0) {
109
+ lines.push(`\n⚠️ ${result.warnings.length} warning(s):\n`);
110
+ result.warnings.forEach((warning, i) => {
111
+ lines.push(this.formatError(warning, i + 1));
112
+ });
113
+ }
114
+ }
115
+ return lines.join('\n');
116
+ }
117
+ /**
118
+ * Format a single error/warning
119
+ */
120
+ formatError(error, index) {
121
+ const icon = error.severity === 'error' ? '❌' : '⚠️';
122
+ const location = error.line ? ` (line ${error.line}${error.column ? `:${error.column}` : ''})` : '';
123
+ const suggestion = error.suggestion ? `\n 💡 ${error.suggestion}` : '';
124
+ return `${icon} ${index}. [${error.type.toUpperCase()}]${location}\n ${error.message}\n Path: ${error.path}${suggestion}\n`;
125
+ }
126
+ /**
127
+ * Format validation results as JSON
128
+ */
129
+ formatResultsJSON(result) {
130
+ return JSON.stringify(result, null, 2);
131
+ }
132
+ }
133
+ // Export singleton instance
134
+ export const workflowValidator = new WorkflowValidator();
@@ -0,0 +1,42 @@
1
+ import { ToolStatus } from './types.js';
2
+ import { PromptEngineerLite } from './prompt-engineer-lite.js';
3
+ export class WorkflowVisualizerLite {
4
+ constructor() {
5
+ this.pe = new PromptEngineerLite();
6
+ this.faces = {
7
+ idle: [' ● ● ', ' ◡ '],
8
+ work: [' ◉ ◉ ', ' ~ '],
9
+ done: [' ★ ★ ', ' \\___//'],
10
+ err: [' x x ', ' ⌒ ']
11
+ };
12
+ }
13
+ getCompactDisplay(workflow, states) {
14
+ const tools = workflow.steps.map(s => s.tool.substring(0, 3));
15
+ const statuses = workflow.steps.map(s => {
16
+ const st = states.get(s.tool) || ToolStatus.IDLE;
17
+ return st === ToolStatus.COMPLETE ? '✓' :
18
+ st === ToolStatus.PROCESSING ? '◉' :
19
+ st === ToolStatus.ERROR ? '!' : '○';
20
+ });
21
+ const progress = Math.round((statuses.filter(s => s === '✓').length / tools.length) * 100);
22
+ const current = workflow.steps.find(s => states.get(s.tool) === ToolStatus.PROCESSING);
23
+ return `${workflow.name} [${statuses.join('→')}] ${progress}%${current ? ` | ${this.pe.getTechniqueDescription(current.promptTechnique)}` : ''}`;
24
+ }
25
+ async renderWorkflow(workflow, states) {
26
+ if (states.size === 0) {
27
+ workflow.steps.forEach(s => states.set(s.tool, ToolStatus.IDLE));
28
+ }
29
+ const display = this.getCompactDisplay(workflow, states);
30
+ console.error(`\n${display}\n`);
31
+ return display;
32
+ }
33
+ async updateProgress(tool, status) {
34
+ const emoji = { idle: '⏸️', processing: '⚙️', complete: '✅', error: '❌' };
35
+ console.error(`${emoji[status]} ${tool}: ${status}`);
36
+ }
37
+ async showCompletion(workflow, results) {
38
+ const dur = ((results[results.length - 1]?.duration || 0) / 1000).toFixed(1);
39
+ const face = this.faces.done;
40
+ console.error(`\n✨ ${workflow.name} Complete in ${dur}s\n @@@@@@@\n @ ${face[0]} @\n @ ${face[1]} @\n @@@@@@@`);
41
+ }
42
+ }
@@ -0,0 +1,179 @@
1
+ import { ToolStatus } from './types.js';
2
+ import { getStatusIndicator } from './workflows.js';
3
+ import { PromptEngineer } from './prompt-engineer.js';
4
+ export class WorkflowVisualizer {
5
+ constructor() {
6
+ this.currentDisplay = '';
7
+ this.animationFrames = new Map();
8
+ this.promptEngineer = new PromptEngineer();
9
+ this.initializeAnimations();
10
+ }
11
+ initializeAnimations() {
12
+ // Processing animations for each tool
13
+ this.animationFrames.set('processing', [
14
+ '.', '..', '...', '..', '.'
15
+ ]);
16
+ this.animationFrames.set('thinking', [
17
+ '~', '≈', '~', '∞', '~'
18
+ ]);
19
+ }
20
+ async renderWorkflow(workflow, toolStates) {
21
+ // Initialize states if empty
22
+ if (toolStates.size === 0) {
23
+ workflow.steps.forEach(step => {
24
+ toolStates.set(step.tool, ToolStatus.IDLE);
25
+ });
26
+ }
27
+ // Build the display from the template
28
+ let display = workflow.visualTemplate;
29
+ // Replace placeholders with actual states
30
+ workflow.steps.forEach(step => {
31
+ const status = toolStates.get(step.tool) || ToolStatus.IDLE;
32
+ const indicator = getStatusIndicator(status);
33
+ // Replace status indicators in template
34
+ switch (step.tool) {
35
+ case 'gemini_brainstorm':
36
+ display = display.replace('{g}', indicator);
37
+ break;
38
+ case 'openai_brainstorm':
39
+ case 'openai_reason':
40
+ display = display.replace('{o}', indicator);
41
+ break;
42
+ case 'think':
43
+ display = display.replace('{t}', indicator);
44
+ break;
45
+ case 'perplexity_research':
46
+ display = display.replace('{p}', indicator);
47
+ break;
48
+ case 'reason':
49
+ display = display.replace('{r}', indicator);
50
+ break;
51
+ }
52
+ });
53
+ // Calculate overall progress
54
+ const completed = Array.from(toolStates.values()).filter(s => s === ToolStatus.COMPLETE).length;
55
+ const total = workflow.steps.length;
56
+ const progress = Math.round((completed / total) * 100);
57
+ // Create progress bar
58
+ const progressBar = this.createProgressBar(progress);
59
+ display = display.replace('{progress}', progressBar);
60
+ // Add current technique and activity
61
+ const currentTool = this.getCurrentTool(workflow, toolStates);
62
+ if (currentTool) {
63
+ const technique = this.promptEngineer.getTechniqueDescription(currentTool.promptTechnique);
64
+ display = display.replace('{technique}', technique);
65
+ display = display.replace('{current}', `Processing with ${currentTool.tool}...`);
66
+ }
67
+ else {
68
+ display = display.replace('{technique}', 'Initializing workflow...');
69
+ display = display.replace('{current}', 'Starting orchestration...');
70
+ }
71
+ this.currentDisplay = display;
72
+ console.error('\n' + display + '\n');
73
+ return display;
74
+ }
75
+ async updateProgress(toolName, status) {
76
+ // This would normally update just the relevant part of the display
77
+ // For now, we'll log the update
78
+ const statusEmoji = {
79
+ [ToolStatus.IDLE]: '⏸️',
80
+ [ToolStatus.PROCESSING]: '⚙️',
81
+ [ToolStatus.COMPLETE]: '✅',
82
+ [ToolStatus.ERROR]: '❌'
83
+ };
84
+ console.error(`\n${statusEmoji[status]} ${toolName}: ${status}\n`);
85
+ // If processing, show animation
86
+ if (status === ToolStatus.PROCESSING) {
87
+ await this.animateProcessing(toolName);
88
+ }
89
+ }
90
+ async animateProcessing(toolName) {
91
+ // Show a simple animation for processing
92
+ const frames = this.animationFrames.get('processing') || ['.'];
93
+ console.error(`🔄 ${toolName} is thinking${frames[0]}`);
94
+ }
95
+ async showCompletion(workflow, results) {
96
+ const duration = results[results.length - 1]?.duration || 0;
97
+ const toolsUsed = results.map(r => r.tool).join(' → ');
98
+ const completion = `
99
+ ╔═══════════════════════════════════════════════════╗
100
+ ║ 🎉 Workflow Complete! 🎉 ║
101
+ ╠═══════════════════════════════════════════════════╣
102
+ ║ Workflow: ${workflow.name.padEnd(39)}║
103
+ ║ Duration: ${(duration / 1000).toFixed(2)}s${' '.repeat(40 - (duration / 1000).toFixed(2).length - 1)}║
104
+ ║ Tools: ${toolsUsed.substring(0, 42).padEnd(42)}║
105
+ ╚═══════════════════════════════════════════════════╝
106
+
107
+ @@@@@@@@@
108
+ @ ● ● @
109
+ @ ◡ @ Mission accomplished!
110
+ @@@@@@@@@
111
+ `;
112
+ console.error(completion);
113
+ }
114
+ createProgressBar(percentage) {
115
+ const width = 20;
116
+ const filled = Math.round((percentage / 100) * width);
117
+ const empty = width - filled;
118
+ return `[${'='.repeat(filled)}${' '.repeat(empty)}] ${percentage}%`;
119
+ }
120
+ getCurrentTool(workflow, toolStates) {
121
+ // Find the currently processing tool
122
+ for (const step of workflow.steps) {
123
+ const status = toolStates.get(step.tool);
124
+ if (status === ToolStatus.PROCESSING) {
125
+ return step;
126
+ }
127
+ }
128
+ // If none processing, find the first incomplete
129
+ for (const step of workflow.steps) {
130
+ const status = toolStates.get(step.tool);
131
+ if (status !== ToolStatus.COMPLETE && status !== ToolStatus.ERROR) {
132
+ return step;
133
+ }
134
+ }
135
+ return null;
136
+ }
137
+ // Special animations for different phases
138
+ async showCreativeExplosion() {
139
+ const explosion = `
140
+ ✨ ★ ✨
141
+ ★ 💡 ★
142
+ ✨ 🎨 ✨
143
+ ★ ★
144
+
145
+ Creative breakthrough!
146
+ `;
147
+ console.error(explosion);
148
+ }
149
+ async showResearchDiscovery() {
150
+ const discovery = `
151
+ 📚 → 🔍 → 💎
152
+
153
+ Found valuable insights!
154
+ `;
155
+ console.error(discovery);
156
+ }
157
+ async showProblemSolved() {
158
+ const solved = `
159
+ 🧩 + 🧩 + 🧩 = ✅
160
+
161
+ Problem decomposed and solved!
162
+ `;
163
+ console.error(solved);
164
+ }
165
+ async showSynthesisComplete() {
166
+ const synthesis = `
167
+ 🎯 All perspectives integrated!
168
+
169
+ ╱│╲
170
+ ─●─ Unified insight achieved
171
+ ╲│╱
172
+ `;
173
+ console.error(synthesis);
174
+ }
175
+ // Get current display for external use
176
+ getCurrentDisplay() {
177
+ return this.currentDisplay;
178
+ }
179
+ }
@@ -0,0 +1,199 @@
1
+ import { EventEmitter } from 'events';
2
+ export var CircuitState;
3
+ (function (CircuitState) {
4
+ CircuitState["CLOSED"] = "CLOSED";
5
+ CircuitState["OPEN"] = "OPEN";
6
+ CircuitState["HALF_OPEN"] = "HALF_OPEN"; // Testing if service recovered
7
+ })(CircuitState || (CircuitState = {}));
8
+ export class CircuitBreaker extends EventEmitter {
9
+ constructor(stepId, options) {
10
+ super();
11
+ this.stepId = stepId;
12
+ this.options = options;
13
+ this.state = CircuitState.CLOSED;
14
+ this.failures = 0;
15
+ this.successes = 0;
16
+ this.lastFailureTime = 0;
17
+ this.lastSuccessTime = 0;
18
+ this.totalRequests = 0;
19
+ this.totalFailures = 0;
20
+ this.startTime = Date.now();
21
+ this.nextAttempt = 0;
22
+ this.setMaxListeners(20); // Allow multiple listeners
23
+ }
24
+ async execute(operation) {
25
+ this.totalRequests++;
26
+ if (this.state === CircuitState.OPEN) {
27
+ if (this.shouldAttemptReset()) {
28
+ this.state = CircuitState.HALF_OPEN;
29
+ this.successes = 0;
30
+ this.emit('half-open', { stepId: this.stepId });
31
+ }
32
+ else {
33
+ this.emit('fallback', { stepId: this.stepId, reason: 'circuit-open' });
34
+ return this.executeFallback();
35
+ }
36
+ }
37
+ try {
38
+ const result = await operation();
39
+ this.onSuccess();
40
+ return result;
41
+ }
42
+ catch (error) {
43
+ this.onFailure(error);
44
+ throw error;
45
+ }
46
+ }
47
+ onSuccess() {
48
+ this.failures = 0;
49
+ this.successes++;
50
+ this.lastSuccessTime = Date.now();
51
+ if (this.state === CircuitState.HALF_OPEN) {
52
+ if (this.successes >= this.options.successThreshold) {
53
+ this.state = CircuitState.CLOSED;
54
+ this.emit('closed', { stepId: this.stepId });
55
+ }
56
+ }
57
+ this.emit('success', { stepId: this.stepId, state: this.state });
58
+ }
59
+ onFailure(error) {
60
+ this.failures++;
61
+ this.totalFailures++;
62
+ this.lastFailureTime = Date.now();
63
+ if (this.state === CircuitState.HALF_OPEN) {
64
+ this.state = CircuitState.OPEN;
65
+ this.nextAttempt = Date.now() + this.options.recoveryTimeout;
66
+ this.emit('opened', { stepId: this.stepId, reason: 'half-open-failure' });
67
+ }
68
+ else if (this.state === CircuitState.CLOSED) {
69
+ if (this.failures >= this.options.failureThreshold) {
70
+ this.state = CircuitState.OPEN;
71
+ this.nextAttempt = Date.now() + this.options.recoveryTimeout;
72
+ this.emit('opened', { stepId: this.stepId, reason: 'failure-threshold' });
73
+ }
74
+ }
75
+ this.emit('failure', { stepId: this.stepId, error: error.message, state: this.state });
76
+ }
77
+ shouldAttemptReset() {
78
+ return Date.now() >= this.nextAttempt;
79
+ }
80
+ async executeFallback() {
81
+ if (this.options.fallback) {
82
+ try {
83
+ const result = await this.options.fallback();
84
+ this.emit('fallback-success', { stepId: this.stepId });
85
+ return result;
86
+ }
87
+ catch (error) {
88
+ this.emit('fallback-failure', { stepId: this.stepId, error: error.message });
89
+ throw new Error(`Circuit breaker open for ${this.stepId} and fallback failed: ${error.message}`);
90
+ }
91
+ }
92
+ throw new Error(`Circuit breaker open for ${this.stepId} and no fallback configured`);
93
+ }
94
+ getStats() {
95
+ return {
96
+ state: this.state,
97
+ failures: this.failures,
98
+ successes: this.successes,
99
+ lastFailure: this.lastFailureTime,
100
+ lastSuccess: this.lastSuccessTime,
101
+ totalRequests: this.totalRequests,
102
+ totalFailures: this.totalFailures,
103
+ uptime: Date.now() - this.startTime
104
+ };
105
+ }
106
+ // Manual control methods
107
+ forceOpen() {
108
+ this.state = CircuitState.OPEN;
109
+ this.nextAttempt = Date.now() + this.options.recoveryTimeout;
110
+ this.emit('force-opened', { stepId: this.stepId });
111
+ }
112
+ forceClose() {
113
+ this.state = CircuitState.CLOSED;
114
+ this.failures = 0;
115
+ this.successes = 0;
116
+ this.emit('force-closed', { stepId: this.stepId });
117
+ }
118
+ forceHalfOpen() {
119
+ this.state = CircuitState.HALF_OPEN;
120
+ this.successes = 0;
121
+ this.emit('force-half-open', { stepId: this.stepId });
122
+ }
123
+ }
124
+ export class CircuitBreakerManager extends EventEmitter {
125
+ constructor() {
126
+ super(...arguments);
127
+ this.breakers = new Map();
128
+ this.defaultOptions = {
129
+ failureThreshold: 5,
130
+ recoveryTimeout: 30000, // 30 seconds
131
+ successThreshold: 2,
132
+ monitoringWindow: 60000, // 1 minute
133
+ };
134
+ }
135
+ getOrCreateCircuitBreaker(stepId, options) {
136
+ if (!this.breakers.has(stepId)) {
137
+ const finalOptions = { ...this.defaultOptions, ...options };
138
+ const breaker = new CircuitBreaker(stepId, finalOptions);
139
+ // Proxy all events to the manager
140
+ breaker.on('opened', (data) => this.emit('breaker-opened', data));
141
+ breaker.on('closed', (data) => this.emit('breaker-closed', data));
142
+ breaker.on('half-open', (data) => this.emit('breaker-half-open', data));
143
+ breaker.on('failure', (data) => this.emit('breaker-failure', data));
144
+ breaker.on('success', (data) => this.emit('breaker-success', data));
145
+ breaker.on('fallback', (data) => this.emit('breaker-fallback', data));
146
+ this.breakers.set(stepId, breaker);
147
+ }
148
+ return this.breakers.get(stepId);
149
+ }
150
+ getAllStats() {
151
+ const stats = {};
152
+ for (const [stepId, breaker] of this.breakers.entries()) {
153
+ stats[stepId] = breaker.getStats();
154
+ }
155
+ return stats;
156
+ }
157
+ getHealthReport() {
158
+ const stats = this.getAllStats();
159
+ const total = Object.keys(stats).length;
160
+ let open = 0;
161
+ let halfOpen = 0;
162
+ let closed = 0;
163
+ for (const stat of Object.values(stats)) {
164
+ switch (stat.state) {
165
+ case CircuitState.OPEN:
166
+ open++;
167
+ break;
168
+ case CircuitState.HALF_OPEN:
169
+ halfOpen++;
170
+ break;
171
+ case CircuitState.CLOSED:
172
+ closed++;
173
+ break;
174
+ }
175
+ }
176
+ const healthScore = total === 0 ? 1.0 : closed / total;
177
+ return {
178
+ totalBreakers: total,
179
+ openBreakers: open,
180
+ halfOpenBreakers: halfOpen,
181
+ closedBreakers: closed,
182
+ healthScore
183
+ };
184
+ }
185
+ // Cleanup unused breakers
186
+ cleanup() {
187
+ const now = Date.now();
188
+ const maxIdle = 300000; // 5 minutes
189
+ for (const [stepId, breaker] of this.breakers.entries()) {
190
+ const stats = breaker.getStats();
191
+ const lastActivity = Math.max(stats.lastSuccess, stats.lastFailure);
192
+ if (lastActivity > 0 && (now - lastActivity) > maxIdle) {
193
+ breaker.removeAllListeners();
194
+ this.breakers.delete(stepId);
195
+ this.emit('breaker-cleanup', { stepId });
196
+ }
197
+ }
198
+ }
199
+ }