import type { ActionProposal, ActionProposalMutationResult, AgentCatalogEntry, AgentClientConfig, ChatQueueState, MessageAttachment, MessageFeedback, ModelCatalogView, QuotaReport, SkillCatalogEntry, ThreadDetail, ThreadSummary, ToolCatalogEntry } from '../../index.js';
import type { AgentBackend, AttachmentUploadStrategy, ChatStreamRequest, ChatStreamResponse, MessageFeedbackInput, QueuedMessageUpdate, QueuedSendResult, ResumeStreamRequest, ThreadPatch, UploadAttachmentOptions } from './backend.js';
import { type AgentRequestError, type ErrorAnswer, type HttpErrorListener } from './http-error.js';
export type { ThreadPatch } from './backend.js';
export type { AgentRequestError, HttpErrorListener } from './http-error.js';
/**
 * Thrown by {@link AgentClient} on a non-2xx response. Carries the HTTP `status` so callers can
 * branch (e.g. 403 → "not your thread", 429 → quota) instead of string-matching a generic Error,
 * and what the server said: `message` is the body's `message` when it sent one (so a hook that
 * shows `error.message` shows the server's words), `code` its machine-readable `code`, and `body`
 * the whole answer, parsed when it is JSON.
 */
export declare class AgentHttpError extends Error implements AgentRequestError {
    readonly status: number;
    readonly method: string;
    readonly path: string;
    /** The answer's body: parsed JSON, else its text; `undefined` when empty. */
    readonly body: unknown;
    /** The body's `code` (`quota_exceeded`, …), when the server sent one. */
    readonly code: string | undefined;
    constructor(status: number, method: string, path: string, statusText: string, answer?: ErrorAnswer);
    /** Read a refused `response`'s body into an error. */
    static from(response: Response, method: string, path: string): Promise<AgentHttpError>;
}
export interface CancelResult {
    aborted: boolean;
}
export interface OkResult {
    ok: boolean;
}
export interface AgentClientOptions {
    /**
     * The server's origin, e.g. `https://api.example.com`. Defaults to `''` (same origin). The
     * agent's route prefix is {@link AgentClientOptions.path}, not part of this.
     */
    baseUrl?: string;
    /**
     * The agent's route prefix — `AgentModule`'s `path`, with any global prefix in front
     * (`'api/agent'`). Leading/trailing slashes are optional. Defaults to `'agent'`.
     */
    path?: string;
    /** Static headers merged into every request. */
    headers?: Record<string, string>;
    /**
     * Resolved per request — for short-lived bearer tokens, or a CSRF header read from a cookie
     * (`{ 'X-XSRF-TOKEN': readCookie('XSRF-TOKEN') }`), which has to be read at request time because
     * the server may rotate it.
     */
    getHeaders?: () => Record<string, string> | Promise<Record<string, string>>;
    /**
     * Forwarded to fetch so cookie auth works. Same-origin requests send cookies by default; set
     * `'include'` when the API lives on another origin (and have it answer with credentialed CORS).
     */
    credentials?: RequestCredentials;
    /** Injectable for tests / non-browser runtimes. */
    fetch?: typeof fetch;
    /**
     * Called with every error answer (an {@link AgentHttpError}, or a `MediaUploadError` from a
     * `mediaAttachments()` upload) right before it is thrown — the place for app-wide reactions such
     * as "401 → sign in again". The error still reaches the caller. Not called for the `404` a
     * resume answers when nothing is streaming, which is an answer, not a failure.
     */
    onHttpError?: HttpErrorListener;
    /** Attachment uploads. */
    attachments?: {
        /**
         * How `uploadAttachment` uploads. Omitted → `POST <path>/attachments` (multipart). Pass
         * `mediaAttachments()` from `@adonis-agora/agent/react/media` for resumable uploads through
         * @adonis-agora/media, or your own {@link AttachmentUploadStrategy}.
         */
        upload?: AttachmentUploadStrategy;
    };
}
/** `'/api/agent'` from `'api/agent'`, `'/api/agent/'`, …; `''` for an empty path. */
export declare function normalizeAgentPath(path: string | undefined): string;
/**
 * Framework-agnostic REST client for the Adonis agent endpoints — the default {@link AgentBackend}.
 * Used by `useAgentChat`, but standalone-usable (vanilla fetch, no React).
 */
