Skip to content

[workflows-shared] Add full step output retrieval to Workflows local explorer - #14822

Open
pombosilva wants to merge 1 commit into
mainfrom
workflows-local-explorer-step-output
Open

[workflows-shared] Add full step output retrieval to Workflows local explorer#14822
pombosilva wants to merge 1 commit into
mainfrom
workflows-local-explorer-step-output

Conversation

@pombosilva

@pombosilva pombosilva commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

Fixes WOR-1510.

Adds a GET /workflows/{workflow_name}/instances/{instance_id}/step that returns a step's complete, untruncated output, serving ReadableStream outputs as raw application/octet-stream bytes, which the explorer UI fetches on demand when a step's inline preview was truncated.


  • Tests
    • Tests included/updated
    • Automated tests not possible - manual testing has been completed as follows:
    • Additional testing not necessary because:
  • Public documentation
    • Cloudflare docs PR(s):
    • Documentation not necessary because: just adds a missing feature to local explorer

A picture of a cute animal (not mandatory, but encouraged)

@changeset-bot

changeset-bot Bot commented Jul 23, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: bef29ae

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 8 packages
Name Type
miniflare Minor
@cloudflare/deploy-helpers Patch
@cloudflare/pages-shared Patch
@cloudflare/remote-bindings Patch
@cloudflare/runtime-types Patch
@cloudflare/vite-plugin Patch
@cloudflare/vitest-pool-workers Patch
wrangler Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@pombosilva
pombosilva force-pushed the workflows-local-explorer-step-output branch from 943ca72 to bef29ae Compare July 24, 2026 07:54
@github-project-automation github-project-automation Bot moved this to Untriaged in workers-sdk Jul 24, 2026
@github-actions

Copy link
Copy Markdown
Contributor

✅ All changesets look good

@pkg-pr-new

pkg-pr-new Bot commented Jul 24, 2026

Copy link
Copy Markdown
@cloudflare/autoconfig

npm i https://pkg.pr.new/@cloudflare/autoconfig@14822

@cloudflare/config

npm i https://pkg.pr.new/@cloudflare/config@14822

create-cloudflare

npm i https://pkg.pr.new/create-cloudflare@14822

@cloudflare/deploy-helpers

npm i https://pkg.pr.new/@cloudflare/deploy-helpers@14822

@cloudflare/kv-asset-handler

npm i https://pkg.pr.new/@cloudflare/kv-asset-handler@14822

miniflare

npm i https://pkg.pr.new/miniflare@14822

@cloudflare/pages-shared

npm i https://pkg.pr.new/@cloudflare/pages-shared@14822

@cloudflare/unenv-preset

npm i https://pkg.pr.new/@cloudflare/unenv-preset@14822

@cloudflare/vite-plugin

npm i https://pkg.pr.new/@cloudflare/vite-plugin@14822

@cloudflare/vitest-pool-workers

npm i https://pkg.pr.new/@cloudflare/vitest-pool-workers@14822

@cloudflare/workers-auth

npm i https://pkg.pr.new/@cloudflare/workers-auth@14822

@cloudflare/workers-editor-shared

npm i https://pkg.pr.new/@cloudflare/workers-editor-shared@14822

@cloudflare/workers-utils

npm i https://pkg.pr.new/@cloudflare/workers-utils@14822

wrangler

npm i https://pkg.pr.new/wrangler@14822

commit: bef29ae

@pombosilva
pombosilva marked this pull request as ready for review July 24, 2026 08:36
@workers-devprod
workers-devprod requested review from a team and dario-piotrowicz and removed request for a team July 24, 2026 08:36
@workers-devprod

workers-devprod commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

Codeowners approval required for this PR:

  • @cloudflare/workflows
  • ✅ @cloudflare/wrangler
Show detailed file reviewers
  • packages/workflows-shared/src/engine.ts: [@cloudflare/workflows]
  • packages/workflows-shared/tests/engine.test.ts: [@cloudflare/workflows]
  • packages/workflows-shared/tests/utils.ts: [@cloudflare/workflows]

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Devin Review: No Issues Found

Devin Review analyzed this PR and found no bugs or issues to report.

Open in Devin Review

@pombosilva

Copy link
Copy Markdown
Contributor Author

/bonk

@ask-bonk

ask-bonk Bot commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

/bonk review — PR #14822

Reviewed the full stack of this change (engine → miniflare resource → OpenAPI/generated client → explorer UI). Summary: the implementation is correct, well-layered, and matches the local-explorer conventions. I verified locally and found no changes required.

