/** * a2a/server.ts — AIBroker as an A2A server. * * `handleA2A(req, res, ctx)` answers exactly two routes and refuses * everything else identically to an unknown route (mirrors * daemon/inbound.ts's rule: an unknown route and a wrong secret both 404, * so probing cannot tell them apart): * * GET /.well-known/agent-card.json — public discovery, no auth. The * card lists only sessions the operator explicitly exposed * (a2a/exposure.ts) — never a full session roster. * POST /a2a — JSON-RPC 2.0. `Authorization: * Bearer `, constant-time compared. Missing, * wrong, or absent-because-unconfigured all answer the SAME 404 as * an unrecognized path — a prober cannot tell "wrong token" from * "no such endpoint" from "no such path" by the response alone. * * Once authenticated, JSON-RPC errors follow the spec's own codes * (schema/types.ts JSONRPC_ERRORS) rather than the uniform pre-auth * refusal — an authenticated caller asking for an unknown method or a * missing task is not the enumeration risk the pre-auth boundary guards * against. * * `message/send` frames the arriving text exactly as daemon/inbound.ts * frames anything from outside: DATA, not an instruction, with the task id * a session replies against. `tasks/send` (pre-0.2 A2A naming) is accepted * as an alias for `message/send`. */ import type { IncomingMessage, ServerResponse } from "node:http"; import { type A2ATask } from "./tasks.js"; import { type AgentCard } from "./schema/types.js"; export declare const A2A_PATH = "/a2a"; export interface A2AContext { agentName?: string; version: string; /** Full external URL of the JSON-RPC endpoint, e.g. "https://host/a2a". */ publicUrl: () => string; /** AIBROKER_A2A_TOKEN. Undefined means "not configured" — every POST refused. */ token: string | undefined; /** Deliver framed text to a session's mailbox, the same two-hop pattern inbound.ts uses. */ deliver: (session: string, text: string) => Promise<{ delivered: boolean; detail?: string; }>; taskFile?: string; exposureFile?: string; } /** * Is A2A actually turned on, independent of whether the shared HTTP * listener happens to be up for some other reason (Todoist)? * * Any one signal is enough, because each means "the operator did something * deliberate": a bearer token was minted, a public URL was pointed at this * host, or a session was actually exposed as a skill. Compiling this code in * is not one of those signals — an idle build with nothing configured must * read as off, the same way an idle Todoist webhook does. */ export declare function a2aConfigured(exposureFile?: string): boolean; export declare function buildAgentCard(ctx: A2AContext): AgentCard; /** * Apply a session's reply to one of its open A2A tasks. Owned here (not in * core-handlers.ts, which this task must not edit) so the IPC wiring in * docs/a2a-wiring can stay a thin call into this function. */ export declare function applyA2AReply(taskId: string, text: string, file?: string): { task: A2ATask; ag2?: { ok: boolean; errors: string[]; }; } | undefined; export declare function handleA2A(req: IncomingMessage, res: ServerResponse, ctx: A2AContext): Promise; //# sourceMappingURL=server.d.ts.map