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.
- package/.env.example +260 -0
- package/CHANGELOG.md +54 -0
- package/CODE_OF_CONDUCT.md +56 -0
- package/CONTRIBUTING.md +54 -0
- package/Dockerfile +36 -0
- package/LICENSE +644 -0
- package/README.md +201 -0
- package/SECURITY.md +95 -0
- package/dist/personality/komaai-expressions.js +12 -0
- package/dist/profiles/balanced.json +33 -0
- package/dist/profiles/code_focus.json +33 -0
- package/dist/profiles/full.json +33 -0
- package/dist/profiles/minimal.json +33 -0
- package/dist/profiles/research_power.json +33 -0
- package/dist/scripts/build-profiles.js +46 -0
- package/dist/src/application/services/focus/FocusModeRegistry.js +46 -0
- package/dist/src/application/services/focus/FocusTool.service.js +109 -0
- package/dist/src/application/services/focus/ModeRegistry.js +46 -0
- package/dist/src/application/services/focus/modes/focus-deep.mode.js +27 -0
- package/dist/src/application/services/focus/modes/status.mode.js +50 -0
- package/dist/src/application/services/focus/modes/tachibot-status.mode.js +50 -0
- package/dist/src/collaborative-orchestrator.js +391 -0
- package/dist/src/config/model-constants.js +188 -0
- package/dist/src/config/model-defaults.js +57 -0
- package/dist/src/config/model-preferences.js +382 -0
- package/dist/src/config/timeout-config.js +130 -0
- package/dist/src/config.js +173 -0
- package/dist/src/domain/interfaces/IFocusMode.js +5 -0
- package/dist/src/domain/interfaces/IProvider.js +6 -0
- package/dist/src/domain/interfaces/ITool.js +5 -0
- package/dist/src/focus-deep.js +245 -0
- package/dist/src/infrastructure/ascii/art/robots.ascii.js +16 -0
- package/dist/src/mcp-client.js +90 -0
- package/dist/src/memory/index.js +17 -0
- package/dist/src/memory/memory-config.js +135 -0
- package/dist/src/memory/memory-interface.js +174 -0
- package/dist/src/memory/memory-manager.js +383 -0
- package/dist/src/memory/providers/devlog-provider.js +385 -0
- package/dist/src/memory/providers/hybrid-provider.js +399 -0
- package/dist/src/memory/providers/local-provider.js +388 -0
- package/dist/src/memory/providers/mem0-provider.js +337 -0
- package/dist/src/modes/architect.js +477 -0
- package/dist/src/modes/auditor.js +362 -0
- package/dist/src/modes/challenger.js +841 -0
- package/dist/src/modes/code-reviewer.js +382 -0
- package/dist/src/modes/commit-guardian.js +424 -0
- package/dist/src/modes/documentation-writer.js +572 -0
- package/dist/src/modes/scout.js +587 -0
- package/dist/src/modes/shared/helpers/challenger-helpers.js +454 -0
- package/dist/src/modes/shared/helpers/index.js +17 -0
- package/dist/src/modes/shared/helpers/scout-helpers.js +270 -0
- package/dist/src/modes/shared/helpers/verifier-helpers.js +332 -0
- package/dist/src/modes/test-architect.js +767 -0
- package/dist/src/modes/verifier.js +378 -0
- package/dist/src/monitoring/performance-monitor.js +435 -0
- package/dist/src/optimization/batch-executor.js +121 -0
- package/dist/src/optimization/context-pruner.js +196 -0
- package/dist/src/optimization/cost-monitor.js +338 -0
- package/dist/src/optimization/index.js +65 -0
- package/dist/src/optimization/model-router.js +264 -0
- package/dist/src/optimization/result-cache.js +114 -0
- package/dist/src/optimization/token-optimizer.js +257 -0
- package/dist/src/optimization/token-tracker.js +118 -0
- package/dist/src/orchestrator-instructions.js +128 -0
- package/dist/src/orchestrator-lite.js +139 -0
- package/dist/src/orchestrator.js +191 -0
- package/dist/src/orchestrators/collaborative/interfaces/IToolExecutionEngine.js +1 -0
- package/dist/src/orchestrators/collaborative/interfaces/IToolExecutionStrategy.js +5 -0
- package/dist/src/orchestrators/collaborative/interfaces/IVisualizationRenderer.js +1 -0
- package/dist/src/orchestrators/collaborative/registries/ModelProviderRegistry.js +95 -0
- package/dist/src/orchestrators/collaborative/registries/ToolAdapterRegistry.js +64 -0
- package/dist/src/orchestrators/collaborative/services/tool-execution/ToolExecutionService.js +502 -0
- package/dist/src/orchestrators/collaborative/services/visualization/VisualizationService.js +206 -0
- package/dist/src/orchestrators/collaborative/types/session-types.js +5 -0
- package/dist/src/profiles/balanced.js +37 -0
- package/dist/src/profiles/code_focus.js +37 -0
- package/dist/src/profiles/debug_intensive.js +59 -0
- package/dist/src/profiles/full.js +37 -0
- package/dist/src/profiles/minimal.js +37 -0
- package/dist/src/profiles/research_code.js +59 -0
- package/dist/src/profiles/research_power.js +37 -0
- package/dist/src/profiles/types.js +5 -0
- package/dist/src/profiles/workflow_builder.js +53 -0
- package/dist/src/prompt-engineer-lite.js +78 -0
- package/dist/src/prompt-engineer.js +399 -0
- package/dist/src/reasoning-chain.js +508 -0
- package/dist/src/sequential-thinking.js +291 -0
- package/dist/src/server-diagnostic.js +74 -0
- package/dist/src/server-raw.js +158 -0
- package/dist/src/server-simple.js +58 -0
- package/dist/src/server.js +514 -0
- package/dist/src/session/session-logger.js +617 -0
- package/dist/src/session/session-manager.js +571 -0
- package/dist/src/session/session-tools.js +400 -0
- package/dist/src/tools/advanced-modes.js +200 -0
- package/dist/src/tools/claude-integration.js +356 -0
- package/dist/src/tools/consolidated/ai-router.js +174 -0
- package/dist/src/tools/consolidated/ai-tool.js +48 -0
- package/dist/src/tools/consolidated/brainstorm-tool.js +87 -0
- package/dist/src/tools/consolidated/environment-detector.js +80 -0
- package/dist/src/tools/consolidated/index.js +50 -0
- package/dist/src/tools/consolidated/search-tool.js +110 -0
- package/dist/src/tools/consolidated/workflow-tool.js +238 -0
- package/dist/src/tools/gemini-tools.js +329 -0
- package/dist/src/tools/grok-enhanced.js +376 -0
- package/dist/src/tools/grok-tools.js +299 -0
- package/dist/src/tools/lmstudio-tools.js +223 -0
- package/dist/src/tools/openai-tools.js +498 -0
- package/dist/src/tools/openrouter-tools.js +317 -0
- package/dist/src/tools/optimized-wrapper.js +204 -0
- package/dist/src/tools/perplexity-tools.js +294 -0
- package/dist/src/tools/pingpong-tool.js +343 -0
- package/dist/src/tools/qwen-wrapper.js +74 -0
- package/dist/src/tools/tool-router.js +444 -0
- package/dist/src/tools/unified-ai-provider.js +260 -0
- package/dist/src/tools/workflow-runner.js +425 -0
- package/dist/src/tools/workflow-validator-tool.js +107 -0
- package/dist/src/types.js +23 -0
- package/dist/src/utils/input-validator.js +130 -0
- package/dist/src/utils/model-router.js +91 -0
- package/dist/src/utils/progress-stream.js +255 -0
- package/dist/src/utils/provider-router.js +88 -0
- package/dist/src/utils/smart-api-client.js +146 -0
- package/dist/src/utils/table-builder.js +218 -0
- package/dist/src/utils/timestamp-formatter.js +134 -0
- package/dist/src/utils/tool-compressor.js +257 -0
- package/dist/src/utils/tool-config.js +201 -0
- package/dist/src/validators/dependency-graph-validator.js +147 -0
- package/dist/src/validators/interpolation-validator.js +222 -0
- package/dist/src/validators/output-usage-validator.js +151 -0
- package/dist/src/validators/syntax-validator.js +102 -0
- package/dist/src/validators/tool-registry-validator.js +123 -0
- package/dist/src/validators/tool-types.js +97 -0
- package/dist/src/validators/types.js +8 -0
- package/dist/src/validators/workflow-validator.js +134 -0
- package/dist/src/visualizer-lite.js +42 -0
- package/dist/src/visualizer.js +179 -0
- package/dist/src/workflows/circuit-breaker.js +199 -0
- package/dist/src/workflows/custom-workflows.js +451 -0
- package/dist/src/workflows/engine/AutoSynthesizer.js +97 -0
- package/dist/src/workflows/engine/StepParameterResolver.js +74 -0
- package/dist/src/workflows/engine/VariableInterpolator.js +123 -0
- package/dist/src/workflows/engine/WorkflowDiscovery.js +125 -0
- package/dist/src/workflows/engine/WorkflowExecutionEngine.js +485 -0
- package/dist/src/workflows/engine/WorkflowExecutor.js +113 -0
- package/dist/src/workflows/engine/WorkflowFileManager.js +244 -0
- package/dist/src/workflows/engine/WorkflowHelpers.js +114 -0
- package/dist/src/workflows/engine/WorkflowOutputFormatter.js +83 -0
- package/dist/src/workflows/engine/events/WorkflowEventBus.js +132 -0
- package/dist/src/workflows/engine/events/interfaces/IEventBus.js +5 -0
- package/dist/src/workflows/engine/handlers/ErrorRecoveryHandler.js +162 -0
- package/dist/src/workflows/engine/handlers/PromptEnhancementHandler.js +115 -0
- package/dist/src/workflows/engine/handlers/SessionPersistenceHandler.js +167 -0
- package/dist/src/workflows/engine/handlers/StepExecutionHandler.js +231 -0
- package/dist/src/workflows/engine/handlers/ToolInvocationHandler.js +46 -0
- package/dist/src/workflows/engine/interfaces/IAutoSynthesizer.js +5 -0
- package/dist/src/workflows/engine/interfaces/IStepParameterResolver.js +5 -0
- package/dist/src/workflows/engine/interfaces/IVariableInterpolator.js +5 -0
- package/dist/src/workflows/engine/interfaces/IWorkflowDiscovery.js +4 -0
- package/dist/src/workflows/engine/interfaces/IWorkflowFileManager.js +5 -0
- package/dist/src/workflows/engine/interfaces/IWorkflowOutputFormatter.js +5 -0
- package/dist/src/workflows/engine/state/WorkflowStateMachine.js +194 -0
- package/dist/src/workflows/engine/state/interfaces/IStateMachine.js +17 -0
- package/dist/src/workflows/fallback-strategies.js +373 -0
- package/dist/src/workflows/message-queue.js +455 -0
- package/dist/src/workflows/model-router.js +189 -0
- package/dist/src/workflows/orchestrator-examples.js +174 -0
- package/dist/src/workflows/orchestrator-integration.js +200 -0
- package/dist/src/workflows/self-healing.js +524 -0
- package/dist/src/workflows/tool-mapper.js +407 -0
- package/dist/src/workflows/tool-orchestrator.js +796 -0
- package/dist/src/workflows/workflow-engine.js +573 -0
- package/dist/src/workflows/workflow-parser.js +283 -0
- package/dist/src/workflows/workflow-types.js +95 -0
- package/dist/src/workflows.js +568 -0
- package/dist/test-workflow-file-output.js +93 -0
- package/docs/API_KEYS.md +570 -0
- package/docs/CLAUDE_CODE_SETUP.md +181 -0
- package/docs/CLAUDE_DESKTOP_MANUAL.md +127 -0
- package/docs/CONFIGURATION.md +745 -0
- package/docs/FOCUS_MODES.md +240 -0
- package/docs/INSTALLATION_BOTH.md +145 -0
- package/docs/TERMS.md +352 -0
- package/docs/TOOLS_REFERENCE.md +1622 -0
- package/docs/TOOL_PARAMETERS.md +496 -0
- package/docs/TOOL_PROFILES.md +236 -0
- package/docs/WORKFLOWS.md +987 -0
- package/docs/WORKFLOW_OUTPUT.md +198 -0
- package/docs/WORKFLOW_PROGRESS_TRACKING.md +305 -0
- package/docs/workflows/design-brainstorm.md +335 -0
- package/package.json +97 -0
- package/profiles/balanced.json +37 -0
- package/profiles/code_focus.json +37 -0
- package/profiles/debug_intensive.json +34 -0
- package/profiles/full.json +37 -0
- package/profiles/minimal.json +37 -0
- package/profiles/research_power.json +37 -0
- package/profiles/workflow_builder.json +37 -0
- package/smithery.yaml +66 -0
- package/start.sh +8 -0
- package/tools.config.json +81 -0
- package/tsconfig.json +18 -0
- package/workflows/accessibility-code-audit.yaml +92 -0
- package/workflows/code-architecture-review.yaml +202 -0
- package/workflows/code-review.yaml +142 -0
- package/workflows/core/iterative-problem-solver.yaml +283 -0
- package/workflows/creative-brainstorm-yaml.yaml +215 -0
- package/workflows/pingpong.yaml +141 -0
- package/workflows/system/README.md +412 -0
- package/workflows/system/challenger.yaml +175 -0
- package/workflows/system/scout.yaml +164 -0
- package/workflows/system/verifier.yaml +133 -0
- package/workflows/ultra-creative-brainstorm.yaml +318 -0
- 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
|
+
}
|