export declare class AgentClient implements AgentBackend {
    private readonly options;
    constructor(options?: AgentClientOptions);
    /** `POST <path>/chat` → the turn's SSE stream. Throws {@link AgentHttpError} on a non-2xx. */
    openChatStream(request: ChatStreamRequest): Promise<ChatStreamResponse>;
    /**
     * `POST <path>/chat` for a message that should wait in the thread's queue — the body carries
     * `mode: 'queue'` (or `'interrupt'`), which the server always answers with `202` JSON.
     */
    enqueueMessage(request: ChatStreamRequest): Promise<QueuedSendResult>;
    /** `GET <path>/threads/:id/queue` — the thread's waiting messages, and whether it drains. */
    getQueue(threadId: string): Promise<ChatQueueState>;
    /** `PATCH <path>/queue/:messageId` — change a waiting message's text/attachments, or move it. */
    updateQueuedMessage(messageId: string, update: QueuedMessageUpdate): Promise<ChatQueueState>;
    /** `DELETE <path>/queue/:messageId`. */
    removeQueuedMessage(messageId: string): Promise<ChatQueueState>;
    /**
     * `POST <path>/queue/:messageId/interrupt` — run a waiting message now, cancelling the running
     * turn for it. `runId` when nothing was running and it started; else `interrupting`.
     */
    interruptQueuedMessage(messageId: string): Promise<ChatQueueState & {
        runId?: string;
        interrupting?: string;
    }>;
    /** `DELETE <path>/threads/:id/queue` — drop every waiting message. */
    clearQueue(threadId: string): Promise<ChatQueueState>;
    /** `POST <path>/threads/:id/queue/resume` — lift a pause; `runId` when the head started. */
    resumeQueue(threadId: string): Promise<ChatQueueState & {
        runId?: string;
    }>;
    /**
     * `GET <path>/chat/:runId/stream[?after=<seq>]` → the run's SSE stream, or `null` when nothing is
     * streaming under that id (404).
     */
    resumeChatStream(request: ResumeStreamRequest): Promise<ChatStreamResponse | null>;
    /**
     * Rate a message (`'up'`/`'down'`, optional comment) or clear its rating (`value: null`). Answers
     * the stored rating.
     */
    setMessageFeedback(messageId: string, input: MessageFeedbackInput): Promise<{
        feedback: MessageFeedback | null;
    }>;
    listThreads(): Promise<ThreadSummary[]>;
    /**
     * The skills this caller can invoke right now, scope-resolved — the same list, built by the same
     * call, that the model is offered, so what a user can type after a `/` and what the agent can
     * reach cannot drift apart. `threadId` reaches the host's own resolver, which may scope a skill to
     * one conversation; omitted, the server reads it as a brand-new thread.
     */
    listSkills(threadId?: string): Promise<SkillCatalogEntry[]>;
    /**
     * The tools this caller can reach through `agent` (the default agent when omitted), each with the
     * server-declared `presentation` a chat narrates it by — the same list the model is offered.
     * Prefer {@link useToolCatalog}, which fetches it once and shares it.
     */
    listTools(agent?: string): Promise<ToolCatalogEntry[]>;
    getThread(id: string): Promise<ThreadDetail>;
    deleteThread(id: string): Promise<void>;
    forkFromMessage(threadId: string, messageId: string): Promise<ThreadSummary>;
    /** General `PATCH <path>/threads/:threadId` — title and/or the thread's pinned default agent. */
    updateThread(id: string, patch: ThreadPatch): Promise<OkResult>;
    /**
     * Uploads a file (image/PDF) for a vision-capable model turn. Multipart, field name `file` —
     * mirrors the backend's `POST <path>/attachments`. The returned {@link MessageAttachment} is
     * what a caller then rides on `sendMessage({ text }, { body: { attachments: [...] } })`.
     */
    uploadAttachment(file: File, options?: UploadAttachmentOptions): Promise<MessageAttachment>;
    private uploadWithProgress;
    promoteThread(id: string): Promise<OkResult>;
    truncateFromMessage(threadId: string, messageId: string): Promise<OkResult>;
    /** `GET <path>/models?agent=` — the models this caller may pick, grouped by provider. */
    listModels(agent?: string): Promise<ModelCatalogView>;
    /** `GET <path>/agents` — the registered agents, the default one flagged. */
    listAgents(): Promise<AgentCatalogEntry[]>;
    /** `GET <path>/config` — attachment limits and upload mode, and which features are on. */
    getConfig(): Promise<AgentClientConfig>;
    /** `GET <path>/quota` — the caller's budget windows and the one blocking sends, if any. */
    getQuota(): Promise<QuotaReport>;
    cancelStream(runId: string): Promise<CancelResult>;
    /**
     * `remember` approves later calls of the same tool in the same thread; `via` names the surface
     * the decision came through (the server records `'web'` when omitted).
     */
    listActionProposals({ threadId }: {
        threadId: string;
    }): Promise<ActionProposal[]>;
    approveActionProposal({ threadId, proposalId, remember, }: {
        threadId: string;
        proposalId: string;
        remember?: boolean;
    }): Promise<ActionProposalMutationResult>;
    rejectActionProposal({ threadId, proposalId, reason, }: {
        threadId: string;
        proposalId: string;
        reason?: string;
    }): Promise<ActionProposalMutationResult>;
    approveToolCall(input: {
        toolCallId: string;
        remember?: boolean;
        via?: string;
    }): Promise<void>;
    rejectToolCall(input: {
        toolCallId: string;
        reason?: string;
        via?: string;
    }): Promise<void>;
    /**
     * Settle a parked question set. `answers` is questionId → chosen option values; a question left
     * out takes the pre-picked default the request carried, resolved server-side against the request
     * the run already holds. Omit the whole object and the user has confirmed every pre-picked
     * answer — which is the point of the surface, so it is a valid submission rather than a blank.
     * `via` names the surface the answer came through (the server records `'web'` when omitted).
     */
    answerToolCall(input: {
        toolCallId: string;
        answers?: Record<string, string[]>;
        via?: string;
    }): Promise<void>;
    /**
     * Decline to answer and let the agent proceed on its own pre-picked values. Lands on the same
     * values a confirmation would, and persists differently on purpose — only one of them is
     * evidence the user chose them.
     */
    skipToolCall(input: {
        toolCallId: string;
        via?: string;
    }): Promise<void>;
    private fetchImpl;
    /** This client's connection, for an {@link AttachmentUploadStrategy}. */
    private connection;
    private baseUrl;
    private agentPath;
    /** Origin + agent path: what every route hangs off. */
    private root;
    private resolveHeaders;
    private credentials;
    private request;
    private requestResponse;
    /** The error for a refused `response`, already reported to `onHttpError`. */
    private failure;
    private handleResponse;
}
//# sourceMappingURL=client.d.ts.map