| | import { useState } from "react"; |
| | import type { InstanceRawLogs } from "../types"; |
| | import * as api from "../api"; |
| |
|
| | interface Props { |
| | dsId: string; |
| | instanceId: string; |
| | } |
| |
|
| | export function StepDetail({ dsId, instanceId }: Props) { |
| | const [logs, setLogs] = useState<InstanceRawLogs | null>(null); |
| | const [loading, setLoading] = useState(false); |
| | const [activeTab, setActiveTab] = useState< |
| | "agent_stdout" | "setup_stderr" | "verifier_report" | "verifier_stdout" |
| | >("agent_stdout"); |
| |
|
| | const loadLogs = async () => { |
| | setLoading(true); |
| | try { |
| | const data = await api.getInstanceRaw(dsId, instanceId); |
| | setLogs(data); |
| | } catch { |
| | |
| | } |
| | setLoading(false); |
| | }; |
| |
|
| | if (!logs) { |
| | return ( |
| | <div className="p-4 border-t border-gray-800"> |
| | <button |
| | onClick={loadLogs} |
| | disabled={loading} |
| | className="px-3 py-1.5 bg-gray-800 rounded text-xs text-gray-300 hover:bg-gray-700 disabled:opacity-50" |
| | > |
| | {loading ? "Loading..." : "Load Raw Logs"} |
| | </button> |
| | </div> |
| | ); |
| | } |
| |
|
| | const tabs = [ |
| | { key: "agent_stdout" as const, label: "Agent Stdout", content: logs.agent_stdout }, |
| | { key: "setup_stderr" as const, label: "Setup Stderr", content: logs.setup_stderr }, |
| | { key: "verifier_report" as const, label: "Verifier Report", content: logs.verifier_report }, |
| | { key: "verifier_stdout" as const, label: "Verifier Stdout", content: logs.verifier_stdout }, |
| | ].filter((t) => t.content); |
| |
|
| | return ( |
| | <div className="border-t border-gray-800"> |
| | <div className="flex border-b border-gray-800"> |
| | {tabs.map((tab) => ( |
| | <button |
| | key={tab.key} |
| | onClick={() => setActiveTab(tab.key)} |
| | className={`px-3 py-2 text-xs font-medium ${ |
| | activeTab === tab.key |
| | ? "text-blue-400 border-b-2 border-blue-400" |
| | : "text-gray-500 hover:text-gray-300" |
| | }`} |
| | > |
| | {tab.label} |
| | </button> |
| | ))} |
| | </div> |
| | |
| | <div className="max-h-96 overflow-y-auto p-3"> |
| | <pre className="code-block text-gray-300 whitespace-pre-wrap break-words"> |
| | {tabs.find((t) => t.key === activeTab)?.content || "No content"} |
| | </pre> |
| | </div> |
| | </div> |
| | ); |
| | } |
| |
|