Commit Graph

1428 Commits

Author SHA1 Message Date
Nathan Colosimo 45cf2f0014 Align Postgres pool default with worker concurrency 2026-07-07 22:38:45 -07:00
Nathan Colosimo ee5a81406b Update docs/content/docs/v5/configuration/index.mdx
Co-authored-by: Peter Wielander <mittgfu@gmail.com>
Signed-off-by: Nathan Colosimo <110621881+NathanColosimo@users.noreply.github.com>
2026-07-07 17:07:00 -07:00
Nathan Colosimo db8ea0f3c2 Document env var docs requirement 2026-07-07 17:01:18 -07:00
Nathan Colosimo 8e70dc6cfd Move v5 configuration nav near API reference 2026-07-07 17:00:11 -07:00
Nathan Colosimo 8cb3234e00 Update docs/content/docs/v5/configuration/index.mdx
Co-authored-by: Peter Wielander <mittgfu@gmail.com>
Signed-off-by: Nathan Colosimo <110621881+NathanColosimo@users.noreply.github.com>
2026-07-07 16:58:03 -07:00
Nathan Colosimo 0c216327a6 Update docs/content/docs/v5/configuration/meta.json
Co-authored-by: Peter Wielander <mittgfu@gmail.com>
Signed-off-by: Nathan Colosimo <110621881+NathanColosimo@users.noreply.github.com>
2026-07-07 16:57:54 -07:00
Nathan Colosimo 32bec511a4 Fix Windows Next test cleanup 2026-07-07 16:36:28 -07:00
Nathan Colosimo 9e356ad8ac Merge remote-tracking branch 'origin/main' into nathanc/unify-workflow-config
# Conflicts:
#	packages/web/app/server/workflow-server-actions.server.ts
2026-07-07 16:26:59 -07:00
Nathan Colosimo 78bc6d44a3 Audit configuration docs 2026-07-07 16:19:53 -07:00
Nathan Colosimo 2ca34ac69c fix(sveltekit): production server crash from bundled TypeScript compiler (#2799)
* fix(sveltekit): patch server chunks with rollup-renamed __filename bindings

The adapter-node chunk patch skipped any chunk matching
/\b(const|let|var)\s+__(file|dir)name\b/ — but $ is not a regex word
character, so rollup-renamed declarations like `__filename$1` (produced
when adapter-node re-bundles the intermediate server output and our
banner's declaration collides) satisfied the check. Chunks that declared
only a renamed binding while a bundled CJS dependency referenced the
bare `__filename` were skipped, and the production server crashed at
boot (observed on main with the TypeScript compiler bundled via
cosmiconfig through @workflow/world-postgres).

Anchor both regexes with (?![\w$]) so renamed identifiers no longer
match. Verified: the sveltekit workbench production server now boots and
serves health checks (with and without a base path), and queue
deliveries from start() succeed.

Signed-off-by: Nathan Colosimo <110621881+NathanColosimo@users.noreply.github.com>

* fix(sveltekit): keep the TypeScript compiler out of the server bundle

Since the world-target injection change, the sveltekit workbench's
hooks.server.ts imports @workflow/world-postgres, whose dependency chain
(graphile-worker -> cosmiconfig) reaches cosmiconfig's TS-config loader.
At runtime that loader's require('typescript') is lazy and never fires,
but SvelteKit bundles the whole chain into the server and rollup's CJS
conversion hoists it into an eager top-level evaluation — executing the
entire TypeScript compiler at boot and crashing the server
("__filename is not defined" inside the bundled compiler).

Alias 'typescript' to a stub module in the SvelteKit plugin, following
the existing pg-native pattern. Server output shrinks from 36MB to 11MB
and boots cleanly.

Verified: sveltekit workbench production build boots, serves
flow?__health (200), and start() runs execute with clean queue
deliveries. The chunk-patch regex fix from the previous commit stays as
hardening for any other CJS dependency that references __filename.

Signed-off-by: Nathan Colosimo <110621881+NathanColosimo@users.noreply.github.com>

* Update .changeset/fix-sveltekit-filename-chunk-patch.md

Signed-off-by: Peter Wielander <mittgfu@gmail.com>

---------

Signed-off-by: Nathan Colosimo <110621881+NathanColosimo@users.noreply.github.com>
Signed-off-by: Peter Wielander <mittgfu@gmail.com>
Co-authored-by: Peter Wielander <mittgfu@gmail.com>
2026-07-07 23:07:13 +00:00
Nathan Colosimo e05c0e7882 Show v4 docs on world pages 2026-07-07 15:58:58 -07:00
Karthik Kalyan 54f46f976d cli: restore dynamic world loading for community backends (#2806)
* cli: restore dynamic world loading for community backends

Since #2752 moved world selection to static injection, setupCliWorld only
constructed the vercel, local, and postgres worlds explicitly and threw
'Unsupported workflow backend' for anything else — breaking community
worlds (e.g. @workflow-worlds/turso) that previously loaded through the
dynamic createWorld() in @workflow/core/runtime.

Generalize the postgres-only dynamic path: any backend other than
vercel/local is now resolved from the user's project directory and loaded
via its createWorld() export, matching @workflow/web's world construction
(#2804), with clear errors when the package is missing or does not export
createWorld().

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* cli: fall back to default.createWorld for CJS world packages

Review feedback on #2804: import() of a require-resolved CJS entry relies
on cjs-module-lexer to surface named exports; fall back to
mod.default.createWorld when detection fails.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* Update .changeset/cli-generic-world-backends.md

Signed-off-by: Peter Wielander <mittgfu@gmail.com>

---------

Signed-off-by: Peter Wielander <mittgfu@gmail.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: Peter Wielander <mittgfu@gmail.com>
2026-07-07 15:47:58 -07:00
Karthik Kalyan cdfac39e07 web: construct worlds explicitly instead of via static-injection stub (#2804)
* web: construct worlds explicitly instead of via static-injection stub

Since #2752, createWorld() from @workflow/core/runtime is a stub that
throws unless a framework build plugin aliases it to a world package.
The CLI was migrated to construct worlds directly, but @workflow/web
still called the stub, so 'workflow web' crashed with 'Workflow target
world was not statically injected' for local and postgres backends
(the vercel path was unaffected since it constructs the world directly).

Mirror the CLI: import the local world statically and resolve any other
configured world package from the inspected project's directory.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* web: fall back to default.createWorld for CJS world packages

Review feedback: import() of a require-resolved CJS entry relies on
cjs-module-lexer to surface named exports; fall back to
mod.default.createWorld when detection fails. Mirrored in the CLI in #2806.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-07 15:47:51 -07:00
Nathan Colosimo b3b42fb69d Refine configuration docs wording 2026-07-07 15:23:43 -07:00
Nathan Colosimo 1c6656cf9e Merge remote-tracking branch 'origin/main' into nathanc/unify-workflow-config 2026-07-07 15:22:21 -07:00
Nathan Colosimo 1c07d7d29a fix(workbench): add @repo/* tsconfig alias to nitro-v2 (#2787)
The workbench workflows are shared across apps (nitro-v2/workflows
symlinks into files shared with workbench/example), and the shared
99_e2e.ts workflow imports @repo/lib/steps/paths-alias-test. nitro-v2's
tsconfig was missing the @repo/* path alias that nitro-v3 already has,
so building nitro-v2 with the Vercel preset failed at esbuild
resolution:

  ../example/workflows/99_e2e.ts: ERROR: Could not resolve
  "@repo/lib/steps/paths-alias-test"

Mirror nitro-v3's alias. Verified NITRO_PRESET=vercel pnpm build now
succeeds (was failing on main before this change).
2026-07-07 15:09:15 -07:00
Nathan Colosimo 50fa246305 Split configuration docs into focused pages 2026-07-07 15:05:30 -07:00
Nathan Colosimo 440bf12e70 Move configuration docs to top level 2026-07-07 14:39:16 -07:00
Nathan Colosimo 902a1f78cf Clarify Vercel queue sleep delay docs 2026-07-07 14:20:22 -07:00
Nathan Colosimo 2dd64fbdb0 Merge remote-tracking branch 'origin/main' into nathanc/unify-workflow-config 2026-07-07 14:14:06 -07:00
Nathan Colosimo 6abb491b7c Support relative target world modules 2026-07-07 14:14:00 -07:00
Peter Wielander 7637196cf0 Fix hook token reuse after dispose() (same-run and cross-run) (#2779) 2026-07-07 14:13:15 -07:00
Nathan Colosimo 20efe1bca7 Align Postgres DATABASE_URL fallback 2026-07-07 14:04:52 -07:00
Nathan Colosimo c8e0bae03f Standardize world factory exports 2026-07-07 13:54:57 -07:00
Nathan Colosimo 27e19e4fcd Clarify Vercel World deployment wording 2026-07-07 13:39:53 -07:00
Nathan Colosimo ef46213f7f Remove World docs toggle 2026-07-07 13:36:47 -07:00
Nathan Colosimo 50292a33b8 Keep World docs version toggle static 2026-07-07 12:41:29 -07:00
Nathan Colosimo 6350f007f6 Merge remote-tracking branch 'origin/main' into nathanc/unify-workflow-config 2026-07-07 12:34:11 -07:00
Nathan Colosimo e08480fc8e Add World docs version toggle 2026-07-07 12:34:07 -07:00
Nathan Colosimo c194d60f61 Revert "Version world docs routes"
This reverts commit b52a351c3f.
2026-07-07 12:29:02 -07:00
Karthik Kalyan ae51f45166 web: list hooks from analytics, fetch token on demand (#2652)
* Add workflow analytics world APIs

* web: read observability list views from world.analytics when available

Route the runs/steps/events/hooks list server actions through the optional
world.analytics namespace when the backend provides one, falling back to the
runtime storage APIs otherwise. Events listing only uses the analytics path
when no payload data is requested. Detail/get actions, streams, and mutations
are unchanged.

* web: keep events and hooks list reads on the runtime storage API

The Events tab and trace viewer derive step names and wait resumeAt from
resolved event payloads, and the hooks table needs the secret token and
ownerId for its resume/copy-token actions. The metadata-only analytics rows
do not carry these, so only the runs and steps list views use world.analytics.

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

* web: read events list from world.analytics with a runtime-shape remap

The events list/trace consumers read only top-level eventType, correlationId,
and createdAt; event payloads are loaded lazily per event via fetchEvent(...,
'all') on the runtime path. Map the flat analytics event rows into the runtime
Event shape (reconstructing eventData.stepName) so fetchEvents and
fetchEventsByCorrelationId can use the analytics read path when available.
Hooks remain on the runtime path (they need the secret token + ownerId).

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

* web: list hooks from world.analytics, fetch token on demand

The hooks list now reads from the metadata-only world.analytics namespace
when the backend provides one (falling back to the runtime storage APIs
otherwise). A hook's secret token is no longer shipped in list rows — it is
fetched one hook at a time via world.hooks.get only when the user copies the
token or resumes the hook, keeping the secret out of bulk list responses.

Adds a fetchHookToken server action + RPC, a HookListItem type (Hook without
token), and a lazy HookTokenCell for the copy-token affordance.

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

* Handle analytics access metadata in web

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-07 12:06:41 -07:00
Nathan Colosimo b52a351c3f Version world docs routes 2026-07-07 12:04:45 -07:00
Nathan Colosimo 7184a6e452 Clarify Vercel World environment overrides 2026-07-07 11:46:35 -07:00
Nathan Colosimo 6650bf7373 Merge remote-tracking branch 'origin/main' into nathanc/unify-workflow-config 2026-07-07 11:46:22 -07:00
Karthik Kalyan 1518c48608 web: read observability list views from world.analytics when available (#2647)
* Add workflow analytics world APIs

* web: read observability list views from world.analytics when available

Route the runs/steps/events/hooks list server actions through the optional
world.analytics namespace when the backend provides one, falling back to the
runtime storage APIs otherwise. Events listing only uses the analytics path
when no payload data is requested. Detail/get actions, streams, and mutations
are unchanged.

* web: keep events and hooks list reads on the runtime storage API

The Events tab and trace viewer derive step names and wait resumeAt from
resolved event payloads, and the hooks table needs the secret token and
ownerId for its resume/copy-token actions. The metadata-only analytics rows
do not carry these, so only the runs and steps list views use world.analytics.

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

* web: read events list from world.analytics with a runtime-shape remap

The events list/trace consumers read only top-level eventType, correlationId,
and createdAt; event payloads are loaded lazily per event via fetchEvent(...,
'all') on the runtime path. Map the flat analytics event rows into the runtime
Event shape (reconstructing eventData.stepName) so fetchEvents and
fetchEventsByCorrelationId can use the analytics read path when available.
Hooks remain on the runtime path (they need the secret token + ownerId).

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

* Handle analytics access metadata in web

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-07 11:45:07 -07:00
Karthik Kalyan 17d4ce2253 cli: read list views from world.analytics when available (#2648)
* Add workflow analytics world APIs

* cli: read list views from world.analytics when available

inspect list views (runs, steps, events, hooks, sleeps) now read from the
optional world.analytics namespace when the active backend provides one,
falling back to the runtime storage APIs otherwise. Payload and detail views
are unchanged. Deprecate --with-data for list views; payloads are viewable
per-resource via 'inspect <resource> <id>'.

* cli: keep hook listing on the runtime storage API

The analytics read path omits ownerId (and the secret hook token), so routing
hook listing through it silently drops the ownerId column. Keep inspect hooks
on the runtime APIs, consistent with the web observability UI. Runs, steps,
events, and sleeps continue to use the analytics read path when available.

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

* Handle analytics access metadata in CLI

* test(cli): preserve analytics pageInfo in json output

* fix(cli): paginate analytics sleeps output

* fix(cli): correct deprecation message flag name to --withData

The list-view deprecation warning referenced '--with-data', but the actual
oclif flag is '--withData' (with '-d' alias); '--with-data' errors with
"Nonexistent flag". Fix the warning text, the doc comment, and the changeset
to reference the real flag name.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(cli): preserve inspect json array output

* fix(cli): fall back when analytics lists are empty

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-07 11:44:57 -07:00
Nathan Colosimo a904a01cdd Render official world pages from v5 docs 2026-07-07 11:37:25 -07:00
Nathan Colosimo 49cb54212d Tighten configuration environment variable docs 2026-07-07 11:10:46 -07:00
Nathan Colosimo a9573ef12a Merge remote-tracking branch 'origin/main' into nathanc/unify-workflow-config 2026-07-07 11:04:58 -07:00
Nathan Colosimo 239031ad9e fix(next): respect basePath for workflow routes (#2732)
* fix(next): respect basePath for workflow routes

* docs(core): note workflow URL resolution gap

* fix(next): expose workflow health route methods

* test(utils): remove workflow route helper tests

* test(builders): remove route handler string test

* fix(next): defer basePath validation to Next.js

* refactor(utils): remove workflow url helper wrappers

* Test Next basePath builder wiring
2026-07-06 16:43:35 -07:00
Nathan Colosimo 622a4e68c4 Replace typed workflow configuration with environment variable docs
Running the workflow.config.ts approach (#2468) into real usage
surfaced too many problems around World config vs runtime config
resolution. This PR now removes that implementation entirely — no new
config file, no workflow/config subpath, no configured-World module
aliasing — and instead makes the v5 docs a complete, accurate reference
for the configuration surface that already exists: environment
variables and framework plugin options.

Docs changes (every variable, default, and clamp verified against
current main source, not copied from the #2446 inventory):

- foundations/configuration (new): the single stated precedence rule
  (explicit option > env var > default), World selection via
  WORKFLOW_TARGET_WORLD, runtime tuning variables (replay/queue/
  inline-step budgets, turbo, optimistic inline start, trace mode,
  compression, queue namespace, DEBUG), advanced tuning escape
  hatches, build-time flags (sourcemap, public manifest, HMR logs),
  and CLI variables.
- Local World: fixed the queue concurrency default (1000; docs said
  100) and replaced the programmatic sample that referenced a
  nonexistent workflow.config.ts with the real mechanism
  (WORKFLOW_TARGET_WORLD pointing at a module that exports a World).
- Vercel World: WORKFLOW_VERCEL_* variables configure tooling (CLI and
  web UI) and have no effect inside deployments — the runtime warns if
  they are set there; documented the auth token fallback chain
  (option > WORKFLOW_VERCEL_AUTH_TOKEN > VERCEL_TOKEN > OIDC),
  WORKFLOW_VERCEL_PROJECT_NAME, and VERCEL_QUEUE_MAX_DELAY_SECONDS;
  fixed the programmatic sample (baseUrl is not an option).
- Postgres World: documented the workflow_ job prefix default and
  option-vs-env precedence.

Closes the code portion of the #2446 plan in favor of documenting the
existing surface.

Signed-off-by: Nathan Colosimo <110621881+NathanColosimo@users.noreply.github.com>
2026-07-06 15:55:54 -07:00
Nathan Rajlich 03862edb65 feat(world-vercel): send x-vercel-queue-region on proxy-mode queue sends (#2789)
* feat(world-vercel): send x-vercel-queue-region on proxy-mode queue sends

Token/proxy clients (CLI, dashboards, external scripts) send queue
messages through api.vercel.com's /v1/workflow proxy, where the fixed
resolveBaseUrl override replaces the queue SDK's own
region -> <region>.vercel-queue.com base-URL resolution — so every
proxied send landed on the region-less VQS host, while the direct
in-function path already dials the regional host (iad1 today).

The proxy now routes sends to the region's VQS dataplane when the
x-vercel-queue-region header is present (vercel/api#79056, deployed).
Set it on every proxy-mode send from the region the QueueClient is
constructed with, giving proxy clients parity with the direct path.

Today that region is the static 'iad1'; when per-send region
resolution lands (#1981), the header automatically carries the
tag/option-derived region — this change is the transport mechanism,
not the policy.

Tests: proxy-mode construction carries the header matching the
client's region; the direct path doesn't.

* chore: trim comments, drop private repo reference

* chore: changeset for proxy-mode x-vercel-queue-region header
2026-07-06 22:30:00 +00:00
Mitul Shah 8a766884cf change timing markers to be precise on the timeline (#2775)
* doen

* Fix: Old test file `test/format-duration-precise.test.ts` still asserts two-decimal output ("45.20s", "1m 0.00s") that no longer matches the trimmed-zero output of `formatDurationPrecise`, so `pnpm test`/CI fails.

This commit fixes the issue reported at packages/web-shared/test/format-duration-precise.test.ts:15

## Bug

The PR changed `formatDurationPrecise` (in `packages/web-shared/src/lib/utils.ts`) to trim trailing zeros by wrapping the fractional value in `Number(x.toFixed(fractionDigits))`:

```ts
if (normalizedMs < MS_IN_MINUTE) {
  return `${Number((normalizedMs / MS_IN_SECOND).toFixed(fractionDigits))}s`;
}
...
parts.push(`${Number(seconds.toFixed(fractionDigits))}s`);
```

`Number("45.20")` → `45.2`, `Number("0.00")` → `0`, so whole/half seconds now render without padding.

A new test file `packages/web-shared/src/lib/utils.test.ts` reflects this behavior, but the pre-existing `packages/web-shared/test/format-duration-precise.test.ts` was left untouched and still asserts the **old** padded output.

## Concrete trigger

Reproduced the actual function output (integer decomposition + trimmed zeros):

| Input | Old assertion | New actual output |
|-------|---------------|-------------------|
| `45200` | `45.20s` | `45.2s` |
| `999.6` | `1.00s` | `1s` |
| `999.5` | `1.00s` | `1s` |
| `59999` | `1m 0.00s` | `1m 0s` |
| `59995` | `1m 0.00s` | `1m 0s` |
| `119999` | `2m 0.00s` | `2m 0s` |
| `3659999` | `1h 1m 0.00s` | `1h 1m 0s` |
| `86459999` | `1d 1m 0.00s` | `1d 1m 0s` |

The root `vitest.config.ts` uses default include globs, so `test/*.test.ts` runs and these assertions fail, breaking CI. (I couldn't run vitest directly in the sandbox because dev deps weren't installed / `vitest/config` unresolved, so I reproduced the exact function logic in a standalone Node script to confirm the outputs.)

## Fix

Updated the stale assertions in `test/format-duration-precise.test.ts` to the trimmed-zero outputs, and adjusted the file-level doc comment (which referenced `"1m 0.00s"` / `"60.00s"`) to describe the current behavior.

Co-authored-by: Vercel <vercel[bot]@users.noreply.github.com>
Co-authored-by: mitul-s <mitulxshah@gmail.com>

---------

Co-authored-by: vercel[bot] <35613825+vercel[bot]@users.noreply.github.com>
Co-authored-by: Vercel <vercel[bot]@users.noreply.github.com>
2026-07-06 18:27:10 -04:00
JJ Kasper 0f557d5ae4 Statically inject workflow world target (#2752)
* Statically inject workflow world target

* Fix static world injection in host bundles

* Fix static world injection gaps

* Fix Vite Nitro server startup

* Fix Nitro pg-native aliasing

* Fix static world target CI gaps

* Fix static world dev rebuild gaps

* Avoid broad runtime alias in Nitro

* Refresh Next dev route for step HMR

* Externalize Nest target world

* Use canary HMR rediscovery timeout

* Bundle local world in Nest builds

* Dedupe world target helpers and fix SvelteKit chunk patch guard
2026-07-06 14:19:45 -07:00
github-actions[bot] 166bb7bde6 Version Packages (beta) (#2692) workflow@5.0.0-beta.27 2026-07-06 13:32:59 -07:00
Peter Wielander cc7f076528 Make runtime tuning constants env-configurable; forward server limit-override header (#2718) 2026-07-06 12:05:13 -07:00
Nathan Colosimo eb7f60c7e9 fix(ts-plugin): allow workflow direct await diagnostics (#2769)
Co-authored-by: Peter Wielander <mittgfu@gmail.com>
2026-07-06 18:14:20 +00:00
Mitul Shah 19577b8d05 feat(web-shared): make the trace viewer span detail panel resizable (#2773)
* nice

* refactor(web-shared): simplify resizable detail panel internals

Inline single-use constants in DraggableBorder and make comments
self-contained.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-05 18:39:36 -07:00
Mitul Shah efec21f279 Update trace-viewer.tsx (#2774) 2026-07-05 15:27:02 -04:00
Nathan Colosimo 2ab7057954 fix(world-local): rebuild hook caches from event log (#2747) 2026-07-02 22:19:34 +00:00