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,451 @@
1
+ /**
2
+ * Custom Workflow System - User-configurable workflows with YAML/JSON support
3
+ * Part of TachiBot's extensibility features
4
+ *
5
+ * This file now delegates to engine modules for better maintainability.
6
+ */
7
+ import * as fs from "fs";
8
+ import * as path from "path";
9
+ import * as yaml from "yaml";
10
+ import { costMonitor } from "../optimization/cost-monitor.js";
11
+ // Import shared types (breaks circular dependency)
12
+ import { WorkflowSchema, WorkflowStepSchema } from "./workflow-types.js";
13
+ export { WorkflowSchema, WorkflowStepSchema };
14
+ // Import engine modules
15
+ import { VariableInterpolator } from "./engine/VariableInterpolator.js";
16
+ import { StepParameterResolver } from "./engine/StepParameterResolver.js";
17
+ import { WorkflowHelpers } from "./engine/WorkflowHelpers.js";
18
+ import { WorkflowDiscovery } from "./engine/WorkflowDiscovery.js";
19
+ import { WorkflowFileManager } from "./engine/WorkflowFileManager.js";
20
+ import { WorkflowOutputFormatter } from "./engine/WorkflowOutputFormatter.js";
21
+ import { AutoSynthesizer } from "./engine/AutoSynthesizer.js";
22
+ import { executeWorkflowImpl } from "./engine/WorkflowExecutionEngine.js";
23
+ import { WorkflowEventBus } from "./engine/events/WorkflowEventBus.js";
24
+ import { PromptEnhancementHandler } from "./engine/handlers/PromptEnhancementHandler.js";
25
+ import { ErrorRecoveryHandler } from "./engine/handlers/ErrorRecoveryHandler.js";
26
+ import { StepExecutionHandler } from "./engine/handlers/StepExecutionHandler.js";
27
+ import { ToolInvocationHandler } from "./engine/handlers/ToolInvocationHandler.js";
28
+ import { WorkflowStateMachine } from "./engine/state/WorkflowStateMachine.js";
29
+ export class CustomWorkflowEngine {
30
+ constructor() {
31
+ this.workflows = new Map();
32
+ this.executionHistory = [];
33
+ // Initialize engine modules
34
+ this.variableInterpolator = new VariableInterpolator();
35
+ this.parameterResolver = new StepParameterResolver();
36
+ this.fileManager = new WorkflowFileManager();
37
+ this.outputFormatter = new WorkflowOutputFormatter();
38
+ this.autoSynthesizer = new AutoSynthesizer();
39
+ this.eventBus = new WorkflowEventBus();
40
+ this.stateMachine = new WorkflowStateMachine();
41
+ // Initialize event handlers (Phase 3: Full event-driven architecture)
42
+ this.promptEnhancer = new PromptEnhancementHandler(this.eventBus);
43
+ this.errorRecovery = new ErrorRecoveryHandler(this.eventBus);
44
+ this.stepExecutor = new StepExecutionHandler(this.eventBus, this.stateMachine);
45
+ this.toolInvoker = new ToolInvocationHandler(this.eventBus);
46
+ console.error('[CustomWorkflowEngine] Phase 3 handlers initialized:');
47
+ console.error(' ✓ PromptEnhancementHandler - 13 prompt engineering techniques');
48
+ console.error(' ✓ ErrorRecoveryHandler - Circuit breaker pattern');
49
+ console.error(' ✓ StepExecutionHandler - Step lifecycle tracking');
50
+ console.error(' ✓ ToolInvocationHandler - Tool execution coordination');
51
+ console.error(' ℹ Progress tracking: manifest.json in workflow-output/');
52
+ // Load workflows
53
+ this.loadBuiltInWorkflows();
54
+ this.loadUserWorkflows();
55
+ }
56
+ /**
57
+ * Load built-in workflow templates
58
+ */
59
+ loadBuiltInWorkflows() {
60
+ const builtInWorkflows = [
61
+ {
62
+ name: "code-review",
63
+ description: "Comprehensive code review with multiple perspectives",
64
+ version: "1.0",
65
+ settings: {
66
+ maxCost: 0.5,
67
+ optimization: {
68
+ enabled: true,
69
+ cacheResults: true,
70
+ compressPrompts: true,
71
+ smartRouting: true,
72
+ },
73
+ },
74
+ steps: [
75
+ {
76
+ name: "Initial Analysis",
77
+ tool: "gemini_analyze_code",
78
+ input: { prompt: "Analyze this code for issues and improvements" },
79
+ output: { variable: "initial_analysis" },
80
+ },
81
+ {
82
+ name: "Security Check",
83
+ tool: "verifier",
84
+ input: {
85
+ prompt: "Check for security vulnerabilities",
86
+ previousStep: "initial_analysis",
87
+ },
88
+ parallel: true,
89
+ },
90
+ {
91
+ name: "Performance Review",
92
+ tool: "gemini_analyze_code", // Use Gemini for performance analysis
93
+ input: {
94
+ prompt: "Analyze performance of: ${input}"
95
+ },
96
+ parallel: true,
97
+ },
98
+ {
99
+ name: "Best Practices",
100
+ tool: "code_reviewer",
101
+ input: { prompt: "Evaluate against best practices" },
102
+ },
103
+ {
104
+ name: "Synthesis",
105
+ tool: "gpt5_analyze",
106
+ input: {
107
+ prompt: "Synthesize all findings into actionable recommendations",
108
+ context: "Combine all previous analyses",
109
+ },
110
+ },
111
+ ],
112
+ },
113
+ {
114
+ name: "brainstorm",
115
+ description: "Multi-model brainstorming session",
116
+ version: "1.0",
117
+ settings: {
118
+ maxCost: 1.0,
119
+ defaultModel: "gpt-5-mini",
120
+ },
121
+ steps: [
122
+ {
123
+ name: "Gemini Ideas",
124
+ tool: "gemini_brainstorm",
125
+ maxTokens: 500,
126
+ },
127
+ {
128
+ name: "GPT-5 Creative",
129
+ tool: "gpt5_mini",
130
+ input: { prompt: "Build on previous ideas with creative twists" },
131
+ },
132
+ {
133
+ name: "Perplexity Research",
134
+ tool: "perplexity_research",
135
+ input: { prompt: "Find real-world examples and evidence" },
136
+ },
137
+ {
138
+ name: "Final Synthesis",
139
+ tool: "focus",
140
+ input: { prompt: "Combine all ideas into top 5 recommendations" },
141
+ },
142
+ ],
143
+ },
144
+ {
145
+ name: "debug-assistant",
146
+ description: "Multi-stage debugging helper",
147
+ version: "1.0",
148
+ steps: [
149
+ {
150
+ name: "Error Analysis",
151
+ tool: "grok_debug",
152
+ input: {
153
+ prompt: "Analyze the error message and stack trace: ${input}"
154
+ },
155
+ output: { variable: "error_analysis" },
156
+ },
157
+ {
158
+ name: "Code Context",
159
+ tool: "grok_code",
160
+ input: {
161
+ prompt: "Analyze the code path leading to this error",
162
+ previousStep: "error_analysis",
163
+ },
164
+ },
165
+ {
166
+ name: "Solution Search",
167
+ tool: "perplexity_code_search",
168
+ input: { prompt: "Find solutions for similar errors" },
169
+ parallel: true,
170
+ },
171
+ {
172
+ name: "Fix Suggestion",
173
+ tool: "gpt5_mini",
174
+ input: {
175
+ prompt: "Suggest specific code fixes",
176
+ context: "Based on all previous analysis",
177
+ },
178
+ },
179
+ ],
180
+ },
181
+ ];
182
+ for (const workflow of builtInWorkflows) {
183
+ this.workflows.set(workflow.name, workflow);
184
+ }
185
+ }
186
+ /**
187
+ * Load user-defined workflows from config directory
188
+ * Delegates to WorkflowDiscovery for multi-location workflow loading
189
+ */
190
+ loadUserWorkflows() {
191
+ const packageRoot = WorkflowDiscovery.getPackageRoot();
192
+ const discovery = new WorkflowDiscovery({
193
+ packageRoot,
194
+ workflowSchema: WorkflowSchema,
195
+ preprocessVariables: this.preprocessWorkflowVariables.bind(this),
196
+ });
197
+ const { workflows, errors } = discovery.discoverWorkflows();
198
+ // Merge discovered workflows
199
+ for (const [name, workflow] of workflows.entries()) {
200
+ this.workflows.set(name, workflow);
201
+ }
202
+ // Log validation errors if any
203
+ if (errors.length > 0) {
204
+ console.error(`⚠️ ${errors.length} workflow validation error(s):`);
205
+ for (const error of errors) {
206
+ console.error(` [${error.source}] ${error.file}: ${error.error}`);
207
+ }
208
+ }
209
+ }
210
+ /**
211
+ * Pre-process workflow to interpolate initial variables (load-time)
212
+ * This resolves ${variable} references from the variables: section
213
+ */
214
+ preprocessWorkflowVariables(obj, variables) {
215
+ if (typeof obj === "string") {
216
+ // Check if this string contains ${variable} references
217
+ if (!obj.includes("${")) {
218
+ return obj; // No interpolation needed
219
+ }
220
+ // Interpolate ${variable} references
221
+ const interpolated = obj.replace(/\${([^}]+)}/g, (match, key) => {
222
+ const value = variables[key];
223
+ if (value === undefined) {
224
+ return match; // Keep unresolved for runtime (e.g., ${step_output})
225
+ }
226
+ // Return the actual value, preserving its type
227
+ // If the entire string is just "${variable}", return the raw value (number stays number)
228
+ // Otherwise convert to string for concatenation
229
+ return value;
230
+ });
231
+ // If the ENTIRE string was just "${variable}", return the value with its original type
232
+ const singleVarMatch = obj.match(/^\${([^}]+)}$/);
233
+ if (singleVarMatch) {
234
+ const value = variables[singleVarMatch[1]];
235
+ return value !== undefined ? value : obj; // Preserve number type!
236
+ }
237
+ return interpolated;
238
+ }
239
+ if (Array.isArray(obj)) {
240
+ return obj.map((item) => this.preprocessWorkflowVariables(item, variables));
241
+ }
242
+ if (obj && typeof obj === "object") {
243
+ const result = {};
244
+ for (const [key, value] of Object.entries(obj)) {
245
+ if (key === "variables") {
246
+ // Don't interpolate variable definitions themselves
247
+ result[key] = value;
248
+ }
249
+ else {
250
+ result[key] = this.preprocessWorkflowVariables(value, variables);
251
+ }
252
+ }
253
+ return result;
254
+ }
255
+ return obj;
256
+ }
257
+ /**
258
+ * Execute a workflow by name
259
+ * Delegates to WorkflowExecutionEngine for the actual execution logic
260
+ */
261
+ async executeWorkflow(workflowName, input, options) {
262
+ const workflow = this.workflows.get(workflowName);
263
+ if (!workflow) {
264
+ throw new Error(`Workflow '${workflowName}' not found`);
265
+ }
266
+ // Check cost limit
267
+ const maxCost = workflow.settings?.maxCost || 10.0;
268
+ const costCheck = await costMonitor.checkRequest("workflow", 1000);
269
+ if (!costCheck.allowed) {
270
+ throw new Error(`Cost limit would be exceeded: ${costCheck.warning}`);
271
+ }
272
+ // Delegate to execution engine
273
+ return executeWorkflowImpl(this, workflowName, input, options);
274
+ }
275
+ /**
276
+ * Helper to evaluate conditions - delegates to WorkflowHelpers
277
+ */
278
+ evaluateCondition(condition, variables, outputs) {
279
+ const context = { ...variables, ...outputs };
280
+ return WorkflowHelpers.evaluateCondition(condition, context);
281
+ }
282
+ /**
283
+ * Helper to interpolate variables in strings - delegates to VariableInterpolator
284
+ */
285
+ async interpolateVariables(template, variables, stepOutputs) {
286
+ return this.variableInterpolator.interpolate(template, {
287
+ variables,
288
+ stepOutputs: new Map(Object.entries(stepOutputs)),
289
+ fileReferences: new Map(Object.entries(stepOutputs)),
290
+ });
291
+ }
292
+ /**
293
+ * Resolve step parameters at runtime - delegates to StepParameterResolver
294
+ */
295
+ resolveStepParameters(step, variables, stepOutputs) {
296
+ return this.parameterResolver.resolve(step, {
297
+ variables,
298
+ stepOutputs,
299
+ });
300
+ }
301
+ /**
302
+ * Call a tool - now integrated with actual MCP tools!
303
+ */
304
+ async callTool(toolName, input, options) {
305
+ // Import tool mapper dynamically to avoid circular dependencies
306
+ const { executeWorkflowTool } = await import("./tool-mapper.js");
307
+ console.error(`Calling ${toolName} with`, { input, options });
308
+ // Execute the actual tool - returns { result, modelUsed }
309
+ return await executeWorkflowTool(toolName, input, options);
310
+ }
311
+ /**
312
+ * Format workflow output - delegates to WorkflowOutputFormatter
313
+ */
314
+ formatOutput(execution, format, truncateSteps = true, maxStepTokens = 2500) {
315
+ return this.outputFormatter.format(execution, format, truncateSteps, maxStepTokens);
316
+ }
317
+ /**
318
+ * Create FileReference for step output - delegates to WorkflowFileManager
319
+ */
320
+ async createFileReference(stepName, content, workflowId, workflowName, saveToFile, outputDir, stepNumber, modelName) {
321
+ return this.fileManager.createFileReference({
322
+ stepName,
323
+ content,
324
+ workflowId,
325
+ workflowName,
326
+ saveToFile,
327
+ outputDir,
328
+ stepNumber,
329
+ modelName
330
+ });
331
+ }
332
+ /**
333
+ * Extract input summary for logging
334
+ */
335
+ extractInputSummary(input) {
336
+ if (typeof input === 'string') {
337
+ return input.length > 200 ? input.substring(0, 200) + '...' : input;
338
+ }
339
+ return JSON.stringify(input).substring(0, 200) + '...';
340
+ }
341
+ /**
342
+ * Calculate step numbers for display - delegates to WorkflowHelpers
343
+ */
344
+ calculateStepNumbers(workflow) {
345
+ return WorkflowHelpers.calculateStepNumbers(workflow);
346
+ }
347
+ /**
348
+ * Estimate total tokens - delegates to AutoSynthesizer
349
+ */
350
+ estimateTotalTokens(results) {
351
+ return this.autoSynthesizer.estimateTotalTokens(results);
352
+ }
353
+ /**
354
+ * Check if auto-synthesis should run - delegates to AutoSynthesizer
355
+ */
356
+ shouldAutoSynthesize(workflow, accumulatedResults, currentStepIndex) {
357
+ return this.autoSynthesizer.shouldSynthesize(workflow, accumulatedResults, currentStepIndex);
358
+ }
359
+ /**
360
+ * Create synthesis step - delegates to AutoSynthesizer
361
+ */
362
+ createSynthesisStep(workflow, variables, sessionDir) {
363
+ return this.autoSynthesizer.createSynthesisStep({
364
+ workflow,
365
+ variables,
366
+ sessionDir: sessionDir || null
367
+ });
368
+ }
369
+ /**
370
+ * Create checkpoint (stub for now)
371
+ */
372
+ async createCheckpoint(workflowName, outputDir, variables, stepIndex) {
373
+ // Implementation to be added if needed
374
+ }
375
+ /**
376
+ * Delete checkpoint (stub for now)
377
+ */
378
+ async deleteCheckpoint(outputDir) {
379
+ // Implementation to be added if needed
380
+ }
381
+ /**
382
+ * List available workflows
383
+ */
384
+ listWorkflows() {
385
+ return Array.from(this.workflows.values()).map((w) => ({
386
+ name: w.name,
387
+ description: w.description,
388
+ steps: w.steps.length,
389
+ }));
390
+ }
391
+ /**
392
+ * Get workflow definition
393
+ */
394
+ getWorkflow(name) {
395
+ return this.workflows.get(name);
396
+ }
397
+ /**
398
+ * Save a new workflow
399
+ */
400
+ async saveWorkflow(workflow, format = "yaml") {
401
+ const dir = path.join(process.cwd(), ".tachi", "workflows");
402
+ if (!fs.existsSync(dir)) {
403
+ fs.mkdirSync(dir, { recursive: true });
404
+ }
405
+ const filename = `${workflow.name}.${format}`;
406
+ const filepath = path.join(dir, filename);
407
+ const content = format === "json"
408
+ ? JSON.stringify(workflow, null, 2)
409
+ : yaml.stringify(workflow);
410
+ fs.writeFileSync(filepath, content);
411
+ this.workflows.set(workflow.name, workflow);
412
+ console.log(`✅ Saved workflow: ${workflow.name} to ${filepath}`);
413
+ }
414
+ /**
415
+ * Load and execute workflow from file (stub - needs implementation)
416
+ */
417
+ async loadAndExecuteWorkflowFile(filePath, query, options) {
418
+ // Load workflow from file
419
+ const discovery = new WorkflowDiscovery({
420
+ packageRoot: WorkflowDiscovery.getPackageRoot(),
421
+ workflowSchema: WorkflowSchema,
422
+ preprocessVariables: this.preprocessWorkflowVariables.bind(this),
423
+ });
424
+ const workflow = discovery.loadWorkflowFile(filePath);
425
+ // Temporarily add to workflows map
426
+ this.workflows.set(workflow.name, workflow);
427
+ // Execute it
428
+ return this.executeWorkflow(workflow.name, query, options);
429
+ }
430
+ /**
431
+ * Get validation errors from workflow loading (stub)
432
+ */
433
+ getValidationErrors() {
434
+ // TODO: Implement validation error tracking
435
+ return [];
436
+ }
437
+ /**
438
+ * Start workflow step-by-step (stub - needs implementation)
439
+ */
440
+ async startWorkflowStepByStep(workflowName, query, options) {
441
+ throw new Error("Step-by-step execution not yet implemented in refactored engine");
442
+ }
443
+ /**
444
+ * Continue workflow from session (stub - needs implementation)
445
+ */
446
+ async continueWorkflow(sessionId) {
447
+ throw new Error("Continue workflow not yet implemented in refactored engine");
448
+ }
449
+ }
450
+ // Export singleton
451
+ export const workflowEngine = new CustomWorkflowEngine();
@@ -0,0 +1,97 @@
1
+ /**
2
+ * Auto-Synthesizer
3
+ * Automatically summarizes large workflow outputs to bypass MCP 25k token limit
4
+ */
5
+ export class AutoSynthesizer {
6
+ /**
7
+ * Determines if auto-synthesis should run
8
+ */
9
+ shouldSynthesize(workflow, accumulatedResults, currentStepIndex) {
10
+ // Check if auto-synthesis is enabled
11
+ const autoSynthesis = workflow.settings?.autoSynthesis;
12
+ if (!autoSynthesis?.enabled) {
13
+ return false;
14
+ }
15
+ // Check if any step up to current has saveToFile: true
16
+ const hasSaveToFile = workflow.steps
17
+ .slice(0, currentStepIndex + 1)
18
+ .some((step) => step.saveToFile === true);
19
+ // Estimate total tokens accumulated
20
+ const totalTokens = this.estimateTotalTokens(accumulatedResults);
21
+ // Trigger if:
22
+ // 1. Any step saves to file (indicates large/important outputs), OR
23
+ // 2. Total tokens exceed threshold
24
+ const shouldTrigger = hasSaveToFile || totalTokens >= (autoSynthesis.tokenThreshold ?? 20000);
25
+ return shouldTrigger;
26
+ }
27
+ /**
28
+ * Creates a synthesis step that summarizes all previous outputs
29
+ */
30
+ createSynthesisStep(context) {
31
+ const { workflow, variables, sessionDir } = context;
32
+ const autoSynthesis = workflow.settings?.autoSynthesis;
33
+ const synthesisTool = autoSynthesis?.synthesisTool ?? 'gemini_analyze_text';
34
+ const maxTokens = autoSynthesis?.synthesisMaxTokens ?? 6000;
35
+ // Collect all step outputs (variable names)
36
+ const stepOutputs = workflow.steps
37
+ .filter((step) => step.output?.variable)
38
+ .map((step) => step.output?.variable)
39
+ .filter((varName) => varName !== undefined);
40
+ // Build text parameter with all outputs
41
+ const allOutputsText = stepOutputs
42
+ .map((varName) => `${variables[varName] ?? ''}`)
43
+ .join('\n\n');
44
+ // Build list of saved files if applicable
45
+ const savedFiles = sessionDir
46
+ ? workflow.steps
47
+ .filter((step) => step.saveToFile)
48
+ .map((step) => `- ${step.name}.md`)
49
+ .join('\n')
50
+ : '';
51
+ const fileNote = savedFiles
52
+ ? `\n\nNote: Full outputs saved to ${sessionDir}/\nFiles:\n${savedFiles}\n\nEnd with: "Use Read tool on saved files for full detailed analysis."`
53
+ : '';
54
+ // Create synthesis task instruction
55
+ const synthesisTask = `Synthesize all workflow outputs into executive summary:
56
+
57
+ 1. Key findings (brief, top 3-5 points)
58
+ 2. Main insights or patterns discovered
59
+ 3. Critical issues or challenges identified
60
+ 4. Recommended next steps with priorities
61
+ 5. Overall assessment${fileNote}
62
+
63
+ Keep under 2000 words for Claude Code.`;
64
+ // Create the synthesis step
65
+ const synthesisStep = {
66
+ name: 'auto-synthesis',
67
+ tool: synthesisTool,
68
+ input: {
69
+ text: allOutputsText,
70
+ task: synthesisTask,
71
+ },
72
+ maxTokens,
73
+ output: {
74
+ variable: 'executive_summary',
75
+ },
76
+ };
77
+ return synthesisStep;
78
+ }
79
+ /**
80
+ * Estimates total tokens across accumulated results
81
+ */
82
+ estimateTotalTokens(results) {
83
+ let total = 0;
84
+ for (const result of results) {
85
+ total += this.estimateTokens(result);
86
+ }
87
+ return total;
88
+ }
89
+ /**
90
+ * Estimate token count for any data type
91
+ * Uses character-based approximation: tokens ≈ characters / 4
92
+ */
93
+ estimateTokens(data) {
94
+ const text = typeof data === 'string' ? data : JSON.stringify(data);
95
+ return Math.ceil(text.length / 4);
96
+ }
97
+ }
@@ -0,0 +1,74 @@
1
+ /**
2
+ * Step Parameter Resolver
3
+ * Resolves step parameters (model, temperature, maxTokens) with variable interpolation
4
+ */
5
+ export class StepParameterResolver {
6
+ /**
7
+ * Type guard to check if value is a FileReference
8
+ */
9
+ isFileReference(value) {
10
+ return (value &&
11
+ typeof value === 'object' &&
12
+ 'stepName' in value &&
13
+ 'summary' in value &&
14
+ 'getContent' in value &&
15
+ typeof value.getContent === 'function');
16
+ }
17
+ /**
18
+ * Resolves step parameters (model, temperature, maxTokens)
19
+ */
20
+ resolve(step, context) {
21
+ const mergedContext = { ...context.variables, ...context.stepOutputs };
22
+ // Helper to resolve a value (string or already-resolved)
23
+ const resolve = (value, type) => {
24
+ if (value === undefined)
25
+ return undefined;
26
+ // Already the correct type
27
+ if (type === "number" && typeof value === "number")
28
+ return value;
29
+ if (type === "string" &&
30
+ typeof value === "string" &&
31
+ !value.includes("${"))
32
+ return value;
33
+ // Interpolate ${variable} if it's a string
34
+ if (typeof value === "string") {
35
+ const interpolated = value.replace(/\${([^}]+)}/g, (match, key) => {
36
+ const resolved = mergedContext[key];
37
+ // Handle FileReference objects - return summary by default
38
+ if (this.isFileReference(resolved)) {
39
+ return resolved.summary;
40
+ }
41
+ // Preserve placeholder if undefined (better for debugging than empty string)
42
+ return resolved !== undefined ? String(resolved) : match;
43
+ });
44
+ // Convert to number if needed
45
+ if (type === "number") {
46
+ const num = parseFloat(interpolated);
47
+ if (isNaN(num)) {
48
+ console.warn(`⚠️ Could not convert "${interpolated}" to number, using undefined`);
49
+ return undefined;
50
+ }
51
+ return num;
52
+ }
53
+ return interpolated;
54
+ }
55
+ return value;
56
+ };
57
+ const resolved = {
58
+ model: resolve(step.model, "string"),
59
+ temperature: resolve(step.temperature, "number"),
60
+ maxTokens: resolve(step.maxTokens, "number"),
61
+ };
62
+ // Log if interpolation happened
63
+ if (step.model && step.model !== resolved.model) {
64
+ console.error(`🔄 Resolved model: "${step.model}" → "${resolved.model}"`);
65
+ }
66
+ if (step.temperature && step.temperature !== resolved.temperature) {
67
+ console.error(`🔄 Resolved temperature: "${step.temperature}" → ${resolved.temperature}`);
68
+ }
69
+ if (step.maxTokens && step.maxTokens !== resolved.maxTokens) {
70
+ console.error(`🔄 Resolved maxTokens: "${step.maxTokens}" → ${resolved.maxTokens}`);
71
+ }
72
+ return resolved;
73
+ }
74
+ }