@adonis-agora/agent
Version:
Governed, durable-backed AI agent (chat + tool-calling + governance) for AdonisJS — part of the Agora ecosystem.
80 lines • 4.07 kB
TypeScript
import type { IncomingMessage, ServerResponse } from 'node:http';
import type { HttpContext } from '@adonisjs/core/http';
import { type PoppyAuthenticate } from './auth.js';
import type { PoppyConversations } from './conversations.js';
/**
* One HTTP exchange, framework-free: what the Poppy handler reads and writes. `adonisExchange`
* and `nodeExchange` build one; any other server can too.
*/
export interface PoppyExchange {
method: string;
/** The path, without the query string. */
path: string;
query: Record<string, string | undefined>;
/** The full PUBLIC URL the request was made to (with its query) — what a DPoP proof's `htu` names. */
url: string;
/** Lower-cased header names, repeated values joined. */
headers: Record<string, string | undefined>;
/** The headers as received (lower-cased names) — what the Session Token resolver verifies. */
rawHeaders: Record<string, string | string[] | undefined>;
/** The raw body, refused past `limit` bytes. */
readBody(limit: number): Promise<string>;
json(status: number, body: unknown, headers?: Record<string, string>): void;
/** Start a `200` streamed response. */
openStream(headers: Record<string, string>): PoppyStreamWriter;
}
export interface PoppyStreamWriter {
write(chunk: string): void;
end(): void;
/** Aborts when the client goes away. */
signal: AbortSignal;
}
export interface PoppyHandlerOptions {
/** The endpoint path, no slashes (`'poppy/conversations'`). */
path: string;
conversations: PoppyConversations;
/** Verifies Session Tokens. Omitted → the global slot, read per request. */
authenticate?: PoppyAuthenticate;
/** Largest accepted request body, in bytes. Default 1 MiB. */
maxBodyBytes?: number;
/** Cap on a read's `wait`, in seconds. Default 30. */
maxWaitSeconds?: number;
/** Close a stream after this long; the Personal Agent reconnects (§7.6). Default 5 minutes. */
streamMaxMs?: number;
/** A comment line this often keeps a stream's proxies from timing it out. Default 15 s. */
keepAliveMs?: number;
onError?: (error: unknown) => void;
}
/**
* The Poppy conversation endpoint (§7) — `POST {endpoint}`, `POST {endpoint}/{id}/messages`,
* `GET {endpoint}/{id}/events` (JSON, long-poll with `wait`, or SSE), `POST …/handoff` and
* `POST …/close`. Returns a handler that answers everything under `/{path}` and reports `false`
* for anything else, so it can sit in front of the router.
*
* Every request is authenticated BEFORE its body is read, by the resolver of
* `Symbol.for('@adonis-agora/poppy:authenticate')` (`@adonis-agora/authkit-server`) or the one
* given. Without either the endpoint answers `501`.
*
* @experimental Tracks Personal Agent Protocol Draft 0.1 (https://personalagentprotocol.org/docs/spec),
* a spec still in development: this API WILL change as the spec evolves — possibly in breaking
* ways, outside semver majors while it is a draft.
*/
export declare function createPoppyHandler(options: PoppyHandlerOptions): (exchange: PoppyExchange) => Promise<boolean>;
/** A {@link PoppyExchange} over a plain Node request — any framework, or a bare `http` server. */
export declare function nodeExchange(req: IncomingMessage, res: ServerResponse, options: {
origin: string;
}): PoppyExchange;
/**
* The public origin of a request: `baseUrl` when configured; else the request's protocol and host
* (Adonis honours `X-Forwarded-*` from trusted proxies) — upgraded to `https` when the Poppy issuer
* is, as a TLS-terminating proxy would otherwise make every DPoP `htu` mismatch.
*/
export declare function publicOrigin(request: {
protocol: string;
host: string;
}, baseUrl: string | undefined, issuer?: string | undefined): string;
/** A {@link PoppyExchange} over an Adonis request — what the Poppy server middleware builds. */
export declare function adonisExchange(ctx: HttpContext, options: {
baseUrl?: string;
}): PoppyExchange;
//# sourceMappingURL=handler.d.ts.map