import * as react from 'react';
import { ReactNode } from 'react';
import { S as StepAgentActivity } from '../agent-activity-C8ZG0F0M.js';
import { a as FlowTrace } from '../flow-types-Cb_AblZs.js';
import { C as CatalogModel } from '../model-catalog-BEAEVDaa.js';
import { Harness } from '../harness/index.js';

/**
 * Client-side chat-stream consumption — the NDJSON parse loop every agent
 * app's chat UI hand-rolls (and breaks). Normalizes the three line shapes the
 * agent-app chat routes emit:
 *
 *   {kind:'event', event:{type:'text'|'reasoning'|'tool_call'|'usage', ...}}
 *   {kind:'tool_result', toolCallId, toolName, label, outcome}
 *   {type:'turn'|'metadata'|'error'|'turn_status', ...}          (route-level)
 *
 * Replayed lines carry an extra `seq` — transparently ignored. Works for
 * router-backed and sandbox-backed chats alike: anything producing these
 * lines (live pump, queued follow, resume replay) feeds the same callbacks.
 */
interface ChatStreamToolCall {
    toolCallId?: string;
    toolName: string;
    args: Record<string, unknown>;
}
interface ChatStreamToolResult {
    toolCallId?: string;
    toolName?: string;
    label?: string;
    outcome: {
        ok: boolean;
        result?: unknown;
        code?: string;
        message?: string;
    };
}
interface ChatStreamCallbacks {
    onTurnId?: (turnId: string) => void;
    onText?: (delta: string) => void;
    onReasoning?: (delta: string) => void;
    onToolCall?: (call: ChatStreamToolCall) => void;
    onToolResult?: (result: ChatStreamToolResult) => void;
    onUsage?: (usage: {
        promptTokens: number;
        completionTokens: number;
    }) => void;
    onMetadata?: (data: Record<string, unknown>) => void;
    /** A loop-level error event (the turn failed server-side). */
    onErrorEvent?: (message: string) => void;
}
interface ConsumeChatStreamResult {
    turnId: string | null;
    /** True when any text/reasoning/tool activity was received. */
    receivedContent: boolean;
}
/** Parse one NDJSON line into the callbacks. Exposed for tests. */
declare function dispatchChatStreamLine(line: string, cb: ChatStreamCallbacks): {
    turnId?: string;
    receivedContent: boolean;
};
/** Drain one NDJSON body into the callbacks. Throws on transport failure
 *  (caller decides whether to resume). */
declare function consumeChatStream(body: ReadableStream<Uint8Array>, cb: ChatStreamCallbacks): Promise<ConsumeChatStreamResult>;
interface StreamChatOptions {
    /** Start the turn (POST the chat request); must return a streaming Response. */
    start: () => Promise<Response>;
    /** Re-attach to a turn after a transport drop (GET the resume route). */
    resume?: (turnId: string, fromSeq: number) => Promise<Response>;
    callbacks: ChatStreamCallbacks;
    /** Called before a resume replays from 0 so the UI can reset accumulated
     *  turn state (text, reasoning, tool chips). */
    onResetForResume?: () => void;
}
/**
 * Run one chat turn with automatic single-shot resume: if the transport drops
 * mid-turn and the server announced a turnId, reset and replay the buffered
 * turn. Server-side the turn keeps running either way (queued runner).
 */
declare function streamChatTurn(opts: StreamChatOptions): Promise<ConsumeChatStreamResult>;

/**
 * Provider brand marks — real logo path data (simple-icons / SVG Logos, both
 * CC0) inlined so the picker shows actual provider identity instead of
 * colored-initial monograms. Providers without a usable mark fall back to a
 * tinted monogram chip. Aliases (z-ai/zai, moonshot/moonshotai, deepseek_ai)
 * normalize to one entry.
 */

interface ProviderLogoProps {
    provider?: string;
    size?: number;
}
/** Real brand mark when we have one; tinted monogram otherwise. */
declare function ProviderLogo({ provider, size }: ProviderLogoProps): ReactNode;

/**
 * Smooth text reveal — turns chunky network deltas into a continuous
 * typewriter paint. Streamed turns arrive in 100-500ms slabs (model burst,
 * flush windows, replay polls); revealing characters at an adaptive rate
 * makes the same bytes read as top-tier streaming. The rate scales with the
 * backlog so the reveal never falls behind the stream — it crawls when caught
 * up and sprints when a burst lands (e.g. a reasoning summary arriving all at
 * once still *types out* instead of popping in).
 */
interface SmoothRevealOptions {
    /** Baseline reveal rate when nearly caught up. Default 90 chars/s. */
    baseCharsPerSecond?: number;
    /** Extra chars/s per backlog character — the catch-up pressure. Default 5. */
    catchUpPerChar?: number;
    /** Hard ceiling so giant bursts still animate. Default 2400 chars/s. */
    maxCharsPerSecond?: number;
}
/** Pure reveal step: how many characters should be visible after `dtMs`.
 *  Exposed for tests; the hook is a thin rAF wrapper around it. */
declare function nextRevealCount(shown: number, targetLength: number, dtMs: number, opts?: SmoothRevealOptions): number;
/**
 * Animate `target` text into view. While `enabled`, the returned string grows
 * smoothly toward `target` (which may itself keep growing); when `enabled` is
 * false the full text returns immediately (history, completed turns). A
 * target that is not an extension of the revealed prefix (new message) resets
 * the reveal.
 */
declare function useSmoothText(target: string, enabled: boolean, opts?: SmoothRevealOptions): string;

type ActivityTone = 'live' | 'ok' | 'error' | 'neutral';
/** Map a delegation status (free-form string on the wire) to a render tone. */
declare function activityTone(status: string): ActivityTone;
/** "$0.4000" under a cent shows 4 decimals; null when unknown/zero. */
declare function formatActivityCost(costUsd?: number): string | null;
/** "8s" / "2m 05s" / "1h 12m"; null when unknown. */
declare function formatActivityDuration(durationMs?: number): string | null;
/** A delegation record on the cross-context surface; `missionRef` links a
 *  promoted delegation back to the mission/step that spawned it. */
interface AgentActivityRecord extends StepAgentActivity {
    missionRef?: {
        missionId: string;
        stepId?: string;
        label?: string;
    };
}
interface AgentActivityPage {
    items: AgentActivityRecord[];
    /** Opaque continuation token; absent ⇒ no further pages. */
    nextCursor?: string;
}
/**
 * Fold a fetched page into the held rows: dedupe by `taskId` with the
 * incoming row winning (a refresh re-fetches the head page, so newer
 * snapshots of in-flight runs replace stale ones), newest `startedAt` first.
 */
declare function mergeActivityPages(existing: AgentActivityRecord[], incoming: AgentActivityRecord[]): AgentActivityRecord[];
interface WaterfallRow {
    name: string;
    kind: 'pipeline' | 'model' | 'tool';
    /** Bar geometry as percentages of the trace's total span. */
    offsetPct: number;
    widthPct: number;
    durationLabel: string;
    approx: boolean;
    /** False only when the span's meta carries an explicit failure. */
    ok: boolean;
}
/** Project a FlowTrace into proportional bar geometry for {@link FlowWaterfall}. */
declare function waterfallLayout(trace: FlowTrace): WaterfallRow[];
interface FlowWaterfallProps {
    trace: FlowTrace;
}
/** Compact proportional waterfall over a FlowTrace — span name, bar, duration
 *  per row; total + cost in the footer. */
declare function FlowWaterfall({ trace }: FlowWaterfallProps): react.JSX.Element | null;
interface MissionActivityLaneProps {
    /** The step's delegated-run snapshot (`MissionStepState.agentActivity`). */
    activity: StepAgentActivity[];
    /** Epoch ms origin for the expanded waterfall — usually the step start. */
    startedAt?: number;
    /** Wall clock for extending in-flight runs on the waterfall. */
    nowMs?: number;
}
/**
 * Collapsed sub-rows under a mission step — one row per delegated run —
 * expanding to the step's waterfall. Renders nothing for an empty lane.
 */
declare function MissionActivityLane({ activity, startedAt, nowMs }: MissionActivityLaneProps): react.JSX.Element | null;
interface AgentActivityPanelProps {
    /** Data port — page through the product's delegation records. Called with
     *  no cursor on mount/refresh, with `nextCursor` for older pages. */
    fetchActivity: (cursor?: string) => Promise<AgentActivityPage>;
    /** Render the mission link for a promoted delegation (chip, anchor, router
     *  Link — the product's routing, not ours). */
    renderMissionRef?: (ref: NonNullable<AgentActivityRecord['missionRef']>, record: AgentActivityRecord) => ReactNode;
    title?: string;
    emptyLabel?: string;
}
/**
 * The standalone cross-context delegation surface: every agent run the
 * product journaled, mission-spawned or not, with status, cost, drill-in, and
 * a mission link slot for promoted delegations.
 */
declare function AgentActivityPanel({ fetchActivity, renderMissionRef, title, emptyLabel }: AgentActivityPanelProps): react.JSX.Element;

interface SandboxTerminalConnection {
    runtimeUrl: string | null;
    sidecarUrl: string | null;
    token: string | null;
    expiresAt: string | null;
    status: string;
    error: string | null;
    loading: boolean;
    sandboxId?: string;
}
interface SandboxTerminalConnectionResponse {
    runtimeUrl?: string;
    sidecarUrl?: string;
    token?: string;
    expiresAt?: string;
    status?: string;
    error?: string;
    sandboxId?: string;
}
interface UseSandboxTerminalConnectionOptions {
    workspaceId: string;
    connectionUrl?: string | ((workspaceId: string) => string);
    fetcher?: typeof fetch;
    provisionPollIntervalMs?: number;
    provisionPollTimeoutMs?: number;
    tokenRefreshSkewMs?: number;
}
interface UseSandboxTerminalConnectionResult extends SandboxTerminalConnection {
    connect: () => Promise<void>;
}
declare function useSandboxTerminalConnection(opts: UseSandboxTerminalConnectionOptions): UseSandboxTerminalConnectionResult;

/**
 * `SeatPaywall` — the shared "unlock this product" screen every agent app
 * shows when a user has no active seat and has spent past the free tier. One
 * component, adopted by all five products (gtm / creative / tax / legal /
 * insurance) in ~2 lines.
 *
 * Copy contract (design §6.8): the included monthly AI usage is framed as a
 * BENEFIT the buyer receives — never the ratio, never the word "margin", never
 * "we debit 50%". Surface the allowance, hide the economics.
 *
 * Styling contract matches the rest of `web-react`: Tailwind classes over the
 * shared design tokens (`bg-card`, `border-border`, `text-muted-foreground`,
 * `bg-primary`, …); glyphs are inline SVGs; no icon or UI library.
 */

interface SeatPaywallProps {
    /** Human product name shown in the headline, e.g. "Creative". */
    product: string;
    /** Fired when the user clicks the unlock CTA — route them to checkout. When
     *  it returns a promise the button shows a pending state and ignores repeat
     *  clicks until it settles (no double-charge on a slow checkout open). */
    onCheckout: () => void | Promise<void>;
    /** Monthly seat price in whole dollars. Default 100. */
    priceUsd?: number;
    /** Included monthly AI usage in whole dollars. Default 50. */
    includedUsageUsd?: number;
    /** Optional one-line value prop under the headline. */
    tagline?: string;
    /** CTA label. Default "Unlock {product}". */
    ctaLabel?: string;
    /** Value-prop bullets. Default = product/usage-derived only; pass your own to
     *  supply product-specific value props (the shell bakes no GTM copy). */
    benefits?: ReactNode[];
    /** Optional fine print under the CTA (e.g. "Cancel anytime."). Omitted by default. */
    footnote?: ReactNode;
}
/**
 * Centered card paywall. The price line reads
 * "$100/mo · includes $50/mo of AI usage" so the included allowance anchors the
 * value without ever exposing the ratio.
 */
declare function SeatPaywall({ product, onCheckout, priceUsd, includedUsageUsd, tagline, ctaLabel, benefits, footnote, }: SeatPaywallProps): ReactNode;

/**
 * Keyboard + pointer model for a trigger-and-popover pair, dependency-free.
 * Outside-mousedown and Escape both close; Escape also returns focus to the
 * trigger so keyboard users aren't dropped at the top of the document. The
 * returned `triggerProps` carry the ARIA contract (`aria-haspopup`/
 * `aria-expanded`); spread them onto the trigger button.
 */
declare function usePopover(open: boolean, setOpen: (open: boolean) => void): {
    containerRef: react.RefObject<HTMLDivElement | null>;
    triggerRef: react.RefObject<HTMLButtonElement | null>;
    triggerProps: {
        ref: react.RefObject<HTMLButtonElement | null>;
        'aria-haspopup': true;
        'aria-expanded': boolean;
    };
};
/**
 * Guard an async action against double-submit. `run` ignores re-entrant calls
 * while a promise is in flight and flips `pending` so the caller can disable
 * the control — the fix for double-charge / double-approve on a slow network.
 * Settles (success or throw) before clearing, and no-ops state updates after
 * unmount.
 */
declare function usePending(): {
    pending: boolean;
    run: (action: () => void | Promise<void>) => void;
};
interface ModelPickerProps {
    value: string;
    onChange: (id: string) => void;
    /** Catalogue models — from `GET`ing the app's catalogue route (see
     *  `runtime/model-catalog`), plus any product-specific entries appended. */
    models: CatalogModel[];
    loading?: boolean;
    /** Render a provider logo/badge; default is a generic sparkle. */
    renderProviderBadge?: (provider: string) => ReactNode;
    /** Section label for `featured` models. */
    recommendedLabel?: string;
}
/**
 * Searchable model picker pill + popover: a featured/recommended section
 * first, then per-provider groups in catalogue order (the server already
 * sorts providers by tier).
 */
declare function ModelPicker({ value, onChange, models, loading, renderProviderBadge, recommendedLabel }: ModelPickerProps): react.JSX.Element;
interface EffortPickerProps {
    value: string;
    onChange: (id: string) => void;
}
/** Reasoning-effort selector pill, styled to match {@link ModelPicker}. Show
 *  it only when the selected model `supportsReasoning`. */
declare function EffortPicker({ value, onChange }: EffortPickerProps): react.JSX.Element;

interface AgentSessionControlsProps {
    /** Catalog models — canonical provider-prefixed ids. */
    models: CatalogModel[];
    modelsLoading?: boolean;
    /** Selected canonical model id. */
    model: string;
    onModelChange(modelId: string): void;
    /** Current harness; harness↔model coherence is enforced on every change. */
    harness: Harness;
    onHarnessChange(harness: Harness): void;
    /** Harnesses to offer; defaults to the labeled set. */
    availableHarnesses?: ReadonlyArray<Harness>;
    /** Reasoning-effort value + setter. Shown only when the selected model
     *  `supportsReasoning`, matching `EffortPicker`'s guidance. */
    effort: string;
    onEffortChange(effort: string): void;
    /**
     * `inline` (default): model, harness, effort side by side — the prior
     * behavior. `compact`: model inline, harness + effort behind a gear popover.
     */
    layout?: 'inline' | 'compact';
    /** Hide the harness control entirely (single-harness products). */
    showHarness?: boolean;
    renderProviderBadge?: (provider: string) => ReactNode;
    className?: string;
}
declare function AgentSessionControls(props: AgentSessionControlsProps): react.JSX.Element;

interface ChatMessageMetrics {
    modelUsed?: string;
    promptTokens?: number;
    completionTokens?: number;
    durationMs?: number;
}
/** "$0.0042" from token counts × catalogue per-token pricing; null when unknown. */
declare function formatModelCost(msg: ChatMessageMetrics, models: CatalogModel[]): string | null;
/** "38 tok/s" from completion tokens over first-token→end duration; null when unknown. */
declare function formatTokensPerSecond(msg: ChatMessageMetrics): string | null;
/** One step of a retained tool run (e.g. a sandbox command + its output). */
interface ToolRunStep {
    at: string;
    label: string;
    detail?: string;
    status?: 'ok' | 'error';
}
/** A retained tool run keyed by the parent message's toolCallId. The product
 *  persists these server-side (fail-closed: only ids its own loop created)
 *  and serves them to the drill-in panel. */
interface ToolRunRecord {
    toolCallId: string;
    toolName: string;
    title: string;
    status: 'running' | 'complete' | 'error';
    steps: ToolRunStep[];
}
interface RunDrillInProps {
    run: ToolRunRecord;
    onClose: () => void;
}
/**
 * Readonly side panel showing a retained tool run's transcript — the
 * "drill into what the sandbox actually did" view. Follow-ups happen in the
 * main chat, never here.
 */
declare function RunDrillIn({ run, onClose }: RunDrillInProps): react.JSX.Element;
interface ChatToolCallInfo {
    id: string;
    name: string;
    status: 'running' | 'done' | 'error';
    /** The call arguments, captured from the tool_call event — shown in the
     *  expanded card so users see exactly what the agent invoked. */
    args?: Record<string, unknown>;
    /** The tool outcome (`{ok, result}` shape). When `result.status` is
     *  'queued_for_approval' the card renders the approval state. */
    result?: unknown;
}
/** Extract `{proposalId, status}` from a tool outcome when it is a proposal
 *  awaiting human approval; null otherwise. */
declare function pendingApprovalOf(call: ChatToolCallInfo): {
    proposalId: string;
} | null;
interface ChatUiMessage extends ChatMessageMetrics {
    id: string;
    role: 'user' | 'assistant' | 'system';
    content: string;
    reasoning?: string;
    toolCalls?: ChatToolCallInfo[];
}
interface ChatMessagesProps {
    messages: ChatUiMessage[];
    /** Catalogue models, for per-message cost from pricing. Pass [] to skip cost. */
    models?: CatalogModel[];
    /** Markdown renderer for assistant content; default renders pre-wrapped text. */
    renderMarkdown?: (content: string) => ReactNode;
    /** Extra per-message content (artifacts, custom panels) appended after the body. */
    renderExtras?: (message: ChatUiMessage) => ReactNode;
    userLabel?: string;
    agentLabel?: string;
    /** Render the trailing "agent is thinking" row. */
    loading?: boolean;
    /** Approve/Reject handlers for proposals awaiting approval. When omitted the
     *  chip still shows "awaiting approval" but without action buttons. */
    approval?: ProposalApprovalHandlers;
    /** Open a full-transcript view (e.g. {@link RunDrillIn}) from a tool card. */
    onToolCallClick?: (call: ChatToolCallInfo, message: ChatUiMessage) => void;
    /** Per-tool custom detail renderers for expanded tool cards. */
    toolRenderers?: ToolDetailRenderers;
    /** Stream-error affordance: when the turn failed (a thrown transport error or
     *  a loop-level `onErrorEvent`), pass the message here to render an error row.
     *  A failed turn otherwise just stops with no UI signal. */
    error?: string | null;
    /** Retry control shown on the error row; omit to render the error without a
     *  retry button (e.g. when the product retries automatically). */
    onRetry?: () => void;
    /** Zero-state renderer, shown when there are no messages and the turn is
     *  neither loading nor errored. Omit to render nothing (current behavior). */
    renderEmpty?: () => ReactNode;
}
interface ProposalApprovalHandlers {
    onApprove: (proposalId: string, toolCallId: string) => void | Promise<void>;
    onReject: (proposalId: string, toolCallId: string) => void | Promise<void>;
}
/** Per-tool custom detail renderers for the expanded card body — keyed by
 *  tool name. Return null to fall back to the generic detail view. */
type ToolDetailRenderers = Record<string, (call: ChatToolCallInfo, message: ChatUiMessage) => ReactNode>;
/**
 * The message thread: one centered column; user messages are right-aligned
 * bubbles with a User label; agent messages carry an Agent meta line with
 * model id, tokens/sec, and cost, plus a collapsible thinking section and
 * tool-call chips.
 */
declare function ChatMessages({ messages, models, renderMarkdown, renderExtras, userLabel, agentLabel, loading, approval, onToolCallClick, toolRenderers, error, onRetry, renderEmpty, }: ChatMessagesProps): react.JSX.Element;

export { type ActivityTone, type AgentActivityPage, AgentActivityPanel, type AgentActivityPanelProps, type AgentActivityRecord, AgentSessionControls, type AgentSessionControlsProps, type ChatMessageMetrics, ChatMessages, type ChatMessagesProps, type ChatStreamCallbacks, type ChatStreamToolCall, type ChatStreamToolResult, type ChatToolCallInfo, type ChatUiMessage, type ConsumeChatStreamResult, EffortPicker, type EffortPickerProps, FlowWaterfall, type FlowWaterfallProps, MissionActivityLane, type MissionActivityLaneProps, ModelPicker, type ModelPickerProps, type ProposalApprovalHandlers, ProviderLogo, type ProviderLogoProps, RunDrillIn, type RunDrillInProps, type SandboxTerminalConnection, type SandboxTerminalConnectionResponse, SeatPaywall, type SeatPaywallProps, type SmoothRevealOptions, type StreamChatOptions, type ToolDetailRenderers, type ToolRunRecord, type ToolRunStep, type UseSandboxTerminalConnectionOptions, type UseSandboxTerminalConnectionResult, type WaterfallRow, activityTone, consumeChatStream, dispatchChatStreamLine, formatActivityCost, formatActivityDuration, formatModelCost, formatTokensPerSecond, mergeActivityPages, nextRevealCount, pendingApprovalOf, streamChatTurn, usePending, usePopover, useSandboxTerminalConnection, useSmoothText, waterfallLayout };
