mirror of
https://github.com/catlog22/Claude-Code-Workflow.git
synced 2026-03-14 17:41:22 +08:00
feat: add CLI Command Node and Prompt Node components for orchestrator
- Implemented CliCommandNode component for executing CLI tools with AI models. - Implemented PromptNode component for constructing AI prompts with context. - Added styling for mode and tool badges in both components. - Enhanced user experience with command and argument previews, execution status, and error handling. test: add comprehensive tests for ask_question tool - Created direct test for ask_question tool execution. - Developed end-to-end tests to validate ask_question tool integration with WebSocket and A2UI surfaces. - Implemented simple and integrated WebSocket tests to ensure proper message handling and surface reception. - Added tool registration test to verify ask_question tool is correctly registered. chore: add WebSocket listener and simulation tests - Added WebSocket listener for A2UI surfaces to facilitate testing. - Implemented frontend simulation test to validate complete flow from backend to frontend. - Created various test scripts to ensure robust testing of ask_question tool functionality.
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
// ========================================
|
||||
// MCP Server Dialog Component
|
||||
// ========================================
|
||||
// Add/Edit dialog for MCP server configuration with template presets
|
||||
// Add/Edit dialog for MCP server configuration with dynamic template loading
|
||||
|
||||
import { useState, useEffect } from 'react';
|
||||
import { useIntl } from 'react-intl';
|
||||
@@ -29,7 +29,7 @@ import {
|
||||
fetchMcpServers,
|
||||
type McpServer,
|
||||
} from '@/lib/api';
|
||||
import { mcpServersKeys } from '@/hooks';
|
||||
import { mcpServersKeys, useMcpTemplates } from '@/hooks';
|
||||
import { cn } from '@/lib/utils';
|
||||
|
||||
// ========== Types ==========
|
||||
@@ -42,14 +42,8 @@ export interface McpServerDialogProps {
|
||||
onSave?: () => void;
|
||||
}
|
||||
|
||||
export interface McpTemplate {
|
||||
id: string;
|
||||
name: string;
|
||||
description: string;
|
||||
command: string;
|
||||
args: string[];
|
||||
env?: Record<string, string>;
|
||||
}
|
||||
// Re-export McpTemplate for convenience
|
||||
export type { McpTemplate } from '@/types/store';
|
||||
|
||||
interface McpServerFormData {
|
||||
name: string;
|
||||
@@ -67,32 +61,6 @@ interface FormErrors {
|
||||
env?: string;
|
||||
}
|
||||
|
||||
// ========== Template Presets ==========
|
||||
|
||||
const TEMPLATE_PRESETS: McpTemplate[] = [
|
||||
{
|
||||
id: 'npx-stdio',
|
||||
name: 'NPX STDIO',
|
||||
description: 'Node.js package using stdio transport',
|
||||
command: 'npx',
|
||||
args: ['{package}'],
|
||||
},
|
||||
{
|
||||
id: 'python-stdio',
|
||||
name: 'Python STDIO',
|
||||
description: 'Python script using stdio transport',
|
||||
command: 'python',
|
||||
args: ['{script}.py'],
|
||||
},
|
||||
{
|
||||
id: 'sse-server',
|
||||
name: 'SSE Server',
|
||||
description: 'HTTP server with Server-Sent Events transport',
|
||||
command: 'node',
|
||||
args: ['{server}.js'],
|
||||
},
|
||||
];
|
||||
|
||||
// ========== Component ==========
|
||||
|
||||
export function McpServerDialog({
|
||||
@@ -105,6 +73,9 @@ export function McpServerDialog({
|
||||
const { formatMessage } = useIntl();
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
// Fetch templates from backend
|
||||
const { templates, isLoading: templatesLoading } = useMcpTemplates();
|
||||
|
||||
// Form state
|
||||
const [formData, setFormData] = useState<McpServerFormData>({
|
||||
name: '',
|
||||
@@ -181,17 +152,17 @@ export function McpServerDialog({
|
||||
};
|
||||
|
||||
const handleTemplateSelect = (templateId: string) => {
|
||||
const template = TEMPLATE_PRESETS.find((t) => t.id === templateId);
|
||||
const template = templates.find((t) => t.name === templateId);
|
||||
if (template) {
|
||||
setFormData((prev) => ({
|
||||
...prev,
|
||||
command: template.command,
|
||||
args: template.args,
|
||||
env: template.env || {},
|
||||
command: template.serverConfig.command,
|
||||
args: template.serverConfig.args || [],
|
||||
env: template.serverConfig.env || {},
|
||||
}));
|
||||
setArgsInput(template.args.join(', '));
|
||||
setArgsInput((template.serverConfig.args || []).join(', '));
|
||||
setEnvInput(
|
||||
Object.entries(template.env || {})
|
||||
Object.entries(template.serverConfig.env || {})
|
||||
.map(([k, v]) => `${k}=${v}`)
|
||||
.join('\n')
|
||||
);
|
||||
@@ -324,23 +295,32 @@ export function McpServerDialog({
|
||||
<label className="text-sm font-medium text-foreground">
|
||||
{formatMessage({ id: 'mcp.dialog.form.template' })}
|
||||
</label>
|
||||
<Select value={selectedTemplate} onValueChange={handleTemplateSelect}>
|
||||
<Select value={selectedTemplate} onValueChange={handleTemplateSelect} disabled={templatesLoading}>
|
||||
<SelectTrigger className="w-full">
|
||||
<SelectValue
|
||||
placeholder={formatMessage({ id: 'mcp.dialog.form.templatePlaceholder' })}
|
||||
placeholder={templatesLoading
|
||||
? formatMessage({ id: 'mcp.templates.loading' })
|
||||
: formatMessage({ id: 'mcp.dialog.form.templatePlaceholder' })
|
||||
}
|
||||
/>
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
{TEMPLATE_PRESETS.map((template) => (
|
||||
<SelectItem key={template.id} value={template.id}>
|
||||
<div className="flex flex-col">
|
||||
<span className="font-medium">{template.name}</span>
|
||||
<span className="text-xs text-muted-foreground">
|
||||
{template.description}
|
||||
</span>
|
||||
</div>
|
||||
{templates.length === 0 ? (
|
||||
<SelectItem value="" disabled>
|
||||
{formatMessage({ id: 'mcp.templates.empty.title' })}
|
||||
</SelectItem>
|
||||
))}
|
||||
) : (
|
||||
templates.map((template) => (
|
||||
<SelectItem key={template.name} value={template.name}>
|
||||
<div className="flex flex-col">
|
||||
<span className="font-medium">{template.name}</span>
|
||||
<span className="text-xs text-muted-foreground">
|
||||
{template.description || formatMessage({ id: 'mcp.dialog.form.templatePlaceholder' })}
|
||||
</span>
|
||||
</div>
|
||||
</SelectItem>
|
||||
))
|
||||
)}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user