Skip to content

Decode UTF-8 stream chunks#1852

Merged
karthikscale3 merged 9 commits intomainfrom
codex/decode-typed-array-stream-chunks
Apr 29, 2026
Merged

Decode UTF-8 stream chunks#1852
karthikscale3 merged 9 commits intomainfrom
codex/decode-typed-array-stream-chunks

Conversation

@karthikscale3
Copy link
Copy Markdown
Contributor

@karthikscale3 karthikscale3 commented Apr 24, 2026

What changed

  • Added shared formatArrayBufferViewForDisplay + summarizeArrayBufferView helpers in @workflow/web-shared (src/lib/stream-display.ts). They UTF-8 decode typed-array values via TextDecoder({ fatal: true }) and fall back to a compact Uint8Array(N) [..] summary for binary data.
  • DataInspector (src/components/ui/data-inspector.tsx) now collapses any ArrayBufferView (other than DataView) into a non-expandable BytesDisplay opaque ref via collapseRefs, then renders it with a DecodedBytesChunk that shows decoded text by default and a Decoded / Bytes toggle to inspect the summarized raw value. Decoded text that parses as JSON is re-rendered through a nested DataInspector.
  • stream-viewer.tsx no longer formats stream chunks itself — chunks flow as raw hydrated values straight into DataInspector, so Events tab payloads, Trace detail fields, and stream chunks all share the same typed-array rendering path.
  • packages/web/app/lib/hooks/use-stream-reader.ts is dramatically simplified (95 lines removed): it no longer pre-formats chunks, it just keeps them hydrated for the inspector.
  • Decoded / Bytes toggle uses aria-pressed + aria-label toggle-button semantics (not role="tab", since the panel content lives above the buttons rather than as a sibling).
  • Public API in src/index.ts exposes only the DecodedStreamChunkSource type from this module; the rendering helpers are intentionally internal.
  • New regression tests in test/collapse-refs.test.ts (9 cases): top-level typed array, nested in plain object, array, Map values, Set entries, non-Uint8Array views (Int16Array), DataView exclusion, binary fallback summary, and primitive passthrough.

Why

AI agent workflow stream deltas (e.g. helloAgentWorkflow) arrive as Uint8Array values serialized through devalue. The previous viewer collapsed them into compact byte summaries like Uint8Array(87) [65, 73, ...], which made the actual text content unreadable. Decoded text alone would be lossy for binary payloads. Routing everything through DataInspector → collapseRefs keeps the readable default, makes the byte-like source explicit and inspectable, and gives Events / Trace / stream views consistent behavior.

Validation

  • pnpm --filter @workflow/web-shared test → 22 passed (22)
  • pnpm --filter @workflow/web-shared typecheck → clean
  • pnpm --filter @workflow/web-shared build → clean
  • pnpm exec biome check on touched files → only pre-existing complexity warnings on untouched code

Reference

@vercel
Copy link
Copy Markdown
Contributor

vercel Bot commented Apr 24, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
example-nextjs-workflow-turbopack Ready Ready Preview, Comment Apr 28, 2026 11:30pm
example-nextjs-workflow-webpack Ready Ready Preview, Comment Apr 28, 2026 11:30pm
example-workflow Ready Ready Preview, Comment Apr 28, 2026 11:30pm
workbench-astro-workflow Ready Ready Preview, Comment Apr 28, 2026 11:30pm
workbench-express-workflow Ready Ready Preview, Comment Apr 28, 2026 11:30pm
workbench-fastify-workflow Ready Ready Preview, Comment Apr 28, 2026 11:30pm
workbench-hono-workflow Ready Ready Preview, Comment Apr 28, 2026 11:30pm
workbench-nitro-workflow Ready Ready Preview, Comment Apr 28, 2026 11:30pm
workbench-nuxt-workflow Ready Ready Preview, Comment Apr 28, 2026 11:30pm
workbench-sveltekit-workflow Ready Ready Preview, Comment Apr 28, 2026 11:30pm
workbench-vite-workflow Ready Ready Preview, Comment Apr 28, 2026 11:30pm
workflow-docs Ready Ready Preview, Comment, Open in v0 Apr 28, 2026 11:30pm
workflow-swc-playground Ready Ready Preview, Comment Apr 28, 2026 11:30pm
workflow-web Ready Ready Preview, Comment Apr 28, 2026 11:30pm

@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented Apr 24, 2026

🦋 Changeset detected

Latest commit: addd614

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

This PR includes changesets to release 17 packages
Name Type
@workflow/web-shared Patch
@workflow/web Patch
@workflow/core Patch
@workflow/cli Patch
@workflow/builders Patch
@workflow/next Patch
@workflow/nitro Patch
@workflow/vitest Patch
workflow Patch
@workflow/world-testing Patch
@workflow/astro Patch
@workflow/nest Patch
@workflow/rollup Patch
@workflow/sveltekit Patch
@workflow/vite Patch
@workflow/nuxt Patch
@workflow/ai 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

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 24, 2026

🧪 E2E Test Results

All tests passed

Summary

Passed Failed Skipped Total
✅ ▲ Vercel Production 989 0 67 1056
✅ 💻 Local Development 1066 0 86 1152
✅ 📦 Local Production 1066 0 86 1152
✅ 🐘 Local Postgres 1066 0 86 1152
✅ 🪟 Windows 96 0 0 96
✅ 📋 Other 270 0 18 288
Total 4553 0 343 4896

Details by Category

✅ ▲ Vercel Production
App Passed Failed Skipped
✅ astro 89 0 7
✅ example 89 0 7
✅ express 89 0 7
✅ fastify 89 0 7
✅ hono 89 0 7
✅ nextjs-turbopack 94 0 2
✅ nextjs-webpack 94 0 2
✅ nitro 89 0 7
✅ nuxt 89 0 7
✅ sveltekit 89 0 7
✅ vite 89 0 7
✅ 💻 Local Development
App Passed Failed Skipped
✅ astro-stable 90 0 6
✅ express-stable 90 0 6
✅ fastify-stable 90 0 6
✅ hono-stable 90 0 6
✅ nextjs-turbopack-canary 77 0 19
✅ nextjs-turbopack-stable 96 0 0
✅ nextjs-webpack-canary 77 0 19
✅ nextjs-webpack-stable 96 0 0
✅ nitro-stable 90 0 6
✅ nuxt-stable 90 0 6
✅ sveltekit-stable 90 0 6
✅ vite-stable 90 0 6
✅ 📦 Local Production
App Passed Failed Skipped
✅ astro-stable 90 0 6
✅ express-stable 90 0 6
✅ fastify-stable 90 0 6
✅ hono-stable 90 0 6
✅ nextjs-turbopack-canary 77 0 19
✅ nextjs-turbopack-stable 96 0 0
✅ nextjs-webpack-canary 77 0 19
✅ nextjs-webpack-stable 96 0 0
✅ nitro-stable 90 0 6
✅ nuxt-stable 90 0 6
✅ sveltekit-stable 90 0 6
✅ vite-stable 90 0 6
✅ 🐘 Local Postgres
App Passed Failed Skipped
✅ astro-stable 90 0 6
✅ express-stable 90 0 6
✅ fastify-stable 90 0 6
✅ hono-stable 90 0 6
✅ nextjs-turbopack-canary 77 0 19
✅ nextjs-turbopack-stable 96 0 0
✅ nextjs-webpack-canary 77 0 19
✅ nextjs-webpack-stable 96 0 0
✅ nitro-stable 90 0 6
✅ nuxt-stable 90 0 6
✅ sveltekit-stable 90 0 6
✅ vite-stable 90 0 6
✅ 🪟 Windows
App Passed Failed Skipped
✅ nextjs-turbopack 96 0 0
✅ 📋 Other
App Passed Failed Skipped
✅ e2e-local-dev-nest-stable 90 0 6
✅ e2e-local-postgres-nest-stable 90 0 6
✅ e2e-local-prod-nest-stable 90 0 6

