import { Part } from '@tangle-network/agent-interface';
import { a as ChatInteractionField, C as ChatInteractionStatus, I as InteractionAnswers, N as NoticeKind } from './contract-CEewO6DI.js';
import { c as WorkProductPersistedPart } from './types-DeEOhQbv.js';
import { ChatPlanPersistedPart } from './plans/index.js';

/**
 * Wire contract between the chat client (composer + `streamChatTurn`) and the
 * assembled server vertical (`createChatTurnRoutes`). Import-free on purpose:
 * `/web-react` re-exports these types into browser bundles, so nothing here may
 * reach a Node builtin or an engine package.
 *
 * The part shape mirrors the sandbox SDK's `PromptInputPart` structurally
 * (text | image | file with filename/mediaType/url/path/content) — derived
 * here, not imported, so the client bundle never touches the SDK.
 */
interface ChatTurnTextPartInput {
    type: 'text';
    text: string;
}
/** A non-text prompt part the upload route hands back and the client echoes
 *  on send. `url` carries an inline `data:` URI for small files; `path` is a
 *  sandbox workspace reference for large ones (the >1 MiB gateway body cap
 *  makes the two-step upload mandatory). */
interface ChatTurnFilePartInput {
    type: 'image' | 'file';
    filename?: string;
    mediaType?: string;
    url?: string;
    path?: string;
    content?: string;
}
/** Resolve input as either a text part or a file part of a chat turn */
type ChatTurnPartInput = ChatTurnTextPartInput | ChatTurnFilePartInput;
/** Represent a text event produced by a source with a fixed type and associated text content */
interface ProducerTextEvent {
    type: 'text';
    text: string;
}
/** Define an event representing reasoning output with a fixed type and associated text */
interface ProducerReasoningEvent {
    type: 'reasoning';
    text: string;
}
/** Represent an event triggered by a producer tool call with its identifier, name, and arguments */
interface ProducerToolCallEvent {
    type: 'tool_call';
    call: {
        toolCallId: string;
        toolName: string;
        args: Record<string, unknown>;
    };
}
/** Describe the structure of an event representing the result of a producer tool call */
interface ProducerToolResultEvent {
    type: 'tool_result';
    toolCallId: string;
    toolName: string;
    outcome: {
        ok: boolean;
        result?: unknown;
        message?: string;
    };
}
/** Describe usage event with prompt and completion token counts for a producer */
interface ProducerUsageEvent {
    type: 'usage';
    usage: {
        promptTokens: number;
        completionTokens: number;
    };
}
/** Define the structure for a producer notice event with type, id, kind, and text fields */
interface ProducerNoticeEvent {
    type: 'notice';
    id: string;
    /** Kept inline with `/interactions`' `NoticeKind` so this file stays import-free. */
    noticeKind: 'warning' | 'auto-declined';
    text: string;
}
/** Represent an error event emitted by a producer containing message, code, and optional details */
interface ProducerErrorEvent {
    type: 'error';
    data: {
        message: string;
        code?: string;
        details?: Record<string, unknown>;
    };
}
/** Stable raw lifecycle/interaction/plan/route events forwarded unchanged. */
type ProducerPassthroughEventType = 'turn' | 'metadata' | 'interaction' | 'interaction.cancel' | 'plan.submitted' | 'done' | 'warning' | 'session.run.started' | 'session.run.completed' | 'session.run.failed' | 'turn_status';
/** Define an event carrying passthrough data with flexible properties for producer communication */
interface ProducerPassthroughEvent {
    type: ProducerPassthroughEventType;
    data?: Record<string, unknown>;
    /** Route markers and raw passthroughs may carry `turnId`, `status`, `seq`, etc. */
    [key: string]: unknown;
}
/** Represent events emitted by a producer during its operation for processing and handling */
type ProducerWireEvent = ProducerTextEvent | ProducerReasoningEvent | ProducerToolCallEvent | ProducerToolResultEvent | ProducerUsageEvent | ProducerNoticeEvent | ProducerErrorEvent | ProducerPassthroughEvent;
/** The image/file split an attachment is rendered and persisted under — the
 *  same discriminant as {@link ChatMentionKind}, but a distinct name because an
 *  attachment carries content the product uploaded (`ChatAttachmentInput`)
 *  while a mention points at a file the box already has. Defined HERE (the
 *  import-free layer) so `ChatAttachmentInput` can reference it and the client
 *  composer imports it without pulling the persisted-part vocabulary;
 *  `/chat-store`'s parts module re-exports it alongside the attachment helpers. */
type ChatAttachmentKind = 'image' | 'file';
/** `POST` turn-body entry describing a file already uploaded to the product's
 *  store (vault/object-store) — distinct from an inline {@link
 *  ChatTurnFilePartInput} (which carries bytes) and from a {@link FileMention}
 *  (a sandbox path the box already holds). The route resolves this field with
 *  {@link resolveChatAttachments}: every path is re-validated and every size is
 *  re-derived from the stored body, so nothing here is trusted as sent. */
interface ChatAttachmentInput {
    path: string;
    name: string;
    size: number;
    mediaType: string;
    kind: ChatAttachmentKind;
}
/** POST body for the turn route. `content` may be empty when `parts` carry the
 *  message (an image-only send). Product routing fields (workspaceId etc.) ride
 *  alongside and are read by the product's `authorize` seam. */
interface ChatTurnRequestPayload {
    threadId: string;
    content?: string;
    /** Non-text parts from the upload route, echoed back verbatim. */
    parts?: ChatTurnFilePartInput[];
    /** `@`-picked file mentions for this turn — path references into the
     *  workspace sandbox, NOT uploads, so they travel in their own field rather
     *  than as `parts` entries. A product whose `parts` field is already spoken
     *  for (an attachment sentinel) can still send mentions, and mentions
     *  persist as their own `ChatMentionPart`s so a retry rebuilds them. The
     *  route validates this field with {@link parseFileMentions} and replaces it
     *  on the payload with the validated, deduped list. */
    mentions?: FileMention[];
    /** Files uploaded to the product's store ahead of the turn — path
     *  references, NOT inline bytes (those ride `parts`). Validated and
     *  size-re-derived by {@link resolveChatAttachments} into persistable
     *  attachment parts; a product whose `parts` field is spoken for by inline
     *  uploads still sends store-backed files here. */
    attachments?: ChatAttachmentInput[];
    model?: string;
    effort?: 'auto' | 'low' | 'medium' | 'high';
    harness?: string;
    /** Client-generated idempotency key for the logical turn (retry-safe). */
    turnId?: string;
    [key: string]: unknown;
}
/** `fetch` init for the turn route — the one place the client wire shape is
 *  serialized, so composer glue and products never drift from the server's
 *  parser. */
declare function chatTurnRequestInit(payload: ChatTurnRequestPayload): RequestInit;
/** Define the maximum byte size allowed for inline parts in data processing */
declare const INLINE_PARTS_MAX_BYTES = 950000;
/** Hard cap on the whole `/prompt` request body as it crosses the sandbox
 *  proxy — smaller in practice than a raw-file write cap because a dispatch
 *  carries several inline parts plus the flattened history in one request. */
declare const DISPATCH_REQUEST_MAX_BYTES: number;
/** Bytes reserved off the top of {@link DISPATCH_REQUEST_MAX_BYTES} for the
 *  JSON structure around the parts array (keys, delimiters, per-part
 *  `type`/`filename`/`mediaType` fields) that {@link base64WireLen} does not
 *  account for — keeps the inline budget off the exact proxy cap where one
 *  stray byte trips the 413. */
declare const DISPATCH_STRUCTURAL_RESERVE_BYTES: number;
/** Sidecar's hard cap on the `parts` array of one prompt request — a dispatch
 *  must never assemble more parts than this or the whole turn 400s. */
declare const DISPATCH_MAX_PARTS = 64;
/** Product-side cap on media parts per dispatch (current turn + carried
 *  history), well under {@link DISPATCH_MAX_PARTS}. History trimming that keeps
 *  a transcript's native media under this is a PRODUCT concern (the pointer
 *  block keeps trimmed media reachable); `buildDispatchParts` enforces only the
 *  total {@link DISPATCH_MAX_PARTS} cap. */
declare const DISPATCH_MAX_MEDIA_PARTS = 24;
/** Size a base64-encoded string occupies on the wire given the raw
 *  (pre-encoding) byte length: base64 packs 3 raw bytes into 4 output
 *  characters, rounded up to the next multiple of 4. */
declare function base64WireLen(byteLen: number): number;
/**
 * Render a raw byte count as a human-readable size (`512B`, `3KB`, `12MB
 * 500KB`). Ported EXACTLY from gtm-agent's `attachment-limits.ts` — byte-
 * identical implementation, not a reinterpretation — so `resolve-attachments`'s
 * and `promote-file-part`'s error strings match gtm's wording verbatim. Lives
 * in the import-free wire layer (not `resolve-attachments.ts` alone) because
 * BOTH the aggregate-cap message here and the per-file oversize message in
 * `promote-file-part.ts` need it; a browser composer wanting the same
 * formatting for a client-side pre-check can also import it with no engine
 * pulled in.
 */
declare function formatBytes(bytes: number): string;
/** Represent errors for invalid chat turn inputs with status and code properties */
declare class ChatTurnInputError extends Error {
    readonly status: number;
    readonly code: string;
    constructor(message: string, status?: number, code?: string);
}
/** Calculate the total byte size of an array of chat turn parts */
declare function promptPartsByteSize(parts: ChatTurnPartInput[]): number;
/** Throws `ChatTurnInputError` (413) when the parts' inline payload would blow
 *  the gateway cap. Path-ref parts are tiny by construction and always pass. */
declare function assertPromptPartsWithinCap(parts: ChatTurnPartInput[], maxBytes?: number): void;
/** A file mention resolved from the composer's `@`-picker: the
 *  workspace-relative path plus enough metadata to build a prompt part and
 *  pointer text. `path` is the canonical identity — the mention pill's
 *  `MentionItem.id` for the file kind (`/web-react`'s `useFileMentions`). */
interface FileMention {
    path: string;
    name: string;
    size?: number;
}
/** The `image/*` mime for a mention path by extension, or `undefined` for
 *  anything not in the known image set (dispatched as `type: 'file'`). */
declare function mediaTypeForMentionPath(path: string): string | undefined;
/** The image/file split a mention is rendered and persisted under — the
 *  composer pill's icon, the dispatched part's `type`, and
 *  `ChatMentionPart.mentionKind` are all this one value. */
type ChatMentionKind = 'image' | 'file';
/** `image` when the path's extension is in the known image set (the same table
 *  {@link mediaTypeForMentionPath} reads), `file` otherwise. Exported so a
 *  client that needs only the discriminant — a pill icon, a persisted part's
 *  `mentionKind` — never re-declares the extension table; two frozen copies of
 *  one mime table is how one gains a format and the other doesn't. */
declare function mentionKindForPath(path: string): ChatMentionKind;
/** Define options to resolve mention paths when converting file mentions to parts */
interface FileMentionsToPartsOptions {
    /** Resolve a mention's workspace-relative path to the absolute path the
     *  dispatched part should carry (e.g. a host prefixing the in-box vault
     *  root). Default: identity — the path travels unchanged. */
    resolvePath?: (path: string) => string;
}
/** Maps resolved file mentions to path-only `ChatTurnFilePartInput`s —
 *  `image` vs `file` by extension, and always a `path`, never a `url` (the
 *  url/path XOR invariant: a mention is a sandbox path reference, never
 *  inline bytes). */
declare function fileMentionsToParts(mentions: readonly FileMention[], opts?: FileMentionsToPartsOptions): ChatTurnFilePartInput[];
/** The agent-facing pointer block appended to the dispatched prompt — never
 *  persisted in message `content`. Empty array → `''` so callers can append
 *  unconditionally. This is the sole producer of that text: the current
 *  turn's dispatch and any history projection built from the same mention
 *  list both route through here, so the two can't drift apart. */
declare function buildMentionPromptBlock(mentions: readonly Pick<FileMention, 'name' | 'path'>[]): string;
/** Hard cap on mentions per turn. Bounds the prompt pointer block, the
 *  persisted parts, and whatever media budget a dispatch draws from them. */
