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,118 @@
|
|
|
1
|
+
export class TokenTracker {
|
|
2
|
+
constructor() {
|
|
3
|
+
this.metrics = new Map();
|
|
4
|
+
this.modelCosts = new Map([
|
|
5
|
+
['gpt5', 12],
|
|
6
|
+
['gpt5_mini', 8],
|
|
7
|
+
['gpt5_nano', 2],
|
|
8
|
+
['gemini-2.5-pro', 10],
|
|
9
|
+
['gemini-2.5-flash', 2],
|
|
10
|
+
['perplexity-sonar-pro', 6],
|
|
11
|
+
['qwen3-coder-480b', 12],
|
|
12
|
+
['qwq-32b', 10],
|
|
13
|
+
['think', 0],
|
|
14
|
+
]);
|
|
15
|
+
}
|
|
16
|
+
track(stepId, response, model, inputTokens, outputTokens) {
|
|
17
|
+
const input = inputTokens || this.estimateInputTokens(response);
|
|
18
|
+
const output = outputTokens || this.estimateOutputTokens(response);
|
|
19
|
+
const total = input + output;
|
|
20
|
+
const cost = this.calculateCost(model, total);
|
|
21
|
+
const metrics = {
|
|
22
|
+
input,
|
|
23
|
+
output,
|
|
24
|
+
total,
|
|
25
|
+
cost,
|
|
26
|
+
model,
|
|
27
|
+
timestamp: Date.now()
|
|
28
|
+
};
|
|
29
|
+
this.metrics.set(stepId, metrics);
|
|
30
|
+
return metrics;
|
|
31
|
+
}
|
|
32
|
+
getReport() {
|
|
33
|
+
let totalTokens = 0;
|
|
34
|
+
let totalCost = 0;
|
|
35
|
+
const byModel = new Map();
|
|
36
|
+
const byStep = new Map();
|
|
37
|
+
for (const [stepId, metrics] of this.metrics) {
|
|
38
|
+
totalTokens += metrics.total;
|
|
39
|
+
totalCost += metrics.cost;
|
|
40
|
+
byStep.set(stepId, metrics);
|
|
41
|
+
const existing = byModel.get(metrics.model);
|
|
42
|
+
if (existing) {
|
|
43
|
+
byModel.set(metrics.model, {
|
|
44
|
+
...existing,
|
|
45
|
+
input: existing.input + metrics.input,
|
|
46
|
+
output: existing.output + metrics.output,
|
|
47
|
+
total: existing.total + metrics.total,
|
|
48
|
+
cost: existing.cost + metrics.cost
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
byModel.set(metrics.model, { ...metrics });
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
const baselineCost = this.calculateBaselineCost(totalTokens);
|
|
56
|
+
const savings = baselineCost - totalCost;
|
|
57
|
+
const optimizationRate = savings / baselineCost;
|
|
58
|
+
return {
|
|
59
|
+
totalTokens,
|
|
60
|
+
totalCost,
|
|
61
|
+
byModel,
|
|
62
|
+
byStep,
|
|
63
|
+
savings,
|
|
64
|
+
optimizationRate
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
reset() {
|
|
68
|
+
this.metrics.clear();
|
|
69
|
+
}
|
|
70
|
+
estimateInputTokens(response) {
|
|
71
|
+
if (typeof response === 'string') {
|
|
72
|
+
return Math.ceil(response.length / 4);
|
|
73
|
+
}
|
|
74
|
+
if (response && response.prompt) {
|
|
75
|
+
return Math.ceil(response.prompt.length / 4);
|
|
76
|
+
}
|
|
77
|
+
return 100;
|
|
78
|
+
}
|
|
79
|
+
estimateOutputTokens(response) {
|
|
80
|
+
if (typeof response === 'string') {
|
|
81
|
+
return Math.ceil(response.length / 4);
|
|
82
|
+
}
|
|
83
|
+
if (response && response.content) {
|
|
84
|
+
return Math.ceil(response.content.length / 4);
|
|
85
|
+
}
|
|
86
|
+
if (response && response.response) {
|
|
87
|
+
return Math.ceil(response.response.length / 4);
|
|
88
|
+
}
|
|
89
|
+
return 500;
|
|
90
|
+
}
|
|
91
|
+
calculateCost(model, tokens) {
|
|
92
|
+
const costPerMillion = this.modelCosts.get(model) || 5;
|
|
93
|
+
return (tokens / 1000000) * costPerMillion;
|
|
94
|
+
}
|
|
95
|
+
calculateBaselineCost(tokens) {
|
|
96
|
+
const baselineModel = 'gpt5';
|
|
97
|
+
return this.calculateCost(baselineModel, tokens);
|
|
98
|
+
}
|
|
99
|
+
getOptimizationSuggestions() {
|
|
100
|
+
const suggestions = [];
|
|
101
|
+
const report = this.getReport();
|
|
102
|
+
if (report.optimizationRate < 0.5) {
|
|
103
|
+
suggestions.push('Consider using more cost-effective models like gemini-2.5-flash for simple tasks');
|
|
104
|
+
}
|
|
105
|
+
for (const [model, metrics] of report.byModel) {
|
|
106
|
+
if (model !== 'think' && metrics.total > 10000) {
|
|
107
|
+
suggestions.push(`High token usage for ${model}: ${metrics.total} tokens. Consider chunking or summarization.`);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
const expensiveModels = ['gpt5_reason', 'qwen3-coder-480b'];
|
|
111
|
+
for (const model of expensiveModels) {
|
|
112
|
+
if (report.byModel.has(model)) {
|
|
113
|
+
suggestions.push(`Using expensive model ${model}. Ensure it's necessary for the task complexity.`);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
return suggestions;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import { MCPClient } from './mcp-client.js';
|
|
2
|
+
import { WorkflowType } from './types.js';
|
|
3
|
+
import { workflows } from './workflows.js';
|
|
4
|
+
import { PromptEngineerLite } from './prompt-engineer-lite.js';
|
|
5
|
+
export class InstructionOrchestrator {
|
|
6
|
+
constructor() {
|
|
7
|
+
this.mcpClient = new MCPClient();
|
|
8
|
+
this.promptEngineer = new PromptEngineerLite();
|
|
9
|
+
this.workflowTemplates = new Map(Object.entries(workflows));
|
|
10
|
+
}
|
|
11
|
+
async initialize() {
|
|
12
|
+
await this.mcpClient.connect();
|
|
13
|
+
}
|
|
14
|
+
generateOrchestrationPlan(mode, query, context) {
|
|
15
|
+
// Select workflow
|
|
16
|
+
const workflowType = this.analyzeQueryIntent(mode, query);
|
|
17
|
+
const workflow = this.workflowTemplates.get(workflowType);
|
|
18
|
+
if (!workflow) {
|
|
19
|
+
throw new Error(`No workflow found for mode: ${mode}`);
|
|
20
|
+
}
|
|
21
|
+
// Generate instructions for each step
|
|
22
|
+
const instructions = [];
|
|
23
|
+
const toolSequence = [];
|
|
24
|
+
workflow.steps.forEach((step, index) => {
|
|
25
|
+
// Apply prompt engineering
|
|
26
|
+
const enhancedPrompt = this.promptEngineer.applyTechnique(step.tool, step.promptTechnique, query, [] // In real execution, previous results would be passed
|
|
27
|
+
);
|
|
28
|
+
// Map to MCP tool name
|
|
29
|
+
const mcpToolName = this.getToolMapping(step.tool);
|
|
30
|
+
// Generate instruction
|
|
31
|
+
const instruction = this.mcpClient.generateToolInstructions(mcpToolName, { prompt: enhancedPrompt, context, query, thought: enhancedPrompt });
|
|
32
|
+
instructions.push(instruction);
|
|
33
|
+
toolSequence.push(step.tool);
|
|
34
|
+
});
|
|
35
|
+
// Create visual guide
|
|
36
|
+
const visualGuide = this.createVisualGuide(workflow, toolSequence);
|
|
37
|
+
return {
|
|
38
|
+
workflow,
|
|
39
|
+
instructions,
|
|
40
|
+
visualGuide
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
analyzeQueryIntent(mode, query) {
|
|
44
|
+
const modeMap = {
|
|
45
|
+
// Creative modes
|
|
46
|
+
'creative': WorkflowType.CREATIVE_DISCOVERY,
|
|
47
|
+
'brainstorm': WorkflowType.CREATIVE_DISCOVERY,
|
|
48
|
+
'ideate': WorkflowType.CREATIVE_DISCOVERY,
|
|
49
|
+
// Research modes
|
|
50
|
+
'research': WorkflowType.DEEP_RESEARCH,
|
|
51
|
+
'investigate': WorkflowType.DEEP_RESEARCH,
|
|
52
|
+
// Problem solving modes
|
|
53
|
+
'solve': WorkflowType.PROBLEM_SOLVING,
|
|
54
|
+
'analyze': WorkflowType.PROBLEM_SOLVING,
|
|
55
|
+
'reason': WorkflowType.PROBLEM_SOLVING,
|
|
56
|
+
// Synthesis modes
|
|
57
|
+
'synthesis': WorkflowType.SYNTHESIS,
|
|
58
|
+
'integrate': WorkflowType.SYNTHESIS,
|
|
59
|
+
// Fact check modes
|
|
60
|
+
'fact-check': WorkflowType.FACT_CHECK,
|
|
61
|
+
'verify': WorkflowType.FACT_CHECK,
|
|
62
|
+
'validate': WorkflowType.FACT_CHECK,
|
|
63
|
+
};
|
|
64
|
+
return modeMap[mode] || WorkflowType.CREATIVE_DISCOVERY;
|
|
65
|
+
}
|
|
66
|
+
getToolMapping(toolName) {
|
|
67
|
+
const toolMap = {
|
|
68
|
+
'gemini_brainstorm': 'mcp__gemini__gemini-brainstorm',
|
|
69
|
+
'perplexity_research': 'mcp__perplexity-ask__perplexity_research',
|
|
70
|
+
'openai_reason': 'mcp__openai-mcp__openai_gpt5_reason',
|
|
71
|
+
'openai_brainstorm': 'mcp__openai-mcp__openai_brainstorm',
|
|
72
|
+
'think': 'mcp__think-mcp-server__think',
|
|
73
|
+
};
|
|
74
|
+
return toolMap[toolName] || toolName;
|
|
75
|
+
}
|
|
76
|
+
createVisualGuide(workflow, tools) {
|
|
77
|
+
const guide = [
|
|
78
|
+
`## ${workflow.name} Orchestration Plan`,
|
|
79
|
+
'',
|
|
80
|
+
'### Execution Sequence:',
|
|
81
|
+
...tools.map((tool, i) => `${i + 1}. **${tool}** - ${this.getStepDescription(workflow.steps[i])}`),
|
|
82
|
+
'',
|
|
83
|
+
'### Visual Flow:',
|
|
84
|
+
'```',
|
|
85
|
+
tools.map(t => t.substring(0, 8)).join(' → '),
|
|
86
|
+
'```',
|
|
87
|
+
'',
|
|
88
|
+
'### Instructions for Claude:',
|
|
89
|
+
'1. Execute each tool in sequence',
|
|
90
|
+
'2. Pass results from each step to inform the next',
|
|
91
|
+
'3. After all tools complete, synthesize the insights',
|
|
92
|
+
'',
|
|
93
|
+
'💡 **Tip**: You can call focus again with `mode="reflect"` to synthesize all results'
|
|
94
|
+
];
|
|
95
|
+
return guide.join('\n');
|
|
96
|
+
}
|
|
97
|
+
getStepDescription(step) {
|
|
98
|
+
const descriptions = {
|
|
99
|
+
'what_if_speculation': 'Explore wild possibilities',
|
|
100
|
+
'alternative_perspectives': 'Multiple viewpoints',
|
|
101
|
+
'comprehensive_investigation': 'Deep research',
|
|
102
|
+
'evidence_gathering': 'Find supporting data',
|
|
103
|
+
'systematic_analysis': 'Structured analysis',
|
|
104
|
+
'first_principles': 'Fundamental reasoning',
|
|
105
|
+
'quick_reflection': 'Pattern recognition',
|
|
106
|
+
'innovative_solutions': 'Creative solutions'
|
|
107
|
+
};
|
|
108
|
+
return descriptions[step.promptTechnique] || step.promptTechnique;
|
|
109
|
+
}
|
|
110
|
+
// Generate a formatted instruction set for display
|
|
111
|
+
formatInstructions(plan) {
|
|
112
|
+
const formatted = [
|
|
113
|
+
plan.visualGuide,
|
|
114
|
+
'',
|
|
115
|
+
'### Ready to Execute:',
|
|
116
|
+
''
|
|
117
|
+
];
|
|
118
|
+
plan.instructions.forEach((inst, i) => {
|
|
119
|
+
formatted.push(`#### Step ${i + 1}: ${inst.description}`);
|
|
120
|
+
formatted.push('```');
|
|
121
|
+
formatted.push(`Tool: ${inst.tool}`);
|
|
122
|
+
formatted.push(`Parameters: ${JSON.stringify(inst.parameters, null, 2)}`);
|
|
123
|
+
formatted.push('```');
|
|
124
|
+
formatted.push('');
|
|
125
|
+
});
|
|
126
|
+
return formatted.join('\n');
|
|
127
|
+
}
|
|
128
|
+
}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import { MCPClient } from './mcp-client.js';
|
|
2
|
+
import { WorkflowType, ToolStatus } from './types.js';
|
|
3
|
+
import { workflows } from './workflows.js';
|
|
4
|
+
import { PromptEngineer } from './prompt-engineer.js';
|
|
5
|
+
import { PromptEngineerLite } from './prompt-engineer-lite.js';
|
|
6
|
+
import { WorkflowVisualizer } from './visualizer.js';
|
|
7
|
+
import { WorkflowVisualizerLite } from './visualizer-lite.js';
|
|
8
|
+
export class FocusOrchestratorLite {
|
|
9
|
+
constructor(options = {}) {
|
|
10
|
+
this.tokenEfficient = options.tokenEfficient ?? false;
|
|
11
|
+
this.mcpClient = new MCPClient();
|
|
12
|
+
// Use lite versions if token efficient mode
|
|
13
|
+
if (this.tokenEfficient) {
|
|
14
|
+
this.promptEngineer = new PromptEngineerLite();
|
|
15
|
+
this.visualizer = new WorkflowVisualizerLite();
|
|
16
|
+
}
|
|
17
|
+
else {
|
|
18
|
+
this.promptEngineer = new PromptEngineer();
|
|
19
|
+
this.visualizer = new WorkflowVisualizer();
|
|
20
|
+
}
|
|
21
|
+
this.workflowTemplates = new Map(Object.entries(workflows));
|
|
22
|
+
}
|
|
23
|
+
async initialize() {
|
|
24
|
+
await this.mcpClient.connect();
|
|
25
|
+
}
|
|
26
|
+
selectWorkflow(mode, query) {
|
|
27
|
+
const workflowType = this.analyzeQueryIntent(mode, query);
|
|
28
|
+
const workflow = this.workflowTemplates.get(workflowType);
|
|
29
|
+
if (!workflow) {
|
|
30
|
+
throw new Error(`No workflow found for type: ${workflowType}`);
|
|
31
|
+
}
|
|
32
|
+
return workflow;
|
|
33
|
+
}
|
|
34
|
+
analyzeQueryIntent(mode, query) {
|
|
35
|
+
const modeMap = {
|
|
36
|
+
'creative': WorkflowType.CREATIVE_DISCOVERY,
|
|
37
|
+
'research': WorkflowType.DEEP_RESEARCH,
|
|
38
|
+
'solve': WorkflowType.PROBLEM_SOLVING,
|
|
39
|
+
'synthesis': WorkflowType.SYNTHESIS,
|
|
40
|
+
'brainstorm': WorkflowType.CREATIVE_DISCOVERY,
|
|
41
|
+
'reason': WorkflowType.PROBLEM_SOLVING,
|
|
42
|
+
};
|
|
43
|
+
return modeMap[mode] || WorkflowType.CREATIVE_DISCOVERY;
|
|
44
|
+
}
|
|
45
|
+
async executeWorkflow(workflow, query, context) {
|
|
46
|
+
const results = [];
|
|
47
|
+
const startTime = Date.now();
|
|
48
|
+
await this.visualizer.renderWorkflow(workflow, new Map());
|
|
49
|
+
for (const [index, step] of workflow.steps.entries()) {
|
|
50
|
+
await this.visualizer.updateProgress(step.tool, ToolStatus.PROCESSING);
|
|
51
|
+
try {
|
|
52
|
+
const enhancedPrompt = this.promptEngineer.applyTechnique(step.tool, step.promptTechnique, query, results);
|
|
53
|
+
const result = await this.executeTool(step.tool, enhancedPrompt, context);
|
|
54
|
+
results.push({
|
|
55
|
+
tool: step.tool,
|
|
56
|
+
output: result,
|
|
57
|
+
timestamp: Date.now(),
|
|
58
|
+
duration: Date.now() - startTime
|
|
59
|
+
});
|
|
60
|
+
await this.visualizer.updateProgress(step.tool, ToolStatus.COMPLETE);
|
|
61
|
+
if (step.adaptationCheck && this.shouldAdapt(result)) {
|
|
62
|
+
await this.adaptWorkflow(workflow, results, index);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
catch (error) {
|
|
66
|
+
await this.visualizer.updateProgress(step.tool, ToolStatus.ERROR);
|
|
67
|
+
if (step.optional) {
|
|
68
|
+
console.error(`Optional tool ${step.tool} failed:`, error);
|
|
69
|
+
continue;
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
throw error;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
const synthesis = await this.synthesizeResults(results, workflow);
|
|
77
|
+
await this.visualizer.showCompletion(workflow, results);
|
|
78
|
+
return synthesis;
|
|
79
|
+
}
|
|
80
|
+
async executeTool(toolName, prompt, context) {
|
|
81
|
+
const toolMap = {
|
|
82
|
+
'gemini_brainstorm': 'mcp__gemini__gemini-brainstorm',
|
|
83
|
+
'perplexity_research': 'mcp__perplexity-ask__perplexity_research',
|
|
84
|
+
'openai_reason': 'mcp__openai-mcp__openai_gpt5_reason',
|
|
85
|
+
'openai_brainstorm': 'mcp__openai-mcp__openai_brainstorm',
|
|
86
|
+
'think': 'mcp__think-mcp-server__think',
|
|
87
|
+
};
|
|
88
|
+
const mcpToolName = toolMap[toolName] || toolName;
|
|
89
|
+
return await this.mcpClient.executeTool(mcpToolName, {
|
|
90
|
+
prompt,
|
|
91
|
+
context,
|
|
92
|
+
query: prompt,
|
|
93
|
+
thought: prompt,
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
shouldAdapt(result) {
|
|
97
|
+
return result.includes('insufficient data') ||
|
|
98
|
+
result.includes('need more information') ||
|
|
99
|
+
result.length < 100;
|
|
100
|
+
}
|
|
101
|
+
async adaptWorkflow(workflow, results, currentIndex) {
|
|
102
|
+
if (results.some(r => r.output.includes('insufficient data'))) {
|
|
103
|
+
workflow.steps.splice(currentIndex + 1, 0, {
|
|
104
|
+
tool: 'perplexity_research',
|
|
105
|
+
promptTechnique: 'evidence_gathering',
|
|
106
|
+
optional: true
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
async synthesizeResults(results, workflow) {
|
|
111
|
+
if (this.tokenEfficient) {
|
|
112
|
+
// Compact synthesis for token efficiency
|
|
113
|
+
const insights = results.map(r => `${r.tool}: ${r.output.split('\n')[0].substring(0, 100)}...`).join('\n');
|
|
114
|
+
return `## ${workflow.name}\n${insights}\n\nDuration: ${(results[results.length - 1].duration / 1000).toFixed(1)}s`;
|
|
115
|
+
}
|
|
116
|
+
// Full synthesis (original code)
|
|
117
|
+
const synthesis = [`## ${workflow.name} Results\n`];
|
|
118
|
+
synthesis.push(`**Duration**: ${results[results.length - 1].duration}ms`);
|
|
119
|
+
synthesis.push(`**Tools**: ${results.map(r => r.tool).join(' → ')}\n`);
|
|
120
|
+
synthesis.push('### Key Insights\n');
|
|
121
|
+
for (const result of results) {
|
|
122
|
+
const keyPoints = this.extractKeyPoints(result.output, result.tool);
|
|
123
|
+
if (keyPoints.length > 0) {
|
|
124
|
+
synthesis.push(`**${result.tool}:**`);
|
|
125
|
+
keyPoints.forEach(point => synthesis.push(`- ${point}`));
|
|
126
|
+
synthesis.push('');
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
return synthesis.join('\n');
|
|
130
|
+
}
|
|
131
|
+
extractKeyPoints(output, tool) {
|
|
132
|
+
const points = [];
|
|
133
|
+
const bulletPoints = output.match(/^[-*•]\s+(.+)$/gm);
|
|
134
|
+
if (bulletPoints) {
|
|
135
|
+
points.push(...bulletPoints.map(p => p.replace(/^[-*•]\s+/, '')));
|
|
136
|
+
}
|
|
137
|
+
return points.slice(0, 3);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
import { MCPClient } from './mcp-client.js';
|
|
2
|
+
import { WorkflowType, ToolStatus } from './types.js';
|
|
3
|
+
import { workflows } from './workflows.js';
|
|
4
|
+
import { PromptEngineer } from './prompt-engineer.js';
|
|
5
|
+
import { WorkflowVisualizer } from './visualizer.js';
|
|
6
|
+
export class FocusOrchestrator {
|
|
7
|
+
constructor() {
|
|
8
|
+
this.mcpClient = new MCPClient();
|
|
9
|
+
this.promptEngineer = new PromptEngineer();
|
|
10
|
+
this.visualizer = new WorkflowVisualizer();
|
|
11
|
+
this.workflowTemplates = new Map(Object.entries(workflows));
|
|
12
|
+
}
|
|
13
|
+
async initialize() {
|
|
14
|
+
await this.mcpClient.connect();
|
|
15
|
+
}
|
|
16
|
+
selectWorkflow(mode, query) {
|
|
17
|
+
// Intelligent workflow selection based on mode and query analysis
|
|
18
|
+
const workflowType = this.analyzeQueryIntent(mode, query);
|
|
19
|
+
const workflow = this.workflowTemplates.get(workflowType);
|
|
20
|
+
if (!workflow) {
|
|
21
|
+
throw new Error(`No workflow found for type: ${workflowType}`);
|
|
22
|
+
}
|
|
23
|
+
return workflow;
|
|
24
|
+
}
|
|
25
|
+
analyzeQueryIntent(mode, query) {
|
|
26
|
+
// Simple mapping for now, can be enhanced with NLP
|
|
27
|
+
const modeMap = {
|
|
28
|
+
'creative': WorkflowType.CREATIVE_DISCOVERY,
|
|
29
|
+
'research': WorkflowType.DEEP_RESEARCH,
|
|
30
|
+
'solve': WorkflowType.PROBLEM_SOLVING,
|
|
31
|
+
'synthesis': WorkflowType.SYNTHESIS,
|
|
32
|
+
'brainstorm': WorkflowType.CREATIVE_DISCOVERY,
|
|
33
|
+
'reason': WorkflowType.PROBLEM_SOLVING,
|
|
34
|
+
};
|
|
35
|
+
return modeMap[mode] || WorkflowType.CREATIVE_DISCOVERY;
|
|
36
|
+
}
|
|
37
|
+
async executeWorkflow(workflow, query, context) {
|
|
38
|
+
const results = [];
|
|
39
|
+
const startTime = Date.now();
|
|
40
|
+
// Show initial workflow visualization
|
|
41
|
+
await this.visualizer.renderWorkflow(workflow, new Map());
|
|
42
|
+
// Execute each step in the workflow
|
|
43
|
+
for (const [index, step] of workflow.steps.entries()) {
|
|
44
|
+
// Update visual progress
|
|
45
|
+
await this.visualizer.updateProgress(step.tool, ToolStatus.PROCESSING);
|
|
46
|
+
try {
|
|
47
|
+
// Apply prompt engineering for this tool
|
|
48
|
+
const enhancedPrompt = this.promptEngineer.applyTechnique(step.tool, step.promptTechnique, query, results // Pass previous results for context
|
|
49
|
+
);
|
|
50
|
+
// Execute the tool
|
|
51
|
+
const result = await this.executeTool(step.tool, enhancedPrompt, context);
|
|
52
|
+
results.push({
|
|
53
|
+
tool: step.tool,
|
|
54
|
+
output: result,
|
|
55
|
+
timestamp: Date.now(),
|
|
56
|
+
duration: Date.now() - startTime
|
|
57
|
+
});
|
|
58
|
+
// Update visual progress
|
|
59
|
+
await this.visualizer.updateProgress(step.tool, ToolStatus.COMPLETE);
|
|
60
|
+
// Check if we should adapt the workflow based on results
|
|
61
|
+
if (step.adaptationCheck) {
|
|
62
|
+
const shouldAdapt = await this.evaluateAdaptation(result, step);
|
|
63
|
+
if (shouldAdapt) {
|
|
64
|
+
await this.adaptWorkflow(workflow, results, index);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
catch (error) {
|
|
69
|
+
await this.visualizer.updateProgress(step.tool, ToolStatus.ERROR);
|
|
70
|
+
// Handle errors gracefully
|
|
71
|
+
if (step.optional) {
|
|
72
|
+
console.error(`Optional tool ${step.tool} failed:`, error);
|
|
73
|
+
continue;
|
|
74
|
+
}
|
|
75
|
+
else {
|
|
76
|
+
throw error;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
// Synthesize all results
|
|
81
|
+
const synthesis = await this.synthesizeResults(results, workflow);
|
|
82
|
+
// Show completion
|
|
83
|
+
await this.visualizer.showCompletion(workflow, results);
|
|
84
|
+
return synthesis;
|
|
85
|
+
}
|
|
86
|
+
async executeTool(toolName, prompt, context) {
|
|
87
|
+
// Map internal tool names to MCP tool names
|
|
88
|
+
const toolMap = {
|
|
89
|
+
'gemini_brainstorm': 'mcp__gemini__gemini-brainstorm',
|
|
90
|
+
'perplexity_research': 'mcp__perplexity-ask__perplexity_research',
|
|
91
|
+
'openai_reason': 'mcp__openai-mcp__openai_gpt5_reason',
|
|
92
|
+
'openai_brainstorm': 'mcp__openai-mcp__openai_brainstorm',
|
|
93
|
+
'think': 'mcp__think-mcp-server__think',
|
|
94
|
+
};
|
|
95
|
+
const mcpToolName = toolMap[toolName] || toolName;
|
|
96
|
+
// Execute via MCP client
|
|
97
|
+
return await this.mcpClient.executeTool(mcpToolName, {
|
|
98
|
+
prompt,
|
|
99
|
+
context,
|
|
100
|
+
query: prompt, // Some tools use 'query' instead of 'prompt'
|
|
101
|
+
thought: prompt, // think-mcp uses 'thought'
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
async evaluateAdaptation(result, step) {
|
|
105
|
+
// Simple heuristics for workflow adaptation
|
|
106
|
+
// Can be enhanced with more sophisticated logic
|
|
107
|
+
if (result.includes('insufficient data') || result.includes('need more information')) {
|
|
108
|
+
return true;
|
|
109
|
+
}
|
|
110
|
+
if (step.adaptationThreshold && result.length < step.adaptationThreshold) {
|
|
111
|
+
return true;
|
|
112
|
+
}
|
|
113
|
+
return false;
|
|
114
|
+
}
|
|
115
|
+
async adaptWorkflow(workflow, results, currentIndex) {
|
|
116
|
+
// Add additional research step if needed
|
|
117
|
+
if (results.some(r => r.output.includes('insufficient data'))) {
|
|
118
|
+
workflow.steps.splice(currentIndex + 1, 0, {
|
|
119
|
+
tool: 'perplexity_research',
|
|
120
|
+
promptTechnique: 'deep_investigation',
|
|
121
|
+
optional: true
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
async synthesizeResults(results, workflow) {
|
|
126
|
+
// Create a comprehensive synthesis of all tool outputs
|
|
127
|
+
const synthesis = [`## ${workflow.name} Results\n`];
|
|
128
|
+
// Add workflow metadata
|
|
129
|
+
synthesis.push(`**Workflow Duration**: ${results[results.length - 1].duration}ms`);
|
|
130
|
+
synthesis.push(`**Tools Used**: ${results.map(r => r.tool).join(' → ')}\n`);
|
|
131
|
+
// Key insights section
|
|
132
|
+
synthesis.push('### Key Insights\n');
|
|
133
|
+
// Extract key points from each tool result
|
|
134
|
+
for (const result of results) {
|
|
135
|
+
const keyPoints = this.extractKeyPoints(result.output, result.tool);
|
|
136
|
+
if (keyPoints.length > 0) {
|
|
137
|
+
synthesis.push(`**From ${result.tool}:**`);
|
|
138
|
+
keyPoints.forEach(point => synthesis.push(`- ${point}`));
|
|
139
|
+
synthesis.push('');
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
// Synthesis section
|
|
143
|
+
synthesis.push('### Synthesis\n');
|
|
144
|
+
// Use think-mcp for final synthesis if available
|
|
145
|
+
if (this.mcpClient.hasTools(['mcp__think-mcp-server__think'])) {
|
|
146
|
+
const synthesisPrompt = `Synthesize these insights into a coherent conclusion:\n${results.map(r => `${r.tool}: ${this.summarize(r.output)}`).join('\n')}`;
|
|
147
|
+
const finalThought = await this.executeTool('think', synthesisPrompt);
|
|
148
|
+
synthesis.push(finalThought);
|
|
149
|
+
}
|
|
150
|
+
else {
|
|
151
|
+
// Fallback synthesis
|
|
152
|
+
synthesis.push(this.createFallbackSynthesis(results));
|
|
153
|
+
}
|
|
154
|
+
return synthesis.join('\n');
|
|
155
|
+
}
|
|
156
|
+
extractKeyPoints(output, tool) {
|
|
157
|
+
// Extract key points based on tool type
|
|
158
|
+
const points = [];
|
|
159
|
+
// Look for bullet points
|
|
160
|
+
const bulletPoints = output.match(/^[-*•]\s+(.+)$/gm);
|
|
161
|
+
if (bulletPoints) {
|
|
162
|
+
points.push(...bulletPoints.map(p => p.replace(/^[-*•]\s+/, '')));
|
|
163
|
+
}
|
|
164
|
+
// Look for numbered lists
|
|
165
|
+
const numberedPoints = output.match(/^\d+\.\s+(.+)$/gm);
|
|
166
|
+
if (numberedPoints) {
|
|
167
|
+
points.push(...numberedPoints.map(p => p.replace(/^\d+\.\s+/, '')));
|
|
168
|
+
}
|
|
169
|
+
// Tool-specific extraction
|
|
170
|
+
if (tool === 'gemini_brainstorm' && points.length === 0) {
|
|
171
|
+
// Extract creative ideas
|
|
172
|
+
const ideas = output.match(/(?:idea|concept|possibility):\s*([^.!?]+[.!?])/gi);
|
|
173
|
+
if (ideas) {
|
|
174
|
+
points.push(...ideas.map(i => i.replace(/^(?:idea|concept|possibility):\s*/i, '')));
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
return points.slice(0, 3); // Limit to top 3 points per tool
|
|
178
|
+
}
|
|
179
|
+
summarize(text, maxLength = 200) {
|
|
180
|
+
// Simple summarization - take first paragraph or N characters
|
|
181
|
+
const firstParagraph = text.split('\n\n')[0];
|
|
182
|
+
if (firstParagraph.length <= maxLength) {
|
|
183
|
+
return firstParagraph;
|
|
184
|
+
}
|
|
185
|
+
return firstParagraph.substring(0, maxLength) + '...';
|
|
186
|
+
}
|
|
187
|
+
createFallbackSynthesis(results) {
|
|
188
|
+
const insights = results.map(r => this.summarize(r.output, 100));
|
|
189
|
+
return `Based on the analysis from ${results.length} different perspectives:\n\n${insights.join('\n\n')}\n\nThese insights suggest a multi-faceted understanding of the query.`;
|
|
190
|
+
}
|
|
191
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Model Provider Registry
|
|
3
|
+
* Maps model names to tool names and providers
|
|
4
|
+
* Replaces hard-coded switch statements
|
|
5
|
+
*/
|
|
6
|
+
export class ModelProviderRegistry {
|
|
7
|
+
constructor() {
|
|
8
|
+
this.mappings = new Map();
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Register a model mapping
|
|
12
|
+
*/
|
|
13
|
+
register(mapping) {
|
|
14
|
+
// Register primary name
|
|
15
|
+
this.mappings.set(mapping.modelName.toLowerCase(), mapping);
|
|
16
|
+
// Register aliases
|
|
17
|
+
if (mapping.aliases) {
|
|
18
|
+
mapping.aliases.forEach(alias => {
|
|
19
|
+
this.mappings.set(alias.toLowerCase(), mapping);
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Register multiple mappings at once
|
|
25
|
+
*/
|
|
26
|
+
registerMany(mappings) {
|
|
27
|
+
mappings.forEach(m => this.register(m));
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Get tool name for a model
|
|
31
|
+
* Returns null if no mapping found
|
|
32
|
+
*/
|
|
33
|
+
getToolName(modelName) {
|
|
34
|
+
const mapping = this.mappings.get(modelName.toLowerCase());
|
|
35
|
+
return mapping?.toolName || null;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Get provider for a model
|
|
39
|
+
* Returns "unknown" if no mapping found
|
|
40
|
+
*/
|
|
41
|
+
getProvider(modelName) {
|
|
42
|
+
const mapping = this.mappings.get(modelName.toLowerCase());
|
|
43
|
+
return mapping?.provider || "unknown";
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Get full mapping for a model
|
|
47
|
+
*/
|
|
48
|
+
getMapping(modelName) {
|
|
49
|
+
return this.mappings.get(modelName.toLowerCase()) || null;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Check if a model is registered
|
|
53
|
+
*/
|
|
54
|
+
hasModel(modelName) {
|
|
55
|
+
return this.mappings.has(modelName.toLowerCase());
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Get all registered model names
|
|
59
|
+
*/
|
|
60
|
+
getRegisteredModels() {
|
|
61
|
+
const models = new Set();
|
|
62
|
+
this.mappings.forEach(mapping => {
|
|
63
|
+
models.add(mapping.modelName);
|
|
64
|
+
});
|
|
65
|
+
return Array.from(models);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
// Singleton instance with default mappings
|
|
69
|
+
export const modelProviderRegistry = new ModelProviderRegistry();
|
|
70
|
+
// Register default model mappings (extracted from CollaborativeOrchestrator)
|
|
71
|
+
modelProviderRegistry.registerMany([
|
|
72
|
+
// Qwen models
|
|
73
|
+
{ modelName: "qwen", toolName: "qwen_coder", provider: "openrouter" },
|
|
74
|
+
{ modelName: "qwen-coder", toolName: "qwen_coder", provider: "openrouter" },
|
|
75
|
+
{ modelName: "qwq", toolName: "qwq_reason", provider: "openrouter" },
|
|
76
|
+
// Grok models
|
|
77
|
+
{ modelName: "grok", toolName: "grok_reason", provider: "x.ai" },
|
|
78
|
+
{ modelName: "grok-4", toolName: "grok_reason", provider: "x.ai", aliases: ["grok-4-0709"] },
|
|
79
|
+
// Claude models
|
|
80
|
+
{ modelName: "claude", toolName: "think", provider: "anthropic", aliases: ["claude-code", "reasoning", "analysis"] },
|
|
81
|
+
// Gemini models
|
|
82
|
+
{ modelName: "gemini", toolName: "gemini_query", provider: "google", aliases: ["gemini-pro", "gemini-2.5-pro"] },
|
|
83
|
+
{ modelName: "gemini-2.5-flash", toolName: "gemini_analyze_text", provider: "google", aliases: ["gemini-2.5-flash-lite"] },
|
|
84
|
+
// Perplexity models
|
|
85
|
+
{ modelName: "perplexity", toolName: "perplexity_ask", provider: "perplexity" },
|
|
86
|
+
{ modelName: "perplexity-reason", toolName: "perplexity_reason", provider: "perplexity" },
|
|
87
|
+
// OpenAI models
|
|
88
|
+
{ modelName: "openai", toolName: "openai_brainstorm", provider: "openai", aliases: ["openai-gpt5", "openai-gpt5-nano"] },
|
|
89
|
+
{ modelName: "gpt5", toolName: "gpt5_reason", provider: "openai", aliases: ["gpt-5"] },
|
|
90
|
+
{ modelName: "gpt5-mini", toolName: "gpt5_mini_reason", provider: "openai", aliases: ["gpt-5-mini"] },
|
|
91
|
+
// Kimi models (Moonshot AI)
|
|
92
|
+
{ modelName: "kimi", toolName: "kimi_thinking", provider: "openrouter", aliases: ["kimi-k2", "kimi-k2-thinking", "kimi-thinking"] },
|
|
93
|
+
// Think tool
|
|
94
|
+
{ modelName: "think", toolName: "think", provider: "anthropic" }
|
|
95
|
+
]);
|