Skip to content

feat: separate Agent into independent module with dedicated page and route#13420

Open
EurFelux wants to merge 26 commits intomainfrom
feat/13329
Open

feat: separate Agent into independent module with dedicated page and route#13420
EurFelux wants to merge 26 commits intomainfrom
feat/13329

Conversation

@EurFelux
Copy link
Collaborator

@EurFelux EurFelux commented Mar 12, 2026

What this PR does

Before this PR:
Agent and Assistant were mixed in a single UnifiedList in the home page sidebar. Users had difficulty discovering the Agent entry. The two have fundamentally different data models (Redux vs SQLite), interaction patterns (topic vs session), and component hierarchies, yet shared the same UI components and Redux state (activeTopicOrSession).

After this PR:
Agent is separated into an independent module with its own sidebar entry, route (/agents), page, navbar, and side panel. The home page only handles Assistants. Navigation between the two is handled via sidebar icons and routes, not Redux state.

Fixes #13329

Why we need it and why it was done in this way

The following tradeoffs were made:

  • AgentSettingsTab was moved to pages/agents/ and is used by the AgentChatNavbar/Tools/SettingsButton drawer.
  • Unified* components were renamed to Assistant* (via git mv) rather than just removing agent code, to make naming accurate and improve readability.
  • activeTopicOrSession was removed from Redux runtime store entirely, replaced by route-based detection where needed, avoiding stale state issues.

The following alternatives were considered:

  • Keeping a shared UnifiedList with a filter — rejected because the data models and interaction patterns are too different, leading to excessive conditional logic.
  • Using a tab within the home page — rejected per issue spec; agents need their own sidebar entry and dedicated page for discoverability.

Breaking changes

None. This is an internal UI refactoring. The Redux migration (v200 → v201) automatically adds the 'agents' sidebar icon to existing user configurations.

Special notes for your reviewer

New directory structure — pages/agents/:

  • AgentPage.tsx — Top-level page with apiServer.enabled guard (early return with alert when server disabled)
  • AgentChat.tsx — Chat area with loading state management (Spin during initialization, alerts for select/create states)
  • AgentNavbar.tsx — Top navbar for left-sidebar layout mode
  • AgentSidePanel.tsx — Left panel with agent list and sessions tabs
  • AgentSettingsTab.tsx — Moved from home, used by AgentChatNavbar settings drawer
  • components/AgentChatNavbar/ — Mirrors home/components/ChatNavBar/ structure:
    • index.tsx — Sidebar toggle buttons + content wrapper
    • AgentContent.tsx — Agent → Session → Model → Workspace breadcrumb navigation
    • Tools/ — Agent-specific toolbar with SettingsButton (uses AgentSettingsTab)
    • OpenExternalAppButton.tsx, SessionWorkspaceMeta.tsx — AgentContent-only components
  • components/ — Migrated agent-only components: AgentItem, AgentSessionInputbar, AgentSessionMessages, SelectAgentBaseModelButton, SessionItem, Sessions

Hook consolidation:

  • Merged two duplicate useActiveAgent hooks into one at hooks/agents/useActiveAgent — now returns both { agent, error, isLoading, setActiveAgentId }
  • Deleted home/Tabs/hooks/useActiveAgent.ts

Loading state improvements:

  • AgentPage top-level guard prevents all child components from rendering when apiServer is disabled
  • AgentChat tracks isInitializing covering: server starting → agents loading → agent loading → session initializing → auto-select pending
  • useAgentSessionInitializer now distinguishes undefined (not initialized) vs null (initialized, no sessions) in activeSessionIdMap, preventing premature "create session" alerts

Shared component extraction:

  • AddButton moved from home/Tabs/components/ to renderer/src/components/ (used by both pages)

Checklist

  • PR: The PR description is expressive enough and will help future contributors
  • Code: Write code that humans can understand and Keep it simple
  • Refactor: You have left the code cleaner than you found it (Boy Scout Rule)
  • Upgrade: Impact of this change on upgrade flows was considered and addressed if required
  • Documentation: A user-guide update was considered and is present (link) or not required. Check this only when the PR introduces or changes a user-facing feature or behavior.
  • Self-review: I have reviewed my own code before requesting review from others

Release note

Added a dedicated "Agents" page accessible from the sidebar, separating Agents from the Assistants list for improved discoverability and clearer navigation.

…route (#13329)

- Add `/agents` route, sidebar icon, launchpad entry, and i18n labels
- Create AgentPage, AgentChat, AgentNavbar, AgentSidePanel components
- Support left sidebar and right-side Sessions panel (topicPosition setting)
- Rename Unified* components/hooks to Assistant* (agents removed from home)
- Remove `activeTopicOrSession` from Redux runtime store (route-based detection)
- Simplify HomePage/Chat.tsx by removing agent-related branches
- Auto-select first agent when navigating to agent page
- Add Redux migration v201 for sidebar icons

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: icarus <eurfelux@gmail.com>
@kangfenmao
Copy link
Collaborator

Do you have a screenshot? Please take a look @EurFelux

@EurFelux
Copy link
Collaborator Author

EurFelux commented Mar 12, 2026

Note

This issue/comment/review was translated by Claude.

image image image image

The styling still needs some fine-tuning.


Original Content image image image image

样式还需要微调一下

EurFelux and others added 4 commits March 12, 2026 19:13
…d AddButton to components

- Move agent-only components (AgentSessionInputbar, AgentSessionMessages,
  AgentContent, AgentItem, SessionItem, Sessions, SelectAgentBaseModelButton,
  OpenExternalAppButton, SessionWorkspaceMeta) to pages/agents/components/
- Move shared AddButton to renderer/src/components/
- Delete dead SessionsTab (no longer imported after agent separation)
- Update all import paths to reflect new locations

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: icarus <eurfelux@gmail.com>
@EurFelux
Copy link
Collaborator Author

EurFelux commented Mar 12, 2026

Note

This issue/comment/review was translated by Claude.

Mostly ready for review. The loading states for API Server not started/agents loading/sessions loading haven't been fine-tuned yet.


Original Content

大体上 ready for review. API Server 未启动/agents 拉取中/sessions 拉取中的状态还没调好

EurFelux and others added 2 commits March 12, 2026 20:27
- Move apiServer.enabled check to AgentPage top level as early return,
  preventing child components (Sessions, AgentSidePanel) from making
  API calls when server is disabled
- Add loading indicator (Spin) during initialization instead of
  flashing incorrect alerts
- Distinguish session map undefined (not initialized) vs null (no
  sessions) in useAgentSessionInitializer to prevent premature
  "create session" alert
- Use apiServerRunning check in AgentChat to cover the gap before
  SWR starts fetching (key is null when server not yet running)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: icarus <eurfelux@gmail.com>
Combine the read-only hook (hooks/agents/useActiveAgent) and the
setter hook (home/Tabs/hooks/useActiveAgent) into a single hook
that returns both { agent, error, isLoading, setActiveAgentId }.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: icarus <eurfelux@gmail.com>
@EurFelux
Copy link
Collaborator Author

EurFelux commented Mar 12, 2026

Note

This issue/comment/review was translated by Claude.

The lifecycle status display issue has been properly handled.


Original Content

生命周期状态显示问题已妥善处理

Copy link
Collaborator

@DeJeune DeJeune left a comment

Choose a reason for hiding this comment

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

Review Summary

Excellent refactoring work — separating Agents into their own page/route is a well-motivated architectural improvement. The migration is clean, activeTopicOrSession removal is complete, and the new component hierarchy mirrors the home page structure nicely.

Issues Found

Bug (1):

  • Migration 202 has a copy-paste error in the success log message ('migrate 201 success' → should be 'migrate 202 success')

Significant (2):

  • AgentChat.tsx: The content rendering block (activeAgentId && activeSessionId) doesn't guard against isInitializing, meaning if Redux already has both IDs set from a previous session, the spinner and chat content could render simultaneously. Adding !isInitializing && to that condition would make it consistent with the other branches.
  • AgentPage.tsx: The auto-select effect's setActiveAgentId dependency is unstable because useAgentSessionInitializer includes activeSessionIdMap in its useCallback deps. This causes unnecessary callback re-creations on every session map change. A ref-based approach for the map check would stabilize the reference.

Minor/Nit (2):

  • AgentChat.tsx: useSettings() called twice — can be merged into one destructuring.
  • AgentContent.tsx: When sidebar is collapsed in top-navbar mode, both a PanelRightClose icon and an animated Menu hamburger icon render as separate toggle buttons. Worth a brief comment explaining the UX intent.

Positives

  • Clean separation of concerns: Agent page, chat, side panel, and navbar are well-structured
  • Good loading state management with the isInitializing composite check and undefined vs null session distinction
  • Migration properly inserts the 'agents' sidebar icon after 'assistants'
  • activeTopicOrSession removal is thorough — no stale references remain
  • Shared component extraction (AddButton) is a nice cleanup

@EurFelux EurFelux requested a review from DeJeune March 12, 2026 14:10
Copy link

@cherry-ai-bot cherry-ai-bot bot left a comment

Choose a reason for hiding this comment

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

Overall direction looks good: separating Agents into a dedicated module/page makes the information architecture much clearer and removes a lot of mixed Assistant/Agent state from the home flow.

I left one inline comment for a likely regression: the old shortcut handler was removed from , but I could not find an equivalent registration under the new page path. As written, this seems likely to break for creating a new agent session on the dedicated Agents page.

Once that shortcut path is restored, this refactor looks in good shape to merge.

Copy link
Collaborator

@SiinXu SiinXu left a comment

Choose a reason for hiding this comment

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

LGTM — clean separation of Agent into its own module. Reviewed the key concerns raised by DeJeune and cherry-ai-bot:

  • isInitializing guard: Fixed. All rendering branches in AgentChat.tsx are now mutually exclusive — spinner and chat content cannot render simultaneously.
  • setActiveAgentId dependency stability: Fixed at the hook level — useAgentSessionInitializer now uses a ref for activeSessionIdMap, keeping initializeAgentSession referentially stable.
  • Migration 202 log: Fixed. Correctly logs 'migrate 202 success'.
  • Cmd/Ctrl+N shortcut regression: Fixed per EurFelux's reply.

Non-blocking nit: useAgentClient() (not modified in this PR) creates a new AgentApiClient instance on every render without useMemo. This makes client referentially unstable, cascading through useAgentSessionInitializersetActiveAgentIdAgentPage useEffect deps. The activeSessionIdMapRef guard prevents actual infinite loops, but the unnecessary callback re-creation is wasteful. Consider wrapping in useMemo([host, port, apiKey]) in a follow-up.

EurFelux and others added 3 commits March 13, 2026 18:00
AgentPage previously only checked apiServer.enabled config, which didn't
handle cases where the server was enabled but failed to start at runtime.
Now uses useApiServer hook to check actual running state with three guards:
not enabled → warning, loading → spinner, not running → error alert.

Also removes redundant apiServerRunning check from AgentChat since
AgentPage now guards it at the parent level.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: icarus <eurfelux@gmail.com>
- Add loading spinner during initialization
- Show "create agent" alert when no agents exist
- Separate loading states for agents, agent selection, and session
  creation
- Fix layout structure for better responsiveness
- Update useAgents hook to return undefined data instead of empty array
  fallback
@kangfenmao
Copy link
Collaborator

Empty state

image

@EurFelux
Copy link
Collaborator Author

EurFelux commented Mar 13, 2026

Empty state

image

improved

image

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.

[Feature]: Separate Agent into an independent module from Assistants

4 participants