import { Nn as TurnUsage, O as SkillConfig, On as ToolResultContent, xn as SessionTurn } from "./agent-BHkvYIH9.js";
import { D as Owner, E as EditPayload, G as ProviderKey, L as CompletionProvider, M as StreamEvent, R as CompletionReference, W as ProviderAuth, Y as ModelInfo, l as ApprovalDecision, w as EditOutcome } from "./tool-formatters-D_fX6FGl.js";

//#region src/chat/color-gradient.d.ts
/**
 * Blend two hex colors in HSL space with shortest-path hue interpolation.
 * `t` ∈ [0, 1]; `t=0` returns `from`, `t=1` returns `to`.
 */
declare function blendHsl(from: string, to: string, t: number): string;
/**
 * Static gradient ramp of length `n` going from `from` (index 0) to
 * `to` (index n-1) in HSL space. For the cycling A→B→A→B ramp the
 * throbber uses, see `buildCycleRamp` in `src/tui/crush-throbber.tsx`.
 */
declare function buildLinearRamp(from: string, to: string, n: number): string[];
//#endregion
//#region src/chat/files-discovery.d.ts
/**
 * Project file discovery for the `@`-prefixed files completion provider.
 *
 * Primary strategy — `git ls-files --cached --others --exclude-standard`.
 * Git already understands `.gitignore`, `.git/info/exclude`, and global
 * excludes, so we get correctness for free + sub-second performance on
 * even huge monorepos. Falls back to a depth-limited filesystem walk when
 * git isn't available or the directory isn't a repo.
 *
 * Pure: callers cache the returned list (e.g. in App state) and pass it
 * into the provider's `getCatalog`. The list is a snapshot — refresh on
 * cwd change or via a user-driven action.
 */
/** One row in the project file catalog. `path` is forward-slashed + relative to `cwd`. */
interface FileEntry {
  /** Forward-slashed relative path from the discovery cwd. Stable across OSes. */
  path: string;
  /** Basename — used for prefix ranking in the completion provider. */
  name: string;
  /** Source — `git` when listed via `git ls-files`, `fs` from the walk fallback. */
  source: 'git' | 'fs';
}
/** Options for `listProjectFiles`. */
interface ListProjectFilesOptions {
  /** Discovery root. Default: `process.cwd()`. */
  cwd?: string;
  /** Cap on returned entries. Default: 10,000. Bigger lists fall back to a truncated set. */
  maxFiles?: number;
  /** Aborts the scan early. Useful when re-running on rapid project switches. */
  signal?: AbortSignal;
}
/**
 * Discover every non-ignored file under `cwd`. Tries `git ls-files` first;
 * on failure (no git, not a repo, abort) walks the fs with a hand-rolled
 * skip list.
 *
 * Errors are not thrown — the function always returns an array (possibly
 * empty). Callers wanting failure diagnostics can opt into them via
 * `ZIDANE_DEBUG`.
 */
declare function listProjectFiles(opts?: ListProjectFilesOptions): Promise<FileEntry[]>;
//#endregion
//#region src/chat/completion-files.d.ts
/** Trigger character — `@` is the conventional file-mention prefix in chat UIs. */
declare const FILES_TRIGGER = "@";
/**
 * Build an `@`-prefixed files completion provider against a *live* catalog.
 *
 * The factory captures a getter so the catalog can be re-scanned (cwd
 * change, manual refresh) without re-instantiating the provider — the
 * App keeps one provider for the lifetime of the prompt block and just
 * mutates the underlying state.
 *
 * `limit` caps the result list so the popover stays bounded on huge
 * monorepos. Filtering is substring on `path` + `name`, case-insensitive,
 * with an fzf-scored basename fuzzy fallback so small typos / omissions
 * (`lop.ts` → `loop.ts`) still surface results; ranking prefers (in
 * order): exact name match, name prefix, name substring, path substring,
 * basename fuzzy match, alphabetical.
 */
