diff --git a/public/index.html b/public/index.html index e07db63..dca6106 100644 --- a/public/index.html +++ b/public/index.html @@ -574,6 +574,85 @@ white-space: pre; padding: 2rem; } + + /* Formatted Log Entry Styles */ + .log-entry { + background: #000; + border: 1px solid var(--terminal-green); + border-left: 3px solid var(--terminal-green); + padding: 12px; + margin-bottom: 12px; + font-family: var(--font-mono); + font-size: 0.9em; + } + + .log-entry.success { + border-left-color: var(--terminal-green); + } + + .log-entry.failed { + border-left-color: #ff4444; + } + + .log-timestamp { + color: var(--terminal-amber); + font-size: 0.85em; + margin-bottom: 6px; + } + + .log-title { + color: var(--terminal-green); + font-weight: bold; + text-shadow: var(--glow-green); + margin-bottom: 8px; + font-size: 1.1em; + } + + .log-entry.failed .log-title { + color: #ff4444; + text-shadow: 0 0 5px #ff4444; + } + + .log-details { + margin-left: 20px; + } + + .log-field { + margin: 6px 0; + color: var(--terminal-green); + } + + .log-label { + color: var(--terminal-amber); + font-weight: bold; + margin-right: 8px; + } + + .log-output { + background: #0a0a0a; + border: 1px solid #003300; + padding: 10px; + margin: 6px 0; + color: var(--terminal-green); + font-family: var(--font-mono); + font-size: 0.9em; + overflow-x: auto; + max-height: 300px; + overflow-y: auto; + } + + .log-error { + color: #ff6666; + border-color: #330000; + } + + .log-entry code { + background: #001a00; + padding: 2px 6px; + border: 1px solid #003300; + color: var(--terminal-green); + font-family: var(--font-mono); + } @@ -914,7 +993,7 @@ if (execution.logs && execution.logs.length > 0) { html += '

Execution Logs:

'; execution.logs.forEach(log => { - html += `
${JSON.stringify(log, null, 2)}
`; + html += formatLogEntry(log); }); } @@ -928,6 +1007,50 @@ } } + function formatLogEntry(log) { + const timestamp = new Date(log.timestamp).toLocaleTimeString(); + + // Format based on log action type + if (log.action === 'command_sent') { + return ` +
+
[${timestamp}]
+
Command Sent
+
+
Command: ${escapeHtml(log.command)}
+
+
+ `; + } + + if (log.action === 'command_result') { + const statusIcon = log.success ? '✓' : '✗'; + const statusClass = log.success ? 'success' : 'failed'; + return ` +
+
[${timestamp}]
+
${statusIcon} Command Result
+
+
Status: ${log.success ? 'Success' : 'Failed'}
+ ${log.duration ? `
Duration: ${log.duration}ms
` : ''} + ${log.stdout ? `
Output:
${escapeHtml(log.stdout)}
` : ''} + ${log.stderr ? `
Errors:
${escapeHtml(log.stderr)}
` : ''} + ${log.error ? `
Error: ${escapeHtml(log.error)}
` : ''} +
+
+ `; + } + + // Fallback for unknown log types + return `
${JSON.stringify(log, null, 2)}
`; + } + + function escapeHtml(text) { + const div = document.createElement('div'); + div.textContent = text; + return div.innerHTML; + } + async function respondToPrompt(executionId, response) { try { const res = await fetch(`/api/executions/${executionId}/respond`, {