* build: declare typescript (catalog:) in every package that runs tsc
Twenty packages invoke tsc in their build/typecheck scripts without
declaring a typescript dependency, resolving whatever tsc pnpm happens
to leave reachable. That broke locally after the TypeScript 6 upgrade
(#2700): base.json now uses the TS6-only 'types': ['*'] wildcard, and
worktrees carrying pre-upgrade node_modules/.bin/tsc shims (orphaned
typescript@5.9.3 bins that pnpm never refreshes for an undeclared
dependency) fail with TS2688 'Cannot find type definition file for *'.
Declaring 'typescript': 'catalog:' (the convention nest already
follows) makes pnpm own each package's tsc bin, so version upgrades
refresh the shims and this staleness class cannot recur. Packages
without tsc in their scripts are left unchanged.
Full pnpm build: 27/27 tasks green.
* Address review: drop duplicate zod devDep; regenerate lockfile minimally
- packages/world listed zod in both dependencies and devDependencies
(pre-existing on main, surfaced by the devDependencies sort) — keep
the runtime dependency only.
- Regenerate pnpm-lock.yaml from a pristine main baseline with
--lockfile-only (a clean-main run produces zero diff, so main has no
drift). Remaining non-typescript changes are mechanical consequences
of the change itself: typescript is an (optional) peer of several
tooling dependencies, so declaring it in 20 importers creates new
peer-resolution snapshot variants and prunes the now-orphaned old
ones; plus one radix-ui 1.6.1->1.6.2 refresh in docs caused by its
floating 'latest' specifier.
- Validated: pnpm install --frozen-lockfile succeeds; full build 27/27.
* 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
* fix(build): use inline sourcemaps across all workspace packages
Prevents a Turbopack bug on Windows that caused the SWC worker to
crash when reading external .js.map files in workspace-linked packages
(paths were concatenated with mixed separators like
'packages/serde/dist\\index.js.map'). Once the worker crashed, the
module graph entered a broken state where all subsequent requests
returned 500, manifesting as flaky E2E Windows tests where the
'should rebuild on imported step dependency change' test would time
out waiting for /api/workflows/start to succeed.
Extends the original fix from #352 (previously applied only to
@workflow/core and workflow) to the shared base tsconfig.json so that
all packages producing a dist/ output benefit.
* Potential fix for pull request finding
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Signed-off-by: Nathan Rajlich <n@n8.io>
* Tighten changeset description
---------
Signed-off-by: Nathan Rajlich <n@n8.io>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
* docs: split v4/v5 content, fix version switcher end-to-end
## Content restructuring
- Split `docs/content/docs/` into `docs/content/docs/v4/` and
`docs/content/docs/v5/` so each version is a fully independent
content tree with no shared-file coupling
- v4 excludes the four pages that are v5-only (AbortController
cancellation docs and the serializable-abort-controller internal page)
- v5 retains all pages; `preRelease` frontmatter field removed (no
longer needed now that each version is its own folder)
- Removed `AbortController` / `AbortSignal` from v4 serialization page
(section moved to v5 only)
## Fumadocs source
- Added `v4docs` and `v5docs` as separate `defineDocs()` collections in
`source.config.ts`; shared `docsSchema` (no more `preRelease` field)
- `source.ts` exports both `source` (v4, `baseUrl: /docs`) and
`v5Source` (v5, same base URL)
## Version routing
- `version-source.ts` simplified: `filterPreReleaseFromNodes` and
`isPreReleaseUrl` logic removed; v4 tree uses `source`, v5 tree uses
`v5Source` + `rewriteNodeUrls`
- v4 `page.tsx`: removed `preRelease` guard (v4Source has no such pages)
- v5 `page.tsx`: uses `v5Source` for `getPage` / `generateStaticParams`
/ `generateMetadata`; `v5Link` wrapper rewrites `/docs/…` hrefs to
`/v5/docs/…` so inline MDX links stay in the v5 context
## Versioned cookbook
- Added `app/[lang]/v5/cookbook/` layout + page (mirrors v4 but uses
`v5Source`, `rewriteCookbookUrlForVersion`, and `V5CookbookLink`)
- `getCookbookTree` accepts a `versionPrefix` parameter; sidebar URLs
are prefixed accordingly (`/v5/cookbook/…`)
- `cookbook-tree.ts`: added `skipVersions?: string[]` per-recipe field
for version-specific exclusions; `distributed-abort-controller` is
marked `skipVersions: ['v5']`
## Version switcher — state & navigation
- New `VersionProvider` context (`hooks/geistdocs/use-version.tsx`)
backed by `localStorage`: URL is source of truth on versioned pages,
`localStorage` carries the preference across non-versioned pages
(cookbook overview, worlds, etc.)
- `VersionSwitcher` uses `useVersion()` context instead of URL-only
detection; now visible on all pages including cookbook
- `DesktopMenu` and `MobileMenu` use `activeVersion` from context so
the "Docs" and "Cookbook" navbar links resolve to the correct version
prefix on every page
- `buildVersionUrl` expanded to handle `/cookbook/…` paths alongside
`/docs/…`; non-versioned routes (worlds, api) return unchanged
- `switchVersion` does a `HEAD` probe before navigating; falls back to
the versioned cookbook or docs home if the target page doesn't exist
in that version (handles v4-only → v5 and v5-only → v4 cases)
## Cookbook content (v5)
- Rewrote `agent-cancellation` recipe using a single `AbortController`
pattern; removed Hard Cancellation vs Stop Signal two-approach
comparison
- Deleted `distributed-abort-controller` recipe from v5 (native
`AbortController` serialization makes it unnecessary)
- Removed references to distributed-abort-controller from
`cookbook/index.mdx` and `common-patterns/timeouts.mdx`
Co-authored-by: Cursor <cursoragent@cursor.com>
* fix(docs): use abortSignal (not signal) in DurableAgent.stream() options
Co-authored-by: Cursor <cursoragent@cursor.com>
* fix(docs): update prepack scripts to use versioned content paths
Content moved from docs/content/docs/ to docs/content/docs/v5/ on main
(pre-release channel). Stable branch will use v4/ after backport.
Co-authored-by: Cursor <cursoragent@cursor.com>
---------
Co-authored-by: Cursor <cursoragent@cursor.com>
* Add stable Next.js eager and lazy test coverage
* Address PR review feedback
* Fix eager Next step route builds
* Fix eager Next manifest refreshes
* Fix eager Next e2e stack assertions
* Externalize native step bundle bindings
* Lazy load Vercel world runtime
* Fix Next dev step sourcemap assertions
* Consolidate eager build changesets
* Fix Vercel world tracing in Next deployments
* Externalize Vercel world in Next builds
* Fix webpack tracing for Vercel world deps
* Fix eager workflow route bundling
* Rely on Next server externals
* feat: allow start() to be called directly inside workflow functions
Add 'use step' to start() so it can be called directly from workflow
code. The SWC compiler strips the function body in workflow mode and
replaces it with a step proxy. When called from a workflow:
1. The workflow function reference is serialized via WorkflowFunction
reducer (serializes { workflowId })
2. start() executes in the step context with full Node.js access
3. The returned Run is serialized via WORKFLOW_SERIALIZE and deserialized
back in the workflow VM
4. Run getters (.status, .returnValue, etc.) are 'use step' getters
that each execute as separate steps
Also re-exports start from @workflow/core/runtime/start in api-workflow.ts
instead of using a throwing stub, adds e2e tests for startFromWorkflow
(with hook communication) and fibonacciWorkflow (recursive composition).
* fix(next): don't copy package step files in deferred builder to avoid duplicate classes
Files belonging to packages (detected by walking up to find a
package.json with a name field) are imported via relative path
instead of being copied to __workflow_step_files__/. Copying creates
a second module instance which breaks JS native private field (#)
brand checks when the runtime creates instances from one copy and
the step handler accesses fields from the other.
* fix(next): only skip copying package files that are serde classes, not all package step files
Regular package step files (like fetch) must still be copied to ensure
the SWC loader registers them. Only serde class files from packages are
excluded from copying since those define classes with JS native private
fields (#) that break when duplicated.
* fix(next): generate thin wrappers for package serde step files instead of full copies
For package files that define serde classes (like Run), generate a thin
wrapper that imports the original class and registers steps/classes from
the manifest. This avoids duplicating the class definition (which breaks
JS native private field brand checks) while still registering all step
functions and the class in the serialization registry.
Regular package step files (like fetch) are still copied as before.
* fix(next): use forceStepModeFiles to transform package serde files in step mode
Instead of copying package serde+step files (which creates duplicate
classes with #private brand check issues) or generating fragile wrappers,
add the original file paths to a shared forceStepModeFiles set. The
loader checks this set and transforms those files in step mode directly,
so the SWC plugin generates proper step registrations on the original
class — no duplication, no reimplemented registration logic.
* fix(next): use step mode for all files with step/serde patterns, not just copies
The loader now selects step mode for any file that has 'use step'
directives or serde patterns, regardless of whether it's a deferred
step copy. Step mode is a superset of client mode — the only addition
is step registry IIFEs, which are harmless for non-step consumers.
This means package serde+step files (like Run) no longer need to be
copied to get step registrations. They're imported directly in the
step route and the loader transforms the original file in step mode.
One class instance, no duplication, no wrapper generation.
---------
Co-authored-by: Nathan Rajlich <n@n8.io>
* [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)