Skip to content

Commit 0ef74c5

Browse files
Oladotun  Olatunjiclaude
authored andcommitted
fix: update remaining files from CLI improvements
- Update mcp-config.json with latest tool configurations - Fix REPL imports and interactive mode handling - Update banner display in CLI - Update research-manager with latest improvements These changes complete the CLI and configuration improvements. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent 83631f9 commit 0ef74c5

4 files changed

Lines changed: 237 additions & 42 deletions

File tree

mcp-config.json

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,34 @@
66
"input_patterns": ["create starter kit for {use_case}", "generate {type} project", "scaffold {application_type} app", "setup boilerplate for {project}"]
77
},
88
"research-manager": {
9-
"description": "Performs in-depth research on technical topics, concepts, or comparisons using Perplexity Sonar.",
10-
"use_cases": ["research", "comparison", "best practices", "explain concept", "technical deep dive", "learn about {topic}"],
11-
"input_patterns": ["research {topic}", "compare {A} and {B}", "best practices for {domain}", "explain {concept}"]
9+
"description": "Performs comprehensive research on any technical topic including frameworks, libraries, packages, tools, and best practices using Perplexity Sonar.",
10+
"use_cases": [
11+
"research {any topic}",
12+
"find latest {technology} packages",
13+
"explore {framework} ecosystem",
14+
"investigate UI/UX libraries",
15+
"discover CLI tools and frameworks",
16+
"analyze development trends",
17+
"compare {tool} alternatives",
18+
"best practices for {domain}",
19+
"explain {concept}",
20+
"technical deep dive",
21+
"learn about {topic}",
22+
"research packages and libraries",
23+
"investigate framework options"
24+
],
25+
"input_patterns": [
26+
"research {topic}",
27+
"perform research on {topic}",
28+
"investigate {technology}",
29+
"explore {framework}",
30+
"find {library} alternatives",
31+
"discover {tool} options",
32+
"compare {A} and {B}",
33+
"best practices for {domain}",
34+
"explain {concept}",
35+
"latest {technology} packages"
36+
]
1237
},
1338
"prd-generator": {
1439
"description": "Creates comprehensive Product Requirements Documents (PRDs) based on a feature or product description.",

src/cli/interactive/repl.ts

Lines changed: 186 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,13 @@ export class VibeInteractiveREPL {
3737
private enableMarkdown = true;
3838
private requestConcurrency = 0;
3939

40+
// Add pending confirmation state for tool execution
41+
private pendingConfirmation: {
42+
toolName: string;
43+
parameters: Record<string, unknown>;
44+
originalRequest: string;
45+
} | null = null;
46+
4047
constructor() {
4148
this.sessionId = `interactive-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
4249
this.history = new CommandHistory();
@@ -257,6 +264,114 @@ export class VibeInteractiveREPL {
257264
* Handle user message input
258265
*/
259266
private async handleUserMessage(message: string): Promise<void> {
267+
// Check if we're waiting for confirmation
268+
if (this.pendingConfirmation) {
269+
const normalizedMessage = message.toLowerCase().trim();
270+
271+
// Check for confirmation responses - be flexible with natural language
272+
const confirmationPatterns = [
273+
'yes', 'y', 'yeah', 'yep', 'sure', 'ok', 'okay',
274+
'proceed', 'go ahead', 'do it', 'confirm', 'continue',
275+
'please proceed', 'go for it', 'lets do it', "let's do it"
276+
];
277+
278+
const cancellationPatterns = [
279+
'no', 'n', 'nope', 'cancel', 'stop', 'abort', 'nevermind',
280+
'never mind', "don't", 'dont', 'skip', 'forget it'
281+
];
282+
283+
// Check if message contains any confirmation pattern
284+
const isConfirmation = confirmationPatterns.some(pattern =>
285+
normalizedMessage === pattern ||
286+
normalizedMessage.startsWith(pattern + ' ') ||
287+
normalizedMessage.includes(' ' + pattern + ' ') ||
288+
normalizedMessage.endsWith(' ' + pattern)
289+
);
290+
291+
// Check if message contains any cancellation pattern
292+
const isCancellation = cancellationPatterns.some(pattern =>
293+
normalizedMessage === pattern ||
294+
normalizedMessage.startsWith(pattern + ' ') ||
295+
normalizedMessage.includes(' ' + pattern + ' ') ||
296+
normalizedMessage.endsWith(' ' + pattern)
297+
);
298+
299+
if (isConfirmation && !isCancellation) {
300+
// User confirmed - execute the pending tool directly
301+
const { toolName, parameters } = this.pendingConfirmation;
302+
this.pendingConfirmation = null; // Clear pending state
303+
304+
// Start progress indicator
305+
progress.start(`Executing ${toolName}...`);
306+
307+
try {
308+
// Create execution context
309+
const context: ToolExecutionContext = {
310+
sessionId: this.sessionId,
311+
transportType: 'interactive',
312+
metadata: {
313+
conversationHistory: this.conversationHistory,
314+
interactiveMode: true
315+
}
316+
};
317+
318+
// Execute the tool directly (bypassing process-request since we already know what to do)
319+
const result = await executeTool(
320+
toolName,
321+
parameters,
322+
this.openRouterConfig!,
323+
context
324+
);
325+
326+
// Stop progress
327+
progress.success('Tool execution complete');
328+
329+
// Extract and display response
330+
const responseText = result.content[0]?.text;
331+
const response = typeof responseText === 'string' ? responseText : 'Tool executed successfully';
332+
333+
// Format and display response
334+
console.log();
335+
if (this.enableMarkdown) {
336+
const rendered = MarkdownRenderer.renderWrapped(response);
337+
ResponseFormatter.formatResponse(rendered);
338+
} else {
339+
ResponseFormatter.formatResponse(response);
340+
}
341+
console.log();
342+
343+
// Add to history
344+
this.conversationHistory.push({ role: 'assistant', content: response });
345+
346+
} catch (error) {
347+
progress.fail('Tool execution failed');
348+
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
349+
console.log();
350+
ResponseFormatter.formatError(errorMessage);
351+
console.log();
352+
logger.error({ err: error }, `Error executing confirmed tool ${toolName}`);
353+
}
354+
355+
return; // Exit early - we've handled the confirmation
356+
} else if (isCancellation) {
357+
// User cancelled
358+
this.pendingConfirmation = null;
359+
console.log();
360+
ResponseFormatter.formatInfo('Tool execution cancelled.');
361+
console.log();
362+
return;
363+
} else if (!isConfirmation && !isCancellation) {
364+
// Ambiguous response - ask for clarification
365+
console.log();
366+
ResponseFormatter.formatWarning(
367+
'Please respond with "yes" to proceed or "no" to cancel.\n' +
368+
`Tool waiting: ${this.pendingConfirmation.toolName}`
369+
);
370+
console.log();
371+
return; // Keep pending state, wait for clear response
372+
}
373+
}
374+
260375
// Check concurrent request limit
261376
const maxConcurrent = configManager.get('performance', 'maxConcurrentRequests');
262377
if (this.requestConcurrency >= maxConcurrent) {
@@ -273,46 +388,81 @@ export class VibeInteractiveREPL {
273388
progress.start('Processing your request...');
274389

275390
try {
276-
// Create execution context
277-
const context: ToolExecutionContext = {
278-
sessionId: this.sessionId,
279-
transportType: 'interactive',
280-
metadata: {
281-
conversationHistory: this.conversationHistory,
282-
interactiveMode: true
283-
}
284-
};
391+
// Import hybridMatch to check if we need confirmation
392+
const { hybridMatch } = await import('../../services/hybrid-matcher/index.js');
285393

286-
// Update progress
287-
progress.update('Analyzing request and routing to appropriate tool...');
288-
289-
// Execute through process-request tool
290-
const result = await executeTool(
291-
'process-request',
292-
{ request: message },
293-
this.openRouterConfig!,
294-
context
295-
);
394+
// First, determine what tool and parameters to use
395+
const matchResult = await hybridMatch(message, this.openRouterConfig!);
296396

297-
// Stop progress
298-
progress.success('Response ready');
299-
300-
// Extract and display response
301-
const responseText = result.content[0]?.text;
302-
const response = typeof responseText === 'string' ? responseText : 'No response';
303-
304-
// Format and display response with markdown if enabled
305-
console.log();
306-
if (this.enableMarkdown) {
307-
const rendered = MarkdownRenderer.renderWrapped(response);
308-
ResponseFormatter.formatResponse(rendered);
397+
// Check if confirmation is required
398+
if (matchResult.requiresConfirmation) {
399+
// Store pending confirmation details
400+
this.pendingConfirmation = {
401+
toolName: matchResult.toolName,
402+
parameters: matchResult.parameters,
403+
originalRequest: message
404+
};
405+
406+
// Stop progress
407+
progress.success('Analysis complete');
408+
409+
// Display confirmation message
410+
console.log();
411+
ResponseFormatter.formatInfo(
412+
`I plan to use the '${matchResult.toolName}' tool for your request.\n` +
413+
`Confidence: ${Math.round(matchResult.confidence * 100)}%\n\n` +
414+
`Do you want to proceed? (yes/no)`
415+
);
416+
console.log();
417+
418+
// Add to history
419+
this.conversationHistory.push({
420+
role: 'assistant',
421+
content: `Requesting confirmation to use ${matchResult.toolName} tool (confidence: ${Math.round(matchResult.confidence * 100)}%)`
422+
});
423+
309424
} else {
310-
ResponseFormatter.formatResponse(response);
425+
// High confidence - execute directly
426+
const context: ToolExecutionContext = {
427+
sessionId: this.sessionId,
428+
transportType: 'interactive',
429+
metadata: {
430+
conversationHistory: this.conversationHistory,
431+
interactiveMode: true
432+
}
433+
};
434+
435+
// Update progress
436+
progress.update(`Executing ${matchResult.toolName}...`);
437+
438+
// Execute the tool directly
439+
const result = await executeTool(
440+
matchResult.toolName,
441+
matchResult.parameters,
442+
this.openRouterConfig!,
443+
context
444+
);
445+
446+
// Stop progress
447+
progress.success('Response ready');
448+
449+
// Extract and display response
450+
const responseText = result.content[0]?.text;
451+
const response = typeof responseText === 'string' ? responseText : 'No response';
452+
453+
// Format and display response
454+
console.log();
455+
if (this.enableMarkdown) {
456+
const rendered = MarkdownRenderer.renderWrapped(response);
457+
ResponseFormatter.formatResponse(rendered);
458+
} else {
459+
ResponseFormatter.formatResponse(response);
460+
}
461+
console.log();
462+
463+
// Add to history
464+
this.conversationHistory.push({ role: 'assistant', content: response });
311465
}
312-
console.log();
313-
314-
// Add to history
315-
this.conversationHistory.push({ role: 'assistant', content: response });
316466

317467
} catch (error) {
318468
// Stop progress with error

src/cli/interactive/ui/banner.ts

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,25 @@
66
import boxen from 'boxen';
77
import figlet from 'figlet';
88
import { themeManager } from '../themes.js';
9+
import { readFileSync } from 'fs';
10+
import { fileURLToPath } from 'url';
11+
import path from 'path';
12+
13+
// Get package version - following established pattern from embeddingStore.ts
14+
const __filename = fileURLToPath(import.meta.url);
15+
const __dirname = path.dirname(__filename);
16+
17+
function getPackageVersion(): string {
18+
try {
19+
const packagePath = path.resolve(__dirname, '../../../../package.json');
20+
const packageContent = readFileSync(packagePath, 'utf-8');
21+
const packageJson = JSON.parse(packageContent);
22+
return packageJson.version || '0.0.0';
23+
} catch {
24+
// Fallback version if package.json can't be read
25+
return '0.0.0';
26+
}
27+
}
928

1029
/**
1130
* Get ASCII art banner
@@ -29,9 +48,10 @@ export function getAsciiBanner(): string {
2948
export function getBanner(): string {
3049
const asciiArt = getAsciiBanner();
3150
const colors = themeManager.getColors();
51+
const version = getPackageVersion();
3252

3353
const content = colors.primary(asciiArt) + '\n\n' +
34-
colors.textBright('AI Development Assistant v1.0.0') + '\n' +
54+
colors.textBright(`AI Development Assistant v${version}`) + '\n' +
3555
colors.textMuted('Powered by OpenRouter & Claude') + '\n\n' +
3656
colors.warning('Quick Commands:') + '\n' +
3757
colors.success(' /help ') + colors.textMuted('Show available commands') + '\n' +

src/tools/research-manager/index.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -278,8 +278,8 @@ const researchInputSchemaShape = {
278278

279279
// Tool definition for the research tool, using the raw shape
280280
const researchToolDefinition: ToolDefinition = {
281-
name: "research", // Keep the original tool name
282-
description: "Performs deep research on a given topic using Perplexity Sonar and enhances the result.",
281+
name: "research-manager", // Align with mcp-config.json and hybrid-matcher expectations
282+
description: "Performs comprehensive research on any technical topic including frameworks, libraries, packages, tools, and best practices using Perplexity Sonar.",
283283
inputSchema: researchInputSchemaShape, // Use the raw shape here
284284
executor: performResearch // Reference the adapted function
285285
};

0 commit comments

Comments
 (0)