📋 View full workflow run

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 24, 2026

📊 Benchmark Results

📈 Comparing against baseline from main branch. Green 🟢 = faster, Red 🔺 = slower.

workflow with no steps

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
💻 Local 🥇 Nitro 0.041s (-3.9%) 1.005s (~) 0.964s 10 1.00x
💻 Local Express 0.044s (-1.1%) 1.005s (~) 0.961s 10 1.06x
💻 Local Next.js (Turbopack) 0.048s 1.005s 0.957s 10 1.16x
🐘 Postgres Express 0.054s (-6.0% 🟢) 1.011s (~) 0.956s 10 1.32x
🐘 Postgres Nitro 0.055s (-42.4% 🟢) 1.010s (-3.2%) 0.955s 10 1.32x
🐘 Postgres Next.js (Turbopack) 0.057s 1.011s 0.953s 10 1.38x
workflow with 1 step

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
💻 Local 🥇 Next.js (Turbopack) 1.116s 2.006s 0.890s 10 1.00x
💻 Local Nitro 1.129s (~) 2.006s (~) 0.877s 10 1.01x
💻 Local Express 1.130s (~) 2.006s (~) 0.877s 10 1.01x
🐘 Postgres Next.js (Turbopack) 1.141s 2.010s 0.869s 10 1.02x
🐘 Postgres Nitro 1.143s (~) 2.009s (~) 0.867s 10 1.02x
🐘 Postgres Express 1.148s (~) 2.011s (~) 0.862s 10 1.03x
workflow with 10 sequential steps

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
💻 Local 🥇 Next.js (Turbopack) 10.794s 11.025s 0.231s 3 1.00x
💻 Local Nitro 10.946s (~) 11.023s (~) 0.078s 3 1.01x
💻 Local Express 10.952s (~) 11.024s (~) 0.071s 3 1.01x
🐘 Postgres Nitro 10.957s (+0.8%) 11.350s (+2.9%) 0.393s 3 1.02x
🐘 Postgres Express 10.961s (~) 11.028s (~) 0.067s 3 1.02x
🐘 Postgres Next.js (Turbopack) 11.002s 11.359s 0.357s 3 1.02x
workflow with 25 sequential steps

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Nitro 14.507s (-0.6%) 15.023s (~) 0.517s 4 1.00x
🐘 Postgres Next.js (Turbopack) 14.508s 15.023s 0.514s 4 1.00x
💻 Local Next.js (Turbopack) 14.596s 15.029s 0.434s 4 1.01x
🐘 Postgres Express 14.621s (~) 15.027s (~) 0.406s 4 1.01x
💻 Local Nitro 14.983s (-0.5%) 15.030s (-6.2% 🟢) 0.047s 4 1.03x
💻 Local Express 14.999s (~) 15.279s (+1.7%) 0.280s 4 1.03x
workflow with 50 sequential steps

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Next.js (Turbopack) 13.770s 14.020s 0.251s 7 1.00x
🐘 Postgres Nitro 13.792s (-1.3%) 14.021s (-2.0%) 0.229s 7 1.00x
🐘 Postgres Express 14.142s (+1.0%) 14.880s (+2.0%) 0.739s 7 1.03x
💻 Local Next.js (Turbopack) 15.743s 16.031s 0.288s 6 1.14x
💻 Local Express 16.535s (~) 17.031s (~) 0.496s 6 1.20x
💻 Local Nitro 16.756s (~) 17.031s (~) 0.275s 6 1.22x
Promise.all with 10 concurrent steps

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Next.js (Turbopack) 1.225s 2.010s 0.785s 15 1.00x
🐘 Postgres Express 1.255s (~) 2.009s (~) 0.754s 15 1.02x
🐘 Postgres Nitro 1.278s (~) 2.009s (~) 0.731s 15 1.04x
💻 Local Express 1.513s (+1.6%) 2.005s (~) 0.493s 15 1.24x
💻 Local Next.js (Turbopack) 1.541s 2.006s 0.465s 15 1.26x
💻 Local Nitro 1.545s (-5.3% 🟢) 2.006s (-3.3%) 0.460s 15 1.26x
Promise.all with 25 concurrent steps

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Nitro 2.325s (-1.1%) 3.009s (~) 0.684s 10 1.00x
🐘 Postgres Next.js (Turbopack) 2.355s 3.007s 0.653s 10 1.01x
🐘 Postgres Express 2.365s (~) 3.010s (~) 0.645s 10 1.02x
💻 Local Next.js (Turbopack) 2.878s 3.342s 0.464s 9 1.24x
💻 Local Express 2.970s (+0.6%) 3.342s (-3.2%) 0.372s 9 1.28x
💻 Local Nitro 3.135s (~) 3.761s (-3.2%) 0.626s 8 1.35x
Promise.all with 50 concurrent steps

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Nitro 3.466s (~) 4.013s (~) 0.547s 8 1.00x
🐘 Postgres Express 3.511s (+0.7%) 4.014s (~) 0.503s 8 1.01x
🐘 Postgres Next.js (Turbopack) 3.622s 4.014s 0.392s 8 1.05x
💻 Local Next.js (Turbopack) 7.191s 7.765s 0.575s 4 2.07x
💻 Local Express 7.682s (-7.9% 🟢) 8.023s (-11.1% 🟢) 0.341s 4 2.22x
💻 Local Nitro 8.748s (+4.8%) 9.270s (+2.8%) 0.523s 4 2.52x
Promise.race with 10 concurrent steps

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Next.js (Turbopack) 1.233s 2.008s 0.775s 15 1.00x
🐘 Postgres Nitro 1.262s (~) 2.008s (~) 0.746s 15 1.02x
🐘 Postgres Express 1.269s (+0.9%) 2.009s (~) 0.740s 15 1.03x
💻 Local Next.js (Turbopack) 1.522s 2.006s 0.484s 15 1.23x
💻 Local Nitro 1.541s (-17.4% 🟢) 2.006s (-14.3% 🟢) 0.465s 15 1.25x
💻 Local Express 1.545s (-18.4% 🟢) 2.006s (-15.1% 🟢) 0.461s 15 1.25x
Promise.race with 25 concurrent steps

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Nitro 2.318s (-0.9%) 3.009s (~) 0.691s 10 1.00x
🐘 Postgres Express 2.354s (+0.5%) 3.010s (~) 0.656s 10 1.02x
🐘 Postgres Next.js (Turbopack) 2.432s 3.009s 0.577s 10 1.05x
💻 Local Next.js (Turbopack) 2.815s 3.310s 0.495s 10 1.21x
💻 Local Express 2.839s (-9.4% 🟢) 3.108s (-17.4% 🟢) 0.269s 10 1.22x
💻 Local Nitro 3.042s (-0.8%) 3.885s (~) 0.843s 8 1.31x
Promise.race with 50 concurrent steps

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Nitro 3.475s (~) 4.011s (~) 0.536s 8 1.00x
🐘 Postgres Express 3.493s (~) 4.011s (~) 0.517s 8 1.01x
🐘 Postgres Next.js (Turbopack) 3.616s 4.011s 0.395s 8 1.04x
💻 Local Next.js (Turbopack) 7.662s 8.270s 0.607s 4 2.21x
💻 Local Express 7.892s (-10.3% 🟢) 8.270s (-10.8% 🟢) 0.378s 4 2.27x
💻 Local Nitro 8.903s (-2.6%) 9.275s (-7.5% 🟢) 0.372s 4 2.56x
workflow with 10 sequential data payload steps (10KB)

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Next.js (Turbopack) 0.778s 1.024s 0.246s 59 1.00x
🐘 Postgres Nitro 0.806s (-1.8%) 1.006s (~) 0.200s 60 1.04x
🐘 Postgres Express 0.837s (~) 1.023s (~) 0.186s 59 1.08x
💻 Local Next.js (Turbopack) 0.865s 1.039s 0.174s 58 1.11x
💻 Local Nitro 1.000s (+2.0%) 1.309s (+19.7% 🔺) 0.309s 46 1.29x
💻 Local Express 1.015s (+3.1%) 1.672s (+55.4% 🔺) 0.657s 36 1.31x
workflow with 25 sequential data payload steps (10KB)

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Nitro 1.914s (-0.7%) 2.075s (-1.2%) 0.161s 44 1.00x
🐘 Postgres Next.js (Turbopack) 1.925s 2.149s 0.225s 42 1.01x
🐘 Postgres Express 1.968s (~) 2.316s (+2.6%) 0.348s 39 1.03x
💻 Local Next.js (Turbopack) 2.737s 3.008s 0.271s 30 1.43x
💻 Local Nitro 3.017s (-0.6%) 3.649s (-2.9%) 0.632s 25 1.58x
💻 Local Express 3.020s (~) 3.610s (+0.7%) 0.589s 25 1.58x
workflow with 50 sequential data payload steps (10KB)

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Next.js (Turbopack) 3.864s 4.076s 0.212s 30 1.00x
🐘 Postgres Nitro 3.866s (-5.8% 🟢) 4.042s (-12.2% 🟢) 0.176s 30 1.00x
🐘 Postgres Express 4.204s (+5.4% 🔺) 5.011s (+14.7% 🔺) 0.807s 24 1.09x
💻 Local Next.js (Turbopack) 8.536s 9.017s 0.481s 14 2.21x
💻 Local Express 8.969s (-2.6%) 9.325s (-6.9% 🟢) 0.355s 13 2.32x
💻 Local Nitro 9.222s (-0.8%) 9.942s (-0.8%) 0.720s 13 2.39x
workflow with 10 concurrent data payload steps (10KB)

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Next.js (Turbopack) 0.247s 1.007s 0.760s 60 1.00x
🐘 Postgres Nitro 0.284s (~) 1.006s (~) 0.722s 60 1.15x
🐘 Postgres Express 0.294s (+4.1%) 1.007s (~) 0.713s 60 1.19x
💻 Local Express 0.562s (~) 1.004s (~) 0.442s 60 2.27x
💻 Local Next.js (Turbopack) 0.575s 1.004s 0.429s 60 2.33x
💻 Local Nitro 0.580s (-4.1%) 1.004s (-1.7%) 0.425s 60 2.34x
workflow with 25 concurrent data payload steps (10KB)

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Next.js (Turbopack) 0.488s 1.007s 0.519s 90 1.00x
🐘 Postgres Express 0.488s (-4.3%) 1.007s (~) 0.519s 90 1.00x
🐘 Postgres Nitro 0.496s (~) 1.006s (~) 0.510s 90 1.02x
💻 Local Express 2.378s (-5.4% 🟢) 3.009s (~) 0.631s 30 4.88x
💻 Local Nitro 2.571s (+1.3%) 3.009s (~) 0.438s 30 5.27x
💻 Local Next.js (Turbopack) 2.576s 3.009s 0.433s 30 5.28x
workflow with 50 concurrent data payload steps (10KB)

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Express 0.792s (-3.3%) 1.008s (-0.9%) 0.217s 120 1.00x
🐘 Postgres Nitro 0.796s (+0.7%) 1.007s (~) 0.211s 120 1.01x
🐘 Postgres Next.js (Turbopack) 0.798s 1.015s 0.217s 119 1.01x
💻 Local Next.js (Turbopack) 10.221s 10.940s 0.718s 11 12.91x
💻 Local Express 10.431s (-6.8% 🟢) 11.028s (-7.6% 🟢) 0.597s 11 13.18x
💻 Local Nitro 11.794s (+5.4% 🔺) 12.327s (+5.7% 🔺) 0.534s 10 14.90x
Stream Benchmarks (includes TTFB metrics)
workflow with stream

