whoiskatrin
90d · built 2026-07-24
90-day totals
- Commits
- 26
- Grow
- 3.1
- Maintenance
- 5.0
- Fixes
- 4.4
- Total ETV
- 12.5
Where this dev ranks
Percentile against the global top-100 leaderboard (all-time totals).
- By commits
- Top 90 %
- By Growth share
- Top 62 %
30-day trajectory
Last 30 days vs. the 30 days before. Up arrows on Growth and ETV mean improvement; up arrow on Fixes share means more time on fixes (worse).
↓-100.0 %
vs 9 prior
↓-5.7 pp
recent vs prior
↓-55.6 pp
recent vs prior
Daily performance
Daily ETV, stacked by Growth, Maintenance and Fixes.
Work-mix over time
Share of Growth / Maintenance / Fixes over a rolling 7-day window. Reads as 'where is effort flowing right now'.
Repository spread
Where this developer's commits land. Concentrated work (top1 > 80%) vs polymath spread (top1 < 30%).
| Repo | Commits | ETV |
|---|---|---|
| agents | 16 | 11.6 |
| sandbox-sdk | 5 | 0.6 |
| cloudflare-docs | 4 | 0.3 |
Most impactful commits
Top 20 by ETV in the 90-day window.
- 3.8ETVfix: stop oversized sessions from bricking the DO with SQLITE_NOMEM on wake (#1724) * fix: stop oversized sessions from bricking the DO with SQLITE_NOMEM on wake (#1710) Four coordinated changes across agents + @cloudflare/think: 1. AgentSessionProvider.getHistory() no longer carries message content through the recursive CTE and its ORDER BY sorter (2-3 transient copies of the whole transcript inside SQLite's allocator); content is fetched in bounded chunks via json_each. 2. Think.onStart degrades instead of throwing when a data-driven step fails (transcript hydration, declared-task reconcile, durable-work recovery) — a throw there is re-run on every wake, including alarm retries, permanently bricking the DO. 3. hydrationByteBudget (default 24MB): oversized transcripts hydrate as a bounded recent window instead of materializing fully in memory. 4. mediaEviction (default on): aged inline media (data-URL file parts, large strings in tool outputs) is evicted from stored messages in background passes, preserved as workspace files by default. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * docs(think): document budget-exemption contract on _readMessagesFromStorage (#1710) * fix: close remaining full-history reads and harden memory bounds (#1710) Deep-review follow-up to the SQLITE_NOMEM fix. The original change bounded onStart hydration, but three helper paths still materialized the full transcript, undermining the budget; this closes them and hardens the new mechanisms. Session layer (agents): - Skill restore no longer bypasses budgeted hydration. The init-time loaded-skill scan is skipped entirely when no skill-capable context provider is configured, and when one is, it enumerates rows via getHistoryRowStats and fetches assistant messages ONE AT A TIME instead of reading the full history (full-read fallback for providers without row stats). A skill block added later via addContext() triggers the scan at that point. HistoryRowStat gains `role` to support the filter. - New Session.internal_rewriteMessage(): maintenance write path that skips the public updateMessage side effects (status broadcast + its FULL-history token estimate) while still notifying the message-change listener. Media eviction rewrites rows through it, so a pass no longer triggers a full-history read per rewritten row. - getRecentHistory(maxContentBytes, minRecentMessages?) gains a window floor: the most recent N rows are always included even when they exceed the byte budget (rows are write-capped, so the floor stays bounded). - Honest fallback: providers without getRecentHistory now report the real serialized size (not 0) and warn once that the budget is unenforced. - Content hydration chunks are bounded by cumulative stored bytes (4MB) as well as row count, removing the 50-near-cap-rows (~90MB) worst case. Think: - Budgeted hydration passes MODEL_RECENT_WINDOW (4 — the truncateOlderMessages default) as the floor, so windowing can never shrink this.messages below the span the model replays at full fidelity. - Media eviction: keepRecentMessages is clamped to that same window (a misconfigured low value can never strip content the model still sees); a pass that stops at maxRowsPerPass with eligible rows remaining schedules the next pass itself so backlogs drain; providers without row-stats support warn once instead of silently no-opping. - chat:hydration:windowed emits on change rather than on every safe- boundary sync (a chronically oversized session syncs many times per turn and would spam identical events). - Public getOnStartDegradations() accessor; stale onStart/JSDoc comments updated to describe the budgeted behavior. Tests (~30 new): restore-scan gating and bounded-restore call counts via stub providers, addContext late-skill scan, honest fallback metadata, silent-rewrite no-broadcast contract, floor semantics and corrupt-leaf behavior at the provider, role in row stats, 6MB multi-chunk round-trip, pure-function coverage for media-eviction.ts (markers, shape preservation, depth limit, no-mutation), eviction clamp and automatic pass chaining, and observability event assertions for chat:onstart:degraded / chat:hydration:windowed / chat:media:evicted. Co-authored-by: Cursor <cursoragent@cursor.com> --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com> Co-authored-by: devin-ai-integration[bot] <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: Sunil Pai <spai@cloudflare.com> Co-authored-by: Cursor <cursoragent@cursor.com>github.com-cloudflare-agents · c18a446d · 2026-06-12
- 3.2ETVWIP - Add Telnyx voice provider (#1461) * Add Telnyx voice provider * Add empty changeset for Telnyx provider * Address Telnyx provider review feedback * Fix Telnyx example typecheck * Update voice-providers/telnyx/src/transport/phone-transport.ts Co-authored-by: devin-ai-integration[bot] <158243242+devin-ai-integration[bot]@users.noreply.github.com> * Refocus Telnyx example on phone bridge * dependency version pinning * port telnyx tests * Bump deps, add aria-label, adjust tests Update dependency versions in examples/telnyx-voice-agent/package.json (bumping @cloudflare/kumo, ai, react, and several devDependencies) to newer releases for compatibility. Add an aria-label ("Text message") to the text input in the Telnyx voice agent UI to improve accessibility. Harden durable-chat recovery tests by checking scheduled callback counts before running retry/continue tasks and waiting for the agent to become idle, reducing flakiness in CI. * Harden Telnyx voice provider lifecycle and exports Keep the Telnyx package root server-safe by moving browser WebRTC helpers to the /browser entrypoint, and update the example/docs to use the clearer root-plus-browser import model. This avoids pulling @telnyx/webrtc into Worker bundles while keeping STT, TTS, and JWT helpers available from server-safe paths. Tighten the phone bridge and credential lifecycle so reconnects preserve the preferred audio format, stale async bridge setup is cancelled without leaking browser audio resources, in-flight starts settle on stop, late STT WebSockets are closed, and failed JWT token creation cleans up orphaned Telnyx credentials. The example now warns about local-only unauthenticated token minting, handles overlapping connect/disconnect attempts, and documents the live browser bridge requirement. Co-authored-by: Cursor <cursoragent@cursor.com> * Notify on websocket close error Ensure the TTS stream is unblocked if websocket.close() throws by calling notify() in the close handler catch. Add a test that simulates close() throwing (via MockWebSocket) and verifies aborting the request immediately resolves the synthesize promise to null. --------- Co-authored-by: devin-ai-integration[bot] <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: Christopher Little-Savage <clittle-savage@cloudflare.com> Co-authored-by: Sunil Pai <spai@cloudflare.com> Co-authored-by: Cursor <cursoragent@cursor.com>github.com-cloudflare-agents · d44f59ad · 2026-05-22
- 1.0ETVFix approved Think tool continuation results reaching clients (#1629) * fix(think): deliver approved tool continuation results * fix(think): harden approved tool continuation for current main Follow-up to the rebase of #1629 onto main, which had diverged significantly (transcript repair was rewritten to preserve-not-delete orphan tool calls via `repairInterruptedToolPart`, and `StreamAccumulator` gained a `cross-message-tool-update` action). Reconciles the approval continuation fix with that new shape and closes the edge cases it exposed. Cross-message tool result (agents/chat + think) - Add a shared, replay-safe `crossMessageToolResultUpdate` builder to `agents/chat` (exported alongside `toolResultUpdate`). It matches the broad set of pre-terminal AND terminal states so a provider that replays the prior tool round-trip during a continuation (e.g. the OpenAI Responses API, #1404) still resolves to the same part; it is first-write-wins (a chunk for an already-settled tool returns the same part reference, never overwriting a resolved result); and it preserves a streamed `preliminary` flag. - Think now consumes `StreamAccumulator`'s `cross-message-tool-update` action instead of re-deriving the cross-message condition inline, so the detection logic lives in exactly one (tested) place and carries `preliminary`. - `_applyToolUpdateToMessages` skips the durable write + redundant MESSAGE_UPDATED broadcast when first-write-wins yields an unchanged part (reference equality), so provider replays don't churn clients. Incomplete-tool-call backstop (think) - Exclude the intentionally-pending `approval-responded` state from `_incompleteToolCallIds`. An approved server tool has no result yet but is not abandoned — `convertToModelMessages` keeps and executes it. Flagging it made every approval continuation log a misleading "repair gap" warning and emit a spurious `chat:transcript:repaired` observability event. Tests - 9 unit tests for `crossMessageToolResultUpdate` (match states, preliminary preservation, output-error + default text, first-write-wins across all terminal states, applyToolUpdate integration). - WS regression test asserting an approval continuation emits no spurious `chat:transcript:repaired` event for the approved tool call (verified to fail without the backstop fix). Validated: `npm run check` (91 projects), @cloudflare/think 475/475, agents/chat tool-state 21/21, nx affected tests green. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(think): mark the stall-recovery continuation done frame The `_streamResult` scheduled-stall branch (ChatStreamStalledError -> outcome === "scheduled") closed the stream with a `done: true` frame that omitted `continuation: true`, unlike every other done frame in that path (success, catch-error, finally). The client reducer closes the stream on any `done` frame regardless of the flag, so this was not a stuck-UI bug — but the inconsistency is a footgun if the state machine ever consults `continuation` on close. Make all `_streamResult` done frames uniform. Note: the same-looking frame in `_streamResultToRpcCallback` is intentionally left as-is — that RPC-callback path has no `continuation` parameter and never participates in the WebSocket continuation-marker scheme. Co-authored-by: Cursor <cursoragent@cursor.com> --------- Co-authored-by: Sunil Pai <spai@cloudflare.com> Co-authored-by: Cursor <cursoragent@cursor.com>github.com-cloudflare-agents · 7d383638 · 2026-06-01
- 0.6ETVfix(mcp): safely route colliding streamable HTTP responses (#1639) * fix(mcp): safely route colliding streamable HTTP responses * fix(mcp): return protocol error for ambiguous streamsgithub.com-cloudflare-agents · 6bac0f43 · 2026-06-01
- 0.6ETVfix(mcp): retain transport owner outside agent context (#1734) StreamableHTTPServerTransport previously recovered its owning agent from AsyncLocalStorage at send time. Host callbacks reached through Worker Loader RPC have no ALS ancestry, so server-to-client requests such as elicitation failed with "Agent was not found in send".\n\nRetain the owning McpAgent for the transport lifetime, matching McpSSETransport. Explicit relatedRequestId routing works without ALS; request-scoped context remains an optional disambiguator when a client reuses an active request id across streams.\n\nAdd request-scoped and standalone elicitation regression coverage and document context behavior.\n\nFixes #1490.github.com-cloudflare-agents · cd2c4307 · 2026-06-24
- 0.5ETVAdd durable cancellation mode for useAgentChat (#1484) * Add durable chat cancellation policy * Make client abort cancellation opt-in Co-authored-by: Cursor <cursoragent@cursor.com> * Respect client abort policy for tool continuations Co-authored-by: Cursor <cursoragent@cursor.com> --------- Co-authored-by: Sunil Pai <spai@cloudflare.com> Co-authored-by: Cursor <cursoragent@cursor.com>github.com-cloudflare-agents · 364a45da · 2026-05-11
- 0.4ETVAllow non-chat Think agent tools to complete (#1483) * Allow non-chat Think agent tools to complete * Reset server streaming when resume ownership changes * Allow Think agent tools to finish without text Allow Think agent-tool children to complete without emitting assistant text and support durable structured output via getAgentToolOutput/getAgentToolSummary. Update docs/design to note output must be persisted before the child turn finishes and keep summaries concise. Fix useAgentChat isServerStreaming cleanup when a resumed stream first enters the fallback observer path and later becomes transport-owned, and add a test covering that behavior. Add test helpers and tests for skipped agent-tool turns (marking them as errors with a clear message) and clean up in-memory bookkeeping after runs complete. --------- Co-authored-by: Sunil Pai <spai@cloudflare.com>github.com-cloudflare-agents · 5373f5ca · 2026-05-12
- 0.4ETVExpose container placement ID on the sandbox (#592) * Expose container placement ID on the sandbox Detecting container replacement currently requires callers to write sentinel files into the container and read them back, which fails the moment the container is unhealthy. Capture CLOUDFLARE_PLACEMENT_ID on the session-create handshake and cache it in Durable Object storage. A new sandbox.getContainerPlacementId() reads the cached value without contacting the container, so callers can compare it against a stored value to detect replacement even when the container is down. * Carry container placement ID through RPC transport The RPC SandboxUtilsAPI.createSession return type and its container implementation did not surface containerPlacementId, so the Sandbox DO could not capture the placement ID when reaching the container over capnweb. Mirror the HTTP handler: include containerPlacementId on the success response and inject it into SESSION_ALREADY_EXISTS error context, so a restarted DO can recover the placement ID from an idempotent retry. * Cover placement ID capture in capnweb E2E suite Add a /api/placement-id route to the test worker that returns sandbox.getContainerPlacementId(), and assert in the capnweb transport suite that a value is captured (string when CLOUDFLARE_PLACEMENT_ID is set, null otherwise) after a session handshake. Guards against the RPC transport silently dropping the field again. --------- Co-authored-by: Aron <263346377+aron-cf@users.noreply.github.com>github.com-cloudflare-sandbox-sdk · b2bf0210 · 2026-04-27
- 0.4ETVfix(ai-chat): preserve first useAgentChat message during initial URL resolution (#1541) * fix(ai-chat): preserve immediate first chat send * test(ai-chat): cover late hydration after first send * fix(ai-chat): merge late history after initial sendgithub.com-cloudflare-agents · bc2b1d38 · 2026-05-19
- 0.3ETVFix agent-tool recovery finalization (#1476) * Fix agent tool recovery finalization * Clarify agent tool recovery changesetgithub.com-cloudflare-agents · 3c48858d · 2026-05-08
- 0.2ETVFix reasoning chunks in approval continuations (#1481) * Fix reasoning chunks in approval continuations * Fix persisted continuation reasoning * Preserve interrupted reasoning continuation * Add tests for reasoning continuation handling Add tests to verify reasoning continuation is persisted and handled correctly in two scenarios: - client-tools-continuation.test.ts: adds a test that ensures reasoning is persisted when a tool-result auto-continuation occurs without delayed chunks, asserting both the initial and continuation reasoning parts are stored as done. - continue-last-turn.test.ts: adds a test that verifies an orphaned continuation (recovered from an interrupted stream) is appended as a new reasoning part after an already-completed reasoning part, and that the recovered text part is persisted as a completed text part. These tests strengthen recovery/continuation behavior coverage for tool-result continuations and interrupted-stream recovery. --------- Co-authored-by: Sunil Pai <spai@cloudflare.com>github.com-cloudflare-agents · 12365dd6 · 2026-05-12
- 0.2ETVCoalesce concurrent destroy() calls (#601) * Coalesce concurrent destroy() calls Callers that invoke destroy() faster than the sandbox can tear down (e.g. an upstream health-check loop) used to spawn multiple concurrent teardowns that fought for the same container lifecycle and accumulated cost per call. Coalesce instead: track the in-flight destroy promise and have concurrent callers await the same work. A canonical sandbox.destroy.coalesced event is logged per coalesced call so repeated destroy traffic is observable. The boundary is the promise itself. There is no magic timeout: once the in-flight destroy settles (resolved or rejected) the field is cleared and a later destroy() call starts a fresh teardown. Rejections propagate to every coalesced caller identically. Three focused tests cover concurrent coalescing, shared rejection propagation, and fresh-teardown-after-settle. Uses an IIFE-style assignment so concurrent callers observe the inflight promise before any await point inside doDestroy(). * Document hung-teardown semantics of destroy() coalescing A stuck super.destroy() leaves inflightDestroy set and makes every coalesced caller wait until DO eviction. Call it out explicitly on the field's doc so the behavior is semantically honest rather than a silent hang, and tell callers who need bounded waits to apply their own timeout around destroy(). * Tighten inflightDestroy cleanup comment Describe current behavior rather than a hypothetical refactor, per AGENTS.md guidance on comments.github.com-cloudflare-sandbox-sdk · 51f1d04b · 2026-04-27
- 0.2ETVfix voice workers ai stt turn handling (#1458)github.com-cloudflare-agents · 84cb429f · 2026-05-04
- 0.2ETVfix voice streaming for AI SDK textStream (#1462)github.com-cloudflare-agents · 5f6214dc · 2026-05-06
- 0.1ETVfix(ai-chat): close stream on socket disconnect (#1487)github.com-cloudflare-agents · 752e25ab · 2026-05-09
- 0.1ETVAdd enabled gate to useVoiceAgent (#1478)github.com-cloudflare-agents · 2c7d91b7 · 2026-05-08
- 0.1ETV[Sandbox] Clarify user workspace guidance (#31069) * [Sandbox] Clarify user workspace guidance * Update src/content/docs/sandbox/concepts/sessions.mdx Co-authored-by: ask-bonk[bot] <249159057+ask-bonk[bot]@users.noreply.github.com> --------- Co-authored-by: ask-bonk[bot] <249159057+ask-bonk[bot]@users.noreply.github.com>github.com-cloudflare-cloudflare-docs · 2ccd6ef4 · 2026-05-27
- 0.1ETVthink: expose additive stop conditions (#1561)github.com-cloudflare-agents · 831ba1d2 · 2026-05-19
- 0.1ETVfix closed websocket replay race in @cloudflare/think (#1463) Mirror the sendIfOpen pattern that ai-chat already uses for the stream-resume ACK fallback. Without this, when the WebSocket closes during ResumableStream.replayCompletedChunksByRequestId the method now returns false (since #1376), and the fallback bare connection.send() in _handleStreamResumeAck throws TypeError: WebSocket send() after close up through onMessage.github.com-cloudflare-agents · ab2b1db3 · 2026-05-05
- 0.1ETV[Agents] Add SDK v0.12.4 changelog (#30792) * [Agents] Add SDK v0.12.4 changelog * [Agents] Fix changelog TypeScript snippetgithub.com-cloudflare-cloudflare-docs · ce79030c · 2026-05-13