Feat/group chat followup ux - #113
Conversation
…nels - Input mode switches between New/Continue/Disabled based on conversation state - Continue uses SSE streaming (continueStream) instead of REST mutation - DiscussionActions bar shows followup + close (continue moved to input) - New Discussion button in sidebar header + mobile dropdown - Workforce board: full lifecycle parity (actions, continue, new discussion) - Right-side panels default to open and persist state in localStorage - i18n: 12 new keys across all 11 locales - Tests updated: 3918 pass, 269 files
… resetStream - group_start SSE handler now appends question on continuation instead of replacing the entire transcript (was wiping prior round context) - Discussion list items: outer <button> → <div role='button'> to fix nested <button> HTML spec violation - Input shows 'Loading…' placeholder while conversation data loads (was briefly showing default placeholder on a disabled input) - Standardized workforce board disabled-messages to groups.* namespace - Added resetStream() to SSE hook — fully resets state (transcript, synthesis, etc) on 'New Discussion' instead of just stopping the stream
|
Caution Review failedThe pull request is closed. ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (6)
📝 WalkthroughWalkthroughThe PR moves discussion continuation into SSE streaming, adds reset and transcript preservation, introduces context-aware input modes and disabled states, simplifies action bars, adds new-discussion controls, introduces workspace switching and persisted panels, updates log streaming and translations, and expands tests. ChangesDiscussion continuation and workspace controls
Estimated code review effort: 4 (Complex) | ~60 minutes Sequence Diagram(s)sequenceDiagram
participant User
participant GroupDetailPage
participant useGroupDiscussionStream
participant streamGroupContinue
User->>GroupDetailPage: Submit continuation question
GroupDetailPage->>useGroupDiscussionStream: continueStream(groupId, conversationId, question)
useGroupDiscussionStream->>streamGroupContinue: Start continuation SSE stream
streamGroupContinue-->>useGroupDiscussionStream: Stream group_start and progress events
useGroupDiscussionStream-->>GroupDetailPage: Update transcript and stream state
GroupDetailPage-->>User: Render continued discussion
Possibly related PRs
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
Pull request overview
This PR refactors the group “continue discussion” flow so continuation is initiated from the context-aware input (instead of the DiscussionActions bar), and wires that pattern into both Group Detail and Workforce Board experiences. It also adds panel-state persistence and expands i18n coverage for the new UX.
Changes:
- Move “continue” UX from
DiscussionActionstoDiscussionInput/BoardInputvia amode+disabledMessageAPI and updated tests. - Add SSE-based continuation (
continueStream) + “New discussion” reset actions in Group Detail and Workforce Board. - Persist Workforce panel open/close state to
localStorage, with test updates for deterministic defaults.
Reviewed changes
Copilot reviewed 22 out of 22 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| src/pages/workforce/workforce-chat.tsx | Persists details panel open state to localStorage. |
| src/pages/workforce/workforce-board.tsx | Adds context-aware input mode (new/continue/disabled), SSE continuation, lifecycle mutations, and “New Discussion”. |
| src/pages/workforce/tests/workforce-pages.test.tsx | Stabilizes tests around new default-open panel behavior and duplicate text occurrences. |
| src/pages/group-detail.tsx | Uses input-driven continuation/new discussion reset; adjusts discussion list item semantics; updates history UI. |
| src/pages/tests/group-detail.test.tsx | Updates assertions for continue being handled by input; adds disabled-input coverage. |
| src/hooks/use-group-discussion-stream.ts | Adds continueStream + resetStream; updates group_start transcript handling. |
| src/components/workforce/board-input.tsx | Adds mode/disabledMessage, hides attachments in continue mode, updates placeholders/a11y. |
| src/components/groups/discussion-input.tsx | Adds mode/disabledMessage, continue icon/label/placeholder behavior. |
| src/components/groups/discussion-actions.tsx | Removes continue-related UI/props; keeps followup + close actions only. |
| src/components/groups/tests/discussion-input.test.tsx | Adds coverage for continue mode and disabled placeholder behavior. |
| src/components/groups/tests/discussion-actions.test.tsx | Updates coverage to reflect continue removal from the action bar. |
| src/i18n/locales/en.json | Adds new group/workforce strings for continue mode, disabled messaging, and “New”. |
| src/i18n/locales/de.json | Propagates new keys for continue mode and disabled messaging. |
| src/i18n/locales/fr.json | Propagates new keys for continue mode and disabled messaging. |
| src/i18n/locales/es.json | Propagates new keys for continue mode and disabled messaging. |
| src/i18n/locales/ar.json | Propagates new keys for continue mode and disabled messaging. |
| src/i18n/locales/zh.json | Propagates new keys for continue mode and disabled messaging. |
| src/i18n/locales/th.json | Propagates new keys for continue mode and disabled messaging. |
| src/i18n/locales/ja.json | Propagates new keys for continue mode and disabled messaging. |
| src/i18n/locales/ko.json | Propagates new keys for continue mode and disabled messaging. |
| src/i18n/locales/pt.json | Propagates new keys for continue mode and disabled messaging. |
| src/i18n/locales/hi.json | Propagates new keys for continue mode and disabled messaging. |
Comments suppressed due to low confidence (2)
src/components/groups/discussion-input.tsx:151
- The expanded dialog textarea stays enabled when
disabledis true, and the Ctrl/Cmd+Enter handler will still callhandleSubmit(). This lets users attempt submissions in states where the inline input is disabled (e.g., CLOSED discussion). Disable the dialog textarea whendisabledis true and gate the shortcut accordingly.
This issue also appears on line 171 of the same file.
disabled={isLoading}
onKeyDown={(e) => {
if (e.key === "Enter" && (e.ctrlKey || e.metaKey)) {
e.preventDefault();
handleSubmit();
}
}}
src/components/groups/discussion-input.tsx:171
- The expanded dialog submit button does not account for the
disabledprop, so it can appear clickable even when the discussion is not accepting input. Includedisabledin the button's disabled condition.
>
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
…Storage guards - board-input: aria-label now mirrors placeholder logic so assistive tech announces the disabled reason (not the stale normal label) - continueStream: reset per-round derived fields (synthesizedAnswer, currentPhase, taskPlan, HITL, cancel, task sets) while keeping the transcript — prevents stale synthesis/task state during continuation - workforce-board + workforce-chat: wrap localStorage read/write in try/catch so pages remain usable when storage is blocked
- 6 new tests covering: continueStream per-round state reset, group_start transcript append vs replace on continuation, resetStream full state clear, callback stability for continueStream and resetStream
There was a problem hiding this comment.
Actionable comments posted: 7
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
src/components/groups/discussion-input.tsx (1)
51-58: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
disabledstate is bypassable via the expand dialog — submissions can slip through when the discussion is disabled.
handleSubmitnever checks thedisabledprop, and the "Expand" trigger button, the dialog's textarea, and the dialog's submit button only gate onisLoading, notdisabled. A user can click "Expand" whiledisabledis true (e.g. discussion closed, surfaced viadisabledMessage), type in the dialog, and submit anyway — undermining the very feature this PR adds.🐛 Proposed fix to thread `disabled` through the expand path
function handleSubmit(e?: React.FormEvent) { e?.preventDefault(); - if (question.trim() && !isLoading) { + if (question.trim() && !isLoading && !disabled) { onSubmit(question.trim()); setQuestion(""); setDialogOpen(false); } }<button type="button" onClick={() => setDialogOpen(true)} + disabled={disabled} className="absolute end-2 inset-y-0 my-auto h-fit rounded p-0.5 text-muted-foreground hover:text-foreground hover:bg-secondary/50 transition-colors" title={t("groups.expandInput", "Expand input")} >- disabled={isLoading} + disabled={isLoading || disabled} onKeyDown={(e) => {<Button onClick={() => handleSubmit()} - disabled={!question.trim() || isLoading} + disabled={!question.trim() || isLoading || disabled} >Also applies to: 90-97, 138-142, 145-145, 170-181
🤖 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 `@src/components/groups/discussion-input.tsx` around lines 51 - 58, Thread the disabled prop through the entire expand-dialog submission flow: update handleSubmit to reject submissions when disabled, and gate the Expand trigger, dialog textarea, and dialog submit button on both disabled and isLoading. Preserve disabledMessage behavior while ensuring no interaction or submission can bypass the disabled state.src/pages/workforce/workforce-board.tsx (1)
139-147: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick winStale
selectedConversationcache aftercontinueStreamcompletes.The completion effect (unchanged, lines 143-147) only calls
setSelectedConvId(streamState.conversationId). For a brand-new discussion this triggers a freshuseGroupConversationfetch (previously disabled sinceselectedConvIdwasnull), but for a continuation,selectedConvIdis already set to the same id, so the state update is a no-op and the underlyinguseGroupConversationquery is never invalidated.inputMode(Lines 210-217) and theDiscussionActionsgating (Lines 493-504) both readselectedConversation.availableActions, so after a continue round finishes, the UI keeps deciding "continue"/"followup"/"close" availability from pre-continuation data.🔧 Proposed fix
useEffect(() => { if (streamState.state === "COMPLETED" && streamState.conversationId) { setSelectedConvId(streamState.conversationId); + queryClient.invalidateQueries({ + queryKey: ["groupConversations", boardId, streamState.conversationId], + }); } - }, [streamState.state, streamState.conversationId]); + }, [streamState.state, streamState.conversationId, boardId, queryClient]);🤖 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 `@src/pages/workforce/workforce-board.tsx` around lines 139 - 147, Update the stream completion effect around useGroupDiscussionStream so it invalidates or refreshes the selected conversation query through queryClient whenever streamState reaches COMPLETED with a conversationId, including continuation completions where setSelectedConvId is unchanged. Preserve the existing auto-selection behavior for new discussions and ensure consumers such as inputMode and DiscussionActions receive the refreshed availableActions data.
🧹 Nitpick comments (4)
src/pages/group-detail.tsx (2)
189-193: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winNo test coverage for
handleNewDiscussion/ the "New Discussion" control.This is a new user-facing entry point (resets stream state and clears selection) but the companion test file doesn't exercise
new-discussion-btn/new-discussion-btn-mobileor assertresetStream+ selection-clearing behavior.🤖 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 `@src/pages/group-detail.tsx` around lines 189 - 193, Add test coverage for handleNewDiscussion in the companion group-detail tests by exercising both new-discussion-btn and new-discussion-btn-mobile. Assert that activating either control invokes resetStream, clears the selected conversation, and resets the pending decision state as implemented by the handler.
592-613: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winDuplicated "New Discussion" button markup.
The Plus-icon "New" button here duplicates the one in
HistoryDropdown(lines 777-792) almost verbatim. Consider extracting a small sharedNewDiscussionButtoncomponent to avoid drift between the two.🤖 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 `@src/pages/group-detail.tsx` around lines 592 - 613, Extract the duplicated Plus-icon “New Discussion” button into a shared NewDiscussionButton component and use it both here and in HistoryDropdown. Preserve the existing click handler, translations, accessibility attributes, test identifier, and styling so both locations remain behaviorally identical.src/pages/workforce/__tests__/workforce-pages.test.tsx (1)
70-103: 📐 Maintainability & Code Quality | 🔵 Trivial | 🏗️ Heavy liftNo coverage for the new continue/new-discussion/followup/close flows.
WorkforceBoardgained a "New Discussion" reset handler, context-awareinputMode/disabledMessage, andfollowup/closemutations wired toDiscussionActions, but this suite still only exercises the pre-existing render/members-panel-toggle paths.🤖 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 `@src/pages/workforce/__tests__/workforce-pages.test.tsx` around lines 70 - 103, The WorkforceBoard test suite lacks coverage for the new discussion and action flows. Extend the WorkforceBoard tests to verify New Discussion resets the board state, inputMode and disabledMessage reflect the active context, and DiscussionActions trigger the followup and close mutations with the expected behavior; preserve the existing render and members-panel tests.src/pages/workforce/workforce-board.tsx (1)
113-130: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winDuplicated localStorage-backed boolean state pattern across two files. Both sites implement the same "read with try/catch, default true, persist on change with try/catch" logic for a panel-visibility flag; extracting a shared
usePersistedBoolean(key, defaultValue)hook would remove the duplication and keep the storage-guard logic in one place.
src/pages/workforce/workforce-board.tsx#L113-L130: replace the inlineshowConfiglazy-init/persist-effect pair withconst [showConfig, setShowConfig] = usePersistedBoolean("workforce-board-config-panel", true);.src/pages/workforce/workforce-chat.tsx#L32-L48: replace the inlineshowDetailslazy-init/persist-effect pair withconst [showDetails, setShowDetails] = usePersistedBoolean("workforce-chat-details-panel", true);.🤖 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 `@src/pages/workforce/workforce-board.tsx` around lines 113 - 130, The duplicated localStorage-backed boolean logic should be centralized in a shared usePersistedBoolean(key, defaultValue) hook. In src/pages/workforce/workforce-board.tsx#L113-L130, replace the inline showConfig initialization and persistence effect with usePersistedBoolean("workforce-board-config-panel", true); apply the same replacement to showDetails in src/pages/workforce/workforce-chat.tsx#L32-L48 using "workforce-chat-details-panel" and true, while preserving guarded storage access in the shared hook.
🤖 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 `@src/pages/group-detail.tsx`:
- Around line 174-187: Update handleInputSubmit so the continuation and
new-discussion success toasts are shown only after continueStream or startStream
confirms the stream was established, and add matching error handling for
immediate failures (including 404/409/network errors). Preserve the existing
HITL failure behavior while ensuring a failed request never leaves an optimistic
“started” toast visible.
- Around line 162-172: Update the disabledMessage useMemo to handle COMPLETED
conversations when availableActions does not include "continue", returning the
appropriate ended/disabled translation instead of undefined. Preserve the
existing state-specific messages and ensure the condition matches the inputMode
disabled behavior.
- Around line 399-409: Update the conversation container’s onKeyDown handler
around handleSelectConversation so Enter/Space events originating from nested
button controls are ignored, allowing their native keyboard activation to
proceed. Preserve the existing preventDefault and conversation-selection
behavior for activation events on the outer role="button" itself.
In `@src/pages/workforce/workforce-board.tsx`:
- Around line 370-380: Guard the New Discussion Button around
handleNewDiscussion so it cannot reset an active stream without confirmation.
When isStreaming is true, require an AlertDialog confirmation before invoking
handleNewDiscussion; preserve the existing direct action when no stream is
active and keep the Stop and Close discussion behavior unchanged.
- Around line 219-229: Update the disabledMessage useMemo to handle COMPLETED
discussions that lack the "continue" action, returning the appropriate
disabled/end-state translation instead of undefined. Keep the existing
state-specific messages unchanged and ensure BoardInput receives a non-empty
disabled message whenever inputMode is "disabled" for this case.
- Around line 232-244: The handleSend callback in workforce-board.tsx drops
attachment metadata because it only accepts a question string. Update handleSend
and the BoardInput onSend contract to either process attachments through the
existing upload/attachment API and pass the resulting context into
startStream/continueStream, or explicitly reject and notify attachment-only
submissions before invoking either stream API.
- Around line 257-262: Export GROUP_CONVERSATIONS_KEY from use-groups.ts, then
update WorkforceBoard’s invalidateConversations callback to build the
invalidation key with [...GROUP_CONVERSATIONS_KEY, boardId] instead of the
hard-coded "groupConversations" prefix, preserving the existing boardId guard.
---
Outside diff comments:
In `@src/components/groups/discussion-input.tsx`:
- Around line 51-58: Thread the disabled prop through the entire expand-dialog
submission flow: update handleSubmit to reject submissions when disabled, and
gate the Expand trigger, dialog textarea, and dialog submit button on both
disabled and isLoading. Preserve disabledMessage behavior while ensuring no
interaction or submission can bypass the disabled state.
In `@src/pages/workforce/workforce-board.tsx`:
- Around line 139-147: Update the stream completion effect around
useGroupDiscussionStream so it invalidates or refreshes the selected
conversation query through queryClient whenever streamState reaches COMPLETED
with a conversationId, including continuation completions where
setSelectedConvId is unchanged. Preserve the existing auto-selection behavior
for new discussions and ensure consumers such as inputMode and DiscussionActions
receive the refreshed availableActions data.
---
Nitpick comments:
In `@src/pages/group-detail.tsx`:
- Around line 189-193: Add test coverage for handleNewDiscussion in the
companion group-detail tests by exercising both new-discussion-btn and
new-discussion-btn-mobile. Assert that activating either control invokes
resetStream, clears the selected conversation, and resets the pending decision
state as implemented by the handler.
- Around line 592-613: Extract the duplicated Plus-icon “New Discussion” button
into a shared NewDiscussionButton component and use it both here and in
HistoryDropdown. Preserve the existing click handler, translations,
accessibility attributes, test identifier, and styling so both locations remain
behaviorally identical.
In `@src/pages/workforce/__tests__/workforce-pages.test.tsx`:
- Around line 70-103: The WorkforceBoard test suite lacks coverage for the new
discussion and action flows. Extend the WorkforceBoard tests to verify New
Discussion resets the board state, inputMode and disabledMessage reflect the
active context, and DiscussionActions trigger the followup and close mutations
with the expected behavior; preserve the existing render and members-panel
tests.
In `@src/pages/workforce/workforce-board.tsx`:
- Around line 113-130: The duplicated localStorage-backed boolean logic should
be centralized in a shared usePersistedBoolean(key, defaultValue) hook. In
src/pages/workforce/workforce-board.tsx#L113-L130, replace the inline showConfig
initialization and persistence effect with
usePersistedBoolean("workforce-board-config-panel", true); apply the same
replacement to showDetails in src/pages/workforce/workforce-chat.tsx#L32-L48
using "workforce-chat-details-panel" and true, while preserving guarded storage
access in the shared hook.
🪄 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 Plus
Run ID: c69fabd6-d022-4055-a3f3-172099fb1217
📒 Files selected for processing (23)
src/components/groups/__tests__/discussion-actions.test.tsxsrc/components/groups/__tests__/discussion-input.test.tsxsrc/components/groups/discussion-actions.tsxsrc/components/groups/discussion-input.tsxsrc/components/workforce/board-input.tsxsrc/hooks/__tests__/use-group-discussion-stream.test.tssrc/hooks/use-group-discussion-stream.tssrc/i18n/locales/ar.jsonsrc/i18n/locales/de.jsonsrc/i18n/locales/en.jsonsrc/i18n/locales/es.jsonsrc/i18n/locales/fr.jsonsrc/i18n/locales/hi.jsonsrc/i18n/locales/ja.jsonsrc/i18n/locales/ko.jsonsrc/i18n/locales/pt.jsonsrc/i18n/locales/th.jsonsrc/i18n/locales/zh.jsonsrc/pages/__tests__/group-detail.test.tsxsrc/pages/group-detail.tsxsrc/pages/workforce/__tests__/workforce-pages.test.tsxsrc/pages/workforce/workforce-board.tsxsrc/pages/workforce/workforce-chat.tsx
- New ModeSwitcher component: dropdown-style workspace switcher placed in both sidebars below the logo. Shows current mode with icon + label + chevron; opens a dropdown with both options. Active mode gets a checkmark. Updates localStorage landing preference on switch. - Follows the same dropdown pattern as sidebar's HelpMenu (outside-click close, Escape, arrow-key nav, focus management) - Collapsed sidebar: icon-only trigger, dropdown positioned to the side - i18n: 3 new keys (modeManager, modeWorkforce, switchMode) × 11 locales
Bug fixes: - discussion-input: thread disabled prop through expand dialog (expand button, dialog textarea, dialog submit, handleSubmit) - group-detail: fix keyboard event propagation on conversation list items — only handle Enter/Space on the container div itself, not nested buttons (fixes delete/cancel keyboard activation) - group-detail: add COMPLETED branch to disabledMessage so disabled input shows explanation instead of generic placeholder - workforce-board: invalidate conversation query on stream complete to refresh availableActions after continuation rounds - workforce-board: add COMPLETED branch to disabledMessage - group-detail: downgrade optimistic stream toasts from success→info Code quality: - Extract usePersistedBoolean hook to DRY up duplicated localStorage boolean pattern (workforce-board + workforce-chat) - Export GROUP_CONVERSATIONS_KEY from use-groups.ts and use it in workforce-board invalidation (type-safe query key) Live logging: - useLogStream now delegates entirely to the session store when unfiltered — no redundant second SSE connection. The Logs page shows data collected since app boot immediately. - Only opens a dedicated SSE when filters are set. Tests: - usePersistedBoolean: 6 tests (read/write, error handling) - ModeSwitcher: 5 tests (render, collapsed, dropdown, keyboard) - DiscussionInput: 2 new tests (disabled expand, disabled bypass) i18n: - groups.inputDisabledCompleted × 11 locales
There was a problem hiding this comment.
Actionable comments posted: 5
🧹 Nitpick comments (1)
src/components/shared/__tests__/mode-switcher.test.tsx (1)
41-62: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winCover mode selection side effects.
Add a test that selects Workforce and asserts navigation to
/workforceplus persistence ofeddi-landing-preference=workforce; the current suite never exercises the primary action.🤖 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 `@src/components/shared/__tests__/mode-switcher.test.tsx` around lines 41 - 62, Add a test alongside the existing ModeSwitcher interaction tests that opens the menu, selects the Workforce menu item, and asserts navigation to /workforce and persistence of eddi-landing-preference=workforce. Reuse the existing renderWithProviders and userEvent setup, and target the Workforce option through its accessible menu item name.
🤖 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 `@src/components/groups/__tests__/discussion-input.test.tsx`:
- Around line 169-179: Update the “does not submit via handleSubmit when
disabled” test to rerender DiscussionInput with disabled enabled after entering
text, then trigger submission through the button or form. Assert onSubmit was
not called, and remove the assertion that only checks the button is initially
enabled.
In `@src/components/shared/mode-switcher.tsx`:
- Around line 20-37: Update the MODES definitions and mode-switcher component to
remove labelKey and fallback fields, then add an in-component mode-label helper
that returns literal t("key", "Fallback") calls for each mode. Replace
downstream dynamic translation usage with this helper while preserving the
existing Manager and Workforce labels.
In `@src/hooks/use-logs.ts`:
- Around line 129-133: Update the filter-change useEffect to reset
filteredConnected to false before invoking connect(), alongside clearing
filtered entries, so consumers never observe the stale connected state while the
replacement SSE stream is being established.
In `@src/hooks/use-persisted-boolean.ts`:
- Around line 12-27: The persisted boolean hook must rehydrate its state
whenever key changes before persisting. Update the usePersistedBoolean flow to
read the new key and reset value to its stored boolean or defaultValue, then
ensure the persistence effect does not write the stale value under the new key
before rehydration completes.
- Line 11: Update the return type of the persisted-boolean hook to use
explicitly imported React state types, ensuring the references to React.Dispatch
and React.SetStateAction resolve without relying on a global React namespace.
Add the necessary type imports and preserve the hook’s existing behavior.
---
Nitpick comments:
In `@src/components/shared/__tests__/mode-switcher.test.tsx`:
- Around line 41-62: Add a test alongside the existing ModeSwitcher interaction
tests that opens the menu, selects the Workforce menu item, and asserts
navigation to /workforce and persistence of eddi-landing-preference=workforce.
Reuse the existing renderWithProviders and userEvent setup, and target the
Workforce option through its accessible menu item name.
🪄 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 Plus
Run ID: 2a49eb49-fd23-4a67-b0cd-70d98d4440a9
📒 Files selected for processing (24)
src/components/groups/__tests__/discussion-input.test.tsxsrc/components/groups/discussion-input.tsxsrc/components/layout/sidebar.tsxsrc/components/shared/__tests__/mode-switcher.test.tsxsrc/components/shared/mode-switcher.tsxsrc/components/workforce/workforce-sidebar.tsxsrc/hooks/__tests__/use-persisted-boolean.test.tssrc/hooks/use-groups.tssrc/hooks/use-logs.tssrc/hooks/use-persisted-boolean.tssrc/i18n/locales/ar.jsonsrc/i18n/locales/de.jsonsrc/i18n/locales/en.jsonsrc/i18n/locales/es.jsonsrc/i18n/locales/fr.jsonsrc/i18n/locales/hi.jsonsrc/i18n/locales/ja.jsonsrc/i18n/locales/ko.jsonsrc/i18n/locales/pt.jsonsrc/i18n/locales/th.jsonsrc/i18n/locales/zh.jsonsrc/pages/group-detail.tsxsrc/pages/workforce/workforce-board.tsxsrc/pages/workforce/workforce-chat.tsx
🚧 Files skipped from review as they are similar to previous changes (9)
- src/pages/workforce/workforce-chat.tsx
- src/i18n/locales/ko.json
- src/i18n/locales/pt.json
- src/i18n/locales/de.json
- src/i18n/locales/fr.json
- src/i18n/locales/ar.json
- src/components/groups/discussion-input.tsx
- src/pages/workforce/workforce-board.tsx
- src/pages/group-detail.tsx
Code fixes (CodeRabbitAI feedback): - usePersistedBoolean: rehydrate on key change via useEffect + explicit Dispatch/SetStateAction imports (no bare React namespace) - use-logs: reset filteredConnected before reconnecting SSE - mode-switcher: replace dynamic t(labelKey) with getModeLabel() helper using literal t() calls per coding guidelines Test fixes: - discussion-input: rewrote disabled-bypass test to properly verify all disabled gating (textarea, button, expand, dialog) - mode-switcher: added tests for selection side effects (navigation + localStorage persistence + no-op on active mode + checkmark) New test files for coverage (>85% lines, >70% functions): - hitl.ts API: 13 tests covering 8 exported functions - view-mode.ts: 9 tests covering get/set functions + error handling - workforce-topbar: 6 tests (render, back, menu, title, right content) - workforce-bottom-tabs: 4 tests (render, tab count, active, navigate) - workforce-shortcuts: 5 tests (null render, n key, ? key, modifier, cleanup) - stream-badge: 4 tests (connected, disconnected, a11y, className) - use-persisted-boolean: 3 additional tests for key-change rehydration
There was a problem hiding this comment.
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 `@src/components/workforce/__tests__/workforce-bottom-tabs.test.tsx`:
- Around line 6-14: Update the router mocks to create mockNavigate through
vi.hoisted so the hoisted vi.mock factories can safely access it. Apply this
change in src/components/workforce/__tests__/workforce-bottom-tabs.test.tsx
lines 6-14, src/components/workforce/__tests__/workforce-shortcuts.test.tsx
lines 5-13, and src/components/workforce/__tests__/workforce-topbar.test.tsx
lines 6-10, preserving each test’s existing useNavigate and useLocation
behavior.
In `@src/lib/api/__tests__/hitl.test.ts`:
- Around line 29-30: Update the getBaseUrl mock in the hitl test setup to return
window.location.origin instead of a hardcoded localhost URL, while leaving
getAuthHeader unchanged.
🪄 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 Plus
Run ID: 335fdaff-8d76-4b89-bf24-d02b146ed613
📒 Files selected for processing (13)
HANDOFF.mdsrc/components/groups/__tests__/discussion-input.test.tsxsrc/components/shared/__tests__/mode-switcher.test.tsxsrc/components/shared/__tests__/view-mode.test.tssrc/components/shared/mode-switcher.tsxsrc/components/ui/__tests__/stream-badge.test.tsxsrc/components/workforce/__tests__/workforce-bottom-tabs.test.tsxsrc/components/workforce/__tests__/workforce-shortcuts.test.tsxsrc/components/workforce/__tests__/workforce-topbar.test.tsxsrc/hooks/__tests__/use-persisted-boolean.test.tssrc/hooks/use-logs.tssrc/hooks/use-persisted-boolean.tssrc/lib/api/__tests__/hitl.test.ts
🚧 Files skipped from review as they are similar to previous changes (4)
- src/hooks/use-persisted-boolean.ts
- src/components/groups/tests/discussion-input.test.tsx
- src/components/shared/mode-switcher.tsx
- src/hooks/use-logs.ts
…bles - 4 test files: replace bare const mockNavigate = vi.fn() with �i.hoisted(() => ...) so the mock is available when vi.mock factory runs (CodeRabbitAI critical feedback) - hitl.test.ts: use window.location.origin instead of hardcoded localhost:7070 per API URL coding guidelines
The config-editor-layout uses custom tab buttons with aria-selected, not Radix Tabs data-state. The E2E test was checking for data-state which doesn't exist on these elements.
This pull request refactors how the "continue discussion" action is handled in group discussions. Previously, the "Continue" action was managed by a dedicated button and composer in the
DiscussionActionsbar. Now, it is consistently handled by the context-aware input field (DiscussionInput), improving the user experience and simplifying the code. The changes also enhance test coverage and accessibility for the new behavior.Refactor: Move "Continue" action to input field
src/components/groups/discussion-actions.tsx: Removes all logic, UI, and props related to the "continue" action from the action bar; updates documentation and types accordingly. The action bar now only handles "followup" and "close" actions. [1] [2] [3] [4] [5]src/components/groups/__tests__/discussion-actions.test.tsx: Updates tests to reflect that "continue" is no longer rendered or handled by the action bar. [1] [2]Enhancement: Context-aware input for "Continue"
src/components/groups/discussion-input.tsx: Adds amodeprop to switch between "new" and "continue" modes, updating placeholder text, button label, and icon accordingly. Also adds adisabledMessageprop for improved accessibility. [1] [2] [3] [4] [5]src/components/groups/__tests__/discussion-input.test.tsx: Adds tests to verify input behavior, placeholder, and button/icon changes in "continue" mode, as well as handling of the disabled state.Consistency: Board input updates
src/components/workforce/board-input.tsx: AddsmodeanddisabledMessageprops, hides attachments in "continue" mode, and updates placeholder and accessibility labels for consistency with the group discussion input. [1] [2] [3] [4] [5]API integration:
src/hooks/use-group-discussion-stream.ts: Prepares for API support by importingstreamGroupContinue.Overall, these changes make the "continue discussion" flow more intuitive and maintainable by consolidating the UI and logic into the main input component, while improving test coverage and accessibility.
Summary by CodeRabbit