diff --git a/src/App.tsx b/src/App.tsx index 0d90bd1..48bc69e 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,8 +1,5 @@ -import { useState } from 'react' import { InferenceContextProvider } from '@/contexts/InferenceContext' import { MCPProvider } from '@/contexts/MCPContext' -import { InferenceTest } from '@/components/InferenceTest' -import { MCPTest } from '@/components/MCPTest' import { ConversationApp } from '@/components/ConversationApp' import { OAuthCallback } from '@/components/OAuthCallback' @@ -20,54 +17,11 @@ function App() { return ; } - const [activeTab, setActiveTab] = useState<'conversations' | 'inference' | 'mcp'>('conversations'); - return (
- {/* Tab Navigation */} -
-
-
- - - -
-
-
- - {/* Tab Content */} - {activeTab === 'conversations' && } - {activeTab === 'inference' && } - {activeTab === 'mcp' && } +
diff --git a/src/components/ConversationApp.tsx b/src/components/ConversationApp.tsx index 7e93758..0463e89 100644 --- a/src/components/ConversationApp.tsx +++ b/src/components/ConversationApp.tsx @@ -11,7 +11,7 @@ export function ConversationApp() { return ( -
+
{/* Left Sidebar - Conversations */}
diff --git a/src/components/InferenceTest.tsx b/src/components/InferenceTest.tsx deleted file mode 100644 index 50d321d..0000000 --- a/src/components/InferenceTest.tsx +++ /dev/null @@ -1,368 +0,0 @@ -// Test UI for inference provider functionality - -import { useState, useCallback } from 'react'; -import { useInference } from '@/contexts/InferenceContext'; -import { OpenRouterApiProvider, OpenRouterOAuthProvider } from '@/providers/openrouter'; -import type { ChatMessage, InferenceRequest } from '@/types/inference'; -import { testTools, executeTestTool } from '@/utils/testTools'; - -export function InferenceTest() { - const { - provider, - isLoading, - error, - setProvider, - clearProvider, - generateResponse, - selectModel, - loadModels, - models, - selectedModel, - isAuthenticated, - } = useInference(); - - const [apiKey, setApiKey] = useState(''); - const [message, setMessage] = useState(''); - const [response, setResponse] = useState(''); - const [conversation, setConversation] = useState([]); - const [enableTools, setEnableTools] = useState(false); - - const handleApiAuth = useCallback(async () => { - if (!apiKey.trim()) { - alert('Please enter an API key'); - return; - } - - try { - const apiProvider = new OpenRouterApiProvider(); - await apiProvider.authenticate({ type: 'api_key', apiKey: apiKey.trim() }); - setProvider(apiProvider); - } catch (err) { - console.error('API authentication failed:', err); - alert(`Authentication failed: ${err instanceof Error ? err.message : 'Unknown error'}`); - } - }, [apiKey, setProvider]); - - const handleOAuthAuth = useCallback(async () => { - try { - const oauthProvider = new OpenRouterOAuthProvider(); - await oauthProvider.authenticate({ type: 'oauth' }); - setProvider(oauthProvider); - } catch (err) { - console.error('OAuth authentication failed:', err); - alert(`OAuth failed: ${err instanceof Error ? err.message : 'Unknown error'}`); - } - }, [setProvider]); - - const handleLoadModels = useCallback(async () => { - try { - await loadModels(); - } catch (err) { - console.error('Failed to load models:', err); - alert(`Failed to load models: ${err instanceof Error ? err.message : 'Unknown error'}`); - } - }, [loadModels]); - - const handleSendMessage = useCallback(async () => { - if (!message.trim() || !provider || !selectedModel) { - alert('Please enter a message and ensure a model is selected'); - return; - } - - const userMessage: ChatMessage = { - role: 'user', - content: message.trim(), - }; - - let currentConversation = [...conversation, userMessage]; - setConversation(currentConversation); - setMessage(''); - setResponse(''); - - const request: InferenceRequest = { - messages: currentConversation, - maxTokens: 500, - temperature: 0.7, - tools: enableTools ? testTools : undefined, - }; - - try { - const result = await generateResponse(request); - let assistantMessage = result.message; - - // Handle tool calls - if (assistantMessage.toolCalls && assistantMessage.toolCalls.length > 0) { - // Add the assistant message with tool calls - currentConversation = [...currentConversation, assistantMessage]; - setConversation(currentConversation); - - // Execute each tool call and add tool results - for (const toolCall of assistantMessage.toolCalls) { - const toolResult = executeTestTool(toolCall.function.name, toolCall.function.arguments); - - const toolMessage: ChatMessage = { - role: 'tool', - content: toolResult, - toolCallId: toolCall.id, - }; - - currentConversation = [...currentConversation, toolMessage]; - setConversation(currentConversation); - } - - // Make another request with the tool results - const followUpRequest: InferenceRequest = { - messages: currentConversation, - maxTokens: 500, - temperature: 0.7, - tools: enableTools ? testTools : undefined, - }; - - const followUpResult = await generateResponse(followUpRequest); - assistantMessage = followUpResult.message; - setResponse(JSON.stringify(followUpResult, null, 2)); - } else { - setResponse(JSON.stringify(result, null, 2)); - } - - setConversation([...currentConversation, assistantMessage]); - } catch (err) { - console.error('Inference failed:', err); - alert(`Inference failed: ${err instanceof Error ? err.message : 'Unknown error'}`); - } - }, [message, provider, selectedModel, conversation, generateResponse, enableTools]); - - const handleClearConversation = useCallback(() => { - setConversation([]); - setResponse(''); - }, []); - - return ( -
-
-

- Inference Provider Test -

- - {/* Authentication Section */} -
-

- Authentication -

- - {!isAuthenticated ? ( -
- {/* API Key Auth */} -
- setApiKey(e.target.value)} - /> - -
- - {/* OAuth Auth */} -
- -
-
- ) : ( -
- - ✓ Authenticated with {provider?.name} - - -
- )} -
- - {/* Model Selection */} - {isAuthenticated && ( -
-
-

- Model Selection -

- -
- - {models.length > 0 ? ( -
- - - {selectedModel && ( -
- Context: {selectedModel.contextLength} tokens | - Max output: {selectedModel.capabilities.maxTokens} tokens | - Tools: ✓ (all models support tools) -
- )} -
- ) : ( -

No models loaded

- )} -
- )} - - {/* Chat Interface */} - {isAuthenticated && selectedModel && ( -
-
-

- Chat Test -

- - -
- - {/* Tool Test Suggestions */} - {enableTools && ( -
-

- Tool Test Suggestions: -

-
-
• "What's the weather in San Francisco?"
-
• "Calculate 123 + 456"
-
• "What time is it in London?"
-
• "Get weather for Tokyo and add 10 + 20"
-
-
- Available tools: get_weather, calculate_sum, get_current_time -
-
- )} - - {/* Conversation */} - {conversation.length > 0 && ( -
- {conversation.map((msg, index) => ( -
-
- {msg.role === 'user' && '👤 You'} - {msg.role === 'assistant' && '🤖 Assistant'} - {msg.role === 'tool' && '🛠️ Tool Result'} -
- -
- {typeof msg.content === 'string' ? msg.content : JSON.stringify(msg.content)} -
- - {msg.toolCalls && msg.toolCalls.length > 0 && ( -
- {msg.toolCalls.map((toolCall, tcIndex) => ( -
-
- 🔧 {toolCall.function.name} -
-
- {JSON.stringify(toolCall.function.arguments, null, 2)} -
-
- ))} -
- )} - - {msg.toolCallId && ( -
- ↳ Response to tool call: {msg.toolCallId} -
- )} -
- ))} -
- )} - - {/* Message Input */} -
- setMessage(e.target.value)} - onKeyPress={(e) => e.key === 'Enter' && handleSendMessage()} - /> - -
-
- )} - - {/* Error Display */} - {error && ( -
-

Error: {error}

-
- )} - - {/* Response Debug */} - {response && ( -
-

- Last Response (Debug): -

-
-              {response}
-            
-
- )} -
-
- ); -} \ No newline at end of file diff --git a/src/components/MCPTest.tsx b/src/components/MCPTest.tsx deleted file mode 100644 index a04d943..0000000 --- a/src/components/MCPTest.tsx +++ /dev/null @@ -1,478 +0,0 @@ -// Test UI for MCP provider functionality - -import { useState, useCallback } from 'react'; -import { useMCP } from '@/contexts/MCPContext'; -import type { MCPServerConfig } from '@/types/mcp'; - -export function MCPTest() { - const { - connections, - isLoading, - error, - addMcpServer, - removeMcpServer, - reconnectServer, - getAllTools, - getToolsForServer, - callTool, - getAllResources, - getConnectedServers, - } = useMCP(); - - const [newServerName, setNewServerName] = useState(''); - const [newServerUrl, setNewServerUrl] = useState(''); - const [selectedConnectionId, setSelectedConnectionId] = useState(''); - const [selectedToolName, setSelectedToolName] = useState(''); - const [toolArgs, setToolArgs] = useState('{}'); - const [toolResult, setToolResult] = useState(''); - - const handleAddServer = useCallback(async () => { - if (!newServerName.trim() || !newServerUrl.trim()) { - alert('Please enter both server name and URL'); - return; - } - - const trimmedName = newServerName.trim(); - - // Check for duplicate server names - const existingServer = connections.find(conn => conn.name === trimmedName); - if (existingServer) { - alert(`A server with the name "${trimmedName}" already exists. Please choose a different name.`); - return; - } - - const config: MCPServerConfig = { - name: trimmedName, - url: newServerUrl.trim(), - transport: 'auto', - authType: 'none', - autoReconnect: false, // Disable auto-reconnect for now to prevent loops - }; - - try { - await addMcpServer(config); - setNewServerName(''); - setNewServerUrl(''); - } catch (error) { - console.error('Failed to add server:', error); - alert(`Failed to add server: ${error instanceof Error ? error.message : 'Unknown error'}`); - } - }, [newServerName, newServerUrl, addMcpServer, connections]); - - const handleAddServerWithOAuth = useCallback(async () => { - if (!newServerName.trim() || !newServerUrl.trim()) { - alert('Please enter both server name and URL'); - return; - } - - const trimmedName = newServerName.trim(); - - // Check for duplicate server names - const existingServer = connections.find(conn => conn.name === trimmedName); - if (existingServer) { - alert(`A server with the name "${trimmedName}" already exists. Please choose a different name.`); - return; - } - - const config: MCPServerConfig = { - name: trimmedName, - url: newServerUrl.trim(), - transport: 'auto', - authType: 'oauth', - autoReconnect: false, - }; - - try { - await addMcpServer(config); - setNewServerName(''); - setNewServerUrl(''); - } catch (error) { - console.error('Failed to add server with OAuth:', error); - alert(`Failed to add server with OAuth: ${error instanceof Error ? error.message : 'Unknown error'}`); - } - }, [newServerName, newServerUrl, addMcpServer, connections]); - - const handleRemoveServer = useCallback((connectionId: string) => { - if (confirm('Are you sure you want to remove this server?')) { - removeMcpServer(connectionId); - if (selectedConnectionId === connectionId) { - setSelectedConnectionId(''); - } - } - }, [removeMcpServer, selectedConnectionId]); - - const handleReconnectServer = useCallback(async (connectionId: string) => { - try { - await reconnectServer(connectionId); - } catch (error) { - console.error('Failed to reconnect:', error); - alert(`Failed to reconnect: ${error instanceof Error ? error.message : 'Unknown error'}`); - } - }, [reconnectServer]); - - const handleCallTool = useCallback(async () => { - if (!selectedConnectionId || !selectedToolName) { - alert('Please select a connection and tool'); - return; - } - - try { - const args = JSON.parse(toolArgs); - const result = await callTool(selectedConnectionId, selectedToolName, args); - setToolResult(JSON.stringify(result, null, 2)); - } catch (error) { - console.error('Tool call failed:', error); - const errorResult = { - error: error instanceof Error ? error.message : 'Unknown error', - details: error, - }; - setToolResult(JSON.stringify(errorResult, null, 2)); - } - }, [selectedConnectionId, selectedToolName, toolArgs, callTool]); - - const getStatusColor = (status: string) => { - switch (status) { - case 'connected': return 'text-green-600 dark:text-green-400'; - case 'connecting': return 'text-yellow-600 dark:text-yellow-400'; - case 'failed': return 'text-red-600 dark:text-red-400'; - case 'disconnected': return 'text-gray-600 dark:text-gray-400'; - default: return 'text-gray-600 dark:text-gray-400'; - } - }; - - const getStatusIcon = (status: string) => { - switch (status) { - case 'connected': return '✅'; - case 'connecting': return '🔄'; - case 'failed': return '❌'; - case 'disconnected': return '⚫'; - default: return '❓'; - } - }; - - const selectedConnection = connections.find(conn => conn.id === selectedConnectionId); - const selectedTools = selectedConnection ? getToolsForServer(selectedConnectionId) : []; - const allTools = getAllTools(); - const allResources = getAllResources(); - const connectedServers = getConnectedServers(); - - return ( -
-
-

- MCP Provider Test -

- - {/* Add Server Section */} -
-

- Add MCP Server -

- - {/* Quick Add Examples */} -
-

- Quick Add Examples -

-
- - -
-

- Click to auto-fill common server configurations -

-
- -
- setNewServerName(e.target.value)} - /> - setNewServerUrl(e.target.value)} - /> -
- -
- - -
-
- - {/* Server List */} -
-

- Connected Servers ({connections.length}) -

- - {connections.length === 0 ? ( -

No servers added yet.

- ) : ( -
- {connections.map((connection) => ( -
-
-
-
- {getStatusIcon(connection.status)} -
-

- {connection.name} -

-

- {connection.url} -

-
-
- -
- - Status: {connection.status} - - - Transport: {connection.transport} - - - Tools: {connection.tools.length} - - - Resources: {connection.resources.length} - - {connection.connectionAttempts > 0 && ( - - Attempts: {connection.connectionAttempts} - - )} -
- - {connection.error && ( -
- Error: {connection.error} -
- )} - - {connection.lastConnected && ( -
- Last connected: {connection.lastConnected.toLocaleString()} -
- )} -
- -
- {connection.status === 'failed' && ( - - )} - -
-
-
- ))} -
- )} -
- - {/* Tool Testing */} - {connectedServers.length > 0 && ( -
-

- Tool Testing -

- -
- {/* Server Selection */} -
- - -
- - {/* Tool Selection */} -
- - -
-
- - {/* Tool Arguments */} -
- -