import { AGENT_CONTEXT_MARK, type ApprovalRequest, type JsonSchema, type RiskLabel, type VendoKnowledgeCitation } from "../../../core/index.js"; import { type UIMessage } from "ai"; export declare function partData(part: UIMessage["parts"][number]): unknown; /** The marker the agent's `wireErrorMessage` puts on its OWN safe error text * (VendoError code + operator-crafted message). Only prefixed strings may be * shown in detail to an end user; raw transport/provider strings never carry * it. Read by both error surfaces (the banner and the turn-error part). */ export declare const VENDO_ERROR_PREFIX = "Vendo: "; /** * The sentence a broken turn CARRIES, verbatim — minus the marker — or nothing. * * The marker says the sentence is OURS: a VendoError's operator-crafted message * plus its code, which is the one error shape a reader may see in detail. It * reaches them unedited. This used to look the code up in a dictionary of canned * first-person lines and print that instead, which spoke as the agent AND threw * the actionable half away — "Vendo: check ANTHROPIC_API_KEY in .env.local * (validation)" arrived as "I couldn't make that request work". * * An UNPREFIXED string is a raw transport/provider error (those carry request * URLs, keys and prompts), so it still yields nothing and the surface says * {@link TURN_FAILURE_NOTICE} in its own voice instead. */ export declare function turnErrorSentence(message: string | undefined): string | undefined; /** What the CHROME says when a turn broke with nothing of ours to repeat: the * system in third person, never the agent in first. */ export declare const TURN_FAILURE_NOTICE = "This request couldn\u2019t be completed \u2014 nothing was changed."; /** * What a person is told when an app build fails: the runtime's own reason. * * `buildFailureReason` (apps' build-messages.ts) emits only classified, * non-leaky text — "timed out", "quota exhausted", the watchdog's line — and * passes the dev-model's actionable lines through verbatim (a missing * `@ai-sdk/*` package, a rejected key). Those are exactly what the reader needs, * and one canned first-person sentence used to replace all of them. The * operator's fuller record — the reason plus every blocking finding — keeps its * home in the server's `[vendo] app build failed (app_…)` line. * * A reason off the WIRE arrives behind the build-failed marker ("app build * failed: timed out"), because the bridge sends the VendoError's whole message; * the marker is plumbing, so it comes off. */ export declare function buildFailureNotice(reason: string | undefined): string; /** * What a person is told when the host's limits policy denies them: the host's * own sentence, verbatim. * * The host set the cap, so the host is the only one who can say what it is, or * when it lifts — the same reason `buildFailureNotice` above passes the * runtime's classified line through rather than replacing it with one canned * sentence. A policy that returned no message gets the chrome's own line, which * claims nothing it cannot know: only that the request never ran. */ export declare function limitNotice(message: string | undefined): string; export declare const SYNTHESIZED_CREATED_AT = "1970-01-01T00:00:00.000Z"; export declare function riskByCall(messages: UIMessage[]): Map; /** Guard approval metadata by tool call — carried in the data-vendo-approval part beside the native ai-SDK approval (whose own id is transport-local). `descriptor` rides here too when the server has one: the wire parts are `.passthrough()`, so a newer server can send the declared schema/title/description with the ask and an older one simply omits it (buildApprovalRequest then degrades to host ToolMeta). */ export declare function approvalByCall(messages: UIMessage[]): Map; export interface ApprovalWireMeta { approvalId?: string; invalidatedGrant?: ApprovalRequest["invalidatedGrant"]; /** The passthrough descriptor fields buildApprovalRequest consumes. */ descriptor?: { title?: string; description?: string; inputSchema?: JsonSchema; }; } /** Grant-set membership by tool call — carried in the data-vendo-grant-set part beside the parked native call. The thread uses it to (a) hand the parked call to the set card instead of the plain ApprovalCard, and (b) resume on a decided announcement that matches the SET (by grantSetId or any member approval id), not just the raw native id. */ export declare function grantSetByCall(messages: UIMessage[]): Map; /** What a turn's `data-vendo-citations` parts add up to. Chips render only ANSWERED citations (a refusal's weak hits stay off the chip row); the flags carry the refusal/outage states. */ export interface TurnKnowledgeSources { citations: VendoKnowledgeCitation[]; refused: boolean; unavailable: boolean; } /** Fold a turn's citations parts into the one summary TurnCitations renders, deduped by doc+chunk across multiple knowledge calls in the same turn. */ export declare function sourcesFor(message: UIMessage): TurnKnowledgeSources; export declare function toolName(part: Extract): string; /** The app-boundary title: the payload's `name`, else its first heading Text node. */ export declare function appTitle(payload: unknown): string | undefined; /** Collapse runs of consecutive identical tool chips (e.g. eight `host_listClientDocuments` calls) into one entry carrying a count. The latest part in the run is kept so the chip icon reflects the final state. */ export declare function collapseToolRuns(parts: UIMessage["parts"]): { part: UIMessage["parts"][number]; index: number; count: number; }[]; /** A tool call the turn is still working, or waiting on: the transcript's beats stay open until every call in the turn has reached a terminal state (a settled output, an error, or a refused ask). */ export declare function toolCallPending(part: UIMessage["parts"][number]): boolean; /** A call PARKED on the user — the one state whose consent card is the turn's live surface, so the turn's hover actions stand down and the beat above the card sits directly on it. Narrower than `toolCallPending` on purpose: pending is also true for a call abandoned mid-flight (Stop never reconciles an aborted call out of `input-available`), and gating the actions on that took Copy/Regenerate away from a stopped turn for good. */ export declare function toolCallParked(part: UIMessage["parts"][number]): boolean; /** A call the HOST's OWN RULES refused — a policy block, a usage limit — which settles carrying the `blocked` outcome (packages/vendo/src/harnesses/wire.ts). Distinct from `output-denied`, which the ai-SDK reserves for an approval the PERSON turned down: nobody asked them about this one, so the beat must not say they said no. */ export declare function toolCallRefused(part: UIMessage["parts"][number]): boolean; /** The narrower case inside `toolCallRefused`: an ask whose wait elapsed with no answer (H2-G). Nobody's no at all — not the person's (they never answered) and not the rules' — so the beat says the question expired instead of attributing the refusal to anyone. */ export declare function toolCallExpired(part: UIMessage["parts"][number]): boolean; /** A failed, refused or declined call is CONTENT, not progress: its beat stays visible after the turn folds, and it never counts as a thing the agent did. Everything else is progress, and progress folds into the summary. */ export declare function toolCallIsContent(part: UIMessage["parts"][number]): boolean; /** The app-building call this turn's app card is narrating. The card bar narrates that step ("Building your view…" → the app's name), so a beat beside it would narrate the same work twice; the settled summary still counts it. Recognized the way the server decides to emit the view part (the apps tool namespace + a tree surface), never by duck-typing an output. A running `vendo_make` is recognized by tool IDENTITY, before its output exists: it is the one tool that streams partial views, so the card is already up during the build window. No other apps tool streams a partial view, so for the rest the beat is the only narration until their tree lands — and a build parked on an approval or FAILED has no card, so its beat is the whole record. */ export declare function narratedByAppCard(part: UIMessage["parts"][number], siblingParts: UIMessage["parts"]): boolean; /** * The grounding carrier: a text part the MODEL reads and the person never sees. * An affordance that opens the conversation about a specific thing (the ✦ remix * popover) has to tell the agent WHICH thing, and the identifier is an app id — * plumbing, not something a person types or reads. So it rides the sent message * as its own marked text part; the transcript skips it and `userText` (which * seeds "edit last message") leaves it out. * * A text part is the carrier because it is the ONLY channel that reaches the * model: `convertToModelMessages` keeps text and drops metadata and data parts. */ export declare const AGENT_CONTEXT_METADATA: { readonly vendo: { readonly agentContext: true; }; }; /** * The SAME mark, in the text itself — core's, re-exported for the chrome's * consumers. * * `providerMetadata` alone is not enough: a store that persists a text part as * `{ type, text }` — which the wire contract permits — drops it, and the marked * part comes back as an ORDINARY text part, so a reloaded transcript prints the * app id. The mark lives in core because the SERVER needs it too: thread titles * are minted server-side in packages/vendo/src/threads.ts. */ export { AGENT_CONTEXT_MARK }; /** The text part that carries grounding to the model and to nobody else. */ export declare function agentContextPart(context: string): { type: "text"; text: string; providerMetadata: typeof AGENT_CONTEXT_METADATA; }; export declare function isAgentContext(part: UIMessage["parts"][number]): boolean; /** The plain text a user turn carried, joined across its text parts — the seed for "edit last message". */ export declare function userText(message: UIMessage): string; /** What "copy this turn" yields for an assistant message: its text parts (the markdown source), blank-line separated — tool beats and views don't copy. */ export declare function assistantText(message: UIMessage): string; /** The in-thread approval preview, built client-side: readable `Label: value` lines instead of raw JSON with literal \n escapes. */ export declare function preview(input: unknown): string;