@agent-native/core 0.84.67 → 0.85.0
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.
- package/corpus/README.md +2 -2
- package/corpus/core/CHANGELOG.md +14 -0
- package/corpus/core/docs/content/locales/ar-SA/tracking.mdx +55 -0
- package/corpus/core/docs/content/locales/de-DE/tracking.mdx +55 -0
- package/corpus/core/docs/content/locales/es-ES/tracking.mdx +55 -0
- package/corpus/core/docs/content/locales/fr-FR/tracking.mdx +55 -0
- package/corpus/core/docs/content/locales/hi-IN/tracking.mdx +55 -0
- package/corpus/core/docs/content/locales/ja-JP/tracking.mdx +55 -0
- package/corpus/core/docs/content/locales/ko-KR/tracking.mdx +55 -0
- package/corpus/core/docs/content/locales/pt-BR/tracking.mdx +55 -0
- package/corpus/core/docs/content/locales/zh-CN/tracking.mdx +55 -0
- package/corpus/core/docs/content/locales/zh-TW/tracking.mdx +55 -0
- package/corpus/core/docs/content/tracking.mdx +2 -0
- package/corpus/core/package.json +1 -1
- package/corpus/core/src/agent/production-agent.ts +199 -38
- package/corpus/core/src/agent/run-manager.ts +79 -0
- package/corpus/core/src/agent/run-store.ts +117 -5
- package/corpus/core/src/agent/types.ts +13 -0
- package/corpus/core/src/client/RunStuckBanner.tsx +14 -0
- package/corpus/core/src/client/agent-chat-adapter.ts +475 -0
- package/corpus/core/src/client/analytics.ts +2 -0
- package/corpus/core/src/client/error-format.ts +4 -0
- package/corpus/core/src/client/extensions/ExtensionsSidebarSection.tsx +1 -1
- package/corpus/core/src/client/session-replay.ts +774 -2
- package/corpus/core/src/client/sse-event-processor.ts +65 -9
- package/corpus/core/src/client/use-run-stuck-detection.ts +31 -7
- package/corpus/core/src/db/runtime-diagnostics.ts +331 -0
- package/corpus/core/src/server/agent-chat-plugin.ts +115 -2
- package/corpus/core/src/server/core-routes-plugin.ts +91 -4
- package/corpus/core/src/server/http-response-telemetry.ts +189 -0
- package/corpus/core/src/server/self-dispatch.ts +29 -0
- package/corpus/templates/analytics/.agents/skills/session-replay/SKILL.md +53 -1
- package/corpus/templates/analytics/AGENTS.md +13 -0
- package/corpus/templates/analytics/actions/view-screen.ts +25 -0
- package/corpus/templates/analytics/app/components/layout/Sidebar.tsx +20 -0
- package/corpus/templates/analytics/app/global.css +55 -0
- package/corpus/templates/analytics/app/i18n/zh-TW.ts +100 -1
- package/corpus/templates/analytics/app/i18n-data.ts +1226 -0
- package/corpus/templates/analytics/app/pages/Settings.tsx +3 -0
- package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/EmailReportDialog.tsx +182 -144
- package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/index.tsx +11 -18
- package/corpus/templates/analytics/app/pages/analyses/AnalysisDetail.tsx +11 -18
- package/corpus/templates/analytics/app/pages/sessions/SessionDetailPage.tsx +49 -1
- package/corpus/templates/analytics/app/pages/sessions/SessionDevToolsPanel.tsx +557 -0
- package/corpus/templates/analytics/app/pages/sessions/session-replay-devtools.ts +274 -0
- package/corpus/templates/analytics/app/pages/settings/AlertRulesSettingsCard.tsx +974 -0
- package/corpus/templates/analytics/changelog/2026-07-02-alert-rules-can-now-be-viewed-and-managed-from-settings.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-02-recent-ask-chats-show-a-loading-placeholder-while-your-chat-.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-02-session-replays-now-capture-console-logs-and-network-request.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-02-sharing-status-labels-use-neutral-icons-instead-of-colored-d.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-02-the-session-replay-viewer-has-a-dev-tools-panel-with-console.md +6 -0
- package/corpus/templates/analytics/server/db/schema.ts +3 -0
- package/corpus/templates/analytics/server/jobs/analytics-alerts.ts +4 -0
- package/corpus/templates/analytics/server/lib/analytics-alerts.ts +142 -1
- package/corpus/templates/analytics/server/lib/session-replay-agent-context.ts +369 -8
- package/corpus/templates/analytics/server/lib/session-replay.ts +76 -2
- package/corpus/templates/analytics/server/routes/api/session-replay/agent-diagnostics.json.get.ts +101 -0
- package/corpus/templates/analytics/shared/session-replay-diagnostics.ts +78 -0
- package/corpus/templates/design/app/pages/DesignEditor.tsx +24 -12
- package/corpus/templates/design/changelog/2026-07-02-the-temporary-code-tab-is-hidden-from-the-design-editor-side.md +6 -0
- package/corpus/templates/plan/actions/create-visual-recap.ts +1 -1
- package/corpus/templates/plan/actions/update-local-plan-folder.ts +3 -1
- package/corpus/templates/plan/actions/update-visual-plan.ts +1 -1
- package/corpus/templates/plan/changelog/2026-07-02-trying-to-edit-a-recap-or-plan-you-can-only-view-now-explain.md +6 -0
- package/corpus/templates/plan/server/plans.ts +26 -9
- package/dist/agent/production-agent.d.ts.map +1 -1
- package/dist/agent/production-agent.js +155 -34
- package/dist/agent/production-agent.js.map +1 -1
- package/dist/agent/run-manager.d.ts +29 -0
- package/dist/agent/run-manager.d.ts.map +1 -1
- package/dist/agent/run-manager.js +73 -0
- package/dist/agent/run-manager.js.map +1 -1
- package/dist/agent/run-store.d.ts +41 -0
- package/dist/agent/run-store.d.ts.map +1 -1
- package/dist/agent/run-store.js +100 -4
- package/dist/agent/run-store.js.map +1 -1
- package/dist/agent/types.d.ts +13 -0
- package/dist/agent/types.d.ts.map +1 -1
- package/dist/agent/types.js.map +1 -1
- package/dist/client/RunStuckBanner.d.ts.map +1 -1
- package/dist/client/RunStuckBanner.js +13 -0
- package/dist/client/RunStuckBanner.js.map +1 -1
- package/dist/client/agent-chat-adapter.d.ts.map +1 -1
- package/dist/client/agent-chat-adapter.js +410 -0
- package/dist/client/agent-chat-adapter.js.map +1 -1
- package/dist/client/analytics.d.ts +1 -1
- package/dist/client/analytics.d.ts.map +1 -1
- package/dist/client/analytics.js.map +1 -1
- package/dist/client/error-format.d.ts.map +1 -1
- package/dist/client/error-format.js +2 -0
- package/dist/client/error-format.js.map +1 -1
- package/dist/client/extensions/ExtensionsSidebarSection.js +1 -1
- package/dist/client/extensions/ExtensionsSidebarSection.js.map +1 -1
- package/dist/client/session-replay.d.ts +36 -0
- package/dist/client/session-replay.d.ts.map +1 -1
- package/dist/client/session-replay.js +579 -1
- package/dist/client/session-replay.js.map +1 -1
- package/dist/client/sse-event-processor.d.ts +20 -1
- package/dist/client/sse-event-processor.d.ts.map +1 -1
- package/dist/client/sse-event-processor.js +42 -11
- package/dist/client/sse-event-processor.js.map +1 -1
- package/dist/client/use-run-stuck-detection.d.ts +14 -4
- package/dist/client/use-run-stuck-detection.d.ts.map +1 -1
- package/dist/client/use-run-stuck-detection.js +18 -4
- package/dist/client/use-run-stuck-detection.js.map +1 -1
- package/dist/collab/awareness.d.ts +2 -2
- package/dist/collab/awareness.d.ts.map +1 -1
- package/dist/collab/routes.d.ts +2 -2
- package/dist/db/runtime-diagnostics.d.ts +52 -0
- package/dist/db/runtime-diagnostics.d.ts.map +1 -0
- package/dist/db/runtime-diagnostics.js +250 -0
- package/dist/db/runtime-diagnostics.js.map +1 -0
- package/dist/notifications/routes.d.ts +1 -1
- package/dist/observability/routes.d.ts +3 -3
- package/dist/progress/routes.d.ts +1 -1
- package/dist/provider-api/corpus-jobs.d.ts +2 -2
- package/dist/resources/handlers.d.ts +1 -1
- package/dist/secrets/routes.d.ts +3 -3
- package/dist/server/agent-chat-plugin.d.ts.map +1 -1
- package/dist/server/agent-chat-plugin.js +101 -2
- package/dist/server/agent-chat-plugin.js.map +1 -1
- package/dist/server/core-routes-plugin.d.ts +17 -0
- package/dist/server/core-routes-plugin.d.ts.map +1 -1
- package/dist/server/core-routes-plugin.js +65 -5
- package/dist/server/core-routes-plugin.js.map +1 -1
- package/dist/server/http-response-telemetry.d.ts +4 -0
- package/dist/server/http-response-telemetry.d.ts.map +1 -0
- package/dist/server/http-response-telemetry.js +174 -0
- package/dist/server/http-response-telemetry.js.map +1 -0
- package/dist/server/self-dispatch.d.ts +17 -0
- package/dist/server/self-dispatch.d.ts.map +1 -1
- package/dist/server/self-dispatch.js +11 -0
- package/dist/server/self-dispatch.js.map +1 -1
- package/docs/content/locales/ar-SA/tracking.mdx +55 -0
- package/docs/content/locales/de-DE/tracking.mdx +55 -0
- package/docs/content/locales/es-ES/tracking.mdx +55 -0
- package/docs/content/locales/fr-FR/tracking.mdx +55 -0
- package/docs/content/locales/hi-IN/tracking.mdx +55 -0
- package/docs/content/locales/ja-JP/tracking.mdx +55 -0
- package/docs/content/locales/ko-KR/tracking.mdx +55 -0
- package/docs/content/locales/pt-BR/tracking.mdx +55 -0
- package/docs/content/locales/zh-CN/tracking.mdx +55 -0
- package/docs/content/locales/zh-TW/tracking.mdx +55 -0
- package/docs/content/tracking.mdx +2 -0
- package/package.json +1 -1
|
@@ -32,7 +32,7 @@ import { getDefaultMaxIterations, MAX_AGENT_MAX_ITERATIONS, MIN_AGENT_MAX_ITERAT
|
|
|
32
32
|
import { maybeCompactThread, buildObservationalContext, hasObservationalMemory, serializeObservationalMemoryBlock, } from "./observational-memory/index.js";
|
|
33
33
|
import { ProcessorChain, TripWire, toolCallsFromContent, } from "./processors.js";
|
|
34
34
|
import { startRun, subscribeToRun, getActiveRunForThread, getActiveRunForThreadAsync, getRun, abortRun, tryClaimRunSlot, } from "./run-manager.js";
|
|
35
|
-
import { writeLedgerEntry, readLedgerEntry, clearLedgerForThread, getCurrentTurnEventsForThread, insertRun, updateRunHeartbeat, updateRunStatusIfRunning, setRunTerminalReason, claimBackgroundRun, readBackgroundRunClaim, recordRunDiagnostic, RUN_DIAG_STAGE, UNCLAIMED_BACKGROUND_RUN_GRACE_MS, } from "./run-store.js";
|
|
35
|
+
import { writeLedgerEntry, readLedgerEntry, clearLedgerForThread, getCurrentTurnEventsForThread, insertRun, updateRunHeartbeat, updateRunStatusIfRunning, setRunTerminalReason, claimBackgroundRun, readBackgroundRunClaim, recordRunDiagnostic, countRunsForTurn, RUN_DIAG_STAGE, UNCLAIMED_BACKGROUND_RUN_GRACE_MS, } from "./run-store.js";
|
|
36
36
|
import { classifyToolCallJournal, findCompletedJournalEntry, } from "./tool-call-journal.js";
|
|
37
37
|
import { redactSensitiveFields, sanitizeToolErrorText, sanitizeToolErrorValue, } from "./tool-error-redaction.js";
|
|
38
38
|
import { createToolSearchEntry, TOOL_SEARCH_ACTION_NAME, } from "./tool-search.js";
|
|
@@ -4246,8 +4246,13 @@ export function createProductionAgentHandler(options) {
|
|
|
4246
4246
|
// Insert the run row up front so /runs/active sees it immediately and
|
|
4247
4247
|
// the slot stays held while the background function cold-starts. Mark
|
|
4248
4248
|
// it background-dispatched so the stale reaper uses the wider window.
|
|
4249
|
+
// The full request body is persisted ON the row (dispatch_payload) so
|
|
4250
|
+
// the self-POST below can carry only the tiny marker — Netlify caps
|
|
4251
|
+
// background-function request bodies at 256KB, and a large chat
|
|
4252
|
+
// history (inline attachments especially) silently exceeded that.
|
|
4249
4253
|
await insertRun(runId, effectiveThreadId, effectiveTurnId, {
|
|
4250
4254
|
dispatchMode: "background",
|
|
4255
|
+
dispatchPayload: JSON.stringify(body),
|
|
4251
4256
|
});
|
|
4252
4257
|
backgroundRowInserted = true;
|
|
4253
4258
|
}
|
|
@@ -4275,15 +4280,29 @@ export function createProductionAgentHandler(options) {
|
|
|
4275
4280
|
// the Authorization Bearer HMAC is preserved either way.
|
|
4276
4281
|
path: backgroundDispatchPath,
|
|
4277
4282
|
taskId: runId,
|
|
4278
|
-
|
|
4279
|
-
|
|
4280
|
-
|
|
4281
|
-
|
|
4282
|
-
|
|
4283
|
-
|
|
4284
|
-
|
|
4283
|
+
// When the row (and its persisted payload) landed, send only the
|
|
4284
|
+
// marker — the worker rehydrates the body from dispatch_payload
|
|
4285
|
+
// (`payloadRef`), keeping the self-POST far under Netlify's 256KB
|
|
4286
|
+
// background-function body cap. If the insert failed we fall back to
|
|
4287
|
+
// carrying the full body inline, exactly as before.
|
|
4288
|
+
body: backgroundRowInserted
|
|
4289
|
+
? {
|
|
4290
|
+
[AGENT_CHAT_BACKGROUND_RUN_FIELD]: {
|
|
4291
|
+
runId,
|
|
4292
|
+
turnId: effectiveTurnId,
|
|
4293
|
+
backgroundFunctionRuntimeExpected: expectsNetlifyBackgroundFunction,
|
|
4294
|
+
payloadRef: true,
|
|
4295
|
+
},
|
|
4296
|
+
}
|
|
4297
|
+
: {
|
|
4298
|
+
...body,
|
|
4299
|
+
// Carry the pre-claimed identity so the worker reuses this run.
|
|
4300
|
+
[AGENT_CHAT_BACKGROUND_RUN_FIELD]: {
|
|
4301
|
+
runId,
|
|
4302
|
+
turnId: effectiveTurnId,
|
|
4303
|
+
backgroundFunctionRuntimeExpected: expectsNetlifyBackgroundFunction,
|
|
4304
|
+
},
|
|
4285
4305
|
},
|
|
4286
|
-
},
|
|
4287
4306
|
});
|
|
4288
4307
|
dispatched = true;
|
|
4289
4308
|
}
|
|
@@ -4503,6 +4522,23 @@ export function createProductionAgentHandler(options) {
|
|
|
4503
4522
|
// foreground fallback, which is not a worker and rides the
|
|
4504
4523
|
// connected client's auto_continue instead.)
|
|
4505
4524
|
if (willChainBackgroundContinuation(run)) {
|
|
4525
|
+
// DURABLE PER-TURN LEDGER: bound the total number of runs one
|
|
4526
|
+
// logical turn may consume, counted in SQL. The in-marker
|
|
4527
|
+
// `continuationCount` resets whenever a fresh POST starts a new
|
|
4528
|
+
// chain for the same turn (client recovery, duplicate delivery),
|
|
4529
|
+
// so it cannot bound cross-chain loops — the SQL count survives
|
|
4530
|
+
// every recovery path and is what actually kills a pathological
|
|
4531
|
+
// turn (the "dozens of runs on one prompt" incident class).
|
|
4532
|
+
const turnRunCount = await countRunsForTurn(effectiveThreadId, effectiveTurnId).catch(() => null);
|
|
4533
|
+
if (turnRunCount !== null &&
|
|
4534
|
+
turnRunCount > MAX_BACKGROUND_RUN_CONTINUATIONS + 5) {
|
|
4535
|
+
console.error(`[agent-chat] turn ${effectiveTurnId} consumed ${turnRunCount} runs — refusing to chain further`, runId);
|
|
4536
|
+
const statusUpdated = await updateRunStatusIfRunning(runId, "errored").catch(() => false);
|
|
4537
|
+
if (statusUpdated) {
|
|
4538
|
+
await setRunTerminalReason(runId, "turn_continuation_budget_exhausted").catch(() => { });
|
|
4539
|
+
}
|
|
4540
|
+
return;
|
|
4541
|
+
}
|
|
4506
4542
|
// Mint the next chunk's runId here and sign the dispatch token
|
|
4507
4543
|
// over it, so the `_process-run` route's HMAC check and the
|
|
4508
4544
|
// worker's run identity agree. Fresh runId (not this chunk's) so
|
|
@@ -4513,36 +4549,121 @@ export function createProductionAgentHandler(options) {
|
|
|
4513
4549
|
const continuationReason = backgroundContinuationReasonForRun(run);
|
|
4514
4550
|
const continuationDispatchPath = resolveAgentChatProcessRunDispatchPath();
|
|
4515
4551
|
const continuationExpectsNetlifyBackgroundFunction = dispatchPathTargetsNetlifyBackgroundFunction(continuationDispatchPath);
|
|
4552
|
+
const continuationMarker = {
|
|
4553
|
+
runId: nextRunId,
|
|
4554
|
+
turnId: effectiveTurnId,
|
|
4555
|
+
continuationCount: backgroundContinuationCount + 1,
|
|
4556
|
+
continuationReason,
|
|
4557
|
+
...(actionPreparationTool ? { actionPreparationTool } : {}),
|
|
4558
|
+
backgroundFunctionRuntimeExpected: continuationExpectsNetlifyBackgroundFunction,
|
|
4559
|
+
};
|
|
4560
|
+
// Strip this chunk's own marker before persisting/forwarding —
|
|
4561
|
+
// the next chunk gets the fresh marker above.
|
|
4562
|
+
const continuationBody = {
|
|
4563
|
+
...body,
|
|
4564
|
+
internalContinuation: true,
|
|
4565
|
+
};
|
|
4566
|
+
delete continuationBody[AGENT_CHAT_BACKGROUND_RUN_FIELD];
|
|
4516
4567
|
try {
|
|
4517
4568
|
await recordRunDiagnostic(run.runId, RUN_DIAG_STAGE.workerSetupStep, `chain_dispatch_start nextRunId=${nextRunId} reason=${continuationReason} path=${continuationDispatchPath}`).catch(() => { });
|
|
4518
|
-
|
|
4519
|
-
|
|
4520
|
-
|
|
4521
|
-
|
|
4522
|
-
|
|
4523
|
-
|
|
4524
|
-
|
|
4525
|
-
|
|
4526
|
-
|
|
4527
|
-
|
|
4528
|
-
|
|
4529
|
-
|
|
4569
|
+
// ── TRANSACTIONAL HANDOFF ──────────────────────────────────
|
|
4570
|
+
// 1. Insert the successor row (with its rehydration payload)
|
|
4571
|
+
// BEFORE firing the dispatch, so:
|
|
4572
|
+
// - /runs/active shows an active run continuously across
|
|
4573
|
+
// the chunk boundary (no idle gap for the client to
|
|
4574
|
+
// misread as "the turn ended"), and
|
|
4575
|
+
// - a lost dispatch leaves a row the unclaimed-run sweep
|
|
4576
|
+
// reaps into a LOUD error instead of a silent hang.
|
|
4577
|
+
// 2. Await the dispatch response fully (`awaitResponse`) —
|
|
4578
|
+
// this worker's Lambda is about to finish, and the old
|
|
4579
|
+
// 250ms settle race let a still-in-flight handoff fetch be
|
|
4580
|
+
// killed by the post-return freeze WITHOUT rejecting: the
|
|
4581
|
+
// turn just stopped, silently. A Netlify background
|
|
4582
|
+
// function 202s on enqueue (normally well under a second),
|
|
4583
|
+
// and this chunk has minutes of budget headroom left, so
|
|
4584
|
+
// awaiting is cheap. Retried with backoff for transient
|
|
4585
|
+
// network blips.
|
|
4586
|
+
let nextRowInserted = false;
|
|
4587
|
+
try {
|
|
4588
|
+
await insertRun(nextRunId, effectiveThreadId, effectiveTurnId, {
|
|
4589
|
+
dispatchMode: "background",
|
|
4590
|
+
dispatchPayload: JSON.stringify(continuationBody),
|
|
4591
|
+
});
|
|
4592
|
+
nextRowInserted = true;
|
|
4593
|
+
}
|
|
4594
|
+
catch (insertErr) {
|
|
4595
|
+
await recordRunDiagnostic(run.runId, RUN_DIAG_STAGE.workerSetupStep, `chain_successor_insert_failed nextRunId=${nextRunId} ${insertErr instanceof Error
|
|
4596
|
+
? insertErr.message
|
|
4597
|
+
: String(insertErr)}`).catch(() => { });
|
|
4598
|
+
console.error("[agent-chat] continuation insertRun failed; dispatching with inline body:", insertErr instanceof Error
|
|
4599
|
+
? insertErr.message
|
|
4600
|
+
: insertErr);
|
|
4601
|
+
}
|
|
4602
|
+
const dispatchBody = nextRowInserted
|
|
4603
|
+
? {
|
|
4530
4604
|
internalContinuation: true,
|
|
4531
4605
|
[AGENT_CHAT_BACKGROUND_RUN_FIELD]: {
|
|
4532
|
-
|
|
4533
|
-
|
|
4534
|
-
continuationCount: backgroundContinuationCount + 1,
|
|
4535
|
-
continuationReason,
|
|
4536
|
-
...(actionPreparationTool
|
|
4537
|
-
? { actionPreparationTool }
|
|
4538
|
-
: {}),
|
|
4539
|
-
backgroundFunctionRuntimeExpected: continuationExpectsNetlifyBackgroundFunction,
|
|
4606
|
+
...continuationMarker,
|
|
4607
|
+
payloadRef: true,
|
|
4540
4608
|
},
|
|
4541
|
-
}
|
|
4542
|
-
|
|
4543
|
-
|
|
4544
|
-
:
|
|
4545
|
-
|
|
4609
|
+
}
|
|
4610
|
+
: {
|
|
4611
|
+
...continuationBody,
|
|
4612
|
+
[AGENT_CHAT_BACKGROUND_RUN_FIELD]: continuationMarker,
|
|
4613
|
+
};
|
|
4614
|
+
let dispatched = false;
|
|
4615
|
+
let lastDispatchErr;
|
|
4616
|
+
for (let attempt = 0; attempt < 3 && !dispatched; attempt++) {
|
|
4617
|
+
try {
|
|
4618
|
+
if (attempt > 0) {
|
|
4619
|
+
await new Promise((resolve) => setTimeout(resolve, 500 * 2 ** attempt));
|
|
4620
|
+
// Keep the pre-inserted successor row visibly alive
|
|
4621
|
+
// while we retry: the awaited attempts + backoff can
|
|
4622
|
+
// outlast UNCLAIMED_BACKGROUND_RUN_GRACE_MS (25s), and
|
|
4623
|
+
// without a fresh heartbeat the unclaimed-run reaper /
|
|
4624
|
+
// sweep could error a handoff we are still delivering.
|
|
4625
|
+
if (nextRowInserted) {
|
|
4626
|
+
await updateRunHeartbeat(nextRunId).catch(() => { });
|
|
4627
|
+
}
|
|
4628
|
+
}
|
|
4629
|
+
await fireInternalDispatch({
|
|
4630
|
+
event,
|
|
4631
|
+
// Continuation chunks use the same path resolution as
|
|
4632
|
+
// the initial dispatch: on hosted Netlify the background
|
|
4633
|
+
// function's DEFAULT url (no custom config.path; async
|
|
4634
|
+
// via background:true; never shadowed because
|
|
4635
|
+
// /.netlify/* is excluded from the /* catch-all) so each
|
|
4636
|
+
// chunk keeps the 15-min budget; off-Netlify the
|
|
4637
|
+
// in-process framework route.
|
|
4638
|
+
path: continuationDispatchPath,
|
|
4639
|
+
taskId: nextRunId,
|
|
4640
|
+
body: dispatchBody,
|
|
4641
|
+
awaitResponse: true,
|
|
4642
|
+
responseTimeoutMs: 15_000,
|
|
4643
|
+
});
|
|
4644
|
+
dispatched = true;
|
|
4645
|
+
}
|
|
4646
|
+
catch (dispatchErr) {
|
|
4647
|
+
lastDispatchErr = dispatchErr;
|
|
4648
|
+
console.error(`[agent-chat] background continuation dispatch attempt ${attempt + 1} failed:`, dispatchErr instanceof Error
|
|
4649
|
+
? dispatchErr.message
|
|
4650
|
+
: dispatchErr);
|
|
4651
|
+
}
|
|
4652
|
+
}
|
|
4653
|
+
if (!dispatched) {
|
|
4654
|
+
// The pre-inserted successor row would otherwise sit
|
|
4655
|
+
// unclaimed until the sweep reaps it — error it now so the
|
|
4656
|
+
// failure is immediate and truthful.
|
|
4657
|
+
if (nextRowInserted) {
|
|
4658
|
+
const nextStatusUpdated = await updateRunStatusIfRunning(nextRunId, "errored").catch(() => false);
|
|
4659
|
+
if (nextStatusUpdated) {
|
|
4660
|
+
await setRunTerminalReason(nextRunId, "background_continuation_dispatch_failed").catch(() => { });
|
|
4661
|
+
}
|
|
4662
|
+
}
|
|
4663
|
+
throw lastDispatchErr instanceof Error
|
|
4664
|
+
? lastDispatchErr
|
|
4665
|
+
: new Error(String(lastDispatchErr));
|
|
4666
|
+
}
|
|
4546
4667
|
await recordRunDiagnostic(run.runId, RUN_DIAG_STAGE.workerSetupStep, `chain_dispatch_sent nextRunId=${nextRunId} reason=${continuationReason}`).catch(() => { });
|
|
4547
4668
|
}
|
|
4548
4669
|
catch (chainErr) {
|