declare const MENTION_MAX_COUNT = 16;
/** Represent the result of a sandbox mention path check indicating success or failure with an error message */
type SandboxMentionPathCheck = {
    succeeded: true;
} | {
    succeeded: false;
    error: string;
};
/**
 * Validate a workspace-relative sandbox mention path. Rejects traversal (a
 * `..` path segment), absolute paths (leading `/`), backslashes, and null
 * bytes — the four ways a path picked in a client can escape the root the
 * index route scanned.
 *
 * Spaces and unicode are deliberately ALLOWED: in-box filenames are arbitrary,
 * and an ASCII-only charset would silently drop real files from a feature
 * whose whole job is naming them.
 */
declare function validateSandboxMentionPath(path: unknown): SandboxMentionPathCheck;
/**
 * Validates the untyped `mentions` array off the wire, mirroring
 * {@link parseChatTurnParts}: the typed list, or `ChatTurnInputError` (400)
 * naming the offending entry. Never sanitizes-and-continues — a traversal path
 * is a rejected request, not a trimmed one.
 *
 * A path repeated within one turn is deduped to its first occurrence rather
 * than rejected: mentioning the same file twice is plausible user input, not
 * an attack.
 */
declare function parseFileMentions(raw: unknown): FileMention[];
/** Validates the untyped `parts` array off the wire. Returns the typed parts
 *  or throws `ChatTurnInputError` (400) naming the offending entry. */
declare function parseChatTurnParts(raw: unknown): ChatTurnFilePartInput[];

/**
 * The stored shape of `message.parts` — one typed vocabulary for every part a
 * product persists into a chat transcript. NOT an ad-hoc union reverse-
 * engineered from product schemas; each member is matched field-for-field to
 * its canonical source:
 *
 * - `text` / `reasoning` / `tool`: the persisted projection `/stream`'s
 *   `normalizePersistedPart` produces from the harness lane's
 *   `message.part.updated` events (ADC sidecar
 *   `apps/sidecar/src/events/session-events.ts:56` wraps the canonical part in
 *   an `{id, sessionID, messageID}` envelope; the projection strips the
 *   session/message ids and keeps the per-segment part id).
 * - `file` / `image` / `step-start` / `step-finish`: the sidecar's canonical
 *   `MessagePartSchema` members (ADC
 *   `apps/sidecar/src/schemas/agent-schemas.ts:50-154`); `step-finish` carries
 *   the harness's per-step usage receipt — tokens
 *   `{total, input, output, reasoning, cache{write, read}}` + `cost` — which is
 *   also the shape the message-level token/cost columns mirror.
 * - `subtask`: `@tangle-network/agent-interface`'s `SubtaskPart` (a spawned
 *   sub-agent task).
 * - `interaction` / `notice`: the persisted-part codecs in
 *   `/web-react`'s chat-interactions contract (`interactionToPersistedPart`,
 *   `noticePart`) — type-only imports, one source of truth for their statuses
 *   and field shapes.
 * - `plan`: the durable-plan projection in `/plans`, derived from the sandbox
 *   SDK's authoritative plan lifecycle.
 * - `work_product`: the persisted work-product anchor card in
 *   `/work-product`'s contract (`workProductToPersistedPart` /
 *   `persistedPartToWorkProduct`) — SYSTEM-authored on the ready transition
 *   and updated on a reviewer verdict; no prompt teaches an agent to author
 *   one.
 * - `mention`: an `@`-picked reference to a file that already lives in the
 *   workspace sandbox (`FileMention` in `/chat-routes`'s wire contract, plus
 *   the image/file discriminant). Neither transport lane produces it — the
 *   turn route persists it from the request's `mentions` field — but it is a
 *   part a product persists into a transcript, so it belongs in this
 *   vocabulary rather than in a parallel one.
 *
 * `@tangle-network/agent-interface` exports the canonical wire `Part` union,
 * but its `PartBase` requires the `sessionID`/`messageID` stream envelope that
 * is deliberately NOT persisted, so the stored union is defined here as the
 * envelope-free projection (a type-level coverage check against the peer's
 * `Part['type']` lives in the tests). Contribute-down candidate: if
 * agent-interface grows envelope-free persisted-part types, re-export them
 * here and delete these definitions.
 *
 * Two transport lanes serialize into this SAME stored shape:
 * - harness lane: canonical `message.part.updated` parts, merged/normalized by
 *   `/stream` (`mergePersistedPart`, `finalizeAssistantParts`);
 * - router/openai-compat lane: `text_delta`/`tool_call` stream events are
 *   mapped INTO canonical part events first (`/runtime`'s `toLoopEvents` +
 *   `/stream`'s `normalizeToolEvent`) and then persisted identically — the
 *   store never sees a router-specific shape.
 */

