Skip to content

feat(tasks): attempt signal, attempt budget, and run deadline - #2274

Open
mattzcarey wants to merge 4 commits into
mainfrom
feat/tasks-attempt-signal-and-budget
Open

mattzcarey wants to merge 4 commits into
mainfrom
feat/tasks-attempt-signal-and-budget

Conversation

@mattzcarey

@mattzcarey mattzcarey commented Sep 14, 2026 •

Copy link
Copy Markdown
Contributor

Why

External harnesses (the first target is flue, whose Cloudflare coordinator we are replatforming onto agents/tasks) run their long work in a Task handler body, the pattern rfc-harness-capability.md prescribes. Three parts of an accepted-work contract were not expressible there:

  • a handler body could not observe cancel() outside step.do (the engine has the attempt signal; TaskStep did not expose it);
  • an attempt whose isolate kept dying replayed immediately and without bound, so a deterministically crashing attempt looped until the memory-limit breaker sealed, and only for memory strikes;
  • there was no wall-clock bound on a run, and #dispatchRun refreshes a held claim indefinitely, so a signal-deaf attempt was never reclaimed while its isolate lived.

A host that keeps its own record of the work also needs to know which run Tasks failed without running its handler.

What

  • step.signal: the attempt-wide AbortSignal, aborted on cancel() and at the run deadline.
  • step.attempt: this execution's claim number (1 on the first attempt; sleep and retry wakes count too). Not what interruptions bounds.
  • run(name, input, { interruptions }): a retry policy for interrupted attempts, in the same TaskRetryConfig shape steps use (limit is total attempts including the first). Named interruptions rather than retries because TasksOptions.retries already means the step defaults. It counts only consecutive interruptions: an attempt that reaches a durable boundary under its own power (a sleep, a step retry park) resets the count, so a long-lived run is never failed for surviving deploys. Between interruptions the run parks on a durable backoff with its own wait reason, interrupted, so a step retry park never reads as an interruption and step.interrupted stays correct under concurrent steps. Reaching limit fails the run with TaskInterruptionsExhaustedError. Omitted, an interruption replays immediately without bound, as today.
  • run(name, input, { deadline }): a parked run's wake is brought forward to the deadline and fails there; a live attempt is settled failed under its generation, its signal aborted with TaskDeadlineExceededError, and any later writes fenced out. Both errors are exported.
  • onError(error, { runId, definition }) for every terminal failure, including those recorded without a handler run (missing definition, spent retry budget, passed deadline, sealed memory-limit breaker). A settlement that lost the generation fence is no longer reported.
  • A handler that catches the cancellation on step.signal, cleans up, and returns normally now settles cancelled, not completed. A deadline at or before the epoch is refused at acceptance.
  • Schema version 2 adds deadline_at, interruptions, and retry_policy (the resolved policy, persisted with the run so later default changes never re-bound in-flight runs); a version 1 table is altered on next start.

Nothing else: no serial lanes, no public driver aperture.

Verification

  • 19 new capability tests: signal on cancel and on cancel caught by the handler; interruption retries (budget spent, backoff park then replay with step.interrupted and step.attempt, immediate replay when omitted, zero-delay policy, both sides of the limit boundary, acceptance → retry_policy → enforcement end to end (via interruptions), no budget spent on a sleep wake, a step retry park with a concurrent step still running, NULL-generation park, cancel and deadline while parked); deadline before acceptance / while parked / over a deaf attempt / over a cooperative attempt (reported once); the v1 → v2 migration; option validation; sealed breaker reaching onError.
  • vitest --project workers src/tests/tasks plus the DDL snapshot (102) and --project chat (545) pass; pnpm run check is green. client-compatibility (2025-11-25) is an unrelated MCP reconnect-timing flake.

- step.signal: the attempt-wide abort signal, for work awaited outside
  step.do (cancel() and the run deadline)
- run(..., { maxAttempts }): cap claims of a run; the reclaim after the
  last permitted attempt fails it with TaskAttemptsExhaustedError
- run(..., { deadline }): wall-clock bound; parked runs wake to fail at
  the deadline, a live attempt is settled over and its signal aborted
- onError(error, { runId, definition }) for every terminal failure,
  including ones recorded without running the handler
- schema version 2 adds max_attempts and deadline_at
@changeset-bot

changeset-bot Bot commented Sep 14, 2026 •

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: f28ffc2

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 2 packages
Name Type
agents Patch
@cloudflare/agent-think Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@agent-think

agent-think Bot commented Sep 14, 2026 •

Copy link
Copy Markdown
Contributor

🟡 agents import sizes

Measured 345 runtime imports as minified bundles. The primary size is gzip; raw minified size is included for diagnosis. An existing import growing by more than 10% is marked red. This report is informational.

Red Yellow Green Unchanged New Removed
0 96 8 239 2 0

Compared a7b29135 with f28ffc2f. Open workflow run.

