// UI Components for G3 Console const components = { // Render status badge statusBadge(status) { const colors = { running: 'badge-success', completed: 'badge-success', failed: 'badge-error', idle: 'badge-warning', terminated: 'badge-neutral' }; return `${status}`; }, // Render progress bar progressBar(instance, stats) { const duration = stats.duration_secs; // Handle zero duration to avoid NaN if (duration === 0) { return this.singleProgressBar(0); } const estimated = duration * 1.5; // Simple estimation const progress = Math.min((duration / estimated) * 100, 100); // Check if this is ensemble mode with turn data if (instance.instance_type === 'ensemble' && stats.turns && stats.turns.length > 0) { return this.ensembleProgressBar(stats.turns, duration); } return `
`; }, // Render multi-segment progress bar for ensemble mode ensembleProgressBar(turns, totalDuration) { const colors = { coach: '#3b82f6', player: '#6b7280', completed: '#10b981', error: '#ef4444' }; if (turns.length === 0) { // Fallback to single progress bar if no turn data return this.singleProgressBar(totalDuration); } let segments = ''; for (const turn of turns) { // Handle zero total duration to avoid NaN if (totalDuration === 0) { continue; } // Ensure percentage never exceeds 100% const rawPercentage = (turn.duration_secs / totalDuration) * 100; const percentage = Math.min(rawPercentage, 100); const color = colors[turn.agent] || colors.player; const statusColor = turn.status === 'error' ? colors.error : color; const agentLabel = turn.agent.charAt(0).toUpperCase() + turn.agent.slice(1); const durationMin = Math.round(turn.duration_secs / 60); const tooltip = `${agentLabel}: ${durationMin}m ${Math.round(turn.duration_secs % 60)}s - ${turn.status}`; segments += `${message}
${message}
${JSON.stringify(toolCall.parameters, null, 2)}
${JSON.stringify(toolCall.result, null, 2)}
${this.escapeHtml(toolCall.error)}
No git repository detected
'; } return `No project files found
'; } let html = '${this.escapeHtml(projectFiles.requirements)}
Showing first 10 lines...
${this.escapeHtml(projectFiles.readme)}
Showing first 10 lines...
${this.escapeHtml(projectFiles.agents)}
Showing first 10 lines...