@agent-native/core 0.84.5 → 0.84.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -44,6 +44,20 @@ export declare const UNCLAIMED_BACKGROUND_RUN_ERROR_EVENT: {
44
44
  readonly recoverable: true;
45
45
  readonly details: "A background-dispatched run was acknowledged (HTTP 202) but its worker never claimed the run, so no progress was produced. The run was reaped early (it had no live worker to protect) so the turn can be retried.";
46
46
  };
47
+ /**
48
+ * Terminal error for a background worker that DID claim the run, then failed
49
+ * during route/handler setup before `startRun` could emit its own error event.
50
+ * Claimed runs are no longer eligible for foreground inline recovery, so the
51
+ * route boundary must fail them loudly instead of leaving subscribers to wait
52
+ * for stale-run recovery.
53
+ */
54
+ export declare const CLAIMED_BACKGROUND_WORKER_FAILED_ERROR_EVENT: {
55
+ readonly type: "error";
56
+ readonly error: "The background agent worker stopped before it could start the turn. You can retry from the preserved chat context.";
57
+ readonly errorCode: "background_worker_failed";
58
+ readonly recoverable: true;
59
+ readonly details: "The durable background worker claimed the run but threw during setup before it could emit agent events.";
60
+ };
47
61
  /**
48
62
  * Grace period before a never-claimed background run (dispatch_mode still
49
63
  * 'background', no worker claim) is treated as a dead handoff and reaped.
@@ -1 +1 @@
1
- {"version":3,"file":"run-store.d.ts","sourceRoot":"","sources":["../../src/agent/run-store.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"run-store.d.ts","sourceRoot":"","sources":["../../src/agent/run-store.ts"],"names":[],"mappings":"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"}
@@ -53,6 +53,20 @@ export const UNCLAIMED_BACKGROUND_RUN_ERROR_EVENT = {
53
53
  recoverable: true,
54
54
  details: "A background-dispatched run was acknowledged (HTTP 202) but its worker never claimed the run, so no progress was produced. The run was reaped early (it had no live worker to protect) so the turn can be retried.",
55
55
  };
56
+ /**
57
+ * Terminal error for a background worker that DID claim the run, then failed
58
+ * during route/handler setup before `startRun` could emit its own error event.
59
+ * Claimed runs are no longer eligible for foreground inline recovery, so the
60
+ * route boundary must fail them loudly instead of leaving subscribers to wait
61
+ * for stale-run recovery.
62
+ */
63
+ export const CLAIMED_BACKGROUND_WORKER_FAILED_ERROR_EVENT = {
64
+ type: "error",
65
+ error: "The background agent worker stopped before it could start the turn. You can retry from the preserved chat context.",
66
+ errorCode: "background_worker_failed",
67
+ recoverable: true,
68
+ details: "The durable background worker claimed the run but threw during setup before it could emit agent events.",
69
+ };
56
70
  /**
57
71
  * Grace period before a never-claimed background run (dispatch_mode still
58
72
  * 'background', no worker claim) is treated as a dead handoff and reaped.
@@ -1 +1 @@
1
- {"version":3,"file":"run-store.js","sourceRoot":"","sources":["../../src/agent/run-store.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * SQL persistence for agent runs and events.\n * Enables cross-isolate access on Cloudflare Workers and\n * reliable reconnection after page refreshes.\n */\nimport { getDbExec, intType, isPostgres } from \"../db/client.js\";\nimport { ensureColumnExists, ensureTableExists } from \"../db/ddl-guard.js\";\nimport { widenIntColumnsToBigInt } from \"../db/widen-columns.js\";\nimport { captureError } from \"../server/capture-error.js\";\nimport type { AgentChatEvent } from \"./types.js\";\n\nlet _initPromise: Promise<void> | undefined;\n\n/**\n * Max time without a heartbeat before a \"running\" run is considered dead.\n * The run-manager heartbeats every 1.5s, so 15s tolerates ~9 missed writes.\n * Widened from 6s to absorb real-world DB latency spikes and GC pauses that\n * caused false-positive reaps: a live run whose heartbeat lagged 6s+ would be\n * reaped and a zombie would keep running, eventually clobbering the new row.\n */\nexport const RUN_STALE_MS = 15_000;\n\n/**\n * Stale window for runs dispatched into a Netlify background function\n * (`dispatch_mode = 'background'`). The design doc flags the 15s reaper vs a\n * background cold-start as the #1 false-failure risk: the foreground POST\n * inserts the `running` row, then `fireInternalDispatch` returns 202 and the\n * background function may take >15s to cold-start and emit its first heartbeat.\n * With the normal 15s window the reaper would falsely kill that freshly-\n * inserted-but-not-yet-heartbeaten row. 90s tolerates a slow background\n * cold-start while still reaping a genuinely dead background worker promptly.\n *\n * Only applied to rows explicitly marked background-dispatched; ordinary\n * foreground runs keep the tight 15s window unchanged.\n */\nexport const BACKGROUND_RUN_STALE_MS = 90_000;\n\nexport const STALE_RUN_ERROR_EVENT = {\n type: \"error\",\n error:\n \"The agent stopped before it could finish. It may have hit a server timeout or the worker may have been interrupted.\",\n errorCode: \"stale_run\",\n recoverable: true,\n details:\n \"The run heartbeat stopped while the run was still marked running. Partial output and tool calls were preserved when available.\",\n} as const;\n\n/**\n * Terminal error for a background-dispatched run whose worker NEVER claimed it\n * (the foreground fired the self-dispatch, Netlify acked it async with a 202,\n * but the `_process-run` worker never ran far enough to flip\n * `dispatch_mode background → background-processing`). Distinct errorCode so the\n * client (and prod triage) can tell \"the worker died silently\" apart from \"a\n * claimed worker's heartbeat went stale\". Recoverable so the client surfaces a\n * retry affordance and re-drives the turn. See `reapUnclaimedBackgroundRun`.\n */\nexport const UNCLAIMED_BACKGROUND_RUN_ERROR_EVENT = {\n type: \"error\",\n error:\n \"The agent run was handed off to a background worker that never started. It was recovered so you can try again.\",\n errorCode: \"background_worker_never_started\",\n recoverable: true,\n details:\n \"A background-dispatched run was acknowledged (HTTP 202) but its worker never claimed the run, so no progress was produced. The run was reaped early (it had no live worker to protect) so the turn can be retried.\",\n} as const;\n\n/**\n * Grace period before a never-claimed background run (dispatch_mode still\n * 'background', no worker claim) is treated as a dead handoff and reaped.\n *\n * This is intentionally MUCH tighter than `BACKGROUND_RUN_STALE_MS` (90s). The\n * wide 90s window exists ONLY to protect a CLAIMED worker whose heartbeat lags\n * during a slow cold start. A run that is still `dispatch_mode = 'background'`\n * has, by definition, NO worker — nothing to protect — so once a Netlify\n * background function has had a reasonable cold-start window to claim it and\n * hasn't, the handoff is dead and should surface promptly instead of leaving\n * the user staring at a spinner for 90s. 25s comfortably exceeds a normal\n * Netlify Lambda cold start while still failing fast on a silent worker death.\n */\nexport const UNCLAIMED_BACKGROUND_RUN_GRACE_MS = 25_000;\n\nasync function ensureRunTables(): Promise<void> {\n if (!_initPromise) {\n _initPromise = (async () => {\n const client = getDbExec();\n\n // Shared CREATE SQL strings — referenced by both the Postgres and SQLite\n // branches so the column definitions stay in one place.\n const agentRunsCreateSql = `\n CREATE TABLE IF NOT EXISTS agent_runs (\n id TEXT PRIMARY KEY,\n thread_id TEXT NOT NULL,\n status TEXT NOT NULL DEFAULT 'running',\n abort_reason TEXT,\n started_at ${intType()} NOT NULL,\n completed_at ${intType()},\n heartbeat_at ${intType()},\n last_progress_at ${intType()},\n turn_id TEXT,\n error_code TEXT,\n error_detail TEXT,\n dispatch_mode TEXT,\n diag_stage TEXT\n )\n `;\n const agentRunEventsCreateSql = `\n CREATE TABLE IF NOT EXISTS agent_run_events (\n run_id TEXT NOT NULL,\n seq ${intType()} NOT NULL,\n event_data TEXT NOT NULL,\n PRIMARY KEY (run_id, seq)\n )\n `;\n // Tool-call result ledger: persists the outcome of write tool calls that\n // completed AFTER their chunk was abandoned (zombie completions). A\n // resumed continuation can recover the real result by matching\n // thread_id + tool_key (name:stableInputHash) instead of re-executing\n // the side effect. Entries are scoped to the thread and expire with it.\n const agentToolLedgerCreateSql = `\n CREATE TABLE IF NOT EXISTS agent_tool_ledger (\n thread_id TEXT NOT NULL,\n tool_key TEXT NOT NULL,\n result_summary TEXT NOT NULL,\n completed_at ${intType()} NOT NULL,\n PRIMARY KEY (thread_id, tool_key)\n )\n `;\n\n if (isPostgres()) {\n // Hot path: in production the tables and all additive columns are\n // virtually always already present. Issuing `CREATE TABLE`/`ALTER TABLE\n // ADD COLUMN` still takes an ACCESS EXCLUSIVE lock — which, in a fresh\n // background-worker process behind a concurrent connection on the shared\n // Neon DB, can block ~indefinitely. So check `information_schema` first\n // (plain reads, no lock) and run DDL ONLY for what is actually missing.\n // The `ensureTableExists` / `ensureColumnExists` wrappers probe →\n // guarded-DDL (bounded `lock_timeout`) → re-probe, and THROW if the\n // schema is still missing after a swallowed lock-timeout so a poisoned\n // init never memoizes success against absent schema (the `_initPromise`\n // rejects and the next call retries).\n await ensureTableExists(\"agent_runs\", agentRunsCreateSql);\n // Additive columns — all listed in the CREATE TABLE above, so on a\n // fresh DB they already exist after the CREATE and these checks are\n // instant short-circuits. On an older deployment that predates a\n // column, the wrapper issues one bounded ALTER.\n //\n // Backfill heartbeat_at on older deployments.\n // heartbeat_at = \"the producer process is alive\" (bumped on a timer).\n // last_progress_at = \"the agent is actually emitting events\" (bumped on\n // each emit). The gap between them is the stuck-detector signal.\n for (const [col, colType] of [\n [\"heartbeat_at\", intType()],\n [\"abort_reason\", \"TEXT\"],\n [\"last_progress_at\", intType()],\n // Backfill turn_id / error_code / error_detail.\n // turn_id = stable identity for one logical assistant turn that may\n // span several continuation runs, so the durable record\n // can be folded across runs instead of dropped per-run.\n // error_code / error_detail = terminal failure classification captured\n // at completion so errored/cut-off runs are queryable for\n // pattern analysis (see listErroredRuns).\n // dispatch_mode marks how a run was started: NULL/\"foreground\" for the\n // normal synchronous path, \"background\" for a run dispatched into a\n // Netlify background function. The reaper/claim widen the stale window\n // for background rows so a slow cold-start isn't falsely reaped.\n // diag_stage records the last reached pipeline stage (+ any error) for a\n // background-dispatched run so a silent worker death is DIAGNOSABLE from\n // the client (/runs/active surfaces it) without reading the unreadable\n // Netlify background-function logs. See recordRunDiagnostic.\n [\"turn_id\", \"TEXT\"],\n [\"error_code\", \"TEXT\"],\n [\"error_detail\", \"TEXT\"],\n [\"dispatch_mode\", \"TEXT\"],\n [\"diag_stage\", \"TEXT\"],\n [\"worker_stage\", \"TEXT\"],\n ] as const) {\n await ensureColumnExists(\n \"agent_runs\",\n col,\n `ALTER TABLE agent_runs ADD COLUMN IF NOT EXISTS ${col} ${colType}`,\n );\n }\n await ensureTableExists(\"agent_run_events\", agentRunEventsCreateSql);\n await ensureTableExists(\"agent_tool_ledger\", agentToolLedgerCreateSql);\n // Widen millisecond-timestamp columns that older deployments created as\n // 32-bit `INTEGER`. `insertRun()` writes `Date.now()` into `started_at`\n // on every turn, so an int4 column makes every agent prompt fail on\n // Postgres with \"value … is out of range for type integer\". No-op once\n // widened (and on fresh DBs that already use BIGINT). See\n // widenIntColumnsToBigInt.\n await widenIntColumnsToBigInt(\"agent_runs\", [\n \"started_at\",\n \"completed_at\",\n \"heartbeat_at\",\n \"last_progress_at\",\n ]);\n await widenIntColumnsToBigInt(\"agent_tool_ledger\", [\"completed_at\"]);\n return;\n }\n\n // SQLite (local dev): no ACCESS EXCLUSIVE lock problem — keep the\n // original create-then-additive-alter behaviour. SQLite has no\n // `ADD COLUMN IF NOT EXISTS`, so the ALTERs stay wrapped in try/catch.\n await client.execute(agentRunsCreateSql);\n // Backfill heartbeat_at on older deployments.\n try {\n await client.execute(\n `ALTER TABLE agent_runs ADD COLUMN heartbeat_at ${intType()}`,\n );\n } catch {\n // Column already exists — ignore\n }\n try {\n await client.execute(\n `ALTER TABLE agent_runs ADD COLUMN abort_reason TEXT`,\n );\n } catch {\n // Column already exists — ignore\n }\n // Backfill last_progress_at — this is distinct from heartbeat_at.\n // heartbeat_at = \"the producer process is alive\" (bumped on a timer).\n // last_progress_at = \"the agent is actually emitting events\" (bumped on\n // each emit). The gap between them is the stuck-detector signal.\n try {\n await client.execute(\n `ALTER TABLE agent_runs ADD COLUMN last_progress_at ${intType()}`,\n );\n } catch {\n // Column already exists — ignore\n }\n // Backfill turn_id / error_code / error_detail.\n // turn_id = stable identity for one logical assistant turn that may\n // span several continuation runs, so the durable record\n // can be folded across runs instead of dropped per-run.\n // error_code / error_detail = terminal failure classification captured\n // at completion so errored/cut-off runs are queryable for\n // pattern analysis (see listErroredRuns).\n // dispatch_mode marks how a run was started: NULL/\"foreground\" for the\n // normal synchronous path, \"background\" for a run dispatched into a\n // Netlify background function. The reaper/claim widen the stale window\n // for background rows so a slow cold-start isn't falsely reaped.\n // diag_stage records the last reached pipeline stage (+ any error) for a\n // background-dispatched run so a silent worker death is DIAGNOSABLE from\n // the client (/runs/active surfaces it) without reading the unreadable\n // Netlify background-function logs. See recordRunDiagnostic.\n for (const col of [\n \"turn_id\",\n \"error_code\",\n \"error_detail\",\n \"dispatch_mode\",\n \"diag_stage\",\n \"worker_stage\",\n ] as const) {\n try {\n await client.execute(`ALTER TABLE agent_runs ADD COLUMN ${col} TEXT`);\n } catch {\n // Column already exists — ignore\n }\n }\n await client.execute(agentRunEventsCreateSql);\n await client.execute(agentToolLedgerCreateSql);\n // Widen millisecond-timestamp columns that older deployments created as\n // 32-bit `INTEGER`. `insertRun()` writes `Date.now()` into `started_at`\n // on every turn, so an int4 column makes every agent prompt fail on\n // Postgres with \"value … is out of range for type integer\". No-op once\n // widened (and on fresh DBs that already use BIGINT). See\n // widenIntColumnsToBigInt.\n await widenIntColumnsToBigInt(\"agent_runs\", [\n \"started_at\",\n \"completed_at\",\n \"heartbeat_at\",\n \"last_progress_at\",\n ]);\n await widenIntColumnsToBigInt(\"agent_tool_ledger\", [\"completed_at\"]);\n })().catch((err) => {\n // Retry init on the next call after a failed startup.\n _initPromise = undefined;\n throw err;\n });\n }\n return _initPromise;\n}\n\n// ─── Tool-call result ledger ─────────────────────────────────────────────────\n//\n// When the run-level abort signal fires (soft timeout / user cancel) while a\n// write tool is in-flight, `Promise.race` abandons the call — but the action's\n// Promise continues running in the background (a \"zombie\"). If the zombie\n// resolves before the continuation's next tool dispatch, we record the result\n// here so the continuation can recover it without re-executing the side effect.\n//\n// Keyed by (thread_id, tool_key) where tool_key = \"<toolName>:<stableJsonHash>\".\n// The write is fire-and-forget from the hot path; reads are synchronous look-\n// ups at the start of each write-tool dispatch in the continuation.\n\n/** Max length for a persisted result summary (8 KB). */\nconst LEDGER_RESULT_MAX_CHARS = 8_000;\n\n/**\n * Persist a zombie tool-call completion to the ledger. Called by the detached\n * promise continuation after `Promise.race` abandons it. Best-effort — never\n * throws so a ledger write failure doesn't break any caller.\n */\nexport async function writeLedgerEntry(\n threadId: string,\n toolKey: string,\n resultSummary: string,\n): Promise<void> {\n try {\n await ensureRunTables();\n const client = getDbExec();\n const capped =\n resultSummary.length > LEDGER_RESULT_MAX_CHARS\n ? resultSummary.slice(0, LEDGER_RESULT_MAX_CHARS) +\n `\\n...[ledger truncated at ${LEDGER_RESULT_MAX_CHARS} chars]`\n : resultSummary;\n await client.execute({\n sql: `INSERT INTO agent_tool_ledger (thread_id, tool_key, result_summary, completed_at)\n VALUES (?, ?, ?, ?)\n ON CONFLICT (thread_id, tool_key) DO UPDATE SET\n result_summary = excluded.result_summary,\n completed_at = excluded.completed_at`,\n args: [threadId, toolKey, capped, Date.now()],\n });\n } catch {\n // Ledger is best-effort; never surface failures to the caller.\n }\n}\n\n/**\n * Look up a prior zombie completion for this thread + tool key. Returns the\n * persisted result summary, or `null` when no entry exists.\n */\nexport async function readLedgerEntry(\n threadId: string,\n toolKey: string,\n): Promise<string | null> {\n try {\n await ensureRunTables();\n const client = getDbExec();\n const { rows } = await client.execute({\n sql: `SELECT result_summary FROM agent_tool_ledger WHERE thread_id = ? AND tool_key = ?`,\n args: [threadId, toolKey],\n });\n if (rows.length === 0) return null;\n const row = rows[0] as { result_summary: string };\n return row.result_summary;\n } catch {\n return null;\n }\n}\n\n/**\n * Delete ledger entries for a thread. Called after a turn fully completes so\n * old entries don't bleed into the next turn's disambiguation.\n * Best-effort — never throws.\n */\nexport async function clearLedgerForThread(threadId: string): Promise<void> {\n try {\n await ensureRunTables();\n const client = getDbExec();\n await client.execute({\n sql: `DELETE FROM agent_tool_ledger WHERE thread_id = ?`,\n args: [threadId],\n });\n } catch {\n // Best-effort.\n }\n}\n\nexport async function insertRun(\n id: string,\n threadId: string,\n turnId?: string,\n options?: { dispatchMode?: \"foreground\" | \"background\" },\n): Promise<void> {\n await ensureRunTables();\n const client = getDbExec();\n const now = Date.now();\n await client.execute({\n sql: `INSERT INTO agent_runs (id, thread_id, status, started_at, heartbeat_at, last_progress_at, turn_id, dispatch_mode) VALUES (?, ?, 'running', ?, ?, ?, ?, ?)`,\n args: [\n id,\n threadId,\n now,\n now,\n now,\n turnId ?? id,\n options?.dispatchMode ?? null,\n ],\n });\n}\n\n/**\n * SQL fragment that resolves the per-row stale cutoff. Background-dispatched\n * runs (`dispatch_mode` starting with `background`) tolerate a much longer gap\n * without a heartbeat (slow Netlify background-function cold-start) before being\n * reaped; every other run keeps the tight 15s window. The bound `now` is\n * subtracted by the resolved window so the comparison is\n * `COALESCE(heartbeat_at, started_at) < (now - window)`.\n *\n * `dispatch_mode` is one of NULL/\"foreground\" (normal sync path), \"background\"\n * (foreground inserted the row for a background dispatch), or\n * \"background-processing\" (the background worker claimed it). Both background\n * states get the wider window via a LIKE-prefix match.\n */\nfunction backgroundAwareStaleCutoffSql(): string {\n // `CAST(? AS BIGINT)` is required: without it Postgres infers the param as\n // int4 from the int4 window literals, so the bound `Date.now()` ms epoch\n // overflows int4. The cast keeps the subtraction 64-bit; a no-op on SQLite.\n return `(CAST(? AS BIGINT) - CASE WHEN dispatch_mode LIKE 'background%' THEN ${BACKGROUND_RUN_STALE_MS} ELSE ${RUN_STALE_MS} END)`;\n}\n\n/**\n * Atomically claim a background-dispatched run for processing. The foreground\n * POST inserts the run row with `dispatch_mode = 'background'`; the FIRST\n * delivery of the background dispatch flips it to `background-processing` and\n * wins the claim. A duplicate Netlify delivery (background functions can be\n * retried) sees `background-processing` and loses, so it no-ops — mirroring\n * `claimAgentTeamRun` returning null. Returns true when this caller won.\n *\n * Idempotent and conditional: the WHERE clause only matches the unclaimed\n * `background` state AND a still-running row, so a reaped/terminal row can't be\n * re-claimed.\n */\nexport async function claimBackgroundRun(runId: string): Promise<boolean> {\n await ensureRunTables();\n const client = getDbExec();\n const { rowsAffected } = await client.execute({\n sql: `UPDATE agent_runs\n SET dispatch_mode = 'background-processing'\n WHERE id = ?\n AND status = 'running'\n AND dispatch_mode = 'background'`,\n args: [runId],\n });\n return (rowsAffected ?? 0) > 0;\n}\n\n/**\n * Read the claim/lifecycle state of a single run by id — for the foreground\n * circuit-breaker that confirms a background worker actually CLAIMED a run that\n * was dispatched with a Netlify async 202. A 202 only means the invocation was\n * ENQUEUED; if the generated background-function wrapper fails to import/hand off\n * to the route it never reaches `claimBackgroundRun`, leaving the row stuck at\n * `dispatch_mode = 'background'`. `'background-processing'` means a worker won\n * the claim; a terminal `status` means the run already resolved. Returns null if\n * the row is missing.\n */\nexport async function readBackgroundRunClaim(runId: string): Promise<{\n dispatchMode: string | null;\n status: string | null;\n diagStage: string | null;\n workerStage: string | null;\n lastLivenessAt: number | null;\n} | null> {\n await ensureRunTables();\n const client = getDbExec();\n const { rows } = await client.execute({\n sql: `SELECT dispatch_mode, status, diag_stage, worker_stage, started_at, heartbeat_at FROM agent_runs WHERE id = ? LIMIT 1`,\n args: [runId],\n });\n const row = rows?.[0] as\n | {\n dispatch_mode?: string | null;\n status?: string | null;\n diag_stage?: string | null;\n worker_stage?: string | null;\n started_at?: number | null;\n heartbeat_at?: number | null;\n }\n | undefined;\n if (!row) return null;\n return {\n dispatchMode: row.dispatch_mode ?? null,\n status: row.status ?? null,\n diagStage: row.diag_stage ?? null,\n workerStage: row.worker_stage ?? null,\n // Same liveness basis the unclaimed-reaper uses (COALESCE(heartbeat_at,\n // started_at)), so the foreground can decide to recover BEFORE the reaper.\n lastLivenessAt: row.heartbeat_at ?? row.started_at ?? null,\n };\n}\n\n/**\n * Resolve the authenticated owner email for a run by joining it to its chat\n * thread. The durable background worker's self-dispatch is cookieless\n * (HMAC-only — see `AGENT_CHAT_PROCESS_RUN_PATH`), so it has no session for the\n * normal owner resolution and would otherwise be treated as unauthenticated.\n * The thread's `owner_email` was written by the authenticated foreground when it\n * created the thread, so it is a trusted, non-forgeable owner source: only the\n * HMAC-signed `runId` selects the row, and the caller cannot influence which\n * owner that row maps to. Returns null when the run (or its thread) is missing.\n */\nexport async function getRunOwnerEmail(runId: string): Promise<string | null> {\n await ensureRunTables();\n const client = getDbExec();\n const { rows } = await client.execute({\n sql: `SELECT t.owner_email AS owner_email FROM agent_runs r JOIN chat_threads t ON r.thread_id = t.id WHERE r.id = ? LIMIT 1`,\n args: [runId],\n });\n const row = rows?.[0] as { owner_email?: string | null } | undefined;\n return row?.owner_email ?? null;\n}\n\n/**\n * Atomically acquire a run lease for a thread. Succeeds (returns true) only\n * when no other run for the same thread is currently status='running' with a\n * fresh heartbeat. Works for both Postgres and SQLite: the stale-cutoff\n * comparison lets a dead producer's run be replaced without waiting for the\n * reaper, mirroring the logic in `reapIfStale`.\n *\n * Callers that win the claim then insert the run row normally; callers that\n * lose skip the run and return the existing active runId to the caller.\n */\nexport async function tryClaimRunSlot(\n threadId: string,\n maxStaleMs?: number,\n): Promise<{ claimed: boolean; activeRunId: string | null }> {\n await ensureRunTables();\n const client = getDbExec();\n const now = Date.now();\n // Default: per-row background-aware window so a live background run (which can\n // legitimately go >15s between heartbeats during a cold-start) isn't seen as\n // \"free\" and double-claimed by a racing foreground POST. An explicit\n // `maxStaleMs` override keeps a flat window for callers that want one.\n if (typeof maxStaleMs === \"number\") {\n const heartbeatCutoff = now - maxStaleMs;\n const { rows } = await client.execute({\n sql: `SELECT id FROM agent_runs\n WHERE thread_id = ?\n AND status = 'running'\n AND COALESCE(heartbeat_at, started_at) >= ?\n ORDER BY started_at DESC LIMIT 1`,\n args: [threadId, heartbeatCutoff],\n });\n if (rows.length > 0) {\n return { claimed: false, activeRunId: (rows[0] as { id: string }).id };\n }\n return { claimed: true, activeRunId: null };\n }\n const { rows } = await client.execute({\n sql: `SELECT id FROM agent_runs\n WHERE thread_id = ?\n AND status = 'running'\n AND COALESCE(heartbeat_at, started_at) >= ${backgroundAwareStaleCutoffSql()}\n ORDER BY started_at DESC LIMIT 1`,\n args: [threadId, now],\n });\n if (rows.length > 0) {\n const row = rows[0] as { id: string };\n return { claimed: false, activeRunId: row.id };\n }\n return { claimed: true, activeRunId: null };\n}\n\n/**\n * Record terminal failure classification for a run so cut-off / errored runs\n * can be surfaced for pattern analysis (see listErroredRuns). Best-effort —\n * never throws, since it runs on the completion path that must not fail the run.\n */\nexport async function setRunError(\n runId: string,\n errorCode: string | undefined,\n errorDetail: string | undefined,\n): Promise<void> {\n if (!errorCode && !errorDetail) return;\n try {\n await ensureRunTables();\n const client = getDbExec();\n await client.execute({\n sql: `UPDATE agent_runs SET error_code = ?, error_detail = ? WHERE id = ?`,\n args: [\n errorCode ?? null,\n errorDetail ? errorDetail.slice(0, 2000) : null,\n runId,\n ],\n });\n } catch {\n // Diagnostics are best-effort; never let them break completion.\n }\n}\n\n/**\n * Diagnostic stage names recorded onto a background run as it moves through the\n * `_process-run` worker pipeline. Each value is the LAST stage successfully\n * reached, so a stuck run's `diag_stage` reveals exactly where it died. Ordered\n * roughly by execution; the literal strings are the client-readable contract.\n */\nexport const RUN_DIAG_STAGE = {\n /** The `_process-run` route handler was entered (the request reached Nitro). */\n routeEntered: \"route_entered\",\n /** HMAC auth + body validation in prepareProcessRunRequest FAILED. */\n authFailed: \"auth_failed\",\n /** HMAC auth + body validation PASSED; about to invoke the worker handler. */\n authPassed: \"auth_passed\",\n /** The re-entered agent-chat handler recognized itself as the bg worker. */\n workerEntered: \"worker_entered\",\n /** The worker won the atomic claim (it owns the run). */\n workerClaimed: \"worker_claimed\",\n /** The worker LOST the claim (a duplicate delivery already owns the run). */\n workerClaimLost: \"worker_claim_lost\",\n /** The agent loop started (startRun fired). */\n workerStarted: \"worker_started\",\n /** Last worker setup stage reached before startRun (progressive hang localizer). */\n workerSetupStep: \"worker_setup_step\",\n /** Pre-claim setup timing breakdown (diagnostic). */\n setupTimings: \"setup_timings\",\n /** The worker threw before/while running the loop (message carried in detail). */\n workerThrew: \"worker_threw\",\n /** The route handler caught an error from the worker invocation. */\n routeThrew: \"route_threw\",\n /**\n * The foreground circuit-breaker fired: a Netlify async 202 was returned but\n * no background worker CLAIMED the run within the foreground grace window\n * (the generated function wrapper never reached the route), so the foreground\n * recovered by running the turn inline. The run still completes for the user.\n */\n foregroundInlineRecovery: \"foreground_inline_recovery\",\n} as const;\n\nexport type RunDiagStage = (typeof RUN_DIAG_STAGE)[keyof typeof RUN_DIAG_STAGE];\n\n/**\n * Record the last reached pipeline stage (+ optional short detail) for a run.\n *\n * PURPOSE: a Netlify background function's logs are not readable from the build\n * tooling, so when its worker dies silently the run just times out with no clue\n * WHY. This writes the failure stage straight onto the `agent_runs` row, which\n * `/runs/active` and `listRunsForThread` surface to the client — so the next\n * prod run's death cause is readable WITHOUT bg-fn logs. Cheap, additive, and\n * best-effort: it must never throw or perturb the run (it is called on the auth\n * path BEFORE a 401 is returned, and around the worker body).\n *\n * The stored value is a compact JSON `{ stage, detail?, at }` capped to 2 KB so\n * a long stack can't bloat the row.\n */\nexport async function recordRunDiagnostic(\n runId: string,\n stage: RunDiagStage,\n detail?: string,\n): Promise<void> {\n if (!runId) return;\n try {\n await ensureRunTables();\n const client = getDbExec();\n const payload = JSON.stringify({\n stage,\n ...(detail ? { detail: detail.slice(0, 1500) } : {}),\n at: Date.now(),\n }).slice(0, 2000);\n // Worker-setup stages ALSO land in `worker_stage`, a column the foreground's\n // inline-recovery `setup_timings` write never touches. `/runs/active` only\n // surfaces a run after it is claimed, and the foreground then overwrites\n // `diag_stage` — so without this the durable worker's pre-claim progression\n // (where it stalled before claiming) is unrecoverable. `worker_stage`\n // preserves the last worker stage reached for post-hoc diagnosis.\n const isWorkerStage =\n stage === RUN_DIAG_STAGE.workerSetupStep ||\n stage === RUN_DIAG_STAGE.workerStarted;\n if (isWorkerStage) {\n await client.execute({\n sql: `UPDATE agent_runs SET diag_stage = ?, worker_stage = ? WHERE id = ?`,\n args: [payload, payload, runId],\n });\n } else {\n await client.execute({\n sql: `UPDATE agent_runs SET diag_stage = ? WHERE id = ?`,\n args: [payload, runId],\n });\n }\n } catch {\n // Diagnostics are best-effort; never let them break the run or the route.\n }\n}\n\n/** Update the run's liveness heartbeat. Called periodically by run-manager. */\nexport async function updateRunHeartbeat(runId: string): Promise<void> {\n await ensureRunTables();\n const client = getDbExec();\n await client.execute({\n sql: `UPDATE agent_runs SET heartbeat_at = ? WHERE id = ?`,\n args: [Date.now(), runId],\n });\n}\n\n/**\n * Bump `last_progress_at` — call this whenever the agent actually emits an\n * event (token, tool call, message). Distinct from `heartbeat_at` so the\n * stuck-detector can tell \"process alive but nothing happening\" from\n * \"process dead.\" Callers should throttle (run-manager debounces to ~1/s).\n */\nexport async function bumpRunProgress(runId: string): Promise<void> {\n await ensureRunTables();\n const client = getDbExec();\n await client.execute({\n sql: `UPDATE agent_runs SET last_progress_at = ? WHERE id = ?`,\n args: [Date.now(), runId],\n });\n}\n\n/**\n * If the given run is marked \"running\" in SQL but its heartbeat is stale\n * (producer likely crashed), flip it to \"errored\" so watchers stop waiting.\n * Returns true if the row was reaped.\n */\nexport async function reapIfStale(\n runId: string,\n maxStaleMs?: number,\n): Promise<boolean> {\n await ensureRunTables();\n const client = getDbExec();\n const completedAt = Date.now();\n // Background-dispatched runs get the wider stale window so a slow cold-start\n // isn't reaped; foreground runs keep the tight 15s window. An explicit\n // override forces a flat window for callers that want one.\n const staleClause =\n typeof maxStaleMs === \"number\"\n ? `COALESCE(heartbeat_at, started_at) < ?`\n : `COALESCE(heartbeat_at, started_at) < ${backgroundAwareStaleCutoffSql()}`;\n const staleArgs =\n typeof maxStaleMs === \"number\" ? [completedAt - maxStaleMs] : [completedAt];\n const { rowsAffected } = await client.execute({\n sql: `UPDATE agent_runs\n SET status = 'errored',\n completed_at = ?,\n error_code = ?,\n error_detail = ?\n WHERE id = ?\n AND status = 'running'\n AND ${staleClause}`,\n args: [\n completedAt,\n STALE_RUN_ERROR_EVENT.errorCode,\n STALE_RUN_ERROR_EVENT.details,\n runId,\n ...staleArgs,\n ],\n });\n const reaped = (rowsAffected ?? 0) > 0;\n if (reaped) {\n await safeAppendTerminalRunEvent(\n runId,\n STALE_RUN_ERROR_EVENT,\n \"reap-if-stale\",\n );\n }\n return reaped;\n}\n\n/**\n * FALLBACK HARDENING for the \"dispatched with 202 but the worker never started\"\n * case. A background-dispatched run sits in `dispatch_mode = 'background'` until\n * the worker wins `claimBackgroundRun` (which flips it to\n * `background-processing`). If the worker silently dies (e.g. the bg-fn 401s\n * before it can claim), the row stays `background`, never heartbeats again, and\n * — because dispatch returned 202 — the foreground already returned the SSE\n * stream, so the existing fast-fail inline fallback never engaged. The run would\n * otherwise hang for the full 90s background window and then error opaquely.\n *\n * This reaps such a run EARLY and DISTINCTLY: a row that is still unclaimed\n * (`dispatch_mode = 'background'`) past the tight `UNCLAIMED_BACKGROUND_RUN_GRACE_MS`\n * grace is a dead handoff — there is no live worker to protect with the wide\n * window — so we flip it to `errored` with the recoverable\n * `background_worker_never_started` code. The client's existing recoverable-error\n * path then lets the user (or auto-recovery) re-drive the turn. Idempotent and\n * conditional: only an unclaimed, still-running, grace-exceeded row matches, so a\n * claimed worker, a fresh dispatch, or a terminal row is never touched.\n *\n * Returns true when this call reaped the run.\n */\nexport async function reapUnclaimedBackgroundRun(\n runId: string,\n): Promise<boolean> {\n await ensureRunTables();\n const client = getDbExec();\n const completedAt = Date.now();\n const cutoff = completedAt - UNCLAIMED_BACKGROUND_RUN_GRACE_MS;\n const { rowsAffected } = await client.execute({\n sql: `UPDATE agent_runs\n SET status = 'errored',\n completed_at = ?,\n error_code = ?,\n error_detail = ?\n WHERE id = ?\n AND status = 'running'\n AND dispatch_mode = 'background'\n AND COALESCE(heartbeat_at, started_at) < ?`,\n args: [\n completedAt,\n UNCLAIMED_BACKGROUND_RUN_ERROR_EVENT.errorCode,\n UNCLAIMED_BACKGROUND_RUN_ERROR_EVENT.details,\n runId,\n cutoff,\n ],\n });\n const reaped = (rowsAffected ?? 0) > 0;\n if (reaped) {\n await recordRunDiagnostic(\n runId,\n RUN_DIAG_STAGE.workerThrew,\n \"unclaimed background dispatch reaped (worker never claimed the run)\",\n );\n await safeAppendTerminalRunEvent(\n runId,\n UNCLAIMED_BACKGROUND_RUN_ERROR_EVENT,\n \"reap-unclaimed-background\",\n );\n }\n return reaped;\n}\n\nexport async function updateRunStatus(\n runId: string,\n status: \"completed\" | \"errored\" | \"aborted\",\n): Promise<void> {\n await ensureRunTables();\n const client = getDbExec();\n await client.execute({\n sql: `UPDATE agent_runs SET status = ?, completed_at = ? WHERE id = ?`,\n args: [status, Date.now(), runId],\n });\n}\n\n/**\n * Conditional terminal status write: only updates if the row still belongs to\n * this run AND is still status='running'. Returns true when the update landed.\n *\n * This is the safe variant used by the producer's finally block so a zombie run\n * (reaped while executing) can never clobber the status written by the reaper\n * or a replacement run.\n */\nexport async function updateRunStatusIfRunning(\n runId: string,\n status: \"completed\" | \"errored\" | \"aborted\",\n): Promise<boolean> {\n await ensureRunTables();\n const client = getDbExec();\n const { rowsAffected } = await client.execute({\n sql: `UPDATE agent_runs SET status = ?, completed_at = ? WHERE id = ? AND status = 'running'`,\n args: [status, Date.now(), runId],\n });\n return (rowsAffected ?? 0) > 0;\n}\n\n/** Read the current status of a run row. Returns null when the row is missing. */\nexport async function getRunStatus(runId: string): Promise<string | null> {\n await ensureRunTables();\n const client = getDbExec();\n const { rows } = await client.execute({\n sql: `SELECT status FROM agent_runs WHERE id = ?`,\n args: [runId],\n });\n if (rows.length === 0) return null;\n return String((rows[0] as { status: string }).status);\n}\n\nexport async function markRunAborted(\n runId: string,\n reason?: string,\n): Promise<void> {\n await ensureRunTables();\n const client = getDbExec();\n await client.execute({\n sql: `UPDATE agent_runs SET status = 'aborted', abort_reason = ?, completed_at = ? WHERE id = ?`,\n args: [reason ?? \"user\", Date.now(), runId],\n });\n await safeAppendTerminalRunEvent(runId, { type: \"done\" }, \"mark-aborted\");\n}\n\nexport async function isRunAborted(runId: string): Promise<boolean> {\n return (await getRunAbortState(runId)).aborted;\n}\n\nexport async function getRunAbortState(\n runId: string,\n): Promise<{ aborted: boolean; reason?: string }> {\n await ensureRunTables();\n const client = getDbExec();\n const { rows } = await client.execute({\n sql: `SELECT status, abort_reason FROM agent_runs WHERE id = ?`,\n args: [runId],\n });\n if (rows.length === 0) return { aborted: false };\n const row = rows[0] as { status: string; abort_reason?: string | null };\n if (row.status !== \"aborted\") return { aborted: false };\n return {\n aborted: true,\n ...(row.abort_reason ? { reason: row.abort_reason } : {}),\n };\n}\n\nexport async function insertRunEvent(\n runId: string,\n seq: number,\n eventData: string,\n): Promise<void> {\n await ensureRunTables();\n const client = getDbExec();\n // ON CONFLICT DO NOTHING: a (runId, seq) collision can happen on the\n // soft-timeout / terminal-event path where `pendingTerminalEvent` was\n // assigned a seq that later gets reused by an event pushed after it.\n // It can also race with `appendTerminalRunEvent` (max-seq + 1) when a\n // run aborts at the same time the producer emits its final event.\n // Treat the second write as a no-op so the run completes cleanly.\n await client.execute({\n sql: `INSERT INTO agent_run_events (run_id, seq, event_data) VALUES (?, ?, ?) ON CONFLICT (run_id, seq) DO NOTHING`,\n args: [runId, seq, eventData],\n });\n}\n\nexport async function getRunEventsSince(\n runId: string,\n fromSeq: number,\n): Promise<Array<{ seq: number; eventData: string }>> {\n await ensureRunTables();\n const client = getDbExec();\n const { rows } = await client.execute({\n sql: `SELECT seq, event_data FROM agent_run_events WHERE run_id = ? AND seq >= ? ORDER BY seq ASC`,\n args: [runId, fromSeq],\n });\n return rows.map((r) => {\n const row = r as { seq: number | string; event_data: string };\n return { seq: Number(row.seq), eventData: row.event_data };\n });\n}\n\nexport async function getRunById(runId: string): Promise<{\n id: string;\n threadId: string;\n status: string;\n startedAt: number;\n} | null> {\n await ensureRunTables();\n const client = getDbExec();\n const { rows } = await client.execute({\n sql: `SELECT id, thread_id, status, started_at FROM agent_runs WHERE id = ?`,\n args: [runId],\n });\n if (rows.length === 0) return null;\n const r = rows[0] as {\n id: string;\n thread_id: string;\n status: string;\n started_at: number | string;\n };\n return {\n id: r.id,\n threadId: r.thread_id,\n status: r.status,\n startedAt: Number(r.started_at),\n };\n}\n\nexport async function getRunByThread(\n threadId: string,\n options?: { includeTerminal?: boolean },\n): Promise<{\n id: string;\n threadId: string;\n turnId?: string | null;\n status: string;\n startedAt: number;\n heartbeatAt: number | null;\n completedAt: number | null;\n lastProgressAt: number | null;\n dispatchMode: string | null;\n diagStage: string | null;\n} | null> {\n await ensureRunTables();\n const client = getDbExec();\n const sql = options?.includeTerminal\n ? `SELECT id, thread_id, turn_id, status, started_at, heartbeat_at, completed_at, last_progress_at, dispatch_mode, diag_stage FROM agent_runs WHERE thread_id = ? ORDER BY started_at DESC LIMIT 1`\n : `SELECT id, thread_id, turn_id, status, started_at, heartbeat_at, completed_at, last_progress_at, dispatch_mode, diag_stage FROM agent_runs WHERE thread_id = ? AND status = 'running' ORDER BY started_at DESC LIMIT 1`;\n const { rows } = await client.execute({ sql, args: [threadId] });\n if (rows.length === 0) return null;\n const r = rows[0] as {\n id: string;\n thread_id: string;\n turn_id?: string | null;\n status: string;\n started_at: number | string;\n heartbeat_at: number | string | null;\n completed_at: number | string | null;\n last_progress_at: number | string | null;\n dispatch_mode?: string | null;\n diag_stage?: string | null;\n };\n return {\n id: r.id,\n threadId: r.thread_id,\n turnId: r.turn_id ?? null,\n status: r.status,\n startedAt: Number(r.started_at),\n heartbeatAt: r.heartbeat_at == null ? null : Number(r.heartbeat_at),\n completedAt: r.completed_at == null ? null : Number(r.completed_at),\n lastProgressAt:\n r.last_progress_at == null ? null : Number(r.last_progress_at),\n dispatchMode: r.dispatch_mode ?? null,\n diagStage: r.diag_stage ?? null,\n };\n}\n\nexport interface AgentRunSummary {\n id: string;\n threadId: string;\n turnId: string | null;\n status: string;\n startedAt: number;\n heartbeatAt: number | null;\n completedAt: number | null;\n lastProgressAt: number | null;\n errorCode: string | null;\n abortReason: string | null;\n dispatchMode: string | null;\n /** Last reached `_process-run` worker stage (JSON `{stage,detail?,at}`). */\n diagStage: string | null;\n}\n\nexport async function listRunsForThread(\n threadId: string,\n options: { limit?: number } = {},\n): Promise<AgentRunSummary[]> {\n await ensureRunTables();\n const limit = Math.min(Math.max(options.limit ?? 10, 1), 50);\n const client = getDbExec();\n const { rows } = await client.execute({\n sql: `SELECT id, thread_id, turn_id, status, started_at, heartbeat_at, completed_at, last_progress_at, error_code, abort_reason, dispatch_mode, diag_stage\n FROM agent_runs\n WHERE thread_id = ?\n ORDER BY started_at DESC\n LIMIT ?`,\n args: [threadId, limit],\n });\n return rows.map((r) => {\n const row = r as {\n id: string;\n thread_id: string;\n turn_id?: string | null;\n status: string;\n started_at: number | string;\n heartbeat_at?: number | string | null;\n completed_at?: number | string | null;\n last_progress_at?: number | string | null;\n error_code?: string | null;\n abort_reason?: string | null;\n dispatch_mode?: string | null;\n diag_stage?: string | null;\n };\n return {\n id: row.id,\n threadId: row.thread_id,\n turnId: row.turn_id ?? null,\n status: row.status,\n startedAt: Number(row.started_at),\n heartbeatAt: row.heartbeat_at == null ? null : Number(row.heartbeat_at),\n completedAt: row.completed_at == null ? null : Number(row.completed_at),\n lastProgressAt:\n row.last_progress_at == null ? null : Number(row.last_progress_at),\n errorCode: row.error_code ?? null,\n abortReason: row.abort_reason ?? null,\n dispatchMode: row.dispatch_mode ?? null,\n diagStage: row.diag_stage ?? null,\n };\n });\n}\n\n/**\n * Read the current logical turn's recorded events for a thread, parsed into\n * `AgentChatEvent`s in seq order, for per-turn tool-call journal classification\n * (see `tool-call-journal.ts`). Read-only and additive — reuses the existing\n * `agent_runs` / `agent_run_events` ledger with no schema change.\n *\n * A logical turn may span several continuation runs (each chunk is its own run\n * sharing one `turn_id`), so we union the events of every run that belongs to\n * the latest turn for this thread. Events are ordered by (started_at, seq) so\n * earlier chunks come before later ones and the positional `tool_start` →\n * `tool_done` matching in the classifier stays correct across chunk boundaries.\n *\n * Returns an empty array when the thread has no run yet or no parseable events.\n * Best-effort on parse: malformed ledger rows are skipped rather than thrown.\n */\nexport async function getCurrentTurnEventsForThread(\n threadId: string,\n): Promise<AgentChatEvent[]> {\n await ensureRunTables();\n const client = getDbExec();\n // Find the latest run for this thread (terminal or running) to learn the\n // logical turn id. The journal is consulted on the resume path, where the\n // just-interrupted run is typically already terminal.\n const latest = await client.execute({\n sql: `SELECT id, turn_id FROM agent_runs WHERE thread_id = ? ORDER BY started_at DESC LIMIT 1`,\n args: [threadId],\n });\n if (latest.rows.length === 0) return [];\n const latestRow = latest.rows[0] as { id: string; turn_id: string | null };\n const turnId = latestRow.turn_id ?? latestRow.id;\n // Gather every run that belongs to this logical turn, oldest chunk first, and\n // read their events in seq order. COALESCE(turn_id, id) folds older rows that\n // predate the turn_id backfill into a turn keyed by their own run id.\n const { rows } = await client.execute({\n sql: `SELECT e.event_data AS event_data\n FROM agent_run_events e\n JOIN agent_runs r ON r.id = e.run_id\n WHERE r.thread_id = ?\n AND COALESCE(r.turn_id, r.id) = ?\n ORDER BY r.started_at ASC, e.seq ASC`,\n args: [threadId, turnId],\n });\n const events: AgentChatEvent[] = [];\n for (const r of rows) {\n const raw = (r as { event_data?: string }).event_data;\n if (!raw) continue;\n try {\n events.push(JSON.parse(raw) as AgentChatEvent);\n } catch {\n // Skip malformed ledger rows — the journal is best-effort.\n }\n }\n return events;\n}\n\n/**\n * Expire any \"running\" rows whose heartbeat is stale — producer died.\n * Safe to call at server startup on multi-isolate deployments: only rows\n * without a fresh heartbeat get reaped, so runs owned by OTHER live\n * isolates (which keep heartbeating) are left alone.\n */\nexport async function reapAllStaleRuns(): Promise<number> {\n await ensureRunTables();\n const client = getDbExec();\n const now = Date.now();\n // Background-dispatched runs use the wider window; everything else 15s.\n const stale = await client.execute({\n sql: `SELECT id FROM agent_runs\n WHERE status = 'running'\n AND COALESCE(heartbeat_at, started_at) < ${backgroundAwareStaleCutoffSql()}`,\n args: [now],\n });\n const completedAt = Date.now();\n const { rowsAffected } = await client.execute({\n sql: `UPDATE agent_runs\n SET status = 'errored',\n completed_at = ?,\n error_code = ?,\n error_detail = ?\n WHERE status = 'running'\n AND COALESCE(heartbeat_at, started_at) < ${backgroundAwareStaleCutoffSql()}`,\n args: [\n completedAt,\n STALE_RUN_ERROR_EVENT.errorCode,\n STALE_RUN_ERROR_EVENT.details,\n completedAt,\n ],\n });\n for (const row of stale.rows) {\n const id = (row as { id?: unknown }).id;\n if (typeof id === \"string\") {\n await safeAppendTerminalRunEvent(\n id,\n STALE_RUN_ERROR_EVENT,\n \"reap-all-stale\",\n );\n }\n }\n return rowsAffected ?? 0;\n}\n\n/** Delete old runs and expire stale \"running\" rows that haven't had activity\n * (e.g. worker crashed before updating status). Completed runs are pruned at\n * `olderThanMs`; errored/aborted runs are kept until `erroredOlderThanMs` (a\n * longer window, falling back to `olderThanMs`) so their event log survives\n * for cut-off pattern analysis via listErroredRuns. */\nexport async function cleanupOldRuns(\n olderThanMs: number,\n erroredOlderThanMs?: number,\n): Promise<void> {\n await ensureRunTables();\n const client = getDbExec();\n const cutoff = Date.now() - olderThanMs;\n const erroredCutoff =\n Date.now() - Math.max(erroredOlderThanMs ?? 0, olderThanMs);\n // Expire stale running rows on the absolute-age threshold — safety net\n // for runs that never received a heartbeat (very old deployments). The\n // SELECT covers BOTH UPDATE conditions so the terminal-event-append loop\n // below catches every row we're about to flip — a 24h-old row with a\n // somehow-fresh heartbeat would slip past a heartbeat-only SELECT.\n const now = Date.now();\n const stale = await client.execute({\n sql: `SELECT id FROM agent_runs\n WHERE status = 'running'\n AND (\n COALESCE(heartbeat_at, started_at) < ${backgroundAwareStaleCutoffSql()}\n OR started_at < ?\n )`,\n args: [now, cutoff],\n });\n const completedAt = Date.now();\n await client.execute({\n sql: `UPDATE agent_runs\n SET status = 'errored',\n completed_at = ?,\n error_code = ?,\n error_detail = ?\n WHERE status = 'running' AND started_at < ?`,\n args: [\n completedAt,\n STALE_RUN_ERROR_EVENT.errorCode,\n STALE_RUN_ERROR_EVENT.details,\n cutoff,\n ],\n });\n // Also expire runs whose heartbeat is stale — producer has died. Uses the\n // background-aware window so a slow background cold-start isn't reaped early.\n await client.execute({\n sql: `UPDATE agent_runs\n SET status = 'errored',\n completed_at = ?,\n error_code = ?,\n error_detail = ?\n WHERE status = 'running'\n AND COALESCE(heartbeat_at, started_at) < ${backgroundAwareStaleCutoffSql()}`,\n args: [\n completedAt,\n STALE_RUN_ERROR_EVENT.errorCode,\n STALE_RUN_ERROR_EVENT.details,\n completedAt,\n ],\n });\n for (const row of stale.rows) {\n const id = (row as { id?: unknown }).id;\n if (typeof id === \"string\") {\n await safeAppendTerminalRunEvent(\n id,\n STALE_RUN_ERROR_EVENT,\n \"cleanup-old-runs\",\n );\n }\n }\n // Delete events for old terminal runs. Completed runs prune at `cutoff`;\n // errored/aborted runs are retained until the (longer) `erroredCutoff`.\n await client.execute({\n sql: `DELETE FROM agent_run_events WHERE run_id IN (\n SELECT id FROM agent_runs\n WHERE (status = 'completed' AND completed_at < ?)\n OR (status IN ('errored', 'aborted') AND completed_at < ?)\n )`,\n args: [cutoff, erroredCutoff],\n });\n await client.execute({\n sql: `DELETE FROM agent_runs\n WHERE (status = 'completed' AND completed_at < ?)\n OR (status IN ('errored', 'aborted') AND completed_at < ?)`,\n args: [cutoff, erroredCutoff],\n });\n}\n\n/**\n * List recent errored/aborted runs for cut-off pattern analysis. Read-only,\n * bounded, and ordered newest-first. Surfaced via the list-errored-runs action\n * so the team can see why chats are failing (terminal error code, duration,\n * turn linkage) instead of discovering it ad hoc.\n */\nexport async function listErroredRuns(options?: {\n limit?: number;\n sinceMs?: number;\n}): Promise<\n Array<{\n id: string;\n threadId: string;\n turnId: string | null;\n status: string;\n errorCode: string | null;\n errorDetail: string | null;\n startedAt: number;\n completedAt: number | null;\n durationMs: number | null;\n }>\n> {\n await ensureRunTables();\n const client = getDbExec();\n const limit = Math.min(Math.max(Math.floor(options?.limit ?? 100), 1), 1000);\n const since =\n options?.sinceMs && options.sinceMs > 0 ? Date.now() - options.sinceMs : 0;\n const { rows } = await client.execute({\n sql: `SELECT id, thread_id, turn_id, status, error_code, error_detail, started_at, completed_at\n FROM agent_runs\n WHERE status IN ('errored', 'aborted')\n AND COALESCE(completed_at, started_at) >= ?\n ORDER BY COALESCE(completed_at, started_at) DESC\n LIMIT ${limit}`,\n args: [since],\n });\n return rows.map((r) => {\n const row = r as {\n id: string;\n thread_id: string;\n turn_id: string | null;\n status: string;\n error_code: string | null;\n error_detail: string | null;\n started_at: number | string;\n completed_at: number | string | null;\n };\n const startedAt = Number(row.started_at);\n const completedAt =\n row.completed_at == null ? null : Number(row.completed_at);\n return {\n id: row.id,\n threadId: row.thread_id,\n turnId: row.turn_id ?? null,\n status: row.status,\n errorCode: row.error_code ?? null,\n errorDetail: row.error_detail ?? null,\n startedAt,\n completedAt,\n durationMs: completedAt == null ? null : completedAt - startedAt,\n };\n });\n}\n\n/**\n * Idempotently append a terminal event to a run's event stream. No-op if the\n * stream already ends in a terminal event. Used by reapers AND by SSE\n * reconnect paths that discover an `errored` run row with no terminal event\n * (e.g. an earlier reaper's silent `.catch(() => {})` swallowed the append).\n *\n * Persisting from the reconnect path is what keeps the system self-healing:\n * subsequent reconnects replay the proper terminal event from SQL instead of\n * synthesizing a fresh one each time.\n */\nexport async function ensureTerminalRunEvent(\n runId: string,\n event: Record<string, unknown>,\n): Promise<void> {\n return appendTerminalRunEvent(runId, event);\n}\n\n/**\n * Append a terminal run event, retrying once on failure and reporting to\n * Sentry if both attempts fail. Background reaper paths can't surface errors\n * to a user, but they MUST eventually persist a terminal event — losing it\n * leaves reconnecting clients staring at a bare `status='errored'` row with\n * no payload to render. The previous `.catch(() => {})` callsites silently\n * dropped transient SQL blips and produced exactly that bug. Never throws.\n */\nasync function safeAppendTerminalRunEvent(\n runId: string,\n event: Record<string, unknown>,\n source: string,\n): Promise<void> {\n let firstError: unknown;\n try {\n await appendTerminalRunEvent(runId, event);\n return;\n } catch (err) {\n firstError = err;\n }\n // Brief backoff — most \"transient\" SQL failures (connection blip, lock\n // contention) clear within a couple hundred ms.\n await new Promise<void>((resolve) => setTimeout(resolve, 100));\n try {\n await appendTerminalRunEvent(runId, event);\n } catch (retryErr) {\n captureError(retryErr, {\n tags: {\n component: \"agent-run-store\",\n operation: \"append-terminal-event\",\n source,\n },\n extra: {\n runId,\n eventType: typeof event.type === \"string\" ? event.type : \"(unknown)\",\n firstError:\n firstError instanceof Error ? firstError.message : String(firstError),\n },\n });\n }\n}\n\nasync function appendTerminalRunEvent(\n runId: string,\n event: Record<string, unknown>,\n): Promise<void> {\n await ensureRunTables();\n const client = getDbExec();\n const { rows } = await client.execute({\n sql: `SELECT seq, event_data FROM agent_run_events WHERE run_id = ? ORDER BY seq DESC LIMIT 1`,\n args: [runId],\n });\n const last = rows[0] as\n | { seq?: number | string; event_data?: string }\n | undefined;\n if (last?.event_data) {\n try {\n const parsed = JSON.parse(last.event_data);\n if (\n parsed?.type === \"done\" ||\n parsed?.type === \"error\" ||\n parsed?.type === \"missing_api_key\" ||\n parsed?.type === \"loop_limit\" ||\n parsed?.type === \"auto_continue\"\n ) {\n return;\n }\n } catch {\n // Ignore malformed rows and append the terminal event.\n }\n }\n const nextSeq = last ? Number(last.seq ?? -1) + 1 : 0;\n await client.execute({\n sql: `INSERT INTO agent_run_events (run_id, seq, event_data) VALUES (?, ?, ?) ON CONFLICT (run_id, seq) DO NOTHING`,\n args: [runId, nextSeq, JSON.stringify(event)],\n });\n}\n"]}
1
+ {"version":3,"file":"run-store.js","sourceRoot":"","sources":["../../src/agent/run-store.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * SQL persistence for agent runs and events.\n * Enables cross-isolate access on Cloudflare Workers and\n * reliable reconnection after page refreshes.\n */\nimport { getDbExec, intType, isPostgres } from \"../db/client.js\";\nimport { ensureColumnExists, ensureTableExists } from \"../db/ddl-guard.js\";\nimport { widenIntColumnsToBigInt } from \"../db/widen-columns.js\";\nimport { captureError } from \"../server/capture-error.js\";\nimport type { AgentChatEvent } from \"./types.js\";\n\nlet _initPromise: Promise<void> | undefined;\n\n/**\n * Max time without a heartbeat before a \"running\" run is considered dead.\n * The run-manager heartbeats every 1.5s, so 15s tolerates ~9 missed writes.\n * Widened from 6s to absorb real-world DB latency spikes and GC pauses that\n * caused false-positive reaps: a live run whose heartbeat lagged 6s+ would be\n * reaped and a zombie would keep running, eventually clobbering the new row.\n */\nexport const RUN_STALE_MS = 15_000;\n\n/**\n * Stale window for runs dispatched into a Netlify background function\n * (`dispatch_mode = 'background'`). The design doc flags the 15s reaper vs a\n * background cold-start as the #1 false-failure risk: the foreground POST\n * inserts the `running` row, then `fireInternalDispatch` returns 202 and the\n * background function may take >15s to cold-start and emit its first heartbeat.\n * With the normal 15s window the reaper would falsely kill that freshly-\n * inserted-but-not-yet-heartbeaten row. 90s tolerates a slow background\n * cold-start while still reaping a genuinely dead background worker promptly.\n *\n * Only applied to rows explicitly marked background-dispatched; ordinary\n * foreground runs keep the tight 15s window unchanged.\n */\nexport const BACKGROUND_RUN_STALE_MS = 90_000;\n\nexport const STALE_RUN_ERROR_EVENT = {\n type: \"error\",\n error:\n \"The agent stopped before it could finish. It may have hit a server timeout or the worker may have been interrupted.\",\n errorCode: \"stale_run\",\n recoverable: true,\n details:\n \"The run heartbeat stopped while the run was still marked running. Partial output and tool calls were preserved when available.\",\n} as const;\n\n/**\n * Terminal error for a background-dispatched run whose worker NEVER claimed it\n * (the foreground fired the self-dispatch, Netlify acked it async with a 202,\n * but the `_process-run` worker never ran far enough to flip\n * `dispatch_mode background → background-processing`). Distinct errorCode so the\n * client (and prod triage) can tell \"the worker died silently\" apart from \"a\n * claimed worker's heartbeat went stale\". Recoverable so the client surfaces a\n * retry affordance and re-drives the turn. See `reapUnclaimedBackgroundRun`.\n */\nexport const UNCLAIMED_BACKGROUND_RUN_ERROR_EVENT = {\n type: \"error\",\n error:\n \"The agent run was handed off to a background worker that never started. It was recovered so you can try again.\",\n errorCode: \"background_worker_never_started\",\n recoverable: true,\n details:\n \"A background-dispatched run was acknowledged (HTTP 202) but its worker never claimed the run, so no progress was produced. The run was reaped early (it had no live worker to protect) so the turn can be retried.\",\n} as const;\n\n/**\n * Terminal error for a background worker that DID claim the run, then failed\n * during route/handler setup before `startRun` could emit its own error event.\n * Claimed runs are no longer eligible for foreground inline recovery, so the\n * route boundary must fail them loudly instead of leaving subscribers to wait\n * for stale-run recovery.\n */\nexport const CLAIMED_BACKGROUND_WORKER_FAILED_ERROR_EVENT = {\n type: \"error\",\n error:\n \"The background agent worker stopped before it could start the turn. You can retry from the preserved chat context.\",\n errorCode: \"background_worker_failed\",\n recoverable: true,\n details:\n \"The durable background worker claimed the run but threw during setup before it could emit agent events.\",\n} as const;\n\n/**\n * Grace period before a never-claimed background run (dispatch_mode still\n * 'background', no worker claim) is treated as a dead handoff and reaped.\n *\n * This is intentionally MUCH tighter than `BACKGROUND_RUN_STALE_MS` (90s). The\n * wide 90s window exists ONLY to protect a CLAIMED worker whose heartbeat lags\n * during a slow cold start. A run that is still `dispatch_mode = 'background'`\n * has, by definition, NO worker — nothing to protect — so once a Netlify\n * background function has had a reasonable cold-start window to claim it and\n * hasn't, the handoff is dead and should surface promptly instead of leaving\n * the user staring at a spinner for 90s. 25s comfortably exceeds a normal\n * Netlify Lambda cold start while still failing fast on a silent worker death.\n */\nexport const UNCLAIMED_BACKGROUND_RUN_GRACE_MS = 25_000;\n\nasync function ensureRunTables(): Promise<void> {\n if (!_initPromise) {\n _initPromise = (async () => {\n const client = getDbExec();\n\n // Shared CREATE SQL strings — referenced by both the Postgres and SQLite\n // branches so the column definitions stay in one place.\n const agentRunsCreateSql = `\n CREATE TABLE IF NOT EXISTS agent_runs (\n id TEXT PRIMARY KEY,\n thread_id TEXT NOT NULL,\n status TEXT NOT NULL DEFAULT 'running',\n abort_reason TEXT,\n started_at ${intType()} NOT NULL,\n completed_at ${intType()},\n heartbeat_at ${intType()},\n last_progress_at ${intType()},\n turn_id TEXT,\n error_code TEXT,\n error_detail TEXT,\n dispatch_mode TEXT,\n diag_stage TEXT\n )\n `;\n const agentRunEventsCreateSql = `\n CREATE TABLE IF NOT EXISTS agent_run_events (\n run_id TEXT NOT NULL,\n seq ${intType()} NOT NULL,\n event_data TEXT NOT NULL,\n PRIMARY KEY (run_id, seq)\n )\n `;\n // Tool-call result ledger: persists the outcome of write tool calls that\n // completed AFTER their chunk was abandoned (zombie completions). A\n // resumed continuation can recover the real result by matching\n // thread_id + tool_key (name:stableInputHash) instead of re-executing\n // the side effect. Entries are scoped to the thread and expire with it.\n const agentToolLedgerCreateSql = `\n CREATE TABLE IF NOT EXISTS agent_tool_ledger (\n thread_id TEXT NOT NULL,\n tool_key TEXT NOT NULL,\n result_summary TEXT NOT NULL,\n completed_at ${intType()} NOT NULL,\n PRIMARY KEY (thread_id, tool_key)\n )\n `;\n\n if (isPostgres()) {\n // Hot path: in production the tables and all additive columns are\n // virtually always already present. Issuing `CREATE TABLE`/`ALTER TABLE\n // ADD COLUMN` still takes an ACCESS EXCLUSIVE lock — which, in a fresh\n // background-worker process behind a concurrent connection on the shared\n // Neon DB, can block ~indefinitely. So check `information_schema` first\n // (plain reads, no lock) and run DDL ONLY for what is actually missing.\n // The `ensureTableExists` / `ensureColumnExists` wrappers probe →\n // guarded-DDL (bounded `lock_timeout`) → re-probe, and THROW if the\n // schema is still missing after a swallowed lock-timeout so a poisoned\n // init never memoizes success against absent schema (the `_initPromise`\n // rejects and the next call retries).\n await ensureTableExists(\"agent_runs\", agentRunsCreateSql);\n // Additive columns — all listed in the CREATE TABLE above, so on a\n // fresh DB they already exist after the CREATE and these checks are\n // instant short-circuits. On an older deployment that predates a\n // column, the wrapper issues one bounded ALTER.\n //\n // Backfill heartbeat_at on older deployments.\n // heartbeat_at = \"the producer process is alive\" (bumped on a timer).\n // last_progress_at = \"the agent is actually emitting events\" (bumped on\n // each emit). The gap between them is the stuck-detector signal.\n for (const [col, colType] of [\n [\"heartbeat_at\", intType()],\n [\"abort_reason\", \"TEXT\"],\n [\"last_progress_at\", intType()],\n // Backfill turn_id / error_code / error_detail.\n // turn_id = stable identity for one logical assistant turn that may\n // span several continuation runs, so the durable record\n // can be folded across runs instead of dropped per-run.\n // error_code / error_detail = terminal failure classification captured\n // at completion so errored/cut-off runs are queryable for\n // pattern analysis (see listErroredRuns).\n // dispatch_mode marks how a run was started: NULL/\"foreground\" for the\n // normal synchronous path, \"background\" for a run dispatched into a\n // Netlify background function. The reaper/claim widen the stale window\n // for background rows so a slow cold-start isn't falsely reaped.\n // diag_stage records the last reached pipeline stage (+ any error) for a\n // background-dispatched run so a silent worker death is DIAGNOSABLE from\n // the client (/runs/active surfaces it) without reading the unreadable\n // Netlify background-function logs. See recordRunDiagnostic.\n [\"turn_id\", \"TEXT\"],\n [\"error_code\", \"TEXT\"],\n [\"error_detail\", \"TEXT\"],\n [\"dispatch_mode\", \"TEXT\"],\n [\"diag_stage\", \"TEXT\"],\n [\"worker_stage\", \"TEXT\"],\n ] as const) {\n await ensureColumnExists(\n \"agent_runs\",\n col,\n `ALTER TABLE agent_runs ADD COLUMN IF NOT EXISTS ${col} ${colType}`,\n );\n }\n await ensureTableExists(\"agent_run_events\", agentRunEventsCreateSql);\n await ensureTableExists(\"agent_tool_ledger\", agentToolLedgerCreateSql);\n // Widen millisecond-timestamp columns that older deployments created as\n // 32-bit `INTEGER`. `insertRun()` writes `Date.now()` into `started_at`\n // on every turn, so an int4 column makes every agent prompt fail on\n // Postgres with \"value … is out of range for type integer\". No-op once\n // widened (and on fresh DBs that already use BIGINT). See\n // widenIntColumnsToBigInt.\n await widenIntColumnsToBigInt(\"agent_runs\", [\n \"started_at\",\n \"completed_at\",\n \"heartbeat_at\",\n \"last_progress_at\",\n ]);\n await widenIntColumnsToBigInt(\"agent_tool_ledger\", [\"completed_at\"]);\n return;\n }\n\n // SQLite (local dev): no ACCESS EXCLUSIVE lock problem — keep the\n // original create-then-additive-alter behaviour. SQLite has no\n // `ADD COLUMN IF NOT EXISTS`, so the ALTERs stay wrapped in try/catch.\n await client.execute(agentRunsCreateSql);\n // Backfill heartbeat_at on older deployments.\n try {\n await client.execute(\n `ALTER TABLE agent_runs ADD COLUMN heartbeat_at ${intType()}`,\n );\n } catch {\n // Column already exists — ignore\n }\n try {\n await client.execute(\n `ALTER TABLE agent_runs ADD COLUMN abort_reason TEXT`,\n );\n } catch {\n // Column already exists — ignore\n }\n // Backfill last_progress_at — this is distinct from heartbeat_at.\n // heartbeat_at = \"the producer process is alive\" (bumped on a timer).\n // last_progress_at = \"the agent is actually emitting events\" (bumped on\n // each emit). The gap between them is the stuck-detector signal.\n try {\n await client.execute(\n `ALTER TABLE agent_runs ADD COLUMN last_progress_at ${intType()}`,\n );\n } catch {\n // Column already exists — ignore\n }\n // Backfill turn_id / error_code / error_detail.\n // turn_id = stable identity for one logical assistant turn that may\n // span several continuation runs, so the durable record\n // can be folded across runs instead of dropped per-run.\n // error_code / error_detail = terminal failure classification captured\n // at completion so errored/cut-off runs are queryable for\n // pattern analysis (see listErroredRuns).\n // dispatch_mode marks how a run was started: NULL/\"foreground\" for the\n // normal synchronous path, \"background\" for a run dispatched into a\n // Netlify background function. The reaper/claim widen the stale window\n // for background rows so a slow cold-start isn't falsely reaped.\n // diag_stage records the last reached pipeline stage (+ any error) for a\n // background-dispatched run so a silent worker death is DIAGNOSABLE from\n // the client (/runs/active surfaces it) without reading the unreadable\n // Netlify background-function logs. See recordRunDiagnostic.\n for (const col of [\n \"turn_id\",\n \"error_code\",\n \"error_detail\",\n \"dispatch_mode\",\n \"diag_stage\",\n \"worker_stage\",\n ] as const) {\n try {\n await client.execute(`ALTER TABLE agent_runs ADD COLUMN ${col} TEXT`);\n } catch {\n // Column already exists — ignore\n }\n }\n await client.execute(agentRunEventsCreateSql);\n await client.execute(agentToolLedgerCreateSql);\n // Widen millisecond-timestamp columns that older deployments created as\n // 32-bit `INTEGER`. `insertRun()` writes `Date.now()` into `started_at`\n // on every turn, so an int4 column makes every agent prompt fail on\n // Postgres with \"value … is out of range for type integer\". No-op once\n // widened (and on fresh DBs that already use BIGINT). See\n // widenIntColumnsToBigInt.\n await widenIntColumnsToBigInt(\"agent_runs\", [\n \"started_at\",\n \"completed_at\",\n \"heartbeat_at\",\n \"last_progress_at\",\n ]);\n await widenIntColumnsToBigInt(\"agent_tool_ledger\", [\"completed_at\"]);\n })().catch((err) => {\n // Retry init on the next call after a failed startup.\n _initPromise = undefined;\n throw err;\n });\n }\n return _initPromise;\n}\n\n// ─── Tool-call result ledger ─────────────────────────────────────────────────\n//\n// When the run-level abort signal fires (soft timeout / user cancel) while a\n// write tool is in-flight, `Promise.race` abandons the call — but the action's\n// Promise continues running in the background (a \"zombie\"). If the zombie\n// resolves before the continuation's next tool dispatch, we record the result\n// here so the continuation can recover it without re-executing the side effect.\n//\n// Keyed by (thread_id, tool_key) where tool_key = \"<toolName>:<stableJsonHash>\".\n// The write is fire-and-forget from the hot path; reads are synchronous look-\n// ups at the start of each write-tool dispatch in the continuation.\n\n/** Max length for a persisted result summary (8 KB). */\nconst LEDGER_RESULT_MAX_CHARS = 8_000;\n\n/**\n * Persist a zombie tool-call completion to the ledger. Called by the detached\n * promise continuation after `Promise.race` abandons it. Best-effort — never\n * throws so a ledger write failure doesn't break any caller.\n */\nexport async function writeLedgerEntry(\n threadId: string,\n toolKey: string,\n resultSummary: string,\n): Promise<void> {\n try {\n await ensureRunTables();\n const client = getDbExec();\n const capped =\n resultSummary.length > LEDGER_RESULT_MAX_CHARS\n ? resultSummary.slice(0, LEDGER_RESULT_MAX_CHARS) +\n `\\n...[ledger truncated at ${LEDGER_RESULT_MAX_CHARS} chars]`\n : resultSummary;\n await client.execute({\n sql: `INSERT INTO agent_tool_ledger (thread_id, tool_key, result_summary, completed_at)\n VALUES (?, ?, ?, ?)\n ON CONFLICT (thread_id, tool_key) DO UPDATE SET\n result_summary = excluded.result_summary,\n completed_at = excluded.completed_at`,\n args: [threadId, toolKey, capped, Date.now()],\n });\n } catch {\n // Ledger is best-effort; never surface failures to the caller.\n }\n}\n\n/**\n * Look up a prior zombie completion for this thread + tool key. Returns the\n * persisted result summary, or `null` when no entry exists.\n */\nexport async function readLedgerEntry(\n threadId: string,\n toolKey: string,\n): Promise<string | null> {\n try {\n await ensureRunTables();\n const client = getDbExec();\n const { rows } = await client.execute({\n sql: `SELECT result_summary FROM agent_tool_ledger WHERE thread_id = ? AND tool_key = ?`,\n args: [threadId, toolKey],\n });\n if (rows.length === 0) return null;\n const row = rows[0] as { result_summary: string };\n return row.result_summary;\n } catch {\n return null;\n }\n}\n\n/**\n * Delete ledger entries for a thread. Called after a turn fully completes so\n * old entries don't bleed into the next turn's disambiguation.\n * Best-effort — never throws.\n */\nexport async function clearLedgerForThread(threadId: string): Promise<void> {\n try {\n await ensureRunTables();\n const client = getDbExec();\n await client.execute({\n sql: `DELETE FROM agent_tool_ledger WHERE thread_id = ?`,\n args: [threadId],\n });\n } catch {\n // Best-effort.\n }\n}\n\nexport async function insertRun(\n id: string,\n threadId: string,\n turnId?: string,\n options?: { dispatchMode?: \"foreground\" | \"background\" },\n): Promise<void> {\n await ensureRunTables();\n const client = getDbExec();\n const now = Date.now();\n await client.execute({\n sql: `INSERT INTO agent_runs (id, thread_id, status, started_at, heartbeat_at, last_progress_at, turn_id, dispatch_mode) VALUES (?, ?, 'running', ?, ?, ?, ?, ?)`,\n args: [\n id,\n threadId,\n now,\n now,\n now,\n turnId ?? id,\n options?.dispatchMode ?? null,\n ],\n });\n}\n\n/**\n * SQL fragment that resolves the per-row stale cutoff. Background-dispatched\n * runs (`dispatch_mode` starting with `background`) tolerate a much longer gap\n * without a heartbeat (slow Netlify background-function cold-start) before being\n * reaped; every other run keeps the tight 15s window. The bound `now` is\n * subtracted by the resolved window so the comparison is\n * `COALESCE(heartbeat_at, started_at) < (now - window)`.\n *\n * `dispatch_mode` is one of NULL/\"foreground\" (normal sync path), \"background\"\n * (foreground inserted the row for a background dispatch), or\n * \"background-processing\" (the background worker claimed it). Both background\n * states get the wider window via a LIKE-prefix match.\n */\nfunction backgroundAwareStaleCutoffSql(): string {\n // `CAST(? AS BIGINT)` is required: without it Postgres infers the param as\n // int4 from the int4 window literals, so the bound `Date.now()` ms epoch\n // overflows int4. The cast keeps the subtraction 64-bit; a no-op on SQLite.\n return `(CAST(? AS BIGINT) - CASE WHEN dispatch_mode LIKE 'background%' THEN ${BACKGROUND_RUN_STALE_MS} ELSE ${RUN_STALE_MS} END)`;\n}\n\n/**\n * Atomically claim a background-dispatched run for processing. The foreground\n * POST inserts the run row with `dispatch_mode = 'background'`; the FIRST\n * delivery of the background dispatch flips it to `background-processing` and\n * wins the claim. A duplicate Netlify delivery (background functions can be\n * retried) sees `background-processing` and loses, so it no-ops — mirroring\n * `claimAgentTeamRun` returning null. Returns true when this caller won.\n *\n * Idempotent and conditional: the WHERE clause only matches the unclaimed\n * `background` state AND a still-running row, so a reaped/terminal row can't be\n * re-claimed.\n */\nexport async function claimBackgroundRun(runId: string): Promise<boolean> {\n await ensureRunTables();\n const client = getDbExec();\n const { rowsAffected } = await client.execute({\n sql: `UPDATE agent_runs\n SET dispatch_mode = 'background-processing'\n WHERE id = ?\n AND status = 'running'\n AND dispatch_mode = 'background'`,\n args: [runId],\n });\n return (rowsAffected ?? 0) > 0;\n}\n\n/**\n * Read the claim/lifecycle state of a single run by id — for the foreground\n * circuit-breaker that confirms a background worker actually CLAIMED a run that\n * was dispatched with a Netlify async 202. A 202 only means the invocation was\n * ENQUEUED; if the generated background-function wrapper fails to import/hand off\n * to the route it never reaches `claimBackgroundRun`, leaving the row stuck at\n * `dispatch_mode = 'background'`. `'background-processing'` means a worker won\n * the claim; a terminal `status` means the run already resolved. Returns null if\n * the row is missing.\n */\nexport async function readBackgroundRunClaim(runId: string): Promise<{\n dispatchMode: string | null;\n status: string | null;\n diagStage: string | null;\n workerStage: string | null;\n lastLivenessAt: number | null;\n} | null> {\n await ensureRunTables();\n const client = getDbExec();\n const { rows } = await client.execute({\n sql: `SELECT dispatch_mode, status, diag_stage, worker_stage, started_at, heartbeat_at FROM agent_runs WHERE id = ? LIMIT 1`,\n args: [runId],\n });\n const row = rows?.[0] as\n | {\n dispatch_mode?: string | null;\n status?: string | null;\n diag_stage?: string | null;\n worker_stage?: string | null;\n started_at?: number | null;\n heartbeat_at?: number | null;\n }\n | undefined;\n if (!row) return null;\n return {\n dispatchMode: row.dispatch_mode ?? null,\n status: row.status ?? null,\n diagStage: row.diag_stage ?? null,\n workerStage: row.worker_stage ?? null,\n // Same liveness basis the unclaimed-reaper uses (COALESCE(heartbeat_at,\n // started_at)), so the foreground can decide to recover BEFORE the reaper.\n lastLivenessAt: row.heartbeat_at ?? row.started_at ?? null,\n };\n}\n\n/**\n * Resolve the authenticated owner email for a run by joining it to its chat\n * thread. The durable background worker's self-dispatch is cookieless\n * (HMAC-only — see `AGENT_CHAT_PROCESS_RUN_PATH`), so it has no session for the\n * normal owner resolution and would otherwise be treated as unauthenticated.\n * The thread's `owner_email` was written by the authenticated foreground when it\n * created the thread, so it is a trusted, non-forgeable owner source: only the\n * HMAC-signed `runId` selects the row, and the caller cannot influence which\n * owner that row maps to. Returns null when the run (or its thread) is missing.\n */\nexport async function getRunOwnerEmail(runId: string): Promise<string | null> {\n await ensureRunTables();\n const client = getDbExec();\n const { rows } = await client.execute({\n sql: `SELECT t.owner_email AS owner_email FROM agent_runs r JOIN chat_threads t ON r.thread_id = t.id WHERE r.id = ? LIMIT 1`,\n args: [runId],\n });\n const row = rows?.[0] as { owner_email?: string | null } | undefined;\n return row?.owner_email ?? null;\n}\n\n/**\n * Atomically acquire a run lease for a thread. Succeeds (returns true) only\n * when no other run for the same thread is currently status='running' with a\n * fresh heartbeat. Works for both Postgres and SQLite: the stale-cutoff\n * comparison lets a dead producer's run be replaced without waiting for the\n * reaper, mirroring the logic in `reapIfStale`.\n *\n * Callers that win the claim then insert the run row normally; callers that\n * lose skip the run and return the existing active runId to the caller.\n */\nexport async function tryClaimRunSlot(\n threadId: string,\n maxStaleMs?: number,\n): Promise<{ claimed: boolean; activeRunId: string | null }> {\n await ensureRunTables();\n const client = getDbExec();\n const now = Date.now();\n // Default: per-row background-aware window so a live background run (which can\n // legitimately go >15s between heartbeats during a cold-start) isn't seen as\n // \"free\" and double-claimed by a racing foreground POST. An explicit\n // `maxStaleMs` override keeps a flat window for callers that want one.\n if (typeof maxStaleMs === \"number\") {\n const heartbeatCutoff = now - maxStaleMs;\n const { rows } = await client.execute({\n sql: `SELECT id FROM agent_runs\n WHERE thread_id = ?\n AND status = 'running'\n AND COALESCE(heartbeat_at, started_at) >= ?\n ORDER BY started_at DESC LIMIT 1`,\n args: [threadId, heartbeatCutoff],\n });\n if (rows.length > 0) {\n return { claimed: false, activeRunId: (rows[0] as { id: string }).id };\n }\n return { claimed: true, activeRunId: null };\n }\n const { rows } = await client.execute({\n sql: `SELECT id FROM agent_runs\n WHERE thread_id = ?\n AND status = 'running'\n AND COALESCE(heartbeat_at, started_at) >= ${backgroundAwareStaleCutoffSql()}\n ORDER BY started_at DESC LIMIT 1`,\n args: [threadId, now],\n });\n if (rows.length > 0) {\n const row = rows[0] as { id: string };\n return { claimed: false, activeRunId: row.id };\n }\n return { claimed: true, activeRunId: null };\n}\n\n/**\n * Record terminal failure classification for a run so cut-off / errored runs\n * can be surfaced for pattern analysis (see listErroredRuns). Best-effort —\n * never throws, since it runs on the completion path that must not fail the run.\n */\nexport async function setRunError(\n runId: string,\n errorCode: string | undefined,\n errorDetail: string | undefined,\n): Promise<void> {\n if (!errorCode && !errorDetail) return;\n try {\n await ensureRunTables();\n const client = getDbExec();\n await client.execute({\n sql: `UPDATE agent_runs SET error_code = ?, error_detail = ? WHERE id = ?`,\n args: [\n errorCode ?? null,\n errorDetail ? errorDetail.slice(0, 2000) : null,\n runId,\n ],\n });\n } catch {\n // Diagnostics are best-effort; never let them break completion.\n }\n}\n\n/**\n * Diagnostic stage names recorded onto a background run as it moves through the\n * `_process-run` worker pipeline. Each value is the LAST stage successfully\n * reached, so a stuck run's `diag_stage` reveals exactly where it died. Ordered\n * roughly by execution; the literal strings are the client-readable contract.\n */\nexport const RUN_DIAG_STAGE = {\n /** The `_process-run` route handler was entered (the request reached Nitro). */\n routeEntered: \"route_entered\",\n /** HMAC auth + body validation in prepareProcessRunRequest FAILED. */\n authFailed: \"auth_failed\",\n /** HMAC auth + body validation PASSED; about to invoke the worker handler. */\n authPassed: \"auth_passed\",\n /** The re-entered agent-chat handler recognized itself as the bg worker. */\n workerEntered: \"worker_entered\",\n /** The worker won the atomic claim (it owns the run). */\n workerClaimed: \"worker_claimed\",\n /** The worker LOST the claim (a duplicate delivery already owns the run). */\n workerClaimLost: \"worker_claim_lost\",\n /** The agent loop started (startRun fired). */\n workerStarted: \"worker_started\",\n /** Last worker setup stage reached before startRun (progressive hang localizer). */\n workerSetupStep: \"worker_setup_step\",\n /** Pre-claim setup timing breakdown (diagnostic). */\n setupTimings: \"setup_timings\",\n /** The worker threw before/while running the loop (message carried in detail). */\n workerThrew: \"worker_threw\",\n /** The route handler caught an error from the worker invocation. */\n routeThrew: \"route_threw\",\n /**\n * The foreground circuit-breaker fired: a Netlify async 202 was returned but\n * no background worker CLAIMED the run within the foreground grace window\n * (the generated function wrapper never reached the route), so the foreground\n * recovered by running the turn inline. The run still completes for the user.\n */\n foregroundInlineRecovery: \"foreground_inline_recovery\",\n} as const;\n\nexport type RunDiagStage = (typeof RUN_DIAG_STAGE)[keyof typeof RUN_DIAG_STAGE];\n\n/**\n * Record the last reached pipeline stage (+ optional short detail) for a run.\n *\n * PURPOSE: a Netlify background function's logs are not readable from the build\n * tooling, so when its worker dies silently the run just times out with no clue\n * WHY. This writes the failure stage straight onto the `agent_runs` row, which\n * `/runs/active` and `listRunsForThread` surface to the client — so the next\n * prod run's death cause is readable WITHOUT bg-fn logs. Cheap, additive, and\n * best-effort: it must never throw or perturb the run (it is called on the auth\n * path BEFORE a 401 is returned, and around the worker body).\n *\n * The stored value is a compact JSON `{ stage, detail?, at }` capped to 2 KB so\n * a long stack can't bloat the row.\n */\nexport async function recordRunDiagnostic(\n runId: string,\n stage: RunDiagStage,\n detail?: string,\n): Promise<void> {\n if (!runId) return;\n try {\n await ensureRunTables();\n const client = getDbExec();\n const payload = JSON.stringify({\n stage,\n ...(detail ? { detail: detail.slice(0, 1500) } : {}),\n at: Date.now(),\n }).slice(0, 2000);\n // Worker-setup stages ALSO land in `worker_stage`, a column the foreground's\n // inline-recovery `setup_timings` write never touches. `/runs/active` only\n // surfaces a run after it is claimed, and the foreground then overwrites\n // `diag_stage` — so without this the durable worker's pre-claim progression\n // (where it stalled before claiming) is unrecoverable. `worker_stage`\n // preserves the last worker stage reached for post-hoc diagnosis.\n const isWorkerStage =\n stage === RUN_DIAG_STAGE.workerSetupStep ||\n stage === RUN_DIAG_STAGE.workerStarted;\n if (isWorkerStage) {\n await client.execute({\n sql: `UPDATE agent_runs SET diag_stage = ?, worker_stage = ? WHERE id = ?`,\n args: [payload, payload, runId],\n });\n } else {\n await client.execute({\n sql: `UPDATE agent_runs SET diag_stage = ? WHERE id = ?`,\n args: [payload, runId],\n });\n }\n } catch {\n // Diagnostics are best-effort; never let them break the run or the route.\n }\n}\n\n/** Update the run's liveness heartbeat. Called periodically by run-manager. */\nexport async function updateRunHeartbeat(runId: string): Promise<void> {\n await ensureRunTables();\n const client = getDbExec();\n await client.execute({\n sql: `UPDATE agent_runs SET heartbeat_at = ? WHERE id = ?`,\n args: [Date.now(), runId],\n });\n}\n\n/**\n * Bump `last_progress_at` — call this whenever the agent actually emits an\n * event (token, tool call, message). Distinct from `heartbeat_at` so the\n * stuck-detector can tell \"process alive but nothing happening\" from\n * \"process dead.\" Callers should throttle (run-manager debounces to ~1/s).\n */\nexport async function bumpRunProgress(runId: string): Promise<void> {\n await ensureRunTables();\n const client = getDbExec();\n await client.execute({\n sql: `UPDATE agent_runs SET last_progress_at = ? WHERE id = ?`,\n args: [Date.now(), runId],\n });\n}\n\n/**\n * If the given run is marked \"running\" in SQL but its heartbeat is stale\n * (producer likely crashed), flip it to \"errored\" so watchers stop waiting.\n * Returns true if the row was reaped.\n */\nexport async function reapIfStale(\n runId: string,\n maxStaleMs?: number,\n): Promise<boolean> {\n await ensureRunTables();\n const client = getDbExec();\n const completedAt = Date.now();\n // Background-dispatched runs get the wider stale window so a slow cold-start\n // isn't reaped; foreground runs keep the tight 15s window. An explicit\n // override forces a flat window for callers that want one.\n const staleClause =\n typeof maxStaleMs === \"number\"\n ? `COALESCE(heartbeat_at, started_at) < ?`\n : `COALESCE(heartbeat_at, started_at) < ${backgroundAwareStaleCutoffSql()}`;\n const staleArgs =\n typeof maxStaleMs === \"number\" ? [completedAt - maxStaleMs] : [completedAt];\n const { rowsAffected } = await client.execute({\n sql: `UPDATE agent_runs\n SET status = 'errored',\n completed_at = ?,\n error_code = ?,\n error_detail = ?\n WHERE id = ?\n AND status = 'running'\n AND ${staleClause}`,\n args: [\n completedAt,\n STALE_RUN_ERROR_EVENT.errorCode,\n STALE_RUN_ERROR_EVENT.details,\n runId,\n ...staleArgs,\n ],\n });\n const reaped = (rowsAffected ?? 0) > 0;\n if (reaped) {\n await safeAppendTerminalRunEvent(\n runId,\n STALE_RUN_ERROR_EVENT,\n \"reap-if-stale\",\n );\n }\n return reaped;\n}\n\n/**\n * FALLBACK HARDENING for the \"dispatched with 202 but the worker never started\"\n * case. A background-dispatched run sits in `dispatch_mode = 'background'` until\n * the worker wins `claimBackgroundRun` (which flips it to\n * `background-processing`). If the worker silently dies (e.g. the bg-fn 401s\n * before it can claim), the row stays `background`, never heartbeats again, and\n * — because dispatch returned 202 — the foreground already returned the SSE\n * stream, so the existing fast-fail inline fallback never engaged. The run would\n * otherwise hang for the full 90s background window and then error opaquely.\n *\n * This reaps such a run EARLY and DISTINCTLY: a row that is still unclaimed\n * (`dispatch_mode = 'background'`) past the tight `UNCLAIMED_BACKGROUND_RUN_GRACE_MS`\n * grace is a dead handoff — there is no live worker to protect with the wide\n * window — so we flip it to `errored` with the recoverable\n * `background_worker_never_started` code. The client's existing recoverable-error\n * path then lets the user (or auto-recovery) re-drive the turn. Idempotent and\n * conditional: only an unclaimed, still-running, grace-exceeded row matches, so a\n * claimed worker, a fresh dispatch, or a terminal row is never touched.\n *\n * Returns true when this call reaped the run.\n */\nexport async function reapUnclaimedBackgroundRun(\n runId: string,\n): Promise<boolean> {\n await ensureRunTables();\n const client = getDbExec();\n const completedAt = Date.now();\n const cutoff = completedAt - UNCLAIMED_BACKGROUND_RUN_GRACE_MS;\n const { rowsAffected } = await client.execute({\n sql: `UPDATE agent_runs\n SET status = 'errored',\n completed_at = ?,\n error_code = ?,\n error_detail = ?\n WHERE id = ?\n AND status = 'running'\n AND dispatch_mode = 'background'\n AND COALESCE(heartbeat_at, started_at) < ?`,\n args: [\n completedAt,\n UNCLAIMED_BACKGROUND_RUN_ERROR_EVENT.errorCode,\n UNCLAIMED_BACKGROUND_RUN_ERROR_EVENT.details,\n runId,\n cutoff,\n ],\n });\n const reaped = (rowsAffected ?? 0) > 0;\n if (reaped) {\n await recordRunDiagnostic(\n runId,\n RUN_DIAG_STAGE.workerThrew,\n \"unclaimed background dispatch reaped (worker never claimed the run)\",\n );\n await safeAppendTerminalRunEvent(\n runId,\n UNCLAIMED_BACKGROUND_RUN_ERROR_EVENT,\n \"reap-unclaimed-background\",\n );\n }\n return reaped;\n}\n\nexport async function updateRunStatus(\n runId: string,\n status: \"completed\" | \"errored\" | \"aborted\",\n): Promise<void> {\n await ensureRunTables();\n const client = getDbExec();\n await client.execute({\n sql: `UPDATE agent_runs SET status = ?, completed_at = ? WHERE id = ?`,\n args: [status, Date.now(), runId],\n });\n}\n\n/**\n * Conditional terminal status write: only updates if the row still belongs to\n * this run AND is still status='running'. Returns true when the update landed.\n *\n * This is the safe variant used by the producer's finally block so a zombie run\n * (reaped while executing) can never clobber the status written by the reaper\n * or a replacement run.\n */\nexport async function updateRunStatusIfRunning(\n runId: string,\n status: \"completed\" | \"errored\" | \"aborted\",\n): Promise<boolean> {\n await ensureRunTables();\n const client = getDbExec();\n const { rowsAffected } = await client.execute({\n sql: `UPDATE agent_runs SET status = ?, completed_at = ? WHERE id = ? AND status = 'running'`,\n args: [status, Date.now(), runId],\n });\n return (rowsAffected ?? 0) > 0;\n}\n\n/** Read the current status of a run row. Returns null when the row is missing. */\nexport async function getRunStatus(runId: string): Promise<string | null> {\n await ensureRunTables();\n const client = getDbExec();\n const { rows } = await client.execute({\n sql: `SELECT status FROM agent_runs WHERE id = ?`,\n args: [runId],\n });\n if (rows.length === 0) return null;\n return String((rows[0] as { status: string }).status);\n}\n\nexport async function markRunAborted(\n runId: string,\n reason?: string,\n): Promise<void> {\n await ensureRunTables();\n const client = getDbExec();\n await client.execute({\n sql: `UPDATE agent_runs SET status = 'aborted', abort_reason = ?, completed_at = ? WHERE id = ?`,\n args: [reason ?? \"user\", Date.now(), runId],\n });\n await safeAppendTerminalRunEvent(runId, { type: \"done\" }, \"mark-aborted\");\n}\n\nexport async function isRunAborted(runId: string): Promise<boolean> {\n return (await getRunAbortState(runId)).aborted;\n}\n\nexport async function getRunAbortState(\n runId: string,\n): Promise<{ aborted: boolean; reason?: string }> {\n await ensureRunTables();\n const client = getDbExec();\n const { rows } = await client.execute({\n sql: `SELECT status, abort_reason FROM agent_runs WHERE id = ?`,\n args: [runId],\n });\n if (rows.length === 0) return { aborted: false };\n const row = rows[0] as { status: string; abort_reason?: string | null };\n if (row.status !== \"aborted\") return { aborted: false };\n return {\n aborted: true,\n ...(row.abort_reason ? { reason: row.abort_reason } : {}),\n };\n}\n\nexport async function insertRunEvent(\n runId: string,\n seq: number,\n eventData: string,\n): Promise<void> {\n await ensureRunTables();\n const client = getDbExec();\n // ON CONFLICT DO NOTHING: a (runId, seq) collision can happen on the\n // soft-timeout / terminal-event path where `pendingTerminalEvent` was\n // assigned a seq that later gets reused by an event pushed after it.\n // It can also race with `appendTerminalRunEvent` (max-seq + 1) when a\n // run aborts at the same time the producer emits its final event.\n // Treat the second write as a no-op so the run completes cleanly.\n await client.execute({\n sql: `INSERT INTO agent_run_events (run_id, seq, event_data) VALUES (?, ?, ?) ON CONFLICT (run_id, seq) DO NOTHING`,\n args: [runId, seq, eventData],\n });\n}\n\nexport async function getRunEventsSince(\n runId: string,\n fromSeq: number,\n): Promise<Array<{ seq: number; eventData: string }>> {\n await ensureRunTables();\n const client = getDbExec();\n const { rows } = await client.execute({\n sql: `SELECT seq, event_data FROM agent_run_events WHERE run_id = ? AND seq >= ? ORDER BY seq ASC`,\n args: [runId, fromSeq],\n });\n return rows.map((r) => {\n const row = r as { seq: number | string; event_data: string };\n return { seq: Number(row.seq), eventData: row.event_data };\n });\n}\n\nexport async function getRunById(runId: string): Promise<{\n id: string;\n threadId: string;\n status: string;\n startedAt: number;\n} | null> {\n await ensureRunTables();\n const client = getDbExec();\n const { rows } = await client.execute({\n sql: `SELECT id, thread_id, status, started_at FROM agent_runs WHERE id = ?`,\n args: [runId],\n });\n if (rows.length === 0) return null;\n const r = rows[0] as {\n id: string;\n thread_id: string;\n status: string;\n started_at: number | string;\n };\n return {\n id: r.id,\n threadId: r.thread_id,\n status: r.status,\n startedAt: Number(r.started_at),\n };\n}\n\nexport async function getRunByThread(\n threadId: string,\n options?: { includeTerminal?: boolean },\n): Promise<{\n id: string;\n threadId: string;\n turnId?: string | null;\n status: string;\n startedAt: number;\n heartbeatAt: number | null;\n completedAt: number | null;\n lastProgressAt: number | null;\n dispatchMode: string | null;\n diagStage: string | null;\n} | null> {\n await ensureRunTables();\n const client = getDbExec();\n const sql = options?.includeTerminal\n ? `SELECT id, thread_id, turn_id, status, started_at, heartbeat_at, completed_at, last_progress_at, dispatch_mode, diag_stage FROM agent_runs WHERE thread_id = ? ORDER BY started_at DESC LIMIT 1`\n : `SELECT id, thread_id, turn_id, status, started_at, heartbeat_at, completed_at, last_progress_at, dispatch_mode, diag_stage FROM agent_runs WHERE thread_id = ? AND status = 'running' ORDER BY started_at DESC LIMIT 1`;\n const { rows } = await client.execute({ sql, args: [threadId] });\n if (rows.length === 0) return null;\n const r = rows[0] as {\n id: string;\n thread_id: string;\n turn_id?: string | null;\n status: string;\n started_at: number | string;\n heartbeat_at: number | string | null;\n completed_at: number | string | null;\n last_progress_at: number | string | null;\n dispatch_mode?: string | null;\n diag_stage?: string | null;\n };\n return {\n id: r.id,\n threadId: r.thread_id,\n turnId: r.turn_id ?? null,\n status: r.status,\n startedAt: Number(r.started_at),\n heartbeatAt: r.heartbeat_at == null ? null : Number(r.heartbeat_at),\n completedAt: r.completed_at == null ? null : Number(r.completed_at),\n lastProgressAt:\n r.last_progress_at == null ? null : Number(r.last_progress_at),\n dispatchMode: r.dispatch_mode ?? null,\n diagStage: r.diag_stage ?? null,\n };\n}\n\nexport interface AgentRunSummary {\n id: string;\n threadId: string;\n turnId: string | null;\n status: string;\n startedAt: number;\n heartbeatAt: number | null;\n completedAt: number | null;\n lastProgressAt: number | null;\n errorCode: string | null;\n abortReason: string | null;\n dispatchMode: string | null;\n /** Last reached `_process-run` worker stage (JSON `{stage,detail?,at}`). */\n diagStage: string | null;\n}\n\nexport async function listRunsForThread(\n threadId: string,\n options: { limit?: number } = {},\n): Promise<AgentRunSummary[]> {\n await ensureRunTables();\n const limit = Math.min(Math.max(options.limit ?? 10, 1), 50);\n const client = getDbExec();\n const { rows } = await client.execute({\n sql: `SELECT id, thread_id, turn_id, status, started_at, heartbeat_at, completed_at, last_progress_at, error_code, abort_reason, dispatch_mode, diag_stage\n FROM agent_runs\n WHERE thread_id = ?\n ORDER BY started_at DESC\n LIMIT ?`,\n args: [threadId, limit],\n });\n return rows.map((r) => {\n const row = r as {\n id: string;\n thread_id: string;\n turn_id?: string | null;\n status: string;\n started_at: number | string;\n heartbeat_at?: number | string | null;\n completed_at?: number | string | null;\n last_progress_at?: number | string | null;\n error_code?: string | null;\n abort_reason?: string | null;\n dispatch_mode?: string | null;\n diag_stage?: string | null;\n };\n return {\n id: row.id,\n threadId: row.thread_id,\n turnId: row.turn_id ?? null,\n status: row.status,\n startedAt: Number(row.started_at),\n heartbeatAt: row.heartbeat_at == null ? null : Number(row.heartbeat_at),\n completedAt: row.completed_at == null ? null : Number(row.completed_at),\n lastProgressAt:\n row.last_progress_at == null ? null : Number(row.last_progress_at),\n errorCode: row.error_code ?? null,\n abortReason: row.abort_reason ?? null,\n dispatchMode: row.dispatch_mode ?? null,\n diagStage: row.diag_stage ?? null,\n };\n });\n}\n\n/**\n * Read the current logical turn's recorded events for a thread, parsed into\n * `AgentChatEvent`s in seq order, for per-turn tool-call journal classification\n * (see `tool-call-journal.ts`). Read-only and additive — reuses the existing\n * `agent_runs` / `agent_run_events` ledger with no schema change.\n *\n * A logical turn may span several continuation runs (each chunk is its own run\n * sharing one `turn_id`), so we union the events of every run that belongs to\n * the latest turn for this thread. Events are ordered by (started_at, seq) so\n * earlier chunks come before later ones and the positional `tool_start` →\n * `tool_done` matching in the classifier stays correct across chunk boundaries.\n *\n * Returns an empty array when the thread has no run yet or no parseable events.\n * Best-effort on parse: malformed ledger rows are skipped rather than thrown.\n */\nexport async function getCurrentTurnEventsForThread(\n threadId: string,\n): Promise<AgentChatEvent[]> {\n await ensureRunTables();\n const client = getDbExec();\n // Find the latest run for this thread (terminal or running) to learn the\n // logical turn id. The journal is consulted on the resume path, where the\n // just-interrupted run is typically already terminal.\n const latest = await client.execute({\n sql: `SELECT id, turn_id FROM agent_runs WHERE thread_id = ? ORDER BY started_at DESC LIMIT 1`,\n args: [threadId],\n });\n if (latest.rows.length === 0) return [];\n const latestRow = latest.rows[0] as { id: string; turn_id: string | null };\n const turnId = latestRow.turn_id ?? latestRow.id;\n // Gather every run that belongs to this logical turn, oldest chunk first, and\n // read their events in seq order. COALESCE(turn_id, id) folds older rows that\n // predate the turn_id backfill into a turn keyed by their own run id.\n const { rows } = await client.execute({\n sql: `SELECT e.event_data AS event_data\n FROM agent_run_events e\n JOIN agent_runs r ON r.id = e.run_id\n WHERE r.thread_id = ?\n AND COALESCE(r.turn_id, r.id) = ?\n ORDER BY r.started_at ASC, e.seq ASC`,\n args: [threadId, turnId],\n });\n const events: AgentChatEvent[] = [];\n for (const r of rows) {\n const raw = (r as { event_data?: string }).event_data;\n if (!raw) continue;\n try {\n events.push(JSON.parse(raw) as AgentChatEvent);\n } catch {\n // Skip malformed ledger rows — the journal is best-effort.\n }\n }\n return events;\n}\n\n/**\n * Expire any \"running\" rows whose heartbeat is stale — producer died.\n * Safe to call at server startup on multi-isolate deployments: only rows\n * without a fresh heartbeat get reaped, so runs owned by OTHER live\n * isolates (which keep heartbeating) are left alone.\n */\nexport async function reapAllStaleRuns(): Promise<number> {\n await ensureRunTables();\n const client = getDbExec();\n const now = Date.now();\n // Background-dispatched runs use the wider window; everything else 15s.\n const stale = await client.execute({\n sql: `SELECT id FROM agent_runs\n WHERE status = 'running'\n AND COALESCE(heartbeat_at, started_at) < ${backgroundAwareStaleCutoffSql()}`,\n args: [now],\n });\n const completedAt = Date.now();\n const { rowsAffected } = await client.execute({\n sql: `UPDATE agent_runs\n SET status = 'errored',\n completed_at = ?,\n error_code = ?,\n error_detail = ?\n WHERE status = 'running'\n AND COALESCE(heartbeat_at, started_at) < ${backgroundAwareStaleCutoffSql()}`,\n args: [\n completedAt,\n STALE_RUN_ERROR_EVENT.errorCode,\n STALE_RUN_ERROR_EVENT.details,\n completedAt,\n ],\n });\n for (const row of stale.rows) {\n const id = (row as { id?: unknown }).id;\n if (typeof id === \"string\") {\n await safeAppendTerminalRunEvent(\n id,\n STALE_RUN_ERROR_EVENT,\n \"reap-all-stale\",\n );\n }\n }\n return rowsAffected ?? 0;\n}\n\n/** Delete old runs and expire stale \"running\" rows that haven't had activity\n * (e.g. worker crashed before updating status). Completed runs are pruned at\n * `olderThanMs`; errored/aborted runs are kept until `erroredOlderThanMs` (a\n * longer window, falling back to `olderThanMs`) so their event log survives\n * for cut-off pattern analysis via listErroredRuns. */\nexport async function cleanupOldRuns(\n olderThanMs: number,\n erroredOlderThanMs?: number,\n): Promise<void> {\n await ensureRunTables();\n const client = getDbExec();\n const cutoff = Date.now() - olderThanMs;\n const erroredCutoff =\n Date.now() - Math.max(erroredOlderThanMs ?? 0, olderThanMs);\n // Expire stale running rows on the absolute-age threshold — safety net\n // for runs that never received a heartbeat (very old deployments). The\n // SELECT covers BOTH UPDATE conditions so the terminal-event-append loop\n // below catches every row we're about to flip — a 24h-old row with a\n // somehow-fresh heartbeat would slip past a heartbeat-only SELECT.\n const now = Date.now();\n const stale = await client.execute({\n sql: `SELECT id FROM agent_runs\n WHERE status = 'running'\n AND (\n COALESCE(heartbeat_at, started_at) < ${backgroundAwareStaleCutoffSql()}\n OR started_at < ?\n )`,\n args: [now, cutoff],\n });\n const completedAt = Date.now();\n await client.execute({\n sql: `UPDATE agent_runs\n SET status = 'errored',\n completed_at = ?,\n error_code = ?,\n error_detail = ?\n WHERE status = 'running' AND started_at < ?`,\n args: [\n completedAt,\n STALE_RUN_ERROR_EVENT.errorCode,\n STALE_RUN_ERROR_EVENT.details,\n cutoff,\n ],\n });\n // Also expire runs whose heartbeat is stale — producer has died. Uses the\n // background-aware window so a slow background cold-start isn't reaped early.\n await client.execute({\n sql: `UPDATE agent_runs\n SET status = 'errored',\n completed_at = ?,\n error_code = ?,\n error_detail = ?\n WHERE status = 'running'\n AND COALESCE(heartbeat_at, started_at) < ${backgroundAwareStaleCutoffSql()}`,\n args: [\n completedAt,\n STALE_RUN_ERROR_EVENT.errorCode,\n STALE_RUN_ERROR_EVENT.details,\n completedAt,\n ],\n });\n for (const row of stale.rows) {\n const id = (row as { id?: unknown }).id;\n if (typeof id === \"string\") {\n await safeAppendTerminalRunEvent(\n id,\n STALE_RUN_ERROR_EVENT,\n \"cleanup-old-runs\",\n );\n }\n }\n // Delete events for old terminal runs. Completed runs prune at `cutoff`;\n // errored/aborted runs are retained until the (longer) `erroredCutoff`.\n await client.execute({\n sql: `DELETE FROM agent_run_events WHERE run_id IN (\n SELECT id FROM agent_runs\n WHERE (status = 'completed' AND completed_at < ?)\n OR (status IN ('errored', 'aborted') AND completed_at < ?)\n )`,\n args: [cutoff, erroredCutoff],\n });\n await client.execute({\n sql: `DELETE FROM agent_runs\n WHERE (status = 'completed' AND completed_at < ?)\n OR (status IN ('errored', 'aborted') AND completed_at < ?)`,\n args: [cutoff, erroredCutoff],\n });\n}\n\n/**\n * List recent errored/aborted runs for cut-off pattern analysis. Read-only,\n * bounded, and ordered newest-first. Surfaced via the list-errored-runs action\n * so the team can see why chats are failing (terminal error code, duration,\n * turn linkage) instead of discovering it ad hoc.\n */\nexport async function listErroredRuns(options?: {\n limit?: number;\n sinceMs?: number;\n}): Promise<\n Array<{\n id: string;\n threadId: string;\n turnId: string | null;\n status: string;\n errorCode: string | null;\n errorDetail: string | null;\n startedAt: number;\n completedAt: number | null;\n durationMs: number | null;\n }>\n> {\n await ensureRunTables();\n const client = getDbExec();\n const limit = Math.min(Math.max(Math.floor(options?.limit ?? 100), 1), 1000);\n const since =\n options?.sinceMs && options.sinceMs > 0 ? Date.now() - options.sinceMs : 0;\n const { rows } = await client.execute({\n sql: `SELECT id, thread_id, turn_id, status, error_code, error_detail, started_at, completed_at\n FROM agent_runs\n WHERE status IN ('errored', 'aborted')\n AND COALESCE(completed_at, started_at) >= ?\n ORDER BY COALESCE(completed_at, started_at) DESC\n LIMIT ${limit}`,\n args: [since],\n });\n return rows.map((r) => {\n const row = r as {\n id: string;\n thread_id: string;\n turn_id: string | null;\n status: string;\n error_code: string | null;\n error_detail: string | null;\n started_at: number | string;\n completed_at: number | string | null;\n };\n const startedAt = Number(row.started_at);\n const completedAt =\n row.completed_at == null ? null : Number(row.completed_at);\n return {\n id: row.id,\n threadId: row.thread_id,\n turnId: row.turn_id ?? null,\n status: row.status,\n errorCode: row.error_code ?? null,\n errorDetail: row.error_detail ?? null,\n startedAt,\n completedAt,\n durationMs: completedAt == null ? null : completedAt - startedAt,\n };\n });\n}\n\n/**\n * Idempotently append a terminal event to a run's event stream. No-op if the\n * stream already ends in a terminal event. Used by reapers AND by SSE\n * reconnect paths that discover an `errored` run row with no terminal event\n * (e.g. an earlier reaper's silent `.catch(() => {})` swallowed the append).\n *\n * Persisting from the reconnect path is what keeps the system self-healing:\n * subsequent reconnects replay the proper terminal event from SQL instead of\n * synthesizing a fresh one each time.\n */\nexport async function ensureTerminalRunEvent(\n runId: string,\n event: Record<string, unknown>,\n): Promise<void> {\n return appendTerminalRunEvent(runId, event);\n}\n\n/**\n * Append a terminal run event, retrying once on failure and reporting to\n * Sentry if both attempts fail. Background reaper paths can't surface errors\n * to a user, but they MUST eventually persist a terminal event — losing it\n * leaves reconnecting clients staring at a bare `status='errored'` row with\n * no payload to render. The previous `.catch(() => {})` callsites silently\n * dropped transient SQL blips and produced exactly that bug. Never throws.\n */\nasync function safeAppendTerminalRunEvent(\n runId: string,\n event: Record<string, unknown>,\n source: string,\n): Promise<void> {\n let firstError: unknown;\n try {\n await appendTerminalRunEvent(runId, event);\n return;\n } catch (err) {\n firstError = err;\n }\n // Brief backoff — most \"transient\" SQL failures (connection blip, lock\n // contention) clear within a couple hundred ms.\n await new Promise<void>((resolve) => setTimeout(resolve, 100));\n try {\n await appendTerminalRunEvent(runId, event);\n } catch (retryErr) {\n captureError(retryErr, {\n tags: {\n component: \"agent-run-store\",\n operation: \"append-terminal-event\",\n source,\n },\n extra: {\n runId,\n eventType: typeof event.type === \"string\" ? event.type : \"(unknown)\",\n firstError:\n firstError instanceof Error ? firstError.message : String(firstError),\n },\n });\n }\n}\n\nasync function appendTerminalRunEvent(\n runId: string,\n event: Record<string, unknown>,\n): Promise<void> {\n await ensureRunTables();\n const client = getDbExec();\n const { rows } = await client.execute({\n sql: `SELECT seq, event_data FROM agent_run_events WHERE run_id = ? ORDER BY seq DESC LIMIT 1`,\n args: [runId],\n });\n const last = rows[0] as\n | { seq?: number | string; event_data?: string }\n | undefined;\n if (last?.event_data) {\n try {\n const parsed = JSON.parse(last.event_data);\n if (\n parsed?.type === \"done\" ||\n parsed?.type === \"error\" ||\n parsed?.type === \"missing_api_key\" ||\n parsed?.type === \"loop_limit\" ||\n parsed?.type === \"auto_continue\"\n ) {\n return;\n }\n } catch {\n // Ignore malformed rows and append the terminal event.\n }\n }\n const nextSeq = last ? Number(last.seq ?? -1) + 1 : 0;\n await client.execute({\n sql: `INSERT INTO agent_run_events (run_id, seq, event_data) VALUES (?, ?, ?) ON CONFLICT (run_id, seq) DO NOTHING`,\n args: [runId, nextSeq, JSON.stringify(event)],\n });\n}\n"]}
@@ -49,11 +49,11 @@ export declare const postAwareness: import("h3").EventHandlerWithFetch<import("h
49
49
  error: string;
50
50
  states?: undefined;
51
51
  } | {
52
- error?: undefined;
53
52
  states: {
54
53
  clientId: number;
55
54
  state: string;
56
55
  }[];
56
+ error?: undefined;
57
57
  }>>;
58
58
  /**
59
59
  * GET /_agent-native/collab/:docId/users
@@ -64,10 +64,10 @@ export declare const getActiveUsers: import("h3").EventHandlerWithFetch<import("
64
64
  error: string;
65
65
  users?: undefined;
66
66
  } | {
67
- error?: undefined;
68
67
  users: {
69
68
  clientId: number;
70
69
  lastSeen: number;
71
70
  }[];
71
+ error?: undefined;
72
72
  }>>;
73
73
  //# sourceMappingURL=awareness.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"awareness.d.ts","sourceRoot":"","sources":["../../src/collab/awareness.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAS3C,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;CAClB;AAOD,eAAO,MAAM,sBAAsB,EAAG,kBAA2B,CAAC;AAElE,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,WAAW,CAAC;IACpB,IAAI,EAAE,kBAAkB,CAAC;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,2EAA2E;IAC3E,MAAM,EAAE,KAAK,CAAC;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACnD,gFAAgF;IAChF,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,sCAAsC;IACtC,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAKD,wBAAgB,mBAAmB,IAAI,YAAY,CAElD;AAED,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,KAAK,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,EAClD,KAAK,CAAC,EAAE,MAAM,EACd,KAAK,CAAC,EAAE,MAAM,GACb,IAAI,CAUN;AAKD,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,CAO1E;AAED,wBAAgB,YAAY,CAAC,GAAG,EAAE,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,GAAG,IAAI,CAOnE;AAUD;;;;;;;GAOG;AACH,eAAO,MAAM,aAAa;;;;;;kBAuCa,MAAM;eAAS,MAAM;;GAa1D,CAAC;AAEH;;;;GAIG;AACH,eAAO,MAAM,cAAc;;;;;;kBAWM,MAAM;kBAAY,MAAM;;GAMvD,CAAC"}
1
+ {"version":3,"file":"awareness.d.ts","sourceRoot":"","sources":["../../src/collab/awareness.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAS3C,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;CAClB;AAOD,eAAO,MAAM,sBAAsB,EAAG,kBAA2B,CAAC;AAElE,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,WAAW,CAAC;IACpB,IAAI,EAAE,kBAAkB,CAAC;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,2EAA2E;IAC3E,MAAM,EAAE,KAAK,CAAC;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACnD,gFAAgF;IAChF,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,sCAAsC;IACtC,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAKD,wBAAgB,mBAAmB,IAAI,YAAY,CAElD;AAED,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,KAAK,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,EAClD,KAAK,CAAC,EAAE,MAAM,EACd,KAAK,CAAC,EAAE,MAAM,GACb,IAAI,CAUN;AAKD,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,CAO1E;AAED,wBAAgB,YAAY,CAAC,GAAG,EAAE,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,GAAG,IAAI,CAOnE;AAUD;;;;;;;GAOG;AACH,eAAO,MAAM,aAAa;;;;;kBAuCa,MAAM;eAAS,MAAM;;;GAa1D,CAAC;AAEH;;;;GAIG;AACH,eAAO,MAAM,cAAc;;;;;kBAWM,MAAM;kBAAY,MAAM;;;GAMvD,CAAC"}
@@ -42,8 +42,8 @@ export declare const postCollabUpdate: import("h3").EventHandlerWithFetch<import
42
42
  */
43
43
  export declare const postCollabText: import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<{
44
44
  ok?: undefined;
45
- error: string;
46
45
  text?: undefined;
46
+ error: string;
47
47
  } | {
48
48
  error?: undefined;
49
49
  ok: boolean;
@@ -11,14 +11,14 @@
11
11
  * DELETE /_agent-native/notifications/:id — delete
12
12
  */
13
13
  export declare function createNotificationsHandler(): import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<"" | import("./types.js").Notification[] | {
14
- error?: undefined;
15
14
  count: number;
16
15
  updated?: undefined;
16
+ error?: undefined;
17
17
  ok?: undefined;
18
18
  } | {
19
- error?: undefined;
20
19
  count?: undefined;
21
20
  updated: number;
21
+ error?: undefined;
22
22
  ok?: undefined;
23
23
  } | {
24
24
  count?: undefined;
@@ -26,9 +26,9 @@ export declare function createNotificationsHandler(): import("h3").EventHandlerW
26
26
  error: string;
27
27
  ok?: undefined;
28
28
  } | {
29
- error?: undefined;
30
29
  count?: undefined;
31
30
  updated?: undefined;
31
+ error?: undefined;
32
32
  ok: boolean;
33
33
  }>>;
34
34
  //# sourceMappingURL=routes.d.ts.map
@@ -42,22 +42,22 @@ export declare function createObservabilityHandler(): import("h3").EventHandlerW
42
42
  avgEvalScore: number;
43
43
  } | {
44
44
  error?: undefined;
45
+ ok?: undefined;
45
46
  summary: import("./types.js").TraceSummary;
46
47
  spans: import("./types.js").TraceSpan[];
47
48
  id?: undefined;
48
- ok?: undefined;
49
49
  } | {
50
50
  error?: undefined;
51
+ ok?: undefined;
51
52
  summary?: undefined;
52
53
  spans?: undefined;
53
54
  id: string;
54
- ok?: undefined;
55
55
  } | {
56
+ ok?: undefined;
56
57
  summary?: undefined;
57
58
  spans?: undefined;
58
59
  id?: undefined;
59
60
  error: any;
60
- ok?: undefined;
61
61
  } | {
62
62
  error?: undefined;
63
63
  summary?: undefined;
@@ -15,7 +15,7 @@ export declare function createProgressHandler(): import("h3").EventHandlerWithFe
15
15
  error: string;
16
16
  ok?: undefined;
17
17
  } | {
18
- error?: undefined;
19
18
  ok: boolean;
19
+ error?: undefined;
20
20
  }>>;
21
21
  //# sourceMappingURL=routes.d.ts.map
@@ -2,6 +2,7 @@ import { type H3Event } from "h3";
2
2
  import { type A2AArtifactResponseOptions, type A2AToolResultSummary } from "../a2a/artifact-response.js";
3
3
  import { type ActionEntry } from "../agent/production-agent.js";
4
4
  import type { AgentRunSummary } from "../agent/run-store.js";
5
+ import { ensureTerminalRunEvent, readBackgroundRunClaim, recordRunDiagnostic, setRunError, updateRunStatusIfRunning } from "../agent/run-store.js";
5
6
  import type { AgentChatAttachment, AgentChatEvent, AgentChatReference, MentionProvider } from "../agent/types.js";
6
7
  import { type ChatThread } from "../chat-threads/store.js";
7
8
  import { McpClientManager } from "../mcp-client/index.js";
@@ -429,6 +430,14 @@ export declare function shouldBlockInProductCodeEditingSurface(input: {
429
430
  type RecurringJobsRuntimeEnvKey = "AGENT_NATIVE_DISABLE_RECURRING_JOBS" | "AGENT_NATIVE_ENABLE_LOCAL_RECURRING_JOBS" | "APP_URL" | "BETTER_AUTH_URL" | "DEPLOY_URL" | "NODE_ENV" | "URL" | "VITE_APP_URL" | "VITE_WORKSPACE_GATEWAY_URL" | "WORKSPACE_GATEWAY_URL";
430
431
  type RecurringJobsRuntimeEnv = Partial<Record<RecurringJobsRuntimeEnvKey, string | undefined>>;
431
432
  export declare function shouldDisableRecurringJobsRuntime(env?: RecurringJobsRuntimeEnv): boolean;
433
+ type AgentChatProcessRunFailureDeps = {
434
+ readBackgroundRunClaim?: typeof readBackgroundRunClaim;
435
+ recordRunDiagnostic?: typeof recordRunDiagnostic;
436
+ setRunError?: typeof setRunError;
437
+ updateRunStatusIfRunning?: typeof updateRunStatusIfRunning;
438
+ ensureTerminalRunEvent?: typeof ensureTerminalRunEvent;
439
+ };
440
+ export declare function finalizeClaimedAgentChatProcessRunFailure(runId: string, err: unknown, deps?: AgentChatProcessRunFailureDeps): Promise<boolean>;
432
441
  export declare function createAgentChatPlugin(options?: AgentChatPluginOptions): NitroPluginDef;
433
442
  /**
434
443
  * Default agent chat plugin with no template-specific actions.