declare function createFilesCompletionProvider(opts: {
  /** Live file catalog. Re-evaluated per call so refreshes take effect immediately. */getCatalog: () => readonly FileEntry[];
  /**
   * Optional hook called the first time the host needs the catalog —
   * e.g. when the user opens the `@` popover. Hosts wire this to a
   * lazy directory walk so boot doesn't pay for it in monorepos
   * where the popover may never open. Idempotent contract: callers
   * may invoke it on every `suggest`; the host caches internally.
   *
   * When provided, `suggest()` returns a Promise on the very first
   * invocation if the catalog is still empty — the popover's loading
   * state surfaces while the walk completes; subsequent calls are
   * sync because `getCatalog()` then returns the populated state.
   */
  ensureCatalog?: () => Promise<readonly FileEntry[]>; /** Max items returned to the popover. Default: 50. */
  limit?: number;
  /**
   * Rewrite the catalog's project-root-relative path into the form
   * inserted into the prompt + matched by `parseReferences`. Wire this
   * to `formatPathForCwd` so paths emitted into the buffer line up
   * with the agent's CWD-resolving tools when the TUI launches from a
   * project subdirectory. Default: identity.
   *
   * Stable identity expected — `parseReferences` calls it once per
   * catalog entry per keystroke for the highlight pass; pure
   * pure-function shape keeps the popover responsive on huge repos.
   */
  formatPath?: (entry: FileEntry) => string;
}): CompletionProvider<FileEntry>;
/**
 * Walk a reference list and return the deduplicated set of files in
 * first-mention order — input to "attach these files to the prompt"
 * downstream logic.
 */
declare function uniqueFilesFromReferences(references: readonly CompletionReference<unknown>[]): FileEntry[];
//#endregion
//#region src/chat/completion-skills.d.ts
/** Trigger character — slash-commands convention. */
declare const SKILLS_TRIGGER = "/";
/**
 * Build a slash-command completion provider against a *live* skills
 * catalog. The factory captures a getter so the catalog can change across
 * renders (toggles, reload) without re-instantiating the provider.
 *
 * Pass `getEnabled` to additionally hide skills the user has toggled off
 * — when undefined, every catalog entry is offered.
 */
declare function createSkillsCompletionProvider(opts: {
  /** Live catalog. Re-evaluated per call so toggles take effect immediately. */getCatalog: () => readonly SkillConfig[]; /** Optional enable-set filter; when undefined every catalog skill is offered. */
  getEnabled?: () => readonly string[] | undefined;
  /**
   * Optional hook called the first time the host needs the catalog —
   * typically when the user opens the `/` popover. Mirror of the
   * files provider's `ensureCatalog`; same idempotent contract.
   *
   * Hosts wire this to a lazy SKILL.md scan so the boot path stays
   * free of disk reads in deeply-nested skill trees. Returns a Promise
   * on the very first `suggest()` call when the catalog is still
   * empty so the popover surfaces its loading state.
   */
  ensureCatalog?: () => Promise<readonly SkillConfig[]>;
}): CompletionProvider<SkillConfig>;
/**
 * Walk a parsed prompt for skill references and return the deduplicated
 * list of skill names — input to `agent.activateSkill(name)` calls on
 * submit.
 */
declare function uniqueSkillNamesFromReferences(references: readonly CompletionReference<unknown>[]): string[];
//#endregion
//#region src/chat/edit-approval.d.ts
/**
 * Convert a per-hunk approval mask into an `EditOutcome[]`. `true` →
 * `applied`; `false` → `denied` with the supplied reason.
 *
 * Length is `Math.max(mask.length, fallbackLength)` so callers passing a
 * shorter mask still get a fully-populated array — missing entries
 * default to applied, matching the "no decision => keep" convention.
 */
declare function maskToOutcomeKinds(mask: readonly boolean[], fallbackLength: number, deniedReason?: string): EditOutcome[];
/**
 * Apply an `ApprovalDecision` to a payload, returning the resolved
 * per-hunk outcomes + the gate-level verdict.
 *
 * Pure — does not mutate `input` or `payload`. The TUI's `applyGate`
 * consumes the result: stashes `outcomes` in the pending-annotation map
 * (keyed by callId) so `tool:transform` can append the
 * `<edit-outcomes>` block to the tool result, rebinds `ctx.input.edits`
 * to the approved subset for `partial`, and emits the `syntheticEvent`
 * for fully-denied or fully-blocked calls.
 */
interface ResolvedApproval {
  /** Final state of every hunk after the decision (1:1 with payload.hunks). */
  outcomes: EditOutcome[];
  /** True when no hunk will be applied — gate should `block` the call. */
  shouldBlock: boolean;
  /**
   * Synthetic `EditPayload` to render in the transcript. Identical to the
   * incoming payload but with `outcomes` set so the renderer can badge
   * each hunk. Only meaningful when at least one hunk was denied —
   * an all-applied decision returns `null` here and the normal
   * `tool:before` event suffices.
   */
  syntheticEvent: EditPayload | null;
}
declare function resolveApprovalForPayload(decision: ApprovalDecision, payload: EditPayload): ResolvedApproval;
/**
 * Render an `EditOutcome[]` as the wire-format annotation block. Returns
 * the body to APPEND to a tool result; callers join with a leading
 * `\n\n` separator. Idempotent on missing reasons — bare `applied` lines
 * stay terse.
 */
declare function buildEditOutcomesAnnotation(outcomes: readonly EditOutcome[]): string;
/**
 * Parse an `<edit-outcomes>…</edit-outcomes>` annotation block out of a
 * tool result body. Returns the outcomes keyed by 1-based hunk index, or
 * `null` when the block is missing / malformed.
 *
 * Anchored on the explicit tag pair so the parser doesn't false-positive
 * on natural prose that happens to contain `#1 applied`.
 */
declare function parseEditOutcomesFromResult(result: string | readonly ToolResultContent[]): EditOutcome[] | null;
/**
 * Strip the first `<edit-outcomes>…</edit-outcomes>` block out of a tool
 * result body, returning the surrounding text. Used by the
 * `tool:transform` hook to peel a body-emitted annotation before
 * re-appending the merged (approval ∪ body) version — otherwise the
 * result would carry two annotation blocks and
 * {@link parseEditOutcomesFromResult} would only see the first.
 *
 * Anchored on the same `\n<edit-outcomes>\n` / start-of-string newline
 * shape the parser uses, so prose that incidentally mentions
 * `<edit-outcomes>` (e.g. a model summarizing its own format) isn't
 * mistakenly stripped. Trims a single leading `\n\n` separator when
 * present so successive strips don't leave dangling blank lines.
 * Idempotent on inputs that don't contain a properly-anchored block.
 */
declare function stripEditOutcomesAnnotation(text: string): string;
/**
 * Merge body-side outcomes (keyed against the approved subset the tool
 * actually ran on, in subset-position order) into approval-side outcomes
 * (1:1 with the model's ORIGINAL `edits` list, with `denied` entries for
 * every hunk the user dropped).
 *
 * Algorithm: walk the approval array; every `applied` placeholder
 * corresponds to one approved hunk that the body ran. Consume body's
 * outcomes in order against those placeholders. Non-`applied` approval
 * entries (`denied`, `skipped`) stay untouched — they describe gate-
 * level decisions the body never saw.
 *
 * Pure. Returns a fresh array; never mutates either input.
 *
 * Edge cases:
 *  - `body` is empty / shorter than the approved count → remaining
 *    approval `applied` placeholders stay as `applied` (the body ran
 *    happily; absence of a body entry means nothing failed).
 *  - `body` longer than approved count → trailing body entries are
 *    ignored. Shouldn't happen in practice (body sees the rebound
 *    subset), but the guard keeps the merge total-pure.
 */
