* Add encryption documentation and world features manifest
- Add encryption.mdx under How it Works explaining end-to-end encryption
- Add features array to worlds-manifest.json (encryption for Vercel World)
- Display encryption support in WorldDetailHero and WorldCardSimple
- Add cross-references from Vercel World and Observability pages
* Derive WorldFeature type from const array
* Address review feedback: simplify key explanation, show 'No' for missing encryption, fix tooltip
* test: improve e2e test failure diagnostics with run context and GitHub annotations
When e2e tests fail, automatically dump workflow run diagnostics (status,
input/output, error details, event timeline, dashboard link) to the CI
logs. Emit GitHub Actions annotations that surface on PR file diffs.
Fix collectedRunIds which was declared but never populated, enabling
observability links in the PR comment. Enrich the aggregation script
to include run IDs and dashboard URLs for failed tests.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: increase diagnostics hook timeout and fix flaky Vercel Prod tests
- Increase onTestFailed hook timeout to 30s (default was 10s) so
diagnostics can fetch run data even after slow test timeouts
- parallelSleepWorkflow: increase elapsed threshold from 10s to 25s to
accommodate Vercel cold start latency
- webhookWorkflow: increase hook polling deadline from 30s to 60s and
test timeout from 60s to 120s for slow Vercel webhook registration
- readableStreamWorkflow: stop reading once expected content is received
instead of waiting for stream close (which can hang on Vercel), and
increase test timeout to 120s
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: emit ::error annotations via process.stdout.write to bypass vitest ANSI prefix
Vitest's console interceptor prepends ANSI escape codes to console.log
output, which prevents GitHub Actions from parsing ::error workflow
commands. Use process.stdout.write() directly to ensure clean output.
Also enhance the custom reporter to emit annotations in onFinished
(which runs after vitest output is complete) as a reliable fallback,
and enrich failure data from the diagnostics sidecar.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: only show observability links for vercel-prod test failures
Community world and local tests don't run on Vercel's backend, so
dashboard links are meaningless for those categories. Previously,
test name collisions across sidecar files could cause community
test failures to show Vercel dashboard URLs from vercel-prod runs.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: link annotations to test files instead of symlinked workflow sources
The workflow source files in workbench/ are symlinks that GitHub can't
resolve, causing annotations to show raw paths like #L0 instead of
linking to code. Now:
- utils.ts: omit file= from onTestFailed annotations (just show title)
- github-reporter.ts: use the actual test file path (e.g.
packages/core/e2e/e2e.test.ts) which GitHub can resolve
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Add documentation for custom class serialization
* Enhance serialization docs: custom class examples with 'use step' instance methods
- Add custom classes to Supported Serializable Types with anchor link
- Replace verbose parenthetical in Requirements with back-link
- Add [!code highlight] to Basic Example serde methods
- Simplify geometry.ts to import Point instead of redefining it
- Rewrite Complex Example to demonstrate 'use step' on instance methods
with realistic APIs (database, HTTP) and contrast with workflow-context methods
- Add pass-by-value note for 'this' context with return-and-reassign pattern
* Fix docs typecheck: use correct @expect-error codes for Order examples
* Fix pre-existing docs typecheck failures in workflow-serde API reference
Add @skip-typecheck to bare static method signatures that aren't valid
standalone TypeScript.
* Revert extractor changes, use HTML comments for @expect-error markers
The docs typecheck extractor only supports HTML comment syntax for
@expect-error on main. Use <!-- @expect-error:XXXX --> instead of
{/* @expect-error:XXXX */} to match the existing convention.
* Use MDX comment syntax for @expect-error markers, add MDX support to extractor
MDX files don't support HTML comments (<!-- -->). The extractor's
@expect-error regex only supported HTML syntax, but @skip-typecheck
already supported both. This aligns @expect-error to also support
the MDX comment syntax ({/* @expect-error:XXXX */}).
* 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
* test: add e2e test proving sleep() works correctly inside loops
Validates a user-reported concern that sleep() inside a loop with step
calls fires all iterations instantly. The test confirms sleep is honored
on replay — 3 iterations with 3s sleeps take ~6s+ total elapsed time.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: address PR review comments
- Fix misleading "3s per iteration" comment to "3s between iterations"
- Update test comment to reflect 2.5s jitter-tolerant threshold
- Add per-iteration delta assertions to ensure each individual sleep fires
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Apply suggestion from @TooTallNate
Co-authored-by: Nathan Rajlich <n@n8.io>
Signed-off-by: Peter Wielander <mittgfu@gmail.com>
---------
Signed-off-by: Peter Wielander <mittgfu@gmail.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: Peter Wielander <mittgfu@gmail.com>
Co-authored-by: Nathan Rajlich <n@n8.io>
* refactor: use `this` value serialization for builtin step functions
Refactor builtin step functions (__builtin_response_json, _text,
_array_buffer) to use `this` instead of an explicit parameter,
leveraging the useStep() proxy's this value serialization support.
- Assign useStep() proxies directly onto Request.prototype and
Response.prototype instead of wrapping them in class methods
- Update builtin function signatures to use `this: Request | Response`
- Remove unused duplicate builtins file from @workflow/core
(the canonical copy lives in workflow/src/internal/builtins.ts)
* use Object.defineProperties for non-enumerable prototype methods
* fix(swc-plugin): closure variable detection for `new` expressions and module-level declarations
Fix two SWC compiler plugin bugs related to closure variable detection:
1. Add Expr::New handling to ClosureVariableCollector so `new Class(...args)`
properly captures both the callee and arguments as closure variables.
2. Exclude module-level declarations (functions, variables, classes) from
closure variable detection, preventing over-capturing of identifiers
that are already available in all bundles. This also allows DCE to
properly remove step-only helpers and their imports from the workflow
bundle.
Fixes#1365
* fix(swc-plugin): handle additional expression/statement types in closure variable collector
Expand closure variable detection to cover more AST patterns:
Expressions: Seq (comma), Yield, OptChain, Prop::Shorthand,
computed property keys, Prop::Assign defaults, Class (skip bodies)
Statements: Throw, Try/Catch/Finally, Switch, ForIn, ForOf,
DoWhile, Labeled
Also fix existing Prop::Shorthand bug where object shorthand
properties like { url } were not being collected as closure vars.
Extend test fixture with cases for all newly handled patterns.
Fix spec.md wording per review feedback.
* fix(swc-plugin): preserve original step function bodies in enclosing functions
In step mode, nested step functions were replaced with bare references
to the hoisted copy (e.g., `return hoisted$fn;`). This broke direct
calls because the hoisted copy uses `__private_getClosureVars()` which
only works in workflow context.
Now the original function body is preserved inline with just the
directive stripped, so JavaScript's normal closure semantics work for
direct calls. The hoisted copy with `__private_getClosureVars()` is
still registered for workflow-driven execution.
Fixes#1369
* fix(swc-plugin): restore metadata tracking for object property steps in step mode
The previous commit accidentally removed the
object_property_workflow_conversions tracking from the step mode path,
causing __internal_workflows metadata to be stripped from step bundle
output for object property step functions.
* fix(swc-plugin): detect closure variables inside nested function/method bodies
The closure variable collector was skipping nested function expressions,
arrow functions, and method bodies entirely. This meant closure
variables used deep inside inner functions (e.g., a variable used inside
a ReadableStream's start() method) were not captured.
Now the collector walks into nested function/arrow/method/getter/setter
bodies while adding their parameters to the local var set, so only
truly free variables from the outer step scope are captured.
Also add ReadableStream, WritableStream, TransformStream, and other
common Web API globals to the known globals list.
* update changeset to include Bug 4
* fix(swc-plugin): handle TypeScript expression wrappers and class bodies in closure detection
After comparing with Next.js's SWC plugin closure detection approach,
identified and fixed remaining gaps:
- TypeScript expression wrappers (as, satisfies, !, type assertions,
const assertions, instantiation expressions) now traverse to the
inner expression instead of being silently skipped
- Class expressions and declarations now walk their body members
(methods, properties, constructors, static blocks) to detect
closure variables used inside them
- Document all remaining safe-to-skip Expr variants (This, Lit,
SuperProp, MetaProp, PrivateName, Invalid, JSX)
* test: add fixture cases for TypeScript wrappers and class body closure detection
* test: add TypeScript fixture for closure detection through TS expression wrappers
Add a proper input.ts fixture that tests closure variable detection
through real TypeScript syntax: `as`, `satisfies`, `!` (non-null),
angle-bracket type assertions, `as const`, and generic function calls.
Update test harness to support input.ts files by adding swc_ecma_parser
dev-dependency and auto-detecting TypeScript syntax from file extension.
Remove the incorrectly placed TypeScript-related test cases from the JS
fixture (they were using plain JS syntax, not actual TS wrappers).
esbuild's discovery build cannot resolve @/ path aliases when the
tsconfig does not have baseUrl set. Use a relative import so the
discovery can trace through _workflows.ts to find all workflow files.
Apply messages override before system override so that the system
message is prepended to the new prompt instead of being discarded.
Previously, system was applied first then messages replaced the
entire conversation prompt, losing the system message.
Add tests for prepareStep system/messages ordering:
- system only: prepended to prompt
- system + messages: system prepended to replaced messages
- system + messages with existing system: replaces existing
- system updates across multi-step tool call rounds
* fix trace viewer for v1 events
* add changeset
* add a test
* add a test for web-shared
* add lock file
* update logic to look for run_created event first
* handle step created
* add changeset
* fix trace viewer for v1 events
* add changeset
* add a test
* add a test for web-shared
* add lock file
* update logic to look for run_created event first
* add stepName with events
* add changeset
* add workflowname to run created
* add postgres migration
* update world-local
* update world-local
* preserve the fields in the original shape
* fix tests
* strip only ref/payload fields
* stub the helper into world
* add test coverage
* fix web package
* fix web package to not pass withData: true
* Add DurableAgent compat tests, e2e agent tests, and migrate to AI SDK v6
- Port ToolLoopAgent test suite as DurableAgent compatibility spec (34 tests,
all expected to fail — each maps to a feature gap to implement)
- Add e2e workflow definitions using mock LLM providers (no API keys needed)
- Add e2e test file for DurableAgent workflows
- Migrate all AI SDK types from V2 to V3 (LanguageModelV2 → V3, etc.)
- Drop AI SDK v5 support: ai peer dep ^5||^6 → ^6, @ai-sdk/provider ^2||^3 → ^3
- Update ai catalog version from 5.0.104 to 6.0.116
- Simplify CompatibleLanguageModel to just LanguageModelV3
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Address PR review feedback
- Remove providerExecuted guard on tool-result stream parts (V3: all
tool-results are provider-executed by definition)
- Remove providerExecuted spread from tool-output-available UI chunks
- Replace inline MockLanguageModelV3 with import from ai/test (works
without msw in AI SDK v6)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Remove streamTextIterator mock from compat tests, use it.fails for gaps
Tests now exercise the real DurableAgent code path instead of mocking
the core iterator. 5 tests pass (features DurableAgent already has),
29 are marked it.fails() for known API gaps that will alert when fixed.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Implement Tier 1+2 gaps, add @workflow/ai/test mock provider, wire e2e in CI
DurableAgent API additions:
- Add `instructions` (string | SystemModelMessage | SystemModelMessage[])
as alias for deprecated `system` on constructor
- Add `onStepFinish` and `onFinish` on constructor, merged with stream
options (constructor first, then stream — matching ToolLoopAgent)
- Add `timeout` on stream options (converted to AbortSignal)
- Add `text`, `finishReason`, `totalUsage` to onFinish event
Test infrastructure:
- Add @workflow/ai/test export with `mockModel()` wrapper that wraps
MockLanguageModelV3 from ai/test as an async step function
- E2e workflows now use mockModel() + convertArrayToReadableStream
from @workflow/ai/test instead of inline V2 mock models
- Add e2e-agent.test.ts to test:e2e script so it runs in CI
- Flip 6 compat tests from it.fails → it (now passing)
Score: 11 passing / 23 it.fails (was 5/29)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Remove e2e agent tests — mock models can't serialize across step boundary
The workflow runtime serializes step arguments, and function closures
(like mock model doStream callbacks) aren't serializable. Mock models
only work in unit tests where 'use step' is a no-op. Real e2e agent
tests would need either a mock HTTP server or real provider credentials.
Also removes 'use step' from mockModel wrapper (closures aren't
serializable) and reverts test:e2e script and example workbench dep.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Add working e2e agent tests with mock model step factories
Mock model factories use the same 'use step' pattern as real providers
(anthropic, openai). Closure variables are bound to locals at the step
body level so the SWC plugin detects them via __private_getClosureVars.
All 4 e2e tests pass against local dev server:
- agentBasicE2e: text response (11s)
- agentToolCallE2e: single tool call + text (11s)
- agentMultiStepE2e: 3 sequential tool calls (12s)
- agentErrorToolE2e: FatalError recovery (11s)
Also adds e2e-agent.test.ts to test:e2e script for CI.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Use @workflow/ai/test package imports for e2e mock models
Split mock provider into two files to work around SWC constructor
closure bug: mock-create.ts has the model creation logic,
mock.ts has the 'use step' wrappers that capture only serializable
args (strings, plain object arrays).
Exports mockTextModel(text) and mockSequenceModel(responses) —
same 'use step' pattern as real providers (anthropic, openai, etc.).
E2e workflows now import directly from @workflow/ai/test.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Simplify mock provider, add comprehensive e2e tests for all features + gaps
Mock provider:
- Replace mock-create.ts with mock-function-wrapper.ts that simply wraps
MockLanguageModelV3 constructor in a function (SWC class closure bug)
- mockTextModel/mockSequenceModel use mockProvider() from wrapper file
- Bind closure vars at step body level (_text = text) for SWC detection
- Fix AbortController not available in workflow VM sandbox
E2e tests (13 total, all passing):
- Core: basic text, tool call, multi-step, error recovery (4)
- Callbacks: onStepFinish constructor+stream, onFinish constructor+stream (2)
- Features: instructions, timeout (2)
- GAPs documented: onStart, onStepStart, onToolCallStart,
onToolCallFinish, prepareCall (5 — complete but callbacks not called)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Add tool approval (needsApproval) gap tests, fix SWC closure var binding
Unit tests: 2 new it.fails() tests for tool approval
- needsApproval: true should pause agent (pending tool call, no result)
- needsApproval as function should receive tool input
E2e tests: 1 new test for tool approval gap
- Documents that needsApproval is currently ignored (tool executes anyway)
Also fixes:
- Bind closure vars at step body level in mock provider (_text = text,
_responses = responses) so SWC plugin detects them
- Guard AbortController usage in workflow VM (not available in sandbox)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Add default args for agent e2e workflows in UI definitions
The nextjs-turbopack UI calls workflows with hardcoded default args.
Without these entries, agent workflows were called with no args,
causing prompt=undefined → ModelMessage validation failure.
Also removes debug logging.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Add DurableAgent chat UI with tools, update docs for AI SDK v6
Chat UI:
- Tab-based layout with Workflows (existing) and DurableAgent Chat tabs
- Chat powered by DurableAgent + WorkflowChatTransport + ai-elements
- Tools: getWeather (fake data), calculate (math expressions)
- Uses createUIMessageStreamResponse for proper stream serialization
- Reconnect route at /api/chat/[runId]/stream
- ai-elements components: conversation, message, prompt-input, tool
- onStepFinish + onFinish callbacks with console logging
Docs (AI SDK v6 migration):
- system → instructions in DurableAgent constructor examples (10 places)
- LanguageModelV2Prompt → LanguageModelV3Prompt in type references (3 places)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Fix tool rendering, add reasoning support, model picker, observability links
- Fix tool part rendering: use `input`/`output` props (not `args`/`result`)
and `tool-{name}` part type (AI SDK v6 format)
- Add reasoning support for Opus 4.5 via providerOptions
- Model picker: Haiku 4.5, Sonnet 4, Opus 4.5 (reasoning), GPT-5.2, GPT-5.3
- Fix observability links: localhost:3456 for local, Vercel dashboard for prod
- Add suggestions above prompt input
- Add MessageParts component handling text, tool, reasoning, step-start
- Add loading spinner for submitted state
- Update docs: system → instructions, LanguageModelV2Prompt → V3
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Fix tool output rendering: use input/output props on ToolInput/ToolOutput
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Fix: Documentation for `PrepareStepInfo` and `PrepareStepResult` interfaces references the obsolete `LanguageModelV2` type while the codebase has fully migrated to `LanguageModelV3`.
This commit fixes the issue reported at docs/content/docs/ai/message-queueing.mdx:36
**Bug explanation:**
The codebase migrated from AI SDK V2 to V3. In `packages/ai/src/agent/types.ts`, `CompatibleLanguageModel` is defined as `LanguageModelV3` (from `@ai-sdk/provider`). The actual TypeScript interfaces in `packages/ai/src/agent/durable-agent.ts` use `string | (() => Promise<CompatibleLanguageModel>)` which resolves to `LanguageModelV3`.
However, the documentation in `docs/content/docs/ai/message-queueing.mdx` at lines 36 and 43 still referenced `LanguageModelV2` for the `model` field in both `PrepareStepInfo` and `PrepareStepResult`. This is inconsistent because:
1. The `messages` fields in the same interfaces were correctly updated to `LanguageModelV3Prompt`
2. The actual source code uses `LanguageModelV3` via `CompatibleLanguageModel`
3. There is no `LanguageModelV2` type anywhere in the codebase
This would mislead developers reading the documentation into using the wrong type.
**Fix explanation:**
Changed both `LanguageModelV2` references to `LanguageModelV3` on lines 36 and 43 of the documentation file, matching the actual codebase types. Verified no other stale `LanguageModelV2` references remain in the docs directory.
Co-authored-by: Vercel <vercel[bot]@users.noreply.github.com>
Co-authored-by: pranaygp <pranay.gp@gmail.com>
* Fix instructions tests: flip from it.fails to it, update snapshots
The 3 instructions tests (string, SystemModelMessage, array) now pass.
The snapshots include the assistant reply message from the agent loop,
which is a behavioral difference from ToolLoopAgent (DurableAgent
captures the prompt after the full loop iteration).
Score: 14 passing / 22 it.fails (was 11/25)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Fix getReadable call: pass startIndex as options object
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Fix docs type errors and turbopack build
Docs:
- Add await to convertToModelMessages() calls (now async in AI SDK v6)
- Change LanguageModelV3Prompt → ModelMessage[] in type references
- Change LanguageModelV3 → LanguageModel in PrepareStepInfo
- Update docs-globals.d.ts convertToModelMessages return type
- Add LanguageModel to import inference map
DurableAgent:
- Update OutputSpecification to match AI SDK v6 Output interface
(type→name, parsePartial→parsePartialOutput, parseOutput→parseCompleteOutput,
responseFormat now PromiseLike)
Turbopack build:
- Remove streamdown plugins from MessageResponse (plugins prop API
changed in streamdown 2.4.0, causing type mismatch in CI)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Fix pnpm-workspace.yaml: use double quotes for catalog entries
The stage-workbench-with-tarballs.mjs script only strips double quotes
when parsing catalog keys. Single-quoted @-scoped entries (e.g.,
'@types/node') weren't matched, causing "unresolved catalog dependencies"
errors in CI.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Fix CI build failures, add changeset
- Remove streamdown plugins from reasoning.tsx (same CI type mismatch)
- Cast ToolHeader type prop and WorkflowChatTransport to fix type errors
- Fix pnpm-workspace.yaml single→double quotes for staging script
- Add minor changeset for @workflow/ai (breaking: AI SDK v6 migration)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Sync webpack workbench with turbopack: add chat UI deps and symlinks
- Symlink app-shell.tsx, chat-client.tsx, agent_chat workflow,
chat API routes into nextjs-webpack
- Add matching deps: streamdown, @streamdown/*, shiki, cmdk, nanoid,
motion, @radix-ui/react-use-controllable-state
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Fix circular symlink: restore chat-client.tsx as real file in turbopack
The previous commit accidentally converted turbopack's chat-client.tsx
into a circular symlink pointing to itself. Webpack's symlink to it
then couldn't resolve, breaking both builds on Vercel.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Add missing deps to webpack: use-stick-to-bottom, radix-ui, @vercel/blob
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Fix model picker: merge body params via prepareSendMessagesRequest
WorkflowChatTransport sends { messages } by default, ignoring the
body option from ChatRequestOptions. Use prepareSendMessagesRequest
to merge { messages, ...body } so the model selection reaches the API.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Fix WorkflowChatTransport: forward body/headers from ChatRequestOptions
The transport hardcoded body: undefined when calling
prepareSendMessagesRequest, so extra body params (like model selection)
from sendMessage({ body: { model } }) were silently dropped.
Now forwards options.body and options.headers to both
prepareSendMessagesRequest and the default request body.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Fix model IDs: use real AI Gateway model names
gpt-5.2 and gpt-5.3 don't exist in the AI Gateway.
Replace with gpt-4o and gpt-4o-mini.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Use correct AI Gateway model IDs: Opus 4.5, GPT-5.2, GPT-5.3
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Enable reasoning for all model providers
- Anthropic: thinking.type='enabled' with 10k token budget
- OpenAI: reasoningEffort='high'
- Instructions kept for all models (no longer conditionally removed)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Fix OpenAI reasoning: use 'medium' effort (GPT-5.3 doesn't support 'high')
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Address all PR review comments
- Change changeset from minor to patch (repo convention)
- Use ?? instead of || for system/instructions fallback
- Clean up timeout: store ID, clearTimeout in finally, { once: true } listeners
- Update class docstring example to use instructions
- Map unrecognized finish reasons to 'other' with validation
- Fix duplicate test, align assertion for unrecognized type
- Support ^ exponentiation in calculate tool
- Remove debug console.log from chat client
- Fix ReactNode/ComponentProps type imports in UI components
- Remove unused MockLanguageModelV3 re-exports from mock.ts
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Remove accidentally created empty mock2.ts
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Change changeset back to minor for breaking AI SDK v6 migration
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Fix agent e2e tests: add Vercel world setup for CI
The agent e2e tests only configured the local filesystem world but not
the Vercel world backend. On CI (Vercel prod tests), this caused
VercelOidcTokenError because the world wasn't initialized.
Now matches the setup pattern from e2e.test.ts: configures Vercel world
with OIDC token and project config from CI environment variables.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Deduplicate e2e test utilities: extract shared code to utils.ts
Extract manifest fetching, workflow lookup, world setup, and types
into shared utils.ts. Both e2e.test.ts and e2e-agent.test.ts now
import from the same source, eliminating ~200 lines of duplication.
Shared utilities:
- WorkflowManifest interface
- fetchManifest() with caching
- getWorkflowMetadata() with retry and fallback
- setupWorld() handling local/Vercel/Postgres backends
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Fix missing deploymentUrl args in e2e.test.ts after utils refactor
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Add @workflow/ai dep to all workbenches for agent e2e tests
All workbenches now have @workflow/ai as a dependency and the
100_durable_agent_e2e.ts symlink, so agent e2e tests run everywhere.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Fix missing imports in e2e.test.ts: add fetchManifest and sleep
The utils refactor removed these imports but they're still used:
- fetchManifest: used in stepFunctionAsStartArgWorkflow test
- sleep (setTimeout): used in webhookWorkflow 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: Vercel <vercel[bot]@users.noreply.github.com>
* Skip OIDC call in fetchRunKey when token already available
getVercelOidcToken() was called unconditionally before checking
options.token or VERCEL_TOKEN. In the CLI/e2e context where a token
is always provided, this is a wasted call that can hang in CI.
Reorder the fallback chain: options.token -> VERCEL_TOKEN -> OIDC.
* Add changeset for OIDC skip fix
* Update changeset and comments to document token precedence order
* Update event list to show decrypt button when a row is expanded
* improve loading skeleton
* add timestamp tooltip
* add a toast adapter
* add changeset
* remove noop timestamp tool tip
* add toast for decryption
* add toast for decryption
* swc-playground: add resizable panels, collapsible outputs, vim mode toggle, and clean up deps
- Add resizable split between input editor and output panels using react-resizable-panels
- Add collapsible accordion-style output views (workflow/step/client) with chevron toggles
- Add vim keybindings toggle (persisted to localStorage) using monaco-vim
- Add shadcn Switch and Resizable UI components
- Remove unused individual @radix-ui/react-* packages in favor of unified radix-ui package
- Remove unused bulk shadcn init dependencies (recharts, sonner, vaul, zod, cmdk, etc.)
* Address PR review: fix vim mode race condition, mount timing, and add aria attributes
- Add cancellation flag to async monaco-vim import to prevent stale callbacks
- Add .catch() for import failure handling
- Track editor mount state so vim mode initializes when persisted as enabled
- Add aria-expanded and aria-controls to collapsible output panel toggle buttons
* fix: separate infrastructure vs user code error handling in runtime and step handler
Transient network errors (ECONNRESET, etc.) during infrastructure calls
(event listing, event creation) were caught by a shared try/catch that
also handles user code errors, incorrectly marking runs as run_failed
or steps as step_failed instead of letting the queue redeliver.
- runtime.ts: Move infrastructure calls outside the user-code try/catch
so errors propagate to the queue handler for automatic retry
- step-handler.ts: Same structural separation — only stepFn.apply() is
wrapped in the try/catch that produces step_failed/step_retrying
- helpers.ts: Add isTransientNetworkError() and update withServerErrorRetry
to retry network errors in addition to 5xx responses
- helpers.test.ts: Add tests for network error detection and retry
* add changeset
* remove withServerErrorRetry and isTransientNetworkError
Redundant with undici RetryAgent which already handles 5xx retries
and network error retries at the HTTP dispatcher level.
* address review feedback: move getEncryptionKeyForRun out of user-code try/catch, re-add 5xx/410 safety net in step handler, relax e2e test assertion
* remove serverError5xxRetryWorkflow e2e test
This test validated withServerErrorRetry's in-process retry behavior,
which was removed. Queue-level retry with process-scoped fault injection
is unreliable across serverless instances and too slow for e2e timeouts.
* remove serverError5xxRetryWorkflow and fault injection helpers from e2e workflows
* remove inline comment about deleted test
spawn({timeout}) sends SIGTERM by default, but the CLI process ignores it
(likely due to undici keeping active connections alive). The process then
runs for minutes until vitest or GitHub Actions eventually kills it.
Using killSignal: 'SIGKILL' ensures the process is forcefully terminated
when the 20s timeout fires, since SIGKILL cannot be caught or ignored.
Set setupGitUser: false on changesets/action to prevent it from
overwriting our git config with the hardcoded github-actions[bot]
identity. The git identity is now configured in a prior step using
the app-slug output from actions/create-github-app-token.
Set git user.name and user.email so that the 'Version Packages' commit
created by changesets/action is attributed to the app's bot account
instead of the default github-actions[bot].
The health command's `endpoint` flag and the shared `env` flag both
declared `char: 'e'`, causing ambiguity. Remove the short flag from
`endpoint` so `-e` unambiguously maps to `--env`.
The e2e tests spawn a CLI subprocess for every inspect/cancel/health call.
Each subprocess performs an npm registry version check on startup, which
can hang under load and exceed the 20s spawn timeout, causing SIGTERM.
Add WORKFLOW_NO_UPDATE_CHECK=1 env var support to skip the check, and
set it in the e2e test harness.
Replace GH_TOKEN_PULL_REQUESTS (shared org PAT) with a dedicated GitHub
App token to avoid rate limiting from noisy neighbors. The app token is
generated per-run via actions/create-github-app-token, providing its own
rate limit bucket and short-lived credentials.
The warning about WORKFLOW_VERCEL_* env vars having no effect at runtime
was incorrectly shown when the Workflow CLI or web observability app was
running. These tools intentionally set those env vars. Gate the warning
on VERCEL=1 so it only fires inside Vercel serverless functions where the
env vars are truly unnecessary.
* Fix connector line showing for run events
* Improve row toggle
* improve error reporting
* add sorting for events
* add changeset
* update search to be best match
* feat: add `exists` getter to `Run` class
Allow checking if a workflow run exists without catching errors.
Returns `true` if the run is found, `false` for WorkflowRunNotFoundError,
and re-throws any other errors.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* address PR feedback: use resolveData: 'none' in exists getter, fix docs wording
Pass { resolveData: 'none' } to world.runs.get() in the exists getter
to skip fetching input/output payloads. Update docs to say "without
throwing when the run is not found" instead of "without throwing an error".
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Support client-side tools in DurableAgent
Tools without an `execute` function now pause the agent loop and return
`clientToolCalls` in the result, enabling human-in-the-loop and
client-side tool execution patterns. Fixes#847.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Match AI SDK result shape for client-side tools
Use `toolCalls` and `toolResults` on DurableAgentStreamResult to match
the AI SDK's GenerateTextResult convention. Consumers find unresolved
client-side tool calls by diffing toolCalls vs toolResults — the same
pattern used with useChat/addToolOutput.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Address PR review feedback
- Use iterMessages (not options.messages) so returned messages include
the assistant tool-call message, enabling callers to resume
- Add resolved server/provider tool results to returned messages as a
tool role message so callers don't re-execute when resuming
- Treat missing tools (!tool) as errors (will throw in executeTool),
only tools that exist but lack execute are client-side
- Track tool-output-available chunks in allUIChunks when
collectUIMessages is enabled so uiMessages is complete
- Add message assertions to tests
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Clean up type casts in client-side tools path
Push directly to iterMessages (LanguageModelV2Prompt) instead of
double-casting through ModelMessage[]. Single cast at the return
point matches the existing pattern at the end of stream().
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Reverse check in resolveProviderToolResult for early exit
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>