Skip to content

feat(agents): move sessions into a Lifecycle capability - #2196

Merged
mattzcarey merged 31 commits into
mainfrom
feat/move-sessions-into-a-capability
Sep 3, 2026
Merged

feat(agents): move sessions into a Lifecycle capability#2196
mattzcarey merged 31 commits into
mainfrom
feat/move-sessions-into-a-capability

Conversation

@mattzcarey

@mattzcarey mattzcarey commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds the experimental agents/sessions Lifecycle capability and the agents/context module, and moves Think and AIChatAgent conversation persistence onto them.

Sessions owns durable conversation storage and nothing else: a tree of messages with branches and compaction overlays, streamed and byte-budgeted reads, opt-in full-text search, and a content-addressed attachment store.

The old agents/experimental/memory provider stack, its Postgres providers, and SessionManager are removed. A user-facing conversation directory remains the responsibility of a parent or router Durable Object.

Nothing is truncated, and nothing is too large to store

Two independent mechanisms, split by type rather than by size.

Attachments leave the message. A part that declares a non-text media type and carries its bytes inline — an image, an audio clip, a PDF — is stored outside the row under its SHA-256. The part keeps its shape and mediaType; only the payload becomes an attachment:sha256:<hex> pointer. Reads put it back verbatim.

The rule is uniform: an image is extracted at 8 KB and at 8 MB, and prose is never extracted at any size. A message's stored shape therefore never depends on how large an image happened to be.

Row chunking is the size backstop. A message whose serialized JSON still exceeds MAX_INLINE_ROW_BYTES (1.5 MiB) is split across numbered continuation rows and reassembled on read, cut on UTF-8 byte boundaries and never through a surrogate pair. There is no ceiling and no size error.

The two never interact: media leaves before the row is measured, so a message carrying a large image usually has no continuation rows at all.

Payload lifetime is derived from reference rows; bytes go when the last reference does. Content addressing buys idempotency on a retried write, not a space saving — nothing in the design assumes payloads repeat.

Why this is not the layer an earlier revision removed

That one extracted only when a row was over budget, which made it a rescue mechanism competing with chunking — and it could not do the job it existed for, because extraction needed an extractable leaf. A row over budget from bloated metadata or thousands of small parts had nothing to extract and failed. Chunking won that argument; this store is an ingest rule, not a rescue.

What it costs

A 200 KB image bills four row writes — the message, one payload chunk, its metadata, one reference — where inlining billed one. A 2 MiB image bills five. Text is unaffected at one row. The bench asserts these exactly.

What that buys is a message row that stays a few hundred bytes however large the payload is, which is what makes pointer-mode reads cheap and the byte budget meaningful.

Hydration budgets bound memory

getRecentHistory(maxContentBytes) charges each row its stored bytes, its continuation rows, and the payloads it points at, at inlined size. Extraction makes the row of a message carrying a 2 MB image tiny, so counting rows alone would let a budget admit a window that hydrates far larger than it measured.

The budget is a hard ceiling with no message-count floor beneath it. A floor that admitted rows regardless of size is not a floor under a budget, it is a hole in one — twenty media-heavy rows would be admitted whatever the limit said. The newest message is always returned. minRecentMessages is gone.

This does change Think: its window can be shorter than MODEL_RECENT_WINDOW when messages are unusually large. With the 32 MiB default it only ever binds on media, since 32 MiB of text is far past what any model could read.

Storage economics

Every table is WITHOUT ROWID with a composite primary key and no secondary index, ordered by a per-session seq. A text append with search off bills one row write, down from two. An unchanged update writes nothing: no row, no continuation, no FTS churn, no event. State is derived rather than maintained.

The attachment reference table carries no index on hash: it takes a write on every media append, and the reachability check that reads it is a scan of a small table, which is far cheaper than maintaining an index on the write path.

Context is not conversation storage

Context blocks, frozen prompts, and the search provider move to a new agents/context module. Think declares blocks through a new configureContext() hook and reaches them through this.context; configureSession() keeps compaction and search. The Session handle stores messages and knows nothing about prompts.

History shaping deliberately stays with the hosts for now. Truncating old tool output slides its boundary a little further every turn, and a sliding boundary rewrites the prompt prefix, which is what invalidates a cache. Moving it here before that is understood would relocate the problem into the module meant to solve it. See #2200.

Intake shaping — the read-path half of #2201 — is stacked on this branch as #2203.

Host mappings

Think

Keeps its message cache, reconciliation, broadcasts, model assembly, branching, and public arrays. hydrationByteBudget defaults to 32 MiB and now bounds memory. Media eviction is unchanged in purpose and simpler in code: it reads inlined history, decodes a data: URL directly, and its Workspace write, [evicted …] marker and /attachments/evicted/ paths are untouched. Rewriting a message to a marker now also drops its attachment reference, so eviction genuinely reclaims session storage rather than only shortening context. Think no longer reads Sessions tables with raw SQL.

AIChatAgent

Keeps its mutable messages array, destructive regeneration, retention, broadcasts, and v4 conversion. Boot no longer loads the transcript synchronously in the constructor: the legacy lift and one bounded hydration run in onStart, the live array mirrors the Sessions change feed, and get-messages streams its response.

Removed

The synchronous storage aperture (session.importMessage() replaces its import use), the R2 tier, the aged-row maintenance pass, the lossy eviction mode, SessionMessageTooLargeError and the size ceiling it guarded, sessionAttachments, sanitizeToolPairs, the token-counter and CompactContext plumbing, onCompactionError, the missingUpdate option, the per-field option thunks, and a duplicate copy of the sanitize helpers.

SessionStats loses totalContentBytes and pathLength. Nothing read either, and both measured only the active branch — excluding other branches, other sessions in the object, and the attachment tables — so as a size signal they answered a different question than the one anyone would ask them. A real signal against the 10 GB ceiling has to sum the tables and deserves its own function.

Migration

Legacy assistant_* message and compaction rows are lifted in SQL. Each source is dropped only after every one of its rows is verified to have a copy holding the same payload; there are no tombstones, because 5 GB of duplicated history in a 10 GB object is its own outage. A lift that cannot verify itself leaves the source in place and does not stamp the schema version, so a later start retries rather than stranding the rows.

AIChatAgent lifts cf_ai_chat_agent_messages into a linear chain and drops it only when every row imported — a row that failed to parse is skipped, not migrated, and dropping the table on a skip would delete it permanently.

