Commit Graph

1384 Commits

Author SHA1 Message Date
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
Nathan Colosimo dd36e26962 Fix Postgres step lifecycle event ordering (#2714)
* Fix Postgres step start event ordering

* Document Postgres step start transaction

* Increase canary HMR e2e timeouts

* Address Postgres lifecycle review comments
2026-07-02 18:35:56 +00:00
Nathan Colosimo 5faffbce95 fix(vitest): derive workflow cwd from project root (#2726)
* fix(vitest): derive workflow cwd from project root

* chore(vitest): simplify project root options
2026-07-02 11:10:20 -07:00
Nathan Colosimo 923ddd98d9 fix(nitro): pass workflow dirs to builders (#2722) 2026-07-02 11:07:37 -07:00
Nathan Colosimo 532b0e10d6 fix(vite-frameworks): derive workflow roots (#2725)
* fix(vite-frameworks): derive workflow roots

* chore(vite-frameworks): simplify derived roots

* chore(vite-frameworks): simplify root derivation

* fix(sveltekit): respect configured routes directory

* test(frameworks): cover builder option pass-through

* test(frameworks): remove builder option tests

* fix(sveltekit): assert loaded routes config

* docs(sveltekit): note internal config loader
2026-07-01 22:50:02 -07:00
Nathan Colosimo 7eabc1f4c6 fix(next): derive workflow project root (#2729)
* fix(next): derive workflow project root

* test(next): clean temp root after leaving app dir

* chore(next): simplify project root detection

* chore(next): mirror root detection
2026-07-01 11:56:44 -07:00
Ben Sabic 5b7fa7cf15 chore(docs): update eve link (#2738)
eve homepage is now live, change the link from the docs to the homepage now, reflecting how the other OSS sites behave

Signed-off-by: Ben Sabic <bensabic@users.noreply.github.com>
Co-authored-by: Ben Sabic <bensabic@users.noreply.github.com>
2026-07-01 10:42:18 -07:00
Nathan Colosimo 0f02af4cfb fix(ai): continue durable agent tool loops (#2730) 2026-07-01 16:40:43 +00:00
Karthik Kalyan f76377bf04 Add workflow analytics world APIs (#2234)
* Add workflow analytics world APIs

* Document analytics schema boundary

* Align analytics SDK contract with access metadata
2026-06-30 18:36:49 -07:00
Nathan Colosimo 3077b8a803 fix(nitro): use workspaceDir for monorepos (#2713)
* fix(nitro): use workspaceDir for monorepos

* test: stabilize Next canary HMR e2e
2026-06-30 13:42:53 -07:00
Nathan Colosimo 97b8469020 Fix workflow Postgres enum schemas (#2705) 2026-06-30 12:08:01 -07:00
Nathan Colosimo 65f1dbc889 Fail fast on incompatible workflow worlds (#2659) 2026-06-30 10:43:39 -07:00
Nathan Colosimo 7615d999f1 Fix graph extraction for annotated step proxies (#2702) 2026-06-30 09:16:43 -07:00
Pranay Prakash fc5bdcb003 [world-local] Reduce sequential replay I/O (#2152)
* [world-local] Reduce sequential replay I/O

* Fix relative local event cache lookups

* Keep event cache eviction test lightweight

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-29 22:48:04 -07:00
Nathan Colosimo 692a6ac5dc Upgrade workspace to TypeScript 6 (#2700)
* Upgrade workspace to TypeScript 6

* Restore Nest baseUrl for SWC builds

* Use empty changeset for TS6 upgrade

* Remove TS6 changeset
2026-06-30 05:37:38 +00:00
Peter Wielander 654f95911b fix(ai): recover from invalid tool-call input instead of aborting the agent stream (#2699)
In-repo copy of #2192 by @boomyao, opened to run the full CI suite.

Co-authored-by: yao <zhangyaoruo@outlook.com>
2026-06-29 18:45:07 -07:00
Karthik Kalyan 89f4726b73 Fix compressed workflow error display (#2680)
* Fix compressed workflow data display

* Add OSS web no-key hydration regression

* Scope compression normalization to read paths; tidy hydration

Address review feedback on the compressed-data fix:

- world-vercel: keep gzip/zstd decompression on the o11y/display read
  paths (getStep/getRun/getEvent/getWorkflowRunEvents/getHook) but not on
  the runtime event-append path (world.events.create, createStep,
  updateStep). That path is runtime-only and re-hydrates every payload via
  the decompress-aware helpers, so decompressing at the adapter was
  redundant work on the TTFB-sensitive run_started/inline-delta path and
  skewed the runtime's deserialize compression telemetry to `codec: none`.
  deserializeStep is now shape-only; normalizeStepData runs in the read
  filter. Adds a regression test pinning the write-path pass-through.
- serialized-data: drop dead `errorRef`/`metadataRef` normalization (refs
  are descriptor objects, never compressed byte payloads).
- web: in the wait-entity path, filter events by correlationId before
  hydrating so an encryption key doesn't decrypt the whole event page.

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

---------

Co-authored-by: Peter Wielander <peter.wielander@vercel.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-29 16:50:43 -07:00
Nathan Colosimo 5a231598e4 test: reduce e2e timing flakes (#2665)
* test: reduce e2e timing flakes

* test: tighten e2e timing bounds
2026-06-29 15:50:42 -07:00
JJ Kasper f6772d95c8 Optimize Next dev HMR rebuilds (#2678)
* Optimize Next dev HMR rebuilds

* Fix Next dev HMR CI coverage

* Gate dev HMR logs behind opt-in flag

* Match workflow dev build logs to Next style

* Fix Next dev HMR changed-file classification

* Fix Windows port detection

* Relax HMR log wait in dev e2e

* Avoid canary workflow execution cache flakes

* Allow slower Turbopack HMR propagation in e2e

* Scope canary HMR fuzz execution assertions
2026-06-29 20:58:38 +00:00
Mitul Shah 6080b8ecdf Add arrow key support on trace viewer (#2694)
* Update trace-viewer.tsx

* Create spicy-paws-nail.md

Signed-off-by: Mitul Shah <mitulxshah@gmail.com>

---------

Signed-off-by: Mitul Shah <mitulxshah@gmail.com>
2026-06-29 20:49:47 +00:00
Mitul Shah ce0bbb1198 fix(web-shared): use Unicode ellipsis character in middle-truncate (#2695)
Co-authored-by: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-06-29 20:29:03 +00:00
JJ Kasper 24f370773d Fix Workflow loader source map warnings (#2693) 2026-06-29 20:16:46 +00:00
Mitul Shah 53ecc57e4c fix(web-shared): align metadata panel styling with attributes section (#2604)
* fix(web-shared): align metadata panel styling with attributes section

Render hook metadata as key-value rows inside a DetailCard, matching
the Attributes section instead of a raw JSON block with a separate label.

* fix(web-shared): align top detail panel rows with attributes styling

Reuse DetailKeyValueRow for Module, Step ID, timestamps, etc. — same
tighter spacing, typography, and no dividers as the Attributes section.

* fix(web-shared): collapse top detail rows into Metadata with mono values

Wrap Module, Step ID, timestamps, etc. in a Metadata DetailCard and
render all values in monospace, including copyable paths and IDs.

* fix(web-shared): use contained header style for Metadata section

Add a contained DetailCard variant with rounded bg header and drop my-2
in favor of py-2 padding on the section wrapper.

* refactor(web-shared): drop reserved badge and use cn for row classes

Remove ReservedBadge and showReservedBadge; keep reserved-key sorting only.
Use cn() for conditional mono font classes in DetailKeyValueRow.

* refactor(web-shared): drop contained DetailCard variant

Use the default section DetailCard for Metadata, matching Attributes.

* feat(web-shared): extend cn with custom tailwind-merge class groups

Add a dedicated cn module that understands text-heading, text-label,
text-copy, text-button, and material utilities when merging classes.

* chore: note cn tailwind-merge update in changeset

* fix(web-shared): remove my-2 from DetailCard summary rows

Move vertical spacing to py-2 on the section container instead.

* fix(web-shared): scope Metadata spacing override

Restore shared DetailCard summary spacing for Input, Output, Events, and
Attributes while keeping Metadata tighter with a summaryClassName override.

* refactor(web-shared): use CVA variants for detail row value styling

Replace the mono boolean and one-off Metadata summary override with CVA-backed row variants and semantic mono row wrapper.

* fix(web-shared): use section padding for DetailCard spacing

Move spacing from summary margins to section padding and add content top
spacing so collapsed and expanded detail cards both breathe consistently.

* fix(web-shared): remove expanded Metadata content gap

Keep DetailCard's default expanded content spacing for data panels, but let
Metadata rows start directly below the title via contentClassName merge.

* refactor(web-shared): use Tailwind classes for disabled detail card

* refactor(web-shared): use DetailCard compound content

* refactor(web-shared): rebuild DetailCard as a compound component

Replace the monolithic DetailCard (summary/trailing/disabled props plus
child-type reflection for content) with a context-driven compound API:
DetailCard + DetailCard.Trigger + DetailCard.Content. Drop the dead
trailing branch, expose data-slot/data-state, and migrate all call sites.

* refactor(web-shared): rename DetailCard to Collapsible

It's a generic collapsible section, not a card-specific component. Rename
the component, its parts, data-slots, and the file accordingly.

* refactor(web-shared): split Collapsible into all-in-one + parts

Export a batteries-included <Collapsible label> for the common case so
consumers don't recompose the trigger/content every time, plus
CollapsibleRoot/CollapsibleTrigger/CollapsibleContent for the few call
sites that need to override part styling. Drop the dot-notation namespace.

* refactor(web-shared): move Collapsible into ui directory

It's a generic UI primitive, not sidebar-specific.

* refactor(web-shared): import cn from lib/cn directly

Drop the cn re-export from lib/utils; consumers import it from its
actual source instead of routing through utils.

* refactor(web-shared): drop cn tailwind-merge changes from this PR

Move the extended cn (lib/cn) work to a separate PR; this branch keeps
using the existing cn from lib/utils.

* ship it

---------

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
2026-06-29 14:26:51 -04:00
github-actions[bot] d1a040c9ed Version Packages (beta) (#2688)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
workflow@5.0.0-beta.26
2026-06-28 17:15:25 -07:00
Pranay Prakash 603ad97615 Redrive on transient workflow-server transport failures instead of failing the run (#2445)
* Redrive on transient workflow-server transport failures instead of failing the run

A firewall in front of workflow-server shedding load with sustained 429/503
makes undici's shared RetryAgent exhaust its retries and throw
UND_ERR_REQ_RETRY. That raw error was rethrown unwrapped, so it was
classified as USER_ERROR and the replay terminal branch wrote run_failed —
permanently failing a run on a transient blip (or, in an outage, falling back
to the ~5min queue visibility-timeout redrive).

- world-vercel: map exhausted-retry / socket / connect / DNS / timeout
  failures to a typed WorkflowWorldError (code TRANSPORT/TIMEOUT) by walking
  the fetch() cause chain.
- core: add isRetryableWorldError (429 / 5xx / TRANSPORT / TIMEOUT) and
  rethrow such errors from the replay terminal branch so the queue redrives
  quickly (1s->60s backoff) instead of failing the run. Reuse it in start()
  and step_started handling.
- world-vercel: surface the Vercel firewall x-vercel-mitigated
  (challenge/deny) header alongside x-vercel-id in error diagnostics and logs.

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

* Address review: back off + cap on every retry path; fix mock; refine scope

Revises the transport-error handling per PR review (VaguelySerious,
karthikscale3).

Blocking fix — step_started no longer self-enqueues a throttled defer for
transient world errors. Returning `{ type: 'throttled', timeoutSeconds: 1 }`
acked the delivery and enqueued a fresh message, resetting the delivery count
so the path never backed off and never reached MAX_QUEUE_DELIVERIES — an
unbounded flat-1s loop if step_started kept failing. It now throws, so the
error flows through the replay loop's retryable-world-error rethrow and earns
both the delivery-count backoff and the max-delivery cap. Throwing is safe on
step_started (the body hasn't run; a write that landed dedupes to skipped).

Also in this revision:
- Backoff that lasts: raise the queue handler-error retry ceiling 60s -> 900s.
  VQS clamps each redelivery to its 900s SQS limit and adds its own post-32
  exponential, so ramping our base toward 900s stretches survival from ~3.7h to
  most of the 24h message-visibility window. Corrected the stale
  MAX_QUEUE_DELIVERIES comment to match the real VQS schedule.
- Stop amplifying firewall challenges: the undici RetryAgent no longer retries
  429 in-process (a challenge is a 429 the client can't solve). 429s surface
  immediately as ThrottleError carrying x-vercel-mitigated / x-vercel-id, so
  the diagnostic header now reaches us for the challenge case too.
- Track world faults as WORLD_CONTRACT_ERROR (not USER_ERROR) in
  classifyRunError so an outage isn't attributed to user code.
- Fix queue.test.ts mock that `biome check --write` had rewritten from a
  newable `function` into an arrow (broke `new QueueClient`); pin with a
  biome-ignore.

All Vercel-specific logic stays in @workflow/world-vercel; @workflow/core
operates only on the generic WorkflowWorldError abstraction.

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

* Update .changeset/transport-error-redrive.md

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

* Trim changeset to a single sentence per review

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

* Route firewall-challenge 429s to the retryable transport path, not ThrottleError

A 429 carrying `x-vercel-mitigated: challenge` is a firewall challenge our
server-to-server client cannot solve, so it recurs for the life of the
incident. Mapping it to `ThrottleError` meant the `step_started` write deferred
it as `{ type: 'throttled' }`, which self-enqueues a FRESH queue message and
resets the delivery count — so it never backed off past `retryAfter` and never
reached `MAX_QUEUE_DELIVERIES`, hot-looping against an already-overloaded
firewall (the exact amplification this PR set out to remove, and contrary to
the "step_started can't loop unbounded" invariant, which only held for 5xx).

Map a challenge to a retryable transport `WorkflowWorldError` (`code:
'TRANSPORT'`) in both the v3 `makeRequest` and v4 `throwForErrorResponse`
(the hot event-write path) error mappings, via a shared `isFirewallChallenge429`
helper. It then propagates through the V1/V2 step paths and the replay loop's
retryable-world-error rethrow, earning the delivery-count backoff AND the
delivery cap. A genuine application-level 429 (no `challenge` mitigation) stays
a `ThrottleError` and keeps its `Retry-After`-paced defer.

Also correct the survival-window comments: with the 900s ceiling,
MAX_QUEUE_DELIVERIES=48 spans ~9-10h (~35,000s), not "the better part of 24h";
reaching 24h would need a higher delivery cap, not a higher per-hop ceiling.

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

---------

Signed-off-by: Peter Wielander <mittgfu@gmail.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: Peter Wielander <mittgfu@gmail.com>
Co-authored-by: Peter Wielander <peter.wielander@vercel.com>
2026-06-28 17:05:03 -07:00
Peter Wielander 2477ad85a7 [core] Gate turbo end-of-run drain writes on the run-ready barrier (#2685) 2026-06-28 16:33:15 -07:00
Pranay Prakash 897aac979f fix(world-vercel): retry idempotent event POSTs in-process to avoid step re-execution (#2675)
* fix(world-vercel): retry idempotent event POSTs in-process to avoid step re-execution

undici's RetryAgent never retries a POST, so a transient transport blip (UND_ERR_REQ_RETRY, ECONNRESET, socket/headers timeout, transient 5xx) when committing a step's terminal event bubbles out, the queue redelivers, and the step's user code re-executes with attempt++ even though it already ran to completion.

workflow-server makes these writes idempotent in outcome: entity handlers run before the event-log row is inserted and state transitions are conditional writes excluding terminal states, so a retry whose original landed throws before any row is written and surfaces as a 409 the SDK already handles. This adds a bounded in-process retry (new event-retry.ts) gated by a validated per-event EVENT_RETRY_ELIGIBILITY map, excluding step_started (double-increments attempt), step_retrying (appends a duplicate row), and hook_received (no server guard).

Complements #2666, which routes completion-persistence failures to queue redelivery instead of recording them as user failures; this avoids the redelivery (and re-execution) for transient blips.

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

* fix(world-vercel): address review on event-POST retry

- Don't retry external cancellation: drop AbortError from the transient set (keep self-timeout TimeoutError), so a caller-requested abort isn't re-issued or stalled by the backoff budget.

- Add DEBUG-gated logging on each retry and on retry exhaustion so an in-process retry vs. a fall-through to queue redelivery is distinguishable in logs.

- Clarify docs: a landed retry surfaces as 409 for most types, but run_started/attr_set return 200 success (not a 409).

- Add createWorkflowRunEvent integration tests (events-retry.test.ts): eventType is threaded into the retry wrapper, and the 404->HookNotFoundError mapping still fires after the retry loop.

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

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: Peter Wielander <mittgfu@gmail.com>
2026-06-28 16:05:23 -07:00
Peter Wielander 1dcdafd422 [world-vercel] Unify HTTP request handling into a shared core (#2631) 2026-06-28 14:59:05 -07:00
github-actions[bot] 4f0fb639cb Version Packages (beta) (#2610) workflow@5.0.0-beta.25 2026-06-27 03:21:47 +00:00
Karthik Kalyan 148d4743e5 Use and show event occurredAt (#2613) 2026-06-26 20:00:30 -07:00
Peter Wielander 59776946a0 [world-local] Retry transport-level queue delivery failures (#2679) 2026-06-27 00:47:48 +00:00
Peter Wielander d5803265d4 [ai] Expose totalUsage and finishReason on DurableAgent stream result (#1863) 2026-06-27 00:23:49 +00:00
Peter Wielander 0f76cec493 [ai] Fix WorkflowChatTransport reconnect test stale after framing normalizer (#2681) 2026-06-26 16:49:52 -07:00
Peter Wielander 096faf0ff6 [ai] Reduce doStreamStep step boundary payload (#1932) 2026-06-26 15:20:37 -07:00
Nathan Colosimo b1802700e4 fix: retry inline completion persistence failures (#2666) 2026-06-26 15:00:42 -07:00
Peter Wielander 8cdfd85914 [ai] Fix "missing text part" stream crash by repairing UI message framing (#2537) 2026-06-26 14:44:08 -07:00
Peter Wielander 7f04d87358 [ci] Fix release "Premature close" by bounding changelog GraphQL batch size (#2669) 2026-06-26 14:42:14 -07:00
Peter Wielander eff215ceec [ai] Drop orphan UI chunks after negative-index reconnect (#2082) 2026-06-26 14:22:29 -07:00
Mitul Shah 8393716687 Fix trace detail panel Input/Output flicker (selection-driven state machine) (#2637)
* Add selection-driven span-detail primitives

Extract the run/step/hook/sleep fetch+hydrate core out of useWorkflowResourceData
into a plain async fetchSpanDetailResource (no React state), and add a
selection-driven state machine in web-shared:

- deriveSpanDetailView / resourceNeedsFetchedDetail: pure view-model deriver
  whose status (idle/loading/ready/error) is a function of (selection, fetched
  detail), so it can never lag the selection.
- useSelectedSpanDetail: fetches a selected span's detail directly with a
  request-token to drop stale/out-of-order responses.

* Drive trace detail panel from the span-detail state machine

Replace the cross-package selection round-trip (EntityDetailPanel useEffect ->
onSpanSelect -> page spanSelection state -> useWorkflowResourceData -> context)
with a single injected fetchSpanDetail capability:

- EntityDetailPanel consumes useSelectedSpanDetail; its loading state now stays
  in phase with the selected span, so Input/Output no longer vanish and pop back
  in while navigating.
- SidebarDataContext drops spanDetailData/Loading/Error + onSpanSelect for a
  single fetchSpanDetail; RunDetailView injects it and drops the duplicate
  spanSelection state.
- WorkflowTraceViewer / RunTraceView take fetchSpanDetail too.

* Test span-detail view-model transitions; add changeset

Cover deriveSpanDetailView (idle/loading/ready/error, stale-detail rejection,
hooks ready inline) and resourceNeedsFetchedDetail.

* Trim redundant/narrative comments in span-detail state machine

Comment-only cleanup: drop PR-narration and cross-file duplication from the
deriveSpanDetailView / useSelectedSpanDetail / EntityDetailPanel / fetchSpanDetail
doc comments, keeping the non-obvious intent (request-token, error scoping,
decrypt closure).

* delete pointless coments

---------

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
2026-06-26 16:42:47 -04:00
Peter Wielander d4e6c5ba34 [world-local] Scope untagged startup recovery to untagged runs (#2667) 2026-06-26 20:37:37 +00:00
Nathan Colosimo 5718df8721 fix(world-postgres): defer loopback worker startup (#2657)
* fix(world-postgres): defer loopback worker startup

* add changeset
2026-06-26 12:04:28 -07:00
Pranay Prakash 92cb05505f docs: deprecate DurableAgent and WorkflowChatTransport, point to AI SDK WorkflowAgent (#2616)
- Add deprecation banners (with migration-guide link) to the DurableAgent and
  WorkflowChatTransport API references in v4 and v5; keep the full API surface intact
- Bring v4 headline guides to parity with v5's WorkflowAgent migration (ai/index,
  foundations/streaming, the cookbook recipe + index)
- Convert standard agent examples (defining-tools, message-queueing) to WorkflowAgent
  and reframe the streamText-vs comparison page
- Banner + repoint the deep recipes that stream custom UIMessageChunk data parts
  (chat-session-modeling, human-in-the-loop, agent-cancellation, serializable-steps) —
  that pattern doesn't map to WorkflowAgent's ModelCallStreamPart model, so their
  legacy DurableAgent examples are kept behind a clear deprecation banner
- Point all WorkflowChatTransport examples at the @ai-sdk/workflow 1:1 port
- Rename the cookbook agent-patterns recipe to WorkflowAgent

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-25 21:59:45 -07:00
Peter Wielander 7c1e2a2c7e [web] Fix HTTP/2 in bundled server build so observability reads work (#2632) 2026-06-25 17:42:08 -07:00
Peter Wielander 1ea2b4ef77 [core] Fix turbo-mode step-body writes racing run_started (#2629) 2026-06-25 17:41:45 -07:00
Nathan Colosimo 361ce23b0f fix(world-postgres): rename setup command (#2644) 2026-06-25 23:32:50 +00:00