fix(cli-run): rely on continuation markers for completion
Use hook-written continuation marker state to gate run completion checks and remove the noisy event-stream shutdown timeout log in run mode.
This commit is contained in:
@@ -0,0 +1,80 @@
|
||||
import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs"
|
||||
import { join } from "node:path"
|
||||
import { CONTINUATION_MARKER_DIR } from "./constants"
|
||||
import type {
|
||||
ContinuationMarker,
|
||||
ContinuationMarkerSource,
|
||||
ContinuationMarkerState,
|
||||
} from "./types"
|
||||
|
||||
function getMarkerPath(directory: string, sessionID: string): string {
|
||||
return join(directory, CONTINUATION_MARKER_DIR, `${sessionID}.json`)
|
||||
}
|
||||
|
||||
export function readContinuationMarker(
|
||||
directory: string,
|
||||
sessionID: string,
|
||||
): ContinuationMarker | null {
|
||||
const markerPath = getMarkerPath(directory, sessionID)
|
||||
if (!existsSync(markerPath)) return null
|
||||
|
||||
try {
|
||||
const raw = readFileSync(markerPath, "utf-8")
|
||||
const parsed = JSON.parse(raw)
|
||||
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return null
|
||||
return parsed as ContinuationMarker
|
||||
} catch {
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
export function setContinuationMarkerSource(
|
||||
directory: string,
|
||||
sessionID: string,
|
||||
source: ContinuationMarkerSource,
|
||||
state: ContinuationMarkerState,
|
||||
reason?: string,
|
||||
): ContinuationMarker {
|
||||
const now = new Date().toISOString()
|
||||
const existing = readContinuationMarker(directory, sessionID)
|
||||
const next: ContinuationMarker = {
|
||||
sessionID,
|
||||
updatedAt: now,
|
||||
sources: {
|
||||
...(existing?.sources ?? {}),
|
||||
[source]: {
|
||||
state,
|
||||
...(reason ? { reason } : {}),
|
||||
updatedAt: now,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
const markerPath = getMarkerPath(directory, sessionID)
|
||||
mkdirSync(join(directory, CONTINUATION_MARKER_DIR), { recursive: true })
|
||||
writeFileSync(markerPath, JSON.stringify(next, null, 2), "utf-8")
|
||||
return next
|
||||
}
|
||||
|
||||
export function clearContinuationMarker(directory: string, sessionID: string): void {
|
||||
const markerPath = getMarkerPath(directory, sessionID)
|
||||
if (!existsSync(markerPath)) return
|
||||
|
||||
try {
|
||||
rmSync(markerPath)
|
||||
} catch {
|
||||
}
|
||||
}
|
||||
|
||||
export function isContinuationMarkerActive(marker: ContinuationMarker | null): boolean {
|
||||
if (!marker) return false
|
||||
return Object.values(marker.sources).some((entry) => entry?.state === "active")
|
||||
}
|
||||
|
||||
export function getActiveContinuationMarkerReason(marker: ContinuationMarker | null): string | null {
|
||||
if (!marker) return null
|
||||
const active = Object.entries(marker.sources).find(([, entry]) => entry?.state === "active")
|
||||
if (!active || !active[1]) return null
|
||||
const [source, entry] = active
|
||||
return entry.reason ?? `${source} continuation is active`
|
||||
}
|
||||
Reference in New Issue
Block a user