import "./agent_run.css"; import type * as React from "react"; import { Collapsible } from "@base-ui/react/collapsible"; import { useRender } from "@base-ui/react/use-render"; import { type IconName } from "./icon"; import { type StyleProps } from "./style_props"; import { type AgentUIPart, type AgentStep, type AgentStepStatus } from "./agent_transform"; /** The raw tool name, its input, and its settle state. */ export interface AgentToolCall { toolName: string; input: unknown; state: AgentStepStatus; } /** Only an output-carrying step reaches the renderer. */ export interface AgentToolOutput { toolName: string; input: unknown; output: unknown; } export interface AgentRunFeedProps extends StyleProps { variant?: "feed"; /** Chat passes `message.parts`; an app passes `useAgentRun().parts`. */ parts: readonly AgentUIPart[]; /** Defaults to `streaming` while any tool step runs. */ state?: "streaming" | "done" | "error"; /** * A breaking error that ended the run, outside `parts` (`useAgentRun().error`); a per-tool * failure rides in its `output-error` part. */ error?: string; /** Return `undefined` for the built-in label. */ labelForCall?: (call: AgentToolCall) => string | undefined; /** * Replaces the default `RawPayload` of an expanded tool step; input and error rendering are * unaffected. */ renderToolOutput?: (call: AgentToolOutput) => React.ReactNode | undefined; onRetry?: () => void; /** * Default `true`; `false` where the run already sits in a collapsed shell, since a fold behind a * fold costs two presses. */ collapseProcess?: boolean; /** The default names the last step: only the host knows which tools wrote. */ summarizeRun?: (steps: readonly AgentStep[]) => string | undefined; accessibilityLabel?: string; testID?: string; ref?: React.Ref; render?: useRender.RenderProp; } /** * Caller override, then `agentRun.tools`, then a prettified name. Exported so a host labelling a * run elsewhere says what the feed says. */ export declare function resolveToolMeta(call: AgentToolCall, labelForCall?: (call: AgentToolCall) => string | undefined, toolLabels?: Record): { label: string; icon: IconName; }; /** `value` is the label — the `ask_user_choice` wire shape. */ export interface AgentRunOption { label: string; description?: string; } /** Exported so a template or test can build one. */ export interface AgentRunQuestion { question: string; options: AgentRunOption[]; allow_custom?: boolean; } /** * Structurally `useAgentRun()`'s shape, declared here so `@lotics/ui` never depends on * `@lotics/app-runtime/sdk`; the app's typecheck is the detector. */ export interface AgentRunLike { status: "idle" | "streaming" | "awaiting_input" | "completed" | "error"; parts: readonly AgentUIPart[]; /** Non-null exactly while parked. */ pendingChoice: { questions: AgentRunQuestion[]; } | null; /** Generic, to keep the one-way boundary above. */ answerChoice: (answers: { value: string; custom: boolean; }[]) => Promise; /** * Stops the run server-side (`useAgentRun().cancel`). Never `abort`, which detaches and leaves * the run executing and billing. */ cancel: () => void; /** * Optional rather than widened: an optional property is not assignable to a required one. Absent, * `undefined` and `null` read alike. */ error?: string | null | undefined; } export interface AgentRunPaneProps extends StyleProps { variant: "pane"; run: AgentRunLike; labelForCall?: AgentRunFeedProps["labelForCall"]; renderToolOutput?: AgentRunFeedProps["renderToolOutput"]; /** The run is left for the operator to retry. */ onCancel: () => void; /** * Required in any host that acts on a run's result: the caller's `run()` already resolved with * `parked` and never resolves again. Re-fires for a follow-up ask. */ onLanding?: (landing: TLanding) => void; testID?: string; ref?: React.Ref; render?: useRender.RenderProp; } export interface AgentRunPillProps extends StyleProps { variant: "pill"; parts: readonly AgentUIPart[]; state?: "streaming" | "done" | "error"; error?: string; /** Defaults to the running step's label, else the `agentProgress` slice's word. */ label?: string; /** Applied to both the pill and the expanded feed. */ labelForCall?: AgentRunFeedProps["labelForCall"]; renderToolOutput?: AgentRunFeedProps["renderToolOutput"]; onRetry?: () => void; defaultExpanded?: boolean; testID?: string; ref?: React.Ref; render?: Collapsible.Root.Props["render"]; } export type AgentRunProps = AgentRunFeedProps | AgentRunPaneProps | AgentRunPillProps; /** * An agent's work, live, in three presentations sized by how much screen the run gets: `feed` in * place; `pane` a dialog body that swaps to the agent's question (with `AgentRunDialog` + * `AgentRunActions`); `pill` off the screen. */ export declare function AgentRun(props: AgentRunProps): React.JSX.Element; /** Lets the run's verbs render in the dialog's footer rather than the scrolling body. */ export declare function AgentRunDialog({ children }: { children: React.ReactNode; }): React.JSX.Element; /** * The run's action bar for a `DialogFooter`, mounted unconditionally: the wizard's verbs while a * question is up, Stop while streaming, nothing once settled. Renders no box, so it takes no style * props. Stop lives outside the scroller because the feed follows its newest part and would scroll * it away. */ export declare function AgentRunActions({ run, onStop }: { run: AgentRunLike; onStop?: () => void; }): React.JSX.Element | null;