/** * Framework route the background function actually runs — sibling to * `AGENT_TEAM_PROCESS_RUN_PATH`. Reached *through* the Netlify background * function, so it inherits the 15-min budget. */ export declare const AGENT_CHAT_PROCESS_RUN_PATH = "/_agent-native/agent-chat/_process-run"; /** * Name of the standalone Netlify background function the build emits (see * `emitSingleTemplateNetlifyBackgroundFunction` in deploy/build.ts). Shared so * the emit and the dispatch-path helper below can never drift on the name. * * MUST end in `-background` — both because that is the conventional Netlify * async-function suffix and because `isInBackgroundFunctionRuntime()` reads the * `AWS_LAMBDA_FUNCTION_NAME` `-background` suffix as a secondary runtime signal. */ export declare const AGENT_BACKGROUND_FUNCTION_NAME = "server-agent-background"; /** * Default function URL of the background function on Netlify. Every Netlify * function is reachable at `/.netlify/functions/` BY DEFAULT; that default * url is removed ONLY if the function declares a custom `config.path`. The * emitted background function declares NO custom `config.path` (it sets * `background: true` and nothing else routing-related), so it KEEPS this default * url — and the Nitro `server` function already excludes `/.netlify/*` from its * `/*` catch-all, so this namespace is never shadowed. The foreground therefore * dispatches HERE on hosted Netlify (see `resolveAgentChatProcessRunDispatchPath`). */ export declare const AGENT_BACKGROUND_FUNCTION_URL_PATH = "/.netlify/functions/server-agent-background"; /** * Marker carried in a Netlify background-function body when the shared * long-running worker should route to a processor other than agent chat. * The emitted wrapper defaults to the normal agent-chat `_process-run` route; * A2A uses this marker to reuse the same 15-minute function for async tasks. */ export declare const AGENT_BACKGROUND_PROCESSOR_FIELD = "__agentNativeProcessor"; export declare const AGENT_BACKGROUND_PROCESSOR_A2A = "a2a"; export declare const AGENT_BACKGROUND_PROCESSOR_INTEGRATION = "integration"; export declare const AGENT_BACKGROUND_PROCESSOR_ROUTE = "route"; export declare const AGENT_BACKGROUND_PROCESSOR_ROUTE_FIELD = "__agentNativeProcessorRoute"; /** * Resolve the path the foreground POST should self-dispatch the chat background * worker to. * * GROUNDED IN THE REAL NETLIFY BUILD OUTPUT + THE NETLIFY DOCS DEFAULT-URL RULE: * the background function is emitted INTO the scanned dir * (`.netlify/functions-internal/server-agent-background`, or per-app * `-agent-background` for workspaces) with `export const config = { * background: true, ... }` and NO custom `config.path`. Because it has no custom * path, Netlify keeps its DEFAULT function url `/.netlify/functions/`, and * `background: true` makes any invocation of that url ASYNC (immediate 202, * 15-min budget). The Nitro `server` function already excludes `/.netlify/*` * from its `/*` catch-all, so the default-url namespace is NEVER shadowed by the * synchronous function. * * Therefore on hosted Netlify the foreground dispatches to the function's DEFAULT * url (`/.netlify/functions/`); the function entry then rewrites the * incoming pathname to `AGENT_CHAT_PROCESS_RUN_PATH` (base-path-prefixed for * workspaces) before delegating to the Nitro router, so the `_process-run` * plugin runs with the async 15-min budget. Everywhere else (local dev, `netlify * dev`, non-Netlify hosts where no second function exists) there is no second * function, so the foreground dispatches to the framework route * `AGENT_CHAT_PROCESS_RUN_PATH` and the same in-process catch-all handles it * inline. The HMAC token (signed over the runId) is unchanged either way. * * NOTE: this is the DOC-CORRECT approach. An earlier attempt gave the function a * custom `config.path` + a catch-all `excludedPath` patch; the custom path was * NOT honored as a route in prod (probe → 404). Using the default function url * (no custom path) is what Netlify documents and is simpler — there is nothing * to shadow because `/.netlify/*` is already excluded from the `server` catch-all. */ export declare function resolveAgentChatProcessRunDispatchPath(): string; export declare function resolveDurableBackgroundDispatchPath(fallbackPath: string): string; export declare function dispatchPathTargetsNetlifyBackgroundFunction(dispatchPath: string): boolean; /** * Env flag for durable background runs. DEFAULT-OFF (opt-in): unset means * disabled; an app opts IN with an explicit truthy value (`true`/`1`/`yes`/`on`). */ export declare const AGENT_CHAT_DURABLE_BACKGROUND_ENV = "AGENT_CHAT_DURABLE_BACKGROUND"; /** * Body field the foreground handler injects when self-dispatching to the * background processor. Its presence is how the re-entered handler knows it is * the background worker (run inline with the background soft-timeout; do NOT * re-claim the slot or re-dispatch). Untrusted on its own — the route also * verifies the HMAC token before invoking the handler. */ export declare const AGENT_CHAT_BACKGROUND_RUN_FIELD = "__backgroundRun"; /** * Mirror of run-manager's private `isHostedRuntime`. Kept in sync deliberately: * the durable-background gate must agree with the soft-timeout regime about * what "hosted" means. */ export declare function isHostedRuntimeForDurableBackground(): boolean; /** * True when THIS process is actually executing inside a Netlify *background* * function (the long, 15-min-budget async function whose deployed name ends in * `-background`). Netlify runs functions on AWS Lambda and sets * `AWS_LAMBDA_FUNCTION_NAME` to the function's name, so a `-background` suffix is * the runtime proof that the ~60s synchronous wall does NOT apply here. * * This is the SAFETY GUARD for the soft-timeout regime. The `_process-run` * self-dispatch worker (`isBackgroundWorker`) is NOT enough on its own: if the * `-background` function was never emitted (deploy gate off, or Netlify routed * the path to the synchronous function), the self-POST lands on the regular * ~60s `server` function. A worker there MUST use the 40s soft-timeout and * checkpoint before the 60s wall — using the ~13min budget would overshoot the * hard wall and get killed at 60s, then re-dispatch/resume in a wasteful loop. * So the 13-min budget is taken ONLY when this returns true. * * The PRIMARY signal is a `globalThis` marker the emitted background function's * entry sets at cold start — the deployed Lambda name is not guaranteed to end * in `-background` on Netlify, so the entry marks its own runtime. A `globalThis` * flag (not `process.env`) keeps the no-env-mutation guard satisfied and carries * no cross-request state (set once per isolate). The `AWS_LAMBDA_FUNCTION_NAME` * suffix and the explicit `AGENT_CHAT_FORCE_BACKGROUND_RUNTIME` env (truthy) are * additional signals — the latter an operator escape hatch. Off by default. */ export declare function isInBackgroundFunctionRuntime(): boolean; export declare function backgroundRunMarkerExpectsBackgroundRuntime(marker: unknown): boolean; export declare function shouldUseBackgroundFunctionTimeoutForWorker(_marker: unknown): boolean; export declare function backgroundRuntimeDiagnosticDetail(marker: unknown): string; export declare const BACKGROUND_FUNCTION_UNREACHABLE_NOTICE_KEY = "__AGENT_NATIVE_BACKGROUND_UNREACHABLE_NOTICE__"; /** * Env flag parse, shared by the runtime gate and the deploy-time emit gates so * they can never drift apart (they did: the workspace deploy copy defaulted ON * while this one defaulted OFF). */ export declare function isDurableBackgroundFlagEnabled(): boolean; export declare function isDurableBackgroundFlagExplicitlyDisabled(): boolean; /** * The single gate. True when the env flag is explicitly enabled, or a workspace * app opted in and has a per-app background-function target, AND the runtime is * hosted AND A2A_SECRET is configured. False otherwise — and false means the * current synchronous behavior is used unchanged. Single-template Netlify app * opt-ins deliberately require the env flag too because that flag controls * whether the `server-agent-background` function exists in the deploy output. */ export declare function isAgentChatDurableBackgroundEnabled(options?: { appOptIn?: boolean; }): boolean; /** * Env flag for the FOREGROUND server-driven self-chain. DEFAULT-OFF: a hosted * app must explicitly opt in with a truthy value (`true`/`1`/`yes`/`on`). A * regular Netlify function has a fixed 60-second wall, and a self-dispatched * successor can otherwise be killed before it persists its next continuation. * Keep this separate from `AGENT_CHAT_DURABLE_BACKGROUND` so the experimental * regular-function chain can be enabled independently after its deployment is * proven safe. */ export declare const AGENT_CHAT_FOREGROUND_SELF_CHAIN_ENV = "AGENT_CHAT_FOREGROUND_SELF_CHAIN"; /** * Gate for the foreground self-chain: a normal (non-durable-background) * agent-chat turn that hits its soft-timeout chunk boundary continues via a * server-side self-dispatch on the REGULAR function (not a Netlify * `-background` function) instead of depending on the client to re-POST * `auto_continue`. Composes exactly like `isAgentChatDurableBackgroundEnabled`: * true only when the env flag is explicitly truthy, the runtime is hosted, and * `A2A_SECRET` is configured (the HMAC handoff authenticates the dispatch). * False means the existing client-driven `auto_continue` re-POST path is used. * * Deliberately independent of `isAgentChatDurableBackgroundEnabled`: an app can * use this narrower capability without opting into the full 15-min * background-function worker path, and the two gates never need to agree. * When BOTH would be true for a given run, the durable-background dispatch * decision in `production-agent.ts` is evaluated first and takes precedence — * a run already dispatched to the durable background worker chains via the * existing `isBackgroundWorker` path, not this one. */ export declare function isAgentChatForegroundSelfChainEnabled(): boolean; /** Decision returned by `prepareProcessRunRequest`. */ export type ProcessRunPreparation = { ok: true; /** The pre-claimed run id the background worker must reuse. */ runId: string; /** Body to stash for the re-entered handler (marker guaranteed present). */ body: Record; } | { ok: false; /** HTTP status the route should return. */ status: number; /** Error payload. */ error: string; /** * The run id parsed from the body, when present. Carried even on failure * so the route can RECORD the auth/validation failure ONTO the run * (diag_stage) before returning the error status — otherwise a 401/503 in * the unreadable Netlify background function would leave the run to time * out with no clue why. Null when no run id could be parsed. */ runId: string | null; }; /** * Parse the run id from a `_process-run` request body without authenticating. * Mirrors the precedence in `prepareProcessRunRequest` (marker.runId, then * top-level taskId). Returns null when neither is a usable string. Used so the * route can attach a diagnostic to the run even on an auth/validation failure. */ export declare function extractProcessRunId(body: unknown): string | null; /** * Pure, transport-agnostic core of the `_process-run` route: validate the body, * authenticate the HMAC self-dispatch, and produce the body the re-entered * agent-chat handler should run as the background worker. * * Auth policy mirrors the agent-teams processor exactly: * - `A2A_SECRET` set → require a valid `verifyInternalToken(runId, token)`. * - no secret → require `isTrustedLocalRuntime({ loopback })` (see * auth-policy.ts): refuse (503) unless `A2A_ALLOW_UNSIGNED_INTERNAL=1` is * set. This function has no h3 `event` of its own, so callers that CAN * see the inbound socket peer (the route handler, which has the event) * should compute `loopback` from it and pass it through; callers that * can't determine the peer address should omit it (defaults to `false` * — never trust unsigned dispatch without an explicit opt-in). * * Extracted from the route handler so the auth + marker-prep decision is unit * testable without booting the whole Nitro plugin. The route only adds body * reading and the final handler invocation around this. */ export declare function prepareProcessRunRequest(body: unknown, authHeader: string | undefined, loopback?: boolean): ProcessRunPreparation; //# sourceMappingURL=durable-background.d.ts.map