import type { UIMessagePart, UIDataTypes, UITools } from "ai"; /** An ai-sdk message part, tool-set-agnostic (we only read `type` + a few fields). */ export type AgentUIPart = UIMessagePart; /** A tool step's settle state, folded from ai's 7-state tool machine. * `awaiting` = the call is parked on a human decision (`approval-requested`) — * first-class, distinct from `running` (working) so the feed never pulses a * parked call. */ export type AgentStepStatus = "running" | "awaiting" | "done" | "error"; /** One tool call, reduced to what the feed shows. `toolName` is the RAW name — the * renderer maps it to a human label + icon (`resolveToolMeta`). */ export interface AgentStep { id: string; toolName: string; status: AgentStepStatus; /** A human was ASKED about this call and answered — approved or refused. Read * from the part's `approval` record rather than its state, because the state * forgets: the moment the output lands the call is `done` like every other, * and the one thing that made it different — someone decided on it — would * be gone. An `isAutomatic` approval is the system's, not an operator's. */ decided: boolean; /** Revealed ON DEMAND (a press-to-open peek), never inline. */ input?: unknown; output?: unknown; errorText?: string; } /** The render timeline: prose, thinking, and groups of consecutive tool calls, in * the order they streamed. */ export type AgentSegment = { kind: "text"; id: string; text: string; } | { kind: "reasoning"; id: string; text: string; } | { kind: "group"; id: string; steps: AgentStep[]; }; /** * Fold a message's parts into the render timeline. Consecutive tool parts collapse * into ONE group (the feed shows a burst as a single expandable row). Prose parts * carry no id in ai's model, so a stable index-based one is synthesized. Part kinds * with no feed representation (`step-start`, `file`, `source-*`, `data-*`, `custom`) * are skipped — the same kinds the chat's own renderer ignores. */ export declare function toSegments(parts: readonly AgentUIPart[]): AgentSegment[]; /** Whether any tool step is still running — the default "is the run streaming" signal. */ export declare function anyRunning(segments: readonly AgentSegment[]): boolean; /** The last still-running tool step, if any — for a compact "currently doing X". */ export declare function lastRunningStep(segments: readonly AgentSegment[]): AgentStep | undefined; /** * A settled run reads as two zones: the WORK it did, and the ANSWER it ended on. * * The split is POSITIONAL. Nothing inside a part says whether its prose is a * plan, a between-call aside, or the report — a model emits all three as `text`, * and deciding between them would be guessing at language. Position is the one * thing that IS knowable: what comes after the last tool call is what the agent * said once the work was over; everything before it is the work. */ export interface AgentTimeline { /** The work, in order — prose narrated on the way, thinking, tool groups. */ process: AgentSegment[]; /** The trailing text segments: what the run ended on. EMPTY when the run * stopped on a tool call (aborted, out of steps, parked) — which is exactly * when the work must NOT be folded away, because nothing would be left. */ result: AgentSegment[]; /** Every tool step in `process`, flattened in order — what a run-level * summary counts and names. */ steps: AgentStep[]; } /** Split a folded timeline into its work and its answer. Pure: the returned * arrays are fresh, and nothing in `segments` is mutated. */ export declare function splitTimeline(segments: readonly AgentSegment[]): AgentTimeline;