/** * The web SSE invoke transport, and the guest-identity wire pieces it shares * with the read-plane adapters. * * Its own module (rather than living in `./web-adapters.ts`) for the same * reason `AgentResponseError` lives in `./errors.ts`, one level down: the * web-adapter bundle takes VALUE imports of `@guuey/mcp-apps-host` (the * ui-resource reader / action-relay assemblies), so a consumer that only * wants the transport — a custom chat surface with its own card layer, or * none — would drag the whole host-role graph into its build, and any * version skew between the two packages becomes that consumer's build * failure (guuey#186 G2). This module's import closure is * `types`/`errors`/`saturation-retry` only; `./web-adapters.ts` imports * from HERE, never the reverse, and `@guuey/agent-client/transport` * publishes exactly this graph. */ import type { InvokeRequest, InvokeTransport } from "./types.js"; import { type ColdStartRetryOptions, type SaturationRetryOptions } from "./saturation-retry.js"; /** * Header carrying a caller-owned anonymous guest secret. A LOCAL MIRROR of the * two server-side constants — the pod's `GUEST_HEADER_NAME` * (`backend/services/nocode-runtime/src/identity.ts`) and the read plane's * `GUEST_HEADER` (`backend/amplify/functions/publicApi/identity.ts`) — because * this is a published npm package and cannot take a `@guuey-private` dep (same * arrangement as `@guuey/host`'s mirrored fs-contract constants). The string is * a wire contract: both planes already advertise it in * `Access-Control-Allow-Headers`, so changing it is a breaking protocol change, * not a rename. */ export declare const GUEST_HEADER = "x-guuey-guest"; /** * Narrow a caller-supplied guest secret to a value that is safe to put on the * wire, or `null`. The single gate for the header: every write of * {@link GUEST_HEADER} in this package goes through it, so a malformed secret * can never reach a request. The value is never logged (here or anywhere on * this path) — it IS the anonymous identity, so a leak is an impersonation. */ export declare function sendableGuestSecret(secret: string | null | undefined): string | null; /** Options for {@link fetchStreamTransport}. */ export interface FetchStreamTransportOptions extends SaturationRetryOptions { /** * Bounded retry on cold-start 503s — the envelope-less refusal an embed * eats for ~30–60s after the agent redeploys (guuey#186 Gap 3). ON by * default (small budget: 3 attempts, 2s/4s/8s) for parity with guuey's * first-party embeds; pass `false` to disable, or options to re-budget. * See {@link withColdStartRetry} for exactly what matches (and what * deliberately stays with the saturation policy instead). */ coldStartRetry?: ColdStartRetryOptions | false; /** * Injectable bearer provider (guuey#186 Gap 4) — identity is a transport * concern (see {@link InvokeTransport}: "owns headers + identity * entirely"), and a harness or non-React host holds credentials in its own * lifecycle, not in a closure minted once at page load. Resolved PER * ATTEMPT, before each request — a retry after a backoff wait re-reads it, * so a token that expired during the wait is refreshed rather than * replayed. When present it takes precedence over the positional * `accessToken`; resolving `null` falls through to the guest secret / * cookie chain exactly as a null `accessToken` does (and carries the same * silent-anonymous-downgrade hazard the `createWebAdapters` docs warn * about). A throw propagates and fails the invoke — deliberately not * caught, for the same reason as `getGuestSecret` there. */ getBearer?: () => string | null | Promise; } /** * The web SSE transport: {@link streamInvokeOnce} under the shared * {@link withSaturationRetry} wrapper, itself under {@link withColdStartRetry}. * Every consumer of this transport (Studio, the widget, anything built on * `createWebAdapters`) therefore inherits the single `POD_SATURATED` retry AND * the bounded cold-start 503 retry, the same pair Portal's React-Native * transport wears — see the wrappers' docblocks for which refusals retry, * which deliberately do not, and why both retries are invisible to the hook. * Both wrappers guard on "nothing yielded yet": once a chunk has streamed, * NOTHING re-POSTs. */ export declare function fetchStreamTransport(req: InvokeRequest, accessToken?: string | null, guestSecret?: string | null, options?: FetchStreamTransportOptions): AsyncIterable; /** * Wrap a transport so every yielded chunk ALSO pings `onChunk` — the * byte-level liveness signal `useAgentInvoke`'s stall watchdog runs on * (guuey#192). Purely observational: chunks pass through unchanged, errors * and completion propagate untouched, and the wrapper adds no timers of its * own — the OBSERVER owns the clock, this module only reports activity. The * first ping doubles as the "first byte seen" arming signal, which is why * the watchdog never fires during a silent cold start: no bytes, no ping, * no armed timer (that phase belongs to {@link withColdStartRetry} and the * user's own abort). */ export declare function withActivityObserver(transport: InvokeTransport, onChunk: () => void): InvokeTransport; //# sourceMappingURL=transport.d.ts.map