The Sessions schema itself has never been deployed, so it needs no migration of its own.

Measured

Against 251,895 real messages from local Claude Code and pi transcripts: three exceed the 1.5 MiB row budget, all three in pi, and all three also exceed SQLite's 2 MB ceiling — so without chunking they would have been outright insert failures rather than degraded writes. The largest purely model-generated message anywhere is 215 KB, about 13.6% of the budget. Inbound tool content, not model output, is what gets large.

Prior deployed runs also confirmed the 32 MiB budget genuinely bounding hydration (19 of 536 messages, 31.11 MiB) and Think/AIChat migrations landing byte-identical. Full detail in design/sessions.md.

Validation

  • agents: 118 files, 1887 tests passing
  • @cloudflare/think: 44 files, 882 tests passing
  • @cloudflare/ai-chat: 50 files, 664 tests passing
  • 117 typecheck projects, oxfmt, oxlint, sherif, and the package exports check all clean

Follow-ups filed: #2204 (optional R2 tier for the attachment store), #2205 (the change-feed cache mirror is duplicated in every host).

@changeset-bot

changeset-bot Bot commented Sep 1, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: d212bf1

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

This PR includes changesets to release 4 packages
Name Type
@cloudflare/think Minor
@cloudflare/ai-chat Minor
agents Minor
@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

devin-ai-integration[bot]

This comment was marked as resolved.

@pkg-pr-new

pkg-pr-new Bot commented Sep 1, 2026

Copy link
Copy Markdown

Open in StackBlitz

agents

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

@cloudflare/ai-chat

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

@cloudflare/codemode

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

hono-agents

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

@cloudflare/shell

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

@cloudflare/think

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

@cloudflare/voice

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

@cloudflare/worker-bundler

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

commit: d212bf1

… context

Sessions stored large content by truncating it and budgeted hydration by
stored bytes, so a pointer row costing 8 MiB of memory was charged the ~100
bytes it occupies on disk. It also owned prompt assembly, which is not
conversation storage.

Storage. Every table is now WITHOUT ROWID with a composite key and no
secondary index, ordered by a per-session `seq`, so a text append bills one
row instead of two. The attachment reference table is (session_id,
message_id, hash) and nothing else. An unchanged update writes nothing at
all: no row, no FTS churn, no reference rewrite, no event.

Offload. Media leaves the row at a size threshold wherever it appears,
including `data:` URLs nested in tool output. Everything else, prose
included, is offloaded largest-first only when the row cannot hold it, and a
row that still does not fit raises SessionMessageTooLargeError. Nothing is
truncated, and offloaded content reconstructs byte for byte. The aged-row
maintenance pass applies that same policy, so a drained legacy row ends up
exactly as if it had been written today.

Memory. getRecentHistory charges each row its stored bytes plus, when
reconstructing inline, the attachment bytes it re-inflates. That is the
difference between a budget that bounds disk and one that bounds the
isolate. Think and AIChatAgent both default to 32 MiB.

Context. Blocks, frozen prompts, and the skill and search providers move to
`agents/context`. Think declares them through a new configureContext() hook
and reaches them through `this.context`; configureSession() keeps compaction
and search. The Session handle stores messages and knows nothing about
prompts.

Hosts. AIChatAgent no longer loads the transcript in its constructor: the
legacy lift and one bounded hydration run at start, the live array mirrors
the change feed, and get-messages streams. Think reads pointers on its
per-tool-result scan and no longer reads Sessions tables with raw SQL.

Deleted: the synchronous storage aperture, the lossy eviction mode,
sanitizeToolPairs, the token-counter plumbing, the per-field option thunks,
and a duplicate copy of the sanitize helpers.

Measured on a deployed worker with a real R2 bucket
(examples/next/sessions-slam, 33 scenarios): one billed row per append,
1.6 MB and 5 MB text parts and a 3 MB tool output offloaded rather than cut,
inline hydration stopping at 31.11 MiB against a 32 MiB budget, and 61.79
MiB of history streamed out of a 128 MiB isolate. Numbers are recorded in
design/sessions.md.

Claude-Session: https://claude.ai/code/session_01MXpoKqJrUFTqgmDrehDti4
devin-ai-integration[bot]

This comment was marked as resolved.

agent-think lives outside packages/ and examples/, so it was missed when the
context system moved out of the Session handle. Its identity block is now
declared through configureContext() and refreshed through this.context.

Claude-Session: https://claude.ai/code/session_01MXpoKqJrUFTqgmDrehDti4
Renaming each lifted table to `*__lifted_v1` left every upgraded object
storing its conversation history twice. A Durable Object tops out at 10 GB
and gets uncomfortable well before that, so a 5 GB history plus its copy has
nowhere to go. The copy already needs that space transiently, which is
exactly why it must not be kept.

Each source is now verified against its destination row by row, comparing
the payload rather than just the key, and dropped only when every row
arrived intact. A table that fails verification is left in place with a
`session:migration:incomplete` event, so a partial lift keeps the only copy
of its rows instead of destroying it. `assistant_sessions` and
`assistant_fts` carry nothing the new schema needs, the registry being
derived and the index rebuilt, so they are dropped outright.

Think lifts `assistant_config` into its own table and now drops it too.
AIChatAgent drops `cf_ai_chat_agent_messages` once every readable row has a
copy, and its lift no longer reads the whole table into the isolate: order is
read as ids alone, then bodies are fetched in windows bounded by rows and
bytes, so a large transcript never lands in memory at once.

Verified against real deployed storage by seeding a Think agent and an
AIChatAgent on the pre-Sessions SDK and redeploying the identical worker
built against this branch over the same objects. Think carried 5 rows and
67,184 bytes across with its branch topology and ids intact, AIChatAgent 4
rows and 53,765 bytes including a 53 KB inline image, both byte-identical,
with no legacy or tombstone table left behind.

Claude-Session: https://claude.ai/code/session_01MXpoKqJrUFTqgmDrehDti4
devin-ai-integration[bot]

This comment was marked as resolved.

…oviders

Storage classified payloads by content type: media left the row at a 32 KiB
threshold, everything else only to keep the row under its budget. Reading a
PDF through pi settles that this is backwards. A document arrives as plain
tool-output text with no media type, so the rule optimised the small case and
ignored the large one. Deduplication, the other argument for it, does not
depend on type either.

Extraction into the attachment tables does not make the database smaller:
chunk rows live in the same Durable Object, inside the same 10 GB. Only R2
reclaims space. And billing counts rows written, not bytes, so rewriting a
500 KB row costs the same single row as a tiny one while extracting it costs
four.

So there is now one rule and no content types in it. A payload is extracted
when a bucket is configured and it reaches `r2ThresholdBytes`, which is the
only extraction that reclaims anything, or when the row cannot otherwise hold
it, largest first, into chunks. `inlineThresholdBytes` is gone and the R2
threshold is the single number. The maintenance pass returns immediately
without a bucket, because inline is then the correct resting place.

Separately, the skill-provider path is deleted: `R2SkillProvider`,
`isSkillProvider`, the load and unload skill state on `ContextBlocks`, the
`load_context` and `unload_context` tools, and the helpers that replayed that
state from the transcript. Nothing ever registered a provider with a `load()`
method. Think shipped its own Agent Skills through `agents/skills` before this
path had a user and registers a plain readonly catalog block, so the tools
never appeared and the history scan always returned immediately. A dead prompt
line telling the model to use context-loading tools went with it.
`agents/context` drops from 1,387 lines to about 880.

Think's media eviction is untouched. It decides what the model sees, which is
a different question from where bytes live.

Claude-Session: https://claude.ai/code/session_01MXpoKqJrUFTqgmDrehDti4
devin-ai-integration[bot]

This comment was marked as resolved.

Sessions is a message store, not a file store. A message can reference a
file without being one, and hosts that handle files already have somewhere
to put them: Think's Workspace spills to R2 at 1,500,000 bytes, the same
threshold the session tier used, so the two were doing one job twice.

With R2 gone there is no reason to extract a payload eagerly at all, because
chunk rows live in the same Durable Object and never reclaim a byte. The rule
is now one sentence with no configuration: a payload stays in its message row
until the row cannot hold it, and then the largest payloads are chunked out
until it fits.

That takes the aged-row maintenance pass with it. Its only remaining job was
draining rows into R2, so the pass, its scheduler, its backlog chaining, the
`offload_candidate_bytes` column and the four core methods that stamped and
read it are all gone. Think never used it: it disables the pass whenever its
own media eviction is on and drives that from a truncated hydration read.

Also removed: the R2 bucket port, key construction and cleanup, the
declared-versus-unknown-length streaming split and `FixedLengthStream`, the
`backend` and `r2_key` blob columns, and the in-memory bucket fakes three
packages carried to observe a tier that no longer exists.
`SessionsAttachmentOptions` goes from seven fields to three.

Think's media eviction is untouched in behavior. It decides what the model
sees, which is a different question from where bytes live, and it is what
moves bytes to the Workspace.

The sessions-slam example is deleted along with the measured table it fed, so
the docs no longer quote numbers nothing can reproduce.

Found in passing: ai-chat's test worker was inserting into a column renamed
some time ago, which surfaced as seven swallowed unhandled rejections in a
passing run.

Adds design/context.md, recording that prompt assembly and history shaping
belong in agents/context while retention stays with the host that owns the
file store, and that shaping tool output at the boundary is the missing third
piece (#2201).

Claude-Session: https://claude.ai/code/session_01MXpoKqJrUFTqgmDrehDti4
devin-ai-integration[bot]

This comment was marked as resolved.

Media declared with a non-text media type and carried inline is stored
separately, addressed by SHA-256, and inlined again on read. The message
keeps a pointer and its mediaType, so a round trip is exact and a row
stays small however large its payloads are. Read with
{ attachments: "pointer" } to see references instead.

The rule is typed rather than sized. An image is extracted at any size
and text is never extracted at any size, so a message's stored shape
never depends on how large an image happened to be. Row chunking stays
as the independent size backstop for prose: the two never interact,
because media leaves before the row is measured.

This is not the layer that was removed. That one extracted only when a
row was over budget, which made it a rescue mechanism competing with
chunking and one that could fail with nothing to extract. 775 lines
replace 1,477.

Payload lifetime is derived from reference rows, taken from the stored
message rather than from what a given write extracted, so a pointer-mode
read written back keeps its payload alive. SessionRowStat.bytes charges
each message for what it points at, at inlined size, so a byte budget
still bounds real hydrated memory.

Cost, measured: a 200 KB image bills four rows and a 2 MiB image five,
against one when inlined. Text messages are unchanged at one row.

Also adds agents/context intake shaping. shapeMessage/shapeHistory cap
oversized tool results with a continuation hint and drop host-named
duplicate fields, on the read path so storage stays lossless. The limits
are a function of one message, so a shaped prefix stays byte-identical
across turns and prompt caching holds — which is why this landed here
and sliding history truncation stayed with the hosts.

Claude-Session: https://claude.ai/code/session_01MXpoKqJrUFTqgmDrehDti4
Pi resizes images on the way into context. We deliberately do not, and
this records why rather than leaving it as an open question: downscaling
re-encodes a user's own bytes, which is a lossy transform of content
nobody asked us to change, and it is the one kind of shaping a host
cannot undo afterwards. Text caps and duplicate-field dropping stay.

Claude-Session: https://claude.ai/code/session_01MXpoKqJrUFTqgmDrehDti4
Intake shaping is a separate concern from keeping attachments out of the
message, and reviewing them together obscures both. It lands on a branch
stacked on this one; nothing here depends on it.

Claude-Session: https://claude.ai/code/session_01MXpoKqJrUFTqgmDrehDti4
devin-ai-integration[bot]

This comment was marked as resolved.

…to-a-capability

# Conflicts:
#	design/rfc-think-multi-session.md
…ions losing rows

Three review findings, all real.

The hydration budget was not a bound. `getRecentHistory` admitted rows
whenever fewer than `minRecentMessages` had been taken, whatever they
weighed, so a window of media-heavy messages hydrated far past the limit
that was supposed to cap it. A floor that ignores size is not a floor
under a budget, it is a hole in one. The parameter is gone from core,
handle, Think and AIChat; the budget is a hard ceiling that always
returns at least the newest message.

Think's window can therefore be shorter than MODEL_RECENT_WINDOW when
messages are unusually large. That is the intended trade: with a 32 MB
budget it only ever binds on media, and 32 MB of text is far past what
any model could read anyway.

AIChat's legacy lift could delete history. It dropped the source table
when `imported + skipped === order.length` — but a skipped row is one
that could NOT be parsed or imported, so accounting for it and migrating
it are not the same thing, and any malformed row was destroyed. It now
drops only when every row actually landed, and says what it kept.

Sessions stamped its schema version even when `migrateLegacy` reported
an incomplete copy, so the lift never retried and the rows it left
behind stayed unreachable. `migrateLegacy` now reports completeness and
the version is stamped only on success. Both lifts are idempotent, so
retrying costs reads and nothing else.

Also resolves the conflict with main in rfc-think-multi-session.md,
taking main's text, which records the same supersession plus the
replacement RFC.

Claude-Session: https://claude.ai/code/session_01MXpoKqJrUFTqgmDrehDti4
@agent-think

agent-think Bot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

🟡 agents import sizes

Measured 294 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 101 0 159 7 27

Compared 6da4c44b with d212bf1b. Open workflow run.

Changed imports (135)
Status Import Base gzip Head gzip Delta
🟡 agents/chat#byteLength 2.3 KiB 2.5 KiB +148 B (+6.26%)
🟡 agents/skills#SkillRegistry 397.5 KiB 416.4 KiB +18.9 KiB (+4.75%)
🟡 agents/chat#enforceRowSizeLimit 3.4 KiB 3.5 KiB +145 B (+4.21%)
🟡 agents/chat#CHAT_RECOVERY_INCIDENT_KEY_PREFIX 2.3 KiB 2.3 KiB +20 B (+0.85%)
🟡 agents/chat#crossMessageToolResultUpdate 2.4 KiB 2.4 KiB +20 B (+0.81%)
🟡 agents/chat#buildInClauseStrings 2.4 KiB 2.4 KiB +20 B (+0.81%)
🟡 agents/chat#AutoContinuationController 2.3 KiB 2.3 KiB +19 B (+0.81%)
🟡 agents/chat#CHAT_RECOVERY_STABLE_RETRY_DELAY_SECONDS 2.3 KiB 2.3 KiB +19 B (+0.81%)
🟡 agents/chat#DEFAULT_CHAT_RECOVERY_MAX_OOM_RETRIES 2.3 KiB 2.3 KiB +19 B (+0.81%)
🟡 agents/chat#CHAT_RECOVERY_PROGRESS_KEY 2.3 KiB 2.3 KiB +19 B (+0.8%)
🟡 agents/chat#CHAT_LAST_TERMINAL_KEY 2.3 KiB 2.3 KiB +19 B (+0.8%)
🟡 agents/chat#pendingChatTerminal 2.3 KiB 2.3 KiB +19 B (+0.8%)
🟡 agents/chat#clearChatTerminal 2.3 KiB 2.3 KiB +19 B (+0.8%)
🟡 agents/chat#recordChatTerminal 2.3 KiB 2.4 KiB +19 B (+0.79%)
🟡 agents/chat#ChatStreamStalledError 2.3 KiB 2.4 KiB +19 B (+0.79%)
🟡 agents/chat#sendIfOpen 2.4 KiB 2.4 KiB +19 B (+0.78%)
🟡 agents/chat#resolveToolMergeId 2.4 KiB 2.4 KiB +19 B (+0.78%)
🟡 agents/chat#reconcileOrphanPartial 2.4 KiB 2.4 KiB +19 B (+0.78%)
🟡 agents/chat#unwrapChatFiberSnapshot 2.4 KiB 2.4 KiB +19 B (+0.77%)
🟡 agents/chat#CHAT_RECOVERING_FLAG_TTL_MS 2.3 KiB 2.3 KiB +18 B (+0.77%)
🟡 agents/chat#CHAT_RECOVERY_INCIDENT_TTL_MS 2.3 KiB 2.3 KiB +18 B (+0.77%)
🟡 agents/chat#normalizeToolInput 2.3 KiB 2.3 KiB +18 B (+0.77%)
🟡 agents/chat#applyChunkToParts 2.3 KiB 2.3 KiB +18 B (+0.77%)
🟡 agents/chat#CHAT_MESSAGE_TYPES 2.3 KiB 2.3 KiB +18 B (+0.77%)
🟡 agents/chat#chatRecoveryTaskRunOptions 2.4 KiB 2.4 KiB +19 B (+0.77%)
🟡 agents/chat#DEFAULT_CHAT_RECOVERY_MAX_ATTEMPTS 2.3 KiB 2.3 KiB +18 B (+0.77%)
🟡 agents/chat#KV_DELETE_MAX_KEYS 2.3 KiB 2.3 KiB +18 B (+0.77%)
🟡 agents/chat#AGENT_TOOL_STREAM_PROGRESS_BUMP_THROTTLE_MS 2.3 KiB 2.3 KiB +18 B (+0.77%)
🟡 agents/chat#CHAT_STREAM_PROGRESS_CREDIT_THROTTLE_MS 2.3 KiB 2.3 KiB +18 B (+0.77%)
🟡 agents/chat#DEFAULT_CHAT_RECOVERY_MAX_WORK 2.3 KiB 2.3 KiB +18 B (+0.77%)
🟡 agents/chat#DEFAULT_CHAT_RECOVERY_STABLE_TIMEOUT_MS 2.3 KiB 2.3 KiB +18 B (+0.77%)
🟡 agents/chat#MAX_BOUND_PARAMS 2.3 KiB 2.3 KiB +18 B (+0.77%)
🟡 agents/chat#sweepStaleChatRecoveryIncidents 2.4 KiB 2.4 KiB +19 B (+0.76%)
🟡 agents/chat#CHAT_RECOVERING_KEY 2.3 KiB 2.3 KiB +18 B (+0.76%)
🟡 agents/chat#wrapChatFiberSnapshot 2.3 KiB 2.3 KiB +18 B (+0.76%)
🟡 agents/chat#cleanupStreamBuffers 2.3 KiB 2.3 KiB +18 B (+0.76%)
🟡 agents/chat#clientResolvableToolNames 2.3 KiB 2.3 KiB +18 B (+0.76%)
🟡 agents/chat#readChatRecoveryProgress 2.3 KiB 2.3 KiB +18 B (+0.76%)
🟡 agents/chat#drainInteractionApplies 2.3 KiB 2.3 KiB +18 B (+0.75%)
🟡 agents/chat#AgentToolStreamProgressThrottle 2.3 KiB 2.4 KiB +18 B (+0.75%)
🟡 agents/chat#StreamProgressCreditThrottle 2.3 KiB 2.4 KiB +18 B (+0.75%)
🟡 agents/chat#bumpChatRecoveryProgress 2.3 KiB 2.4 KiB +18 B (+0.75%)
🟡 agents/chat#repairInterruptedToolParts 2.6 KiB 2.6 KiB +20 B (+0.75%)
🟡 agents/chat#shouldCreditStreamProgress 2.3 KiB 2.4 KiB +18 B (+0.75%)
🟡 agents/chat#applyToolUpdate 2.4 KiB 2.4 KiB +18 B (+0.74%)
🟡 agents/chat#buildChatRecoveringFrame 2.4 KiB 2.4 KiB +18 B (+0.74%)
🟡 agents/chat#isReplayChunk 2.4 KiB 2.4 KiB +18 B (+0.74%)
🟡 agents/chat#pausedExecutionUpdate 2.4 KiB 2.4 KiB +18 B (+0.74%)
🟡 agents/chat#toolResultUpdate 2.4 KiB 2.4 KiB +18 B (+0.74%)
🟡 agents/chat#awaitWithDeadline 2.4 KiB 2.4 KiB +18 B (+0.74%)
🟡 agents/chat#partAwaitsClientInteraction 2.4 KiB 2.4 KiB +18 B (+0.74%)
🟡 agents/chat#toolApprovalUpdate 2.4 KiB 2.4 KiB +18 B (+0.73%)
🟡 agents/chat#runChatRecoveryExhaustion 2.5 KiB 2.6 KiB +19 B (+0.73%)
🟡 agents/chat#classifyAgentToolChildRecovery 2.4 KiB 2.4 KiB +18 B (+0.73%)
🟡 agents/chat#hasIncompleteToolBatch 2.4 KiB 2.4 KiB +18 B (+0.73%)
🟡 agents/chat#aiSdkRecoveryCodec 2.3 KiB 2.3 KiB +17 B (+0.72%)
🟡 agents/chat#CHAT_RECOVERY_ALARM_DEBOUNCE_MS 2.3 KiB 2.3 KiB +17 B (+0.72%)
🟡 agents/chat#DEFAULT_CHAT_RECOVERY_NO_PROGRESS_TIMEOUT_MS 2.3 KiB 2.3 KiB +17 B (+0.72%)
🟡 agents/chat#STREAM_CLEANUP_DELAY_SECONDS 2.3 KiB 2.3 KiB +17 B (+0.72%)
🟡 agents/chat#setChatRecovering 2.4 KiB 2.5 KiB +18 B (+0.72%)
🟡 agents/chat#TIMED_OUT 2.3 KiB 2.3 KiB +17 B (+0.72%)
🟡 agents/chat#createChatFiberSnapshot 2.4 KiB 2.5 KiB +18 B (+0.72%)
🟡 agents/chat#createChatRecoveryTaskDefinition 2.6 KiB 2.6 KiB +19 B (+0.72%)
🟡 agents/chat#isPlatformFailure 2.6 KiB 2.6 KiB +19 B (+0.71%)
🟡 agents/chat#DEFAULT_CHAT_RECOVERY_TERMINAL_MESSAGE 2.3 KiB 2.4 KiB +17 B (+0.71%)
🟡 agents/chat#createChatTurnTaskDefinition 2.6 KiB 2.7 KiB +19 B (+0.7%)
🟡 agents/chat#ContinuationState 2.6 KiB 2.7 KiB +19 B (+0.7%)
🟡 agents/chat#AbortRegistry 2.5 KiB 2.5 KiB +18 B (+0.7%)
🟡 agents/chat#listActiveChatRecoveryIncidents 2.4 KiB 2.4 KiB +17 B (+0.69%)
🟡 agents/chat#resolveChatRecoveryConfig 2.5 KiB 2.6 KiB +18 B (+0.69%)
🟡 agents/chat#MessageType 2.4 KiB 2.4 KiB +17 B (+0.69%)
🟡 agents/chat#iterateWithStallWatchdog 2.6 KiB 2.6 KiB +18 B (+0.68%)
🟡 agents/chat#ROW_MAX_BYTES 2.3 KiB 2.3 KiB +16 B (+0.68%)
🟡 agents/chat#CHAT_RECOVERY_TASK_NAME 2.3 KiB 2.3 KiB +16 B (+0.68%)
🟡 agents/chat#interceptAgentToolBroadcast 2.5 KiB 2.5 KiB +17 B (+0.67%)
🟡 agents/chat#PreStreamTurns 2.6 KiB 2.6 KiB +18 B (+0.67%)
🟡 agents/chat#createAgentToolEventState 2.3 KiB 2.3 KiB +16 B (+0.67%)
🟡 agents/chat#STREAM_RESUME_NONE_REASONS 2.3 KiB 2.3 KiB +16 B (+0.67%)
🟡 agents/chat#StreamAccumulator 2.9 KiB 2.9 KiB +20 B (+0.67%)
🟡 agents/chat#AgentToolProgressEmitter 2.6 KiB 2.7 KiB +18 B (+0.66%)
🟡 agents/chat#parseProtocolMessage 2.5 KiB 2.5 KiB +17 B (+0.66%)
🟡 agents/chat#TurnQueue 2.6 KiB 2.6 KiB +17 B (+0.64%)
🟡 agents/chat#reconcileMessages 2.8 KiB 2.8 KiB +18 B (+0.64%)
🟡 agents/chat#applyAgentToolEvent 3.2 KiB 3.2 KiB +20 B (+0.62%)
🟡 agents/chat#TextSegmentJoiner 2.7 KiB 2.7 KiB +17 B (+0.62%)
🟡 agents/chat#persistReconstructedOrphan 3.0 KiB 3.1 KiB +19 B (+0.61%)
🟡 agents/chat#broadcastTransition 3.1 KiB 3.1 KiB +19 B (+0.59%)
🟡 agents/chat#toolPartHasSettledResult 2.3 KiB 2.3 KiB +14 B (+0.59%)
🟡 agents/chat#SubmitConcurrencyController 2.9 KiB 2.9 KiB +17 B (+0.58%)
🟡 agents/chat#ResumeHandshake 2.9 KiB 3.0 KiB +17 B (+0.56%)
🟡 agents/chat#dispatchChatRecoveryToHandoff 3.0 KiB 3.0 KiB +16 B (+0.52%)
🟡 agents/chat#ChatRecoveryEngine 4.4 KiB 4.4 KiB +16 B (+0.36%)
🟡 agents/chat#ResumableStream 4.6 KiB 4.6 KiB +15 B (+0.32%)
🟡 agents/chat#sanitizeMessage 2.5 KiB 2.5 KiB +8 B (+0.31%)
🟡 agents/chat#createChatStreams 5.5 KiB 5.5 KiB +17 B (+0.3%)
🟡 agents/chat#createToolsFromClientSchemas 114.3 KiB 114.3 KiB +19 B (+0.02%)
🟡 agents/skills#runner 369.0 KiB 369.0 KiB +9 B (+0%)
🟡 agents/skills#parseSkillFrontmatter 328.4 KiB 328.4 KiB +4 B (+0%)
🟡 agents/skills#r2 330.2 KiB 330.2 KiB +4 B (+0%)
🟡 agents/skills#fromManifest 309.8 KiB 309.8 KiB +2 B (+0%)
🟡 agents/skills#parseSkillMarkdown 328.6 KiB 328.6 KiB +1 B (+0%)
agents/chat#truncateOlderMessages 3.2 KiB
agents/context#AgentContextProvider 412 B
agents/context#AgentSearchProvider 640 B
agents/context#ContextBlocks 87.4 KiB
agents/sessions#createCompactFunction 1.7 KiB
agents/sessions#Session 1.9 KiB
agents/sessions#Sessions 8.8 KiB
🟢 agents/experimental/memory/session#AgentContextProvider 425 B
🟢 agents/experimental/memory/session#AgentSearchProvider 821 B
🟢 agents/experimental/memory/session#AgentSessionProvider 2.5 KiB
🟢 agents/experimental/memory/session#isSearchProvider 128 B
🟢 agents/experimental/memory/session#isSkillProvider 127 B
🟢 agents/experimental/memory/session#isWritableProvider 126 B
🟢 agents/experimental/memory/session#PostgresContextProvider 422 B
🟢 agents/experimental/memory/session#PostgresSearchProvider 630 B
🟢 agents/experimental/memory/session#PostgresSessionProvider 1.7 KiB
🟢 agents/experimental/memory/session#R2SkillProvider 436 B
🟢 agents/experimental/memory/session#Session 93.4 KiB
🟢 agents/experimental/memory/session#SessionManager 94.5 KiB
🟢 agents/experimental/memory/utils#alignBoundaryBackward 291 B
🟢 agents/experimental/memory/utils#alignBoundaryForward 275 B
🟢 agents/experimental/memory/utils#buildSummaryPrompt 867 B
🟢 agents/experimental/memory/utils#CHARS_PER_TOKEN 51 B
🟢 agents/experimental/memory/utils#COMPACTION_PREFIX 63 B
🟢 agents/experimental/memory/utils#computeSummaryBudget 363 B
🟢 agents/experimental/memory/utils#createCompactFunction 1.8 KiB
🟢 agents/experimental/memory/utils#estimateMessageTokens 336 B
🟢 agents/experimental/memory/utils#estimateStringTokens 142 B
🟢 agents/experimental/memory/utils#findTailCutByTokens 597 B
🟢 agents/experimental/memory/utils#isCompactionMessage 98 B
🟢 agents/experimental/memory/utils#sanitizeToolPairs 537 B
🟢 agents/experimental/memory/utils#TOKENS_PER_MESSAGE 51 B
🟢 agents/experimental/memory/utils#truncateOlderMessages 1022 B
🟢 agents/experimental/memory/utils#WORDS_TOKEN_MULTIPLIER 53 B
All 267 current runtime imports
Status Import Gzip Raw minified
agents#__DO_NOT_USE_WILL_BREAK__agentContext 258.6 KiB 1130.0 KiB
agents#__DO_NOT_USE_WILL_BREAK__withInvocationScope 258.6 KiB 1130.0 KiB
agents#Agent 258.6 KiB 1130.0 KiB
agents#AGENT_TOOL_MILESTONE_PART 258.6 KiB 1130.0 KiB
agents#AGENT_TOOL_PROGRESS_PART 258.6 KiB 1130.0 KiB
agents#buildAgentPath 259.1 KiB 1132.3 KiB
agents#buildAgentUrl 259.3 KiB 1132.7 KiB
agents#callable 258.6 KiB 1130.1 KiB
agents#camelCaseToKebabCase 258.6 KiB 1130.0 KiB
agents#createHeaderBasedEmailResolver 258.8 KiB 1130.4 KiB
agents#DEFAULT_AGENT_STATIC_OPTIONS 258.6 KiB 1130.0 KiB
agents#DurableObjectOAuthClientProvider 258.6 KiB 1130.0 KiB
agents#getAgentByName 258.6 KiB 1130.0 KiB
agents#getCurrentAgent 258.6 KiB 1130.0 KiB
agents#getSubAgentByName 258.9 KiB 1130.7 KiB
agents#isDurableObjectCodeUpdateReset 258.6 KiB 1130.0 KiB
agents#isDurableObjectMemoryLimitReset 258.6 KiB 1130.0 KiB
agents#isDurableObjectStorageReset 258.6 KiB 1130.1 KiB
agents#isPlatformTransientError 258.6 KiB 1130.0 KiB
agents#MCP_SERVER_ID_MAX_LENGTH 258.6 KiB 1130.0 KiB
agents#MessageType 258.8 KiB 1130.3 KiB
agents#normalizeServerId 258.6 KiB 1130.0 KiB
agents#parseSubAgentPath 258.6 KiB 1130.0 KiB
agents#routeAgentEmail 258.9 KiB 1130.7 KiB
agents#routeAgentRequest 259.2 KiB 1131.9 KiB
agents#routeSubAgentRequest 258.8 KiB 1130.6 KiB
agents#SqlError 258.6 KiB 1130.0 KiB
agents#StreamingResponse 258.6 KiB 1130.0 KiB
agents#SUB_PREFIX 258.6 KiB 1130.0 KiB
agents#unstable_callable 258.7 KiB 1130.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 146.0 KiB 630.3 KiB
agents/browser/ai#createBrowserTools 146.0 KiB 630.3 KiB
agents/browser/ai#createQuickActionTools 122.5 KiB 554.3 KiB
agents/browser/tanstack-ai#createBrowserTools 161.7 KiB 699.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.1 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#cleanupStreamBuffers 2.3 KiB 8.2 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 5.5 KiB 19.3 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 4.6 KiB 15.3 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_CLEANUP_DELAY_SECONDS 2.3 KiB 8.2 KiB
🟡 agents/chat#STREAM_RESUME_NONE_REASONS 2.3 KiB 8.3 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 261.0 KiB 1141.6 KiB
agents/chat-sdk#ChatSdkStateAgent 260.4 KiB 1139.1 KiB
agents/chat-sdk#createChatSdkState 261.0 KiB 1141.6 KiB
agents/chat-sdk#defaultKeyShard 258.8 KiB 1130.2 KiB
agents/chat-sdk#defaultThreadShard 258.7 KiB 1130.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 5.7 KiB 16.6 KiB
agents/client#AgentConnectionError 582 B 993 B
agents/client#agentFetch 4.2 KiB 12.3 KiB
agents/client#createStubProxy 638 B 1.0 KiB
agents/client#DEFAULT_CALL_TIMEOUT_MS 473 B 770 B
agents/client#isTerminalCloseEvent 509 B 822 B
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.3 KiB 25.8 KiB
agents/lifecycle#LifecycleCapability 484 B 975 B
agents/mcp#createLegacyMcpHandler 375.9 KiB 1572.2 KiB
agents/mcp#createMcpHandler 388.2 KiB 1617.4 KiB
agents/mcp#DurableObjectEventStore 342.5 KiB 1430.7 KiB
agents/mcp#ElicitRequestSchema 342.5 KiB 1430.7 KiB
agents/mcp#experimental_createMcpHandler 376.1 KiB 1572.5 KiB
agents/mcp#getMcpAuthContext 342.5 KiB 1430.8 KiB
agents/mcp#MCP_SERVER_ID_MAX_LENGTH 342.5 KiB 1430.7 KiB
agents/mcp#McpAgent 342.5 KiB 1430.7 KiB
agents/mcp#normalizeServerId 342.5 KiB 1430.7 KiB
agents/mcp#RPC_DO_PREFIX 342.5 KiB 1430.7 KiB
agents/mcp#RPCClientTransport 342.5 KiB 1430.7 KiB
agents/mcp#RPCServerTransport 342.5 KiB 1430.7 KiB
agents/mcp#SSEEdgeClientTransport 342.6 KiB 1431.0 KiB
agents/mcp#StreamableHTTPEdgeClientTransport 342.6 KiB 1431.0 KiB
agents/mcp#WorkerTransport 345.8 KiB 1447.6 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/react#_testUtils 3.8 KiB 9.5 KiB
agents/react#useAgent 10.8 KiB 31.1 KiB
agents/react#useAgentToolEvents 5.6 KiB 16.8 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#createCompactFunction 1.7 KiB 4.0 KiB
agents/sessions#Session 1.9 KiB 5.4 KiB
agents/sessions#Sessions 8.8 KiB 31.2 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/streams#DEFAULT_MAX_CHUNK_BYTES 83 B 81 B
agents/streams#sseResponse 843 B 1.6 KiB
agents/streams#StreamClosedError 161 B 197 B
agents/streams#StreamNotFoundError 201 B 261 B
agents/streams#Streams 3.4 KiB 11.1 KiB
agents/streams#StreamSerializationError 158 B 186 B
agents/tasks#DuplicateTaskStepError 328 B 463 B
agents/tasks#MAX_SERIALIZED_BYTES 190 B 232 B
agents/tasks#MissingTaskDefinitionError 358 B 536 B
agents/tasks#NonRetryableError 238 B 308 B
agents/tasks#TaskReplayDivergedError 341 B 483 B
agents/tasks#Tasks 8.9 KiB 31.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/websockets#CALLABLES_RPC_QUERY 12.4 KiB 43.3 KiB
agents/websockets#CALLABLES_RPC_VALUE 12.4 KiB 43.3 KiB
agents/websockets#callablesFromDecorated 12.7 KiB 44.3 KiB
agents/websockets#callablesRpcUrl 12.5 KiB 43.5 KiB
agents/websockets#isCallablesRpcUpgrade 12.4 KiB 43.4 KiB
agents/websockets#WebSockets 17.7 KiB 62.2 KiB
agents/workflows#AgentWorkflow 260.0 KiB 1134.8 KiB
agents/workflows#WorkflowRejectedError 258.7 KiB 1130.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.

`pathRowStats` charges a message for the payloads it points at, because
that is what a read materializes. The incremental stats cache did not:
it added the serialized POINTER json, so `stats().totalContentBytes`
depended on whether the cache happened to be warm.

Invalidate instead of tracking. Replicating the base64 charge in append
and update would put the formula in three places and let them drift,
which is how the two disagreed in the first place. A media write now
drops the cache and the next `stats()` derives it — one recursive CTE
read against writes that cost ~1000x more. Text writes, the hot path,
keep the incremental path untouched.

Narrow in practice: Think and pi read `totalContentBytes` from
`getRecentHistory`, which derives from `pathRowStats` on every call and
never from this cache, so no shipped behavior was wrong. But an API that
returns a different number depending on cache warmth is a trap, and the
regression test added here is the first thing that would have hit it.

Claude-Session: https://claude.ai/code/session_01MXpoKqJrUFTqgmDrehDti4
Two findings from auditing Think against the Sessions API.

`SessionStats` loses `totalContentBytes` and `pathLength`. Nothing read
either — Think and pi take their byte total from `getRecentHistory`,
which derives it from `pathRowStats` on every call and never from this
cache. Both fields also measured the ACTIVE BRANCH only, excluding other
branches, other sessions in the object, and the attachment tables, so as
a "how big is this session" signal they answered a different question
than the one anyone would ask them. A real size signal against the 10 GB
ceiling has to sum the tables and deserves its own function. What
remains is the token estimate that gates auto-compaction, which is the
only field with a reader and the reason the cache exists at all.

That also removes the cache invalidation added a commit ago: it existed
solely to keep `totalContentBytes` honest once row stats began charging
attachment bytes. Notably the field that diverged was the unused one —
`tokenEstimate` is stamped from the message BEFORE extraction, so it
always counted the payload and the compaction trigger was never wrong.

`appendMessage` now returns the same inlined message whether it inserted
or found a duplicate. It previously returned `getMessageRaw` on the
duplicate and not-inserted paths, so `AppendResult.message` and the
change feed carried `attachment:sha256:` pointers on some appends and
inline content on others — one call, two shapes, depending on whether
the row already existed.

Think compensated for that with `_messageForCache`, which serialized
every incoming message and substring-searched it for the pointer prefix
before deciding whether to re-read, on the streaming hot path. Fixing
the contract deletes the helper and its three call sites. AIChat's
similarly named helper stays: it does v4 to v5 transformation, which is
genuinely its own concern.

The remaining duplication — both hosts reimplementing the change-feed
cache mirror — is filed as #2205 rather than attempted here.

Claude-Session: https://claude.ai/code/session_01MXpoKqJrUFTqgmDrehDti4
devin-ai-integration[bot]

This comment was marked as resolved.

Finishing a fix I got half right. The previous commit made
`appendMessage`'s duplicate paths inline but left the inserted path
returning `prepared.message` — the caller's own object. So a caller that
reads with `attachments: "pointer"` and writes the result back got
pointer form on the insert and inline form on the retry: the same
inconsistency as before, mirrored.

It also invalidated the assumption the previous commit relied on to
delete Think's `_messageForCache`. That helper existed because the feed
could carry pointers; removing it was only safe if Sessions guarantees
it never does. For pointer-form writes, it did not, and the pointers
would have reached Think's live cache and then a model request.

`appendMessage` and `updateMessage` now pass what they return and emit
through `core.inlineMessage()`, so the guarantee holds for every write
regardless of what the caller supplied. It is a no-op by reference when
there are no pointers, so the ordinary write pays a walk and nothing
else.

The invariant now has one choke point instead of being maintained per
branch, which is what went wrong twice here: each fix made another call
site consistent rather than stating the contract in one place.

Both tests fail without the change: insert-then-duplicate returning
identical shapes with nothing pointer-shaped reaching a subscriber, and
the same for updates.

Claude-Session: https://claude.ai/code/session_01MXpoKqJrUFTqgmDrehDti4
devin-ai-integration[bot]

This comment was marked as resolved.

…to-a-capability

# Conflicts:
#	packages/ai-chat/src/index.ts
#	packages/ai-chat/src/tests/worker.ts
`updateMessage` resolved attachments before checking the outcome, so a
write against a row that no longer exists materialized every referenced
payload and then returned null — megabytes loaded to be discarded, on a
write guaranteed to fail.

That path is also the one place a pointer legitimately cannot resolve:
if the row is gone its payloads may have been collected with it. Bailing
on `missing` before inlining settles both.

Also drops `MAX_BOUND_PARAMS` and `buildInClauseStrings`, which arrived
with main for the row-size-limit path this branch deletes.

Claude-Session: https://claude.ai/code/session_01MXpoKqJrUFTqgmDrehDti4
Add ThinkSession, a forwarding wrapper around the agents/sessions handle,
so a subclass written against Think 0.17 keeps compiling and running:
configureSession() still accepts the withContext()/withCachedPrompt()
chain, the context accessors on this.session forward to this.context,
and appendMessage/getHistory/getRecentHistory accept their positional
arguments. Context blocks load during onStart again so the synchronous
accessors answer after start.

MediaEvictionConfig.externalizeToWorkspace is accepted and ignored, and
WorkspaceLike.writeFileBytes is optional; a workspace without it disables
media eviction and skills projection with a one-time warning.

Rewrite the think, agents and ai-chat changesets as upgrade guides that
state the one-way storage migration and its rollback loss, drop the
shell changeset (no shell change in this PR), and add an "Upgrading from
0.17" section to the Think docs.

Claude-Session: https://claude.ai/code/session_01PbR74FnDvmhMyzGxKUGXEu
Build the FTS index on the first search() instead of by option. Think
enabled searchIndexing but never searched, so every append billed a
second row for an index nothing read; now an object pays for the index
only once something calls search(), with the existing SQL backfill.
Removes the searchIndexing option and SessionSearchDisabledError.

Remove what no host uses: fork(), listSessions(), appendMany(), stats()
and its maintained cache, the pointer-mode read option, the dead
rawMessagesByStats/describe helpers, SessionSerializationError, and the
constants and estimators the index re-exported. Merge the leaf and seq
caches into one per-session tail read once per object lifetime; the
token estimate that gates compactAfter is derived from content-free
rows on each call. Collapse appendMessage's three duplicate paths into
one: core.append returns the stored row whether or not it inserted.

Dispatch the append event before auto-compaction runs, and report a
throwing change-feed listener through session:error instead of
rejecting a write that already committed.

AIChat retention counts stored rows rather than the hydrated window,
and persistMessages skips a message whose JSON matches the mirrored
array before Sessions would decode and hash its media to find out.

ContextBlocks shares one block loader, keeps toSystemPrompt and
friends private, and exposes freezeSystemPrompt/refreshSystemPrompt as
the prompt surface.

Claude-Session: https://claude.ai/code/session_01PbR74FnDvmhMyzGxKUGXEu
…ncation

skillWorkspace defaults to false so an upgrade writes nothing into a
user's Workspace: 0.17 loaded skills from their sources only, and this
release keeps doing that unless a subclass opts in with {}.

getRecentHistory reports truncated: true when the branch is deeper than
the 10,000-row path cap, which hides older rows exactly as the byte
budget does. Found while lifting a 1.14 GB, 494k-message legacy
transcript: the read returned the newest 10,001 rows and claimed the
whole path fit.

Claude-Session: https://claude.ai/code/session_01PbR74FnDvmhMyzGxKUGXEu
devin-ai-integration[bot]

This comment was marked as resolved.

A branch of exactly the cap's length returned every row and was still
reported truncated. Truncation now means the oldest returned row has a
parent the read could not follow.
@mattzcarey
mattzcarey merged commit ec93caf into main Sep 3, 2026
17 checks passed
@mattzcarey
mattzcarey deleted the feat/move-sessions-into-a-capability branch September 3, 2026 14:31
@github-actions github-actions Bot mentioned this pull request Sep 2, 2026
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