💻 Local Development

World Framework Workflow Time TTFB Slurp Wall Time Overhead Samples vs Fastest
💻 Local 🥇 Next.js (Turbopack) 0.183s 1.003s 0.010s 1.016s 0.834s 10 1.00x
🐘 Postgres Next.js (Turbopack) 0.190s 1.000s 0.001s 1.009s 0.819s 10 1.04x
🐘 Postgres Nitro 0.203s (-0.8%) 0.996s (~) 0.001s (-33.3% 🟢) 1.008s (~) 0.805s 10 1.11x
💻 Local Nitro 0.208s (-2.6%) 1.004s (~) 0.012s (-1.6%) 1.019s (~) 0.810s 10 1.14x
🐘 Postgres Express 0.227s (+10.5% 🔺) 0.996s (~) 0.001s (-12.5% 🟢) 1.011s (~) 0.784s 10 1.24x
💻 Local Express 0.248s (+24.5% 🔺) 1.004s (~) 0.020s (+67.8% 🔺) 1.027s (+0.8%) 0.779s 10 1.36x
stream pipeline with 5 transform steps (1MB)

💻 Local Development

World Framework Workflow Time TTFB Slurp Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Nitro 0.619s (-0.7%) 1.026s (+1.9%) 0.004s (-5.8% 🟢) 1.046s (+2.3%) 0.427s 58 1.00x
🐘 Postgres Express 0.627s (-0.5%) 1.005s (~) 0.012s (+205.3% 🔺) 1.030s (+0.6%) 0.403s 59 1.01x
🐘 Postgres Next.js (Turbopack) 0.640s 1.044s 0.004s 1.058s 0.418s 57 1.03x
💻 Local Next.js (Turbopack) 0.696s 1.012s 0.011s 1.026s 0.331s 59 1.12x
💻 Local Nitro 0.747s (-10.9% 🟢) 1.012s (~) 0.010s (+8.2% 🔺) 1.023s (-8.3% 🟢) 0.276s 59 1.21x
💻 Local Express 0.763s (+0.8%) 1.012s (-1.6%) 0.010s (+1.4%) 1.024s (-1.6%) 0.260s 59 1.23x
10 parallel streams (1MB each)

