Skip to content

feat: improve agent content navigation#2102

Merged
yottahmd merged 4 commits intomainfrom
codex/agent-content-navigation
May 6, 2026
Merged

feat: improve agent content navigation#2102
yottahmd merged 4 commits intomainfrom
codex/agent-content-navigation

Conversation

@yottahmd
Copy link
Copy Markdown
Collaborator

@yottahmd yottahmd commented May 6, 2026

Summary

  • Replace the floating agent modal flow with a desktop sidebar mode that can be toggled from navigation and resized.
  • Add a right-content navigation bar with a home shortcut and breadcrumbs for detail pages.
  • Add a /home navigation hub modeled after the Administration page card layout.

Validation

  • pnpm --dir ui test src/layouts/__tests__/Layout.test.tsx src/pages/home/__tests__/index.test.tsx src/__tests__/menu.test.tsx
  • pnpm --dir ui typecheck
  • pnpm --dir ui exec eslint src/App.tsx src/layouts/Layout.tsx src/layouts/ContentNavigation.tsx src/layouts/__tests__/Layout.test.tsx src/pages/home/index.tsx src/pages/home/__tests__/index.test.tsx src/menu.tsx src/features/agent/components/AgentChatPanel.tsx

Summary by CodeRabbit

  • New Features

    • New home dashboard with configurable, permission-aware navigation.
    • Dynamic breadcrumb navigation for clearer context.
    • Resizable agent sidebar, integrated agent panel with a close action, and additional UI entry point to toggle agent mode.
  • Tests

    • Expanded unit and end-to-end tests covering home page, breadcrumbs, agent panel behavior, resizing, and related flows.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 6, 2026

📝 Walkthrough

Walkthrough

Adds a HomePage and route, a ContentNavigation breadcrumb component, integrates a resizable agent chat sidebar into Layout (pointer + keyboard resizing), exposes an optional onClose on AgentChatPanel and an onAgentModeToggle hook in the menu, and updates unit and e2e tests.

Changes

Home, Breadcrumbs, and Layout Integration

Layer / File(s) Summary
Data Shape / Types
ui/src/pages/home/index.tsx
Adds HomeLink and HomeSection types to model dashboard link sections.
Breadcrumbs / Navigation Utility
ui/src/layouts/ContentNavigation.tsx
New ContentNavigation component and getBreadcrumbItems helper mapping pathname segments to breadcrumb items with decoding/prettifying and route-specific logic.
Home Page Component
ui/src/pages/home/index.tsx, ui/src/pages/home/__tests__/index.test.tsx
Adds HomePage (default export) rendering permission- and feature-gated sections (Overview, Workflows, Executions, Monitor, Integrations, Administration); test verifies heading and key links/hrefs.
App Routing
ui/src/App.tsx
Imports HomePage and registers a protected route at /home.
Layout Core Changes
ui/src/layouts/Layout.tsx, ui/src/layouts/__tests__/Layout.test.tsx
Introduces sidebarMode, agentSidebarWidth, isResizingAgentSidebar, isMobileSidebarOpen; adds agent sidebar width helpers, pointer and keyboard resize handlers, clamp/persist logic, conditional rendering of AgentChatPanel, draggable divider, and integrates ContentNavigation; tests updated/mocked to verify breadcrumbs, agent opening, and resizing behaviors.
Agent Panel & Menu Wiring
ui/src/features/agent/components/AgentChatPanel.tsx, ui/src/menu.tsx
AgentChatPanel props gain onClose?: () => void; MainListItems accepts optional onAgentModeToggle?: () => void and uses it (via handleAgentClick) to open agent mode if provided; menu button now uses that handler.
E2E & Test Adjustments
ui/e2e/distributed-stack.spec.ts, ui/src/layouts/__tests__/Layout.test.tsx
E2E: removed getQueue import, replaced text-based DAG checks with heading/link checks, added button assertions, and reordered releaseRuns(); unit tests: added localStorage clearing, updated mocks for agent/menu, and new tests covering breadcrumbs, agent panel flows, and resize persistence.

Sequence Diagram(s)

