chat agent
This commit is contained in:
parent
b9c6c831c1
commit
b44e4ed6f9
11 changed files with 626 additions and 16 deletions
|
|
@ -66,19 +66,39 @@
|
|||
<h2>Recent Activity</h2>
|
||||
<p>Track latest agent executions across all directives.</p>
|
||||
</header>
|
||||
<div class="dashboard-content glass">
|
||||
<table class="activity-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Directive</th>
|
||||
<th>Status</th>
|
||||
<th>Date</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="recent-runs-list">
|
||||
<!-- Recent runs will be injected here -->
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="dashboard-content-grid">
|
||||
<div class="dashboard-content glass">
|
||||
<table class="activity-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Directive</th>
|
||||
<th>Status</th>
|
||||
<th>Date</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="recent-runs-list">
|
||||
<!-- Recent runs will be injected here -->
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div id="chat-container" class="chat-container glass">
|
||||
<div class="chat-header">
|
||||
<h3>Quick Chat</h3>
|
||||
<button id="clear-chat-btn" class="btn btn-ghost btn-sm">Clear</button>
|
||||
</div>
|
||||
<div id="chat-messages" class="chat-messages">
|
||||
<!-- Chat messages will be injected here -->
|
||||
<div class="chat-empty-state">
|
||||
<p>Start a conversation with the assistant.</p>
|
||||
</div>
|
||||
</div>
|
||||
<form id="chat-form" class="chat-form">
|
||||
<input type="text" id="chat-input" placeholder="Type a message..." autocomplete="off"
|
||||
required>
|
||||
<button type="submit" id="chat-send-btn" class="btn btn-primary btn-sm">Send</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -16,7 +16,8 @@ const state = {
|
|||
selectedRunId: null,
|
||||
currentView: 'dashboard', // 'dashboard' or 'task'
|
||||
isEditing: false,
|
||||
isAuthenticated: false
|
||||
isAuthenticated: false,
|
||||
chatMessages: []
|
||||
};
|
||||
// DOM elements
|
||||
const loginOverlay = document.getElementById('login-overlay');
|
||||
|
|
@ -53,6 +54,11 @@ const schedulePresets = document.getElementById('schedule-presets');
|
|||
const toggleCustomCronBtn = document.getElementById('toggle-custom-cron');
|
||||
const customCronContainer = document.getElementById('custom-cron-container');
|
||||
const presetBtns = document.querySelectorAll('.btn-preset');
|
||||
const chatMessagesEl = document.getElementById('chat-messages');
|
||||
const chatForm = document.getElementById('chat-form');
|
||||
const chatInput = document.getElementById('chat-input');
|
||||
const clearChatBtn = document.getElementById('clear-chat-btn');
|
||||
const chatSendBtn = document.getElementById('chat-send-btn');
|
||||
|
||||
function updateState(newState) {
|
||||
Object.assign(state, newState);
|
||||
|
|
@ -89,6 +95,7 @@ function renderApp() {
|
|||
|
||||
if (state.currentView === 'dashboard') {
|
||||
fetchRecentRuns();
|
||||
renderChat();
|
||||
} else if (state.selectedTaskId) {
|
||||
const task = state.tasks.find(t => t.id === state.selectedTaskId);
|
||||
if (task) {
|
||||
|
|
@ -354,6 +361,62 @@ function escapeHtml(text) {
|
|||
return div.innerHTML;
|
||||
}
|
||||
|
||||
function renderChat() {
|
||||
if (!chatMessagesEl) return;
|
||||
|
||||
if (state.chatMessages.length === 0) {
|
||||
chatMessagesEl.innerHTML = `
|
||||
<div class="chat-empty-state">
|
||||
<p>Start a conversation with the assistant.</p>
|
||||
</div>
|
||||
`;
|
||||
return;
|
||||
}
|
||||
|
||||
chatMessagesEl.innerHTML = state.chatMessages
|
||||
.map(msg => `
|
||||
<div class="chat-message ${msg.role}">
|
||||
${escapeHtml(msg.content)}
|
||||
</div>
|
||||
`)
|
||||
.join('');
|
||||
|
||||
chatMessagesEl.scrollTop = chatMessagesEl.scrollHeight;
|
||||
}
|
||||
|
||||
async function sendChatMessage(text) {
|
||||
const userMessage = { role: 'user', content: text };
|
||||
state.chatMessages.push(userMessage);
|
||||
renderChat();
|
||||
|
||||
chatInput.value = '';
|
||||
chatInput.disabled = true;
|
||||
chatSendBtn.disabled = true;
|
||||
|
||||
try {
|
||||
const response = await fetchWithAuth(`${API_URL}/chat`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ messages: state.chatMessages })
|
||||
});
|
||||
|
||||
if (!response.ok) throw new Error('Chat API failed');
|
||||
|
||||
const result = await response.json();
|
||||
state.chatMessages.push(result.message);
|
||||
renderChat();
|
||||
} catch (error) {
|
||||
console.error('Chat error:', error);
|
||||
showToast('Failed to get chat response.', 'error');
|
||||
state.chatMessages.push({ role: 'assistant', content: 'Sorry, I encountered an error. Please try again.' });
|
||||
renderChat();
|
||||
} finally {
|
||||
chatInput.disabled = false;
|
||||
chatSendBtn.disabled = false;
|
||||
chatInput.focus();
|
||||
}
|
||||
}
|
||||
|
||||
// Event Listeners
|
||||
rerunBtn.addEventListener('click', async () => {
|
||||
if (!state.selectedTaskId) return;
|
||||
|
|
@ -447,6 +510,19 @@ toggleCustomCronBtn.addEventListener('click', () => {
|
|||
customCronContainer.classList.toggle('hidden');
|
||||
});
|
||||
|
||||
chatForm.addEventListener('submit', (e) => {
|
||||
e.preventDefault();
|
||||
const text = chatInput.value.trim();
|
||||
if (text) {
|
||||
sendChatMessage(text);
|
||||
}
|
||||
});
|
||||
|
||||
clearChatBtn.addEventListener('click', () => {
|
||||
state.chatMessages = [];
|
||||
renderChat();
|
||||
});
|
||||
|
||||
cronInput.addEventListener('input', () => {
|
||||
// If user types manually, update presets active state
|
||||
updateScheduleUI(cronInput.value);
|
||||
|
|
|
|||
|
|
@ -124,6 +124,104 @@ body {
|
|||
background: rgba(255, 255, 255, 0.03);
|
||||
}
|
||||
|
||||
.dashboard-content-grid {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 350px;
|
||||
gap: 24px;
|
||||
flex: 1;
|
||||
min-height: 0;
|
||||
}
|
||||
|
||||
.chat-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
border-radius: 12px;
|
||||
overflow: hidden;
|
||||
background: rgba(255, 255, 255, 0.02);
|
||||
}
|
||||
|
||||
.chat-header {
|
||||
padding: 16px 20px;
|
||||
background: rgba(255, 255, 255, 0.03);
|
||||
border-bottom: 1px solid var(--glass-border);
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.chat-header h3 {
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: var(--text-dim);
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.5px;
|
||||
}
|
||||
|
||||
.chat-messages {
|
||||
flex: 1;
|
||||
padding: 20px;
|
||||
overflow-y: auto;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.chat-empty-state {
|
||||
margin: auto;
|
||||
text-align: center;
|
||||
color: var(--text-dim);
|
||||
font-style: italic;
|
||||
font-size: 13px;
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
.chat-message {
|
||||
max-width: 85%;
|
||||
padding: 10px 14px;
|
||||
border-radius: 12px;
|
||||
font-size: 14px;
|
||||
line-height: 1.4;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
.chat-message.user {
|
||||
align-self: flex-end;
|
||||
background: var(--primary);
|
||||
color: white;
|
||||
border-bottom-right-radius: 4px;
|
||||
}
|
||||
|
||||
.chat-message.assistant {
|
||||
align-self: flex-start;
|
||||
background: rgba(255, 255, 255, 0.08);
|
||||
color: var(--text-main);
|
||||
border-bottom-left-radius: 4px;
|
||||
}
|
||||
|
||||
.chat-form {
|
||||
padding: 16px;
|
||||
background: rgba(255, 255, 255, 0.02);
|
||||
border-top: 1px solid var(--glass-border);
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.chat-form input {
|
||||
flex: 1;
|
||||
background: rgba(0, 0, 0, 0.2);
|
||||
border: 1px solid var(--glass-border);
|
||||
border-radius: 6px;
|
||||
padding: 8px 12px;
|
||||
color: var(--text-main);
|
||||
font-size: 14px;
|
||||
outline: none;
|
||||
transition: var(--transition);
|
||||
}
|
||||
|
||||
.chat-form input:focus {
|
||||
border-color: var(--primary);
|
||||
}
|
||||
|
||||
.activity-table .status-badge {
|
||||
display: inline-block;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue