modify main.js to English

This commit is contained in:
xiangjinyu 2025-03-10 16:24:07 +08:00
parent 81b9bb3660
commit 110213a29f

View File

@ -5,7 +5,7 @@ function createTask() {
const prompt = promptInput.value.trim(); const prompt = promptInput.value.trim();
if (!prompt) { if (!prompt) {
alert("请输入有效的提示内容"); alert("Please enter a valid prompt");
promptInput.focus(); promptInput.focus();
return; return;
} }
@ -16,7 +16,7 @@ function createTask() {
} }
const container = document.getElementById('task-container'); const container = document.getElementById('task-container');
container.innerHTML = '<div class="loading">任务初始化中...</div>'; container.innerHTML = '<div class="loading">Initializing task...</div>';
document.getElementById('input-container').classList.add('bottom'); document.getElementById('input-container').classList.add('bottom');
fetch('/tasks', { fetch('/tasks', {
@ -28,20 +28,20 @@ function createTask() {
}) })
.then(response => { .then(response => {
if (!response.ok) { if (!response.ok) {
return response.json().then(err => { throw new Error(err.detail || '请求失败') }); return response.json().then(err => { throw new Error(err.detail || 'Request failed') });
} }
return response.json(); return response.json();
}) })
.then(data => { .then(data => {
if (!data.task_id) { if (!data.task_id) {
throw new Error('无效的任务ID'); throw new Error('Invalid task ID');
} }
setupSSE(data.task_id); setupSSE(data.task_id);
loadHistory(); loadHistory();
}) })
.catch(error => { .catch(error => {
container.innerHTML = `<div class="error">错误: ${error.message}</div>`; container.innerHTML = `<div class="error">Error: ${error.message}</div>`;
console.error('创建任务失败:', error); console.error('Failed to create task:', error);
}); });
} }
@ -49,13 +49,13 @@ function setupSSE(taskId) {
let retryCount = 0; let retryCount = 0;
const maxRetries = 3; const maxRetries = 3;
const retryDelay = 2000; const retryDelay = 2000;
function connect() { function connect() {
const eventSource = new EventSource(`/tasks/${taskId}/events`); const eventSource = new EventSource(`/tasks/${taskId}/events`);
currentEventSource = eventSource; currentEventSource = eventSource;
const container = document.getElementById('task-container'); const container = document.getElementById('task-container');
let heartbeatTimer = setInterval(() => { let heartbeatTimer = setInterval(() => {
container.innerHTML += '<div class="ping">·</div>'; container.innerHTML += '<div class="ping">·</div>';
}, 5000); }, 5000);
@ -67,13 +67,13 @@ function setupSSE(taskId) {
updateTaskStatus(task); updateTaskStatus(task);
}) })
.catch(error => { .catch(error => {
console.error('轮询失败:', error); console.error('Polling failed:', error);
}); });
}, 10000); }, 10000);
if (!eventSource._listenersAdded) { if (!eventSource._listenersAdded) {
eventSource._listenersAdded = true; eventSource._listenersAdded = true;
let lastResultContent = ''; let lastResultContent = '';
eventSource.addEventListener('status', (event) => { eventSource.addEventListener('status', (event) => {
clearInterval(heartbeatTimer); clearInterval(heartbeatTimer);
@ -92,9 +92,9 @@ function setupSSE(taskId) {
stepContainer = container.querySelector('.step-container'); stepContainer = container.querySelector('.step-container');
} }
// 保存result内容 // Save result content
if (data.steps && data.steps.length > 0) { if (data.steps && data.steps.length > 0) {
// 遍历所有步骤找到最后一个result类型 // Iterate through all steps, find the last result type
for (let i = data.steps.length - 1; i >= 0; i--) { for (let i = data.steps.length - 1; i >= 0; i--) {
if (data.steps[i].type === 'result') { if (data.steps[i].type === 'result') {
lastResultContent = data.steps[i].result; lastResultContent = data.steps[i].result;
@ -116,24 +116,24 @@ function setupSSE(taskId) {
</div> </div>
`; `;
}).join(''); }).join('');
// Auto-scroll to bottom // Auto-scroll to bottom
container.scrollTo({ container.scrollTo({
top: container.scrollHeight, top: container.scrollHeight,
behavior: 'smooth' behavior: 'smooth'
}); });
} catch (e) { } catch (e) {
console.error('状态更新失败:', e); console.error('Status update failed:', e);
} }
}); });
// 添加对think事件的处理 // Add handler for think event
eventSource.addEventListener('think', (event) => { eventSource.addEventListener('think', (event) => {
clearInterval(heartbeatTimer); clearInterval(heartbeatTimer);
try { try {
const data = JSON.parse(event.data); const data = JSON.parse(event.data);
container.querySelector('.loading')?.remove(); container.querySelector('.loading')?.remove();
let stepContainer = container.querySelector('.step-container'); let stepContainer = container.querySelector('.step-container');
if (!stepContainer) { if (!stepContainer) {
container.innerHTML = '<div class="step-container"></div>'; container.innerHTML = '<div class="step-container"></div>';
@ -142,7 +142,7 @@ function setupSSE(taskId) {
const content = data.result; const content = data.result;
const timestamp = new Date().toLocaleTimeString(); const timestamp = new Date().toLocaleTimeString();
const step = document.createElement('div'); const step = document.createElement('div');
step.className = 'step-item think'; step.className = 'step-item think';
step.innerHTML = ` step.innerHTML = `
@ -151,34 +151,34 @@ function setupSSE(taskId) {
<pre>${content}</pre> <pre>${content}</pre>
</div> </div>
`; `;
stepContainer.appendChild(step); stepContainer.appendChild(step);
container.scrollTo({ container.scrollTo({
top: container.scrollHeight, top: container.scrollHeight,
behavior: 'smooth' behavior: 'smooth'
}); });
// 更新任务状态 // Update task status
fetch(`/tasks/${taskId}`) fetch(`/tasks/${taskId}`)
.then(response => response.json()) .then(response => response.json())
.then(task => { .then(task => {
updateTaskStatus(task); updateTaskStatus(task);
}) })
.catch(error => { .catch(error => {
console.error('状态更新失败:', error); console.error('Status update failed:', error);
}); });
} catch (e) { } catch (e) {
console.error('思考事件处理失败:', e); console.error('Think event handling failed:', e);
} }
}); });
// 添加对tool事件的处理 // Add handler for tool event
eventSource.addEventListener('tool', (event) => { eventSource.addEventListener('tool', (event) => {
clearInterval(heartbeatTimer); clearInterval(heartbeatTimer);
try { try {
const data = JSON.parse(event.data); const data = JSON.parse(event.data);
container.querySelector('.loading')?.remove(); container.querySelector('.loading')?.remove();
let stepContainer = container.querySelector('.step-container'); let stepContainer = container.querySelector('.step-container');
if (!stepContainer) { if (!stepContainer) {
container.innerHTML = '<div class="step-container"></div>'; container.innerHTML = '<div class="step-container"></div>';
@ -187,7 +187,7 @@ function setupSSE(taskId) {
const content = data.result; const content = data.result;
const timestamp = new Date().toLocaleTimeString(); const timestamp = new Date().toLocaleTimeString();
const step = document.createElement('div'); const step = document.createElement('div');
step.className = 'step-item tool'; step.className = 'step-item tool';
step.innerHTML = ` step.innerHTML = `
@ -196,34 +196,34 @@ function setupSSE(taskId) {
<pre>${content}</pre> <pre>${content}</pre>
</div> </div>
`; `;
stepContainer.appendChild(step); stepContainer.appendChild(step);
container.scrollTo({ container.scrollTo({
top: container.scrollHeight, top: container.scrollHeight,
behavior: 'smooth' behavior: 'smooth'
}); });
// 更新任务状态 // Update task status
fetch(`/tasks/${taskId}`) fetch(`/tasks/${taskId}`)
.then(response => response.json()) .then(response => response.json())
.then(task => { .then(task => {
updateTaskStatus(task); updateTaskStatus(task);
}) })
.catch(error => { .catch(error => {
console.error('状态更新失败:', error); console.error('Status update failed:', error);
}); });
} catch (e) { } catch (e) {
console.error('工具事件处理失败:', e); console.error('Tool event handling failed:', e);
} }
}); });
// 添加对act事件的处理 // Add handler for act event
eventSource.addEventListener('act', (event) => { eventSource.addEventListener('act', (event) => {
clearInterval(heartbeatTimer); clearInterval(heartbeatTimer);
try { try {
const data = JSON.parse(event.data); const data = JSON.parse(event.data);
container.querySelector('.loading')?.remove(); container.querySelector('.loading')?.remove();
let stepContainer = container.querySelector('.step-container'); let stepContainer = container.querySelector('.step-container');
if (!stepContainer) { if (!stepContainer) {
container.innerHTML = '<div class="step-container"></div>'; container.innerHTML = '<div class="step-container"></div>';
@ -232,7 +232,7 @@ function setupSSE(taskId) {
const content = data.result; const content = data.result;
const timestamp = new Date().toLocaleTimeString(); const timestamp = new Date().toLocaleTimeString();
const step = document.createElement('div'); const step = document.createElement('div');
step.className = 'step-item act'; step.className = 'step-item act';
step.innerHTML = ` step.innerHTML = `
@ -241,35 +241,34 @@ function setupSSE(taskId) {
<pre>${content}</pre> <pre>${content}</pre>
</div> </div>
`; `;
stepContainer.appendChild(step); stepContainer.appendChild(step);
container.scrollTo({ container.scrollTo({
top: container.scrollHeight, top: container.scrollHeight,
behavior: 'smooth' behavior: 'smooth'
}); });
// 更新任务状态 // Update task status
fetch(`/tasks/${taskId}`) fetch(`/tasks/${taskId}`)
.then(response => response.json()) .then(response => response.json())
.then(task => { .then(task => {
updateTaskStatus(task); updateTaskStatus(task);
}) })
.catch(error => { .catch(error => {
console.error('状态更新失败:', error); console.error('Status update failed:', error);
}); });
} catch (e) { } catch (e) {
console.error('执行事件处理失败:', e); console.error('Act event handling failed:', e);
} }
}); });
// 添加对run事件的处理 // Add handler for log event
// 添加对log事件的处理
eventSource.addEventListener('log', (event) => { eventSource.addEventListener('log', (event) => {
clearInterval(heartbeatTimer); clearInterval(heartbeatTimer);
try { try {
const data = JSON.parse(event.data); const data = JSON.parse(event.data);
container.querySelector('.loading')?.remove(); container.querySelector('.loading')?.remove();
let stepContainer = container.querySelector('.step-container'); let stepContainer = container.querySelector('.step-container');
if (!stepContainer) { if (!stepContainer) {
container.innerHTML = '<div class="step-container"></div>'; container.innerHTML = '<div class="step-container"></div>';
@ -278,7 +277,7 @@ function setupSSE(taskId) {
const content = data.result; const content = data.result;
const timestamp = new Date().toLocaleTimeString(); const timestamp = new Date().toLocaleTimeString();
const step = document.createElement('div'); const step = document.createElement('div');
step.className = 'step-item log'; step.className = 'step-item log';
step.innerHTML = ` step.innerHTML = `
@ -287,24 +286,24 @@ function setupSSE(taskId) {
<pre>${content}</pre> <pre>${content}</pre>
</div> </div>
`; `;
stepContainer.appendChild(step); stepContainer.appendChild(step);
container.scrollTo({ container.scrollTo({
top: container.scrollHeight, top: container.scrollHeight,
behavior: 'smooth' behavior: 'smooth'
}); });
// 更新任务状态 // Update task status
fetch(`/tasks/${taskId}`) fetch(`/tasks/${taskId}`)
.then(response => response.json()) .then(response => response.json())
.then(task => { .then(task => {
updateTaskStatus(task); updateTaskStatus(task);
}) })
.catch(error => { .catch(error => {
console.error('状态更新失败:', error); console.error('Status update failed:', error);
}); });
} catch (e) { } catch (e) {
console.error('日志事件处理失败:', e); console.error('Log event handling failed:', e);
} }
}); });
@ -313,7 +312,7 @@ function setupSSE(taskId) {
try { try {
const data = JSON.parse(event.data); const data = JSON.parse(event.data);
container.querySelector('.loading')?.remove(); container.querySelector('.loading')?.remove();
let stepContainer = container.querySelector('.step-container'); let stepContainer = container.querySelector('.step-container');
if (!stepContainer) { if (!stepContainer) {
container.innerHTML = '<div class="step-container"></div>'; container.innerHTML = '<div class="step-container"></div>';
@ -322,7 +321,7 @@ function setupSSE(taskId) {
const content = data.result; const content = data.result;
const timestamp = new Date().toLocaleTimeString(); const timestamp = new Date().toLocaleTimeString();
const step = document.createElement('div'); const step = document.createElement('div');
step.className = 'step-item run'; step.className = 'step-item run';
step.innerHTML = ` step.innerHTML = `
@ -331,24 +330,24 @@ function setupSSE(taskId) {
<pre>${content}</pre> <pre>${content}</pre>
</div> </div>
`; `;
stepContainer.appendChild(step); stepContainer.appendChild(step);
container.scrollTo({ container.scrollTo({
top: container.scrollHeight, top: container.scrollHeight,
behavior: 'smooth' behavior: 'smooth'
}); });
// 更新任务状态 // Update task status
fetch(`/tasks/${taskId}`) fetch(`/tasks/${taskId}`)
.then(response => response.json()) .then(response => response.json())
.then(task => { .then(task => {
updateTaskStatus(task); updateTaskStatus(task);
}) })
.catch(error => { .catch(error => {
console.error('状态更新失败:', error); console.error('Status update failed:', error);
}); });
} catch (e) { } catch (e) {
console.error('运行事件处理失败:', e); console.error('Run event handling failed:', e);
} }
}); });
@ -363,35 +362,35 @@ function setupSSE(taskId) {
container.innerHTML = '<div class="step-container"></div>'; container.innerHTML = '<div class="step-container"></div>';
stepContainer = container.querySelector('.step-container'); stepContainer = container.querySelector('.step-container');
} }
// Create new step element // Create new step element
const step = document.createElement('div'); const step = document.createElement('div');
step.className = `step-item ${data.type || 'step'}`; step.className = `step-item ${data.type || 'step'}`;
// Format content and timestamp // Format content and timestamp
const content = data.result; const content = data.result;
const timestamp = new Date().toLocaleTimeString(); const timestamp = new Date().toLocaleTimeString();
step.innerHTML = ` step.innerHTML = `
<div class="log-line ${data.type || 'info'}"> <div class="log-line ${data.type || 'info'}">
<span class="log-prefix">${getEventIcon(data.type)} [${timestamp}] ${getEventLabel(data.type)}:</span> <span class="log-prefix">${getEventIcon(data.type)} [${timestamp}] ${getEventLabel(data.type)}:</span>
<pre>${content}</pre> <pre>${content}</pre>
</div> </div>
`; `;
// Add step to container with animation // Add step to container with animation
stepContainer.prepend(step); stepContainer.prepend(step);
setTimeout(() => { setTimeout(() => {
step.classList.add('show'); step.classList.add('show');
}, 10); }, 10);
// Auto-scroll to bottom // Auto-scroll to bottom
container.scrollTo({ container.scrollTo({
top: container.scrollHeight, top: container.scrollHeight,
behavior: 'smooth' behavior: 'smooth'
}); });
} catch (e) { } catch (e) {
console.error('消息处理失败:', e); console.error('Message handling failed:', e);
} }
}); });
@ -403,13 +402,13 @@ function setupSSE(taskId) {
clearInterval(pollInterval); clearInterval(pollInterval);
container.innerHTML += ` container.innerHTML += `
<div class="complete"> <div class="complete">
<div> 任务完成</div> <div> Task completed</div>
<pre>${lastResultContent}</pre> <pre>${lastResultContent}</pre>
</div> </div>
`; `;
eventSource.close(); eventSource.close();
currentEventSource = null; currentEventSource = null;
lastResultContent = ''; // 清空结果内容 lastResultContent = ''; // Clear result content
}); });
eventSource.addEventListener('error', (event) => { eventSource.addEventListener('error', (event) => {
@ -419,17 +418,17 @@ function setupSSE(taskId) {
const data = JSON.parse(event.data); const data = JSON.parse(event.data);
container.innerHTML += ` container.innerHTML += `
<div class="error"> <div class="error">
错误: ${data.message} Error: ${data.message}
</div> </div>
`; `;
eventSource.close(); eventSource.close();
currentEventSource = null; currentEventSource = null;
} catch (e) { } catch (e) {
console.error('错误处理失败:', e); console.error('Error handling failed:', e);
} }
}); });
} }
container.scrollTo({ container.scrollTo({
top: container.scrollHeight, top: container.scrollHeight,
behavior: 'smooth' behavior: 'smooth'
@ -439,30 +438,30 @@ function setupSSE(taskId) {
if (isTaskComplete) { if (isTaskComplete) {
return; return;
} }
console.error('SSE连接错误:', err); console.error('SSE connection error:', err);
clearInterval(heartbeatTimer); clearInterval(heartbeatTimer);
clearInterval(pollInterval); clearInterval(pollInterval);
eventSource.close(); eventSource.close();
if (retryCount < maxRetries) { if (retryCount < maxRetries) {
retryCount++; retryCount++;
container.innerHTML += ` container.innerHTML += `
<div class="warning"> <div class="warning">
连接中断${retryDelay/1000}秒后重试 (${retryCount}/${maxRetries})... Connection lost, retrying in ${retryDelay/1000} seconds (${retryCount}/${maxRetries})...
</div> </div>
`; `;
setTimeout(connect, retryDelay); setTimeout(connect, retryDelay);
} else { } else {
container.innerHTML += ` container.innerHTML += `
<div class="error"> <div class="error">
连接中断请尝试刷新页面 Connection lost, please try refreshing the page
</div> </div>
`; `;
} }
}; };
} }
connect(); connect();
} }
@ -474,112 +473,223 @@ function getEventIcon(eventType) {
case 'result': return '🏁'; case 'result': return '🏁';
case 'error': return '❌'; case 'error': return '❌';
case 'complete': return '✅'; case 'complete': return '✅';
case 'warning': return '⚠️';
case 'log': return '📝'; case 'log': return '📝';
default: return '⚡'; case 'run': return '⚙️';
default: return '';
} }
} }
function getEventLabel(eventType) { function getEventLabel(eventType) {
switch(eventType) { switch(eventType) {
case 'think': return '思考'; case 'think': return 'Thinking';
case 'tool': return '工具执行'; case 'tool': return 'Using Tool';
case 'act': return '执行'; case 'act': return 'Action';
case 'result': return '结果'; case 'result': return 'Result';
case 'error': return '错误'; case 'error': return 'Error';
case 'complete': return '完成'; case 'complete': return 'Complete';
case 'warning': return '警告'; case 'log': return 'Log';
case 'log': return '日志'; case 'run': return 'Running';
default: return '步骤'; default: return 'Info';
} }
} }
function formatContent(content) {
// Remove timestamp and log level prefixes
content = content.replace(/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d{3} \| [A-Z]+\s*\| /gm, '');
// Format the remaining content
return content
.replace(/\n/g, '<br>')
.replace(/ /g, '&nbsp;&nbsp;')
.replace(/✨ Manus's thoughts:/g, '')
.replace(/🛠️ Manus selected/g, '')
.replace(/🧰 Tools being prepared:/g, '')
.replace(/🔧 Activating tool:/g, '')
.replace(/🎯 Tool/g, '')
.replace(/📝 Oops!/g, '')
.replace(/🏁 Special tool/g, '');
}
function updateTaskStatus(task) { function updateTaskStatus(task) {
const taskCard = document.querySelector(`.task-card[data-task-id="${task.id}"]`); const statusBar = document.getElementById('status-bar');
if (taskCard) { if (!statusBar) return;
const statusEl = taskCard.querySelector('.task-meta .status');
if (statusEl) { if (task.status === 'completed') {
statusEl.className = `status-${task.status ? task.status.toLowerCase() : 'unknown'}`; statusBar.innerHTML = `<span class="status-complete">✅ Task completed</span>`;
statusEl.textContent = task.status || '未知状态'; } else if (task.status === 'failed') {
} statusBar.innerHTML = `<span class="status-error">❌ Task failed: ${task.error || 'Unknown error'}</span>`;
} else {
statusBar.innerHTML = `<span class="status-running">⚙️ Task running: ${task.status}</span>`;
} }
} }
function loadHistory() { function loadHistory() {
fetch('/tasks') fetch('/tasks')
.then(response => { .then(response => {
if (!response.ok) { if (!response.ok) {
return response.text().then(text => { throw new Error('Failed to load history');
throw new Error(`请求失败: ${response.status} - ${text.substring(0, 100)}`); }
return response.json();
})
.then(tasks => {
const historyContainer = document.getElementById('history-container');
if (!historyContainer) return;
historyContainer.innerHTML = '';
if (tasks.length === 0) {
historyContainer.innerHTML = '<div class="history-empty">No recent tasks</div>';
return;
}
const historyList = document.createElement('div');
historyList.className = 'history-list';
tasks.forEach(task => {
const taskItem = document.createElement('div');
taskItem.className = `history-item ${task.status}`;
taskItem.innerHTML = `
<div class="history-prompt">${task.prompt}</div>
<div class="history-meta">
<span class="history-time">${new Date(task.created_at).toLocaleString()}</span>
<span class="history-status">${getStatusIcon(task.status)}</span>
</div>
`;
taskItem.addEventListener('click', () => {
loadTask(task.id);
});
historyList.appendChild(taskItem);
}); });
}
return response.json(); historyContainer.appendChild(historyList);
}) })
.then(tasks => { .catch(error => {
const listContainer = document.getElementById('task-list'); console.error('Failed to load history:', error);
listContainer.innerHTML = tasks.map(task => ` const historyContainer = document.getElementById('history-container');
<div class="task-card" data-task-id="${task.id}"> if (historyContainer) {
<div>${task.prompt}</div> historyContainer.innerHTML = `<div class="error">Failed to load history: ${error.message}</div>`;
<div class="task-meta"> }
${new Date(task.created_at).toLocaleString()} - });
<span class="status status-${task.status ? task.status.toLowerCase() : 'unknown'}">
${task.status || '未知状态'}
</span>
</div>
</div>
`).join('');
})
.catch(error => {
console.error('加载历史记录失败:', error);
const listContainer = document.getElementById('task-list');
listContainer.innerHTML = `<div class="error">加载失败: ${error.message}</div>`;
});
} }
document.addEventListener('DOMContentLoaded', function() { function getStatusIcon(status) {
switch(status) {
case 'completed': return '✅';
case 'failed': return '❌';
case 'running': return '⚙️';
default: return '⏳';
}
}
function loadTask(taskId) {
if (currentEventSource) {
currentEventSource.close();
currentEventSource = null;
}
const container = document.getElementById('task-container');
container.innerHTML = '<div class="loading">Loading task...</div>';
document.getElementById('input-container').classList.add('bottom');
fetch(`/tasks/${taskId}`)
.then(response => {
if (!response.ok) {
throw new Error('Failed to load task');
}
return response.json();
})
.then(task => {
if (task.status === 'running') {
setupSSE(taskId);
} else {
displayTask(task);
}
})
.catch(error => {
console.error('Failed to load task:', error);
container.innerHTML = `<div class="error">Failed to load task: ${error.message}</div>`;
});
}
function displayTask(task) {
const container = document.getElementById('task-container');
container.innerHTML = '';
container.classList.add('active');
const welcomeMessage = document.querySelector('.welcome-message'); const welcomeMessage = document.querySelector('.welcome-message');
if (welcomeMessage) { if (welcomeMessage) {
welcomeMessage.style.display = 'flex'; welcomeMessage.style.display = 'none';
} }
// 监听任务容器显示状态 const stepContainer = document.createElement('div');
const taskContainer = document.getElementById('task-container'); stepContainer.className = 'step-container';
if (taskContainer) {
const observer = new MutationObserver((mutations) => { if (task.steps && task.steps.length > 0) {
mutations.forEach(mutation => { task.steps.forEach(step => {
if (mutation.attributeName === 'class') { const stepItem = document.createElement('div');
const welcomeMessage = document.querySelector('.welcome-message'); stepItem.className = `step-item ${step.type || 'step'}`;
if (taskContainer.classList.contains('active')) {
if (welcomeMessage) { const content = step.result;
welcomeMessage.style.display = 'none'; const timestamp = new Date(step.timestamp || task.created_at).toLocaleTimeString();
}
} else { stepItem.innerHTML = `
if (welcomeMessage) { <div class="log-line">
welcomeMessage.style.display = 'block'; <span class="log-prefix">${getEventIcon(step.type)} [${timestamp}] ${getEventLabel(step.type)}:</span>
} <pre>${content}</pre>
} </div>
} `;
});
stepContainer.appendChild(stepItem);
}); });
} else {
observer.observe(taskContainer, { stepContainer.innerHTML = '<div class="no-steps">No steps recorded for this task</div>';
attributes: true }
container.appendChild(stepContainer);
if (task.status === 'completed') {
let lastResultContent = '';
if (task.steps && task.steps.length > 0) {
for (let i = task.steps.length - 1; i >= 0; i--) {
if (task.steps[i].type === 'result') {
lastResultContent = task.steps[i].result;
break;
}
}
}
container.innerHTML += `
<div class="complete">
<div> Task completed</div>
<pre>${lastResultContent}</pre>
</div>
`;
} else if (task.status === 'failed') {
container.innerHTML += `
<div class="error">
Error: ${task.error || 'Unknown error'}
</div>
`;
}
updateTaskStatus(task);
}
// Initialize the app when the DOM is loaded
document.addEventListener('DOMContentLoaded', () => {
loadHistory();
// Set up event listeners
document.getElementById('create-task-btn').addEventListener('click', createTask);
document.getElementById('prompt-input').addEventListener('keydown', (e) => {
if (e.key === 'Enter' && !e.shiftKey) {
e.preventDefault();
createTask();
}
});
// Show history button functionality
const historyToggle = document.getElementById('history-toggle');
if (historyToggle) {
historyToggle.addEventListener('click', () => {
const historyPanel = document.getElementById('history-panel');
if (historyPanel) {
historyPanel.classList.toggle('open');
historyToggle.classList.toggle('active');
}
});
}
// Clear button functionality
const clearButton = document.getElementById('clear-btn');
if (clearButton) {
clearButton.addEventListener('click', () => {
document.getElementById('prompt-input').value = '';
document.getElementById('prompt-input').focus();
}); });
} }
}); });