Merge branch 'fix_chrome'

This commit is contained in:
yuanmengqi
2025-07-15 02:13:58 +00:00
parent 7c807d4f3e
commit 756ef96850
21 changed files with 922 additions and 103 deletions

View File

@@ -1,5 +1,8 @@
document.addEventListener('DOMContentLoaded', () => {
fetchTasks();
fetchAvailableConfigs().then(() => {
fetchConfig();
fetchTasks();
});
// Bind filter functionality
document.getElementById('total-tasks').parentElement.addEventListener('click', () => setTaskFilter('all'));
document.getElementById('active-tasks').parentElement.addEventListener('click', () => setTaskFilter('active'));
@@ -9,6 +12,9 @@ document.addEventListener('DOMContentLoaded', () => {
let allTaskData = null;
let currentFilter = 'all';
let availableConfigs = [];
let currentConfig = null;
let categoryStats = {};
function refreshPage() {
// Save expanded state before refresh
@@ -31,8 +37,8 @@ function fetchTasksForRefresh() {
fetch('/api/tasks/brief')
.then(response => response.json())
.then(data => {
// Update stored data
allTaskData = data;
categoryStats = calculateCategoryStats(data);
// Only update statistics and task status, do not fully re-render
updateStatistics(data);
updateTaskStatus(data);
@@ -148,6 +154,7 @@ function fetchTasks() {
.then(response => response.json())
.then(data => {
allTaskData = data;
categoryStats = calculateCategoryStats(data);
renderTasks(data);
updateStatistics(data);
})
@@ -208,13 +215,15 @@ function updateStatistics(data) {
document.getElementById('completed-tasks').textContent = completedTasks;
document.getElementById('error-tasks').textContent = errorTasks;
// Update score display with formatted score
// Update score display with formatted score and accuracy percentage
const scoreDisplay = document.getElementById('score-display');
if (completedTasks > 0) {
const scoreFormatted = totalScore.toFixed(2);
scoreDisplay.innerHTML = `<span>${scoreFormatted}</span> / <span>${completedTasks}</span>`;
const averageScore = totalScore / completedTasks;
const accuracyPercentage = (averageScore * 100).toFixed(1);
scoreDisplay.innerHTML = `<span>${scoreFormatted}</span> / <span>${completedTasks}</span> <span class="accuracy-percentage">(${accuracyPercentage}%)</span>`;
} else {
scoreDisplay.innerHTML = '<span>0.00</span> / <span>0</span>';
scoreDisplay.innerHTML = '<span>0.00</span> / <span>0</span> <span class="accuracy-percentage">(0.0%)</span>';
}
// Highlight the currently selected statistics card
@@ -279,6 +288,10 @@ function renderTasks(data) {
// Create header with task type name and statistics
const typeHeader = document.createElement('div');
typeHeader.className = 'task-type-header';
// Get category stats for this task type
const stats = categoryStats[taskType] || {};
typeHeader.innerHTML = `
<span class="task-type-name"><i class="fas fa-layer-group"></i> ${taskType}</span>
<div class="task-type-stats">
@@ -286,6 +299,9 @@ function renderTasks(data) {
<span class="task-stat"><i class="fas fa-tasks"></i> ${tasks.length} total</span>
<span class="task-stat running"><i class="fas fa-running"></i> ${runningCount} active</span>
<span class="task-stat completed"><i class="fas fa-check-circle"></i> ${completedCount} completed</span>
${stats.avg_score ? `<span class="task-stat score"><i class="fas fa-star"></i> ${stats.avg_score} avg score</span>` : ''}
${stats.avg_steps ? `<span class="task-stat steps"><i class="fas fa-chart-line"></i> ${stats.avg_steps} avg steps</span>` : ''}
${stats.completion_rate ? `<span class="task-stat rate"><i class="fas fa-percentage"></i> ${stats.completion_rate}% completed</span>` : ''}
</div>
`;
typeSection.appendChild(typeHeader);
@@ -453,7 +469,181 @@ function renderTasks(data) {
container.appendChild(typeSection);
});
}
// add auto-refresh with time interval 10 seconds
setInterval(() => {
refreshPage();
}, 10000); // 10 seconds interval
function fetchAvailableConfigs() {
return fetch('/api/available-configs')
.then(response => response.json())
.then(data => {
availableConfigs = data;
populateConfigSelect();
return data;
})
.catch(error => {
console.error('Error fetching available configs:', error);
return [];
});
}
function populateConfigSelect() {
const select = document.getElementById('config-select');
select.innerHTML = '';
if (availableConfigs.length === 0) {
select.innerHTML = '<option value="">No configurations found in results directory</option>';
return;
}
// Add available configurations
availableConfigs.forEach((config, index) => {
const option = document.createElement('option');
option.value = index;
option.textContent = `${config.action_space} / ${config.observation_type} / ${config.model_name}`;
select.appendChild(option);
});
}
function changeConfiguration() {
const select = document.getElementById('config-select');
const selectedIndex = select.value;
if (selectedIndex === '' || selectedIndex < 0 || selectedIndex >= availableConfigs.length) {
return;
}
const selectedConfig = availableConfigs[selectedIndex];
// Send configuration change request
fetch('/api/set-config', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(selectedConfig)
})
.then(response => response.json())
.then(data => {
currentConfig = data;
displayConfig(data);
// Refresh tasks with new configuration
fetchTasks();
})
.catch(error => {
console.error('Error setting config:', error);
displayConfigError();
});
}
function fetchConfig() {
return fetch('/api/current-config')
.then(response => response.json())
.then(data => {
currentConfig = data;
displayConfig(data);
updateConfigSelect();
return data;
})
.catch(error => {
console.error('Error fetching config:', error);
displayConfigError();
});
}
function updateConfigSelect() {
if (!currentConfig || availableConfigs.length === 0) return;
const select = document.getElementById('config-select');
const currentConfigIndex = availableConfigs.findIndex(config =>
config.action_space === currentConfig.action_space &&
config.observation_type === currentConfig.observation_type &&
config.model_name === currentConfig.model_name
);
if (currentConfigIndex !== -1) {
select.value = currentConfigIndex;
} else {
// Current config not found in available configs, select the first one if available
if (availableConfigs.length > 0) {
select.value = 0;
console.warn('Current config not found in available configs, defaulting to first available config');
}
}
}
function displayConfig(config) {
document.getElementById('action-space').textContent = config.action_space || 'N/A';
document.getElementById('observation-type').textContent = config.observation_type || 'N/A';
document.getElementById('model-name').textContent = config.model_name || 'N/A';
document.getElementById('max-steps').textContent = config.max_steps || 'N/A';
}
function displayConfigError() {
const configValues = document.querySelectorAll('.config-value');
configValues.forEach(element => {
element.textContent = 'Error loading';
element.style.color = '#dc3545';
});
}
function calculateCategoryStats(data) {
const stats = {};
Object.entries(data).forEach(([taskType, tasks]) => {
let totalTasks = tasks.length;
let completedTasks = 0;
let runningTasks = 0;
let errorTasks = 0;
let totalScore = 0;
let totalSteps = 0;
let completedWithSteps = 0;
tasks.forEach(task => {
const status = task.status.status;
if (['Done', 'Done (Message Exit)', 'Done (Max Steps)', 'Done (Thought Exit)'].includes(status)) {
completedTasks++;
// Calculate score if available
if (task.status.result) {
try {
const score = parseFloat(task.status.result);
if (!isNaN(score) && score >= 0 && score <= 1) {
totalScore += score;
}
} catch (e) {
// Ignore parsing errors
}
}
// Calculate steps for completed tasks
if (task.status.progress && task.status.progress > 0) {
totalSteps += task.status.progress;
completedWithSteps++;
}
} else if (['Running', 'Preparing', 'Initializing'].includes(status)) {
runningTasks++;
} else if (status === 'Error') {
errorTasks++;
}
});
// Calculate averages
const avgScore = completedTasks > 0 ? totalScore / completedTasks : 0;
const avgSteps = completedWithSteps > 0 ? totalSteps / completedWithSteps : 0;
const completionRate = totalTasks > 0 ? (completedTasks / totalTasks * 100) : 0;
stats[taskType] = {
total_tasks: totalTasks,
completed_tasks: completedTasks,
running_tasks: runningTasks,
error_tasks: errorTasks,
total_score: Math.round(totalScore * 100) / 100,
avg_score: Math.round(avgScore * 10000) / 10000,
avg_steps: Math.round(avgSteps * 10) / 10,
completion_rate: Math.round(completionRate * 10) / 10
};
});
return stats;
}