declare function mergeApprovalAndBodyOutcomes(approval: readonly EditOutcome[], body: readonly EditOutcome[] | null): EditOutcome[];
/**
 * Rewrite a `multi_edit` body header so the totals reflect the model's
 * ORIGINAL edit list (the merged outcomes count) instead of the subset
 * the body actually saw after gate rebinding. Without this, a partially
 * approved call surfaces a misleading `applied 2 of 2 edits` (subset
 * counts) on the wire even when the original was `applied 2 of 3`.
 *
 * Three body-side shapes are handled (matching `multi_edit`'s emit):
 *   1. `Edited <path>: applied N edits (R replacements).`
 *   2. `Edited <path>: applied N of M edits (R replacements).`
 *   3. `multi_edit error: no edits applied to <path> (M attempted).`
 *
 * The replacements count is preserved verbatim — it's a body-side stat
 * the chat layer can't recompute. When the first line doesn't look like
 * any of the three shapes (e.g. an unrelated error preamble bubbled up),
 * the text is returned unchanged.
 */
declare function rewriteMultiEditHeader(text: string, merged: readonly EditOutcome[], path: string): string;
/**
 * Aggregate counts for the transcript's summary badge (`3 applied · 1
 * denied · 1 skipped`). Exported so renderers don't reimplement the
 * tally. Pure / O(n).
 */
declare function summarizeOutcomes(outcomes: readonly EditOutcome[] | undefined): {
  applied: number;
  denied: number;
  skipped: number;
  failed: number;
  pending: number;
  total: number;
};
//#endregion
//#region src/tools/edit-utils.d.ts
/**
 * Locate the actual substring in `haystack` that corresponds to `needle`,
 * recovering from typographical mismatch on six escalating fallbacks:
 *
 * 1. Exact substring match (the happy path — no transformation).
 * 2. Curly-quote normalization on both sides — when the model emits straight
 *    quotes but the file has curly ones (or vice versa), the slice of the
 *    file at the matched position carries the file's actual typography.
 * 3. Anthropic-sanitization undo on the needle — the model's `<n>` becomes
 *    the file's `<name>`, etc.
 * 4. Combined: desanitize + quote normalization on the needle.
 * 5. Line-number-prefix strip — when the model pasted a numbered `read_file`
 *    chunk verbatim into `old_string` and the file carries no such prefix.
 * 6. Combined: line-number strip + quote normalization — paste-back of a
 *    numbered chunk against a file whose typography differs from the model's.
 *
 * Returns `{ actual, occurrences }` — `actual` is the string that exists in
 * the file (use this to do the actual replace; preserves the file's
 * typography). `occurrences` is the count of those matches in the file.
 *
 * Fallbacks 3-4 (desanitize-class) only fire when the transformed needle is
 * UNIQUE in the file — they rewrite the needle's meaning rather than its
 * typography, so an ambiguous match risks silently retargeting the wrong
 * text (see the inline comment at step 3).
 *
 * Returns `null` when no recovery worked.
 */
interface ResolvedMatch {
  actual: string;
  occurrences: number;
  /** Recovery path — `'exact'` when no transformation was applied. */
  via: 'exact' | 'quotes' | 'desanitize' | 'quotes+desanitize' | 'line-numbers' | 'quotes+line-numbers';
}
//#endregion
//#region src/chat/edit-diff.d.ts
declare function extractEditPayload(name: string, input: Record<string, unknown>, priorContent?: string): EditPayload | undefined;
type DiffOp = 'context' | 'add' | 'remove';
interface DiffLine {
  op: DiffOp;
  text: string;
}
declare function computeLineDiff(oldString: string, newString: string): DiffLine[];
/**
 * Split a string into lines preserving empty lines but dropping the
 * implicit trailing `""` produced by a final `\n`. Exported only for
 * its tests — callers should use `computeLineDiff`.
 */
declare function splitLines(s: string): string[];
interface InlineSegment {
  text: string;
  changed: boolean;
}
interface InlineDiff {
  oldSegments: InlineSegment[];
  newSegments: InlineSegment[];
}
declare function computeInlineDiff(oldLine: string, newLine: string): InlineDiff;
/**
 * Tokenize on word / non-word boundaries. Each run of `\w+` is one
 * token; each run of `\W+` (whitespace, punctuation) is another. This
 * gives the right granularity for renames (`oldName` → `newName`) and
 * for symbol swaps (`+ → -`) without exploding into per-char segments.
 *
 * Exported only for its tests.
 */
