import type { DbExec } from "../db/client.js"; import type { EngineRequestShape } from "./engine/types.js"; import { type AgentTurnInitiator } from "./run-store.js"; import type { AgentChatEvent, RunEvent, RunStatus } from "./types.js"; export interface ActiveRun { runId: string; threadId: string; parentId?: string | null; turnId: string; agentKitApprovalContinuation?: boolean; events: RunEvent[]; status: RunStatus; subscribers: Set<(event: RunEvent) => void>; abort: AbortController; nextEventSeq?: number; pendingAbortEvent?: RunEvent; flushEvents?: () => Promise; waitForPersistence?: () => Promise; abortReason?: string; abortPersistenceManaged?: boolean; abortPersistencePromise?: Promise; continuationTerminalEvent?: Extract; startedAt: number; } export interface StartedRun extends ActiveRun { finalized: Promise; livenessReady: Promise; } export declare const DEFAULT_HOSTED_RUN_SOFT_TIMEOUT_MS = 40000; export declare const HOSTED_SOFT_TIMEOUT_CEILING_MS = 40000; export declare const DEFAULT_BACKGROUND_NO_PROGRESS_TIMEOUT_MS = 150000; export declare function resolveRunToolTimeoutCeilingMs(softTimeoutMs: number): number; export declare function resolveRunNoProgressTimeoutMs(params: { softTimeoutMs: number; backgroundFunction?: boolean; overrideMs?: number; backgroundOverrideMs?: number; }): number; export declare const DEFAULT_COMPLETED_RUN_RETENTION_MS: number; export declare const DEFAULT_ERRORED_RUN_RETENTION_MS: number; export declare const TERMINAL_RUN_RECONNECT_WINDOW_MS: number; export declare const SQL_SUBSCRIPTION_ACTIVE_POLL_MS = 125; export declare const SQL_SUBSCRIPTION_IDLE_POLL_MS = 500; export declare const SQL_SUBSCRIPTION_ACTIVE_GRACE_MS = 2000; export declare const SQL_SUBSCRIPTION_STATUS_POLL_MS = 500; export declare const SQL_SUBSCRIPTION_IDLE_DECAY_AFTER_POLLS = 4; export declare const SQL_SUBSCRIPTION_IDLE_MAX_POLL_MS = 2000; export declare const SQL_SUBSCRIPTION_REAP_POLL_MS = 5000; export declare const SQL_SUBSCRIPTION_RETRY_BASE_MS = 250; export declare const IN_MEMORY_TERMINAL_SETTLE_MS = 5000; export declare const SQL_SUBSCRIPTION_MAX_CONSECUTIVE_FAILURES = 4; export declare const SQL_SUBSCRIPTION_RETRY_MAX_MS = 2000; export declare function resolveSqlSubscriptionPollMs(now: number, activePollUntil: number, consecutiveEmptyPolls?: number): number; export declare function nextSqlSubscriptionEmptyPolls(current: number, hadEvents: boolean, now: number, activePollUntil: number): number; export declare function resolveSqlSubscriptionRetryMs(consecutiveFailures: number): number; export declare function engineRequestShapeTags(shape: EngineRequestShape | undefined): Record; export interface StartRunOptions { waitUntil?: (promise: Promise) => void; softTimeoutMs?: number; softTimeoutDeadlineAt?: number; useHostedSoftTimeoutDefault?: boolean; turnId?: string; agentKitApprovalContinuation?: boolean; parentId?: string | null; backgroundFunction?: boolean; noProgressTimeoutMs?: number; backgroundNoProgressTimeoutMs?: number; dispatchMode?: "foreground" | "foreground-self-chain" | "background"; turnInitiator?: AgentTurnInitiator; runRowAlreadyInserted?: boolean; /** Serialized with the run insert before the run driver starts. */ afterRunInsert?: (tx: DbExec) => Promise; executionLease?: boolean; model?: string; engineName?: string; userId?: string; attemptCount?: number; recoverChunkBoundaries?: boolean; persistEvent?: (write: () => Promise, metadata: { terminal: boolean; runId: string; seq: number; eventData: string; }) => Promise; } export interface RunChunkControl { readonly turnSignal: AbortSignal; readonly chunkSignal: AbortSignal; chunkBoundaryReason(): string | null; beginChunk(): AbortSignal; flushEvents(): Promise; } export interface ResolveRunSoftTimeoutOptions { useHostedDefault?: boolean; backgroundFunction?: boolean; } export declare function isHostedRuntime(): boolean; export declare function resolveRunSoftTimeoutMs(overrideMs?: number, options?: ResolveRunSoftTimeoutOptions): number; export declare function resolveCompletedRunRetentionMs(): number; export declare function resolveErroredRunRetentionMs(): number; export declare function resolveBackgroundRunHardTimeoutMs(): number; export declare function resolveBackgroundAutomationSoftTimeoutMs(overrideMs?: number): number; /** * A tool result with no later assistant text is an unfinished turn, not a * successful terminal response. Keep this predicate beside the run-manager's * terminal synthesis so the run-manager and production continuation paths use * the same boundary evidence. * * A FAILED tool result counts too. Skipping it made the verdict depend on * whether some earlier call in the same turn happened to succeed: a turn ending * on `resources` ok then `web_request` failed continued, while the same turn * with both failing terminated as a plain `done`. The client can only render * "stopped after these actions ... without sending a final message" for that, * so the tool's real error — an expired handoff URL, a missing credential — * never reached the user, and typing "continue" by hand was the only way to see * it. The model has not read the error yet at this point, which makes a failed * tail strictly more unfinished than a successful one. */ export declare function endsAfterToolResultWithoutAssistantFinal(run: ActiveRun): boolean; export declare function endsDuringActionPreparation(run: ActiveRun): boolean; export declare function startRun(runId: string, threadId: string, runFn: (send: (event: AgentChatEvent) => Promise, signal: AbortSignal, control: RunChunkControl) => Promise, onComplete?: (run: ActiveRun) => void | Promise, options?: StartRunOptions): StartedRun; export declare function subscribeToRun(runId: string, fromSeq: number): ReadableStream | null; export declare function replayCompletedTurn(threadId: string, turnId: string): Promise | null>; export declare function getActiveRunForThread(threadId: string): ActiveRun | null; export declare function getActiveRunForThreadAsync(threadId: string): Promise<{ runId: string; threadId: string; turnId: string; status: string; /** * The one answer to "is a run in flight on this thread". A terminal run is * still returned inside `TERMINAL_RUN_RECONNECT_WINDOW_MS` so a reconnecting * client can replay it, which is why `status` alone being present means * nothing; `/runs/active` reports this as its `active` flag. */ inFlight: boolean; heartbeatAt: number; lastProgressAt: number | null; dispatchMode?: string | null; terminalReason?: string | null; successorOfRunId?: string; reapFailed?: boolean; diagStage?: string | null; /** * True exactly when this run is a `chainServerDrivenContinuation` deferral * (dispatch_mode === 'background', never claimed) still inside * `UNCLAIMED_BACKGROUND_RUN_REDISPATCH_BOUND_MS` — the same condition this * function already uses below to skip its own `reapUnclaimedBackgroundRun`. * Surfaced on `/runs/active` (agent-chat-plugin.ts) so * `agent-chat-adapter.ts`'s follow loop can tell "silently deferred, * server-side recovery in progress" apart from "dead" and stop counting the * quiet gap against its idle timeout — see the THREE-SITE INVARIANT comment * below and in agent-chat-plugin.ts / production-agent.ts. False for a live * in-memory run; the same-turn successor path can select an unclaimed SQL * successor beside a stale in-memory predecessor, so it uses the same bound. */ awaitingRedispatch: boolean; hasInFlightWork: boolean; } | null>; export declare function getRun(runId: string): ActiveRun | null; export declare function abortRun(runId: string, reason?: string): boolean; /** * Abort a run and wait until the cross-isolate SQL state and terminal event * are durable. Request handlers that start recovery immediately after aborting * must use this path; otherwise the recovery POST can race the old row while * it is still marked running. */ export declare function abortRunDurably(runId: string, reason?: string, options?: { allowNotStarted?: boolean; }): Promise; /** Abort after the durable run store confirms no model or tool work is in flight. */ export declare function abortRunAtSafeBoundaryDurably(runId: string, reason?: string): Promise; export declare function abortTurnByRefDurably(threadId: string, turnId: string, reason?: string): Promise<"aborted" | "already_terminal">; export declare function abortTurnDurably(runId: string, reason?: string): Promise<"aborted" | "already_terminal">; /** Persist a Stop's turn marker even when a terminal event flush must be reported. */ export declare function abortRunAndTurnDurably(runId: string, reason?: string, options?: { safeBoundary?: boolean; }): Promise; export { getSlotHoldingRunId, tryClaimRunSlot } from "./run-store.js";