[world-vercel] Switch event endpoints to v4 wire format#2055
Draft
VaguelySerious wants to merge 3 commits into
Draft
[world-vercel] Switch event endpoints to v4 wire format#2055VaguelySerious wants to merge 3 commits into
VaguelySerious wants to merge 3 commits into
Conversation
Mirrors the v4 server-side handlers landing in workflow-server. The
v4 wire format moves event metadata into x-wf-* request/response
headers and treats payloads as opaque user-data bytes (streamed
end-to-end). The SDK passes Uint8Array bytes through unchanged at
this layer; higher-level world-vercel adapter glue handles CBOR.
Adds:
- packages/world-vercel/src/frames.ts: encoder + async-iterable
decoder for the length-prefixed binary frame format used by the
v4 list-events response.
- packages/world-vercel/src/events-v4.ts: three new functions:
* createWorkflowRunEventV4 — POST with x-wf-* headers + payload
bytes, returns event/run ids and timestamp from response
headers.
* getEventV4 — GET single event, returns metadata + body bytes.
* getWorkflowRunEventsV4 — GET list, parses frame stream, returns
events + pagination cursor.
- V4_HEADERS exported as the canonical name map; mirrors the
server-side constant.
V4 client characteristics:
- Required runId in URL for run_created too (no /runs/null/events
shortcut; the runId is part of the S3 key the server allocates).
Higher-level callers generate the ULID client-side.
- Payload bytes flow through without CBOR encode/decode on this
layer. Callers CBOR-encode for parity with v3 if they want.
- Pagination cursor surfaces in the LIST response — eliminates the
per-large-payload /refs round-trip used by v2/v3.
Tests (10 new in src/frames.test.ts, no new e2e):
- Canonical wire layout round-trip.
- Multi-frame round-trip with pagination cursor.
- Decoder survives 1-byte chunk delivery (matching spike B's chunk-
boundary robustness requirement).
- 64 KB body split across many small chunks.
- Bodies containing 0xff padding don't mis-frame.
- Back-to-back frames in a single chunk.
- Truncated stream raises.
- Meta CBOR types (numbers, booleans, arrays) preserved.
The world-vercel adapter still defaults to the v3 path; v4 is exposed
for direct callers and a follow-up PR will switch the adapter over
once the matching server-side PR is on staging.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
🦋 Changeset detectedLatest commit: 963d632 The changes in this PR will be included in the next version bump. This PR includes changesets to release 17 packages
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 |
Contributor
Contributor
🧪 E2E Test Results❌ Some tests failed Summary
❌ Failed Tests📦 Local Production (1 failed)nextjs-webpack-stable-lazy-discovery-enabled (1 failed):
Details by Category✅ 💻 Local Development
❌ 📦 Local Production
✅ 🐘 Local Postgres
✅ 🪟 Windows
✅ 📋 Other
❌ Some E2E test jobs failed:
Check the workflow run for details. |
Contributor
📊 Benchmark Results
workflow with no steps💻 Local Development
workflow with 1 step💻 Local Development
workflow with 10 sequential steps💻 Local Development
workflow with 25 sequential steps💻 Local Development
workflow with 50 sequential steps💻 Local Development
Promise.all with 10 concurrent steps💻 Local Development
Promise.all with 25 concurrent steps💻 Local Development
Promise.all with 50 concurrent steps💻 Local Development
Promise.race with 10 concurrent steps💻 Local Development
Promise.race with 25 concurrent steps💻 Local Development
Promise.race with 50 concurrent steps💻 Local Development
workflow with 10 sequential data payload steps (10KB)💻 Local Development
workflow with 25 sequential data payload steps (10KB)💻 Local Development
workflow with 50 sequential data payload steps (10KB)💻 Local Development
workflow with 10 concurrent data payload steps (10KB)💻 Local Development
workflow with 25 concurrent data payload steps (10KB)💻 Local Development
workflow with 50 concurrent data payload steps (10KB)💻 Local Development
Stream Benchmarks (includes TTFB metrics)workflow with stream💻 Local Development
stream pipeline with 5 transform steps (1MB)💻 Local Development
10 parallel streams (1MB each)💻 Local Development
fan-out fan-in 10 streams (1MB each)💻 Local Development
SummaryFastest Framework by WorldWinner determined by most benchmark wins
Fastest World by FrameworkWinner determined by most benchmark wins
Column Definitions
Worlds:
|
Sets WORKFLOW_SERVER_URL_OVERRIDE in packages/world-vercel/src/utils.ts to https://workflow-server-git-peter-v4.vercel.sh so that e2e tests running off this SDK branch exercise the v4-enabled workflow-server preview instead of production. The override is the inline mechanism documented at the constant — when set, it wins over both the default (https://vercel-workflow.com) and the VERCEL_WORKFLOW_SERVER_URL env var. The same pattern is used in v4 testing on the workflow- server side: CI rewrites this string on PR branches. Reset to '' before merging to main. Companion to vercel/workflow-server#439. Updates four tests in utils.test.ts that previously assumed the override is empty. Each affected assertion gets a comment noting what the expectation looks like on main; flipping back to the main behavior is a one-line edit per test when the override is reset. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The adapter's createWorkflowRunEvent / getEvent / getWorkflowRunEvents
now call the v4 endpoints internally instead of v2/v3. Public function
signatures and the EventResult / Event / PaginatedResponse<Event>
shapes returned to the workflow runtime are unchanged — only the wire
protocol switches.
Wire-format changes the SDK now drives:
- Event metadata rides in x-wf-* request/response headers.
- User payload is CBOR-encoded by the SDK at the eventData[field]
boundary and shipped as opaque body bytes; never parsed on the
server.
- POST event response carries the materialized EventResult as a
CBOR body — see workflow-server PR #439's
"Return materialized entity in POST event response body" commit
for the matching server-side change. The SDK no longer needs a
second round-trip after POST to read run/step state.
- LIST events uses the v4 binary-frame stream
(application/vnd.workflow.v4-frames). Per-event `/refs` calls
are gone — payloads come back inline in each frame.
What goes away:
- packages/world-vercel/src/refs.ts (deleted) — the /refs ref-
hydration path is no longer needed.
- hydrateEventRefs / collectPendingRefs / eventDataRefFieldMap and
the EventResultResolveWireSchema / EventResultLazyWireSchema /
EventWithRefsSchema wire schemas (deleted).
- The lazy-refs branching inside createWorkflowRunEvent — the
server already respects `remoteRefBehavior` (still sent for
`eventsNeedingResolve` types) and bakes the resolution decision
into its CBOR response.
What stays:
- v1Compat path on `createWorkflowRunEvent` (runs.create.v1 /
runs.cancel.v1) — still uses v1 endpoints for legacy migrations
that haven't moved to event sourcing.
- validateUlidTimestamp on run_created, the HookNotFoundError
translation on hook_disposed/hook_received 404s, and the
stripEventDataRefs path for resolveData='none'.
Not yet covered:
- listEventsByCorrelationId throws a clear error — v4 has no
by-correlation-id list endpoint yet; callers in the hot path
have been fetching hooks directly anyway. A future server PR
can add /api/v4/events?correlationId= if needed.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Draft. Switches the
world-verceladapter's event endpoints from v2/v3 to v4. Companion to workflow-server PR #439; both land together.What changes
The adapter's
createWorkflowRunEvent/getEvent/getWorkflowRunEventskeep their public signatures and theEventResult/Event/PaginatedResponse<Event>shapes the workflow runtime consumes. What changes is what's on the wire under those calls:x-wf-*HTTP request/response headers instead of inside the body.eventData[field]boundary on write and CBOR-decodes on read; the server treats the bytes as opaque and streams them straight to S3.EventResultas a CBOR body. The runtime reads e.g.result.run.startedAtimmediately after POST without a second round-trip.application/vnd.workflow.v4-frames). One frame per event with CBOR metadata + raw payload bytes inline. The per-event/refsround-trip used by the v3 client is gone.What goes away
packages/world-vercel/src/refs.ts— deleted. The/refshydration path is no longer used.hydrateEventRefs/collectPendingRefs/eventDataRefFieldMapand the wire schemas (EventResultResolveWireSchema,EventResultLazyWireSchema,EventWithRefsSchema) — deleted fromevents.ts.createWorkflowRunEvent— the server still respectsremoteRefBehavior(passed via header foreventsNeedingResolvetypes) and bakes the resolution decision into its CBOR response, so the SDK has nothing to do.Net diff:
+297 / -601lines on this PR.What stays
v1Compatpath increateWorkflowRunEvent— still uses/v1endpoints for legacy SDK migrations that haven't moved to event sourcing. v4 doesn't cover these.validateUlidTimestamponrun_created, theHookNotFoundErrortranslation on hook404s, and thestripEventDataRefspath forresolveData='none'.events-v4.tsis now an internal helper module — not re-exported from the package's public API.Not yet covered (by design)
storage.events.listByCorrelationIdthrows a clear error explaining the v4 server has no by-correlation-id list endpoint. The runtime mostly used this for hook lookups, which can usestorage.hooks.getByTokeninstead. If real callers need it, a follow-up server PR can add/api/v4/events?correlationId=.Test plan
pnpm --filter @workflow/world-vercel buildcleanpnpm --filter @workflow/world-vercel test— 79/79 passpnpm build(full workspace) — 27/27 packages buildWORKFLOW_SERVER_URL_OVERRIDEon this branch points at the workflow-server PR Fix command injection vulnerability in CI workflow via untrusted fork PR #439 preview deployment for e2e tests.🤖 Generated with Claude Code