declare function tokenize(s: string): string[];
/**
 * Apply the payload's hunks against `priorContent` and return the
 * resulting file body. Mirrors the agent's tool-side semantics:
 *   - `replaceAll === true`  → `String.replaceAll`
 *   - otherwise              → first-occurrence `String.replace`
 *
 * Hunks are applied in order — a `multi_edit` later hunk operates on
 * the output of the earlier ones, just like the actual tool.
 */
declare function applyEditPayload(payload: EditPayload, priorContent: string): string;
/**
 * Like `buildUnifiedDiff` but operating against the full file content
 * so the diff carries *real* file line numbers and configurable
 * surrounding context.
 *
 * Strategy:
 *   1. Apply the payload to `priorContent` → `newContent`.
 *   2. Run `computeLineDiff` over the whole file.
 *   3. Group non-context ops into hunks, padding each with up to
 *      `contextLines` of context above and below. Adjacent hunks
 *      whose context regions touch are merged so we don't emit two
 *      `@@` headers separated by zero context lines.
 *
 * The output line numbers in the `@@` header are 1-based and reflect
 * the change's position in the actual file — what the user expects
 * when reading a diff alongside their editor.
 *
 * For `write_file` creating a new file (priorContent === ''), this
 * falls back to the same `--- /dev/null` convention as
 * `buildUnifiedDiff`.
 */
declare function buildContextualDiff(payload: EditPayload, priorContent: string, contextLines?: number): string;
interface EditHunkSummary {
  /** 1-based line number in the new file where the change starts; undefined when unknown (no priorContent). */
  line?: number;
  /** Number of lines added in this hunk. */
  added: number;
  /** Number of lines removed in this hunk. */
  removed: number;
  /** First removed line preview (trimmed, may be empty for pure additions). */
  firstOld?: string;
  /** First added line preview (trimmed, may be empty for pure deletions). */
  firstNew?: string;
}
interface EditSummary {
  totalAdded: number;
  totalRemoved: number;
  hunks: EditHunkSummary[];
}
/**
 * Build a per-hunk digest used by the compact diff view.
 *
 * Strategy:
 *  - When `priorContent` is present and the payload describes a real
 *    file transformation, compute the contextual diff once, then walk
 *    the LCS ops splitting at runs of `add` / `remove` to anchor each
 *    summary entry to the **real** file line. This guarantees the
 *    summary's `L<n>` matches what the user sees in their editor.
 *  - Otherwise, fall back to per-hunk LCS over the (oldString,
 *    newString) snippet pair. Line numbers are absent because the
 *    snippet has no file position.
 */
declare function summarizeEditPayload(payload: EditPayload): EditSummary;
interface HunkResolution {
  /**
   * True when the tool body would find this hunk's `old_string` AND apply
   * it without ambiguity. False when `resolveOldString` returned null OR
   * the match was ambiguous (multiple occurrences and `replace_all` off).
   */
  resolved: boolean;
  /** Path the resolver took — `'exact'` when no recovery was needed. */
  via?: ResolvedMatch['via'];
  /** Match count in the running content for the hunk. */
  occurrences?: number;
  /** True when the resolver found >1 match without `replace_all`. */
  ambiguous?: boolean;
}
interface PreviewResult {
  /** Full unified diff of the (resolvable) hunks against `priorContent`. */
  diffText: string;
  /** 1:1 with `payload.hunks`. */
  resolution: HunkResolution[];
  /**
   * Per-hunk isolated diff text rendered against the cumulative content
   * after applying all earlier resolved hunks. Useful for the modal's
   * focused-hunk view so hunk #N's preview reflects the state hunks
   * 1..N-1 will leave the file in (same as the tool's order).
   */
  perHunkDiff: string[];
  /**
   * Resolved hunks with `oldString` rewritten to the haystack's actual
   * bytes and `newString` re-styled to preserve curly-quote typography
   * / line-prefix conventions. Pass this to `buildContextualDiff` to
   * paint the unified diff.
   */
  resolvedPayload: EditPayload;
}
declare function previewEditPayload(payload: EditPayload, priorContent: string, contextLines?: number): PreviewResult;
declare function buildUnifiedDiff(payload: EditPayload): string;
declare function filetypeFromPath(path: string): string | undefined;
//#endregion
//#region src/chat/format.d.ts
/** Compact token formatter — 12_415 → "12.4k", 1_234_567 → "1.23M". */
declare function fmtTokens(n: number): string;
/** Compact relative-time formatter — "just now / 5m / 3h / 2d". */
declare function ageString(ts: number, now?: number): string;
/** Six-char short form of a session id for headers and lists. */
declare function shortId(id: string): string;
/**
 * Single-line preview of a multi-line string, capped at `max` chars and
 * ellipsis-terminated when truncated.
 *
 * Whitespace runs (newlines, tabs, multiple spaces) collapse into one
 * space so the rendered output stays on a single visual row no matter
 * how the input was shaped. Used by every transcript "preview" surface
 * (spawn-start task, `tool: shell (background): <command>`,
 * `<task-notification>` summary line, etc.) — without the whitespace
 * collapse, a 60-char `slice` on a string with an inline `\n\n` paints
 * the second paragraph below the first, producing the visible
 * "preview text spills onto multiple lines" bug (and, downstream,
 * misaligned spawn markers when the wrapped lines collide with
 * other events).
 *
 * Reserves one slot for the `…` so the displayed width is exactly
 * `max` when truncation kicks in.
 */
declare function previewLine(s: string, max: number): string;
/**
 * Compact human-readable duration formatter shared by background-task
 * surfaces (the `<task-notification>` summary, the TUI banner, the
 * `shell_kill` tool result, etc.).
 *
 * Format ladder:
 *   - `< 1s`   →  `"Nms"`
 *   - `< 10s`  →  `"N.Ns"` (one decimal)
 *   - `< 1m`   →  `"Ns"`   (whole seconds)
 *   - `< 1h`   →  `"NmNs"` / `"Nm"` when seconds round to 0
 *   - `≥ 1h`   →  `"NhNm"` / `"Nh"` when minutes round to 0
 *
 * Single source of truth so a 60s task renders the same across the
 * model-facing XML summary and the user-facing banner. Earlier
 * separate formatters disagreed (XML said `"60.0s"`, banner said `"1m"`)
 * which was confusing to the user reading both side by side.
 */
declare function formatDuration(ms: number): string;
/**
 * Status label for a terminated background task — `"exited <code>"`
 * for natural exits, `"killed"` (with the signal name when known)
 * for our-issued SIGTERMs.
 *
 * Pulled out as its own function so the `<task-notification>` XML
 * summary, the TUI banner header, the `shell_kill` tool result, and
 * future surfaces all read the same string.
 */
declare function formatTaskStatus(info: {
  status: 'exited' | 'killed';
  exitCode: number;
  signal?: NodeJS.Signals;
}): string;
/**
 * One-line summary of a terminated background task — the shape used by
 * the `<task-notification>` XML's `<summary>` tag AND the TUI banner's
 * `event.text` fallback string. Three dot-separated segments:
 *
 *   `<command preview · status · duration>`
 *
 * Centralizes the format so live + replay + wire all agree, and so a
 * future cosmetic tweak (separator glyph, segment ordering) lands in
 * exactly one place.
 */
declare function formatTaskSummary(info: {
  command: string;
  status: 'exited' | 'killed';
  exitCode: number;
  signal?: NodeJS.Signals;
  durationMs: number;
}, maxCommandChars?: number): string;
/**
 * Compact an absolute path for display: replace the user's `$HOME`
 * prefix with `~` (so `/Users/yael/Code/zidane` → `~/Code/zidane`),
 * and optionally left-truncate with an ellipsis when the result
 * still exceeds `maxWidth` (so the path's *tail* — the part the user
 * recognizes — stays visible: `…/zidane` rather than `/Users/yaeluil…`).
 *
 * `maxWidth` is the maximum *display width* in cells. Omit to skip
 * truncation. Paths outside `$HOME` are returned verbatim modulo
 * truncation. The ellipsis (`…`) counts as one cell.
 *
 * `home` overrides `os.homedir()` for tests; production callers leave
 * it undefined and pay the cheap one-syscall lookup per call.
 */
declare function compactPath(path: string, maxWidth?: number, home?: string): string;
//#endregion
//#region src/chat/model-catalog.d.ts
/** A model entry as displayed in the cross-provider picker. */
interface CatalogEntry {
  providerKey: ProviderKey;
  providerLabel: string;
  model: ModelInfo;
  /**
   * Pre-computed lowercase corpus for substring search across the
   * provider key, label, model id, and display name. Built once at
   * catalog-assembly time so filtering on every keystroke is
   * O(catalogSize × queryLength), not O(catalogSize × fieldCount ×
   * lowercase-overhead × queryLength).
   */
  searchCorpus: string;
}
/**
 * Build the unified catalog from a list of available providers.
 *
 * Provider order is preserved (callers typically pass the picker order
 * — alphabetical, auth-detection order, etc.); model order inside each
 * provider matches whatever `modelsFor` returns. The current selection
 * (when set) is bubbled to the top of its provider's section so it
 * shows first without disturbing relative ordering elsewhere.
 *
 * `modelsFor` is injected (not imported from `./providers`) so the same
 * helper works with hosts that supply their own model resolver via
 * `ResolvedConfig.modelsFor`.
 */
declare function buildModelCatalog(opts: {
  providers: readonly ProviderAuth[];
  modelsFor: (key: ProviderKey) => readonly ModelInfo[]; /** Optional currently-selected pair — promoted to the top of its provider group. */
  current?: {
    providerKey: ProviderKey;
    modelId: string;
  } | null;
}): CatalogEntry[];
/**
 * Filter `catalog` by a user query. Empty / whitespace-only queries
 * pass everything through unchanged (`O(1)` short-circuit). Multi-term
 * queries (space-separated) require EVERY term to appear somewhere in
 * the entry's search corpus — so `"claude opus"` matches `claude-opus-4`
 * regardless of how the words are interleaved with provider names.
 *
 * Match is case-insensitive (the corpus is pre-lowercased; the query
 * is lowercased once per call).
 */
declare function filterModelCatalog(catalog: readonly CatalogEntry[], query: string): CatalogEntry[];
/**
 * Find a catalog entry's index by its `{providerKey, modelId}` tuple.
 * Returns `-1` when not present. Useful when re-rendering the picker
 * (a query just narrowed the list, where did the selection land?).
 */
declare function indexOfEntry(catalog: readonly CatalogEntry[], target: {
  providerKey: ProviderKey;
  modelId: string;
} | null | undefined): number;
//#endregion
//#region src/chat/streaming-pure.d.ts
/** Flip any trailing streaming markdown blocks (any owner) to finalized. */
declare function finalizeStreamingMarkdown(events: StreamEvent[]): StreamEvent[];
/** Flip the trailing streaming markdown block for one specific owner. */
declare function finalizeStreamingMarkdownForOwner(events: StreamEvent[], owner: Owner): StreamEvent[];
/**
 * Effective context size for a single turn.
 *
 * `usage.input` is misleading on its own when prompt caching is active: providers
 * (Anthropic, OpenRouter→Anthropic, Gemini) report `input` as the *new uncached*
 * tokens only — the cached prefix shows up in `cacheRead`, and newly-cached
 * tokens in `cacheCreation`. The model still saw all three buckets, so the real
 * context-window utilization is their sum.
 *
 * Non-caching providers leave `cacheRead`/`cacheCreation` undefined, so this
 * collapses to plain `input` for them.
 */
declare function turnContextSize(usage: TurnUsage | undefined): number;
//#endregion
//#region src/chat/turn-operations.d.ts
/**
 * Fork — keep every turn up to and including `turnId`, then strip any
 * `tool_call` blocks left without a matching `tool_result` in the slice.
 *
 * Semantics:
 *   - Include the selected turn ("branch from HERE" mental model — the
 *     user wants the selected message to be the latest in the fork).
 *   - If the selected turn is an assistant turn with unresolved
 *     `tool_call` blocks (their `tool_result`s live in turns AFTER the
 *     slice), strip those calls. Otherwise the fork would post an
 *     assistant turn with no matching tool results, breaking the next
 *     provider call.
 *   - Drop turns that become empty (all blocks stripped).
 *
 * Returns `null` when `turnId` doesn't exist in `turns` — caller should
 * surface a "turn not found" error rather than silently no-op.
 */
declare function truncateTurnsAt(turns: readonly SessionTurn[], turnId: string): SessionTurn[] | null;
/**
 * Delete — remove the turn with `turnId` and any tool blocks left
 * orphaned by the removal. Returns `null` when `turnId` doesn't exist.
 *
 * Strategy:
 *   1. Drop the target turn.
 *   2. Scan the remaining turns for `tool_call`s without a matching
 *      `tool_result` (orphaned by removing the user turn that carried
 *      the result), and `tool_result`s without a matching `tool_call`
 *      (orphaned by removing the assistant turn that issued the call).
 *      Strip both sides.
 *   3. Drop turns whose content is now empty.
 *
 * This guarantees the resulting history is protocol-clean — a follow-up
 * `agent.run()` against the modified session can post turns without the
 * provider rejecting the history.
 */
declare function deleteTurnSafely(turns: readonly SessionTurn[], turnId: string): SessionTurn[] | null;
/**
 * Serialize a turn's content to a clean text representation suited for
 * the clipboard. Joins text + thinking blocks verbatim; tool calls and
 * tool results get bracketed labels so the user can paste a readable
 * record of what happened without losing structure.
 *
 * Empty turns return `''`.
 */
declare function turnAsText(turn: SessionTurn): string;
/**
 * Count turns before / after the one identified by `turnId` in the
 * given list. Returns `null` when the id is missing. Used to label the
 * turn-details modal with `N before · M after`.
 */
declare function countNeighbors(turnIds: readonly string[], turnId: string): {
  before: number;
  after: number;
} | null;
//#endregion
export { uniqueFilesFromReferences as $, buildUnifiedDiff as A, buildEditOutcomesAnnotation as B, EditSummary as C, PreviewResult as D, InlineSegment as E, previewEditPayload as F, rewriteMultiEditHeader as G, mergeApprovalAndBodyOutcomes as H, splitLines as I, SKILLS_TRIGGER as J, stripEditOutcomesAnnotation as K, summarizeEditPayload as L, computeLineDiff as M, extractEditPayload as N, applyEditPayload as O, filetypeFromPath as P, createFilesCompletionProvider as Q, tokenize as R, EditHunkSummary as S, InlineDiff as T, parseEditOutcomesFromResult as U, maskToOutcomeKinds as V, resolveApprovalForPayload as W, uniqueSkillNamesFromReferences as X, createSkillsCompletionProvider as Y, FILES_TRIGGER as Z, formatTaskSummary as _, finalizeStreamingMarkdown as a, DiffLine as b, CatalogEntry as c, indexOfEntry as d, FileEntry as et, ageString as f, formatTaskStatus as g, formatDuration as h, turnAsText as i, buildLinearRamp as it, computeInlineDiff as j, buildContextualDiff as k, buildModelCatalog as l, fmtTokens as m, deleteTurnSafely as n, listProjectFiles as nt, finalizeStreamingMarkdownForOwner as o, compactPath as p, summarizeOutcomes as q, truncateTurnsAt as r, blendHsl as rt, turnContextSize as s, countNeighbors as t, ListProjectFilesOptions as tt, filterModelCatalog as u, previewLine as v, HunkResolution as w, DiffOp as x, shortId as y, ResolvedApproval as z };
//# sourceMappingURL=turn-operations-CCl7rpbT.d.ts.map