CodeIssuesDiscussionsWikiPull RequestsProjectsCommitsActionsReleasesContributorsPulse● GatesSecuritySettingsDeploymentsPipelineInsightsAgents✨ Explain✨ Ask AI✨ Workspace✨ Spec✨ Tests▓ Debt Map✨ NL Search🏛 Archaeology
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | /**
* LogTail — SSR component that renders a <pre> and streams live workflow-run
* step-log chunks into it via SSE.
*
* The initial <pre> is pre-populated with `fallbackLogs` (the DB row's stored
* logs blob so a viewer with JS disabled, an unsupported browser, or a
* blocked SSE endpoint still sees whatever was already persisted). Once the
* inline script connects to `/live-events/workflow-run-<runId>`, it appends
* step-log chunks as plain escaped text and reloads the page on run-done so
* the static view takes over.
*/
import { raw } from "hono/html";
import { liveLogTailScript } from "../lib/sse-client";
export function LogTail(props: {
runId: string;
jobId?: string;
fallbackLogs?: string | null;
height?: string;
reloadOnRunDone?: boolean;
}) {
const elementId = `log-tail-${props.runId}${props.jobId ? "-" + props.jobId : ""}`;
const topic = `workflow-run-${props.runId}`;
const script = liveLogTailScript({
topic,
targetElementId: elementId,
jobId: props.jobId,
onRunDone:
props.reloadOnRunDone === false ? undefined : "location.reload()",
});
return (
<div>
<div
style="display: flex; justify-content: space-between; align-items: center; padding: 6px 10px; background: var(--bg-tertiary); border-top-left-radius: 6px; border-top-right-radius: 6px; font-size: 11px; color: var(--text-muted); font-family: monospace"
>
<span>● live log</span>
<span id={`${elementId}-status`}>connecting…</span>
</div>
<pre
id={elementId}
style={`margin: 0; padding: 12px 14px; background: var(--bg-tertiary); color: var(--text); font-size: 12px; line-height: 1.45; overflow: auto; max-height: ${props.height || "480px"}; border-bottom-left-radius: 6px; border-bottom-right-radius: 6px`}
>
{props.fallbackLogs || ""}
</pre>
<script dangerouslySetInnerHTML={{ __html: script }} />
);
}
|