import type { PlayBundleArtifact } from '../plays/artifact-types'; import type { PlayCheckpoint, PlayExecutionEvent, PlayRowUpdate, PlayStep, } from './ctx-types'; import type { PlayExecutionSuspension } from './suspension'; import type { PlayStaticPipeline } from '../plays/static-pipeline'; import type { PlayLiveEventSource } from './live-events'; import type { PreloadedRuntimeDbSession } from './db-session'; import type { PacingRule } from './governor/rate-state-backend'; import type { GovernanceSnapshot } from './governor/governor'; import type { PlaySandboxRuntimeLimits } from './sandbox-runtime-limits'; import type { PlayRunInputPayload } from './play-input'; import type { PlayRunFailureDetails } from './run-failure'; import type { ToolExecutionErrorSchemaVersion } from '../tool-execution-error'; import type { ToolResponseContract } from './tool-response-contract'; import type { FixtureBehavior } from './fixture-behavior'; export type PlayRunnerRateStateBackendConfig = | { kind: 'in_memory'; } | { kind: 'app_runtime_postgres'; schedulerSchema?: string | null; }; export type PlayRunnerRateStateAcquireInput = { bucketId: string; rateScopeToken?: string | null; rules: PacingRule[]; requested: number; /** Confirmed provider successes since this runner's previous reservation. */ observedSuccesses?: number; schedulerSchema?: string | null; }; export type PlayRunnerRateStateAcquireResult = { granted: number; waitMs: number; /** * Gateway clock used to produce `scheduledAtMs`. Runners translate the * schedule into relative delays so cross-machine clock skew cannot compress * provider spacing. */ serverNowMs?: number; /** * One globally reserved dispatch timestamp per granted permit. The runtime * may cache the block, but must not dispatch a permit before its timestamp. */ scheduledAtMs?: number[]; /** Live shared rate after adaptive backpressure/recovery. */ effectiveRequestsPerSecond?: number; /** One independently-expiring concurrency reservation per granted permit. */ leaseIds?: string[]; /** * Absolute epoch-ms until which the pacer's own cooldown holds (internally * capped, e.g. 45min probe cadence). Advisory: exposes the current backoff to * observers; the client already sleeps on `waitMs`. */ coolUntilMs?: number; /** * The most recent server Retry-After stored verbatim (uncapped) as an absolute * epoch-ms deadline. Purely observational — never gates a grant on its own. */ claimedRetryAtMs?: number; }; export type PlayRunnerRateStateReleaseInput = { bucketId: string; rateScopeToken?: string | null; rules: PacingRule[]; leaseIds: string[]; schedulerSchema?: string | null; }; export type PlayRunnerRateStatePenalizeInput = { bucketId: string; rateScopeToken?: string | null; cooldownMs: number; schedulerSchema?: string | null; }; export type PlayRunnerBudgetCharge = { key: string; amount: number; limit: number; }; export type PlayRunnerBudgetChargeInput = { rootRunId: string; reservationId: string; charges: PlayRunnerBudgetCharge[]; schedulerSchema?: string | null; }; export type PlayRunnerBudgetChargeResult = { counters: Record; }; export interface PlayRunnerContextConfig { executorToken?: string; baseUrl?: string; /** * Runtime API origin reachable from a customer-code sandbox. Production sends * execution traffic directly to the app; preview may use the combined gateway * because the preview app requires a protection-bypass credential. */ executionGatewayBaseUrl?: string | null; receiptGatewayBaseUrl?: string | null; /** * Request execution through the relay's durable invocation fence. This is * required when the execution relay and receipt gateway have different * origins, where the legacy same-origin inference cannot apply. */ requestDurableInvocationFence?: boolean; /** * Preserves the explicit fence capability for callers that validate an * ambiguous dispatched provider request before allowing a retry. */ durableInvocationFence?: boolean; runtimeTestFaultHeader?: string | null; vercelProtectionBypassToken?: string | null; integrationMode?: 'live' | 'eval_stub' | 'fixture'; /** * Docflow rollout answer for this run, stamped at admission onto the signed * runtime authority and relayed here. Absent means OFF, so a runner reading a * launch queued before the field existed captures nothing extra. */ docflowEnabled?: boolean; /** Validated internal fixture-only provider response simulation. */ fixtureBehavior?: FixtureBehavior | null; /** Preview/dev test seam that applies provider pacing to fixture responses. */ enforceFixtureProviderPacing?: boolean; /** Validated per-run ceiling for provider-tool executions and ctx.fetch. */ maxConcurrentExternalCalls?: number | null; maxConcurrentRows?: number | null; /** Immutable tool-error payload schema copied from the run contract. */ toolErrorSchemaVersion?: ToolExecutionErrorSchemaVersion; /** Immutable execute response contract copied from the Play artifact. */ toolResponseContract?: ToolResponseContract; /** Explicit response-transform revision participating in receipt identity. */ toolResponseReceiptRevision?: string; orgId?: string; workflowId?: string; playId?: string; runId?: string; runAttempt?: number | null; playName?: string; userEmail?: string; convexUrl?: string; staticPipeline?: PlayStaticPipeline | null; force?: boolean | null; forceToolRefresh?: boolean | null; /** * Controls how scoped Postgres sessions enter the runner. `preloaded` means * the launch config carries short-lived encrypted sessions minted before * dispatch. Daytona sandboxes never mint direct database sessions. */ dbSessionStrategy?: 'preloaded' | 'gateway_only' | 'trusted_dynamic'; /** * Short-lived scoped Postgres sessions minted by the worker before the runner * starts. A missing or mismatched session is a fatal launch-contract error; * an external attempt token can never mint a replacement. */ preloadedDbSessions?: PreloadedRuntimeDbSession[]; /** * Secret that decrypts `preloadedDbSessions` postgres URLs. The preloaded * sessions are AES-GCM sealed at submit time with the run's original executor * (authority) token, whose string is the key material. Durable schedulers * re-mint a fresh per-attempt executor token (with `run_attempt`/capabilities * claims) for API auth, which changes the token string and would break unwrap * if used as the decryption key. This field pins the stable submit-time secret * so unwrap always uses the exact token that encrypted the sessions, * independent of per-attempt re-minting. Absent means fall back to * `executorToken` (legacy/no-remint paths where they are equal). */ postgresSessionUnwrapKey?: string | null; rateStateBackend?: PlayRunnerRateStateBackendConfig; runtimeSchedulerSchema?: string | null; /** * Push-execution wiring for the Daytona sandbox runner. When present the * runner keeps the Absurd run claim alive itself (heartbeating the receipt * gateway on a `leaseSeconds / 3` cadence) instead of the worker babysitting a * held `executeCommand` await. Absent for the worker-babysat local-process * backend and every non-Daytona runtime, which keep their existing behavior. */ runnerPushExecution?: RunnerPushExecutionConfig | null; governance?: GovernanceSnapshot | null; /** Immutable resource envelope resolved at launch. */ sandboxRuntimeLimits?: PlaySandboxRuntimeLimits | null; } /** * Runner-side push-execution parameters. The receipt gateway resolves the run's * queue server-side, so the runner only needs the lease window (to derive the * heartbeat cadence) and the run identity it heartbeats. */ export interface RunnerPushExecutionConfig { /** Absurd claim lease window in seconds; heartbeat cadence is this / 3. */ leaseSeconds: number; /** The run the runner heartbeats. Must match the executor token's run scope. */ runId: string; } export interface PlayRunnerExecutionConfig { artifact: PlayBundleArtifact; artifactTransport?: { bundledCodePath?: string | null; bundledCodeEncoding?: 'utf8' | 'gzip'; sourceMapPath?: string | null; } | null; input: PlayRunInputPayload; checkpoint?: PlayCheckpoint | null; csvSourcePath?: string | null; csvSourceUrl?: string | null; csvSourceContentBase64?: string | null; runtimeInputAlias?: string | null; materializedFiles: Record; workspaceRoot: string; context: PlayRunnerContextConfig; } export type PlayRunnerLogEvent = { type: 'log'; at: string; source: PlayLiveEventSource; line: string; }; export type PlayRunnerEvent = | PlayRunnerLogEvent | { type: 'checkpoint'; checkpoint: PlayCheckpoint; } | { type: 'row_update'; update: PlayRowUpdate; } | { type: 'execution_event'; event: PlayExecutionEvent; } | { type: 'result'; result: PlayRunnerResult; }; export type PlayRunnerRuntimeTiming = | { backend: 'daytona'; daytonaCreateMs?: number; daytonaUploadMs?: number; daytonaExecuteMs?: number; modalCreateMs?: never; modalUploadMs?: never; modalExecuteMs?: never; } | { backend: 'modal'; modalCreateMs?: number; modalUploadMs?: number; modalExecuteMs?: number; daytonaCreateMs?: never; daytonaUploadMs?: never; daytonaExecuteMs?: never; }; /** * Why replay checkpoint state is present or absent on the detached-runner * terminal wire. This describes checkpoint transport only; it never classifies * the customer's returned output as oversized. */ export const RUNNER_TERMINAL_CHECKPOINT_DISPOSITION = { OMITTED_TERMINAL_REPLAY: 'omitted_terminal_replay', INCLUDED_RESUME_REQUIRED: 'included_resume_required', ABSENT: 'absent', } as const; export type RunnerTerminalCheckpointDisposition = (typeof RUNNER_TERMINAL_CHECKPOINT_DISPOSITION)[keyof typeof RUNNER_TERMINAL_CHECKPOINT_DISPOSITION]; export type PlayRunOutputWarning = { code: 'RUN_OUTPUT_TRUNCATED'; reason: 'array_preview_limit' | 'byte_limit'; message: string; originalBytes?: number; originalBytesAtLeast?: number; retainedBytes?: number; limitBytes?: number; limitItems?: number; originalItems?: number; retainedItems?: number; retryable: false; recoverableFrom: 'runtime_sheet' | 'none'; }; export type PlayRunnerResult = | { status: 'completed'; output: unknown; outputWarnings?: PlayRunOutputWarning[]; outputRowCount?: number; logs: string[]; stats: Record; steps: PlayStep[]; checkpoint: PlayCheckpoint; tableNamespace?: string | null; totalRows?: number; inserted?: number; skipped?: number; runtimeTiming?: PlayRunnerRuntimeTiming; } | { status: 'suspended'; suspension: PlayExecutionSuspension; logs: string[]; stats: Record; steps: PlayStep[]; checkpoint: PlayCheckpoint; tableNamespace?: string | null; totalRows?: number; inserted?: number; skipped?: number; runtimeTiming?: PlayRunnerRuntimeTiming; } | { status: 'failed'; error: string; errors?: PlayRunFailureDetails[]; logs: string[]; stats: Record; steps: PlayStep[]; checkpoint?: PlayCheckpoint | null; tableNamespace?: string | null; totalRows?: number; inserted?: number; skipped?: number; runtimeTiming?: PlayRunnerRuntimeTiming; };