@sema-agent/core
Version:
Stateless, task-oriented AI agent core
47 lines (46 loc) • 3.52 kB
TypeScript
/**
* The HTTP credentials a protocol declaration carries — its static `headers` and the per-task principal
* header (`principalHeader`) — and the one rule they obey, for MCP and A2A alike: they travel only to the
* endpoints the declaration names, and every header name has exactly one owner, compared the way HTTP
* compares names (case-insensitively). The principal header's owner is the engine: it sends the task's
* principal under that name, or nothing under it when the task has none. A static header the credential vocabulary
* reads as a credential is one the engine holds from the moment it resolves it: no child spawned on this host inherits
* a variable whose value equals it (`holdOwnCredentialValues`, src/core/secret-env.ts).
*
* A declaration that breaks the rule is that peer's defect: the resolver throws inside the peer's own dial,
* so the peer is skipped with a coded warning and its siblings still mount. The MCP transport binds its
* endpoint by dialing only the declared URL with redirects not followed (`declaredEndpointFetch`); the A2A
* peer, whose card may name another endpoint, is bound by {@link assertEndpointBound} and by
* {@link redirectPolicy}.
*/
import type { ProtocolId } from "./protocol-table.js";
/** The per-peer HTTP auth declaration every protocol spec carries in the same two fields. */
export interface ProtocolHttpAuth {
headers?: Record<string, string>;
principalHeader?: string;
}
/** The first header name (any case) the declaration gives two owners, with both spellings. */
export declare function headerOwnershipCollision(t: ProtocolHttpAuth): {
readonly first: string;
readonly second: string;
} | undefined;
/**
* Resolve the HTTP request headers for one remote peer of `protocol`: the static headers, plus the
* principal under `principalHeader` when both are present. Throws `config.protocol_header_collision` when
* one header name has two owners (two static spellings, or a static entry under the principal header's
* name — which would otherwise be sent merged beside the principal, or alone when the task has none), and
* on a principal carrying CR/LF. Callers invoke it INSIDE their per-peer boundary.
*/
export declare function resolveProtocolHttpHeaders(protocol: ProtocolId, t: ProtocolHttpAuth, principal?: string): Readonly<Record<string, string>> | undefined;
/** The engine's default request headers under the declared ones: a declared name, in any case, owns that header
* (the default of the same name is not sent beside it). */
export declare function underDeclaredHeaders(defaults: Readonly<Record<string, string>>, declared: Record<string, string> | undefined): Record<string, string>;
/** Whether a resolved header set carries anything the declaration bound to its endpoints. */
export declare function carriesDeclaredHeaders(headers: Record<string, string> | undefined): boolean;
/** A request carrying declared headers does not follow a redirect (the next hop is not a declared endpoint). */
export declare function redirectPolicy(headers: Record<string, string> | undefined): "manual" | "follow";
/**
* Refuse an endpoint a peer advertised (an A2A card's interface URL) when it lies outside every origin the
* declaration names and the peer's requests carry declared headers: `config.protocol_endpoint_unbound`.
*/
export declare function assertEndpointBound(protocol: ProtocolId, peer: string, endpoint: string, declared: readonly string[], headers: Record<string, string> | undefined): void;