What I checked

  • Engine (getStepOutput)packages/workflows-shared/src/engine.ts:570

    • Correctly resolves the step's groupKey from STEP_START/WAIT_START, then reconstructs status from the group's events.
    • Streamed outputs are replayed via replayStreamFromMeta() (integrity-checked, only when Complete) and returned as a ReadableStream; non-stream outputs fall back to metadata.result.
    • attempt handling is sound: ATTEMPT_FAILURE → errored with that attempt's error; in-flight (ATTEMPT_START only) → running; successful attempt correctly falls through to the shared stored value.
    • waitForEvent maps WAIT_COMPLETE → payload, WAIT_TIMED_OUT → errored, else waiting.
  • Miniflare resourcepackages/miniflare/src/workers/local-explorer/resources/workflows.ts:797

    • ReadableStream outputs are streamed back as application/octet-stream; JSON otherwise via wrapResponse().
    • Error mapping (step_not_found → 404, not_found/"Engine was never started" → 404, else 500) is consistent with the existing instance-details handler.
    • The attempt + waitForEvent combination is rejected with a 400 before hitting the DO.
    • Cross-instance forwarding via findWorkflowOwner() + fetchFromPeer() preserves the raw (including octet-stream) body.
    • Nice cleanup extracting resolveEngineStub() and deduplicating the hex-vs-name DO id logic.
  • OpenAPI + generated client — spec added in openapi-filter-config.ts; types.gen.ts/zod.gen.ts/index.ts are consistent with it. validateQuery() coerces the string attempt param to a number, so the z.number() schema validates correctly.

  • UIStepRow.tsx lazily fetches the full output only when the inline preview is a truncated stream preview (isTruncatedStreamPreview), decodes UTF-8 with a base64 fallback for binary, and cancels via an active flag on unmount. CopyButton disabled state and loading UI look right.

Verification run locally

  • pnpm -F @cloudflare/workflows-shared test:ci → 154 passed (incl. the 5 new getStepOutput cases). The boom/step-boom uncaught-exception log lines are expected from the failure-path tests.
  • pnpm -F @cloudflare/workflows-shared check:type → clean.

Minor, non-blocking notes (no action needed):

  1. The OpenAPI attempt param declares exclusiveMinimum: 0, but generated zod is z.number().int() (codegen drops the bound). The handler doesn't rely on it, so it's cosmetic.
  2. No miniflare-layer .spec.ts covers getWorkflowStepOutput (octet-stream response, 400 for attempt+waitForEvent, peer forwarding). The engine layer is well covered; a resource-level spec would be a nice future addition but isn't required given there's no existing workflows spec file.

LGTM. 🔨

@ask-bonk

ask-bonk Bot commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

Posted my review on PR #14822.

Summary

@pombosilva invoked /bonk — a request to thoroughly review the PR. I reviewed the full stack of PR #14822 ("Add full step output retrieval to Workflows local explorer") across all layers and verified it locally.

Findings: the implementation is correct and no code changes were needed.

What I verified:

  • Engine (getStepOutput in engine.ts:570): correct group-key resolution, stream replay with integrity checks, sound attempt/waitForEvent/failure status mapping.
  • Miniflare resource (workflows.ts:797): octet-stream vs JSON responses, consistent error→HTTP mapping, the 400 guard for attempt+waitForEvent, and cross-instance peer forwarding that preserves raw bodies. Also a clean resolveEngineStub() refactor.
  • OpenAPI + generated client: spec and generated types.gen.ts/zod.gen.ts/index.ts are consistent; validateQuery coerces the string attempt param.
  • UI (StepRow.tsx): lazy full-output fetch only on truncated previews, UTF-8 decode with base64 fallback, proper unmount cancellation.

Verification:

  • pnpm -F @cloudflare/workflows-shared test:ci154 passed (incl. 5 new getStepOutput tests)
  • pnpm -F @cloudflare/workflows-shared check:type → clean

I noted two minor non-blocking observations (a cosmetic codegen gap on the attempt bound, and the absence of a miniflare-layer spec for the resource handler) but neither warrants changes. LGTM.

github run

return () => {
active = false;
};
}, [needsFetch, workflowName, instanceId, step.name]);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i think restart from step can display stale output? it omits step output/version

}
let active = true;
setState({ status: "loading" });
void workflowsGetStepOutput({

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do you think 1gb of download all at once would crash the tab?

@dario-piotrowicz dario-piotrowicz left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM with a couple of minor suggestions 🙂

return (
typeof value === "string" &&
(value.endsWith(STREAM_PREVIEW_TRUNCATED_MARKER) ||
value.startsWith("[ReadableStream"))

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: I think a regex would be more correct here?

Suggested change
value.startsWith("[ReadableStream"))
/^\[ReadableStream:\s\d+\s\w+]$/.test(value)

(Then we can also have some other tests that make sure that incorrect string starting with [ReadableStream are not accepted)

Comment thread packages/workflows-shared/src/engine.ts
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Untriaged

Development

Successfully merging this pull request may close these issues.

4 participants