import type { TreeNode } from "../types.js"; import { type Interval } from "./intervals.js"; export type TimelineSpan = { id: string; kind: string; depth: number; extent: Interval; /** Recorded tool start, which can differ from the duration-derived envelope. */ toolStartedAt?: number; /** Start-marking event has no matching terminus yet (live run under follow). */ running: boolean; /** Envelope minus the union of DIRECT child span envelopes. Without * this, the top-level llmCall span (which wraps the whole tool loop) * absorbs the entire run — observed as a 193% share. */ selfIntervals: Interval[]; selfMs: number; }; /** Hidden by default in timeline views: per-interrupt bookkeeping that * appears under nearly every tool call and buries the signal. */ export declare const ADMIN_KINDS: string[]; export type SpanOptions = { hideKinds: string[]; /** Keep only the spans that overlap this window, cut to it, with self * time counted inside it: one turn of a session. */ window?: Interval; }; export declare function timelineSpans(root: TreeNode, opts: SpanOptions): TimelineSpan[]; /** Envelope over ALL descendant leaves: start = min(timestamp − timeTaken), * end = max(timestamp). All-descendants is what makes parent ⊇ child hold * (tree.ts uses the same rule for duration), which keeps self-time ≥ 0. * Called once per node plus once per direct child, and isRunning walks * again — O(n·depth) overall. Fine at current statelog sizes; fold into * one memoised post-order pass when the cross-run project starts feeding * this bigger inputs. */ export declare function spanExtent(node: TreeNode): Interval | undefined; export declare function hasRunningWork(node: TreeNode): boolean;