💻 Local Development

World Framework Workflow Time TTFB Slurp Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Next.js (Turbopack) 0.926s 1.199s 0.000s 1.208s 0.282s 51 1.00x
🐘 Postgres Nitro 0.955s (-1.4%) 1.168s (-6.4% 🟢) 0.000s (-52.9% 🟢) 1.193s (-5.2% 🟢) 0.238s 51 1.03x
🐘 Postgres Express 0.967s (+0.6%) 1.246s (-2.5%) 0.000s (-52.1% 🟢) 1.259s (-3.7%) 0.292s 48 1.04x
💻 Local Express 1.214s (-0.9%) 2.020s (~) 0.000s (-10.0% 🟢) 2.022s (~) 0.808s 30 1.31x
💻 Local Nitro 1.233s (+0.8%) 2.021s (~) 0.000s (+333.3% 🔺) 2.023s (~) 0.790s 30 1.33x
💻 Local Next.js (Turbopack) 1.313s 2.022s 0.000s 2.025s 0.712s 30 1.42x
fan-out fan-in 10 streams (1MB each)

💻 Local Development

World Framework Workflow Time TTFB Slurp Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Nitro 1.732s (-3.3%) 2.139s (~) 0.000s (-100.0% 🟢) 2.152s (-1.0%) 0.419s 28 1.00x
🐘 Postgres Next.js (Turbopack) 1.803s 2.106s 0.000s 2.138s 0.334s 29 1.04x
🐘 Postgres Express 1.817s (+2.6%) 2.261s (+3.8%) 0.000s (+Infinity% 🔺) 2.270s (+3.2%) 0.453s 27 1.05x
💻 Local Express 3.438s (-0.9%) 4.032s (~) 0.001s (-33.3% 🟢) 4.035s (~) 0.597s 15 1.98x
💻 Local Nitro 3.503s (+3.4%) 4.032s (~) 0.001s (~) 4.035s (~) 0.532s 15 2.02x
💻 Local Next.js (Turbopack) 3.861s 4.235s 0.000s 4.239s 0.378s 15 2.23x

