* [docs] Rename workflowdevkit references to workflowsdk
* [docs] Rename useworkflow.dev to workflow-sdk.dev
* [chore] Add changeset for domain rename
* [docs] Revert sitemap rewrite to useworkflow.dev (crawled-sitemap not yet available for new domain)
Move `workflow/runtime` resolution from `createStepsBundle` into
`discoverEntries` so callers pass the original `inputFiles` array
reference. This restores the WeakMap cache hit when
`createWorkflowsBundle` and `createStepsBundle` are called with
the same inputFiles, avoiding a redundant second esbuild discovery
pass per build that was causing E2E Local Dev Tests to flake on CI.
* fix(builders): improve step bundle discovery and externalization for SDK serde classes
- Broaden importParents tracking to all imports (not just file extensions)
so parentHasChild() works through bare specifier imports
- Include workflow/runtime in discovery inputs so SDK serde classes like
Run are always discovered
- Bundle node_modules deps instead of externalizing with broken relative
paths in CJS shims
* fix(builders): address review feedback
- Preserve inputFiles array reference for discoverEntries() WeakMap
caching when no extra entries are needed
- Add test verifying importParents/parentHasChild works through bare
specifier imports (entry -> bare-pkg -> serde file)
* fix(next): resolve bare specifiers in copied step files for lazy discovery
When the deferred builder copies step files to __workflow_step_files__/,
bare specifiers that are transitive SDK deps can't resolve from the app
directory. Use enhanced-resolve with ESM conditions (preferring 'import'
over 'require') to resolve from the original source location, only when
the specifier can't be resolved from the app directory.
Also add enhanced-resolve to the pnpm catalog and use catalog: in both
@workflow/builders and @workflow/next.
* fix(next): address review feedback on lazy discovery resolver
- Cache ESM/CJS resolvers as class fields instead of re-creating per call
- Remove redundant try/catch (resolveBareCopiedStepSpecifier already
returns undefined on failure)
- Use shared NODE_RESOLVE_OPTIONS / NODE_ESM_RESOLVE_OPTIONS matching
the configuration in swc-esbuild-plugin.ts for consistent resolution
* Remove isWorkflowSdkFile serde exclusion
The SWC detect mode's AST-level manifest (hasManifestEntries) already
correctly filters files without serde class definitions. The broad
isWorkflowSdkFile path exclusion is redundant and was preventing
class definitions in SDK packages from being discovered.
Removed from: builders, next, rollup
* Address review feedback: major semver bump, fix doc comment, add tests
- Bump changeset to major (removing exported APIs is breaking)
- Fix misleading doc comment referencing 'detect mode' in shouldTransformFile
- Add unit tests for shouldTransformFile covering all code paths
* Add AST-level serde filtering to Next.js deferred builder
The isWorkflowSdkFile path-based exclusion was removed from all paths,
but the Next.js deferred builder (collectTransitiveSerdeFiles) was still
using regexp-only detection, causing SDK internal files to be bundled
into the workflow sandbox and triggering stack overflows.
Fix: add applySwcTransform('detect', ...) verification at the end of
collectTransitiveSerdeFiles(). Regex-matched serde candidates are now
verified via the SWC plugin's AST-level manifest to confirm they
actually define serde classes before inclusion in the bundle.
* Add detect mode to SWC plugin for false positive directive filtering
Add a new 'detect' mode to the SWC workflow plugin that walks the AST
to find directives and serde patterns and emits the manifest, but does
not transform any code. The discover-entries plugin now uses a two-phase
approach: fast regexp pre-scan to filter out most files, then SWC detect
mode on candidates to validate at the AST level. This eliminates false
positives where directive-like strings appear inside template literals
or other non-code contexts. The mode:false syntax-only transform is also
removed since esbuild handles TypeScript natively.
* Keep SWC syntax transform in discover phase for decorator support
esbuild does not support legacy decorators or emitDecoratorMetadata,
so all files still need the SWC syntax transform (TS→JS) during
discovery. For regexp-matched files the 'detect' mode handles both
the syntax transform and manifest in a single pass; for all other
files the existing mode:false call is used.
* Use Set for discoveredWorkflows/Steps/SerdeFiles
Eliminates the manual .includes() dedup check and prevents duplicate
entries structurally.
* Update DeferredDiscoveredEntries to use Set<string>
* Add @workflow/next to changeset
The previous pre-release versions (4.x.y-beta.N) caused two issues:
- semver.inc('4.0.0-beta.N', 'major') returns 4.0.0, not 5.0.0
- Pre-release numbers carried over (beta.61 -> beta.62 instead of beta.0)
Setting all versions to 4.0.0 (non-pre-release) ensures a clean major
bump to 5.0.0-beta.0. Also removes @workflow/swc-playground-wasm from
the changeset and pre.json since it is a private package.
* Fix node-module-error plugin matching identifiers in multi-line comments
The findIdentifierUsage function only stripped single-line comments and
same-line block comments, but didn't track multi-line block comment state.
Lines inside JSDoc/block comments (e.g. ` * ... Writable stream`) passed
through unstripped, causing the plugin to point at comments instead of
actual code usage.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Strip string literals before scanning for comment delimiters
Move string stripping before comment detection so that comment delimiters
inside string literals (e.g. `const s = "/*"`) don't incorrectly trigger
block comment mode. Adds regression test.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: Peter Wielander <mittgfu@gmail.com>
* fix(builders): override sideEffects:false for discovered workflow/step/serde entries
When node_modules packages include "sideEffects": false in their
package.json, esbuild drops bare imports from the virtual-entry.js
file. This is incorrect because the SWC compiler transform injects
side-effectful registration code (workflow IDs, step IDs, class
serialization) into these modules.
Fix: return the resolved path alongside sideEffects: true from the
onResolve handler so esbuild uses the plugin's resolution result
instead of re-reading the package.json.
* refactor(builders): normalize sideEffectEntries with realpaths for symlink compatibility
Extract withRealpaths() helper and use it for both normalizedEntriesToBundle
and sideEffectEntries at all three bundle sites. This ensures the
sideEffects override works correctly under pnpm/workspace symlinked
layouts where enhanced-resolve may return realpaths that differ from
the original discovered file paths.
* perf(builders): skip enhanced-resolve for transitive imports when only sideEffectEntries is set
When entriesToBundle is not set (workflow/client bundles), only top-level
import statements need the sideEffects override — transitive imports
from deep within the bundle are not bare imports and don't need resolution.
Skip enhanced-resolve for non-import-statement kinds to reduce overhead.
* feat: export semantic error types and add API reference documentation
Add missing error exports (HookNotFoundError, EntityConflictError,
RunExpiredError, TooEarlyError, ThrottleError, RunNotSupportedError,
WorkflowWorldError) to workflow/internal/errors. Create new error
classes for world-level semantics. Tighten TSDoc comments on all
error classes. Add API reference docs for all error types.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: use @setup declarations, workflow/errors import, and errors/ doc section
- Replace @skip-typecheck with proper `declare` + `// @setup` lines
so code samples are typechecked but setup lines hidden from readers
- Add `workflow/errors` export to package.json (public API, replaces
`workflow/internal/errors` in docs)
- Add `workflow/errors` path mapping in docs-typecheck type-checker
- Add HookConflictError to re-export list
- Move all error docs under api-reference/workflow/errors/ subdirectory
- Update all internal cross-references and links
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* refactor: move error docs to top-level workflow-errors section
- Move semantic error docs to api-reference/workflow-errors/ (matching
the workflow/errors import path, like workflow-api for workflow/api)
- Keep FatalError and RetryableError in api-reference/workflow/ since
they're imported from workflow, not workflow/errors
- Fix all cross-reference links
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* chore: update HTTP debug logger JSDoc to clarify scope
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: make TooEarlyError.retryAfter a number (seconds) matching WorkflowWorldError
TooEarlyError.retryAfter is now seconds (number) instead of a Date,
consistent with ThrottleError and WorkflowWorldError. The conversion
from seconds to Date is done at the consumer site (step-handler) rather
than at construction time.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: address review feedback on docs accuracy
- WorkflowWorldError docs: add status, code, url, retryAfter properties
to TSDoc; clarify that .is() only matches direct instances (not
subclasses); use instanceof in catch-all example
- TooEarlyError/ThrottleError docs: mark retryAfter as optional (?)
to match actual type definitions
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: enforce max queue deliveries in handlers with graceful failure
Replace VQS maxDeliveries cap with handler-level enforcement. Handlers
now gracefully fail runs/steps after excessive queue redeliveries,
preventing "phantom stuck" runs.
- Add MAX_QUEUE_DELIVERIES constant (64) and enforce in both workflow
and step handlers with run_failed/step_failed events
- Remove maxDeliveries from VQS trigger configs (builders + sveltekit)
- Improve world-local queue: safety limit loop, structured logging
with runId/stepId, backoff delay on failures
- Add MAX_DELIVERIES_EXCEEDED error code
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* address PR review comments
- Expand max-delivery comments explaining minimal-work approach
- Make workflow handler error message verbose (matching step handler)
- Fix comment: "consume the message silently"
- Reduce local queue safety limit from 1000 to 256
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* change MAX_QUEUE_DELIVERIES to 48 and use 5s linear backoff locally
VQS uses linear 5s backoff for attempts 1-32, then exponential capped
at 2h. At 48 attempts total elapsed time is ~20h, safely under the
24h message visibility limit. Local world now uses 5s linear backoff
to approximate VQS timing.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Set maxDuration: "max" in vc-config for workflow functions
* Use maxDuration: 60 for flow route, "max" for step/webhook
* Remove explicit maxDuration from webhook route, rely on plan default
* first pass
* fix failing test
* Update changeset to fix SWC compiler issue
Fix bug where the SWC compiler bug prunes step-only imports in the client-mode transformation
Signed-off-by: Nathan Rajlich <n@n8.io>
* DCO Remediation Commit for nathancolosimo <nathancolosimo@gmail.com>
I, nathancolosimo <nathancolosimo@gmail.com>, hereby add my Signed-off-by to this commit: 150d175e7d
I, nathancolosimo <nathancolosimo@gmail.com>, hereby add my Signed-off-by to this commit: 429747fcc3
Signed-off-by: nathancolosimo <nathancolosimo@gmail.com>
---------
Signed-off-by: Nathan Rajlich <n@n8.io>
Signed-off-by: nathancolosimo <nathancolosimo@gmail.com>
Co-authored-by: Nathan Rajlich <n@n8.io>
* fix(builders): enable directive discovery in dot-prefixed files and directories
The glob-based file scanning in getInputFiles() was using tinyglobby's
default behavior which skips dot-prefixed files/directories. This prevented
discovering files with 'use step' / 'use workflow' directives inside paths
like .config/step.ts or .hidden-workflow.ts.
Switch to relative glob patterns with per-directory cwd and dot: true to
ensure dot-files are scanned while still respecting the explicit ignore
list (.git, .next, .vercel, etc.).
* test: add E2E tests for dot-directory directive discovery
Add workbench fixtures and E2E tests verifying that 'use step' / 'use
workflow' directives inside dot-prefixed directories (.well-known/agent/)
are correctly discovered, included in manifests, and executed at runtime.
* fix: normalize paths in getInputFiles tests for Windows compatibility
tinyglobby returns forward-slash paths even on Windows, while Node's
path.join() uses backslashes. Normalize both sides to forward slashes
before comparison.
* refactor: use dirname() instead of join(.., '..') in test helper
Cleaner and more idiomatic way to get the parent directory.
* fix: add .nuxt and other build tool dot-directories to ignore list
With dot: true enabled, framework build output directories like .nuxt/
are now traversed and their generated files picked up as input files.
This caused a circular dependency in the nuxt builder where generated
.nuxt/workflow/steps.mjs was being re-discovered as an input file.
Add .nuxt, .turbo, .cache, .yarn, and .pnpm-store to the ignore list,
matching the directories already ignored by the eager builder's watcher.