/** Start/end wall-clock millis, as normalized by `/stream`'s `normalizeTime`. */
interface ChatPartTime {
    start?: number;
    end?: number;
}
/** `id` is the harness's per-segment identity; absent on legacy/router parts,
 *  which collapse to a single logical text stream. Never invented client-side. */
interface ChatTextPart {
    type: 'text';
    text: string;
    id?: string;
}
/** Define a reasoning part of a chat with text content and optional metadata fields */
interface ChatReasoningPart {
    type: 'reasoning';
    text: string;
    id?: string;
    time?: ChatPartTime;
}
/** Superset of the sidecar's status enum (`pending|running|completed|failed`)
 *  and agent-interface's `ToolState` statuses; `error` is the persisted
 *  terminal form `/stream`'s `normalizePersistedPart` settles on. */
type ChatToolStatus = 'pending' | 'running' | 'completed' | 'error' | 'failed';
/** Describe the current state and data of a chat tool including status, input, output, and metadata */
interface ChatToolState {
    status: ChatToolStatus;
    input?: unknown;
    output?: unknown;
    error?: string;
    title?: string;
    metadata?: Record<string, unknown>;
    time?: ChatPartTime;
}
/** Define a chat component representing a tool with its state and optional call identifier */
interface ChatToolPart {
    type: 'tool';
    id: string;
    tool: string;
    callID?: string;
    state: ChatToolState;
}
/** Union of the sidecar's legacy (path-based) and AI-SDK (url-based) file
 *  shapes; response-side every field besides `type` is optional. `name` is the
 *  attachment-flavored display label an uploaded/promoted file carries (see
 *  {@link ChatAttachmentPart}) — absent on a harness-emitted file part, which
 *  uses `filename`. */
interface ChatFilePart {
    type: 'file';
    id?: string;
    filename?: string;
    name?: string;
    mediaType?: string;
    url?: string;
    path?: string;
    content?: string;
}
/** Define properties for an image part within a chat message including optional metadata fields */
interface ChatImagePart {
    type: 'image';
    filename?: string;
    name?: string;
    mediaType?: string;
    url?: string;
    path?: string;
}
/** Define a subtask part of a chat with prompt, description, agent, and optional identifier */
interface ChatSubtaskPart {
    type: 'subtask';
    prompt: string;
    description: string;
    agent: string;
    id?: string;
}
/** OpenCode step-boundary marker — no renderable text; preserved so mappers
 *  never coerce it into a "[object Object]" text part. */
interface ChatStepStartPart {
    type: 'step-start';
}
/** Per-step usage receipt as the harness reports it (sidecar
 *  `StepFinishPartSchema`). The message-level token/cost columns are this
 *  shape flattened. */
interface ChatUsageTokens {
    total?: number;
    input?: number;
    output?: number;
    reasoning?: number;
    cache?: {
        write?: number;
        read?: number;
    };
}
/** Define a chat step finish part indicating completion with optional reason, tokens, and cost */
interface ChatStepFinishPart {
    type: 'step-finish';
    reason?: string;
    tokens?: ChatUsageTokens;
    cost?: number;
}
/** Persisted human-in-the-loop ask — byte-matches
 *  `interactionToPersistedPart` in `/web-react`'s chat-interactions contract. */
interface ChatInteractionPart {
    type: 'interaction';
    id: string;
    kind: string;
    title: string;
    body?: string;
    answerSpec: {
        fields: ChatInteractionField[];
    };
    status: ChatInteractionStatus;
    answers?: InteractionAnswers;
    cancelReason?: string;
}
/** Resolve a chat plan part by aliasing it to the persisted chat plan part type */
type ChatPlanPart = ChatPlanPersistedPart;
/** Persisted work-product anchor card — byte-matches
 *  `workProductToPersistedPart` in `/work-product`'s contract. Written by the
 *  PLATFORM on the ready transition (and updated on a verdict); never
 *  authored by a prompt. */
type ChatWorkProductPart = WorkProductPersistedPart;
/** Persisted one-line transcript notice — byte-matches `noticePart` in
 *  `/web-react`'s chat-interactions contract. */
interface ChatNoticePart {
    type: 'notice';
    id: string;
    noticeKind: NoticeKind;
    text: string;
}
/**
 * A file the user `@`-mentioned on this turn: a workspace-relative path into
 * the sandbox, never bytes. `type: 'mention'` is its own discriminant
 * precisely so it does NOT collide with the `file`/`image` attachment parts —
 * an attachment carries content the product uploaded, a mention points at
 * something the box already has, and a transcript renders them differently
 * (an inline pill, not an attachment card).
 *
 * `path` is the identity: mentioning one file twice in a turn folds to one
 * part. `turnId` is optional and set by products that rebuild a turn's
 * mentions on retry.
 */
interface ChatMentionPart {
    type: 'mention';
    mentionKind: ChatMentionKind;
    path: string;
    name: string;
    size?: number;
    turnId?: string;
}
/** Represent parts of a chat message including text, reasoning, tools, files, images, subtasks, steps, interactions, notices, plans, and mentions */
type ChatMessagePart = ChatTextPart | ChatReasoningPart | ChatToolPart | ChatFilePart | ChatImagePart | ChatSubtaskPart | ChatStepStartPart | ChatStepFinishPart | ChatInteractionPart | ChatNoticePart | ChatPlanPart | ChatWorkProductPart | ChatMentionPart;
/** Every canonical harness wire-part kind must be storable — compile-time
 *  guarantee that a new agent-interface part kind cannot silently fall out of
 *  the persisted vocabulary. */
type StorableHarnessPartKind = Part['type'] & ChatMessagePart['type'];
/**
 * The typed projection at the `/stream` → `/chat-store` boundary. The stream
 * normalizers (`normalizePersistedPart`/`mergePersistedPart`/
 * `finalizeAssistantParts`) deliberately produce untyped `JsonRecord`s — they
 * normalize wire shapes and do not own the stored vocabulary. THIS module
 * owns it, so this is where rows gain the `ChatMessagePart` type: each entry
 * is validated against its kind's required fields and narrowed, junk is
 * dropped, and — enforced by the exhaustiveness check below — no storable
 * kind can silently fall out (the step-finish/interaction trap).
 */
declare function toChatMessageParts(parts: Array<Record<string, unknown>>): ChatMessagePart[];
/** Resolve whether a ChatMessagePart is specifically a ChatToolPart based on its type property */
declare function isChatToolPart(part: ChatMessagePart): part is ChatToolPart;
/** Resolve whether a chat message part is a text part based on its type property */
declare function isChatTextPart(part: ChatMessagePart): part is ChatTextPart;
/** Resolve whether a ChatMessagePart is a ChatInteractionPart based on its type property */
declare function isChatInteractionPart(part: ChatMessagePart): part is ChatInteractionPart;
/** Resolve whether a chat message part is a persisted chat plan part */
declare function isChatPlanPart(part: ChatMessagePart): part is ChatPlanPart;
/** Resolve whether a chat message part is a persisted work-product anchor */
declare function isChatWorkProductPart(part: ChatMessagePart): part is ChatWorkProductPart;
/** Determine if a chat message part represents the completion of a chat step */
declare function isChatStepFinishPart(part: ChatMessagePart): part is ChatStepFinishPart;
/** Widened to `unknown` — unlike its siblings this guard also runs over raw
 *  untyped stored rows (a transcript renderer reads `message.parts` before the
 *  typed projection), which is exactly what {@link mentionPartsFromMessageParts}
 *  needs. `path` and `name` carry the pill; a row missing either is unrenderable.
 *
 *  Mirrors the write contract exactly (`parseFileMention` in `/chat-routes`,
 *  then {@link mentionInputToPart}): a blank `name` is rejected there and so is
 *  rejected here, and `size` — optional, but typed `number` once present — is
 *  type-checked so `'12'` or `null` cannot ride through the guard wearing a
 *  type it does not have. Negative sizes are NOT re-rejected: the wire screens
 *  them, `mentionInputToPart` trusts its input, and a read guard stricter than
 *  what the writer can emit would drop rows it produced itself. */
declare function isChatMentionPart(part: unknown): part is ChatMentionPart;
/** Every mention part on one message, in stored order. The projection a
 *  transcript renderer runs before deciding which mentions the message text
 *  already shows inline (see `segmentMentionContent` in `/web-react`). */
declare function mentionPartsFromMessageParts(parts: ReadonlyArray<Record<string, unknown>> | ReadonlyArray<ChatMessagePart> | null | undefined): ChatMentionPart[];
/** A validated wire mention (`parseFileMentions` in `/chat-routes`) as the
 *  part the turn route persists. An absent/non-finite `size` is DROPPED rather
 *  than stored as `undefined`, so a stored row never carries a key that means
 *  nothing. */
declare function mentionInputToPart(input: FileMention): ChatMentionPart;
/** `image` for any `image/*` mime, `file` for everything else (including an
 *  absent/empty mime) — the same split the composer and the persisted-part
 *  discriminant both key on. */
declare function attachmentKindForMime(mime?: string): ChatAttachmentKind;

/**
 * Persisted attachment part: structurally an attachment-flavored `ChatFilePart`
 * / `ChatImagePart` (`path` + `name` promoted to required) rather than a
 * separate union member — see the section note above. The index signature keeps
 * it a `Record<string, unknown>` so it drops into the same untyped `parts`
 * arrays every other stored part rides in, and lets the `type`-driven
 * constructors below build it without union-discriminant gymnastics.
 */
interface ChatAttachmentPart {
    type: ChatAttachmentKind;
    path: string;
    name: string;
    size?: number;
    mediaType?: string;
    turnId?: string;
    [key: string]: unknown;
}
/** True for any `image`/`file` part carrying a non-empty string `path`.
 *  DELIBERATELY also matches a sidecar path-bearing file part (a mention-style
 *  `file` part with only `path`) — the guard is a structural attachment shape,
 *  not proof of provenance; a caller that needs to exclude those filters
 *  upstream. The `path.length > 0` check diverges from gtm's original guard
 *  (which only checked `typeof`), mirroring sibling {@link isChatMentionPart}:
 *  read-side robustness against a stored `{type:'file', path:''}` row — which
 *  would otherwise render a malformed `(vault: )` pointer line — justifies the
 *  small divergence from byte-for-byte gtm parity here; no legitimate write
 *  path ever produces an empty `path`. */
declare function isChatAttachmentPart(part: unknown): part is ChatAttachmentPart;
/** Drop absent/empty optional fields rather than persisting `undefined`/`''`
 *  — keeps stored parts minimal. */
declare function attachmentInputToPart(input: ChatAttachmentInput): ChatAttachmentPart;
/** Every attachment part on one message's stored `parts`, in stored order. */
declare function attachmentPartsFromMessageParts(parts: ReadonlyArray<Record<string, unknown>> | null | undefined): ChatAttachmentPart[];
/** gtm's exact default header for {@link buildAttachmentPromptBlock} — kept
 *  byte-identical because it feeds dispatched prompts (gtm-agent#618
 *  reproduces the prompt bytes through this module). Override only with intent. */
declare const DEFAULT_ATTACHMENT_PROMPT_HEADER = "Attached files (already saved to the workspace vault \u2014 read them from these paths):";
/**
 * The agent-facing pointer block appended to the dispatched prompt — never
 * persisted in `message.content`. Empty array → `''` so callers can append
 * unconditionally. The sole producer of this text: both the current turn's
 * dispatch and history projection ({@link historyContentWithAttachments}) build
 * it from here, so the two can never drift. `header` overrides the first line
 * ({@link DEFAULT_ATTACHMENT_PROMPT_HEADER}); the per-file line format is fixed.
 *
 * Every interpolated `name`/`path` is swept for control characters first
 * (newline/carriage-return/tab included) and each one replaced with a single
 * space — a single-line-per-file guarantee. Without it, a control character
 * riding through on a PERSISTED row (`historyContentWithAttachments` reads
 * whatever is already stored; a legacy or hand-edited row was never re-checked
 * against `resolveChatAttachments`) could inject extra lines — fabricated
 * pointer entries or instructions — into a prompt the agent trusts verbatim.
 * The wire-side validator is the primary control; this is the backstop for
 * rows it never saw.
 */
declare function buildAttachmentPromptBlock(atts: ReadonlyArray<Pick<ChatAttachmentPart, 'name' | 'path'>>, header?: string): string;
/**
 * History projection for a persisted message: `content` unchanged when it
 * carries no attachment parts, else the block is appended once. The
 * no-double-annotation guarantee holds under the invariant that the block is
 * never persisted INTO `message.content` — it is appended only at read time,
 * by this function and the current turn's dispatch, both sourcing from
 * `attachmentPartsFromMessageParts` — never by content inspection. This
 * function does not (and cannot) detect an already-embedded block by scanning
 * `content` for its text: a message whose stored `content` happens to already
 * contain the block's bytes, alongside attachment parts, still gets the block
 * appended a second time. See the pinned test for that boundary.
 */
declare function historyContentWithAttachments(message: {
    content: string;
    parts?: ReadonlyArray<Record<string, unknown>> | null;
}, header?: string): string;

export { type ProducerErrorEvent as $, isChatInteractionPart as A, isChatMentionPart as B, type ChatMessagePart as C, DEFAULT_ATTACHMENT_PROMPT_HEADER as D, isChatPlanPart as E, isChatStepFinishPart as F, isChatTextPart as G, isChatToolPart as H, isChatWorkProductPart as I, mentionInputToPart as J, mentionPartsFromMessageParts as K, toChatMessageParts as L, type FileMention as M, type ChatTurnRequestPayload as N, type ChatTurnPartInput as O, type ChatTurnFilePartInput as P, type ChatAttachmentInput as Q, ChatTurnInputError as R, type StorableHarnessPartKind as S, type ChatTurnTextPartInput as T, DISPATCH_MAX_MEDIA_PARTS as U, DISPATCH_MAX_PARTS as V, DISPATCH_REQUEST_MAX_BYTES as W, DISPATCH_STRUCTURAL_RESERVE_BYTES as X, type FileMentionsToPartsOptions as Y, INLINE_PARTS_MAX_BYTES as Z, MENTION_MAX_COUNT as _, type ChatAttachmentKind as a, type ProducerNoticeEvent as a0, type ProducerPassthroughEvent as a1, type ProducerPassthroughEventType as a2, type ProducerReasoningEvent as a3, type ProducerTextEvent as a4, type ProducerToolCallEvent as a5, type ProducerToolResultEvent as a6, type ProducerUsageEvent as a7, type ProducerWireEvent as a8, type SandboxMentionPathCheck as a9, assertPromptPartsWithinCap as aa, base64WireLen as ab, buildMentionPromptBlock as ac, chatTurnRequestInit as ad, fileMentionsToParts as ae, formatBytes as af, mediaTypeForMentionPath as ag, mentionKindForPath as ah, parseChatTurnParts as ai, parseFileMentions as aj, promptPartsByteSize as ak, validateSandboxMentionPath as al, type ChatAttachmentPart as b, type ChatFilePart as c, type ChatImagePart as d, type ChatInteractionPart as e, type ChatMentionKind as f, type ChatMentionPart as g, type ChatNoticePart as h, type ChatPartTime as i, type ChatPlanPart as j, type ChatReasoningPart as k, type ChatStepFinishPart as l, type ChatStepStartPart as m, type ChatSubtaskPart as n, type ChatTextPart as o, type ChatToolPart as p, type ChatToolState as q, type ChatToolStatus as r, type ChatUsageTokens as s, type ChatWorkProductPart as t, attachmentInputToPart as u, attachmentKindForMime as v, attachmentPartsFromMessageParts as w, buildAttachmentPromptBlock as x, historyContentWithAttachments as y, isChatAttachmentPart as z };