sequenceDiagram
    participant User as User (browser)
    participant Menu as Menu
    participant Router as Router/App
    participant Layout as Layout
    participant Breadcrumb as ContentNavigation
    participant Agent as AgentChatPanel

    User->>Menu: click "Open Agent"
    Menu->>Layout: call onAgentModeToggle / toggle agent mode
    Layout->>Agent: render AgentChatPanel (passes onClose)
    Agent->>Layout: invoke onClose (optional)
    User->>Layout: drag divider / press Arrow keys to resize
    Layout->>Layout: update & persist agentSidebarWidth (clamp)
    Router->>Breadcrumb: route change (/home)
    Breadcrumb->>Layout: provide breadcrumb items
    Layout->>User: render HomePage and breadcrumbs
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

  • dagucloud/dagu#1996: Touches the same E2E test (ui/e2e/distributed-stack.spec.ts) and thus likely related test edits.
  • dagucloud/dagu#2099: Related to agent panel resizing/dragging behavior and bounds handling.
  • dagucloud/dagu#2012: Overlaps on agent, layout, and routing integration points (AgentChatPanel, Layout, App routing).
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 20.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat: improve agent content navigation' directly reflects the main changes: adding a new ContentNavigation component for breadcrumbs and a /home navigation hub, and integrating the agent into a sidebar with resizing capabilities.
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.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/agent-content-navigation

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 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 `@ui/src/layouts/ContentNavigation.tsx`:
- Around line 121-128: When handling agent routes, don't always push a second
literal 'Agent' for nested paths; instead, keep the Administration and top-level
Agent items then, if normalized !== '/agent', push a label derived from
STATIC_ROUTE_LABELS[normalized] or a fallback that preserves the actual subpage
(e.g., humanize segments[1] or join relevant segments) so routes like
/agent-souls/new and /agent-souls/:soulId render the specific page label; update
the block that uses segments, normalized, STATIC_ROUTE_LABELS and items.push
accordingly.

In `@ui/src/layouts/Layout.tsx`:
- Around line 85-104: The saved agentSidebarWidth must be re-clamped whenever
the viewport changes: call clampAgentSidebarWidth(getSavedWidth()) and update
the agentSidebarWidth state (and persisted desktopSidebarWidth) inside the
resize handler and any place where saved width is loaded (initialization and
effects that read desktopSidebarWidth) so the value never exceeds
getAgentSidebarMaxWidth(); specifically, ensure getAgentSidebarMaxWidth() and
clampAgentSidebarWidth(width) are used to clamp values in the resize event
listener and the code paths that set agentSidebarWidth/desktopSidebarWidth
(initial load and any effect handlers around the divider drag/save logic) so the
width is always reset to Math.min(getAgentSidebarMaxWidth(),
Math.max(AGENT_SIDEBAR_MIN_WIDTH, Math.round(width))).
🪄 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: 99abe7c5-ee02-46ae-a052-55a332751aeb

📥 Commits

Reviewing files that changed from the base of the PR and between 928231d and 4e1ba93.

📒 Files selected for processing (8)
  • ui/src/App.tsx
  • ui/src/features/agent/components/AgentChatPanel.tsx
  • ui/src/layouts/ContentNavigation.tsx
  • ui/src/layouts/Layout.tsx
  • ui/src/layouts/__tests__/Layout.test.tsx
  • ui/src/menu.tsx
  • ui/src/pages/home/__tests__/index.test.tsx
  • ui/src/pages/home/index.tsx

Comment thread ui/src/layouts/ContentNavigation.tsx
Comment thread ui/src/layouts/Layout.tsx
Copy link
Copy Markdown
Collaborator Author

yottahmd commented May 6, 2026

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 6, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
ui/src/layouts/Layout.tsx (1)

1-10: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Add the repository license header to this file.

ui/src/layouts/Layout.tsx is part of the changed surface, but it still lacks the required GPL header used elsewhere in the UI sources.

📄 Minimal fix
+// Copyright (C) 2026 Yota Hamada
+// SPDX-License-Identifier: GPL-3.0-or-later
+
 import { LicenseBanner } from '@/components/LicenseBanner';
 import { UpdateBanner } from '@/components/UpdateBanner';

As per coding guidelines, **/*.{go,ts,tsx,js}: Apply GPL v3 license headers on source files, managed via make addlicense.

🤖 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 `@ui/src/layouts/Layout.tsx` around lines 1 - 10, This file is missing the
project's GPL v3 license header; add the same GPL v3 header block used across
other UI sources to the top of the Layout component file (the file that defines
the Layout component and imports LicenseBanner, UpdateBanner, useConfig, etc.).
Ensure the header exactly matches the format used by the repo (so automated
tooling recognizes it) or run the repository helper (make addlicense) to apply
it consistently.
🤖 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 `@ui/src/layouts/Layout.tsx`:
- Around line 396-400: The main area currently stacks
ContentNavigation/UpdateBanner/LicenseBanner before a body div with h-full which
causes the scroller to include the header; change the <main> (Layout component)
to be a column flex container (e.g., add flex flex-col min-h-0 overflow-hidden)
and move scrolling responsibility to the body wrapper by making the body div the
flex-1 overflow-auto container (remove h-full on the body). Specifically update
the element that renders ContentNavigation, UpdateBanner, LicenseBanner and the
children so ContentNavigation/UpdateBanner/LicenseBanner are static siblings
above the scrolling region and the children container (the div wrapping
{children}) is the only element with flex-1 and overflow-auto and min-h-0.

---

Outside diff comments:
In `@ui/src/layouts/Layout.tsx`:
- Around line 1-10: This file is missing the project's GPL v3 license header;
add the same GPL v3 header block used across other UI sources to the top of the
Layout component file (the file that defines the Layout component and imports
LicenseBanner, UpdateBanner, useConfig, etc.). Ensure the header exactly matches
the format used by the repo (so automated tooling recognizes it) or run the
repository helper (make addlicense) to apply it consistently.
🪄 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: d4543277-2538-42ad-9356-9c421f2d64be

📥 Commits

Reviewing files that changed from the base of the PR and between 4e1ba93 and 0596097.

📒 Files selected for processing (4)
  • ui/e2e/distributed-stack.spec.ts
  • ui/src/layouts/ContentNavigation.tsx
  • ui/src/layouts/Layout.tsx
  • ui/src/layouts/__tests__/Layout.test.tsx

Comment thread ui/src/layouts/Layout.tsx Outdated
@yottahmd
Copy link
Copy Markdown
Collaborator Author

yottahmd commented May 6, 2026

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 6, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
ui/src/layouts/Layout.tsx (1)

185-194: 💤 Low value

Consider persisting agentSidebarWidth only at drag end.

This effect runs synchronously on every state update, including each pointermove tick during a drag (see the handler at Line 207-209). Each tick triggers a synchronous localStorage.setItem, which can be tens of writes per second while resizing. Persisting on pointerup (or via a small debounce on isResizingAgentSidebar transitioning to false) achieves the same persistence without serializing to disk on every frame.

♻️ Possible refactor
   React.useEffect(() => {
+    if (isResizingAgentSidebar) {
+      return;
+    }
     try {
       localStorage.setItem(
         AGENT_SIDEBAR_WIDTH_STORAGE_KEY,
         agentSidebarWidth.toString()
       );
     } catch {
       // Ignore unavailable storage.
     }
-  }, [agentSidebarWidth]);
+  }, [agentSidebarWidth, isResizingAgentSidebar]);
🤖 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 `@ui/src/layouts/Layout.tsx` around lines 185 - 194, The current
React.useEffect writes AGENT_SIDEBAR_WIDTH_STORAGE_KEY to localStorage on every
agentSidebarWidth change (including each pointermove during a drag); change this
to persist only when the drag finishes: move the localStorage.setItem call out
of the synchronous effect and run it in the resize end handler (e.g., the
pointerup / onPointerUp that toggles isResizingAgentSidebar) or trigger it when
isResizingAgentSidebar transitions from true to false (or use a short debounce
on that transition) so you stop doing tens of setItem writes per second;
reference agentSidebarWidth, AGENT_SIDEBAR_WIDTH_STORAGE_KEY and the
isResizingAgentSidebar/pointerup handler to locate where to place the write.
🤖 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.

Nitpick comments:
In `@ui/src/layouts/Layout.tsx`:
- Around line 185-194: The current React.useEffect writes
AGENT_SIDEBAR_WIDTH_STORAGE_KEY to localStorage on every agentSidebarWidth
change (including each pointermove during a drag); change this to persist only
when the drag finishes: move the localStorage.setItem call out of the
synchronous effect and run it in the resize end handler (e.g., the pointerup /
onPointerUp that toggles isResizingAgentSidebar) or trigger it when
isResizingAgentSidebar transitions from true to false (or use a short debounce
on that transition) so you stop doing tens of setItem writes per second;
reference agentSidebarWidth, AGENT_SIDEBAR_WIDTH_STORAGE_KEY and the
isResizingAgentSidebar/pointerup handler to locate where to place the write.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 38a8d691-6837-4ced-8d07-de44991a110f

📥 Commits

Reviewing files that changed from the base of the PR and between 0596097 and 1800647.

📒 Files selected for processing (1)
  • ui/src/layouts/Layout.tsx

@yottahmd yottahmd merged commit 6e1efea into main May 6, 2026
11 checks passed
@yottahmd yottahmd deleted the codex/agent-content-navigation branch May 6, 2026 10:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant