Skip to content

Commit 5026457

Browse files
committed
added chat to UI and agent flow but chat not working
1 parent 110812f commit 5026457

2 files changed

Lines changed: 260 additions & 0 deletions

File tree

static/js/chat.js

Lines changed: 193 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,193 @@
1+
// Chat functionality for MCP Agent
2+
class ChatInterface {
3+
constructor() {
4+
this.chatMessages = document.getElementById('chatMessages');
5+
this.chatInput = document.getElementById('chatInput');
6+
this.chatForm = document.getElementById('chatForm');
7+
this.sendButton = document.getElementById('sendButton');
8+
this.statusIndicator = document.getElementById('statusIndicator');
9+
this.sessionId = null;
10+
11+
this.init();
12+
}
13+
14+
async init() {
15+
// Initialize chat session
16+
try {
17+
await this.initializeSession();
18+
this.setupEventListeners();
19+
this.enableInterface();
20+
this.updateStatus('Ready to chat!', 'connected');
21+
} catch (error) {
22+
console.error('Failed to initialize chat:', error);
23+
this.updateStatus('Failed to connect to AI service', 'error');
24+
}
25+
}
26+
27+
async initializeSession() {
28+
try {
29+
const response = await fetch('/api/chat/session', {
30+
method: 'POST',
31+
headers: {
32+
'Content-Type': 'application/json'
33+
}
34+
});
35+
36+
if (!response.ok) {
37+
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
38+
}
39+
40+
const data = await response.json();
41+
this.sessionId = data.session_id;
42+
console.log('Chat session initialized:', this.sessionId);
43+
} catch (error) {
44+
console.error('Session initialization failed:', error);
45+
throw error;
46+
}
47+
}
48+
49+
setupEventListeners() {
50+
this.chatForm.addEventListener('submit', (e) => {
51+
e.preventDefault();
52+
this.sendMessage();
53+
});
54+
55+
this.chatInput.addEventListener('keypress', (e) => {
56+
if (e.key === 'Enter' && !e.shiftKey) {
57+
e.preventDefault();
58+
this.sendMessage();
59+
}
60+
});
61+
}
62+
63+
enableInterface() {
64+
this.chatInput.disabled = false;
65+
this.sendButton.disabled = false;
66+
this.chatInput.focus();
67+
}
68+
69+
disableInterface() {
70+
this.chatInput.disabled = true;
71+
this.sendButton.disabled = true;
72+
}
73+
74+
updateStatus(message, type = 'info') {
75+
this.statusIndicator.innerHTML = `<span class="status-text status-${type}">${message}</span>`;
76+
}
77+
78+
async sendMessage() {
79+
const message = this.chatInput.value.trim();
80+
if (!message || !this.sessionId) return;
81+
82+
// Add user message to chat
83+
this.addMessage(message, 'user');
84+
this.chatInput.value = '';
85+
86+
// Show loading state
87+
this.setLoading(true);
88+
this.updateStatus('AI is thinking...', 'processing');
89+
90+
try {
91+
const response = await fetch('/api/chat/message', {
92+
method: 'POST',
93+
headers: {
94+
'Content-Type': 'application/json'
95+
},
96+
body: JSON.stringify({
97+
message: message,
98+
session_id: this.sessionId
99+
})
100+
});
101+
102+
if (!response.ok) {
103+
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
104+
}
105+
106+
const data = await response.json();
107+
108+
// Add assistant response
109+
this.addMessage(data.response, 'assistant');
110+
111+
// If there were tool calls, show them
112+
if (data.tool_calls && data.tool_calls.length > 0) {
113+
this.showToolCalls(data.tool_calls);
114+
}
115+
116+
this.updateStatus('Ready to chat!', 'connected');
117+
} catch (error) {
118+
console.error('Send message failed:', error);
119+
this.addMessage('Sorry, I encountered an error processing your request. Please try again.', 'assistant', true);
120+
this.updateStatus('Error occurred', 'error');
121+
} finally {
122+
this.setLoading(false);
123+
}
124+
}
125+
126+
addMessage(content, sender, isError = false) {
127+
const messageDiv = document.createElement('div');
128+
messageDiv.className = `message ${sender}-message${isError ? ' error-message' : ''}`;
129+
130+
const timestamp = new Date().toLocaleTimeString();
131+
132+
messageDiv.innerHTML = `
133+
<div class="message-content">
134+
<strong>${sender === 'user' ? 'You' : 'AI Assistant'}:</strong> ${this.formatMessage(content)}
135+
</div>
136+
<div class="message-time">${timestamp}</div>
137+
`;
138+
139+
this.chatMessages.appendChild(messageDiv);
140+
this.scrollToBottom();
141+
}
142+
143+
showToolCalls(toolCalls) {
144+
const toolCallDiv = document.createElement('div');
145+
toolCallDiv.className = 'message tool-call-message';
146+
147+
const timestamp = new Date().toLocaleTimeString();
148+
let toolCallsHtml = '<div class="message-content"><strong>Tool Calls:</strong><ul>';
149+
150+
toolCalls.forEach(call => {
151+
toolCallsHtml += `<li><code>${call.tool_name}</code> - ${call.description || 'Tool executed'}</li>`;
152+
});
153+
154+
toolCallsHtml += '</ul></div>';
155+
toolCallDiv.innerHTML = toolCallsHtml + `<div class="message-time">${timestamp}</div>`;
156+
157+
this.chatMessages.appendChild(toolCallDiv);
158+
this.scrollToBottom();
159+
}
160+
161+
formatMessage(content) {
162+
// Basic formatting for messages
163+
return content
164+
.replace(/\n/g, '<br>')
165+
.replace(/\*\*(.*?)\*\*/g, '<strong>$1</strong>')
166+
.replace(/\*(.*?)\*/g, '<em>$1</em>')
167+
.replace(/`(.*?)`/g, '<code>$1</code>');
168+
}
169+
170+
setLoading(loading) {
171+
const sendText = this.sendButton.querySelector('.send-text');
172+
const sendLoading = this.sendButton.querySelector('.send-loading');
173+
174+
if (loading) {
175+
sendText.style.display = 'none';
176+
sendLoading.style.display = 'inline-block';
177+
this.disableInterface();
178+
} else {
179+
sendText.style.display = 'inline-block';
180+
sendLoading.style.display = 'none';
181+
this.enableInterface();
182+
}
183+
}
184+
185+
scrollToBottom() {
186+
this.chatMessages.scrollTop = this.chatMessages.scrollHeight;
187+
}
188+
}
189+
190+
// Initialize chat interface when DOM is loaded
191+
document.addEventListener('DOMContentLoaded', () => {
192+
new ChatInterface();
193+
});

templates/chat.html

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8">
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
6+
<title>MCP Agent Chat - To-do List App</title>
7+
<link rel="stylesheet" href="/static/css/style.css">
8+
</head>
9+
<body>
10+
<div class="container">
11+
<!-- Header -->
12+
<div class="header">
13+
<h1>MCP Agent Chat</h1>
14+
<p>AI-powered todo management with Azure AI Foundry</p>
15+
</div>
16+
17+
<!-- Navigation -->
18+
<div class="navigation-tabs">
19+
<a href="/" class="nav-tab">Todo List</a>
20+
<a href="/chat" class="nav-tab active">AI Chat</a>
21+
</div>
22+
23+
<!-- Chat Interface -->
24+
<div class="chat-container">
25+
<div class="chat-messages" id="chatMessages">
26+
<div class="message assistant-message">
27+
<div class="message-content">
28+
<strong>AI Assistant:</strong> Hi! I'm your AI assistant powered by Azure AI Foundry with MCP integration. I can help you manage your todos through natural language. Try asking me to "create a new todo" or "show me all my todos"!
29+
</div>
30+
<div class="message-time" id="initialTime"></div>
31+
</div>
32+
</div>
33+
34+
<div class="chat-input-container">
35+
<form id="chatForm" class="chat-form">
36+
<div class="input-group">
37+
<input
38+
type="text"
39+
id="chatInput"
40+
placeholder="Ask me to manage your todos... (e.g., 'Create a high priority todo to finish the project')"
41+
class="chat-input"
42+
disabled
43+
>
44+
<button type="submit" id="sendButton" class="send-button" disabled>
45+
<span class="send-text">Send</span>
46+
<span class="send-loading" style="display: none;">
47+
<span class="spinner"></span>
48+
</span>
49+
</button>
50+
</div>
51+
</form>
52+
</div>
53+
</div>
54+
55+
<!-- Status indicator -->
56+
<div class="status-indicator" id="statusIndicator">
57+
<span class="status-text">Connecting to AI service...</span>
58+
</div>
59+
</div>
60+
61+
<script src="/static/js/chat.js"></script>
62+
<script>
63+
// Set initial timestamp
64+
document.getElementById('initialTime').textContent = new Date().toLocaleTimeString();
65+
</script>
66+
</body>
67+
</html>

0 commit comments

Comments
 (0)