Summary

Fastest Framework by World

Winner determined by most benchmark wins

World 🥇 Fastest Framework Wins
💻 Local Next.js (Turbopack) 15/21
🐘 Postgres Next.js (Turbopack) 10/21
Fastest World by Framework

Winner determined by most benchmark wins

Framework 🥇 Fastest World Wins
Express 🐘 Postgres 18/21
Next.js (Turbopack) 🐘 Postgres 17/21
Nitro 🐘 Postgres 18/21
Column Definitions
  • Workflow Time: Runtime reported by workflow (completedAt - createdAt) - primary metric
  • TTFB: Time to First Byte - time from workflow start until first stream byte received (stream benchmarks only)
  • Slurp: Time from first byte to complete stream consumption (stream benchmarks only)
  • Wall Time: Total testbench time (trigger workflow + poll for result)
  • Overhead: Testbench overhead (Wall Time - Workflow Time)
  • Samples: Number of benchmark iterations run
  • vs Fastest: How much slower compared to the fastest configuration for this benchmark

Worlds:

  • 💻 Local: In-memory filesystem world (local development)
  • 🐘 Postgres: PostgreSQL database world (local development)
  • ▲ Vercel: Vercel production/preview deployment
  • 🌐 Turso: Community world (local development)
  • 🌐 MongoDB: Community world (local development)
  • 🌐 Redis: Community world (local development)
  • 🌐 Jazz: Community world (local development)

