fix(runs): accept any JSON in step/run output + paginate dashboard list#41
Merged
Conversation
- StepResponse/RunResponse JSON-blob fields broadened from dict[str, Any]
to Any, so list/scalar step outputs no longer 500 GET /runs/{id}
- Dashboard runs list now uses server pagination (page_size=50) with
prev/next controls and total count
There was a problem hiding this comment.
Pull request overview
This PR fixes a server-side schema mismatch that caused GET /api/v1/runs/{id} to fail when JSONB-backed fields contained non-object JSON (e.g., lists/scalars), and updates the dashboard runs list to use server pagination.
Changes:
- Server: widen Run/Step response “JSON blob” fields to accept non-dict JSON values.
- Tests: add a regression suite to ensure RunResponse/StepResponse accept lists/scalars and round-trip through
model_dump()/model_validate(). - Dashboard: paginate the runs list with
page_size=50, total count display, and prev/next controls.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 5 comments.
| File | Description |
|---|---|
server/src/flowforge_server/api/schemas/runs.py |
Updates Run/Step response schemas to allow non-dict JSON values for JSONB-backed fields. |
tests/unit/test_runs_schema.py |
Adds regression tests covering list/scalar JSON values and nested round-trips. |
dashboard/src/app/(dashboard)/runs/page.tsx |
Switches runs list to server-driven pagination and updates the header + adds pager UI. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
|
||
| useEffect(() => { | ||
| let cancelled = false; | ||
| const fetch = async () => { |
Comment on lines
8
to
10
| import { api, type Run } from '@/lib/api'; | ||
| import { VarStrip } from '@/components/ui/var-strip'; | ||
|
|
Comment on lines
+16
to
+18
| input: Any | None = Field(None, description="Step input") | ||
| output: Any | None = Field(None, description="Step output") | ||
| error: Any | None = Field(None, description="Error details") |
| status: str = Field(..., description="Current status") | ||
| trigger_type: str = Field(..., description="How the run was triggered") | ||
| trigger_data: dict[str, Any] = Field(..., description="Trigger data") | ||
| trigger_data: Any = Field(..., description="Trigger data") |
Comment on lines
+39
to
+41
|
|
||
|
|
||
| def _run_kwargs(**overrides): |
…tests Addresses Copilot review: - runs list now flips to loading state on filter/page change so the pager buttons disable and the spinner row renders during in-flight refetches; background polling stays silent - regression tests now exercise RunResponse(trigger_data=...) with list/string/int values
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
StepResponseandRunResponseJSON-blob fields (input,output,error,tool_input,tool_output,agent_state,trigger_data) typed asAnyinstead ofdict[str, Any]. The runner persists any JSON value to JSONB columns; the previous typing madeGET /api/v1/runs/{id}500 whenever a step output was a list/scalar, taking down the entire run-detail endpoint.tests/unit/test_runs_schema.pycovering lists, scalars, and nested round-trip.page_size=50) with prev/next controls, total count in the header, and resets to page 1 on filter change.Test plan
ruff check server/src/flowforge_server/api/schemas/runs.pypytest tests/unit/test_runs_schema.py -v— 15 passedGET /api/v1/runs/{id}against a run with a list step output — expect 200 with the list preserved