ta
TanStack
GitHub
ai
Workspace
GitHub
CI Pipeline Executions
Filtered
Runs
Demo
Insights
Compare tasks
Analytics
Sign in
Toggle sidebar
Overview
⌘K
ai
Loading workspace stats
Loading workspace insights...
Statistics interval
7 days
30 days
Latest CI Pipeline Executions
Status
Fix filter
Filter
Fuzzy
Filter range
Sort by
Sort by
Start time
Sort ascending
Sort descending
Succeeded
1030-ai-persistence-capbodysize-strips-the-bodys-known-length-so-artifacts-cant-be-persisted-to-cloudflare-r2
af5deaa5 fix(ai-persistence): address review — zero-byte ranges, slice-at-storage, R2 recipe - `parseRangeHeader`: any range against a zero-byte object is unsatisfiable. The suffix branch resolved `bytes=-1` on an empty artifact to `{ offset: 0 }`, which then threw a RangeError out of the store instead of answering 416. - SQLite store (example + docs reference impl): a ranged read ran `SELECT *` and then `substr`, so it loaded the whole object AND the slice. Metadata now comes from a projection without `body`; `head` too. - R2 recipe: parts are cut on an exact boundary with the remainder carried, since R2 requires equal-sized parts, and chunks are joined once per part rather than re-copied per chunk. Single-shot is capped at 5 GiB, multipart fails fast at the 10,000-part ceiling. - R2 ranged get: `head` and `get` are tied together with `onlyIf: { etagMatches }`, so an overwrite between them cannot pair one version's Content-Range with another's bytes; a ranged head miss returns null instead of falling through to a whole-object read. - Drop the "no limit" claims: `maxArtifactBytes: false` removes the application ceiling, not the backend's.
by Tom Beckenham
T
Succeeded
1030-ai-persistence-capbodysize-strips-the-bodys-known-length-so-artifacts-cant-be-persisted-to-cloudflare-r2
af5deaa5 Merge 5e3a7476e3b55de80ffa6ccacb9d5aff782dcaf4 into 1cb04d5d6ee4a09299ded4a9f3f96b00daa7f122
by Tom Beckenham
T
Succeeded
1030-ai-persistence-capbodysize-strips-the-bodys-known-length-so-artifacts-cant-be-persisted-to-cloudflare-r2
8850bc13 Merge f8b4ca6ebebf5d94d6d87fa57a2b78ba013a5601 into 1cb04d5d6ee4a09299ded4a9f3f96b00daa7f122
by Tom Beckenham
T
Succeeded
1030-ai-persistence-capbodysize-strips-the-bodys-known-length-so-artifacts-cant-be-persisted-to-cloudflare-r2
8850bc13 fix(ai-persistence): ignore an invalid byte-range-spec instead of 416ing RFC 9110 §14.1.1: `bytes=100-50` (last-byte-pos < first-byte-pos) is an invalid spec, not an unsatisfiable one, so it must be ignored and the whole representation served. `parseRangeHeader` returned 'unsatisfiable', which would have failed a request that is supposed to succeed. Checked before satisfiability so the object's size cannot turn an ignorable spec into a 416.
by Tom Beckenham
T
Succeeded
1030-ai-persistence-capbodysize-strips-the-bodys-known-length-so-artifacts-cant-be-persisted-to-cloudflare-r2
2fb7f11f Merge 985fe4d158cc777cd16a8612e70462498aaea7f8 into 1cb04d5d6ee4a09299ded4a9f3f96b00daa7f122
by Tom Beckenham
T
Succeeded
1030-ai-persistence-capbodysize-strips-the-bodys-known-length-so-artifacts-cant-be-persisted-to-cloudflare-r2
2fb7f11f fix(ai-persistence): stream artifacts to length-strict stores, serve byte ranges The cap-enforcing TransformStream wrapper stripped the declared length off every URL-fetched artifact body, so workerd's `R2Bucket.put` rejected all of them with `TypeError: Provided readable stream must have a known length`. - Wrap only when the response does not already bound itself. A trustworthy `content-length` is checked against the cap up front and HTTP framing holds the origin to it, so those bodies now reach `BlobStore.put` exactly as `fetch` produced them — length intact, single-shot into R2, nothing buffered. Chunked and content-encoded replies still get the counter. - Add `BlobPutOptions.expectedLength`, the exact decoded length when the origin declared one, for SDKs that want the length as an argument (S3). Not forwarded on content-encoded replies, where it measures compressed bytes. - Fix `Number(null) === 0` reading an absent `content-length` as a declared length of 0. - `maxArtifactBytes`: default 100 MiB -> 1 GiB (it bounds transfer, not memory), and accept `false` to drop the ceiling entirely. - Add `BlobStore.get(key, { range })` + `BlobObject.range`, threaded through `retrieveBlob`, with `parseRangeHeader` / `resolveBlobRange` helpers. Video seeking is built on 206/Content-Range and Safari will not play a source that ignores Range. - Conformance: length-less stream puts (with and without the hint) and ranged reads, so a store that only handles byte bodies or ignores ranges fails the suite instead of failing on first real use. - Docs, Cloudflare + media-generation skills, and the ts-react-chat example (SQLite store slices with `substr`, serve route answers 206/416) updated to match. Closes #1030
by Tom Beckenham
T
Previous page
Previous
Next
Next page