[pull] main from vercel:main - #393
Merged
Merged
Conversation
Signed-off-by: Andrew Barba <barba@hey.com>
…tion (#3243) * ci: stop deploying changeset-release/main, run its e2e against production The changesets action force-pushes `changeset-release/main`, and it can point at exactly main's HEAD SHA. Vercel keeps one commit status per project per SHA, so when both a production deployment (from main) and a preview deployment (from changeset-release/main) are built for the same commit, whichever finishes last owns the status. On 2026-07-30 the preview finished last, so `vercel/wait-for-deployment-action` — which reads the deployment ID out of that status — handed production e2e runs a preview deployment ID and forked runs across environments. Disable git deployments for that branch in every Vercel project rooted in this repo, and give the changeset PR's Vercel e2e lanes a deployment to test that actually exists: main's production deployment for the PR's base SHA, resolved by SHA so a mid-flight production build is waited out rather than silently replaced by an older one. Signed-off-by: Pranay Prakash <pranay.gp@gmail.com> * ci: resolve changeset-release e2e deployments with the wait action, tokenless Per review: with changeset-release/main no longer deployed, main SHAs can never again be deployed to a second environment of these projects, so the per-SHA commit status the action reads is unambiguous for exactly this lane. Reuse vercel/wait-for-deployment-action with environment: production and sha pinned to the PR base SHA instead of the Vercel-API polling script, drop the script and its VERCEL_TOKEN usage, and inherit the action's inactive/skipped-build handling. Signed-off-by: Pranay Prakash <pranay.gp@gmail.com> --------- Signed-off-by: Pranay Prakash <pranay.gp@gmail.com>
* chore: upgrade @vercel/geistdocs to 1.17.1
Picks up the new footer (Footer no longer takes a config prop), the
heading font-weight change to 450, and the tightened navbar OSS-menu
marks. Also switches the site's own navbar logo from the vendored
geistcn LogoWorkflow fallback to the package's LogoWorkflowSdk, using
its new tuned default height instead of a hardcoded 15.
Fixes a resulting regression: navbarOssProducts entries lacked an `id`,
so resolveOssProducts' `product.id !== activeProduct` filter evaluated
to `undefined !== undefined` (false) for every entry and emptied the
OSS flyout. Added stable `id`/`label` values to each entry.
* refactor: use default navbarOssProducts list instead of a custom override
The manual navbarOssProducts array (with local logo imports/heights) is
no longer needed now that the package's DEFAULT_OSS_PRODUCTS list
already includes all these SDKs with proper id/label/section values.
navbarActiveProduct: 'workflow-sdk' now handles self-exclusion instead.
* fix: use bg-background-200 for docs surfaces to match the template
The docs, cookbook, and v5 route layouts plus the shared DocsLayout
container hardcoded bg-background-100 (pure white), so /docs/* pages
rendered on a lighter surface than the rest of the site. Switch them to
bg-background-200, matching the geistdocs template's page background.
* style: adopt package text-heading-* utilities for homepage headings
The marketing homepage headings hardcoded font-semibold (weight 600)
plus manual responsive sizes/tracking, so they rendered heavier than
the docs headings that now use Geist's 450 heading weight. Swap each
display heading to the package's text-heading-* utilities, which bundle
the 450 weight, line-height, and tracking, mapped across breakpoints to
the nearest design-system size. Inline label/emphasis spans keep their
own weight.
* style: adopt package text-heading-* utilities for worlds headings
Extends the homepage heading change to the /worlds section: the world
listing, detail, compare, and building-a-world pages plus their
components hardcoded font-semibold display headings. Swap each to the
package's text-heading-* utilities (450 weight + line-height +
tracking), mapped across breakpoints to the nearest design-system size.
Mono stat numbers, per-benchmark item labels, and the dialog title keep
their own weight.
* style: remove the bordered grid framing from the homepage
The homepage sections were wrapped in a grid divide-y border-y sm:border-x
container, drawing side borders and divider lines between every section.
Drop that framing so the sections flow with whitespace separation.
* style: remove vertical column dividers from homepage sections
Drop the divide-x column dividers still drawn inside the use-cases
(3-col), feature-grid (2-col), and templates sections, so no vertical
lines remain after the section-grid removal. Section padding keeps the
columns visually separated.
* style: make the homepage "Get started" CTA button rounded-full
* style: use text-heading-* for the feature-grid paragraph text
The two 2-col feature blurbs ("Deep integration with AI SDK.",
"Durable agents by default.") hardcoded their size/leading/tracking
plus font-medium/font-semibold weights. Those manual sizes already
equal text-heading-20/24, so swap to text-heading-20 lg:text-heading-24
— same sizes, but the Geist 450 heading weight (lead drops 600 -> 500
via the utility's [&>strong] rule). The lead stays gray-1000 for
emphasis; body stays gray-900.
* style: fade out the run-anywhere provider logos at the left/right edges
Add linear-gradient masks to the flanking cloud-provider logo groups in
the "Run anywhere, no lock-in" viz so they fade to transparent toward
the outer edges, leaving the centered code block untouched.
* style: widen the right-edge fade on the Vercel dashboard viz
The "Workflow SDK on Vercel" dashboard is offset off the right edge, so
the existing to_left black_10% mask fell off-screen and the visible
right edge hard-clipped. Widen it to black_40% so the dashboard fades
out gradually at the visible right edge.
* style: add spacing between the Vercel, use-cases, and templates sections
Wrap the UseCases and Templates sections with a top margin so there's
clear separation between "Workflow SDK on Vercel", "Build anything with
AI Agents", and "Get started" now that the section dividers are gone.
* style: widen the homepage layout from 1080px to 1200px
* style: align use-cases code block and templates cards with the Vercel section
Switch the "Build anything with" and "Get started" sections from
grid-cols-3 / [1fr_2fr] to [1fr_1.5fr], matching the "Workflow SDK on
Vercel" section above so their code block and cards share the same
right-hand column. The wider text column also lets "Build anything with"
sit on one line. Normalize both to outer padding + column gap so the
code block and cards line up exactly.
* style: extend use-cases/templates content to the right layout edge
Drop the right padding at md+ (md:pr-0) so the code block and template
cards reach the same right edge as the "Workflow SDK on Vercel"
dashboard above, which bleeds to the container edge. Mobile keeps its
padding.
* style: remove the divider between the two feature cards
Drop divide-y/lg:divide-y-0 from the feature grid so no border shows
between "Deep integration with AI SDK" and "Durable agents by default".
* refactor: position homepage sections on a shared 12-col grid
Replace the ad-hoc [1fr_1.5fr] + md:pr-0 + lg:pl-* positioning on the
Vercel, use-cases, and templates sections with a shared grid-cols-12
layout (text col-span-5, visual col-span-7), matching the vercel.com
marketing grid convention. The Vercel dashboard becomes a proper grid
cell instead of an absolutely-offset right-bleed, so all three
sections' visuals align by the grid columns with no magic values.
* style: align homepage width with the navbar content
Widen the homepage container from max-w-[1200px] to the site's
max-w-[1448px] (matching the navbar/footer) and reduce the section
gutters from sm:px-12 to sm:px-6, so section content lines up with the
navbar's content edges (right edge flush at the same column as the
navbar and footer). Also convert the "Reliability-as-code" section to
the shared grid-cols-12 layout (col-span-5 text / col-span-7 code
example), replacing its lg:grid-cols-[330px_1fr] magic values.
* refactor: handle homepage horizontal padding at the root container
Move the mobile/desktop gutter (px-4 sm:px-6) onto the homepage root
container and remove the horizontal padding from every section
component. Section content still aligns with the navbar/footer content
edges, but the gutter is now defined once instead of repeated per
section. Inner-element padding (tab buttons, visual internals) is
unchanged.
* style: left-align content sections on mobile + fix run-anywhere/o11y viz
- Left-align the centered content sections on mobile only (FeatureCardWide,
TweetWall heading, Frameworks, Run-anywhere heading/buttons), restoring
their centered layout at sm and up.
- Make the "Inspect every run" timeline span edge-to-edge by shifting its
gantt from a 14-col grid (content in cols 2-13) to a flush 12-col grid.
- Constrain the run-anywhere viz cluster to the code block width so the
provider cards (AWS/Docker/etc.) overlap behind the code block again.
* style: anchor run-anywhere provider cards to overlap the code block
Position the flanking provider-card groups relative to the centered
code block (right/left calc(50%+140px)) instead of the section edges,
so the cards sit behind and overlap the code block regardless of the
section width.
* style: make the reliability-as-code example fill its column to the right edge
Drop max-w-3xl mx-auto from the workflow/non-workflow code examples so
they fill the col-span-7 cell, aligning the code block's right edge with
the layout's right content edge (matching the tabs and other sections).
* style: split feature-card copy into a title + description
Break the AI SDK / durable-agents feature blurbs into a heading and a
separate muted description with a gap (matching the other sections)
instead of one inline paragraph, and drop the trailing periods from the
feature titles so they read as headings.
* update
* update
* style: give the tweet cards a bg-background-100 surface
* fix(swc-playground): pin monaco-editor to 0.55.1
The lockfile refresh resolved the unpinned `monaco-editor: "latest"` from
0.55.1 to 0.56.0, breaking the workflow-swc-playground Turbopack build.
0.56.0 rewrote its exports map to reroot subpaths under `esm/vs/`
("./*": "./esm/vs/*.js"). monaco-vim@0.4.4 deep-imports
`monaco-editor/esm/vs/editor/editor.api` and
`.../common/commands/shiftCommand`, which now map to
`esm/vs/esm/vs/...` — a path that does not exist. Under 0.55.1
("./*": "./*") both specifiers resolve to real files.
monaco-vim 0.4.4 is the latest published release, so pinning
monaco-editor is the only available fix.
* update
---------
Signed-off-by: christopherkindl <53372002+christopherkindl@users.noreply.github.com>
Signed-off-by: Alex Langenfeld <alex.langenfeld@vercel.com>
…ilures (#1834) * Make resumeHook() resilient to transient hook_received event write failures When events.create('hook_received') fails with a retryable error (429/5xx), resumeHook() now dispatches the queue message with a `hookInput` payload carrying the dehydrated hook payload. The workflow runtime materializes the missing hook_received event from that payload on its next delivery, mirroring the existing resilient-start behavior of start() / run_created / run_started. Returned Hook carries a new `resilientResume: true` flag when the fallback path was taken. Both write paths share a client-minted `resumeId` as an idempotency key so the runtime can dedup if the direct write actually committed but the client saw a transient error. Uses a sequential write-then-queue flow (not parallel) to avoid a dedup race on the happy path: hook_received events have no entity-level conflict guard (unlike run_created), so a duplicate written before the direct write commits would double-deliver the payload to the workflow. * Fix resilient resume: use local payload in materialized hook_received event The server returns a 'lazy' response for hook_received event creation, where eventData.payload may be a RefDescriptor (when the payload exceeded the inline size and was offloaded to blob storage) rather than the raw bytes. Pushing this directly to the in-memory events array caused the workflow VM to fail with 'Invalid input' when trying to deserialize the RefDescriptor as a Uint8Array. Substitute the eventData we already have locally so the in-memory event matches what getWorkflowRunEvents would return after client-side ref hydration. * Gate resilient resume on target runtime capability; carry hook token; export ResumedHook; docs - Only take the resilient path when the target run's recorded @workflow/core version understands hookInput on the queue payload. Runs keep executing on the deployment they were created on (skew protection), and older runtimes parse the queue message with a schema that silently strips unknown fields - the resume payload would be lost while resumeHook() reported success. Fail fast (propagate the original event-write error) for such runs instead, preserving the caller's ability to retry. - Carry the hook token on hookInput and write it into the materialized hook_received event so it gets the same replay-divergence guard as a directly written event (#2030 parity). - Export ResumedHook from @workflow/core/runtime and workflow/api. - Add changelog page and update resumeHook() API reference docs. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * Address review: correct capability cutoff, drop own-version escape hatch, replay-side resumeId dedup Review fixes for the resilient-resume capability gate and dedup: - Bump the supportsQueueHookInput cutoff to 5.0.0-beta.39: 5.0.0-beta.38 is published WITHOUT this feature (its queue-payload schema strips hookInput), so classifying it as capable would silently lose resume payloads. The cutoff is now a single exported constant (QUEUE_HOOK_INPUT_MIN_VERSION) with a TODO(release) requiring re-verification at merge time. - Remove the own-version exact-match escape hatch entirely: version strings do not identify builds (a published beta.38 and a main-built tarball can share a version string while differing in content), so the check could declare a featureless published deployment capable. Pre-release builds now fall back to fail-fast until the version is bumped past the cutoff — the safe direction. Tests simulate a capable target explicitly. - Make duplicate suppression authoritative at the replay boundary: replay now dedups hook_received events sharing a resumeId (same resume attempt), so even when concurrent redelivery of the same queue message double-materializes the event (no World enforces uniqueness on hook_received), the payload reaches workflow code exactly once. This is a pure function of the persisted log, keeping replay deterministic. The runtime's snapshot check remains as best-effort write suppression, with its comment corrected to say so; the EntityConflictError catch is kept as the forward-compatible signal for planned server-side (runId, resumeId) uniqueness, with its comment corrected to say it is defensive today. - Stamp materialized hook_received events with occurredAt decoded from the resumeId ULID so resiliently-resumed hooks are timestamped at resume time rather than after the queue round-trip. - Pin the cross-version compat contract in a test: the direct write is resumeId-only (no digest or negotiation fields), which later server-side idempotency work must keep accepting. - Exercise the published boundary (5.0.0-beta.38) in fail-fast tests, and make the capability tests self-check against the exported cutoff constant instead of restating literals. - Docs: changelog date June -> July 2026, dash consistency, and document the replay-side dedup guarantee. * Encode release-gate and successor-rebase contracts into code comments Comment-only changes capturing the review agreements so they survive the parallel-resume successor rebase (no behavior change): - capabilities.ts: the QUEUE_HOOK_INPUT_MIN_VERSION re-verification point is the actual combined SDK release (after the successor lands and its server-side dedup is deployed), not source-merge time — this PR merges source-only and no SDK is published from it alone. Every Version Packages merge in between moves the earliest possible carrier. - workflow/hook.ts + runtime.ts: scope the replay-side resumeId dedup honestly as defense-in-depth over the persisted log, not a cross-invocation exactly-once guarantee — concurrent invocations replaying pre-duplicate snapshots each see only their own row; the storage-level (runId, resumeId) constraint in the successor work is the correctness boundary. The set stays useful post-constraint for logs written before it deployed. - runtime.ts: document the EntityConflictError swallow's known gap while the branch is defensive (this invocation's local log lacks the payload; progress relies on the other writer's delivery or redelivery) and pin the rebase contract for when the constraint makes it live: a matching claim must append the canonical event locally and succeed; a real conflict must rethrow for redelivery. - resume-hook-resilient.test.ts: reframe the wire-shape pin as a tripwire rather than a permanent contract — the successor deliberately widens it (ID/digest pair + attestation) before any SDK release, so the resumeId-only shape never ships as a published server contract. --------- Co-authored-by: Peter Wielander <peter.wielander@vercel.com> Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
…environment queue deliveries client-side (#3244) * feat(core): stamp creator environment into runInput and reject cross-environment queue deliveries client-side `start()` makes two writes that have to land in the same tenant: the `run_created` event, attributed to whatever environment the caller authenticates as, and the queue message, pinned to a deployment. A misconfigured caller can split them — writing the run to one environment while addressing the message to a deployment in another. The consumer finds no run under its own tenant, the backend's resilient start (`run_started` creates the run when `run_created` was never seen) mints a second copy of the same run id in the consumer's environment, and both copies are real: the creator's sits pending forever while the other executes. The deployment id is not the discriminator — it matched end to end in the incident that motivated this. The environment is. So carry it: add an optional `World.getEnvironment()`, implement it in world-vercel from the same resolution that produces the `x-vercel-environment` header, and stamp it into the queue message's `runInput`. The consuming deployment already knows its own environment, so it can refuse the delivery itself with no server coordination — and refuse before `run_started`, the write that would create the fork. The refusal acks the message instead of throwing: the mismatch is baked into the message, so every redelivery would reach the same verdict and throwing would hot-loop until MAX_QUEUE_DELIVERIES. Both sides must be known for the check to run, so worlds with a single tenant (local, Postgres) and runs started by an older SDK behave exactly as before. A companion diagnostic logs a deployment-id mismatch without refusing, since deployment ids differ for benign reasons too. Signed-off-by: Pranay Prakash <pranay.gp@gmail.com> * fix(world-vercel): resolve the runtime environment from VERCEL_TARGET_ENV For a deployment in a Vercel custom environment, the OIDC token's environment claim is the custom environment's slug (the platform mints `customEnvironment?.slug ?? envTarget`) while VERCEL_ENV reports 'preview' — so keying the cross-environment guard on VERCEL_ENV could false-refuse a legitimate delivery, e.g. a CLI client attributed to 'staging' starting a run on the staging deployment. VERCEL_TARGET_ENV is populated from exactly the same slug-or-target pair as the claim, so prefer it, keeping VERCEL_ENV as the fallback for contexts that don't inject it. Also sorts runtime.ts imports per the Biome rule that landed on main in #3241. Signed-off-by: Pranay Prakash <pranay.gp@gmail.com> --------- Signed-off-by: Pranay Prakash <pranay.gp@gmail.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 subscribe to this conversation on GitHub.
Already have an account?
Sign in.
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.
See Commits and Changes for more details.
Created by
pull[bot] (v2.0.0-alpha.4)
Can you help keep this open source service alive? 💖 Please sponsor : )