import type { H3Event } from "h3"; export declare const BUILDER_CALLBACK_PATH = "/_agent-native/builder/callback"; export declare const BUILDER_RELAY_PATH = "/_agent-native/builder/relay"; export declare const BUILDER_RELAY_STATE_PARAM = "_an_relay"; export declare const BUILDER_RELAY_SECRET_ENV = "AGENT_NATIVE_BUILDER_RELAY_SECRET"; export declare const BUILDER_RELAY_TARGET_ORIGINS_ENV = "AGENT_NATIVE_BUILDER_RELAY_TARGET_ORIGINS"; export declare const BUILDER_RELAY_TARGET_DOMAIN_SUFFIXES_ENV = "AGENT_NATIVE_BUILDER_RELAY_TARGET_DOMAIN_SUFFIXES"; export declare const BUILDER_RELAY_TIMESTAMP_HEADER = "x-agent-native-relay-timestamp"; export declare const BUILDER_RELAY_FLOW_HEADER = "x-agent-native-relay-flow"; export declare const BUILDER_RELAY_SIGNATURE_HEADER = "x-agent-native-relay-signature"; declare const BUILDER_RELAY_PURPOSE = "builder-preview-callback-relay"; export interface BuilderPreviewRelayState { v: 1; purpose: typeof BUILDER_RELAY_PURPOSE; flowId: string; ownerEmail: string; targetOrigin: string; basePath: string; iat: number; exp: number; } export interface BuilderRelayCredentials { privateKey: string; publicKey: string; userId: string | null; orgName: string | null; orgKind: string | null; subscription: string | null; subscriptionLevel: string | null; subscriptionName: string | null; isEnterprise: boolean | null; isFreeAccount: boolean | null; } export interface BuilderRelayRequestBody { relayState: string; credentials: BuilderRelayCredentials; } export declare function isSafeBuilderRelayTargetOrigin(value: string): boolean; export declare function isTrustedBuilderRelayTargetOrigin(value: string): boolean; /** * Netlify's deploy-preview alias is convenient for people but mutable, so it * must never be the signed relay destination. The deploy builder embeds * Netlify's DEPLOY_ID into the Nitro server bundle, while SITE_NAME remains * available to Functions at runtime. Use that pair only when it * identifies the same site as the visible preview alias; otherwise preserve * the visible origin so callback validation fails closed. */ export declare function resolveBuilderPreviewRelayTargetOrigin(previewOrigin: string): string; export declare function signBuilderPreviewRelayState(input: { ownerEmail: string; targetOrigin: string; basePath?: string; flowId?: string; now?: number; }): { state: string; payload: BuilderPreviewRelayState; }; export declare function verifyBuilderPreviewRelayState(state: string | null | undefined, options?: { now?: number; }): BuilderPreviewRelayState | null; /** * Corporate callback trust check. Preview-side state verification and relay * receipt deliberately do not require this callback-only allowlist. */ export declare function verifyBuilderPreviewRelayStateForCallback(state: string | null | undefined, options?: { now?: number; }): BuilderPreviewRelayState | null; export declare function getBuilderPreviewRelayUrl(payload: BuilderPreviewRelayState): string; export declare function createBuilderRelayRequest(relayState: string, credentials: BuilderRelayCredentials, options?: { now?: number; }): { body: string; headers: Record; url: string; }; export declare function verifyBuilderRelayRequest(input: { body: string; timestamp: string | null | undefined; flowId: string | null | undefined; signature: string | null | undefined; requestOrigin: string; requestBasePath: string; now?: number; }): { payload: BuilderPreviewRelayState; body: BuilderRelayRequestBody; } | null; /** * Query-param name carrying the signed CSRF state on the connect→callback * round-trip. Prefixed with `_an_` to avoid collisions if Builder ever * adds standard OAuth `state` support to cli-auth. Builder preserves * the path/query of `redirect_url` verbatim when redirecting back, so * we embed `_an_state=…` inside the redirect_url query string at * connect time and read it back on the callback. */ export declare const BUILDER_STATE_PARAM = "_an_state"; export declare const BUILDER_CONNECT_PARAM = "_an_connect"; export declare const BUILDER_CONNECT_OWNER_COOKIE = "an_builder_connect_owner"; export declare const BUILDER_SIGNUP_SOURCE_PARAM = "signupSource"; export declare const BUILDER_AGENT_NATIVE_FLOW_PARAM = "agentNativeFlow"; export declare const BUILDER_AGENT_NATIVE_CONNECT_SOURCE_PARAM = "agentNativeConnectSource"; export declare const BUILDER_AGENT_NATIVE_APP_PARAM = "agentNativeApp"; export declare const BUILDER_AGENT_NATIVE_TEMPLATE_PARAM = "agentNativeTemplate"; export interface BuilderConnectTrackingParams { signupSource?: string; agentNativeFlow?: string; agentNativeConnectSource?: string; agentNativeApp?: string; agentNativeTemplate?: string; } export declare function getBuilderConnectTrackingParams(params: URLSearchParams): BuilderConnectTrackingParams; export declare function builderConnectTrackingProperties(tracking: BuilderConnectTrackingParams): Record; export interface BuilderBrowserStatus { configured: boolean; builderEnabled: boolean; branchProjectIdConfigured: boolean; branchProjectId?: string; /** * True when `BUILDER_PRIVATE_KEY` is set at the deployment level. This is a * fallback credential; signed-in users can still connect their own Builder * account, which takes precedence for their request. */ envManaged: boolean; credentialSource?: "user" | "org" | "workspace" | "env"; /** * The currently effective Builder credential was rejected by Builder's API. * This is durable status about the credential pair, not a failure of an * in-progress cli-auth callback. */ authError?: { message: string; at: number; }; connectError?: { message: string; at: number; }; appHost: string; apiHost: string; /** * Ready-to-open Builder CLI auth URL for this request owner, when the * callback can return to the same deployment that minted the state. Preview * deployments that must callback through a gateway omit this and use * connectUrl so the server can write a pending-connect row first. */ cliAuthUrl?: string; connectUrl: string; publicKeyConfigured: boolean; privateKeyConfigured: boolean; userId?: string; orgName?: string; /** * The Builder space(s) the effective credential can reach, with their real * display names (derived from the Admin GraphQL API). A `bpk-` key is * space-scoped, so today this is one entry; the list shape lets the Sources * drill-down grow to multiple spaces without a restructure. Absent/empty when * the name can't be derived — UIs fall back to `orgName`. */ spaces?: Array<{ id: string; name: string; }>; orgKind?: string; subscription?: string; subscriptionLevel?: string; subscriptionName?: string; isEnterprise?: boolean; isFreeAccount?: boolean; } export interface BrowserConnectionArgs { sessionId?: string; projectId?: string; branchName?: string; proxyOrigin?: string; proxyDefaultOrigin?: string; proxyDestination?: string; } /** * Mint a signed CSRF state token bound to the current session's email * and a fresh nonce. Round-trips through Builder's cli-auth flow inside * the redirect_url query string and is verified on the callback before * any keys are written. * * Why bind to email: it's the only stable, universally-available * identity field across all auth modes (Better Auth, BYOA, AUTH_MODE=local). * Binding to the session token instead would put the cookie value in a * URL that may end up in server logs / browser history. */ export declare function signBuilderCallbackState(sessionEmail: string): string; /** * Verify a state token produced by `signBuilderCallbackState`. Returns * false on any malformed, forged, expired, or cross-session token. */ export declare function verifyBuilderCallbackState(token: string | null | undefined, sessionEmail: string): boolean; export declare function verifyBuilderCallbackStateAndGetOwner(token: string | null | undefined): string | null; export declare function signBuilderConnectToken(ownerEmail: string): string; export declare function verifyBuilderConnectToken(token: string | null | undefined, ownerEmail: string): boolean; export declare function verifyBuilderConnectTokenAndGetOwner(token: string | null | undefined): string | null; export declare function appendBuilderConnectToken(connectUrl: string, ownerEmail: string): string; export declare function getBuilderAppHost(): string; export declare function getBuilderApiHost(): string; export declare function getBuilderBranchProjectId(): string; export declare function isBuilderBranchingEnabled(): boolean; export declare function resolveBuilderBranchProjectId(): Promise; export declare function resolveIsBuilderBranchingEnabled(): Promise; /** * Query param on the callback URL that carries the original preview opener * origin when cli-auth's allow-list forces `preview_url` to the gateway. * Read on the callback to derive the correct postMessage targetOrigin. * * Not signed: the receive-side trust check in `useBuilderStatus` still * gates messages by allow-listed origin. The worst an attacker could do by * crafting a different `_an_opener` value is target a postMessage to an * origin that doesn't match the actual opener — postMessage drops the * message in that case, identical to the legacy wildcard-fallback path. */ export declare const BUILDER_OPENER_PARAM = "_an_opener"; /** * Build the Builder cli-auth URL for the connect popup. When a signed * `state` token is supplied it is embedded inside the `redirect_url` * query string so it survives Builder's redirect verbatim — Builder * preserves the redirect_url's existing query when appending p-key / * api-key / etc., so we don't depend on Builder echoing a top-level * `state` parameter (it doesn't). * * Status responses can surface this URL directly; the legacy * `/_agent-native/builder/connect` trampoline still calls this helper for * clients that only know the app-local connect URL. */ export declare function buildBuilderCliAuthUrl(callbackOrigin: string, state?: string | null, options?: { previewOrigin?: string; relayState?: string; tracking?: BuilderConnectTrackingParams; }): string; /** * The bare URL surfaced to clients as `connectUrl`. The status route appends * a short-lived signed connect token when it knows the current owner; this * helper stays bare so server-rendered cards can still render without a * request-bound owner and the connect route can fall back to Fetch Metadata. */ export declare function getBuilderBrowserConnectUrl(origin: string): string; export declare function getBuilderBrowserConnectUrlForOwner(origin: string, ownerEmail: string | null | undefined): string; /** * User-visible Builder connect origin. In Builder/Fusion previews, keep the * connect URL on the actual app preview origin so clicking Connect happens in * the same deployment that minted the signed connect token. */ export declare function getBuilderBrowserOriginForEvent(event: H3Event): string; /** * Builder's /cli-auth page currently only accepts localhost, *.builder.io, * *.agent-native.com, or builder: redirect_url destinations. Preview hosts * such as *.builderio.xyz and *.builder.codes are valid app origins for us, * but Builder rejects them and falls back to http://localhost:10110/auth. * Use a configured public gateway for the callback in those cases while * leaving the surfaced connect URL on the user's active preview. */ export declare function getBuilderCliAuthCallbackOriginForEvent(event: H3Event): string; export declare function getBuilderBrowserStatus(origin: string): BuilderBrowserStatus; export declare function getBuilderBrowserStatusForEvent(event: H3Event): BuilderBrowserStatus; /** * Env vars written by the Builder CLI-auth callback. Single source of truth * for the connect/disconnect key set — `getBuilderCallbackEnvVars` and the * disconnect handler's scrub loop both derive from this list, so drift * (e.g. disconnect silently leaving `BUILDER_USER_ID` behind because * someone added a key to one site but not the other) is impossible. */ export declare const BUILDER_ENV_KEYS: readonly ["BUILDER_PRIVATE_KEY", "BUILDER_PUBLIC_KEY", "BUILDER_USER_ID", "BUILDER_ORG_NAME", "BUILDER_ORG_KIND", "BUILDER_SUBSCRIPTION", "BUILDER_SUBSCRIPTION_LEVEL", "BUILDER_SUBSCRIPTION_NAME", "BUILDER_IS_ENTERPRISE", "BUILDER_IS_FREE_ACCOUNT"]; export type BuilderEnvKey = (typeof BUILDER_ENV_KEYS)[number]; export declare function getBuilderCallbackEnvVars(params: { privateKey?: string | null; publicKey?: string | null; userId?: string | null; orgName?: string | null; orgKind?: string | null; subscription?: string | null; subscriptionLevel?: string | null; subscriptionName?: string | null; isEnterprise?: boolean | null; isFreeAccount?: boolean | null; }): { key: "BUILDER_IS_ENTERPRISE" | "BUILDER_IS_FREE_ACCOUNT" | "BUILDER_ORG_KIND" | "BUILDER_ORG_NAME" | "BUILDER_PRIVATE_KEY" | "BUILDER_PUBLIC_KEY" | "BUILDER_SUBSCRIPTION" | "BUILDER_SUBSCRIPTION_LEVEL" | "BUILDER_SUBSCRIPTION_NAME" | "BUILDER_USER_ID"; value: string; }[]; export declare function resolveSafePreviewUrl(previewUrl: string | null | undefined, event: H3Event): string; export declare function resolveBuilderPreviewRelayParentOrigin(options: { openerOrigin?: string | null; targetOrigin: string; }): string; export declare function resolveBuilderCallbackReturnUrl(options: { event: H3Event; openerOrigin?: string | null; previewUrl?: string | null; }): string; export declare function createBuilderBrowserCallbackPage(previewUrl: string, opts?: { parentOrigin?: string; }): string; /** * HTML page rendered inside the OAuth popup when the callback handler caught * an error persisting the per-user Builder credentials. Without this, the * popup would show the success page even though the write failed — leaving * the parent window stuck on "Waiting for Builder…" until the 5-minute poll * timeout fires (Midhun reported this on 2026-04-28). * * The page does two things: * 1. Shows the user a clear "couldn't save credentials" message with the * underlying error so they can retry or report. * 2. `postMessage`s the parent (same-origin opener) so the connect-flow * polling stops immediately rather than waiting for the next /status * poll to surface the SQL `builder-connect-error:` row. */ export declare function createBuilderBrowserCallbackErrorPage(message: string, opts?: { title?: string; body?: string; closeHint?: string; parentOrigin?: string; }): string; export interface RunBuilderAgentArgs { prompt: string; projectId?: string; branchName?: string; userEmail?: string; userId?: string; } export interface RunBuilderAgentResult { branchName: string; projectId: string; url: string; status: string; } /** * POST a prompt to the Builder agents-run API. The Builder agent runs in a * cloud sandbox and writes code to a branch; the returned URL opens that * branch in the Visual Editor so the user can watch progress. * * Spec: https://www.builder.io/c/docs/agents-run-api */ export declare function runBuilderAgent(args: RunBuilderAgentArgs): Promise; export declare function requestBuilderBrowserConnection(args: BrowserConnectionArgs): Promise>; export {}; //# sourceMappingURL=builder-browser.d.ts.map