Skip to content

fix(desktop): collapse v2 chat double header into pane header#3805

Merged
saddlepaddle merged 1 commit into
mainfrom
fix-chat-headers
Apr 27, 2026
Merged

fix(desktop): collapse v2 chat double header into pane header#3805
saddlepaddle merged 1 commit into
mainfrom
fix-chat-headers

Conversation

@saddlepaddle
Copy link
Copy Markdown
Collaborator

@saddlepaddle saddlepaddle commented Apr 27, 2026

Summary

  • v2 chat panes were rendering an h-8 session-selector bar inside the pane below the pane header — two stacked headers. Moved the session selector into the pane header itself via renderTitle (new ChatPaneTitle), so v2 chat now matches the single-header model used by every other pane type.
  • ChatPane.tsx no longer needs the wrapper flex-col + inner header, and stops pulling session-list state it no longer renders. The WorkspaceChatInterface is now mounted directly.
  • Removed the dev-only "Copy raw chat JSON" tooltip button (v1) along with the supporting useChatRawSnapshot hook, the ChatRawSnapshot type, and the onRawSnapshotChange prop / emitter useEffect. v2 carried a duplicated copy of the prop/type that was never wired up — also deleted.

Net: 11 files, +73 / −198.

Test plan

  • Open a v2 workspace, add a chat pane, confirm only one header is visible and the session-switcher dropdown opens from the pane header.
  • Switch sessions, create a new chat, delete a session — all flows still work.
  • Notification dot still appears next to the session title when there are unread chat notifications.
  • Open a v1 chat pane — session selector still works in the toolbar; confirm the dev "copy" icon is gone in dev mode.
  • bun run typecheck --filter=@superset/desktop ✅ (run locally)
  • bun run lint:fix ✅ (run locally)

Summary by cubic

Fixes the double header in v2 chat by moving the session selector into the pane header. Also removes dev-only raw JSON snapshot code and simplifies the chat pane layout.

  • Bug Fixes

    • Moved the session selector into the pane header via renderTitle, so v2 chat now uses a single header like other panes.
    • Session switch, create, delete flows unchanged; unread notification indicator stays in the header.
  • Refactors

    • Simplified ChatPane: removed inner header/layout, mounted WorkspaceChatInterface directly, and stopped reading session-list state not rendered here.
    • Added ChatPaneTitle and wired it in usePaneRegistry renderTitle.
    • Removed the dev-only “Copy raw chat JSON” button and all related onRawSnapshotChange/snapshot types/hooks in both v1 and v2.

Written for commit 3df7395. Summary will update on new commits. Review in cubic

Summary by CodeRabbit

  • Refactor
    • Reorganized chat interface components for improved code maintainability and cleaner architecture.
    • Removed development-only debugging tooling for internal snapshot inspection.

Move the chat session switcher into the v2 pane header via
renderTitle so the chat pane stops rendering its own h-8 header
underneath the pane header. Also drop the dev-only "Copy raw chat
JSON" button and the now-unused onRawSnapshotChange/ChatRawSnapshot
plumbing in both v1 and v2.
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 27, 2026

📝 Walkthrough

Walkthrough

This PR refactors chat pane components across two separate locations by extracting session management UI into a dedicated ChatPaneTitle component and removing all development-only raw chat snapshot debugging functionality. The changes simplify ChatPane implementations and centralize title-related logic while eliminating the useChatRawSnapshot hook, ChatRawSnapshot type, and onRawSnapshotChange callback mechanism.

Changes