Changed imports (106)
Status Import Base gzip Head gzip Delta
🟡 agents/tasks#Tasks 8.9 KiB 9.7 KiB +814 B (+8.96%)
🟡 agents#buildAgentUrl 261.8 KiB 262.7 KiB +883 B (+0.33%)
🟡 agents/chat-sdk#defaultThreadShard 261.1 KiB 261.9 KiB +880 B (+0.33%)
🟡 agents/chat-sdk#defaultKeyShard 261.2 KiB 262.0 KiB +877 B (+0.33%)
🟡 agents#unstable_callable 261.2 KiB 262.0 KiB +875 B (+0.33%)
🟡 agents#routeAgentRequest 261.7 KiB 262.6 KiB +876 B (+0.33%)
🟡 agents#routeSubAgentRequest 261.3 KiB 262.2 KiB +867 B (+0.32%)
🟡 agents/chat-sdk#ChatSdkStateAdapter 263.5 KiB 264.3 KiB +874 B (+0.32%)
🟡 agents/chat-sdk#createChatSdkState 263.5 KiB 264.3 KiB +872 B (+0.32%)
🟡 agents/chat-sdk#ChatSdkStateAgent 262.8 KiB 263.7 KiB +868 B (+0.32%)
🟡 agents#AGENT_TOOL_PROGRESS_PART 261.1 KiB 261.9 KiB +860 B (+0.32%)
🟡 agents#createHeaderBasedEmailResolver 261.3 KiB 262.1 KiB +860 B (+0.32%)
🟡 agents#SUB_PREFIX 261.1 KiB 261.9 KiB +857 B (+0.32%)
🟡 agents/workflows#AgentWorkflow 262.4 KiB 263.2 KiB +861 B (+0.32%)
🟡 agents#MessageType 261.2 KiB 262.1 KiB +857 B (+0.32%)
🟡 agents#routeAgentEmail 261.4 KiB 262.2 KiB +857 B (+0.32%)
🟡 agents#isDurableObjectMemoryLimitReset 261.1 KiB 261.9 KiB +854 B (+0.32%)
🟡 agents/workflows#WorkflowRejectedError 261.2 KiB 262.0 KiB +854 B (+0.32%)
🟡 agents#getSubAgentByName 261.4 KiB 262.2 KiB +854 B (+0.32%)
🟡 agents#parseSubAgentPath 261.1 KiB 261.9 KiB +853 B (+0.32%)
🟡 agents#DurableObjectOAuthClientProvider 261.1 KiB 261.9 KiB +852 B (+0.32%)
🟡 agents#DEFAULT_AGENT_STATIC_OPTIONS 261.1 KiB 261.9 KiB +848 B (+0.32%)
🟡 agents#MCP_SERVER_ID_MAX_LENGTH 261.1 KiB 261.9 KiB +848 B (+0.32%)
🟡 agents#callable 261.1 KiB 261.9 KiB +847 B (+0.32%)
🟡 agents#AGENT_TOOL_MILESTONE_PART 261.1 KiB 261.9 KiB +846 B (+0.32%)
🟡 agents#__DO_NOT_USE_WILL_BREAK__withInvocationScope 261.1 KiB 261.9 KiB +845 B (+0.32%)
🟡 agents#getCurrentAgent 261.1 KiB 261.9 KiB +844 B (+0.32%)
🟡 agents#isPlatformTransientError 261.1 KiB 261.9 KiB +843 B (+0.32%)
🟡 agents#isDurableObjectCodeUpdateReset 261.1 KiB 261.9 KiB +843 B (+0.32%)
🟡 agents#__DO_NOT_USE_WILL_BREAK__agentContext 261.1 KiB 261.9 KiB +842 B (+0.31%)
🟡 agents#camelCaseToKebabCase 261.1 KiB 261.9 KiB +842 B (+0.31%)
🟡 agents#getAgentByName 261.1 KiB 261.9 KiB +842 B (+0.31%)
🟡 agents#SqlError 261.1 KiB 261.9 KiB +842 B (+0.31%)
🟡 agents#Agent 261.1 KiB 261.9 KiB +840 B (+0.31%)
🟡 agents#StreamingResponse 261.1 KiB 261.9 KiB +839 B (+0.31%)
🟡 agents#buildAgentPath 261.7 KiB 262.5 KiB +840 B (+0.31%)
🟡 agents#normalizeServerId 261.1 KiB 261.9 KiB +835 B (+0.31%)
🟡 agents#isDurableObjectStorageReset 261.1 KiB 261.9 KiB +814 B (+0.3%)
🟡 agents/tasks#MissingTaskDefinitionError 358 B 359 B +1 B (+0.28%)
🟡 agents/mcp#MCP_SERVER_ID_MAX_LENGTH 345.1 KiB 346.0 KiB +912 B (+0.26%)
🟡 agents/mcp#getMcpAuthContext 345.1 KiB 346.0 KiB +892 B (+0.25%)
🟡 agents/mcp#McpAgent 345.1 KiB 346.0 KiB +890 B (+0.25%)
🟡 agents/mcp#SSEEdgeClientTransport 345.2 KiB 346.1 KiB +890 B (+0.25%)
🟡 agents/mcp#RPC_DO_PREFIX 345.1 KiB 346.0 KiB +885 B (+0.25%)
🟡 agents/mcp#DurableObjectEventStore 345.1 KiB 346.0 KiB +877 B (+0.25%)
🟡 agents/mcp#StreamableHTTPEdgeClientTransport 345.2 KiB 346.1 KiB +872 B (+0.25%)
🟡 agents/mcp#normalizeServerId 345.1 KiB 346.0 KiB +871 B (+0.25%)
🟡 agents/mcp#RPCClientTransport 345.1 KiB 346.0 KiB +871 B (+0.25%)
🟡 agents/mcp#RPCServerTransport 345.1 KiB 346.0 KiB +871 B (+0.25%)
🟡 agents/mcp#ElicitRequestSchema 345.1 KiB 346.0 KiB +854 B (+0.24%)
🟡 agents/mcp#WorkerTransport 348.5 KiB 349.4 KiB +854 B (+0.24%)
🟡 agents/mcp#experimental_createMcpHandler 378.7 KiB 379.6 KiB +850 B (+0.22%)
🟡 agents/mcp#createLegacyMcpHandler 378.6 KiB 379.4 KiB +833 B (+0.21%)
🟡 agents/mcp#createMcpHandler 390.9 KiB 391.7 KiB +827 B (+0.21%)
🟡 agents/chat#createChatFiberSnapshot 2.5 KiB 2.5 KiB +2 B (+0.08%)
🟡 agents/chat#aiSdkRecoveryCodec 2.3 KiB 2.3 KiB +1 B (+0.04%)
🟡 agents/chat#CHAT_RECOVERY_ALARM_DEBOUNCE_MS 2.3 KiB 2.3 KiB +1 B (+0.04%)
🟡 agents/chat#CHAT_RECOVERY_INCIDENT_TTL_MS 2.3 KiB 2.3 KiB +1 B (+0.04%)
🟡 agents/chat#DEFAULT_CHAT_RECOVERY_NO_PROGRESS_TIMEOUT_MS 2.3 KiB 2.3 KiB +1 B (+0.04%)
🟡 agents/chat#normalizeToolInput 2.3 KiB 2.3 KiB +1 B (+0.04%)
🟡 agents/chat#applyChunkToParts 2.3 KiB 2.3 KiB +1 B (+0.04%)
🟡 agents/chat#CHAT_MESSAGE_TYPES 2.3 KiB 2.3 KiB +1 B (+0.04%)
🟡 agents/chat#DEFAULT_CHAT_RECOVERY_MAX_ATTEMPTS 2.3 KiB 2.3 KiB +1 B (+0.04%)
🟡 agents/chat#MAX_BOUND_PARAMS 2.3 KiB 2.3 KiB +1 B (+0.04%)
🟡 agents/chat#CHAT_RECOVERY_TASK_NAME 2.3 KiB 2.3 KiB +1 B (+0.04%)
🟡 agents/chat#CHAT_LAST_TERMINAL_KEY 2.3 KiB 2.3 KiB +1 B (+0.04%)
🟡 agents/chat#clientResolvableToolNames 2.3 KiB 2.3 KiB +1 B (+0.04%)
🟡 agents/chat#clearChatTerminal 2.3 KiB 2.3 KiB +1 B (+0.04%)
🟡 agents/chat#STREAM_RESUME_NONE_REASONS 2.3 KiB 2.3 KiB +1 B (+0.04%)
🟡 agents/chat#drainInteractionApplies 2.3 KiB 2.3 KiB +1 B (+0.04%)
🟡 agents/chat#recordChatTerminal 2.4 KiB 2.4 KiB +1 B (+0.04%)
🟡 agents/chat#ChatStreamStalledError 2.4 KiB 2.4 KiB +1 B (+0.04%)
🟡 agents/chat#bumpChatRecoveryProgress 2.4 KiB 2.4 KiB +1 B (+0.04%)
🟡 agents/chat#shouldCreditStreamProgress 2.4 KiB 2.4 KiB +1 B (+0.04%)
🟡 agents/chat#buildChatRecoveringFrame 2.4 KiB 2.4 KiB +1 B (+0.04%)
🟡 agents/chat#sendIfOpen 2.4 KiB 2.4 KiB +1 B (+0.04%)
🟡 agents/chat#pausedExecutionUpdate 2.4 KiB 2.4 KiB +1 B (+0.04%)
🟡 agents/chat#awaitWithDeadline 2.4 KiB 2.4 KiB +1 B (+0.04%)
🟡 agents/chat#listActiveChatRecoveryIncidents 2.4 KiB 2.4 KiB +1 B (+0.04%)
🟡 agents/chat#crossMessageToolResultUpdate 2.4 KiB 2.4 KiB +1 B (+0.04%)
🟡 agents/chat#buildInClauseStrings 2.4 KiB 2.4 KiB +1 B (+0.04%)
🟡 agents/chat#classifyAgentToolChildRecovery 2.4 KiB 2.4 KiB +1 B (+0.04%)
🟡 agents/chat#hasIncompleteToolBatch 2.4 KiB 2.4 KiB +1 B (+0.04%)
🟡 agents/chat#sweepStaleChatRecoveryIncidents 2.4 KiB 2.4 KiB +1 B (+0.04%)
🟡 agents/chat#interceptAgentToolBroadcast 2.5 KiB 2.5 KiB +1 B (+0.04%)
🟡 agents/chat#AbortRegistry 2.5 KiB 2.5 KiB +1 B (+0.04%)
🟡 agents/chat#ContinuationState 2.7 KiB 2.7 KiB +1 B (+0.04%)
🟡 agents/chat#createChatTurnTaskDefinition 2.7 KiB 2.7 KiB +1 B (+0.04%)
🟡 agents/chat#AgentToolProgressEmitter 2.7 KiB 2.7 KiB +1 B (+0.04%)
🟡 agents/chat#SubmitConcurrencyController 2.9 KiB 2.9 KiB +1 B (+0.03%)
🟡 agents/chat#StreamAccumulator 2.9 KiB 2.9 KiB +1 B (+0.03%)
🟡 agents/chat#ResumeHandshake 3.0 KiB 3.0 KiB +1 B (+0.03%)
🟡 agents/chat#broadcastTransition 3.2 KiB 3.2 KiB +1 B (+0.03%)
🟡 agents/chat#truncateOlderMessages 3.2 KiB 3.2 KiB +1 B (+0.03%)
🟡 agents/chat#enforceRowSizeLimit 3.5 KiB 3.5 KiB +1 B (+0.03%)
🟡 agents/chat#ChatRecoveryEngine 4.4 KiB 4.4 KiB +1 B (+0.02%)
🟢 agents/chat#TextSegmentJoiner 2.7 KiB 2.7 KiB -4 B (-0.14%)
🟢 agents/chat#dispatchChatRecoveryToHandoff 3.0 KiB 3.0 KiB -2 B (-0.06%)
🟢 agents/chat#setChatRecovering 2.5 KiB 2.5 KiB -1 B (-0.04%)
🟢 agents/chat#TurnQueue 2.6 KiB 2.6 KiB -1 B (-0.04%)
🟢 agents/chat#repairInterruptedToolParts 2.6 KiB 2.6 KiB -1 B (-0.04%)
🟢 agents/chat#applyAgentToolEvent 3.2 KiB 3.2 KiB -1 B (-0.03%)
🟢 agents/chat#createChatStreams 6.4 KiB 6.4 KiB -1 B (-0.02%)
🟢 agents/chat#createToolsFromClientSchemas 114.3 KiB 114.3 KiB -1 B (-0%)
⚪ agents/tasks#TaskDeadlineExceededError — 299 B —
⚪ agents/tasks#TaskInterruptionsExhaustedError — 312 B —
All 345 current runtime imports
Status Import Gzip Raw minified
🟡 agents#__DO_NOT_USE_WILL_BREAK__agentContext 261.9 KiB 1144.0 KiB
🟡 agents#__DO_NOT_USE_WILL_BREAK__withInvocationScope 261.9 KiB 1144.0 KiB
🟡 agents#Agent 261.9 KiB 1144.0 KiB
🟡 agents#AGENT_TOOL_MILESTONE_PART 261.9 KiB 1144.0 KiB
🟡 agents#AGENT_TOOL_PROGRESS_PART 261.9 KiB 1144.0 KiB
🟡 agents#buildAgentPath 262.5 KiB 1146.3 KiB
🟡 agents#buildAgentUrl 262.7 KiB 1146.7 KiB
🟡 agents#callable 261.9 KiB 1144.1 KiB
🟡 agents#camelCaseToKebabCase 261.9 KiB 1144.0 KiB
🟡 agents#createHeaderBasedEmailResolver 262.1 KiB 1144.4 KiB
🟡 agents#DEFAULT_AGENT_STATIC_OPTIONS 261.9 KiB 1144.0 KiB
🟡 agents#DurableObjectOAuthClientProvider 261.9 KiB 1144.0 KiB
🟡 agents#getAgentByName 261.9 KiB 1144.0 KiB
🟡 agents#getCurrentAgent 261.9 KiB 1144.0 KiB
🟡 agents#getSubAgentByName 262.2 KiB 1144.7 KiB
🟡 agents#isDurableObjectCodeUpdateReset 261.9 KiB 1144.0 KiB
🟡 agents#isDurableObjectMemoryLimitReset 261.9 KiB 1144.0 KiB
🟡 agents#isDurableObjectStorageReset 261.9 KiB 1144.1 KiB
🟡 agents#isPlatformTransientError 261.9 KiB 1144.0 KiB
🟡 agents#MCP_SERVER_ID_MAX_LENGTH 261.9 KiB 1144.0 KiB
🟡 agents#MessageType 262.1 KiB 1144.3 KiB
🟡 agents#normalizeServerId 261.9 KiB 1144.0 KiB
🟡 agents#parseSubAgentPath 261.9 KiB 1144.0 KiB
🟡 agents#routeAgentEmail 262.2 KiB 1144.7 KiB
🟡 agents#routeAgentRequest 262.6 KiB 1145.9 KiB
🟡 agents#routeSubAgentRequest 262.2 KiB 1144.6 KiB
🟡 agents#SqlError 261.9 KiB 1144.0 KiB
🟡 agents#StreamingResponse 261.9 KiB 1144.0 KiB
🟡 agents#SUB_PREFIX 261.9 KiB 1144.0 KiB
🟡 agents#unstable_callable 262.0 KiB 1144.2 KiB
⚪ agents/agent-tools#agentTool 112.5 KiB 538.2 KiB
⚪ agents/browser#BrowserConnector 50.5 KiB 176.6 KiB
⚪ agents/browser#browserContent 36.3 KiB 127.4 KiB
⚪ agents/browser#browserExtract 36.3 KiB 127.4 KiB
⚪ agents/browser#browserLinks 36.3 KiB 127.4 KiB
⚪ agents/browser#browserMarkdown 36.3 KiB 127.4 KiB
⚪ agents/browser#browserPdf 36.3 KiB 127.3 KiB
⚪ agents/browser#BrowserRenderingError 36.0 KiB 126.7 KiB
⚪ agents/browser#browserScrape 36.3 KiB 127.4 KiB
⚪ agents/browser#browserScreenshot 36.3 KiB 127.3 KiB
⚪ agents/browser#browserSnapshot 36.3 KiB 127.4 KiB
⚪ agents/browser#CdpSession 37.2 KiB 129.8 KiB
⚪ agents/browser#CodemodeRuntime 39.6 KiB 139.0 KiB
⚪ agents/browser#connectBrowser 37.8 KiB 131.4 KiB
⚪ agents/browser#connectBrowserSession 37.5 KiB 130.4 KiB
⚪ agents/browser#connectUrl 37.6 KiB 130.5 KiB
⚪ agents/browser#createBrowserSession 36.3 KiB 127.5 KiB
⚪ agents/browser#DEFAULT_EXEC_SWEEP_IDLE_MS 36.0 KiB 126.6 KiB
⚪ agents/browser#DEFAULT_SWEEP_IDLE_MS 36.0 KiB 126.6 KiB
⚪ agents/browser#deleteBrowserSession 36.1 KiB 126.9 KiB
⚪ agents/browser#DurableBrowserSessionStore 36.4 KiB 127.6 KiB
⚪ agents/browser#getBrowserRecording 36.2 KiB 127.1 KiB
⚪ agents/browser#listBrowserTargets 36.1 KiB 126.9 KiB
⚪ agents/browser#loadCdpSpec 36.6 KiB 128.3 KiB
⚪ agents/browser#runQuickAction 36.0 KiB 126.6 KiB
⚪ agents/browser/ai#createBrowserRuntime 147.0 KiB 632.8 KiB
⚪ agents/browser/ai#createBrowserTools 147.0 KiB 632.9 KiB
⚪ agents/browser/ai#createQuickActionTools 122.5 KiB 554.3 KiB
⚪ agents/browser/tanstack-ai#createBrowserTools 162.7 KiB 701.7 KiB
⚪ agents/channels#ChannelHost 3.3 KiB 9.1 KiB
⚪ agents/channels#consumeChunks 237 B 321 B
⚪ agents/channels#createUserIdentityStore 1.3 KiB 3.2 KiB
⚪ agents/channels#fallback 155 B 160 B
⚪ agents/channels#fallbackChannel 893 B 1.9 KiB
⚪ agents/channels#fanout 151 B 156 B
⚪ agents/channels#fanoutChannel 875 B 1.9 KiB
⚪ agents/channels#identityKey 178 B 223 B
⚪ agents/channels#isChannelMessageSurface 271 B 452 B
⚪ agents/channels#linkChannelIdentities 113 B 99 B
⚪ agents/channels#matchesPath 110 B 96 B
⚪ agents/channels#routes 307 B 507 B
⚪ agents/channels#UserIdentityConflictError 248 B 335 B
⚪ agents/channels/ai-sdk#createSendMessageTool 112.2 KiB 537.4 KiB
⚪ agents/channels/ai-sdk#toChannelChunks 112.5 KiB 538.4 KiB
⚪ agents/channels/email#email 23.5 KiB 75.4 KiB
⚪ agents/channels/email#inboundEmail 22.3 KiB 72.3 KiB
⚪ agents/channels/slack#slack 5.5 KiB 14.6 KiB
⚪ agents/channels/slack#slackWebhook 2.2 KiB 5.1 KiB
⚪ agents/channels/tanstack-ai#createSendMessageTool 16.2 KiB 68.4 KiB
⚪ agents/channels/telegram#telegram 3.8 KiB 10.3 KiB
⚪ agents/channels/telegram#telegramWebhook 1.6 KiB 3.6 KiB
⚪ agents/channels/voice#browserVoice 1010 B 2.2 KiB
🟡 agents/chat#AbortRegistry 2.5 KiB 8.9 KiB
⚪ agents/chat#AGENT_TOOL_STREAM_PROGRESS_BUMP_THROTTLE_MS 2.3 KiB 8.2 KiB
🟡 agents/chat#AgentToolProgressEmitter 2.7 KiB 9.5 KiB
⚪ agents/chat#AgentToolStreamProgressThrottle 2.4 KiB 8.3 KiB
🟡 agents/chat#aiSdkRecoveryCodec 2.3 KiB 8.2 KiB
🟢 agents/chat#applyAgentToolEvent 3.2 KiB 11.0 KiB
🟡 agents/chat#applyChunkToParts 2.3 KiB 8.2 KiB
⚪ agents/chat#applyToolUpdate 2.4 KiB 8.4 KiB
⚪ agents/chat#AutoContinuationController 2.3 KiB 8.2 KiB
🟡 agents/chat#awaitWithDeadline 2.4 KiB 8.4 KiB
🟡 agents/chat#broadcastTransition 3.2 KiB 11.4 KiB
🟡 agents/chat#buildChatRecoveringFrame 2.4 KiB 8.4 KiB
🟡 agents/chat#buildInClauseStrings 2.4 KiB 8.4 KiB
🟡 agents/chat#bumpChatRecoveryProgress 2.4 KiB 8.3 KiB
⚪ agents/chat#byteLength 2.5 KiB 8.5 KiB
🟡 agents/chat#CHAT_LAST_TERMINAL_KEY 2.3 KiB 8.2 KiB
🟡 agents/chat#CHAT_MESSAGE_TYPES 2.3 KiB 8.2 KiB
⚪ agents/chat#CHAT_RECOVERING_FLAG_TTL_MS 2.3 KiB 8.2 KiB
⚪ agents/chat#CHAT_RECOVERING_KEY 2.3 KiB 8.2 KiB
🟡 agents/chat#CHAT_RECOVERY_ALARM_DEBOUNCE_MS 2.3 KiB 8.2 KiB
⚪ agents/chat#CHAT_RECOVERY_INCIDENT_KEY_PREFIX 2.3 KiB 8.2 KiB
🟡 agents/chat#CHAT_RECOVERY_INCIDENT_TTL_MS 2.3 KiB 8.2 KiB
⚪ agents/chat#CHAT_RECOVERY_PROGRESS_KEY 2.3 KiB 8.2 KiB
⚪ agents/chat#CHAT_RECOVERY_STABLE_RETRY_DELAY_SECONDS 2.3 KiB 8.2 KiB
🟡 agents/chat#CHAT_RECOVERY_TASK_NAME 2.3 KiB 8.2 KiB
⚪ agents/chat#CHAT_STREAM_PROGRESS_CREDIT_THROTTLE_MS 2.3 KiB 8.2 KiB
🟡 agents/chat#ChatRecoveryEngine 4.4 KiB 15.3 KiB
⚪ agents/chat#chatRecoveryTaskRunOptions 2.4 KiB 8.6 KiB
🟡 agents/chat#ChatStreamStalledError 2.4 KiB 8.3 KiB
🟡 agents/chat#classifyAgentToolChildRecovery 2.4 KiB 8.5 KiB
🟡 agents/chat#clearChatTerminal 2.3 KiB 8.3 KiB
🟡 agents/chat#clientResolvableToolNames 2.3 KiB 8.3 KiB
🟡 agents/chat#ContinuationState 2.7 KiB 9.8 KiB
⚪ agents/chat#createAgentToolEventState 2.3 KiB 8.3 KiB
🟡 agents/chat#createChatFiberSnapshot 2.5 KiB 8.6 KiB
⚪ agents/chat#createChatRecoveryTaskDefinition 2.6 KiB 9.0 KiB
🟢 agents/chat#createChatStreams 6.4 KiB 22.1 KiB
🟡 agents/chat#createChatTurnTaskDefinition 2.7 KiB 8.9 KiB
🟢 agents/chat#createToolsFromClientSchemas 114.3 KiB 545.4 KiB
🟡 agents/chat#crossMessageToolResultUpdate 2.4 KiB 8.6 KiB
🟡 agents/chat#DEFAULT_CHAT_RECOVERY_MAX_ATTEMPTS 2.3 KiB 8.2 KiB
⚪ agents/chat#DEFAULT_CHAT_RECOVERY_MAX_OOM_RETRIES 2.3 KiB 8.2 KiB
⚪ agents/chat#DEFAULT_CHAT_RECOVERY_MAX_WORK 2.3 KiB 8.2 KiB
🟡 agents/chat#DEFAULT_CHAT_RECOVERY_NO_PROGRESS_TIMEOUT_MS 2.3 KiB 8.2 KiB
⚪ agents/chat#DEFAULT_CHAT_RECOVERY_STABLE_TIMEOUT_MS 2.3 KiB 8.2 KiB
⚪ agents/chat#DEFAULT_CHAT_RECOVERY_TERMINAL_MESSAGE 2.4 KiB 8.3 KiB
🟢 agents/chat#dispatchChatRecoveryToHandoff 3.0 KiB 9.9 KiB
🟡 agents/chat#drainInteractionApplies 2.3 KiB 8.3 KiB
🟡 agents/chat#enforceRowSizeLimit 3.5 KiB 11.2 KiB
🟡 agents/chat#hasIncompleteToolBatch 2.4 KiB 8.6 KiB
🟡 agents/chat#interceptAgentToolBroadcast 2.5 KiB 8.7 KiB
⚪ agents/chat#isPlatformFailure 2.6 KiB 8.9 KiB
⚪ agents/chat#isReplayChunk 2.4 KiB 8.7 KiB
⚪ agents/chat#iterateWithStallWatchdog 2.6 KiB 8.8 KiB
⚪ agents/chat#KV_DELETE_MAX_KEYS 2.3 KiB 8.2 KiB
🟡 agents/chat#listActiveChatRecoveryIncidents 2.4 KiB 8.4 KiB
🟡 agents/chat#MAX_BOUND_PARAMS 2.3 KiB 8.2 KiB
⚪ agents/chat#MessageType 2.4 KiB 9.0 KiB
🟡 agents/chat#normalizeToolInput 2.3 KiB 8.2 KiB
⚪ agents/chat#parseProtocolMessage 2.5 KiB 9.0 KiB
⚪ agents/chat#partAwaitsClientInteraction 2.4 KiB 8.6 KiB
🟡 agents/chat#pausedExecutionUpdate 2.4 KiB 8.4 KiB
⚪ agents/chat#pendingChatTerminal 2.3 KiB 8.3 KiB
⚪ agents/chat#persistReconstructedOrphan 3.1 KiB 11.0 KiB
⚪ agents/chat#PreStreamTurns 2.6 KiB 9.3 KiB
⚪ agents/chat#readChatRecoveryProgress 2.3 KiB 8.3 KiB
⚪ agents/chat#reconcileMessages 2.8 KiB 9.6 KiB
⚪ agents/chat#reconcileOrphanPartial 2.4 KiB 8.5 KiB
🟡 agents/chat#recordChatTerminal 2.4 KiB 8.3 KiB
🟢 agents/chat#repairInterruptedToolParts 2.6 KiB 9.1 KiB
⚪ agents/chat#resolveChatRecoveryConfig 2.6 KiB 8.9 KiB
⚪ agents/chat#resolveToolMergeId 2.4 KiB 8.5 KiB
⚪ agents/chat#ResumableStream 5.1 KiB 16.8 KiB
🟡 agents/chat#ResumeHandshake 3.0 KiB 10.4 KiB
⚪ agents/chat#ROW_MAX_BYTES 2.3 KiB 8.2 KiB
⚪ agents/chat#runChatRecoveryExhaustion 2.6 KiB 8.9 KiB
⚪ agents/chat#sanitizeMessage 2.5 KiB 8.8 KiB
🟡 agents/chat#sendIfOpen 2.4 KiB 8.4 KiB
🟢 agents/chat#setChatRecovering 2.5 KiB 8.5 KiB
🟡 agents/chat#shouldCreditStreamProgress 2.4 KiB 8.3 KiB
🟡 agents/chat#STREAM_RESUME_NONE_REASONS 2.3 KiB 8.2 KiB
🟡 agents/chat#StreamAccumulator 2.9 KiB 10.7 KiB
⚪ agents/chat#StreamProgressCreditThrottle 2.4 KiB 8.3 KiB
🟡 agents/chat#SubmitConcurrencyController 2.9 KiB 10.3 KiB
🟡 agents/chat#sweepStaleChatRecoveryIncidents 2.4 KiB 8.5 KiB
🟢 agents/chat#TextSegmentJoiner 2.7 KiB 9.2 KiB
⚪ agents/chat#TIMED_OUT 2.3 KiB 8.2 KiB
⚪ agents/chat#toolApprovalUpdate 2.4 KiB 8.5 KiB
⚪ agents/chat#toolPartHasSettledResult 2.3 KiB 8.4 KiB
⚪ agents/chat#toolResultUpdate 2.4 KiB 8.5 KiB
🟡 agents/chat#truncateOlderMessages 3.2 KiB 10.4 KiB
🟢 agents/chat#TurnQueue 2.6 KiB 9.2 KiB
⚪ agents/chat#unwrapChatFiberSnapshot 2.4 KiB 8.5 KiB
⚪ agents/chat#wrapChatFiberSnapshot 2.3 KiB 8.2 KiB
🟡 agents/chat-sdk#ChatSdkStateAdapter 264.3 KiB 1155.6 KiB
🟡 agents/chat-sdk#ChatSdkStateAgent 263.7 KiB 1153.1 KiB
🟡 agents/chat-sdk#createChatSdkState 264.3 KiB 1155.6 KiB
🟡 agents/chat-sdk#defaultKeyShard 262.0 KiB 1144.2 KiB
🟡 agents/chat-sdk#defaultThreadShard 261.9 KiB 1144.1 KiB
⚪ agents/chat/react#detectToolsRequiringConfirmation 3.3 KiB 8.3 KiB
⚪ agents/chat/react#extractClientToolSchemas 3.2 KiB 8.3 KiB
⚪ agents/chat/react#getAgentMessages 3.4 KiB 8.6 KiB
⚪ agents/chat/react#getToolApproval 3.1 KiB 8.0 KiB
⚪ agents/chat/react#getToolCallId 3.1 KiB 8.0 KiB
⚪ agents/chat/react#getToolInput 3.1 KiB 8.0 KiB
⚪ agents/chat/react#getToolOutput 3.1 KiB 8.0 KiB
⚪ agents/chat/react#getToolPartState 3.2 KiB 8.2 KiB
⚪ agents/chat/react#useAgentChat 132.9 KiB 609.7 KiB
⚪ agents/chat/react#WebSocketChatTransport 5.7 KiB 17.1 KiB
⚪ agents/chat/transport#WebSocketChatTransport 2.8 KiB 9.2 KiB
⚪ agents/client#AgentClient 21.8 KiB 75.2 KiB
⚪ agents/client#AgentConnectionError 16.3 KiB 57.8 KiB
⚪ agents/client#agentFetch 19.7 KiB 69.0 KiB
⚪ agents/client#createStubProxy 16.4 KiB 57.8 KiB
⚪ agents/client#DEFAULT_CALL_TIMEOUT_MS 16.2 KiB 57.6 KiB
⚪ agents/client#isTerminalCloseEvent 16.3 KiB 57.6 KiB
⚪ agents/client#nativeCall 16.5 KiB 58.3 KiB
⚪ agents/client#NativeCallQueue 16.7 KiB 58.9 KiB
⚪ agents/client#splitCallOptions 16.3 KiB 57.7 KiB
⚪ agents/context#AgentContextProvider 412 B 792 B
⚪ agents/context#AgentSearchProvider 640 B 1.3 KiB
⚪ agents/context#ContextBlocks 87.4 KiB 429.7 KiB
⚪ agents/email#createAddressBasedEmailResolver 193 B 227 B
⚪ agents/email#createCatchAllEmailResolver 110 B 97 B
⚪ agents/email#createHeaderBasedEmailResolver 334 B 492 B
⚪ agents/email#createSecureReplyEmailResolver 718 B 1.3 KiB
⚪ agents/email#DEFAULT_MAX_AGE_SECONDS 56 B 39 B
⚪ agents/email#isAutoReplyEmail 201 B 249 B
⚪ agents/email#signAgentHeaders 424 B 812 B
⚪ agents/experimental/webmcp#registerWebMcp 85.2 KiB 295.8 KiB
⚪ agents/lifecycle#getCurrentAgent 376 B 798 B
⚪ agents/lifecycle#Lifecycle 8.4 KiB 26.1 KiB
⚪ agents/lifecycle#LifecycleCapability 497 B 999 B
🟡 agents/mcp#createLegacyMcpHandler 379.4 KiB 1586.4 KiB
🟡 agents/mcp#createMcpHandler 391.7 KiB 1631.6 KiB
🟡 agents/mcp#DurableObjectEventStore 346.0 KiB 1444.9 KiB
🟡 agents/mcp#ElicitRequestSchema 346.0 KiB 1444.9 KiB
🟡 agents/mcp#experimental_createMcpHandler 379.6 KiB 1586.7 KiB
🟡 agents/mcp#getMcpAuthContext 346.0 KiB 1444.9 KiB
🟡 agents/mcp#MCP_SERVER_ID_MAX_LENGTH 346.0 KiB 1444.9 KiB
🟡 agents/mcp#McpAgent 346.0 KiB 1444.9 KiB
🟡 agents/mcp#normalizeServerId 346.0 KiB 1444.9 KiB
🟡 agents/mcp#RPC_DO_PREFIX 346.0 KiB 1444.9 KiB
🟡 agents/mcp#RPCClientTransport 346.0 KiB 1444.9 KiB
🟡 agents/mcp#RPCServerTransport 346.0 KiB 1444.9 KiB
🟡 agents/mcp#SSEEdgeClientTransport 346.1 KiB 1445.1 KiB
🟡 agents/mcp#StreamableHTTPEdgeClientTransport 346.1 KiB 1445.2 KiB
🟡 agents/mcp#WorkerTransport 349.4 KiB 1461.8 KiB
⚪ agents/mcp/client#getNamespacedData 62.9 KiB 240.0 KiB
⚪ agents/mcp/client#MCP_SERVER_ID_MAX_LENGTH 62.9 KiB 239.9 KiB
⚪ agents/mcp/client#MCPClientManager 158.6 KiB 702.6 KiB
⚪ agents/mcp/client#normalizeServerId 63.0 KiB 240.2 KiB
⚪ agents/mcp/do-oauth-client-provider#DurableObjectOAuthClientProvider 2.1 KiB 6.6 KiB
⚪ agents/mcp/server#createMcpHandler 80.5 KiB 307.2 KiB
⚪ agents/mcp/server#getMcpAuthContext 64.0 KiB 245.5 KiB
⚪ agents/observability#channels 259 B 549 B
⚪ agents/observability#genericObservability 470 B 1.2 KiB
⚪ agents/observability#subscribe 324 B 668 B
⚪ agents/observability/ai#wrapAISDK 8.8 KiB 30.5 KiB
⚪ agents/queue#Queue 3.1 KiB 9.6 KiB
⚪ agents/react#_testUtils 19.3 KiB 66.4 KiB
⚪ agents/react#useAgent 27.1 KiB 89.9 KiB
⚪ agents/react#useAgentToolEvents 21.1 KiB 73.7 KiB
⚪ agents/routing#getAgentByName 795 B 1.7 KiB
⚪ agents/routing#routeAgentRequest 1.6 KiB 3.6 KiB
⚪ agents/routing#RoutedAgents 2.4 KiB 6.2 KiB
⚪ agents/schedule#getSchedulePrompt 85.8 KiB 424.7 KiB
⚪ agents/schedule#scheduleSchema 85.3 KiB 423.6 KiB
⚪ agents/schedule#unstable_getSchedulePrompt 85.9 KiB 424.9 KiB
⚪ agents/schedule#unstable_scheduleSchema 85.3 KiB 423.6 KiB
⚪ agents/schedules#Scheduler 6.8 KiB 22.0 KiB
⚪ agents/schedules/parser#getSchedulePrompt 85.8 KiB 424.7 KiB
⚪ agents/schedules/parser#scheduleSchema 85.3 KiB 423.6 KiB
⚪ agents/sessions#COMPACTION_PREFIX 147 B 160 B
⚪ agents/sessions#createCompactFunction 1.7 KiB 4.0 KiB
⚪ agents/sessions#isCompactionMessage 177 B 200 B
⚪ agents/sessions#Session 2.0 KiB 6.3 KiB
⚪ agents/sessions#Sessions 9.6 KiB 34.3 KiB
⚪ agents/skills#fromManifest 309.8 KiB 1084.0 KiB
⚪ agents/skills#parseSkillFrontmatter 328.4 KiB 1146.2 KiB
⚪ agents/skills#parseSkillMarkdown 328.6 KiB 1146.5 KiB
⚪ agents/skills#r2 330.2 KiB 1150.4 KiB
⚪ agents/skills#runner 369.0 KiB 1297.8 KiB
⚪ agents/skills#SkillRegistry 416.4 KiB 1581.7 KiB
⚪ agents/skills/compile#compileSkillScript 15.4 KiB 43.4 KiB
⚪ agents/skills/compile#isCompilableSkillScript 15.4 KiB 43.3 KiB
⚪ agents/state#State 1.1 KiB 2.4 KiB
⚪ agents/streams#DEFAULT_MAX_CHUNK_BYTES 94 B 96 B
⚪ agents/streams#sseResponse 857 B 1.6 KiB
⚪ agents/streams#StreamClosedError 175 B 212 B
⚪ agents/streams#StreamNotFoundError 215 B 276 B
⚪ agents/streams#Streams 4.3 KiB 13.9 KiB
⚪ agents/streams#StreamSerializationError 171 B 201 B
⚪ agents/tasks#DuplicateTaskStepError 328 B 463 B
⚪ agents/tasks#MAX_SERIALIZED_BYTES 190 B 232 B
🟡 agents/tasks#MissingTaskDefinitionError 359 B 536 B
⚪ agents/tasks#NonRetryableError 238 B 308 B
⚪ agents/tasks#TaskDeadlineExceededError 299 B 414 B
⚪ agents/tasks#TaskInterruptionsExhaustedError 312 B 442 B
⚪ agents/tasks#TaskReplayDivergedError 341 B 483 B
🟡 agents/tasks#Tasks 9.7 KiB 34.8 KiB
⚪ agents/tasks#TaskSerializationError 258 B 339 B
⚪ agents/types#MessageType 211 B 365 B
⚪ agents/vite#default 353.8 KiB 1356.1 KiB
⚪ agents/voice#addSFUTracks 324 B 424 B
⚪ agents/voice#createSFUSession 255 B 306 B
⚪ agents/voice#createSFUWebSocketAdapter 331 B 429 B
⚪ agents/voice#decodeVarint 157 B 160 B
⚪ agents/voice#downsample48kStereoTo16kMono 238 B 324 B
⚪ agents/voice#encodePayloadToProtobuf 189 B 279 B
⚪ agents/voice#encodeVarint 129 B 122 B
⚪ agents/voice#extractPayloadFromProtobuf 271 B 425 B
⚪ agents/voice#iterateText 1.6 KiB 3.8 KiB
⚪ agents/voice#renegotiateSFUSession 329 B 428 B
⚪ agents/voice#SentenceChunker 550 B 1.1 KiB
⚪ agents/voice#sfuFetch 294 B 358 B
⚪ agents/voice#upsample16kMonoTo48kStereo 211 B 272 B
⚪ agents/voice#VOICE_PROTOCOL_VERSION 51 B 31 B
⚪ agents/voice#withVoice 9.5 KiB 32.7 KiB
⚪ agents/voice#withVoiceInput 4.8 KiB 16.0 KiB
⚪ agents/voice#WorkersAIFluxSTT 1.5 KiB 4.3 KiB
⚪ agents/voice#WorkersAINova3STT 1.6 KiB 4.3 KiB
⚪ agents/voice#WorkersAITTS 682 B 1.4 KiB
⚪ agents/voice/client#VOICE_PROTOCOL_VERSION 473 B 768 B
⚪ agents/voice/client#VoiceClient 10.1 KiB 31.6 KiB
⚪ agents/voice/client#WebSocketVoiceTransport 4.6 KiB 13.3 KiB
⚪ agents/voice/errors#logVoiceError 132 B 173 B
⚪ agents/voice/errors#toVoiceError 94 B 80 B
⚪ agents/voice/errors#voiceErrorMessage 125 B 111 B
⚪ agents/voice/errors#VoiceProviderError 190 B 345 B
⚪ agents/voice/react#useVoiceAgent 13.6 KiB 42.5 KiB
⚪ agents/voice/react#useVoiceInput 13.3 KiB 41.4 KiB
⚪ agents/voice/react#WebSocketVoiceTransport 7.4 KiB 21.3 KiB
⚪ agents/voice/sfu#addSFUTracks 323 B 424 B
⚪ agents/voice/sfu#createSFUSession 254 B 306 B
⚪ agents/voice/sfu#createSFUWebSocketAdapter 329 B 429 B
⚪ agents/voice/sfu#decodeVarint 155 B 160 B
⚪ agents/voice/sfu#downsample48kStereoTo16kMono 236 B 324 B
⚪ agents/voice/sfu#encodePayloadToProtobuf 188 B 279 B
⚪ agents/voice/sfu#encodeVarint 129 B 122 B
⚪ agents/voice/sfu#extractPayloadFromProtobuf 270 B 425 B
⚪ agents/voice/sfu#renegotiateSFUSession 329 B 428 B
⚪ agents/voice/sfu#sfuFetch 292 B 358 B
⚪ agents/voice/sfu#upsample16kMonoTo48kStereo 209 B 272 B
⚪ agents/voice/text#iterateText 1.6 KiB 3.8 KiB
⚪ agents/voice/text#SentenceChunker 549 B 1.1 KiB
⚪ agents/voice/types#VOICE_PROTOCOL_VERSION 51 B 31 B
⚪ agents/voice/workers-ai#WorkersAIFluxSTT 1.5 KiB 4.3 KiB
⚪ agents/voice/workers-ai#WorkersAINova3STT 1.6 KiB 4.3 KiB
⚪ agents/voice/workers-ai#WorkersAITTS 682 B 1.4 KiB
⚪ agents/websockets#CAPNWEB_TRANSPORT_QUERY 12.4 KiB 43.3 KiB
⚪ agents/websockets#CAPNWEB_TRANSPORT_VALUE 12.4 KiB 43.3 KiB
⚪ agents/websockets#capnWebTransportUrl 12.5 KiB 43.5 KiB
⚪ agents/websockets#CF_NO_PROTOCOL_KEY 12.4 KiB 43.3 KiB
⚪ agents/websockets#CF_READONLY_KEY 12.4 KiB 43.3 KiB
⚪ agents/websockets#isCapnWebTransportUpgrade 12.5 KiB 43.4 KiB
⚪ agents/websockets#registerInternalConnectionKeys 12.4 KiB 43.4 KiB
⚪ agents/websockets#WebSockets 20.0 KiB 69.3 KiB
🟡 agents/workflows#AgentWorkflow 263.2 KiB 1148.8 KiB
🟡 agents/workflows#WorkflowRejectedError 262.0 KiB 1144.2 KiB
⚪ agents/x402#normalizeNetwork 14.7 KiB 61.1 KiB
⚪ agents/x402#withX402 23.0 KiB 89.2 KiB
⚪ agents/x402#withX402Client 104.1 KiB 346.5 KiB

Reported by agent-think[bot].

devin-ai-integration[bot]

This comment was marked as resolved.

…ed failures, refuse pre-epoch deadlines

Review follow-ups: a handler that catches step.signal and returns no
longer completes a run whose cancel() was accepted; the memory-limit
breaker's sealed failure reaches onError with its run; a deadline at or
before the epoch is rejected before the row is inserted. Also updates the
DDL snapshot for the two schema v2 columns.

@devin-ai-integration devin-ai-integration Bot left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note

This report is out of date. Scroll down for Devin Review's latest report on this PR.

Devin Review found 3 new potential issues.

Devin Review

Comment on lines +1308 to +1312
// A cancel accepted mid-attempt wins over a result: a handler that
// caught `step.signal`, cleaned up, and returned normally has honoured
// the cancellation, and the run must not read as completed.
const current = this.#store.getRun(runId);
if (current?.cancel_requested === 1) {

@devin-ai-integration devin-ai-integration Bot Sep 16, 2026 •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Cancellation loses to result serialization

When a cancelled handler returns an unserializable value, serializeTaskValue throws before cancel_requested is checked. The run becomes failed instead of cancelled.

Learn more

Cancellation is recorded durably and aborts the attempt signal. A cooperative handler can catch that abort, clean up, and return any JavaScript value. The return value is serialized before the new cancellation check, so serialization errors enter #settleThrown and terminally fail the run. The cancellation check never executes in that case.

Example: A handler catches step.signal and returns { value: 1n }. JSON serialization throws for the bigint, so the run records TaskSerializationError rather than the accepted cancellation reason.

Recommended fix: Read cancel_requested immediately after the handler resolves, before calling serializeTaskValue. Settle under the same generation fence, then serialize only when cancellation was not requested.

Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.


Tasks: expose the attempt-wide abort signal to handler bodies, and bound a run by attempts and by wall-clock time.

- `step.signal` aborts for the whole attempt — on `cancel()` and when the run's `deadline` passes — so work awaited outside `step.do()` (a long model turn, a drain loop) can unwind. Inside a step the per-attempt signal already covered it.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔍 Incomplete signal release note

The changeset leaves the step.signal comparison unfinished with a literal .... Replace it with the actual step.do() signal behavior before release.

Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Comment thread docs/agents/tasks.md Outdated
Comment on lines +109 to +116
Two options bound a run. `maxAttempts` caps how many times it is claimed —
the first attempt, each replay after an interruption, and each wake from a
sleep or retry park all count — and once the last permitted attempt ends
without settling, the run fails with `TaskAttemptsExhaustedError` instead of
being claimed again. `deadline` (epoch milliseconds or a `Date`) is a
wall-clock bound: a live attempt's `step.signal` aborts and the run fails
with `TaskDeadlineExceededError`; a parked run is woken at the deadline and
fails there. Both are unbounded when omitted.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔍 Upstream documentation sync unverified

The docs rule requires manually porting this update to cloudflare/cloudflare-docs. That companion change is not verifiable in this repository.

Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

@pkg-pr-new

pkg-pr-new Bot commented Sep 16, 2026 •

Copy link
Copy Markdown

Open in StackBlitz

agents

npm i https://pkg.pr.new/agents@2274

@cloudflare/ai-chat

npm i https://pkg.pr.new/@cloudflare/ai-chat@2274

@cloudflare/codemode

npm i https://pkg.pr.new/@cloudflare/codemode@2274

hono-agents

npm i https://pkg.pr.new/hono-agents@2274

@cloudflare/shell

npm i https://pkg.pr.new/@cloudflare/shell@2274

@cloudflare/think

npm i https://pkg.pr.new/@cloudflare/think@2274

@cloudflare/voice

npm i https://pkg.pr.new/@cloudflare/voice@2274

@cloudflare/worker-bundler

npm i https://pkg.pr.new/@cloudflare/worker-bundler@2274

commit: f28ffc2

… add step.attempt

maxAttempts counted every claim of a run, so a run that slept ten times
with maxAttempts 10 was killed for sleeping. Replace it with
run(..., { retries }) in the vocabulary steps already use: the policy
bounds consecutive unclean interruptions (an attempt whose isolate died),
parks the run on a durable backoff between them, and fails it with
TaskAttemptsExhaustedError when limit is reached. Reaching a durable
boundary under the attempt's own power resets the count, so a long-lived
run is never failed for surviving deploys. The park carries its own wait
reason, 'interrupted', so a step retry park never reads as an
interruption and step.interrupted stays correct under concurrent steps.

Schema v2 (unreleased) becomes deadline_at, interruptions, retry_policy;
the resolved policy is persisted with the run. TaskRetryConfig is one
shared shape for step and run retries. step.attempt exposes the claim
number.

@devin-ai-integration devin-ai-integration Bot left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note

This report is out of date. Scroll down for Devin Review's latest report on this PR.

Devin Review found 2 new potential issues.

Devin Review

Comment on lines +1344 to +1345
const current = this.#store.getRun(runId);
if (current?.cancel_requested === 1) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔴 Late handlers complete past deadline

When a handler returns after its deadline, #runAttempt can still complete the run. Deadline enforcement only occurs when the wake dispatch executes.

Learn more

A run deadline is a wall-clock terminal bound. The alarm normally invokes #enforceDeadline, but alarm delivery can lag while the handler is running. The completion path reads the current row yet checks only cancellation before committing completed. It therefore needs to compare deadline_at with the current time before accepting the result.

Example: A handler performs synchronous work from 12:00:00.000 until 12:00:02.000 with a 12:00:01.000 deadline. The alarm cannot dispatch during that synchronous work. The handler writes completed first, and the later deadline wake finds a terminal run.

Recommended fix: Before serializing or committing the result, read the current row and terminally settle TaskDeadlineExceededError when deadline_at <= Date.now(). Preserve generation fencing and invoke onError exactly once, consistently with #enforceDeadline.

Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Comment thread packages/agents/src/tasks/types.ts
`retries` already means the step defaults on TasksOptions; using it again
on TaskRunOptions for the interruption budget made one name mean two
things in one object graph. The run option is now `interruptions` and
the error is TaskInterruptionsExhaustedError. Both were unreleased.

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 1 new potential issue.

Devin Review

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔍 Deadline-only rows escape reconciliation

#nextWake supports deadline_at without next_at, but startup selects only rows with next_at. Verify this invariant or reconcile all non-terminal rows.

(Refers to this code)

Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant