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,294 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Perplexity Tools Implementation
|
|
3
|
+
* Provides web search and reasoning capabilities
|
|
4
|
+
* No need for separate perplexity-mcp server
|
|
5
|
+
*/
|
|
6
|
+
import { z } from "zod";
|
|
7
|
+
// Perplexity API configuration
|
|
8
|
+
const PERPLEXITY_API_URL = "https://api.perplexity.ai";
|
|
9
|
+
// Function to get the API key (deferred reading)
|
|
10
|
+
function getPerplexityApiKey() {
|
|
11
|
+
return process.env.PERPLEXITY_API_KEY;
|
|
12
|
+
}
|
|
13
|
+
// Debug logging function - call when needed
|
|
14
|
+
function debugApiKey() {
|
|
15
|
+
const apiKey = getPerplexityApiKey();
|
|
16
|
+
console.error('[PERPLEXITY DEBUG] API Key present:', !!apiKey);
|
|
17
|
+
if (apiKey) {
|
|
18
|
+
console.error('[PERPLEXITY DEBUG] Key length:', apiKey.length);
|
|
19
|
+
console.error('[PERPLEXITY DEBUG] Key prefix:', apiKey.substring(0, 8) + '...');
|
|
20
|
+
}
|
|
21
|
+
else {
|
|
22
|
+
console.error('[PERPLEXITY DEBUG] process.env keys:', Object.keys(process.env).filter(k => k.includes('PERP') || k.includes('API')));
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
// Available Perplexity models (2025 latest)
|
|
26
|
+
export var PerplexityModel;
|
|
27
|
+
(function (PerplexityModel) {
|
|
28
|
+
// Models from Perplexity API docs
|
|
29
|
+
PerplexityModel["SONAR_PRO"] = "sonar";
|
|
30
|
+
PerplexityModel["SONAR_REASONING_PRO"] = "sonar-reasoning";
|
|
31
|
+
PerplexityModel["SONAR_DEEP_RESEARCH"] = "sonar-deep-research";
|
|
32
|
+
PerplexityModel["SONAR"] = "sonar";
|
|
33
|
+
PerplexityModel["SONAR_SMALL"] = "sonar-small";
|
|
34
|
+
})(PerplexityModel || (PerplexityModel = {}));
|
|
35
|
+
/**
|
|
36
|
+
* Call Perplexity API
|
|
37
|
+
*/
|
|
38
|
+
export async function callPerplexity(messages, model = PerplexityModel.SONAR_PRO, searchDomain, searchRecency) {
|
|
39
|
+
const apiKey = getPerplexityApiKey();
|
|
40
|
+
if (!apiKey) {
|
|
41
|
+
debugApiKey(); // Log debug info when key is missing
|
|
42
|
+
return `[Perplexity API key not configured. Add PERPLEXITY_API_KEY to .env file]`;
|
|
43
|
+
}
|
|
44
|
+
try {
|
|
45
|
+
const url = `${PERPLEXITY_API_URL}/chat/completions`;
|
|
46
|
+
const requestBody = {
|
|
47
|
+
model,
|
|
48
|
+
messages,
|
|
49
|
+
temperature: 0.2,
|
|
50
|
+
max_tokens: 16384, // Increased for comprehensive research responses
|
|
51
|
+
return_citations: true,
|
|
52
|
+
return_images: false
|
|
53
|
+
};
|
|
54
|
+
// Add search filters if provided
|
|
55
|
+
if (searchDomain) {
|
|
56
|
+
requestBody.search_domain = searchDomain;
|
|
57
|
+
}
|
|
58
|
+
if (searchRecency) {
|
|
59
|
+
requestBody.search_recency = searchRecency;
|
|
60
|
+
}
|
|
61
|
+
const response = await fetch(url, {
|
|
62
|
+
method: "POST",
|
|
63
|
+
headers: {
|
|
64
|
+
"Authorization": `Bearer ${apiKey}`,
|
|
65
|
+
"Content-Type": "application/json"
|
|
66
|
+
},
|
|
67
|
+
body: JSON.stringify(requestBody)
|
|
68
|
+
});
|
|
69
|
+
if (!response.ok) {
|
|
70
|
+
throw new Error(`Perplexity API error: ${response.statusText}`);
|
|
71
|
+
}
|
|
72
|
+
const data = await response.json();
|
|
73
|
+
// Extract the response and citations
|
|
74
|
+
let result = data.choices?.[0]?.message?.content || "No response from Perplexity";
|
|
75
|
+
// Add sources if available (Perplexity API changed from citations to search_results in 2025)
|
|
76
|
+
if (data.search_results && data.search_results.length > 0) {
|
|
77
|
+
result += "\n\n**Sources:**\n";
|
|
78
|
+
data.search_results.forEach((source, idx) => {
|
|
79
|
+
result += `${idx + 1}. ${source.title || 'Untitled'} - ${source.url}`;
|
|
80
|
+
if (source.date)
|
|
81
|
+
result += ` (${source.date})`;
|
|
82
|
+
result += '\n';
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
return result;
|
|
86
|
+
}
|
|
87
|
+
catch (error) {
|
|
88
|
+
return `[Perplexity error: ${error instanceof Error ? error.message : String(error)}]`;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Perplexity Ask Tool
|
|
93
|
+
* Search the web and retrieve up-to-date information
|
|
94
|
+
*/
|
|
95
|
+
export const perplexityAskTool = {
|
|
96
|
+
name: "perplexity_ask",
|
|
97
|
+
description: "Web search",
|
|
98
|
+
parameters: z.object({
|
|
99
|
+
query: z.string(),
|
|
100
|
+
searchDomain: z.enum(["general", "academic", "news", "social"]).optional(),
|
|
101
|
+
searchRecency: z.enum(["hour", "day", "week", "month", "year"]).optional()
|
|
102
|
+
}),
|
|
103
|
+
execute: async (args, { log }) => {
|
|
104
|
+
const messages = [
|
|
105
|
+
{
|
|
106
|
+
role: "system",
|
|
107
|
+
content: "You are a helpful research assistant. Provide accurate, up-to-date information with sources."
|
|
108
|
+
},
|
|
109
|
+
{
|
|
110
|
+
role: "user",
|
|
111
|
+
content: args.query
|
|
112
|
+
}
|
|
113
|
+
];
|
|
114
|
+
return await callPerplexity(messages, PerplexityModel.SONAR_PRO, args.searchDomain, args.searchRecency);
|
|
115
|
+
}
|
|
116
|
+
};
|
|
117
|
+
/**
|
|
118
|
+
* Perplexity Research Tool
|
|
119
|
+
* Deep research with multiple queries and synthesis
|
|
120
|
+
*/
|
|
121
|
+
export const perplexityResearchTool = {
|
|
122
|
+
name: "perplexity_research",
|
|
123
|
+
description: "Deep research",
|
|
124
|
+
parameters: z.object({
|
|
125
|
+
topic: z.string(),
|
|
126
|
+
questions: z.array(z.string()).optional(),
|
|
127
|
+
depth: z.enum(["quick", "standard", "deep"]).optional()
|
|
128
|
+
}),
|
|
129
|
+
execute: async (args, { log }) => {
|
|
130
|
+
const { topic, questions, depth = "standard" } = args;
|
|
131
|
+
// Generate research questions if not provided
|
|
132
|
+
const researchQuestions = questions || [
|
|
133
|
+
`What is the current state of ${topic}?`,
|
|
134
|
+
`What are the latest developments in ${topic}?`,
|
|
135
|
+
`What are the key challenges and opportunities in ${topic}?`,
|
|
136
|
+
`What do experts say about ${topic}?`
|
|
137
|
+
];
|
|
138
|
+
// Adjust based on depth
|
|
139
|
+
const questionsToAsk = depth === "quick" ?
|
|
140
|
+
researchQuestions.slice(0, 2) :
|
|
141
|
+
depth === "deep" ?
|
|
142
|
+
[...researchQuestions,
|
|
143
|
+
`What are the future predictions for ${topic}?`,
|
|
144
|
+
`What are the best practices and recommendations for ${topic}?`] :
|
|
145
|
+
researchQuestions;
|
|
146
|
+
let research = `# Research Report: ${topic}\n\n`;
|
|
147
|
+
// Conduct research for each question
|
|
148
|
+
for (const question of questionsToAsk) {
|
|
149
|
+
const messages = [
|
|
150
|
+
{
|
|
151
|
+
role: "system",
|
|
152
|
+
content: "You are a research expert. Provide detailed, factual information with sources."
|
|
153
|
+
},
|
|
154
|
+
{
|
|
155
|
+
role: "user",
|
|
156
|
+
content: question
|
|
157
|
+
}
|
|
158
|
+
];
|
|
159
|
+
const answer = await callPerplexity(messages, PerplexityModel.SONAR_PRO);
|
|
160
|
+
research += `## ${question}\n\n${answer}\n\n`;
|
|
161
|
+
}
|
|
162
|
+
// Add synthesis
|
|
163
|
+
const synthesisMessages = [
|
|
164
|
+
{
|
|
165
|
+
role: "system",
|
|
166
|
+
content: "You are a research synthesizer. Create a concise summary of the key findings."
|
|
167
|
+
},
|
|
168
|
+
{
|
|
169
|
+
role: "user",
|
|
170
|
+
content: `Synthesize these research findings into key insights:\n\n${research}`
|
|
171
|
+
}
|
|
172
|
+
];
|
|
173
|
+
const synthesis = await callPerplexity(synthesisMessages, PerplexityModel.SONAR_PRO);
|
|
174
|
+
research += `## Synthesis\n\n${synthesis}`;
|
|
175
|
+
return research;
|
|
176
|
+
}
|
|
177
|
+
};
|
|
178
|
+
/**
|
|
179
|
+
* Perplexity Reason Tool
|
|
180
|
+
* Perform complex reasoning tasks
|
|
181
|
+
*/
|
|
182
|
+
export const perplexityReasonTool = {
|
|
183
|
+
name: "perplexity_reason",
|
|
184
|
+
description: "Reasoning with search",
|
|
185
|
+
parameters: z.object({
|
|
186
|
+
problem: z.string(),
|
|
187
|
+
context: z.string().optional(),
|
|
188
|
+
approach: z.enum(["analytical", "creative", "systematic", "comparative"]).optional()
|
|
189
|
+
}),
|
|
190
|
+
execute: async (args, { log }) => {
|
|
191
|
+
const { problem, context, approach = "analytical" } = args;
|
|
192
|
+
const approachPrompts = {
|
|
193
|
+
analytical: "Break down the problem systematically and analyze each component",
|
|
194
|
+
creative: "Think outside the box and consider unconventional solutions",
|
|
195
|
+
systematic: "Follow a step-by-step logical process",
|
|
196
|
+
comparative: "Compare different approaches and evaluate trade-offs"
|
|
197
|
+
};
|
|
198
|
+
const messages = [
|
|
199
|
+
{
|
|
200
|
+
role: "system",
|
|
201
|
+
content: `You are an expert reasoning system. ${approachPrompts[approach]}.
|
|
202
|
+
Provide clear, logical reasoning with evidence and examples.
|
|
203
|
+
${context ? `Context: ${context}` : ''}`
|
|
204
|
+
},
|
|
205
|
+
{
|
|
206
|
+
role: "user",
|
|
207
|
+
content: problem
|
|
208
|
+
}
|
|
209
|
+
];
|
|
210
|
+
return await callPerplexity(messages, PerplexityModel.SONAR_REASONING_PRO);
|
|
211
|
+
}
|
|
212
|
+
};
|
|
213
|
+
/**
|
|
214
|
+
* Perplexity Fact Check Tool
|
|
215
|
+
* Verify claims with evidence
|
|
216
|
+
*/
|
|
217
|
+
export const perplexityFactCheckTool = {
|
|
218
|
+
name: "perplexity_fact_check",
|
|
219
|
+
description: `Fact-check claims`,
|
|
220
|
+
parameters: z.object({
|
|
221
|
+
claim: z.string(),
|
|
222
|
+
context: z.string().optional()
|
|
223
|
+
}),
|
|
224
|
+
execute: async (args, { log }) => {
|
|
225
|
+
const messages = [
|
|
226
|
+
{
|
|
227
|
+
role: "system",
|
|
228
|
+
content: `You are a fact-checking expert. Verify the following claim with evidence.
|
|
229
|
+
Provide:
|
|
230
|
+
1. Verdict: TRUE, FALSE, PARTIALLY TRUE, or UNVERIFIABLE
|
|
231
|
+
2. Evidence supporting or refuting the claim
|
|
232
|
+
3. Sources for verification
|
|
233
|
+
4. Any important context or nuance
|
|
234
|
+
${args.context ? `Additional context: ${args.context}` : ''}`
|
|
235
|
+
},
|
|
236
|
+
{
|
|
237
|
+
role: "user",
|
|
238
|
+
content: `Fact-check this claim: "${args.claim}"`
|
|
239
|
+
}
|
|
240
|
+
];
|
|
241
|
+
return await callPerplexity(messages, PerplexityModel.SONAR_PRO, "general", "month");
|
|
242
|
+
}
|
|
243
|
+
};
|
|
244
|
+
/**
|
|
245
|
+
* Perplexity Code Search Tool
|
|
246
|
+
* Search for code examples and documentation
|
|
247
|
+
*/
|
|
248
|
+
export const perplexityCodeSearchTool = {
|
|
249
|
+
name: "perplexity_code_search",
|
|
250
|
+
description: `Code search`,
|
|
251
|
+
parameters: z.object({
|
|
252
|
+
query: z.string(),
|
|
253
|
+
language: z.string().optional(),
|
|
254
|
+
framework: z.string().optional()
|
|
255
|
+
}),
|
|
256
|
+
execute: async (args, { log }) => {
|
|
257
|
+
const searchQuery = `${args.language || ''} ${args.framework || ''} ${args.query} code example implementation`.trim();
|
|
258
|
+
const messages = [
|
|
259
|
+
{
|
|
260
|
+
role: "system",
|
|
261
|
+
content: `You are a programming expert. Find and explain code solutions.
|
|
262
|
+
Focus on:
|
|
263
|
+
1. Working code examples
|
|
264
|
+
2. Best practices
|
|
265
|
+
3. Common pitfalls to avoid
|
|
266
|
+
4. Links to documentation`
|
|
267
|
+
},
|
|
268
|
+
{
|
|
269
|
+
role: "user",
|
|
270
|
+
content: searchQuery
|
|
271
|
+
}
|
|
272
|
+
];
|
|
273
|
+
return await callPerplexity(messages, PerplexityModel.SONAR_PRO);
|
|
274
|
+
}
|
|
275
|
+
};
|
|
276
|
+
/**
|
|
277
|
+
* Check if Perplexity is available
|
|
278
|
+
*/
|
|
279
|
+
export function isPerplexityAvailable() {
|
|
280
|
+
return !!getPerplexityApiKey();
|
|
281
|
+
}
|
|
282
|
+
export function getAllPerplexityTools() {
|
|
283
|
+
if (!isPerplexityAvailable()) {
|
|
284
|
+
return [];
|
|
285
|
+
}
|
|
286
|
+
// Minimized tool set - keeping only essential Perplexity tools
|
|
287
|
+
return [
|
|
288
|
+
perplexityAskTool, // Web search
|
|
289
|
+
perplexityReasonTool, // Complex reasoning
|
|
290
|
+
perplexityResearchTool,
|
|
291
|
+
// Removed: perplexityFactCheckTool (can use verifier instead)
|
|
292
|
+
// Removed: perplexityCodeSearchTool (can use perplexity_ask)
|
|
293
|
+
];
|
|
294
|
+
}
|
|
@@ -0,0 +1,343 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PingPong Tool - Customizable multi-model conversation
|
|
3
|
+
* Supports workflow-like YAML/JSON configuration
|
|
4
|
+
*/
|
|
5
|
+
import { z } from "zod";
|
|
6
|
+
import * as yaml from 'yaml';
|
|
7
|
+
import * as fs from 'fs';
|
|
8
|
+
import * as path from 'path';
|
|
9
|
+
import { collaborativeOrchestrator } from '../collaborative-orchestrator.js';
|
|
10
|
+
import { TechnicalDomain } from '../reasoning-chain.js';
|
|
11
|
+
// PingPong configuration schema
|
|
12
|
+
const PingPongConfigSchema = z.object({
|
|
13
|
+
name: z.string().optional(),
|
|
14
|
+
description: z.string().optional(),
|
|
15
|
+
settings: z.object({
|
|
16
|
+
rounds: z.number().min(1).default(5), // No hardcoded max - validated against config.maxPingPongRounds
|
|
17
|
+
style: z.enum(['collaborative', 'debate', 'build-upon', 'competitive']).default('collaborative'),
|
|
18
|
+
temperature: z.number().min(0).max(2).default(0.7),
|
|
19
|
+
maxTokensPerRound: z.number().default(2000),
|
|
20
|
+
synthesis_every: z.number().optional(), // Synthesize every N rounds
|
|
21
|
+
save_session: z.boolean().default(true),
|
|
22
|
+
include_cost_analysis: z.boolean().default(true)
|
|
23
|
+
}).optional().default({}),
|
|
24
|
+
models: z.array(z.union([
|
|
25
|
+
z.string(), // Simple model name
|
|
26
|
+
z.object({
|
|
27
|
+
name: z.string(),
|
|
28
|
+
role: z.string().optional(),
|
|
29
|
+
prompt_style: z.string().optional(),
|
|
30
|
+
temperature: z.number().optional(),
|
|
31
|
+
maxTokens: z.number().optional()
|
|
32
|
+
})
|
|
33
|
+
])).optional(),
|
|
34
|
+
flow: z.object({
|
|
35
|
+
type: z.enum(['sequential', 'parallel', 'conditional']).default('sequential'),
|
|
36
|
+
conditions: z.array(z.object({
|
|
37
|
+
round: z.number(),
|
|
38
|
+
if: z.string(),
|
|
39
|
+
then: z.string(),
|
|
40
|
+
else: z.string().optional()
|
|
41
|
+
})).optional()
|
|
42
|
+
}).optional(),
|
|
43
|
+
prompts: z.object({
|
|
44
|
+
system: z.string().optional(),
|
|
45
|
+
first_round: z.string().optional(),
|
|
46
|
+
subsequent_rounds: z.string().optional(),
|
|
47
|
+
synthesis: z.string().optional()
|
|
48
|
+
}).optional(),
|
|
49
|
+
output: z.object({
|
|
50
|
+
format: z.enum(['summary', 'detailed', 'json', 'structured']).default('structured'),
|
|
51
|
+
save_to_file: z.string().optional(),
|
|
52
|
+
include_metadata: z.boolean().default(true)
|
|
53
|
+
}).optional().default({})
|
|
54
|
+
});
|
|
55
|
+
/**
|
|
56
|
+
* Load configuration from YAML/JSON file or inline object
|
|
57
|
+
*/
|
|
58
|
+
async function loadPingPongConfig(config) {
|
|
59
|
+
if (typeof config === 'string') {
|
|
60
|
+
// Check if it's a file path
|
|
61
|
+
if (config.endsWith('.yaml') || config.endsWith('.yml') || config.endsWith('.json')) {
|
|
62
|
+
const configPath = path.resolve(config);
|
|
63
|
+
if (fs.existsSync(configPath)) {
|
|
64
|
+
const content = fs.readFileSync(configPath, 'utf8');
|
|
65
|
+
const parsed = config.endsWith('.json')
|
|
66
|
+
? JSON.parse(content)
|
|
67
|
+
: yaml.parse(content);
|
|
68
|
+
return PingPongConfigSchema.parse(parsed);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
// Try to parse as inline YAML/JSON
|
|
72
|
+
try {
|
|
73
|
+
const parsed = yaml.parse(config);
|
|
74
|
+
return PingPongConfigSchema.parse(parsed);
|
|
75
|
+
}
|
|
76
|
+
catch {
|
|
77
|
+
try {
|
|
78
|
+
const parsed = JSON.parse(config);
|
|
79
|
+
return PingPongConfigSchema.parse(parsed);
|
|
80
|
+
}
|
|
81
|
+
catch {
|
|
82
|
+
throw new Error('Invalid configuration format. Provide YAML, JSON, or file path.');
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
// It's already an object
|
|
87
|
+
return PingPongConfigSchema.parse(config);
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Build custom model configuration
|
|
91
|
+
*/
|
|
92
|
+
function buildModelConfig(config, overrides) {
|
|
93
|
+
const settings = config.settings || {};
|
|
94
|
+
// Determine models to use
|
|
95
|
+
let models = overrides?.models || [];
|
|
96
|
+
if (models.length === 0 && config.models) {
|
|
97
|
+
models = config.models.map(m => typeof m === 'string' ? m : m.name);
|
|
98
|
+
}
|
|
99
|
+
if (models.length === 0) {
|
|
100
|
+
models = ['grok', 'gemini', 'openai', 'qwen']; // Default models
|
|
101
|
+
}
|
|
102
|
+
return {
|
|
103
|
+
models,
|
|
104
|
+
rounds: overrides?.rounds || settings.rounds || 5,
|
|
105
|
+
style: overrides?.style || settings.style || 'collaborative',
|
|
106
|
+
temperature: settings.temperature || 0.7,
|
|
107
|
+
maxTokensPerRound: settings.maxTokensPerRound || 2000,
|
|
108
|
+
saveSession: settings.save_session !== false,
|
|
109
|
+
includeCostAnalysis: settings.include_cost_analysis !== false,
|
|
110
|
+
synthesisEvery: settings.synthesis_every
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Format output based on configuration
|
|
115
|
+
*/
|
|
116
|
+
function formatOutput(result, config, metadata) {
|
|
117
|
+
const outputConfig = config.output || {};
|
|
118
|
+
switch (outputConfig.format) {
|
|
119
|
+
case 'json':
|
|
120
|
+
return JSON.stringify({
|
|
121
|
+
result,
|
|
122
|
+
metadata: outputConfig.include_metadata ? metadata : undefined,
|
|
123
|
+
config: config.name ? { name: config.name, description: config.description } : undefined
|
|
124
|
+
}, null, 2);
|
|
125
|
+
case 'summary':
|
|
126
|
+
// Extract just the synthesis/summary section
|
|
127
|
+
const summaryMatch = result.match(/## .*Synthesis.*\n([\s\S]*?)(?=##|$)/);
|
|
128
|
+
return summaryMatch ? summaryMatch[1].trim() : result;
|
|
129
|
+
case 'detailed':
|
|
130
|
+
// Include everything
|
|
131
|
+
return result;
|
|
132
|
+
case 'structured':
|
|
133
|
+
default:
|
|
134
|
+
// Well-formatted markdown with sections
|
|
135
|
+
let structured = `# PingPong Conversation`;
|
|
136
|
+
if (config.name)
|
|
137
|
+
structured += `: ${config.name}`;
|
|
138
|
+
structured += '\n\n';
|
|
139
|
+
if (config.description)
|
|
140
|
+
structured += `*${config.description}*\n\n`;
|
|
141
|
+
structured += result;
|
|
142
|
+
return structured;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* PingPong Tool Definition
|
|
147
|
+
*/
|
|
148
|
+
export const pingpongTool = {
|
|
149
|
+
name: "pingpong",
|
|
150
|
+
description: "Multi-model conversation",
|
|
151
|
+
parameters: z.object({
|
|
152
|
+
problem: z.string(),
|
|
153
|
+
config: z.union([
|
|
154
|
+
z.string(),
|
|
155
|
+
z.object({
|
|
156
|
+
name: z.string().optional(),
|
|
157
|
+
description: z.string().optional(),
|
|
158
|
+
settings: z.any().optional(),
|
|
159
|
+
models: z.any().optional(),
|
|
160
|
+
flow: z.any().optional(),
|
|
161
|
+
prompts: z.any().optional(),
|
|
162
|
+
output: z.any().optional()
|
|
163
|
+
})
|
|
164
|
+
]).optional(),
|
|
165
|
+
models: z.array(z.string()).optional(),
|
|
166
|
+
rounds: z.number().min(1).optional(),
|
|
167
|
+
style: z.enum(['collaborative', 'debate', 'build-upon', 'competitive']).optional(),
|
|
168
|
+
domain: z.enum([
|
|
169
|
+
"architecture", "algorithms", "debugging", "security",
|
|
170
|
+
"performance", "api_design", "database", "frontend",
|
|
171
|
+
"backend", "devops", "testing"
|
|
172
|
+
]).optional(),
|
|
173
|
+
customPrompts: z.record(z.string()).optional(),
|
|
174
|
+
template: z.string().optional()
|
|
175
|
+
}),
|
|
176
|
+
execute: async (args, { log }) => {
|
|
177
|
+
try {
|
|
178
|
+
// Load configuration
|
|
179
|
+
let config;
|
|
180
|
+
if (args.template) {
|
|
181
|
+
// Use predefined template
|
|
182
|
+
config = getPredefinedTemplate(args.template);
|
|
183
|
+
}
|
|
184
|
+
else if (args.config) {
|
|
185
|
+
config = await loadPingPongConfig(args.config);
|
|
186
|
+
}
|
|
187
|
+
else {
|
|
188
|
+
// Default configuration
|
|
189
|
+
config = {
|
|
190
|
+
settings: {
|
|
191
|
+
rounds: 5,
|
|
192
|
+
style: 'collaborative',
|
|
193
|
+
temperature: 0.7,
|
|
194
|
+
maxTokensPerRound: 2000,
|
|
195
|
+
save_session: true,
|
|
196
|
+
include_cost_analysis: true
|
|
197
|
+
},
|
|
198
|
+
output: {
|
|
199
|
+
format: 'structured',
|
|
200
|
+
include_metadata: true
|
|
201
|
+
}
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
// Build final configuration with overrides
|
|
205
|
+
const finalConfig = buildModelConfig(config, {
|
|
206
|
+
models: args.models,
|
|
207
|
+
rounds: args.rounds,
|
|
208
|
+
style: args.style
|
|
209
|
+
});
|
|
210
|
+
// Map domain string to TechnicalDomain enum
|
|
211
|
+
const domainMap = {
|
|
212
|
+
'architecture': TechnicalDomain.ARCHITECTURE,
|
|
213
|
+
'algorithms': TechnicalDomain.ALGORITHMS,
|
|
214
|
+
'debugging': TechnicalDomain.DEBUGGING,
|
|
215
|
+
'security': TechnicalDomain.SECURITY,
|
|
216
|
+
'performance': TechnicalDomain.PERFORMANCE,
|
|
217
|
+
'api_design': TechnicalDomain.API_DESIGN,
|
|
218
|
+
'database': TechnicalDomain.DATABASE,
|
|
219
|
+
'frontend': TechnicalDomain.FRONTEND,
|
|
220
|
+
'backend': TechnicalDomain.BACKEND,
|
|
221
|
+
'devops': TechnicalDomain.DEVOPS,
|
|
222
|
+
'testing': TechnicalDomain.TESTING
|
|
223
|
+
};
|
|
224
|
+
const domain = domainMap[args.domain || 'architecture'] || TechnicalDomain.ARCHITECTURE;
|
|
225
|
+
log?.info(`Starting PingPong: ${config.name || 'Custom'}, ${finalConfig.rounds} rounds, ${finalConfig.models.length} models`);
|
|
226
|
+
// Execute the pingpong conversation
|
|
227
|
+
const result = await collaborativeOrchestrator.executeAdvancedPingPong({
|
|
228
|
+
problem: args.problem,
|
|
229
|
+
domain: domain,
|
|
230
|
+
rounds: finalConfig.rounds,
|
|
231
|
+
models: finalConfig.models,
|
|
232
|
+
temperature: finalConfig.temperature,
|
|
233
|
+
maxTokensPerRound: finalConfig.maxTokensPerRound,
|
|
234
|
+
style: finalConfig.style,
|
|
235
|
+
saveSession: finalConfig.saveSession
|
|
236
|
+
});
|
|
237
|
+
// Format output
|
|
238
|
+
const formattedResult = formatOutput(result, config, {
|
|
239
|
+
rounds: finalConfig.rounds,
|
|
240
|
+
models: finalConfig.models,
|
|
241
|
+
style: finalConfig.style,
|
|
242
|
+
timestamp: new Date().toISOString()
|
|
243
|
+
});
|
|
244
|
+
// Save to file if configured
|
|
245
|
+
if (config.output?.save_to_file) {
|
|
246
|
+
const outputPath = path.resolve(config.output.save_to_file);
|
|
247
|
+
fs.writeFileSync(outputPath, formattedResult, 'utf8');
|
|
248
|
+
log?.info(`PingPong result saved to: ${outputPath}`);
|
|
249
|
+
}
|
|
250
|
+
return formattedResult;
|
|
251
|
+
}
|
|
252
|
+
catch (error) {
|
|
253
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
254
|
+
log?.error('PingPong execution failed:', errorMessage);
|
|
255
|
+
return `PingPong Error: ${errorMessage}`;
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
};
|
|
259
|
+
/**
|
|
260
|
+
* Get predefined templates
|
|
261
|
+
*/
|
|
262
|
+
function getPredefinedTemplate(template) {
|
|
263
|
+
const templates = {
|
|
264
|
+
debate: {
|
|
265
|
+
name: 'Technical Debate',
|
|
266
|
+
description: 'Models debate different approaches',
|
|
267
|
+
settings: {
|
|
268
|
+
rounds: 6,
|
|
269
|
+
style: 'debate',
|
|
270
|
+
temperature: 0.8,
|
|
271
|
+
maxTokensPerRound: 2000,
|
|
272
|
+
save_session: true,
|
|
273
|
+
include_cost_analysis: true
|
|
274
|
+
},
|
|
275
|
+
models: [
|
|
276
|
+
{ name: 'grok', role: 'challenger', prompt_style: 'Challenge assumptions aggressively' },
|
|
277
|
+
{ name: 'openai', role: 'defender', prompt_style: 'Defend conventional wisdom' },
|
|
278
|
+
{ name: 'gemini', role: 'mediator', prompt_style: 'Find middle ground' }
|
|
279
|
+
],
|
|
280
|
+
output: { format: 'structured', include_metadata: true }
|
|
281
|
+
},
|
|
282
|
+
brainstorm: {
|
|
283
|
+
name: 'Creative Brainstorm',
|
|
284
|
+
description: 'Collaborative idea generation',
|
|
285
|
+
settings: {
|
|
286
|
+
rounds: 8,
|
|
287
|
+
style: 'build-upon',
|
|
288
|
+
temperature: 0.9,
|
|
289
|
+
maxTokensPerRound: 1500,
|
|
290
|
+
synthesis_every: 3,
|
|
291
|
+
save_session: true,
|
|
292
|
+
include_cost_analysis: false
|
|
293
|
+
},
|
|
294
|
+
models: [
|
|
295
|
+
{ name: 'gemini', role: 'ideator' },
|
|
296
|
+
{ name: 'grok', role: 'innovator' },
|
|
297
|
+
{ name: 'qwen', role: 'implementer' },
|
|
298
|
+
{ name: 'openai', role: 'synthesizer' }
|
|
299
|
+
],
|
|
300
|
+
output: { format: 'structured', include_metadata: false }
|
|
301
|
+
},
|
|
302
|
+
review: {
|
|
303
|
+
name: 'Architecture Review',
|
|
304
|
+
description: 'Multi-perspective code/architecture review',
|
|
305
|
+
settings: {
|
|
306
|
+
rounds: 4,
|
|
307
|
+
style: 'collaborative',
|
|
308
|
+
temperature: 0.6,
|
|
309
|
+
maxTokensPerRound: 2500,
|
|
310
|
+
save_session: true,
|
|
311
|
+
include_cost_analysis: true
|
|
312
|
+
},
|
|
313
|
+
models: [
|
|
314
|
+
{ name: 'grok', role: 'security reviewer' },
|
|
315
|
+
{ name: 'openai', role: 'performance analyst' },
|
|
316
|
+
{ name: 'gemini', role: 'best practices expert' }
|
|
317
|
+
],
|
|
318
|
+
output: { format: 'detailed', include_metadata: true }
|
|
319
|
+
},
|
|
320
|
+
design: {
|
|
321
|
+
name: 'System Design',
|
|
322
|
+
description: 'Collaborative system design session',
|
|
323
|
+
settings: {
|
|
324
|
+
rounds: 10,
|
|
325
|
+
style: 'build-upon',
|
|
326
|
+
temperature: 0.7,
|
|
327
|
+
maxTokensPerRound: 3000,
|
|
328
|
+
synthesis_every: 5,
|
|
329
|
+
save_session: true,
|
|
330
|
+
include_cost_analysis: true
|
|
331
|
+
},
|
|
332
|
+
models: ['grok', 'gemini', 'openai', 'qwen'],
|
|
333
|
+
output: { format: 'structured', include_metadata: true }
|
|
334
|
+
}
|
|
335
|
+
};
|
|
336
|
+
return templates[template] || templates.brainstorm;
|
|
337
|
+
}
|
|
338
|
+
/**
|
|
339
|
+
* Check if pingpong tool is available
|
|
340
|
+
*/
|
|
341
|
+
export function isPingPongAvailable() {
|
|
342
|
+
return true; // Always available since it uses the collaborative orchestrator
|
|
343
|
+
}
|