Cohort / File(s) Summary
ChatPane Refactoring & Title Extraction
apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/hooks/usePaneRegistry/components/ChatPane/ChatPane.tsx, apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/hooks/usePaneRegistry/components/ChatPane/components/ChatPaneTitle/*
Simplifies ChatPane by removing SessionSelector UI and session management handlers; creates new ChatPaneTitle component to handle session selection, updates, and notification status indicators.
ChatPaneInterface Cleanup
apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/hooks/usePaneRegistry/components/ChatPane/components/WorkspaceChatInterface/*, apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/ChatPane/ChatPaneInterface/*
Removes onRawSnapshotChange prop and related effect from ChatPaneInterface components; deletes ChatRawSnapshot type definition from both locations' type files.
Raw Snapshot Debugging Removal
apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/ChatPane/ChatPane.tsx, apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/ChatPane/hooks/useChatRawSnapshot/*
Removes development-only raw chat snapshot tooling: deletes useChatRawSnapshot hook with copy-to-clipboard feature and dev-only toolbar UI; removes related imports.
Pane Registry Update
apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/hooks/usePaneRegistry/usePaneRegistry.tsx
Refactors chat pane title rendering to delegate to ChatPaneTitle component, replacing inline JSX that composed icon, label, and notification indicator.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Poem

🐰 Hops of joy through refactored code,
SessionTitle now lightens the load,
Snapshots gone—no more dev debug cheer,
ChatPane's cleaner, the structure's more clear!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.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
Title check ✅ Passed The title accurately captures the main change: collapsing v2 chat's double header into a single pane header by moving the session selector.
Description check ✅ Passed The description covers key aspects (summary, test plan) and is mostly complete. However, it lacks explicit sections matching the template structure (Related Issues, Type of Change, Testing structure, Screenshots).
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 fix-chat-headers

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.

@greptile-apps
Copy link
Copy Markdown

greptile-apps Bot commented Apr 27, 2026

Greptile Summary

This PR fixes the double-header issue in v2 chat panes by lifting the session selector out of the pane body and into renderTitle via a new ChatPaneTitle component, matching the single-header pattern used by terminal and other pane types. It also removes the dev-only "Copy raw chat JSON" feature (hook, type, prop, and useEffect) from both the v1 and v2 chat implementations.

Confidence Score: 5/5

Safe to merge — changes are well-scoped UI refactors and dead-code removal with no functional regressions.

All findings are P2 (style/performance suggestions). The double useWorkspaceChatController instance is a minor inefficiency consistent with the existing terminal pane pattern, and the isActive styling concern is cosmetic. No logic errors or data-integrity issues were found.

ChatPaneTitle.tsx — two P2 notes on duplicate hook instantiation and dropped isActive styling.

Important Files Changed

Filename Overview
apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/hooks/usePaneRegistry/components/ChatPane/ChatPane.tsx Simplified: removes the inner session-selector header bar and wrapping flex-col container; now mounts WorkspaceChatInterface directly, eliminating the double-header.
apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/hooks/usePaneRegistry/components/ChatPane/components/ChatPaneTitle/ChatPaneTitle.tsx New component rendering SessionSelector + V2NotificationStatusIndicator in the pane header; introduces a second useWorkspaceChatController instance per pane and drops the isActive-based text-color transition.
apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/hooks/usePaneRegistry/usePaneRegistry.tsx Replaces inline renderTitle JSX with ChatPaneTitle component; clean refactor, imports and useMemo deps unchanged.
apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/ChatPane/ChatPane.tsx Removes dev-only copy-JSON toolbar button, useChatRawSnapshot hook call, showDevToolbarActions flag, and env import — all cleanly removed.
apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/ChatPane/hooks/useChatRawSnapshot/useChatRawSnapshot.ts Deleted useChatRawSnapshot hook — dev-only clipboard snapshot utility no longer needed.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    subgraph Before["Before (double-header)"]
        A[usePaneRegistry renderTitle] -->|inline JSX| B["MessageSquare + 'Chat' + NotificationIndicator"]
        C[usePaneRegistry renderPane] --> D[ChatPane]
        D --> E["flex-col wrapper\n- SessionSelector header\n- WorkspaceChatInterface"]
    end

    subgraph After["After (single-header)"]
        F[usePaneRegistry renderTitle] --> G[ChatPaneTitle]
        G --> G1[useWorkspaceChatController]
        G --> H["SessionSelector + NotificationIndicator"]
        I[usePaneRegistry renderPane] --> J[ChatPane]
        J --> J1[useWorkspaceChatController]
        J --> K[WorkspaceChatInterface directly]
    end
Loading
Prompt To Fix All With AI
This is a comment left during a code review.
Path: apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/hooks/usePaneRegistry/components/ChatPane/components/ChatPaneTitle/ChatPaneTitle.tsx
Line: 26-35

Comment:
**Duplicate `useWorkspaceChatController` per pane**

`ChatPaneTitle` (rendered by `renderTitle`) and `ChatPane` (rendered by `renderPane`) each independently call `useWorkspaceChatController`, so two separate `useLiveQuery` subscriptions and two `workspace.get` tRPC queries run per chat pane. `ChatPane` still needs `organizationId`, `workspacePath`, and `getOrCreateSession` from the hook, so the overlap can't be eliminated completely — but the subscription to the session list is doubled for every open chat pane. This is consistent with how `TerminalSessionDropdown` works in the terminal pane, but worth noting as a scalability consideration.

How can I resolve this? If you propose a fix, please make it concise.

---

This is a comment left during a code review.
Path: apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/hooks/usePaneRegistry/components/ChatPane/components/ChatPaneTitle/ChatPaneTitle.tsx
Line: 14-52

Comment:
**`context.isActive` unused — pane-focus text styling dropped**

The old inline `renderTitle` applied `ctx.isActive ? "text-foreground" : "text-muted-foreground"` to the title span. `ChatPaneTitle` receives the full `context` (which includes `context.isActive`) but never threads it into `SessionSelector`, so the header title no longer changes color when the pane gains or loses focus. Compare with `FilePaneTabTitle` which explicitly forwards `isActive` to apply that transition. If `SessionSelector` handles its own active-state styling this is fine; otherwise the pane header will appear static regardless of focus.

How can I resolve this? If you propose a fix, please make it concise.

Reviews (1): Last reviewed commit: "fix(desktop): collapse v2 chat double he..." | Re-trigger Greptile

Comment on lines +26 to +35
const {
sessionItems,
handleSelectSession,
handleNewChat,
handleDeleteSession,
} = useWorkspaceChatController({
workspaceId,
sessionId,
onSessionIdChange,
});
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 Duplicate useWorkspaceChatController per pane

ChatPaneTitle (rendered by renderTitle) and ChatPane (rendered by renderPane) each independently call useWorkspaceChatController, so two separate useLiveQuery subscriptions and two workspace.get tRPC queries run per chat pane. ChatPane still needs organizationId, workspacePath, and getOrCreateSession from the hook, so the overlap can't be eliminated completely — but the subscription to the session list is doubled for every open chat pane. This is consistent with how TerminalSessionDropdown works in the terminal pane, but worth noting as a scalability consideration.

Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/hooks/usePaneRegistry/components/ChatPane/components/ChatPaneTitle/ChatPaneTitle.tsx
Line: 26-35

Comment:
**Duplicate `useWorkspaceChatController` per pane**

`ChatPaneTitle` (rendered by `renderTitle`) and `ChatPane` (rendered by `renderPane`) each independently call `useWorkspaceChatController`, so two separate `useLiveQuery` subscriptions and two `workspace.get` tRPC queries run per chat pane. `ChatPane` still needs `organizationId`, `workspacePath`, and `getOrCreateSession` from the hook, so the overlap can't be eliminated completely — but the subscription to the session list is doubled for every open chat pane. This is consistent with how `TerminalSessionDropdown` works in the terminal pane, but worth noting as a scalability consideration.

How can I resolve this? If you propose a fix, please make it concise.

Comment on lines +14 to +52
export function ChatPaneTitle({ context, workspaceId }: ChatPaneTitleProps) {
const data = context.pane.data as ChatPaneData;
const { sessionId } = data;
const { actions } = context;

const onSessionIdChange = useCallback(
(nextSessionId: string | null) => {
actions.updateData({ ...data, sessionId: nextSessionId });
},
[actions, data],
);

const {
sessionItems,
handleSelectSession,
handleNewChat,
handleDeleteSession,
} = useWorkspaceChatController({
workspaceId,
sessionId,
onSessionIdChange,
});

return (
<div className="flex min-w-0 flex-1 items-center gap-1.5">
<SessionSelector
currentSessionId={sessionId}
sessions={sessionItems}
fallbackTitle="New Chat"
onSelectSession={handleSelectSession}
onNewChat={handleNewChat}
onDeleteSession={handleDeleteSession}
/>
<V2NotificationStatusIndicator
workspaceId={workspaceId}
sources={getV2NotificationSourcesForPane(context.pane)}
/>
</div>
);
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 context.isActive unused — pane-focus text styling dropped

The old inline renderTitle applied ctx.isActive ? "text-foreground" : "text-muted-foreground" to the title span. ChatPaneTitle receives the full context (which includes context.isActive) but never threads it into SessionSelector, so the header title no longer changes color when the pane gains or loses focus. Compare with FilePaneTabTitle which explicitly forwards isActive to apply that transition. If SessionSelector handles its own active-state styling this is fine; otherwise the pane header will appear static regardless of focus.

Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/hooks/usePaneRegistry/components/ChatPane/components/ChatPaneTitle/ChatPaneTitle.tsx
Line: 14-52

Comment:
**`context.isActive` unused — pane-focus text styling dropped**

The old inline `renderTitle` applied `ctx.isActive ? "text-foreground" : "text-muted-foreground"` to the title span. `ChatPaneTitle` receives the full `context` (which includes `context.isActive`) but never threads it into `SessionSelector`, so the header title no longer changes color when the pane gains or loses focus. Compare with `FilePaneTabTitle` which explicitly forwards `isActive` to apply that transition. If `SessionSelector` handles its own active-state styling this is fine; otherwise the pane header will appear static regardless of focus.

How can I resolve this? If you propose a fix, please make it concise.

Copy link
Copy Markdown
Contributor

@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

🧹 Nitpick comments (2)
apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/hooks/usePaneRegistry/components/ChatPane/components/ChatPaneTitle/ChatPaneTitle.tsx (2)

4-5: Nit: prefer tsconfig path aliases over deep relative imports.

../../../../../../components/V2NotificationStatusIndicator and ../../../../../../types are fragile to file moves. If a renderer/... (or similar) alias is configured, prefer it here.

As per coding guidelines: "Use alias as defined in tsconfig.json when possible".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/`$workspaceId/hooks/usePaneRegistry/components/ChatPane/components/ChatPaneTitle/ChatPaneTitle.tsx
around lines 4 - 5, Replace the fragile deep-relative imports in
ChatPaneTitle.tsx by using the project's tsconfig path aliases: import
V2NotificationStatusIndicator via the components alias and import ChatPaneData
and PaneViewerData via the types alias (replace
"../../../../../../components/V2NotificationStatusIndicator" and
"../../../../../../types" with the configured aliases); update the import
statements that reference V2NotificationStatusIndicator, ChatPaneData, and
PaneViewerData to use the matching tsconfig.json alias entries so future file
moves won't break the imports.

19-24: Optional: stabilize onSessionIdChange identity.

Closing over data makes this callback's identity change whenever any field on data (e.g., launchConfig) updates, which churns the dep array of useWorkspaceChatController. Reading the latest pane data inside the action (or via a ref) keeps the handler stable.

♻️ Possible refactor
-	const onSessionIdChange = useCallback(
-		(nextSessionId: string | null) => {
-			actions.updateData({ ...data, sessionId: nextSessionId });
-		},
-		[actions, data],
-	);
+	const dataRef = useRef(data);
+	dataRef.current = data;
+	const onSessionIdChange = useCallback(
+		(nextSessionId: string | null) => {
+			actions.updateData({ ...dataRef.current, sessionId: nextSessionId });
+		},
+		[actions],
+	);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/`$workspaceId/hooks/usePaneRegistry/components/ChatPane/components/ChatPaneTitle/ChatPaneTitle.tsx
around lines 19 - 24, onSessionIdChange currently closes over the entire data
object which causes its identity to change whenever any field on data updates;
change it so it does not reference data directly—call actions.updateData with a
functional updater or read the latest pane data from a ref inside the handler
(so onSessionIdChange only depends on actions), ensuring you keep
useWorkspaceChatController's dependency array stable; update the handler
implementation in ChatPaneTitle.tsx (function name onSessionIdChange, call site
actions.updateData) to use an updater callback or ref-based read instead of
spreading the closed-over data.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/`$workspaceId/hooks/usePaneRegistry/components/ChatPane/components/ChatPaneTitle/ChatPaneTitle.tsx:
- Around line 26-35: ChatPaneTitle and ChatPane both call
useWorkspaceChatController, causing duplicate queries/subscriptions/mutations;
lift the hook out to a single owner (e.g., the pane registry's chat config or a
pane-scoped context) so side effects run once and pass down only needed values
(sessionItems, handleSelectSession, handleNewChat, handleDeleteSession, and any
runtime handlers) as props to ChatPaneTitle and ChatPane, or alternatively split
useWorkspaceChatController into two hooks (useWorkspaceSessionList and
useWorkspaceChatRuntime) and replace the duplicated calls in ChatPaneTitle and
ChatPane with the appropriate lighter hook; update the parent component that
renders ChatPane and ChatPaneTitle to call the single hook (or both split hooks)
and forward the derived handlers/state.

---

Nitpick comments:
In
`@apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/`$workspaceId/hooks/usePaneRegistry/components/ChatPane/components/ChatPaneTitle/ChatPaneTitle.tsx:
- Around line 4-5: Replace the fragile deep-relative imports in
ChatPaneTitle.tsx by using the project's tsconfig path aliases: import
V2NotificationStatusIndicator via the components alias and import ChatPaneData
and PaneViewerData via the types alias (replace
"../../../../../../components/V2NotificationStatusIndicator" and
"../../../../../../types" with the configured aliases); update the import
statements that reference V2NotificationStatusIndicator, ChatPaneData, and
PaneViewerData to use the matching tsconfig.json alias entries so future file
moves won't break the imports.
- Around line 19-24: onSessionIdChange currently closes over the entire data
object which causes its identity to change whenever any field on data updates;
change it so it does not reference data directly—call actions.updateData with a
functional updater or read the latest pane data from a ref inside the handler
(so onSessionIdChange only depends on actions), ensuring you keep
useWorkspaceChatController's dependency array stable; update the handler
implementation in ChatPaneTitle.tsx (function name onSessionIdChange, call site
actions.updateData) to use an updater callback or ref-based read instead of
spreading the closed-over data.
🪄 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: 743cf80d-e269-4620-8eb0-c049da149fab

📥 Commits

Reviewing files that changed from the base of the PR and between 298d773 and 3df7395.

📒 Files selected for processing (11)
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/hooks/usePaneRegistry/components/ChatPane/ChatPane.tsx
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/hooks/usePaneRegistry/components/ChatPane/components/ChatPaneTitle/ChatPaneTitle.tsx
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/hooks/usePaneRegistry/components/ChatPane/components/ChatPaneTitle/index.ts
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/hooks/usePaneRegistry/components/ChatPane/components/WorkspaceChatInterface/ChatPaneInterface.tsx
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/hooks/usePaneRegistry/components/ChatPane/components/WorkspaceChatInterface/types.ts
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/hooks/usePaneRegistry/usePaneRegistry.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/ChatPane/ChatPane.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/ChatPane/ChatPaneInterface/ChatPaneInterface.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/ChatPane/ChatPaneInterface/types.ts
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/ChatPane/hooks/useChatRawSnapshot/index.ts
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/ChatPane/hooks/useChatRawSnapshot/useChatRawSnapshot.ts
💤 Files with no reviewable changes (7)
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/ChatPane/hooks/useChatRawSnapshot/index.ts
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/ChatPane/ChatPaneInterface/ChatPaneInterface.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/ChatPane/ChatPaneInterface/types.ts
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/hooks/usePaneRegistry/components/ChatPane/components/WorkspaceChatInterface/ChatPaneInterface.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/ChatPane/hooks/useChatRawSnapshot/useChatRawSnapshot.ts
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/hooks/usePaneRegistry/components/ChatPane/components/WorkspaceChatInterface/types.ts
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/ChatPane/ChatPane.tsx

Comment on lines +26 to +35
const {
sessionItems,
handleSelectSession,
handleNewChat,
handleDeleteSession,
} = useWorkspaceChatController({
workspaceId,
sessionId,
onSessionIdChange,
});
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.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Inspect useWorkspaceChatController for side effects (queries, subscriptions, mutations, effects).
fd -t f 'useWorkspaceChatController' --exec cat {}
echo "----- callers -----"
rg -nP '\buseWorkspaceChatController\s*\(' -C2

Repository: superset-sh/superset

Length of output: 8096


🏁 Script executed:

#!/bin/bash
# Check if ChatPaneTitle is imported/used in ChatPane
echo "=== Checking ChatPane.tsx for ChatPaneTitle import/usage ==="
cat "apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/\$workspaceId/hooks/usePaneRegistry/components/ChatPane/ChatPane.tsx"

echo -e "\n=== Checking ChatPaneTitle full file ==="
cat "apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/\$workspaceId/hooks/usePaneRegistry/components/ChatPane/components/ChatPaneTitle/ChatPaneTitle.tsx"

Repository: superset-sh/superset

Length of output: 2825


🏁 Script executed:

#!/bin/bash
# Search for imports of ChatPaneTitle
echo "=== Finding ChatPaneTitle imports ==="
rg 'ChatPaneTitle' --type ts --type tsx -g '!node_modules'

# Check what the pane registry structure looks like
echo -e "\n=== Checking pane registry hook to understand pane rendering ==="
fd -t f 'usePaneRegistry' --path '*/hooks/*' | head -5
</script>

Repository: superset-sh/superset

Length of output: 551


🏁 Script executed:

#!/bin/bash
# Search more broadly for ChatPaneTitle
echo "=== Searching for ChatPaneTitle ==="
rg 'ChatPaneTitle' -t ts -t tsx

# Look for how pane titles/components are registered
echo -e "\n=== Finding usePaneRegistry hook ==="
find . -name '*usePaneRegistry*' -type f | grep -v node_modules

# Check if ChatPaneTitle is exported in a barrel export
echo -e "\n=== Checking ChatPane directory index files ==="
find "apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/\$workspaceId/hooks/usePaneRegistry/components/ChatPane" -name 'index.*' -type f -exec cat {} \;

Repository: superset-sh/superset

Length of output: 3700


🏁 Script executed:

#!/bin/bash
# Read usePaneRegistry to see how panes are structured
echo "=== usePaneRegistry.tsx ===" 
cat "apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/\$workspaceId/hooks/usePaneRegistry/usePaneRegistry.tsx"

Repository: superset-sh/superset

Length of output: 15908


Lift useWorkspaceChatController to avoid duplicate side effects.

useWorkspaceChatController is called twice for the same pane — once in ChatPaneTitle (for session list UI) and once in ChatPane (for chat runtime). The hook runs queries, subscriptions, and mutations, so duplicate calls cause duplicate workspace queries, duplicate session subscriptions, and duplicate mutation setups.

Consider lifting the hook call to a shared parent (the pane registry's chat config or a context provider scoped to the pane) and passing only the needed values as props to each child, or split the hook into separate "session-list" and "chat-runtime" hooks so side effects run exactly once per pane.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/`$workspaceId/hooks/usePaneRegistry/components/ChatPane/components/ChatPaneTitle/ChatPaneTitle.tsx
around lines 26 - 35, ChatPaneTitle and ChatPane both call
useWorkspaceChatController, causing duplicate queries/subscriptions/mutations;
lift the hook out to a single owner (e.g., the pane registry's chat config or a
pane-scoped context) so side effects run once and pass down only needed values
(sessionItems, handleSelectSession, handleNewChat, handleDeleteSession, and any
runtime handlers) as props to ChatPaneTitle and ChatPane, or alternatively split
useWorkspaceChatController into two hooks (useWorkspaceSessionList and
useWorkspaceChatRuntime) and replace the duplicated calls in ChatPaneTitle and
ChatPane with the appropriate lighter hook; update the parent component that
renders ChatPane and ChatPaneTitle to call the single hook (or both split hooks)
and forward the derived handlers/state.

Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

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

No issues found across 11 files

@saddlepaddle saddlepaddle merged commit 50eb125 into main Apr 27, 2026
7 checks passed
@github-actions
Copy link
Copy Markdown
Contributor

🧹 Preview Cleanup Complete

The following preview resources have been cleaned up:

  • ⚠️ Neon database branch

Thank you for your contribution! 🎉

@Kitenite Kitenite deleted the fix-chat-headers branch May 6, 2026 04:52
MocA-Love pushed a commit to MocA-Love/superset that referenced this pull request May 21, 2026
…et-sh#3805)

Move the chat session switcher into the v2 pane header via
renderTitle so the chat pane stops rendering its own h-8 header
underneath the pane header. Also drop the dev-only "Copy raw chat
JSON" button and the now-unused onRawSnapshotChange/ChatRawSnapshot
plumbing in both v1 and v2.
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