[codex] Add runtime lifecycle recovery and live issue visibility (#4419)

This commit is contained in:
Dotta
2026-04-24 15:50:32 -05:00
committed by GitHub
parent 9a8d219949
commit 5a0c1979cf
121 changed files with 9625 additions and 2044 deletions
+48 -17
View File
@@ -110,6 +110,8 @@ const runStatusIcons: Record<string, { icon: typeof CheckCircle2; color: string
cancelled: { icon: Slash, color: "text-neutral-500 dark:text-neutral-400" },
};
const RUN_LOG_PAGE_BYTES = 256_000;
const REDACTED_ENV_VALUE = "***REDACTED***";
const SECRET_ENV_KEY_RE =
/(api[-_]?key|access[-_]?token|auth(?:_?token)?|authorization|bearer|secret|passwd|password|credential|jwt|private[-_]?key|cookie|connectionstring)/i;
@@ -3473,6 +3475,8 @@ function LogViewer({ run, adapterType }: { run: HeartbeatRun; adapterType: strin
const [logLoading, setLogLoading] = useState(!!run.logRef);
const [logError, setLogError] = useState<string | null>(null);
const [logOffset, setLogOffset] = useState(0);
const [hasMoreLog, setHasMoreLog] = useState(false);
const [loadingMoreLog, setLoadingMoreLog] = useState(false);
const [isFollowing, setIsFollowing] = useState(false);
const [isStreamingConnected, setIsStreamingConnected] = useState(false);
const [transcriptMode, setTranscriptMode] = useState<TranscriptMode>("nice");
@@ -3627,6 +3631,8 @@ function LogViewer({ run, adapterType }: { run: HeartbeatRun; adapterType: strin
pendingLogLineRef.current = "";
setLogLines([]);
setLogOffset(0);
setHasMoreLog(false);
setLoadingMoreLog(false);
setLogError(null);
if (!run.logRef && !isLive) {
@@ -3637,25 +3643,14 @@ function LogViewer({ run, adapterType }: { run: HeartbeatRun; adapterType: strin
}
setLogLoading(true);
const firstLimit =
typeof run.logBytes === "number" && run.logBytes > 0
? Math.min(Math.max(run.logBytes + 1024, 256_000), 2_000_000)
: 256_000;
const load = async () => {
try {
let offset = 0;
let first = true;
while (!cancelled) {
const result = await heartbeatsApi.log(run.id, offset, first ? firstLimit : 256_000);
if (cancelled) break;
appendLogContent(result.content, result.nextOffset === undefined);
const next = result.nextOffset ?? offset + result.content.length;
setLogOffset(next);
offset = next;
first = false;
if (result.nextOffset === undefined || isLive) break;
}
const result = await heartbeatsApi.log(run.id, 0, RUN_LOG_PAGE_BYTES);
if (cancelled) return;
appendLogContent(result.content, result.nextOffset === undefined);
const next = result.nextOffset ?? result.content.length;
setLogOffset(next);
setHasMoreLog(!isLive && result.nextOffset !== undefined);
} catch (err) {
if (!cancelled) {
if (isLive && isRunLogUnavailable(err)) {
@@ -3675,6 +3670,23 @@ function LogViewer({ run, adapterType }: { run: HeartbeatRun; adapterType: strin
};
}, [run.id, run.logRef, run.logBytes, isLive]);
async function loadMorePersistedLog() {
if (loadingMoreLog || !hasMoreLog) return;
setLoadingMoreLog(true);
setLogError(null);
try {
const result = await heartbeatsApi.log(run.id, logOffset, RUN_LOG_PAGE_BYTES);
appendLogContent(result.content, result.nextOffset === undefined);
const next = result.nextOffset ?? logOffset + result.content.length;
setLogOffset(next);
setHasMoreLog(result.nextOffset !== undefined);
} catch (err) {
setLogError(err instanceof Error ? err.message : "Failed to load more run log");
} finally {
setLoadingMoreLog(false);
}
}
// Poll for live updates
useEffect(() => {
if (!isLive || isStreamingConnected) return;
@@ -3941,6 +3953,25 @@ function LogViewer({ run, adapterType }: { run: HeartbeatRun; adapterType: strin
streaming={isLive}
emptyMessage={run.logRef ? "Waiting for transcript..." : "No persisted transcript for this run."}
/>
{hasMoreLog && (
<div className="mt-3 flex flex-wrap items-center gap-2 border-t border-border/60 pt-3">
<Button
type="button"
variant="outline"
size="xs"
onClick={loadMorePersistedLog}
disabled={loadingMoreLog}
>
{loadingMoreLog ? "Loading..." : "Load more log"}
</Button>
<span className="text-xs text-muted-foreground">
Showing the first {Math.round(logOffset / 1024).toLocaleString("en-US")} KB
{typeof run.logBytes === "number" && run.logBytes > 0
? ` of ${Math.round(run.logBytes / 1024).toLocaleString("en-US")} KB`
: ""}
</span>
</div>
)}
{logError && (
<div className="mt-3 rounded-xl border border-red-500/20 bg-red-500/[0.06] px-3 py-2 text-xs text-red-700 dark:text-red-300">
{logError}