UNPKG

@adonis-agora/agent

Version:

Governed, durable-backed AI agent (chat + tool-calling + governance) for AdonisJS — part of the Agora ecosystem.

222 lines • 11.5 kB
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