📋 View full workflow run

@karthikscale3 karthikscale3 requested review from TooTallNate, VaguelySerious and pranaygp and removed request for TooTallNate April 24, 2026 23:26
@karthikscale3 karthikscale3 marked this pull request as ready for review April 24, 2026 23:26
Copy link
Copy Markdown
Member

@VaguelySerious VaguelySerious left a comment

Choose a reason for hiding this comment

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

(AI) I'm not sure how https://github.com/vercel/front/pull/68191 is a mirror of this, but as long as both ends work, LGTM. I haven't tried it out locally, so I'd want to re-test once the live deployment is back online, or before release

Comment thread packages/web-shared/src/index.ts Outdated
Comment thread packages/web-shared/src/components/ui/data-inspector.tsx
Comment thread packages/web-shared/test/stream-display.test.ts Outdated
…lapseRefs tests

- Remove unused formatStreamChunkForDisplay/sanitizeStreamChunkForDisplay
  exports; keep only the formatArrayBufferViewForDisplay path actually used
  by DataInspector.
- Replace broken role=tablist/role=tab on the Decoded/Bytes switcher
  with aria-pressed toggle-button semantics.
- Export collapseRefs/isBytesDisplay and add regression tests covering
  typed-array detection (top-level, nested in object/array/Map/Set,
  DataView exclusion).
@karthikscale3
Copy link
Copy Markdown
Contributor Author

(AI) I'm not sure how vercel/front#68191 is a mirror of this, but as long as both ends work, LGTM. I haven't tried it out locally, so I'd want to re-test once the live deployment is back online, or before release

Front to close but not exactly 1:1. I will make a separate PR to close the gap.

karthikscale3 and others added 3 commits April 28, 2026 15:55
* Replace eval with JSON.parse in serialization revive helper

devalue.stringify() always produces valid JSON — special values
(undefined, NaN, Infinity, -0) are encoded as negative integer
sentinels. JSON.parse yields the same flattened array form that
unflatten() expects, without the eval anti-pattern (VULN-918).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* Drop redundant workflow package from changeset

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
Emits Uint8Array chunks containing multi-byte UTF-8 (Latin Extended,
CJK, emoji, RTL Arabic) plus a UTF-8 encoded JSON document, and
asserts each chunk round-trips through TextDecoder({ fatal: true }).
Exercises the same decode path the web inspector relies on for
typed-array stream values.

Made-with: Cursor
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backport-stable Cherry-pick this PR to the stable branch when merged

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants