UNPKG

@adonis-agora/agent

Version:

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

179 lines • 7.94 kB
import type { CompanyClient, McpConnection, StoredKey } from '../poppy-client/index.js'; import { AgentIdentity, OAuthError, PoppyError, ResourceAuthError } from '../poppy-client/index.js'; import type { Actor } from '../types.js'; import { type PoppyCompanyPolicy, type PoppyConnectionsConfig, type PoppyConnectionsTexts } from './config.js'; import type { PoppyConnectionRecord, PoppyConnectionStore, PoppyPendingConnect } from './store.js'; /** A Company outside the allow-list. The model is told plainly, and nothing is fetched. */ export declare class PoppyCompanyNotAllowedError extends Error { readonly domain: string; constructor(domain: string); } /** One connection as the app and the model see it — never a token. */ export interface PoppyConnectionView { domain: string; organization: string; status: PoppyConnectionRecord['status']; scope: string; connectedSince: number | null; } /** What a connect page shows. */ export type PoppyConnectPageData = { kind: 'expired'; } | { kind: 'connected'; organization: string; } | { kind: 'open'; id: string; organization: string; direct: boolean; device: boolean; mediated: { name: string; label: string; secret: boolean; }[] | null; }; /** What `ask`/`request` bring back from the Company's agent. */ export interface PoppyCompanyReply { conversationId: string; replies: { text: string; data?: Record<string, unknown>; }[]; /** The Company said the token lacks something (§7.11). */ authorization?: { error: string; scope?: string; }; status: string; } export interface PoppyConnectionsOptions { config: PoppyConnectionsConfig; store: PoppyConnectionStore; secret: string; production: boolean; /** Called once a connect completes — the provider decides the parked `connect` call. */ onConnected?: (pending: PoppyPendingConnect) => Promise<void>; log?: (line: string) => void; } /** * This app's agent acting on other Poppy Companies for its users: the agent identity, the * connections (sealed at rest), the connect flows and the calls the tools make. * * @experimental Tracks Personal Agent Protocol Draft 0.1 — will change as the spec evolves. */ export declare class PoppyConnections { #private; readonly texts: PoppyConnectionsTexts; readonly path: string; readonly baseUrl: string; readonly insecureDev: boolean; constructor(options: PoppyConnectionsOptions); /** How long a connect link works, in ms (`connectTtlSeconds`, default 15 minutes). */ get connectTtlMs(): number; /** The agent's display name (its `client_name`). */ get identityName(): string; /** The app's agent identity (`client_id` = `{baseUrl}/{path}/agent.json`). */ identity(): Promise<AgentIdentity>; ownerOf(actor: Actor): string; /** The policy for `domain`, or `null` when it is not allow-listed (default: nothing is). */ policy(domain: string): PoppyCompanyPolicy | null; /** The allow-listed Companies (when the allow-list is a list or a map). */ allowedCompanies(): { domain: string; label?: string; }[]; /** * The allow-listed domain the model meant by `company`. A model often names a company rather than * its domain ("MeuProntoo", "meuprontoo.com" for `localhost:3841`): when `company` is not itself * allowed, it resolves to the ONE allowed company whose label, or the organization of the * owner's connection to it, it names. Ambiguous or unknown → `company` as given (then refused). */ resolveCompany(owner: string, company: string): Promise<string>; /** * The organization an allow-listed company names itself in its `poppy.json` (cached ten * minutes), or `undefined` when it cannot be reached — no owner, no sign-in needed. */ organizationOf(domain: string): Promise<string | undefined>; /** Run `fn` with this owner's client at `domain`, serialized per owner. */ withCompany<T>(owner: string, domain: string, fn: (client: CompanyClient, policy: PoppyCompanyPolicy) => Promise<T>): Promise<T>; list(owner: string): Promise<PoppyConnectionView[]>; /** The connection at `domain`, without contacting it. */ connection(owner: string, domain: string): Promise<PoppyConnectionView | null>; /** Sign out at the Company (revokes the Account Token, §4.9) and mark the connection revoked. */ disconnect(owner: string, domain: string): Promise<boolean>; /** * Start a connect: the link the person opens (web or WhatsApp — it is a URL), bound to the parked * `connect` call so completing it resumes the conversation. `id` makes a replayed call land on the * same link. */ startConnect(input: { actor: Actor; domain: string; scope?: string; threadId?: string; runId?: string; toolCallId?: string; id?: string; }): Promise<{ id: string; url: string; organization: string; scope: string; }>; /** The connect started by one tool call (`runId`, `toolCallId`), if any. */ pendingFor(runId: string, toolCallId: string): Promise<PoppyPendingConnect | null>; /** * The connect id of one tool call (`runId:toolCallId`): a replayed call reaches the same link. * Keyed with the app secret — the link is a bearer capability, so it must not be derivable. */ connectIdFor(key: string): string; connectUrl(id: string): string; page(id: string): Promise<PoppyConnectPageData>; /** Direct Sign-In (§4.5): the authorization URL to send the browser to. */ directUrl(id: string): Promise<string | null>; /** The Direct Sign-In redirect back to `redirect_uri`. */ directCallback(params: URLSearchParams): Promise<{ ok: boolean; organization: string | null; }>; /** * Mediated Sign-In (§4.7) from this app's own page: the credentials go from the person's browser * to this server and straight to the Company — never stored, logged, or shown to the model. */ mediated(id: string, credentials: Record<string, string>): Promise<{ status: 'connected' | 'code_required' | 'failed' | 'expired'; sentTo?: string; }>; mediatedCode(id: string, code: string): Promise<{ status: 'connected' | 'code_required' | 'failed' | 'expired'; sentTo?: string; }>; /** Device Sign-In (§4.6): the code and the Company page where the person approves it. */ deviceStart(id: string): Promise<{ userCode: string; verificationUri: string; } | null>; /** The device code already started for this connect, if any. */ deviceInfo(id: string): Promise<{ userCode: string; verificationUri: string; } | null>; /** One device-code exchange, when the person says they approved. */ deviceCheck(id: string): Promise<'connected' | 'pending' | 'failed' | 'expired'>; /** The Company's MCP server, with a Bearer token for it (§6). Closed by the caller. */ mcp(owner: string, domain: string): Promise<McpConnection>; /** * One exchange with the Company's agent (§7): `act: false` narrows the token to the read scopes * (`policy.readScopes`, default `poppy:read`), so a question can never make the Company act; * `act: true` uses the whole grant — the tools gate that behind the person's confirmation. */ ask(owner: string, domain: string, text: string, options: { act: boolean; }): Promise<PoppyCompanyReply>; } /** Private EC JWKs (or poppy-client `StoredKey`s, or a JSON string of either) → `StoredKey[]`. */ export declare function normalizeKeys(input: PoppyConnectionsConfig['identity']['keys']): Promise<StoredKey[]>; export { OAuthError, PoppyError, ResourceAuthError }; //# sourceMappingURL=service.d.ts.map