Skip to content

feat(flows): Workflows B5a — list page + nav tab (/flows)#4471

Merged
graycyrus merged 2 commits into
tinyhumansai:mainfrom
graycyrus:feat/flows-b5a-page-tab
Jul 3, 2026
Merged

feat(flows): Workflows B5a — list page + nav tab (/flows)#4471
graycyrus merged 2 commits into
tinyhumansai:mainfrom
graycyrus:feat/flows-b5a-page-tab

Conversation

@graycyrus

@graycyrus graycyrus commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

Summary

The Workflows hub: a top-level /flows page listing saved workflows (name, enabled toggle, last run + status, Run button), reachable from a new nav tab. Makes the feature discoverable and gives runs/inspector a home. Uses existing RPCs — no backend change.

Changes

  • New pages/FlowsPage.tsx (+test) — PanelPage shell; listFlows on mount; loading/error/empty states (empty has no CTA until the B5b canvas). Toggle → setFlowEnabled (optimistic); Run → fire-and-forget runFlow + "Workflow started" toast + refetch (only on success, so a run error keeps its banner).
  • New components/flows/FlowListRow.tsx (+test) — CoreJobList-style row: name, Enabled/Paused badge, last-run line, SettingsSwitch toggle, Run + View-runs.
  • flowsApi.ts — appended listFlows / setFlowEnabled / runFlow (+ Flow type). B3b (feat(flows): Workflows B3b — Run Inspector drawer #4450) doesn't touch this file → no conflict.
  • Nav wired in lockstep (the CI-gated part): navConfig (Workflows tab, 4th), navIcons, SidebarNav + CollapsedNavRail matchActive, AppRoutes (/flows/*), the E2E navigation.spec ROUTES table, and the nav-config/shell unit tests. The /workflows/* Skill routes are untouched.
  • i18nflows.* + nav.flows across all 14 locales (distinct namespace from B3b/B4).

Route decision

New page uses /flows (matches the flows:: domain), leaving the Skills /workflows/new|run + /workflows/settings/automations routes untouched.

Sequencing

The run inspector (B3b, #4450) is a clearly-marked stub here — wired after #4450 merges + rebase (inspector is keyed by run id). No flows_list_all_runs RPC needed for this page (flows_list returns last-run status per flow).

Verification

pnpm typecheck + lint + prettier clean · 69 Vitest tests pass · pnpm i18n:check parity clean.

Summary by CodeRabbit

  • New Features

    • Added a new Workflows (“Flows”) navigation tab with a protected /flows route.
    • Introduced the Workflows list page with per-flow enable/disable, run-now, view-runs actions, and loading/empty/error states (including “never run” handling).
    • Updated navigation active highlighting for nested /flows/ routes and added a dedicated flows icon.
    • Added localized UI text for the Workflows experience across multiple languages.
  • Tests

    • Expanded unit/integration/e2e coverage for navigation active state, routing, API behavior, page states, and flow row interactions (run and toggle).

@graycyrus graycyrus requested a review from a team July 3, 2026 19:52
@coderabbitai

coderabbitai Bot commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

You’ve reached a temporary PR review limit under our Fair Usage Limits Policy.

Your recent review volume is higher than typical usage, so adaptive limits are currently applied.

Next review available in: 2 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 0f414acc-bc50-4909-b083-dbb4fb505a69

📥 Commits

Reviewing files that changed from the base of the PR and between 921216e and 8d7fcfd.

📒 Files selected for processing (29)
  • app/src/AppRoutes.tsx
  • app/src/components/flows/FlowListRow.test.tsx
  • app/src/components/flows/FlowListRow.tsx
  • app/src/components/layout/shell/CollapsedNavRail.test.tsx
  • app/src/components/layout/shell/CollapsedNavRail.tsx
  • app/src/components/layout/shell/SidebarNav.test.tsx
  • app/src/components/layout/shell/SidebarNav.tsx
  • app/src/components/layout/shell/navIcons.tsx
  • app/src/config/__tests__/navConfig.test.ts
  • app/src/config/navConfig.ts
  • app/src/lib/i18n/ar.ts
  • app/src/lib/i18n/bn.ts
  • app/src/lib/i18n/de.ts
  • app/src/lib/i18n/en.ts
  • app/src/lib/i18n/es.ts
  • app/src/lib/i18n/fr.ts
  • app/src/lib/i18n/hi.ts
  • app/src/lib/i18n/id.ts
  • app/src/lib/i18n/it.ts
  • app/src/lib/i18n/ko.ts
  • app/src/lib/i18n/pl.ts
  • app/src/lib/i18n/pt.ts
  • app/src/lib/i18n/ru.ts
  • app/src/lib/i18n/zh-CN.ts
  • app/src/pages/FlowsPage.test.tsx
  • app/src/pages/FlowsPage.tsx
  • app/src/services/api/flowsApi.test.ts
  • app/src/services/api/flowsApi.ts
  • app/test/e2e/specs/navigation.spec.ts
📝 Walkthrough

Walkthrough

Adds a new protected /flows Workflows page with API-backed list, run, and enable actions, plus a new list-row component. It also wires the Workflows tab into navigation, active-state matching, translations, and tests.

Changes

Workflows feature

Layer / File(s) Summary
Flows API client and types
app/src/services/api/flowsApi.ts, app/src/services/api/flowsApi.test.ts
Adds the Flow type and listFlows, setFlowEnabled, and runFlow RPC helpers, with tests for request shapes, response unwrapping, and error propagation.
FlowListRow component
app/src/components/flows/FlowListRow.tsx, app/src/components/flows/FlowListRow.test.tsx
Adds the row component for flow name, status, relative last-run text, toggle/run/view-runs actions, and busy-state handling, with unit coverage.
FlowsPage and route
app/src/pages/FlowsPage.tsx, app/src/pages/FlowsPage.test.tsx, app/src/AppRoutes.tsx, app/test/e2e/specs/navigation.spec.ts
Adds the page state and action handlers, protected /flows/* routing, and page/navigation tests covering loading, empty, error, toggle, run, and refetch behavior.
Workflows nav tab
app/src/config/navConfig.ts, app/src/config/__tests__/navConfig.test.ts, app/src/components/layout/shell/navIcons.tsx, app/src/components/layout/shell/SidebarNav.tsx, app/src/components/layout/shell/SidebarNav.test.tsx, app/src/components/layout/shell/CollapsedNavRail.tsx, app/src/components/layout/shell/CollapsedNavRail.test.tsx
Adds the flows nav tab, its icon, and active-route matching for /flows and nested sub-routes, with config and UI tests.
Flows translations
app/src/lib/i18n/*.ts
Adds nav.flows and flows.* translation strings across the supported locales.

Estimated code review effort: 3 (Moderate) | ~30 minutes

Possibly related PRs

  • tinyhumansai/openhuman#4433: Adds the backend openhuman.flows_list, openhuman.flows_set_enabled, and openhuman.flows_run paths consumed by this frontend work.

Suggested labels: feature

Suggested reviewers: M3gA-Mind, sanil-23

Poem

Hops through routes, the bunny grins,
New Workflows paths and flows begin. 🐇
Toggle, run, and view runs too,
Translations bloom in every hue.
A soft carrot cheer in code-review light,
This little flow now feels just right.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly matches the main change: adding a Workflows list page and a new /flows navigation tab.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot added the feature Net-new user-facing capability or product behavior. label Jul 3, 2026

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 9166e31abe

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +101 to +103
data-testid={`flow-view-runs-${flow.id}`}
onClick={() => onViewRuns(flow)}>
{t('flows.list.viewRuns')}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Wire or hide the View runs action

Until the B3b inspector exists, every saved flow shows an enabled “View runs” button, but the callback only stores selectedFlowId and logs it (a repo-wide search for FlowRunInspector/selectedFlowId shows no rendered consumer). Users who click this on /flows get no drawer, navigation, or run list, so this is a dead action; hide/disable it or wire it to listFlowRuns before exposing it.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed in e55de28 — removed the "View runs" button + its onViewRuns wiring entirely (it was a dead action with no consumer until B3b). The B3b integration note is preserved; the wired button comes back in the post-#4450 rebase.

Comment on lines +37 to +38
if (mins < 1) return 'just now';
if (mins < 60) return `${mins}m ago`;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Localize the last-run relative time text

When a user is in any non-English locale and a flow has last_run_at, these branches render English strings like just now and 5m ago directly instead of using useT() or locale-aware formatting. The rest of the new Workflows page has translations, but this run metadata remains untranslated; please route it through i18n or Intl.RelativeTimeFormat.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed in e55de28relativeTime() now routes through useT() with new flows.list.{justNow,minutesAgo,hoursAgo,daysAgo} keys (real translations in all 14 locales, {count} via .replace).

@coderabbitai coderabbitai 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.

Actionable comments posted: 1

🧹 Nitpick comments (3)
app/src/pages/FlowsPage.tsx (2)

82-84: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Toggle/run failures show raw, untranslated backend error text.

loadFlows uses a translated generic message (t('flows.page.loadError')), but handleToggle/handleRun surface the raw exception message via errorMessage(err) directly in the UI (ErrorBanner). This is inconsistent and bypasses i18n for these paths — non-English users will see raw English/backend error strings.

Consider using a translated generic fallback (e.g., t('flows.list.toggleError') / t('flows.list.runError')) instead of the raw message, or at least translate a wrapper string around it.

As per coding guidelines, "All user-facing UI text in the React app must go through useT()".

Also applies to: 109-111

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@app/src/pages/FlowsPage.tsx` around lines 82 - 84, The toggle/run error
handling in FlowsPage is surfacing raw backend text via errorMessage(err)
instead of translated UI copy, which breaks the i18n rule used by loadFlows.
Update handleToggle and handleRun to use useT()-backed translated fallback
messages (for example flows.list.toggleError and flows.list.runError), and only
include raw error details if they are wrapped inside a translated user-facing
string before passing to ErrorBanner.

Source: Coding guidelines


43-43: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Stub wiring for selectedFlowId — acceptable but slightly convoluted.

The extra useEffect exists solely to keep selectedFlowId from being flagged as unused by noUnusedLocals until the B3b inspector lands. This works but adds an effect + dependency array purely as a lint workaround. A void selectedFlowId; comment or a narrower // eslint-disable-next-line at declaration would achieve the same without a full effect.

Given this is explicitly a temporary stub per the PR notes, low priority.

Also applies to: 119-132, 191-201

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@app/src/pages/FlowsPage.tsx` at line 43, The `selectedFlowId` stub in
`FlowsPage` is being kept alive with an extra `useEffect` only to satisfy
`noUnusedLocals`, which is unnecessarily convoluted. Remove the effect-based
workaround around `selectedFlowId` and use a lighter temporary suppression at
the declaration site instead, such as a `void selectedFlowId;` or a narrowly
scoped eslint disable. Apply the same cleanup to the related stub wiring noted
elsewhere in `FlowsPage` so the temporary B3b placeholder stays simple.
app/src/components/layout/shell/SidebarNav.tsx (1)

26-34: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Duplicate matchActive logic across nav components.

This matchActive helper is duplicated verbatim in CollapsedNavRail.tsx (lines 15-21). Both had to be edited identically to add the /flows rule, and CollapsedNavRail.tsx's copy is already missing the /agent-world case present here — a sign the two can silently drift. Consider extracting a shared matchActive (and NavTab type) into a common module (e.g. navConfig.ts or a new navMatch.ts) imported by both components.

♻️ Suggested extraction
// app/src/config/navMatch.ts
export function matchActive(path: string, pathname: string): boolean {
  if (path === '/chat') return pathname.startsWith('/chat');
  if (path === '/settings') return pathname === '/settings' || pathname.startsWith('/settings/');
  if (path === '/agent-world')
    return pathname === '/agent-world' || pathname.startsWith('/agent-world/');
  if (path === '/flows') return pathname === '/flows' || pathname.startsWith('/flows/');
  if (path === '/home') return pathname === '/home';
  return pathname === path;
}

Then import this in both SidebarNav.tsx and CollapsedNavRail.tsx instead of maintaining two copies.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@app/src/components/layout/shell/SidebarNav.tsx` around lines 26 - 34, The
`matchActive` helper in `SidebarNav.tsx` is duplicated in
`CollapsedNavRail.tsx`, and the copies are already drifting (e.g. `/agent-world`
and `/flows` handling). Extract the shared route-matching logic into a common
module such as `navMatch.ts` or `navConfig.ts`, and have both `SidebarNav` and
`CollapsedNavRail` import the same `matchActive` implementation. If `NavTab` is
also shared between these components, move that type alongside the helper so
navigation behavior stays consistent in one place.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@app/src/components/flows/FlowListRow.tsx`:
- Around line 34-43: The user-facing strings in `relativeTime()` are hardcoded
in English and bypass the app’s i18n flow. Update `FlowListRow` to source these
labels through `useT()`/`t()` instead of raw literals, and add the needed keys
for “just now” and the relative-time formats to `en.ts` plus every locale file.
Follow the existing interpolation pattern in this codebase (for example,
translating a template then replacing placeholders) so the `relativeTime()`
helper can render localized minutes, hours, and days consistently.

---

Nitpick comments:
In `@app/src/components/layout/shell/SidebarNav.tsx`:
- Around line 26-34: The `matchActive` helper in `SidebarNav.tsx` is duplicated
in `CollapsedNavRail.tsx`, and the copies are already drifting (e.g.
`/agent-world` and `/flows` handling). Extract the shared route-matching logic
into a common module such as `navMatch.ts` or `navConfig.ts`, and have both
`SidebarNav` and `CollapsedNavRail` import the same `matchActive`
implementation. If `NavTab` is also shared between these components, move that
type alongside the helper so navigation behavior stays consistent in one place.

In `@app/src/pages/FlowsPage.tsx`:
- Around line 82-84: The toggle/run error handling in FlowsPage is surfacing raw
backend text via errorMessage(err) instead of translated UI copy, which breaks
the i18n rule used by loadFlows. Update handleToggle and handleRun to use
useT()-backed translated fallback messages (for example flows.list.toggleError
and flows.list.runError), and only include raw error details if they are wrapped
inside a translated user-facing string before passing to ErrorBanner.
- Line 43: The `selectedFlowId` stub in `FlowsPage` is being kept alive with an
extra `useEffect` only to satisfy `noUnusedLocals`, which is unnecessarily
convoluted. Remove the effect-based workaround around `selectedFlowId` and use a
lighter temporary suppression at the declaration site instead, such as a `void
selectedFlowId;` or a narrowly scoped eslint disable. Apply the same cleanup to
the related stub wiring noted elsewhere in `FlowsPage` so the temporary B3b
placeholder stays simple.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 610c8c35-5d6c-4807-9613-8d6d09f01543

📥 Commits

Reviewing files that changed from the base of the PR and between 9a5176a and 9166e31.

📒 Files selected for processing (29)
  • app/src/AppRoutes.tsx
  • app/src/components/flows/FlowListRow.test.tsx
  • app/src/components/flows/FlowListRow.tsx
  • app/src/components/layout/shell/CollapsedNavRail.test.tsx
  • app/src/components/layout/shell/CollapsedNavRail.tsx
  • app/src/components/layout/shell/SidebarNav.test.tsx
  • app/src/components/layout/shell/SidebarNav.tsx
  • app/src/components/layout/shell/navIcons.tsx
  • app/src/config/__tests__/navConfig.test.ts
  • app/src/config/navConfig.ts
  • app/src/lib/i18n/ar.ts
  • app/src/lib/i18n/bn.ts
  • app/src/lib/i18n/de.ts
  • app/src/lib/i18n/en.ts
  • app/src/lib/i18n/es.ts
  • app/src/lib/i18n/fr.ts
  • app/src/lib/i18n/hi.ts
  • app/src/lib/i18n/id.ts
  • app/src/lib/i18n/it.ts
  • app/src/lib/i18n/ko.ts
  • app/src/lib/i18n/pl.ts
  • app/src/lib/i18n/pt.ts
  • app/src/lib/i18n/ru.ts
  • app/src/lib/i18n/zh-CN.ts
  • app/src/pages/FlowsPage.test.tsx
  • app/src/pages/FlowsPage.tsx
  • app/src/services/api/flowsApi.test.ts
  • app/src/services/api/flowsApi.ts
  • app/test/e2e/specs/navigation.spec.ts

Comment thread app/src/components/flows/FlowListRow.tsx Outdated
coderabbitai[bot]
coderabbitai Bot previously approved these changes Jul 3, 2026
graycyrus added 2 commits July 4, 2026 01:48
The discoverable hub: a top-level /flows page listing saved workflows (name,
enabled toggle, last run + status, Run button) reachable from a new nav tab.
Uses existing RPCs only — no backend change.

- pages/FlowsPage.tsx (+test): PanelPage shell; listFlows on mount; loading/
  error/empty states (empty has no CTA until the B5b canvas); toggle →
  setFlowEnabled (optimistic), Run → fire-and-forget runFlow + toast + refetch
  (refetch only on success so a run error keeps its banner).
- components/flows/FlowListRow.tsx (+test): CoreJobList-style row — name,
  Enabled/Paused badge, last-run line, SettingsSwitch toggle, Run + View-runs.
- flowsApi.ts: appended listFlows / setFlowEnabled / runFlow (+ Flow type);
  B3b (tinyhumansai#4450) doesn't touch this file, so no conflict.
- Nav wired in lockstep: navConfig (flows tab, 4th), navIcons, SidebarNav +
  CollapsedNavRail matchActive, AppRoutes (/flows/*), and the E2E
  navigation.spec ROUTES + nav-config/shell tests (the CI-gated bits). The
  /workflows/* Skill routes are untouched.
- The run inspector (B3b) is a clearly-marked stub, wired after tinyhumansai#4450 merges.
- i18n: flows.* + nav.flows across all 14 locales (distinct namespace).

typecheck/lint/prettier clean; 69 Vitest tests pass; i18n parity clean.
…button

- FlowListRow relativeTime() now routes through useT() with flows.list.{justNow,
  minutesAgo,hoursAgo,daysAgo} (real translations x14, {count} interpolation via
  .replace) instead of hardcoded English. [Codex + CodeRabbit]
- Removed the 'View runs' button + onViewRuns wiring — it was a dead action with
  no consumer until B3b's inspector; the B3b integration note is preserved for
  the post-tinyhumansai#4450 rebase. [Codex]
- prettier: FlowApprovalCard.test.tsx (pre-existing dirty on main).

typecheck/lint/prettier(repo-wide) clean; 46+8 tests pass; i18n parity clean.
@graycyrus graycyrus force-pushed the feat/flows-b5a-page-tab branch from e55de28 to 8d7fcfd Compare July 3, 2026 20:20
@graycyrus graycyrus merged commit a5b6a13 into tinyhumansai:main Jul 3, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feature Net-new user-facing capability or product behavior.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant