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,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Environment Detector
|
|
3
|
+
* Detects the current environment and available providers
|
|
4
|
+
*/
|
|
5
|
+
export function detectEnvironment() {
|
|
6
|
+
const env = {
|
|
7
|
+
type: 'standalone',
|
|
8
|
+
nativeProviders: [],
|
|
9
|
+
availableProviders: {},
|
|
10
|
+
apiKeys: {},
|
|
11
|
+
skipNativeAPIs: []
|
|
12
|
+
};
|
|
13
|
+
// Detect environment type
|
|
14
|
+
if (process.env.CLAUDE_CODE_SESSION || process.env.ANTHROPIC_SESSION_ID) {
|
|
15
|
+
env.type = 'claude-code';
|
|
16
|
+
env.nativeProviders.push('claude');
|
|
17
|
+
env.skipNativeAPIs.push('anthropic');
|
|
18
|
+
}
|
|
19
|
+
else if (process.env.CURSOR_SESSION || process.env.CURSOR_IDE) {
|
|
20
|
+
env.type = 'cursor';
|
|
21
|
+
env.nativeProviders.push('openai');
|
|
22
|
+
env.skipNativeAPIs.push('openai');
|
|
23
|
+
}
|
|
24
|
+
else if (process.env.CODEX_SESSION) {
|
|
25
|
+
env.type = 'codex';
|
|
26
|
+
env.nativeProviders.push('openai');
|
|
27
|
+
env.skipNativeAPIs.push('openai');
|
|
28
|
+
}
|
|
29
|
+
else if (process.env.VSCODE_PID) {
|
|
30
|
+
env.type = 'vscode';
|
|
31
|
+
}
|
|
32
|
+
// Check available API keys
|
|
33
|
+
const providers = {
|
|
34
|
+
openai: process.env.OPENAI_API_KEY,
|
|
35
|
+
anthropic: process.env.ANTHROPIC_API_KEY,
|
|
36
|
+
grok: process.env.GROK_API_KEY,
|
|
37
|
+
perplexity: process.env.PERPLEXITY_API_KEY,
|
|
38
|
+
gemini: process.env.GOOGLE_API_KEY,
|
|
39
|
+
deepseek: process.env.DEEPSEEK_API_KEY,
|
|
40
|
+
openrouter: process.env.OPENROUTER_API_KEY
|
|
41
|
+
};
|
|
42
|
+
for (const [provider, key] of Object.entries(providers)) {
|
|
43
|
+
env.availableProviders[provider] = !!key;
|
|
44
|
+
env.apiKeys[provider] = key;
|
|
45
|
+
}
|
|
46
|
+
// Check GPT-5 feature flag
|
|
47
|
+
if (process.env.ENABLE_GPT5 === 'true' && env.availableProviders.openai) {
|
|
48
|
+
env.availableProviders['gpt5'] = true;
|
|
49
|
+
}
|
|
50
|
+
return env;
|
|
51
|
+
}
|
|
52
|
+
export function getBestAvailableProvider(env, taskType) {
|
|
53
|
+
// Task-specific routing
|
|
54
|
+
const preferences = {
|
|
55
|
+
reason: ['grok', 'openai', 'gemini', 'anthropic', 'deepseek'],
|
|
56
|
+
search: ['perplexity', 'grok', 'openai'],
|
|
57
|
+
code: ['openai', 'anthropic', 'deepseek', 'gemini'],
|
|
58
|
+
analyze: ['gemini', 'openai', 'anthropic', 'grok'],
|
|
59
|
+
brainstorm: ['gemini', 'grok', 'openai', 'anthropic'],
|
|
60
|
+
general: ['openai', 'anthropic', 'gemini', 'grok', 'perplexity']
|
|
61
|
+
};
|
|
62
|
+
const preferred = preferences[taskType] || preferences.general;
|
|
63
|
+
for (const provider of preferred) {
|
|
64
|
+
// Check if we should use native provider
|
|
65
|
+
if (env.nativeProviders.includes(provider)) {
|
|
66
|
+
return provider;
|
|
67
|
+
}
|
|
68
|
+
// Check if API key is available and not skipped
|
|
69
|
+
if (env.availableProviders[provider] && !env.skipNativeAPIs.includes(provider)) {
|
|
70
|
+
return provider;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
// Try any available provider
|
|
74
|
+
for (const [provider, available] of Object.entries(env.availableProviders)) {
|
|
75
|
+
if (available && !env.skipNativeAPIs.includes(provider)) {
|
|
76
|
+
return provider;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
return null;
|
|
80
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Consolidated Tools Export
|
|
3
|
+
* 12 smart tools replacing 62 individual tools
|
|
4
|
+
* Target: 6,500 tokens (from 13,400)
|
|
5
|
+
*/
|
|
6
|
+
// Core tools are defined directly in server.ts, not here
|
|
7
|
+
// export { thinkTool } from '../core/think-tool.js';
|
|
8
|
+
// export { focusTool } from '../core/focus-tool.js';
|
|
9
|
+
// New consolidated tools
|
|
10
|
+
export { aiTool } from './ai-tool.js';
|
|
11
|
+
export { searchTool } from './search-tool.js';
|
|
12
|
+
export { brainstormTool } from './brainstorm-tool.js';
|
|
13
|
+
export { workflowTool } from './workflow-tool.js';
|
|
14
|
+
// Additional consolidated tools (to be implemented - commented out for now)
|
|
15
|
+
// export { analyzeTool } from './analyze-tool.js';
|
|
16
|
+
// export { generateTool } from './generate-tool.js';
|
|
17
|
+
// export { reasonTool } from './reason-tool.js';
|
|
18
|
+
// export { verifyTool } from './verify-tool.js';
|
|
19
|
+
// export { challengeTool } from './challenge-tool.js';
|
|
20
|
+
// export { orchestrateTool } from './orchestrate-tool.js';
|
|
21
|
+
// Export all as array for easy registration
|
|
22
|
+
export const consolidatedTools = [
|
|
23
|
+
'think',
|
|
24
|
+
'focus',
|
|
25
|
+
'workflow',
|
|
26
|
+
'ai',
|
|
27
|
+
'search',
|
|
28
|
+
'analyze',
|
|
29
|
+
'generate',
|
|
30
|
+
'reason',
|
|
31
|
+
'brainstorm',
|
|
32
|
+
'verify',
|
|
33
|
+
'challenge',
|
|
34
|
+
'orchestrate'
|
|
35
|
+
];
|
|
36
|
+
// Tool descriptions for documentation
|
|
37
|
+
export const toolDescriptions = {
|
|
38
|
+
think: 'Internal reasoning and caching',
|
|
39
|
+
focus: 'Multi-mode orchestration (16+ modes)',
|
|
40
|
+
workflow: 'Execute YAML workflows',
|
|
41
|
+
ai: 'Universal AI query',
|
|
42
|
+
search: 'Web search (auto-selects provider)',
|
|
43
|
+
analyze: 'Any analysis type',
|
|
44
|
+
generate: 'Code/text generation',
|
|
45
|
+
reason: 'Complex reasoning',
|
|
46
|
+
brainstorm: 'Creative ideation',
|
|
47
|
+
verify: 'Multi-model verification',
|
|
48
|
+
challenge: 'Critical thinking',
|
|
49
|
+
orchestrate: 'Custom workflows/PingPong'
|
|
50
|
+
};
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Consolidated Search Tool
|
|
3
|
+
* Smart web search with provider selection
|
|
4
|
+
*/
|
|
5
|
+
import { z } from "zod";
|
|
6
|
+
import { detectEnvironment } from './environment-detector.js';
|
|
7
|
+
import { callPerplexity, PerplexityModel } from '../perplexity-tools.js';
|
|
8
|
+
import { callGrok } from '../grok-tools.js';
|
|
9
|
+
import * as fs from 'fs/promises';
|
|
10
|
+
import * as path from 'path';
|
|
11
|
+
/**
|
|
12
|
+
* Unified Search Tool
|
|
13
|
+
* Replaces: perplexity_ask, perplexity_research, grok_search, perplexity_code_search, perplexity_fact_check
|
|
14
|
+
* Token cost: ~200 tokens (vs 1000+ for individual tools)
|
|
15
|
+
*/
|
|
16
|
+
export const searchTool = {
|
|
17
|
+
name: "search",
|
|
18
|
+
description: "Web search", // Ultra-short description
|
|
19
|
+
parameters: z.object({
|
|
20
|
+
query: z.string(),
|
|
21
|
+
type: z.enum(["general", "research", "code", "fact", "latest"])
|
|
22
|
+
.default("general"),
|
|
23
|
+
provider: z.enum(["auto", "perplexity", "grok"])
|
|
24
|
+
.default("auto"),
|
|
25
|
+
live: z.boolean()
|
|
26
|
+
.optional(),
|
|
27
|
+
maxSources: z.number()
|
|
28
|
+
.optional(),
|
|
29
|
+
recency: z.enum(["hour", "day", "week", "month", "year"])
|
|
30
|
+
.optional(),
|
|
31
|
+
saveAs: z.string()
|
|
32
|
+
.optional()
|
|
33
|
+
}),
|
|
34
|
+
execute: async (args, { log }) => {
|
|
35
|
+
const env = detectEnvironment();
|
|
36
|
+
// Determine provider
|
|
37
|
+
let selectedProvider = args.provider || 'auto';
|
|
38
|
+
if (selectedProvider === 'auto') {
|
|
39
|
+
// Auto-select based on type and availability
|
|
40
|
+
if (args.type === 'latest' || args.live) {
|
|
41
|
+
// Prefer Grok for latest/live search
|
|
42
|
+
selectedProvider = env.availableProviders.grok ? 'grok' : 'perplexity';
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
// Prefer Perplexity for general search
|
|
46
|
+
selectedProvider = env.availableProviders.perplexity ? 'perplexity' : 'grok';
|
|
47
|
+
}
|
|
48
|
+
// Fallback if neither available
|
|
49
|
+
if (!env.availableProviders[selectedProvider]) {
|
|
50
|
+
return '[No search providers available. Please set PERPLEXITY_API_KEY or GROK_API_KEY]';
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
log?.info(`Search: provider=${selectedProvider}, type=${args.type}, live=${args.live}`);
|
|
54
|
+
try {
|
|
55
|
+
let result;
|
|
56
|
+
if (selectedProvider === 'grok' && env.availableProviders.grok) {
|
|
57
|
+
// Use Grok search
|
|
58
|
+
const grokOptions = {
|
|
59
|
+
live: args.live,
|
|
60
|
+
maxSources: args.maxSources
|
|
61
|
+
};
|
|
62
|
+
const messages = [{
|
|
63
|
+
role: 'user',
|
|
64
|
+
content: args.query
|
|
65
|
+
}];
|
|
66
|
+
result = await callGrok(messages, grokOptions);
|
|
67
|
+
}
|
|
68
|
+
else if (selectedProvider === 'perplexity' && env.availableProviders.perplexity) {
|
|
69
|
+
// Use Perplexity search
|
|
70
|
+
const messages = [{
|
|
71
|
+
role: 'user',
|
|
72
|
+
content: args.query
|
|
73
|
+
}];
|
|
74
|
+
// Select Perplexity model based on type
|
|
75
|
+
let model = PerplexityModel.SONAR_PRO;
|
|
76
|
+
if (args.type === 'research') {
|
|
77
|
+
model = PerplexityModel.SONAR_DEEP_RESEARCH;
|
|
78
|
+
}
|
|
79
|
+
// Map type to search domain if needed
|
|
80
|
+
let searchDomain;
|
|
81
|
+
if (args.type === 'code') {
|
|
82
|
+
searchDomain = 'github.com stackoverflow.com';
|
|
83
|
+
}
|
|
84
|
+
result = await callPerplexity(messages, model, searchDomain, args.recency);
|
|
85
|
+
}
|
|
86
|
+
else {
|
|
87
|
+
return `[${selectedProvider} search not available. Please check API keys]`;
|
|
88
|
+
}
|
|
89
|
+
// Save if requested
|
|
90
|
+
if (args.saveAs) {
|
|
91
|
+
try {
|
|
92
|
+
const filePath = path.resolve(args.saveAs);
|
|
93
|
+
await fs.writeFile(filePath, result, 'utf8');
|
|
94
|
+
log?.info(`Saved search results to: ${filePath}`);
|
|
95
|
+
return `${result}\n\n[Saved to: ${filePath}]`;
|
|
96
|
+
}
|
|
97
|
+
catch (error) {
|
|
98
|
+
log?.error(`Failed to save: ${error}`);
|
|
99
|
+
return `${result}\n\n[Failed to save: ${error instanceof Error ? error.message : String(error)}]`;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
return result;
|
|
103
|
+
}
|
|
104
|
+
catch (error) {
|
|
105
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
106
|
+
log?.error(`Search error: ${errorMessage}`);
|
|
107
|
+
return `[Search Error: ${errorMessage}]`;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
};
|
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Workflow Tool
|
|
3
|
+
* Execute YAML workflows and custom orchestrations
|
|
4
|
+
*/
|
|
5
|
+
import { z } from "zod";
|
|
6
|
+
import * as yaml from 'yaml';
|
|
7
|
+
import * as fs from 'fs/promises';
|
|
8
|
+
import * as path from 'path';
|
|
9
|
+
import { fileURLToPath } from 'url';
|
|
10
|
+
import { AIRouter } from './ai-router.js';
|
|
11
|
+
import { searchTool } from './search-tool.js';
|
|
12
|
+
import { brainstormTool } from './brainstorm-tool.js';
|
|
13
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
14
|
+
const __dirname = path.dirname(__filename);
|
|
15
|
+
/**
|
|
16
|
+
* Workflow Execution Tool
|
|
17
|
+
* Replaces: nextThought, workflow tools, and session management
|
|
18
|
+
* Token cost: ~150 tokens
|
|
19
|
+
*/
|
|
20
|
+
export const workflowTool = {
|
|
21
|
+
name: "workflow",
|
|
22
|
+
description: "Execute workflows", // Ultra-short description
|
|
23
|
+
parameters: z.object({
|
|
24
|
+
task: z.string(),
|
|
25
|
+
template: z.string()
|
|
26
|
+
.optional(),
|
|
27
|
+
steps: z.array(z.string())
|
|
28
|
+
.optional(),
|
|
29
|
+
inputs: z.record(z.string())
|
|
30
|
+
.optional(),
|
|
31
|
+
saveAs: z.string()
|
|
32
|
+
.optional(),
|
|
33
|
+
format: z.enum(["md", "json", "yaml"])
|
|
34
|
+
.default("md")
|
|
35
|
+
}),
|
|
36
|
+
execute: async (args, { log }) => {
|
|
37
|
+
log?.info(`Workflow: task="${args.task}", template=${args.template || 'inline'}`);
|
|
38
|
+
try {
|
|
39
|
+
let workflow;
|
|
40
|
+
if (args.template) {
|
|
41
|
+
// Load workflow from template
|
|
42
|
+
workflow = await loadWorkflowTemplate(args.template);
|
|
43
|
+
}
|
|
44
|
+
else if (args.steps) {
|
|
45
|
+
// Create inline workflow
|
|
46
|
+
workflow = createInlineWorkflow(args.task, args.steps);
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
// Default simple workflow
|
|
50
|
+
workflow = createDefaultWorkflow(args.task);
|
|
51
|
+
}
|
|
52
|
+
// Execute workflow
|
|
53
|
+
const result = await executeWorkflow(workflow, args.inputs || {}, log);
|
|
54
|
+
// Format output
|
|
55
|
+
const formatted = formatWorkflowOutput(result, args.format || 'md', workflow);
|
|
56
|
+
// Save if requested
|
|
57
|
+
if (args.saveAs || workflow.output?.saveAs) {
|
|
58
|
+
const savePath = args.saveAs || workflow.output?.saveAs;
|
|
59
|
+
if (savePath) {
|
|
60
|
+
const filePath = path.resolve(savePath);
|
|
61
|
+
await fs.writeFile(filePath, formatted, 'utf8');
|
|
62
|
+
log?.info(`Saved workflow output to: ${filePath}`);
|
|
63
|
+
return `${formatted}\n\n[Saved to: ${filePath}]`;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
return formatted;
|
|
67
|
+
}
|
|
68
|
+
catch (error) {
|
|
69
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
70
|
+
log?.error(`Workflow error: ${errorMessage}`);
|
|
71
|
+
return `[Workflow Error: ${errorMessage}]`;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
async function loadWorkflowTemplate(templatePath) {
|
|
76
|
+
try {
|
|
77
|
+
// Check if it's a built-in template
|
|
78
|
+
const builtInPath = path.join(__dirname, '../../../workflows/templates', `${templatePath}.yaml`);
|
|
79
|
+
const customPath = path.resolve(templatePath);
|
|
80
|
+
let workflowPath = customPath;
|
|
81
|
+
try {
|
|
82
|
+
await fs.access(builtInPath);
|
|
83
|
+
workflowPath = builtInPath;
|
|
84
|
+
}
|
|
85
|
+
catch {
|
|
86
|
+
// Use custom path
|
|
87
|
+
}
|
|
88
|
+
const content = await fs.readFile(workflowPath, 'utf8');
|
|
89
|
+
return yaml.parse(content);
|
|
90
|
+
}
|
|
91
|
+
catch (error) {
|
|
92
|
+
throw new Error(`Failed to load workflow template: ${error instanceof Error ? error.message : String(error)}`);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
function createInlineWorkflow(task, steps) {
|
|
96
|
+
return {
|
|
97
|
+
name: 'inline-workflow',
|
|
98
|
+
description: task,
|
|
99
|
+
steps: steps.map((step, index) => {
|
|
100
|
+
const [action, ...rest] = step.split(':');
|
|
101
|
+
return {
|
|
102
|
+
id: `step_${index + 1}`,
|
|
103
|
+
tool: action.trim(),
|
|
104
|
+
prompt: rest.join(':').trim()
|
|
105
|
+
};
|
|
106
|
+
})
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
function createDefaultWorkflow(task) {
|
|
110
|
+
return {
|
|
111
|
+
name: 'default-workflow',
|
|
112
|
+
description: task,
|
|
113
|
+
steps: [
|
|
114
|
+
{
|
|
115
|
+
id: 'analyze',
|
|
116
|
+
tool: 'ai',
|
|
117
|
+
action: 'analyze',
|
|
118
|
+
prompt: task
|
|
119
|
+
},
|
|
120
|
+
{
|
|
121
|
+
id: 'execute',
|
|
122
|
+
tool: 'ai',
|
|
123
|
+
action: 'generate',
|
|
124
|
+
prompt: `Execute: ${task}\nBased on analysis: {{analyze.output}}`
|
|
125
|
+
}
|
|
126
|
+
]
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
async function executeWorkflow(workflow, inputs, log) {
|
|
130
|
+
const results = { ...inputs };
|
|
131
|
+
const router = new AIRouter();
|
|
132
|
+
for (const step of workflow.steps) {
|
|
133
|
+
log?.info(`Executing step: ${step.id}`);
|
|
134
|
+
// Check condition
|
|
135
|
+
if (step.condition && !evaluateCondition(step.condition, results)) {
|
|
136
|
+
log?.info(`Skipping step ${step.id} due to condition`);
|
|
137
|
+
continue;
|
|
138
|
+
}
|
|
139
|
+
// Resolve variables in step
|
|
140
|
+
const resolvedStep = resolveVariables(step, results);
|
|
141
|
+
// Handle external MCP
|
|
142
|
+
if (step.external_mcp) {
|
|
143
|
+
results[step.id] = {
|
|
144
|
+
output: `[External MCP: ${step.external_mcp} - ${step.action}]`,
|
|
145
|
+
external: true
|
|
146
|
+
};
|
|
147
|
+
continue;
|
|
148
|
+
}
|
|
149
|
+
// Execute based on tool
|
|
150
|
+
let stepResult;
|
|
151
|
+
switch (step.tool) {
|
|
152
|
+
case 'ai':
|
|
153
|
+
case 'analyze':
|
|
154
|
+
case 'generate':
|
|
155
|
+
case 'reason':
|
|
156
|
+
stepResult = await router.route({
|
|
157
|
+
prompt: resolvedStep.prompt || resolvedStep.input || '',
|
|
158
|
+
mode: resolvedStep.action
|
|
159
|
+
});
|
|
160
|
+
break;
|
|
161
|
+
case 'search':
|
|
162
|
+
stepResult = await searchTool.execute({
|
|
163
|
+
query: resolvedStep.query || resolvedStep.prompt || '',
|
|
164
|
+
provider: resolvedStep.provider,
|
|
165
|
+
type: resolvedStep.type
|
|
166
|
+
}, { log });
|
|
167
|
+
break;
|
|
168
|
+
case 'brainstorm':
|
|
169
|
+
stepResult = await brainstormTool.execute({
|
|
170
|
+
topic: resolvedStep.prompt || resolvedStep.topic || '',
|
|
171
|
+
approach: resolvedStep.approach
|
|
172
|
+
}, { log });
|
|
173
|
+
break;
|
|
174
|
+
case 'think':
|
|
175
|
+
stepResult = `[Thinking: ${resolvedStep.thought || resolvedStep.prompt}]`;
|
|
176
|
+
break;
|
|
177
|
+
case 'write_file':
|
|
178
|
+
case 'save':
|
|
179
|
+
const savePath = path.resolve(resolvedStep.path || `output_${step.id}.md`);
|
|
180
|
+
const content = resolvedStep.content || resolvedStep.prompt || '';
|
|
181
|
+
await fs.writeFile(savePath, content, 'utf8');
|
|
182
|
+
stepResult = `Saved to: ${savePath}`;
|
|
183
|
+
break;
|
|
184
|
+
default:
|
|
185
|
+
stepResult = `[Tool ${step.tool} not implemented in consolidated version]`;
|
|
186
|
+
}
|
|
187
|
+
results[step.id] = {
|
|
188
|
+
output: stepResult,
|
|
189
|
+
timestamp: new Date().toISOString()
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
return results;
|
|
193
|
+
}
|
|
194
|
+
function resolveVariables(obj, context) {
|
|
195
|
+
if (typeof obj === 'string') {
|
|
196
|
+
return obj.replace(/\{\{([^}]+)\}\}/g, (match, path) => {
|
|
197
|
+
const keys = path.trim().split('.');
|
|
198
|
+
let value = context;
|
|
199
|
+
for (const key of keys) {
|
|
200
|
+
value = value?.[key];
|
|
201
|
+
}
|
|
202
|
+
return value?.output || value || match;
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
if (typeof obj === 'object' && obj !== null) {
|
|
206
|
+
const resolved = {};
|
|
207
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
208
|
+
resolved[key] = resolveVariables(value, context);
|
|
209
|
+
}
|
|
210
|
+
return resolved;
|
|
211
|
+
}
|
|
212
|
+
return obj;
|
|
213
|
+
}
|
|
214
|
+
function evaluateCondition(condition, context) {
|
|
215
|
+
// Simple condition evaluation
|
|
216
|
+
const resolved = resolveVariables(condition, context);
|
|
217
|
+
return resolved !== 'false' && resolved !== '' && resolved !== null;
|
|
218
|
+
}
|
|
219
|
+
function formatWorkflowOutput(results, format, workflow) {
|
|
220
|
+
if (format === 'json') {
|
|
221
|
+
return JSON.stringify(results, null, 2);
|
|
222
|
+
}
|
|
223
|
+
if (format === 'yaml') {
|
|
224
|
+
return yaml.stringify(results);
|
|
225
|
+
}
|
|
226
|
+
// Markdown format
|
|
227
|
+
let output = `# Workflow: ${workflow.name}\n\n`;
|
|
228
|
+
output += `*${workflow.description}*\n\n`;
|
|
229
|
+
for (const step of workflow.steps) {
|
|
230
|
+
const result = results[step.id];
|
|
231
|
+
if (result) {
|
|
232
|
+
output += `## Step: ${step.id}\n\n`;
|
|
233
|
+
output += result.output || JSON.stringify(result);
|
|
234
|
+
output += '\n\n';
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
return output;
|
|
238
|
+
}
|