feat(ui): re-skin the chat experience (stacked on #331, #332)#333
feat(ui): re-skin the chat experience (stacked on #331, #332)#333Manushpm8 wants to merge 13 commits into
Conversation
Foundational frontend utilities for the staged chat UI/UX work: - cn(): clsx + tailwind-merge className composition so conflicting Tailwind utilities resolve deterministically. - titleCaseWords()/ACRONYMS: humanize snake_case and `__`-separated identifiers (tool and function names) into display labels, upper-casing common acronyms. - AppMotionConfig: a Motion provider that honors prefers-reduced-motion. Adds clsx, tailwind-merge, and motion. Covered 100% by unit tests; no UI behavior changes yet. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Signed-off-by: Manush Maheshwari <manushm@nvidia.com>
Adds the UI-only shared component library the chat redesign builds on: - Sources/*: source chips, list, and reference parsing (web + doc kinds). - research/*: StatusDot, ToolCallRow, and a generic tool-label engine for the live research trace. - Surface/Card, Actions/CopyButton, CollapsibleBlock, Mermaid. - MarkdownRenderer upgrade: an answer variant, superscript citations with hover popovers, KaTeX math, and Mermaid diagrams. Prod's artifact-URL handling is preserved verbatim; chart fences fall through unchanged. Adds mermaid, katex, rehype-katex, remark-math, unist-util-visit. No warehouse/predictive features are ported. Covered by unit and render tests. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Signed-off-by: Manush Maheshwari <manushm@nvidia.com>
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
WalkthroughThis PR introduces interactive clarification and plan-approval prompts, phased research traces, citation-aware Markdown and Mermaid rendering, responsive chat/panel layouts, selected-model persistence, composer controls, source utilities, and extensive supporting tests and styling. ChangesChat and research UI
Estimated code review effort: 5 (Critical) | ~120 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Warning There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure. 🔧 Biome (2.5.3)frontends/ui/src/app/globals.cssFile contains syntax errors that prevent linting: Line 189: Tailwind-specific syntax is disabled.; Line 202: Tailwind-specific syntax is disabled.; Line 206: Tailwind-specific syntax is disabled.; Line 210: Tailwind-specific syntax is disabled.; Line 214: Tailwind-specific syntax is disabled.; Line 218: Tailwind-specific syntax is disabled.; Line 222: Tailwind-specific syntax is disabled.; Line 226: Tailwind-specific syntax is disabled.; Line 230: Tailwind-specific syntax is disabled.; Line 234: Tailwind-specific syntax is disabled.; Line 242: Tailwind-specific syntax is disabled.; Line 246: Tailwind-specific syntax is disabled.; Line 250: Tailwind-specific syntax is disabled.; Line 254: Tailwind-specific syntax is disabled.; Line 259: Tailwind-specific syntax is disabled.; Line 265: Tailwind-specific syntax is disabled.; Line 269: Tailwind-specific syntax is disabled.; Line 273: Tailwind-specific syntax is disabled.; Line 281: Tailwind-specific syntax is disabled.; Line 285: Tailwind-specific syntax is disabled.; Line 289: Tailwind-specific syntax is disabled.; Line 293: Tailwind-specific syntax is disabled.; Line 297: Tailwind-specific syntax is disabled.; Line 301: Tailwind-specific syntax is disabled.; Line 305: Tailwind-specific syntax is disabled.; Line 309: Tailwind-specific syntax is disabled.; Line 313: Tailwind-specific syntax is disabled.; Line 317: Tailwind-specific syntax is disabled. Comment |
70651fc to
3c607d3
Compare
There was a problem hiding this comment.
Actionable comments posted: 27
🤖 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 `@frontends/ui/package.json`:
- Around line 33-36: Update the dependency versions in the package manifest so
react and react-dom target React 19, matching next@^16.2.6; if TypeScript React
type dependencies are present, align `@types/react` and `@types/react-dom` with
React 19 as well.
In `@frontends/ui/src/app/globals.css`:
- Line 360: Rename the keyframes dotBreathe, assistantTurnIn, thinkingDot,
thinkSweep, and answerBlockReveal to kebab-case in their `@keyframes`
declarations, then update every corresponding animation reference throughout
globals.css so each usage matches its renamed keyframe.
- Around line 510-521: Update the reduced-motion handling in globals.css for
both .thinking-dots > span (thinkingDot) and .thinking-progress::after
(thinkSweep), adding a prefers-reduced-motion: reduce override consistent with
the existing animation overrides in the file. Ensure both infinite decorative
animations are disabled or otherwise made non-animating when reduced motion is
requested.
- Line 670: Replace the deprecated word-break: break-word declaration with
overflow-wrap: anywhere in the affected style rule, adding word-break: normal or
line-break: strict only if needed to preserve the existing wrapping behavior.
In `@frontends/ui/src/features/chat/components/AgentPrompt.tsx`:
- Line 193: Update the approved-state calculation in AgentPrompt so approval
requires an actual non-empty response: retain the rejection check, but do not
treat missing or empty response values as approved. Preserve the existing
behavior for explicit approval and rejection responses.
In `@frontends/ui/src/features/chat/components/AgentResponse.tsx`:
- Around line 149-158: Update the report button flow around handleViewReport and
reportButton so loadResearchPanelTab failures render an existing KUI error
treatment with role="alert" instead of only placing the error in the title. Keep
the button disabled while loading, disable or preserve the appropriate retry
behavior after failure, and add interaction-test coverage for the failed load
and retry state.
In `@frontends/ui/src/features/chat/lib/deep-research-trace.ts`:
- Around line 129-132: Update the tool-call filtering logic in the
trace-building flow so calls with an unknown or dangling agentId are retained
through the “no owning agent” fallback, rather than only accepting calls where
agentId is absent. Add a regression test covering an unknown agentId and verify
the call is included in the generated steps.
In `@frontends/ui/src/features/chat/lib/intermediate-step-parser.ts`:
- Around line 193-199: Update getToolLabel and its caller around the
intermediate-step parser to return an explicit mapping-status indicator, such as
matched or isFallback, alongside the label. Replace the string comparison
against titleCaseWords(cleaned) with that indicator, while preserving the
existing mapped-label and generic title-casing behavior.
- Around line 181-190: Extend titleCaseWords in
frontends/ui/src/shared/lib/humanize.ts:16-26 with an optional case-preservation
parameter so acronym words remain uppercase while non-acronym words can retain
their original casing. In
frontends/ui/src/features/chat/lib/intermediate-step-parser.ts:181-190, replace
the inline acronym-mapping logic with titleCaseWords configured for case
preservation, preserving the existing hyphen splitting and joining behavior.
In `@frontends/ui/src/features/chat/store.ts`:
- Around line 2406-2418: Restrict hydrateDeepResearchFromMessage to
conversations owned by currentUserId before findInConversation inspects messages
or hydration data. Update the fallback over conversations to exclude other
users’ conversations while preserving the current-conversation lookup, and add a
regression test proving cross-user persisted conversations are not hydrated.
In `@frontends/ui/src/features/layout/components/AgentCard.tsx`:
- Around line 68-79: The dedupeToolCalls function currently collapses distinct
unrecognized inputs and fails to replace running calls with error results. Make
the deduplication key uniquely represent unknown inputs, and update replacement
logic so a newer terminal error or complete call supersedes a non-terminal
existing call while preserving the established status behavior. Add tests
covering distinct unknown inputs and a same-argument running-to-error
transition.
In `@frontends/ui/src/features/layout/components/AgentsTab.tsx`:
- Around line 64-68: Update the count badge rendering in AgentsTab to use the
number of top-level deep research thinking steps when runningCount is zero,
rather than deepResearchAgents.length. Reuse deepResearchToThinkingSteps and its
isTopLevel marker so orphan tool calls display an accurate nonzero count while
preserving the existing running-agent count behavior.
In `@frontends/ui/src/features/layout/components/ChatArea.tsx`:
- Line 219: Restore the file-card workflow in ChatArea by implementing
handleFileRetry and reconnecting file message rows to the existing retry,
cancel, and delete handlers. Update the rendering around the file status row and
the handleFileRetry callback so failed and pending files expose actionable
controls, reusing the established file-card components and handlers rather than
leaving inert rows.
In `@frontends/ui/src/features/layout/components/DataConnectionCard.tsx`:
- Around line 133-144: Add tests for the DataConnectionCard/DataConnectionsTab
icon rendering introduced by SourceKindIcon and getDataSourceKind. Cover web and
document sources, and verify the rendered icon styling for enabled and disabled
states, using the existing component test patterns and stable accessible or test
identifiers.
In `@frontends/ui/src/features/layout/components/DataSourcesPanel.spec.tsx`:
- Around line 233-237: Update the closed-state assertion in the DataSourcesPanel
test to target the panel wrapper specifically, rather than any descendant
matching aria-hidden="true". Verify that the wrapper itself has
aria-hidden="true" (and preserve the existing render setup) so decorative icons
cannot satisfy the assertion.
In `@frontends/ui/src/features/layout/components/ReportTab.tsx`:
- Around line 121-147: Bound the expanded generated-files list in ReportTab’s
showFiles rendering so it cannot grow beyond the report panel and hide later
content or the export footer. Apply the existing scroll/overflow styling to the
Flex containing deepResearchFiles.map while preserving the current toggle
behavior and accessible button attributes.
In `@frontends/ui/src/features/layout/components/SessionsPanel.tsx`:
- Around line 201-216: Update closeSearch to restore focus to the “Search
sessions” trigger after closing and unmounting the input, including Escape and
empty-query blur paths. Add or forward a ref through the search trigger’s NavRow
(or use a focusable button) and focus it after setSearchOpen(false), while
preserving the existing query clearing behavior.
In `@frontends/ui/src/shared/components/CollapsibleBlock/CollapsibleBlock.tsx`:
- Around line 36-90: Add a dedicated spec for the CollapsibleBlock component,
covering the collapsible header click invoking onOpenChange with the toggled
value, aria-expanded reflecting open state, and the non-collapsible mode always
rendering children without a header button. Place the tests alongside the
component and exercise the header button versus static div behavior directly.
In `@frontends/ui/src/shared/components/MarkdownRenderer/Citation.spec.tsx`:
- Around line 40-44: Update the non-numeric Citation test to assert that the
visible bracketed fallback text, such as “[NaN]”, is rendered, while retaining
the existing assertions that no link or source chip appears.
In `@frontends/ui/src/shared/components/MarkdownRenderer/Citation.tsx`:
- Around line 31-45: Update the citation control in the component rendering the
`chip` so URL-less sources use a keyboard-focusable button or span instead of an
anchor without `href`, while preserving the anchor behavior for sources with
`src.url`. Keep the existing hover/focus tooltip handlers and accessible
labeling for both variants, and retain link target/rel attributes only when a
URL exists.
In `@frontends/ui/src/shared/components/Mermaid/MermaidBlock.tsx`:
- Around line 183-225: Update the fullscreen branch in the MermaidBlock
component to use the existing KUI modal/dialog component and its
focus-management behavior instead of rendering only a fixed overlay. Ensure
fullscreen is announced as a modal, traps focus within the dialog, restores
focus when closed, supports the existing Escape behavior, and keeps the zoom
controls and Mermaid content inside the dialog.
- Around line 132-148: Update the wheel handler in the MermaidBlock useEffect to
intercept only explicit diagram-zoom gestures, such as wheel events with Ctrl or
Command pressed, while preserving browser-level zoom behavior and normal page
scrolling. Check whether scaling can actually change before calling
preventDefault(), and keep the existing anchor and setScale behavior for valid
zoom events. Ensure the interaction remains accessible and does not block
unrelated scrolling.
In `@frontends/ui/src/shared/components/research/StatusDot.tsx`:
- Around line 15-20: The StatusDot component hides the node state from assistive
technologies without providing an accessible equivalent. Update StatusDot to
include visually hidden text derived from state (running, done, error, etc.)
while keeping the decorative visual dot hidden, so consumers such as ToolCallRow
expose the status to screen readers without requiring additional changes.
In `@frontends/ui/src/shared/components/Sources/parse-references.ts`:
- Around line 125-145: Update renumberOrderedLists so counter resets when a
non-list prose block begins a separate ordered list, not only after headings.
Preserve numbering across nested bullets and other continuation lines, while
allowing an intentional top-level “1.” after prose to remain the start of a new
list.
- Around line 12-13: Unify the references-heading grammar used by
splitReferences and stripTrailingReferences by extracting and reusing a shared
matcher that accepts bold References/Sources and Markdown headings at levels
1–6. Update the splitReferences parsing path to use this matcher so every block
removable by stripTrailingReferences also produces SourceRef entries, and add
coverage for all accepted heading variants.
In `@frontends/ui/src/shared/components/Sources/source-utils.ts`:
- Around line 33-35: Update sourceLabel so prettyDomain is used only for web
sources; for document sources, preserve ref or derive its path basename and fall
back to “Document” when absent. Add regression coverage for nested paths such as
folder/report.pdf and scheme-like document references, ensuring they are not
domain-normalized.
In `@frontends/ui/src/shared/components/Sources/SourceList.tsx`:
- Around line 29-50: Update the source rendering in the sources map to make any
URL-bearing source clickable, including when s.label equals prettyDomain(s.url).
Render s.label itself as the anchor in that case, while preserving the separate
domain link only when it differs from the label; add a regression test covering
a URL source whose label matches its domain.
🪄 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: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Enterprise
Run ID: 9a13f411-99bb-435e-b5ff-66effa4d62b1
⛔ Files ignored due to path filters (1)
frontends/ui/package-lock.jsonis excluded by!**/package-lock.json
📒 Files selected for processing (114)
frontends/ui/package.jsonfrontends/ui/src/adapters/api/websocket-client.tsfrontends/ui/src/app/globals.cssfrontends/ui/src/app/page.tsxfrontends/ui/src/app/providers.tsxfrontends/ui/src/features/chat/components/AgentPrompt.spec.tsxfrontends/ui/src/features/chat/components/AgentPrompt.tsxfrontends/ui/src/features/chat/components/AgentResponse.spec.tsxfrontends/ui/src/features/chat/components/AgentResponse.tsxfrontends/ui/src/features/chat/components/ChatThinking.spec.tsxfrontends/ui/src/features/chat/components/ChatThinking.tsxfrontends/ui/src/features/chat/components/DeepResearchBanner.tsxfrontends/ui/src/features/chat/components/ErrorBanner.tsxfrontends/ui/src/features/chat/components/FileUploadBanner.tsxfrontends/ui/src/features/chat/components/NoSourcesBanner.tsxfrontends/ui/src/features/chat/components/UserMessage.tsxfrontends/ui/src/features/chat/components/index.tsfrontends/ui/src/features/chat/hooks/use-websocket-chat.tsfrontends/ui/src/features/chat/lib/deep-research-trace.spec.tsfrontends/ui/src/features/chat/lib/deep-research-trace.tsfrontends/ui/src/features/chat/lib/intermediate-step-parser.spec.tsfrontends/ui/src/features/chat/lib/intermediate-step-parser.tsfrontends/ui/src/features/chat/lib/session-activity.tsfrontends/ui/src/features/chat/store.spec.tsfrontends/ui/src/features/chat/store.tsfrontends/ui/src/features/chat/types.tsfrontends/ui/src/features/layout/components/AgentCard.spec.tsxfrontends/ui/src/features/layout/components/AgentCard.tsxfrontends/ui/src/features/layout/components/AgentsTab.spec.tsxfrontends/ui/src/features/layout/components/AgentsTab.tsxfrontends/ui/src/features/layout/components/AppBar.spec.tsxfrontends/ui/src/features/layout/components/AppBar.tsxfrontends/ui/src/features/layout/components/ChatArea.autoscroll.spec.tsxfrontends/ui/src/features/layout/components/ChatArea.spec.tsxfrontends/ui/src/features/layout/components/ChatArea.tsxfrontends/ui/src/features/layout/components/CitationCard.spec.tsxfrontends/ui/src/features/layout/components/CitationCard.tsxfrontends/ui/src/features/layout/components/DataConnectionCard.tsxfrontends/ui/src/features/layout/components/DataConnectionsTab.spec.tsxfrontends/ui/src/features/layout/components/DataConnectionsTab.tsxfrontends/ui/src/features/layout/components/DataSourcesPanel.spec.tsxfrontends/ui/src/features/layout/components/DataSourcesPanel.tsxfrontends/ui/src/features/layout/components/FileCard.tsxfrontends/ui/src/features/layout/components/FileSourceCard.spec.tsxfrontends/ui/src/features/layout/components/FileSourceCard.tsxfrontends/ui/src/features/layout/components/FileSourcesTab.spec.tsxfrontends/ui/src/features/layout/components/FileSourcesTab.tsxfrontends/ui/src/features/layout/components/InputArea.tsxfrontends/ui/src/features/layout/components/MainLayout.spec.tsxfrontends/ui/src/features/layout/components/MainLayout.tsxfrontends/ui/src/features/layout/components/ReportCard.spec.tsxfrontends/ui/src/features/layout/components/ReportCard.tsxfrontends/ui/src/features/layout/components/ReportTab.tsxfrontends/ui/src/features/layout/components/ResearchPanel.spec.tsxfrontends/ui/src/features/layout/components/ResearchPanel.tsxfrontends/ui/src/features/layout/components/SessionsPanel.spec.tsxfrontends/ui/src/features/layout/components/SessionsPanel.tsxfrontends/ui/src/features/layout/components/SettingsPanel.spec.tsxfrontends/ui/src/features/layout/components/SettingsPanel.tsxfrontends/ui/src/features/layout/components/SourceCard.spec.tsxfrontends/ui/src/features/layout/components/SourceCard.tsxfrontends/ui/src/features/layout/components/TaskCard.spec.tsxfrontends/ui/src/features/layout/components/TaskCard.tsxfrontends/ui/src/features/layout/components/TasksTab.spec.tsxfrontends/ui/src/features/layout/components/TasksTab.tsxfrontends/ui/src/features/layout/components/ThinkingTab.spec.tsxfrontends/ui/src/features/layout/components/ThinkingTab.tsxfrontends/ui/src/features/layout/components/ThoughtCard.spec.tsxfrontends/ui/src/features/layout/components/ThoughtCard.tsxfrontends/ui/src/features/layout/components/index.tsfrontends/ui/src/features/layout/data-sources.spec.tsfrontends/ui/src/features/layout/data-sources.tsfrontends/ui/src/features/layout/index.tsfrontends/ui/src/features/layout/store.spec.tsfrontends/ui/src/features/layout/store.tsfrontends/ui/src/features/layout/types.tsfrontends/ui/src/shared/components/Actions/CopyButton.spec.tsxfrontends/ui/src/shared/components/Actions/CopyButton.tsxfrontends/ui/src/shared/components/CollapsibleBlock/CollapsibleBlock.tsxfrontends/ui/src/shared/components/CollapsibleBlock/index.tsfrontends/ui/src/shared/components/MarkdownRenderer/Citation.spec.tsxfrontends/ui/src/shared/components/MarkdownRenderer/Citation.tsxfrontends/ui/src/shared/components/MarkdownRenderer/MarkdownRenderer.spec.tsxfrontends/ui/src/shared/components/MarkdownRenderer/MarkdownRenderer.tsxfrontends/ui/src/shared/components/MarkdownRenderer/rehype-citations.spec.tsfrontends/ui/src/shared/components/MarkdownRenderer/rehype-citations.tsfrontends/ui/src/shared/components/MarkdownRenderer/types.tsfrontends/ui/src/shared/components/Mermaid/MermaidBlock.spec.tsxfrontends/ui/src/shared/components/Mermaid/MermaidBlock.tsxfrontends/ui/src/shared/components/Mermaid/index.tsfrontends/ui/src/shared/components/Sources/SourceKindIcon.tsxfrontends/ui/src/shared/components/Sources/SourceList.tsxfrontends/ui/src/shared/components/Sources/SourceStrip.spec.tsxfrontends/ui/src/shared/components/Sources/SourceStrip.tsxfrontends/ui/src/shared/components/Sources/parse-references.spec.tsfrontends/ui/src/shared/components/Sources/parse-references.tsfrontends/ui/src/shared/components/Sources/source-utils.spec.tsfrontends/ui/src/shared/components/Sources/source-utils.tsfrontends/ui/src/shared/components/Sources/types.tsfrontends/ui/src/shared/components/Surface/Card.spec.tsxfrontends/ui/src/shared/components/Surface/Card.tsxfrontends/ui/src/shared/components/research/StatusDot.tsxfrontends/ui/src/shared/components/research/ToolCallRow.tsxfrontends/ui/src/shared/components/research/index.tsfrontends/ui/src/shared/components/research/research-labels.spec.tsfrontends/ui/src/shared/components/research/research-labels.tsfrontends/ui/src/shared/lib/cn.spec.tsfrontends/ui/src/shared/lib/cn.tsfrontends/ui/src/shared/lib/humanize.spec.tsfrontends/ui/src/shared/lib/humanize.tsfrontends/ui/src/shared/lib/motion.spec.tsxfrontends/ui/src/shared/lib/motion.tsxfrontends/ui/src/shared/lib/scroll.spec.tsfrontends/ui/src/shared/lib/scroll.ts
💤 Files with no reviewable changes (14)
- frontends/ui/src/features/chat/components/ErrorBanner.tsx
- frontends/ui/src/features/layout/components/SettingsPanel.spec.tsx
- frontends/ui/src/features/chat/components/NoSourcesBanner.tsx
- frontends/ui/src/features/layout/components/DataConnectionsTab.spec.tsx
- frontends/ui/src/features/chat/components/FileUploadBanner.tsx
- frontends/ui/src/features/layout/components/ResearchPanel.spec.tsx
- frontends/ui/src/features/layout/components/ReportCard.spec.tsx
- frontends/ui/src/features/layout/components/FileSourcesTab.spec.tsx
- frontends/ui/src/features/chat/components/DeepResearchBanner.tsx
- frontends/ui/src/features/chat/components/index.ts
- frontends/ui/src/features/layout/components/TasksTab.spec.tsx
- frontends/ui/src/features/layout/components/SourceCard.spec.tsx
- frontends/ui/src/features/layout/components/CitationCard.spec.tsx
- frontends/ui/src/features/layout/components/index.ts
📜 Review details
🧰 Additional context used
📓 Path-based instructions (3)
frontends/ui/**/*.{js,ts,jsx,tsx,vue}
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Run npm lint, type-check, and build validation for UI changes in frontends/ui
Files:
frontends/ui/src/shared/lib/cn.tsfrontends/ui/src/shared/lib/scroll.spec.tsfrontends/ui/src/features/layout/index.tsfrontends/ui/src/shared/lib/motion.tsxfrontends/ui/src/shared/components/Mermaid/index.tsfrontends/ui/src/app/providers.tsxfrontends/ui/src/shared/components/research/index.tsfrontends/ui/src/shared/components/research/StatusDot.tsxfrontends/ui/src/shared/components/research/ToolCallRow.tsxfrontends/ui/src/shared/lib/motion.spec.tsxfrontends/ui/src/adapters/api/websocket-client.tsfrontends/ui/src/shared/components/MarkdownRenderer/types.tsfrontends/ui/src/features/layout/data-sources.spec.tsfrontends/ui/src/shared/components/CollapsibleBlock/CollapsibleBlock.tsxfrontends/ui/src/shared/components/CollapsibleBlock/index.tsfrontends/ui/src/shared/components/MarkdownRenderer/rehype-citations.spec.tsfrontends/ui/src/features/layout/components/SettingsPanel.tsxfrontends/ui/src/shared/lib/cn.spec.tsfrontends/ui/src/features/layout/components/FileCard.tsxfrontends/ui/src/features/layout/components/TaskCard.tsxfrontends/ui/src/shared/components/Sources/SourceList.tsxfrontends/ui/src/shared/lib/humanize.spec.tsfrontends/ui/src/shared/components/Mermaid/MermaidBlock.spec.tsxfrontends/ui/src/app/page.tsxfrontends/ui/src/shared/components/Sources/SourceKindIcon.tsxfrontends/ui/src/shared/components/MarkdownRenderer/rehype-citations.tsfrontends/ui/src/features/layout/components/CitationCard.tsxfrontends/ui/src/features/layout/components/DataSourcesPanel.spec.tsxfrontends/ui/src/shared/components/research/research-labels.spec.tsfrontends/ui/src/shared/lib/humanize.tsfrontends/ui/src/shared/components/Sources/source-utils.tsfrontends/ui/src/shared/components/Actions/CopyButton.spec.tsxfrontends/ui/src/shared/components/Actions/CopyButton.tsxfrontends/ui/src/features/layout/store.spec.tsfrontends/ui/src/shared/lib/scroll.tsfrontends/ui/src/features/chat/lib/session-activity.tsfrontends/ui/src/features/chat/components/UserMessage.tsxfrontends/ui/src/features/layout/components/DataConnectionCard.tsxfrontends/ui/src/shared/components/MarkdownRenderer/Citation.spec.tsxfrontends/ui/src/shared/components/MarkdownRenderer/MarkdownRenderer.spec.tsxfrontends/ui/src/shared/components/MarkdownRenderer/Citation.tsxfrontends/ui/src/features/layout/components/ChatArea.autoscroll.spec.tsxfrontends/ui/src/features/layout/components/AgentsTab.tsxfrontends/ui/src/shared/components/Sources/source-utils.spec.tsfrontends/ui/src/shared/components/Sources/types.tsfrontends/ui/src/shared/components/Surface/Card.tsxfrontends/ui/src/features/layout/components/DataConnectionsTab.tsxfrontends/ui/src/features/layout/components/AgentsTab.spec.tsxfrontends/ui/src/features/chat/lib/deep-research-trace.tsfrontends/ui/src/shared/components/Surface/Card.spec.tsxfrontends/ui/src/shared/components/Sources/parse-references.spec.tsfrontends/ui/src/shared/components/Sources/SourceStrip.tsxfrontends/ui/src/features/chat/lib/intermediate-step-parser.spec.tsfrontends/ui/src/features/chat/store.spec.tsfrontends/ui/src/features/layout/components/FileSourceCard.spec.tsxfrontends/ui/src/shared/components/Sources/parse-references.tsfrontends/ui/src/features/layout/data-sources.tsfrontends/ui/src/features/layout/components/TasksTab.tsxfrontends/ui/src/shared/components/Mermaid/MermaidBlock.tsxfrontends/ui/src/features/layout/components/SourceCard.tsxfrontends/ui/src/features/layout/types.tsfrontends/ui/src/shared/components/research/research-labels.tsfrontends/ui/src/features/chat/types.tsfrontends/ui/src/features/layout/components/ThinkingTab.tsxfrontends/ui/src/features/layout/components/TaskCard.spec.tsxfrontends/ui/src/features/layout/components/ThoughtCard.tsxfrontends/ui/src/features/layout/store.tsfrontends/ui/src/features/chat/components/AgentResponse.tsxfrontends/ui/src/features/chat/components/ChatThinking.spec.tsxfrontends/ui/src/features/layout/components/FileSourceCard.tsxfrontends/ui/src/features/layout/components/ReportCard.tsxfrontends/ui/src/features/layout/components/ReportTab.tsxfrontends/ui/src/features/layout/components/ThinkingTab.spec.tsxfrontends/ui/src/features/chat/lib/intermediate-step-parser.tsfrontends/ui/src/features/chat/hooks/use-websocket-chat.tsfrontends/ui/src/features/layout/components/MainLayout.spec.tsxfrontends/ui/src/features/layout/components/DataSourcesPanel.tsxfrontends/ui/src/features/layout/components/InputArea.tsxfrontends/ui/src/features/layout/components/AgentCard.spec.tsxfrontends/ui/src/features/chat/lib/deep-research-trace.spec.tsfrontends/ui/src/features/layout/components/AgentCard.tsxfrontends/ui/src/features/layout/components/MainLayout.tsxfrontends/ui/src/shared/components/MarkdownRenderer/MarkdownRenderer.tsxfrontends/ui/src/features/chat/components/ChatThinking.tsxfrontends/ui/src/features/layout/components/ChatArea.spec.tsxfrontends/ui/src/features/chat/components/AgentPrompt.tsxfrontends/ui/src/features/chat/components/AgentResponse.spec.tsxfrontends/ui/src/features/chat/components/AgentPrompt.spec.tsxfrontends/ui/src/features/layout/components/AppBar.tsxfrontends/ui/src/features/layout/components/ThoughtCard.spec.tsxfrontends/ui/src/shared/components/Sources/SourceStrip.spec.tsxfrontends/ui/src/features/layout/components/AppBar.spec.tsxfrontends/ui/src/features/layout/components/SessionsPanel.tsxfrontends/ui/src/features/layout/components/FileSourcesTab.tsxfrontends/ui/src/features/layout/components/SessionsPanel.spec.tsxfrontends/ui/src/features/layout/components/ChatArea.tsxfrontends/ui/src/features/chat/store.tsfrontends/ui/src/features/layout/components/ResearchPanel.tsx
frontends/ui/**/*.{ts,tsx,jsx,js}
📄 CodeRabbit inference engine (AGENTS.md)
frontends/ui/**/*.{ts,tsx,jsx,js}: The UI is built with Next.js / React / TypeScript / Tailwind with KUI components; reuse existing KUI components and visual patterns rather than introducing new ones
Validate UI-affecting changes with npm run lint, npm run type-check, and npm run test:ci, and include a screenshot for visible changes
Files:
frontends/ui/src/shared/lib/cn.tsfrontends/ui/src/shared/lib/scroll.spec.tsfrontends/ui/src/features/layout/index.tsfrontends/ui/src/shared/lib/motion.tsxfrontends/ui/src/shared/components/Mermaid/index.tsfrontends/ui/src/app/providers.tsxfrontends/ui/src/shared/components/research/index.tsfrontends/ui/src/shared/components/research/StatusDot.tsxfrontends/ui/src/shared/components/research/ToolCallRow.tsxfrontends/ui/src/shared/lib/motion.spec.tsxfrontends/ui/src/adapters/api/websocket-client.tsfrontends/ui/src/shared/components/MarkdownRenderer/types.tsfrontends/ui/src/features/layout/data-sources.spec.tsfrontends/ui/src/shared/components/CollapsibleBlock/CollapsibleBlock.tsxfrontends/ui/src/shared/components/CollapsibleBlock/index.tsfrontends/ui/src/shared/components/MarkdownRenderer/rehype-citations.spec.tsfrontends/ui/src/features/layout/components/SettingsPanel.tsxfrontends/ui/src/shared/lib/cn.spec.tsfrontends/ui/src/features/layout/components/FileCard.tsxfrontends/ui/src/features/layout/components/TaskCard.tsxfrontends/ui/src/shared/components/Sources/SourceList.tsxfrontends/ui/src/shared/lib/humanize.spec.tsfrontends/ui/src/shared/components/Mermaid/MermaidBlock.spec.tsxfrontends/ui/src/app/page.tsxfrontends/ui/src/shared/components/Sources/SourceKindIcon.tsxfrontends/ui/src/shared/components/MarkdownRenderer/rehype-citations.tsfrontends/ui/src/features/layout/components/CitationCard.tsxfrontends/ui/src/features/layout/components/DataSourcesPanel.spec.tsxfrontends/ui/src/shared/components/research/research-labels.spec.tsfrontends/ui/src/shared/lib/humanize.tsfrontends/ui/src/shared/components/Sources/source-utils.tsfrontends/ui/src/shared/components/Actions/CopyButton.spec.tsxfrontends/ui/src/shared/components/Actions/CopyButton.tsxfrontends/ui/src/features/layout/store.spec.tsfrontends/ui/src/shared/lib/scroll.tsfrontends/ui/src/features/chat/lib/session-activity.tsfrontends/ui/src/features/chat/components/UserMessage.tsxfrontends/ui/src/features/layout/components/DataConnectionCard.tsxfrontends/ui/src/shared/components/MarkdownRenderer/Citation.spec.tsxfrontends/ui/src/shared/components/MarkdownRenderer/MarkdownRenderer.spec.tsxfrontends/ui/src/shared/components/MarkdownRenderer/Citation.tsxfrontends/ui/src/features/layout/components/ChatArea.autoscroll.spec.tsxfrontends/ui/src/features/layout/components/AgentsTab.tsxfrontends/ui/src/shared/components/Sources/source-utils.spec.tsfrontends/ui/src/shared/components/Sources/types.tsfrontends/ui/src/shared/components/Surface/Card.tsxfrontends/ui/src/features/layout/components/DataConnectionsTab.tsxfrontends/ui/src/features/layout/components/AgentsTab.spec.tsxfrontends/ui/src/features/chat/lib/deep-research-trace.tsfrontends/ui/src/shared/components/Surface/Card.spec.tsxfrontends/ui/src/shared/components/Sources/parse-references.spec.tsfrontends/ui/src/shared/components/Sources/SourceStrip.tsxfrontends/ui/src/features/chat/lib/intermediate-step-parser.spec.tsfrontends/ui/src/features/chat/store.spec.tsfrontends/ui/src/features/layout/components/FileSourceCard.spec.tsxfrontends/ui/src/shared/components/Sources/parse-references.tsfrontends/ui/src/features/layout/data-sources.tsfrontends/ui/src/features/layout/components/TasksTab.tsxfrontends/ui/src/shared/components/Mermaid/MermaidBlock.tsxfrontends/ui/src/features/layout/components/SourceCard.tsxfrontends/ui/src/features/layout/types.tsfrontends/ui/src/shared/components/research/research-labels.tsfrontends/ui/src/features/chat/types.tsfrontends/ui/src/features/layout/components/ThinkingTab.tsxfrontends/ui/src/features/layout/components/TaskCard.spec.tsxfrontends/ui/src/features/layout/components/ThoughtCard.tsxfrontends/ui/src/features/layout/store.tsfrontends/ui/src/features/chat/components/AgentResponse.tsxfrontends/ui/src/features/chat/components/ChatThinking.spec.tsxfrontends/ui/src/features/layout/components/FileSourceCard.tsxfrontends/ui/src/features/layout/components/ReportCard.tsxfrontends/ui/src/features/layout/components/ReportTab.tsxfrontends/ui/src/features/layout/components/ThinkingTab.spec.tsxfrontends/ui/src/features/chat/lib/intermediate-step-parser.tsfrontends/ui/src/features/chat/hooks/use-websocket-chat.tsfrontends/ui/src/features/layout/components/MainLayout.spec.tsxfrontends/ui/src/features/layout/components/DataSourcesPanel.tsxfrontends/ui/src/features/layout/components/InputArea.tsxfrontends/ui/src/features/layout/components/AgentCard.spec.tsxfrontends/ui/src/features/chat/lib/deep-research-trace.spec.tsfrontends/ui/src/features/layout/components/AgentCard.tsxfrontends/ui/src/features/layout/components/MainLayout.tsxfrontends/ui/src/shared/components/MarkdownRenderer/MarkdownRenderer.tsxfrontends/ui/src/features/chat/components/ChatThinking.tsxfrontends/ui/src/features/layout/components/ChatArea.spec.tsxfrontends/ui/src/features/chat/components/AgentPrompt.tsxfrontends/ui/src/features/chat/components/AgentResponse.spec.tsxfrontends/ui/src/features/chat/components/AgentPrompt.spec.tsxfrontends/ui/src/features/layout/components/AppBar.tsxfrontends/ui/src/features/layout/components/ThoughtCard.spec.tsxfrontends/ui/src/shared/components/Sources/SourceStrip.spec.tsxfrontends/ui/src/features/layout/components/AppBar.spec.tsxfrontends/ui/src/features/layout/components/SessionsPanel.tsxfrontends/ui/src/features/layout/components/FileSourcesTab.tsxfrontends/ui/src/features/layout/components/SessionsPanel.spec.tsxfrontends/ui/src/features/layout/components/ChatArea.tsxfrontends/ui/src/features/chat/store.tsfrontends/ui/src/features/layout/components/ResearchPanel.tsx
frontends/ui/**/*
⚙️ CodeRabbit configuration file
frontends/ui/**/*: Review UI changes for strict TypeScript behavior, API contract alignment, auth/session handling, accessible controls,
resilient loading and error states, and report/chat state consistency. Prefer existing UI patterns and require tests
for changed user-visible workflows.
Files:
frontends/ui/src/shared/lib/cn.tsfrontends/ui/src/shared/lib/scroll.spec.tsfrontends/ui/src/features/layout/index.tsfrontends/ui/src/shared/lib/motion.tsxfrontends/ui/src/shared/components/Mermaid/index.tsfrontends/ui/src/app/providers.tsxfrontends/ui/src/shared/components/research/index.tsfrontends/ui/src/shared/components/research/StatusDot.tsxfrontends/ui/src/shared/components/research/ToolCallRow.tsxfrontends/ui/src/shared/lib/motion.spec.tsxfrontends/ui/src/adapters/api/websocket-client.tsfrontends/ui/src/shared/components/MarkdownRenderer/types.tsfrontends/ui/src/features/layout/data-sources.spec.tsfrontends/ui/src/shared/components/CollapsibleBlock/CollapsibleBlock.tsxfrontends/ui/src/shared/components/CollapsibleBlock/index.tsfrontends/ui/src/shared/components/MarkdownRenderer/rehype-citations.spec.tsfrontends/ui/src/features/layout/components/SettingsPanel.tsxfrontends/ui/src/shared/lib/cn.spec.tsfrontends/ui/src/features/layout/components/FileCard.tsxfrontends/ui/src/features/layout/components/TaskCard.tsxfrontends/ui/src/shared/components/Sources/SourceList.tsxfrontends/ui/src/shared/lib/humanize.spec.tsfrontends/ui/src/shared/components/Mermaid/MermaidBlock.spec.tsxfrontends/ui/src/app/page.tsxfrontends/ui/src/shared/components/Sources/SourceKindIcon.tsxfrontends/ui/src/shared/components/MarkdownRenderer/rehype-citations.tsfrontends/ui/package.jsonfrontends/ui/src/features/layout/components/CitationCard.tsxfrontends/ui/src/features/layout/components/DataSourcesPanel.spec.tsxfrontends/ui/src/shared/components/research/research-labels.spec.tsfrontends/ui/src/shared/lib/humanize.tsfrontends/ui/src/shared/components/Sources/source-utils.tsfrontends/ui/src/shared/components/Actions/CopyButton.spec.tsxfrontends/ui/src/shared/components/Actions/CopyButton.tsxfrontends/ui/src/features/layout/store.spec.tsfrontends/ui/src/shared/lib/scroll.tsfrontends/ui/src/features/chat/lib/session-activity.tsfrontends/ui/src/features/chat/components/UserMessage.tsxfrontends/ui/src/features/layout/components/DataConnectionCard.tsxfrontends/ui/src/shared/components/MarkdownRenderer/Citation.spec.tsxfrontends/ui/src/shared/components/MarkdownRenderer/MarkdownRenderer.spec.tsxfrontends/ui/src/shared/components/MarkdownRenderer/Citation.tsxfrontends/ui/src/features/layout/components/ChatArea.autoscroll.spec.tsxfrontends/ui/src/features/layout/components/AgentsTab.tsxfrontends/ui/src/shared/components/Sources/source-utils.spec.tsfrontends/ui/src/shared/components/Sources/types.tsfrontends/ui/src/shared/components/Surface/Card.tsxfrontends/ui/src/features/layout/components/DataConnectionsTab.tsxfrontends/ui/src/features/layout/components/AgentsTab.spec.tsxfrontends/ui/src/features/chat/lib/deep-research-trace.tsfrontends/ui/src/shared/components/Surface/Card.spec.tsxfrontends/ui/src/shared/components/Sources/parse-references.spec.tsfrontends/ui/src/shared/components/Sources/SourceStrip.tsxfrontends/ui/src/features/chat/lib/intermediate-step-parser.spec.tsfrontends/ui/src/features/chat/store.spec.tsfrontends/ui/src/features/layout/components/FileSourceCard.spec.tsxfrontends/ui/src/shared/components/Sources/parse-references.tsfrontends/ui/src/features/layout/data-sources.tsfrontends/ui/src/features/layout/components/TasksTab.tsxfrontends/ui/src/shared/components/Mermaid/MermaidBlock.tsxfrontends/ui/src/features/layout/components/SourceCard.tsxfrontends/ui/src/features/layout/types.tsfrontends/ui/src/shared/components/research/research-labels.tsfrontends/ui/src/features/chat/types.tsfrontends/ui/src/features/layout/components/ThinkingTab.tsxfrontends/ui/src/features/layout/components/TaskCard.spec.tsxfrontends/ui/src/features/layout/components/ThoughtCard.tsxfrontends/ui/src/features/layout/store.tsfrontends/ui/src/features/chat/components/AgentResponse.tsxfrontends/ui/src/features/chat/components/ChatThinking.spec.tsxfrontends/ui/src/features/layout/components/FileSourceCard.tsxfrontends/ui/src/features/layout/components/ReportCard.tsxfrontends/ui/src/features/layout/components/ReportTab.tsxfrontends/ui/src/features/layout/components/ThinkingTab.spec.tsxfrontends/ui/src/features/chat/lib/intermediate-step-parser.tsfrontends/ui/src/features/chat/hooks/use-websocket-chat.tsfrontends/ui/src/features/layout/components/MainLayout.spec.tsxfrontends/ui/src/features/layout/components/DataSourcesPanel.tsxfrontends/ui/src/features/layout/components/InputArea.tsxfrontends/ui/src/features/layout/components/AgentCard.spec.tsxfrontends/ui/src/features/chat/lib/deep-research-trace.spec.tsfrontends/ui/src/features/layout/components/AgentCard.tsxfrontends/ui/src/features/layout/components/MainLayout.tsxfrontends/ui/src/shared/components/MarkdownRenderer/MarkdownRenderer.tsxfrontends/ui/src/features/chat/components/ChatThinking.tsxfrontends/ui/src/features/layout/components/ChatArea.spec.tsxfrontends/ui/src/features/chat/components/AgentPrompt.tsxfrontends/ui/src/features/chat/components/AgentResponse.spec.tsxfrontends/ui/src/features/chat/components/AgentPrompt.spec.tsxfrontends/ui/src/features/layout/components/AppBar.tsxfrontends/ui/src/features/layout/components/ThoughtCard.spec.tsxfrontends/ui/src/shared/components/Sources/SourceStrip.spec.tsxfrontends/ui/src/features/layout/components/AppBar.spec.tsxfrontends/ui/src/features/layout/components/SessionsPanel.tsxfrontends/ui/src/features/layout/components/FileSourcesTab.tsxfrontends/ui/src/features/layout/components/SessionsPanel.spec.tsxfrontends/ui/src/features/layout/components/ChatArea.tsxfrontends/ui/src/features/chat/store.tsfrontends/ui/src/features/layout/components/ResearchPanel.tsxfrontends/ui/src/app/globals.css
🪛 ast-grep (0.44.1)
frontends/ui/src/shared/components/Mermaid/MermaidBlock.tsx
[warning] 251-251: Usage of dangerouslySetInnerHTML detected. This bypasses React's built-in XSS protection. Always sanitize HTML content using libraries like DOMPurify before injecting it into the DOM to prevent XSS attacks.
Context: dangerouslySetInnerHTML
Note: [CWE-79] Improper Neutralization of Input During Web Page Generation
(react-unsafe-html-injection)
frontends/ui/src/shared/components/research/research-labels.ts
[warning] 167-167: Regular expression constructed from variable input detected. This can lead to Regular Expression Denial of Service (ReDoS) attacks if the variable contains malicious patterns. Use libraries like 'recheck' to validate regex safety or use static patterns.
Context: new RegExp(["']${escapedKey}["']\\s*:\\s*"((?:\\\\.|[^"\\\\])*)")
Note: [CWE-1333] Inefficient Regular Expression Complexity
(regexp-from-variable)
[warning] 172-172: Regular expression constructed from variable input detected. This can lead to Regular Expression Denial of Service (ReDoS) attacks if the variable contains malicious patterns. Use libraries like 'recheck' to validate regex safety or use static patterns.
Context: new RegExp(["']${escapedKey}["']\\s*:\\s*'((?:\\\\.|[^'\\\\])*)')
Note: [CWE-1333] Inefficient Regular Expression Complexity
(regexp-from-variable)
🪛 OpenGrep (1.25.0)
frontends/ui/src/shared/components/MarkdownRenderer/rehype-citations.ts
[ERROR] 24-24: Dynamic command passed to child_process.exec/execSync. Use child_process.execFile or spawn with an argument array instead.
(coderabbit.command-injection.exec-js)
frontends/ui/src/shared/components/Mermaid/MermaidBlock.tsx
[WARNING] 243-253: dangerouslySetInnerHTML with dynamic content can lead to XSS. Sanitize the input with a library like DOMPurify before rendering.
(coderabbit.xss.react-dangerously-set-innerhtml)
🪛 Stylelint (17.14.0)
frontends/ui/src/app/globals.css
[error] 670-670: Deprecated keyword "break-word" for property "word-break" (declaration-property-value-keyword-no-deprecated)
(declaration-property-value-keyword-no-deprecated)
[error] 360-360: Expected keyframe name "dotBreathe" to be kebab-case (keyframes-name-pattern)
(keyframes-name-pattern)
[error] 453-453: Expected keyframe name "assistantTurnIn" to be kebab-case (keyframes-name-pattern)
(keyframes-name-pattern)
[error] 522-522: Expected keyframe name "thinkingDot" to be kebab-case (keyframes-name-pattern)
(keyframes-name-pattern)
[error] 596-596: Expected keyframe name "thinkSweep" to be kebab-case (keyframes-name-pattern)
(keyframes-name-pattern)
[error] 745-745: Expected keyframe name "answerBlockReveal" to be kebab-case (keyframes-name-pattern)
(keyframes-name-pattern)
- rehype-citations: skip [n] markers inside code/pre so code samples like arr[1] are not turned into citations. - CopyButton: track the reset timeout in a ref, clearing it on re-click and unmount. - SourceList: always render a clickable link for URL-bearing sources, including when the label equals the domain. - source-utils: reuse the computed kind instead of re-testing the URL regex. - CollapsibleBlock: wire aria-controls to the disclosed region id. - SourceStrip: expose aria-expanded on the "+N more" button. - Citation: keep URL-less citations keyboard-focusable. - Add CollapsibleBlock and SourceList unit tests. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Signed-off-by: Manush Maheshwari <manushm@nvidia.com>
3c607d3 to
138aa63
Compare
There was a problem hiding this comment.
Actionable comments posted: 13
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (4)
frontends/ui/src/shared/components/CollapsibleBlock/CollapsibleBlock.tsx (1)
62-91: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
aria-controlsdangles once the panel unmounts.
AnimatePresencefully removes themotion.div(and itsid={regionId}) from the DOM when collapsed, but the button'saria-controls={regionId}is set unconditionally — so while closed, assistive tech is told to control an element that no longer exists.As per path instructions, "Review UI changes for ... accessible controls."
♿ Proposed fix
- aria-controls={regionId} + aria-controls={open ? regionId : undefined}🤖 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 `@frontends/ui/src/shared/components/CollapsibleBlock/CollapsibleBlock.tsx` around lines 62 - 91, Update the collapsible trigger in CollapsibleBlock so aria-controls is only set while the controlled motion.div is mounted, matching the (open || !collapsible) rendering condition. Preserve regionId on the panel and the existing expanded-state behavior.Source: Path instructions
frontends/ui/src/features/layout/components/AgentCard.tsx (1)
87-176: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick winRender
agent.outputin the expandable body
hasExpandableContentonly checkscurrentTaskand tool calls, butcompleteDeepResearchAgentpopulatesAgentInfo.output. A completed agent with no other content stays disabled and its result never appears here; addoutputto the expandability/content check, or remove it from this card’s contract/tests if it isn’t meant to surface.🤖 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 `@frontends/ui/src/features/layout/components/AgentCard.tsx` around lines 87 - 176, Update AgentCard’s hasExpandableContent and expandable body to include agent.output, allowing completed agents with output but no task or tool calls to expand and display their result. Preserve the existing currentTask and tool-call rendering, and ensure the expandability, disabled state, and rendered content use the same output-aware condition.frontends/ui/src/adapters/api/websocket-client.ts (1)
222-240: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueUpdate JSDoc for the new
selectedModelparam.The docstring above
sendMessagestill lists only the original three params; add@param selectedModelto keep it accurate.📝 Suggested docstring update
/** * Send a user chat message * `@param` content - The message text content (query) * `@param` enabledDataSources - Optional array of enabled data source IDs to include in the query * `@param` activeReportJobId - Optional completed report job ID for report-aware follow-up + * `@param` selectedModel - Optional model identifier to include in the outgoing payload */🤖 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 `@frontends/ui/src/adapters/api/websocket-client.ts` around lines 222 - 240, Update the JSDoc above sendMessage to document the selectedModel parameter, describing it as the optional selected model identifier used for the query.frontends/ui/src/shared/components/Actions/CopyButton.tsx (1)
44-55: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win"Copied" confirmation may not reach screen-reader users.
The state change is only exposed via
aria-label/title. Per accessibility guidance, an accessible-name change on the currently focused element "is not consistently announced" by screen readers without a live region. Consider adding a visually-hiddenaria-live="polite"span announcing "Copied to clipboard" alongside the icon swap.As per path instructions, review UI changes for "accessible controls."
🤖 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 `@frontends/ui/src/shared/components/Actions/CopyButton.tsx` around lines 44 - 55, Add a visually hidden aria-live="polite" announcement alongside the icon in the CopyButton component, announcing “Copied to clipboard” when copied becomes true. Keep the existing button label, title, focus behavior, and icon swap unchanged.Source: Path instructions
♻️ Duplicate comments (1)
frontends/ui/src/shared/components/MarkdownRenderer/Citation.tsx (1)
32-47: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick winKeyboard focus restored; consider adding an explicit role for full semantics.
tabIndex={0}fixes the focus-reachability issue from the prior review. For a more robust fix, consider addingrole="button"(or rendering a<button>/<span>for the URL-less case, as originally suggested) so assistive tech exposes correct semantics instead of a bare, role-less<a>.🤖 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 `@frontends/ui/src/shared/components/MarkdownRenderer/Citation.tsx` around lines 32 - 47, Update the `chip` anchor in `Citation` to expose explicit button semantics when `src?.url` is absent, such as by adding the appropriate conditional role while preserving normal link semantics for URL-backed citations.
🤖 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 `@frontends/ui/src/app/globals.css`:
- Around line 983-1001: Replace the !important-based overrides in
.agent-action-approve and .agent-action-reject, including their hover states, by
using the underlying KUI Button’s supported color/kind variant props to achieve
the same text, background, and border styling. Update the button usage rather
than relying on brittle CSS specificity, while preserving the existing approve
and reject visual states.
In `@frontends/ui/src/features/chat/components/AgentPrompt.spec.tsx`:
- Around line 300-317: Update the test for the responded approval prompt with no
response to assert that neither “Plan approved” nor “Plan rejected” is rendered.
Keep the missing response state neutral, and add or update coverage for the
changed user-visible approval workflow as needed.
In `@frontends/ui/src/features/chat/components/AgentResponse.spec.tsx`:
- Around line 163-170: Extend the `surfaces a report-load error as an inline
alert and offers retry` test to click the Retry button and assert that
`mockLoadResearchPanelTab` is called with `job-1` and `report`. Keep the
existing alert text and button-presence assertions.
In `@frontends/ui/src/features/chat/components/ChatThinking.tsx`:
- Around line 375-385: Add stable unique IDs to the controlled content regions
and set matching aria-controls values on the CollapsibleText toggle and PhaseRow
head button alongside their existing aria-expanded attributes. Reuse the
useId-based disclosure pattern from CollapsibleBlock, and ensure each control
references only its own region.
- Around line 213-231: Replace the weighted numeric rank in the
duplicate-selection logic with an explicit lexicographic comparison in the
groups loop: prefer top-level steps, then completed/successful steps, then the
latest index. Update the `rank`/`best` comparison around `enriched` so index
magnitude cannot override either higher-priority criterion, while preserving the
existing grouping and drop behavior.
- Around line 426-477: Update the PhaseRow open state so it re-synchronizes with
defaultOpen whenever the phase state changes from running to done, using the
existing CollapsibleText resync pattern. Preserve manual toggling through the
head button’s click handler while ensuring completed phases collapse
automatically when defaultOpen becomes false.
In `@frontends/ui/src/features/chat/store.spec.ts`:
- Around line 2286-2347: Add a regression test alongside
hydrateDeepResearchFromMessage covering the fallback across multiple
conversations: configure currentUserId as user-1, set currentConversation to an
empty user-1 conversation, include a user-2 conversation containing saved state
for the requested job, and assert hydrateDeepResearchFromMessage returns false
without hydrating that state.
In `@frontends/ui/src/features/layout/components/AgentCard.tsx`:
- Around line 68-81: Update dedupeToolCalls so every duplicate key
unconditionally replaces the existing entry with the latest tool call,
preserving Map iteration order and reflecting terminal-to-terminal status
transitions. Add a regression test in AgentCard.spec.tsx covering an
error-to-complete or complete-to-error same-key transition alongside the
existing running-to-error case.
In `@frontends/ui/src/features/layout/components/AgentsTab.tsx`:
- Around line 46-48: Update the running-state derivation in AgentsTab so it
reflects rendered top-level steps, including orphan tool calls with status
"running", rather than only deepResearchAgents. Keep ChatThinking’s
incomplete-phase state and the header’s “running” indicator consistent with that
derived count, and add coverage for a running orphan tool call.
- Around line 51-56: Update the scrolling useEffect in AgentsTab around
scrollRef, steps.length, and runningCount so it also reacts when existing step
content or status changes, not only when the array length changes. Use the
relevant step data or update signal already available in the component while
preserving the nearBottom check and pinned-scroll behavior.
In `@frontends/ui/src/features/layout/components/ChatArea.tsx`:
- Around line 221-227: Update the chat message container in ChatArea’s returned
Flex element to expose it as an ARIA live log, adding the appropriate role and
live-region attributes while preserving the existing aria-label and scrolling
behavior.
In `@frontends/ui/src/features/layout/components/SessionsPanel.tsx`:
- Around line 700-746: Update groupSessionsByDate to preserve the input sessions
order: remove the ordered copy and date-based sort, then iterate directly over
sessions while retaining the existing bucket grouping and output order. Keep
bucket assignment unchanged so groups and sessions within each group reflect the
caller’s sort order, and add a regression test covering order that differs from
session.date.
In `@frontends/ui/src/features/layout/components/ThinkingTab.tsx`:
- Around line 209-217: Update the expanded generated-files list in ThinkingTab’s
showFiles rendering to apply a bounded maximum height and appropriate overflow
scrolling, matching the equivalent Report view. Preserve the existing
deepResearchFiles mapping and FileCard rendering while ensuring many files
cannot collapse or be clipped by the parent panel.
---
Outside diff comments:
In `@frontends/ui/src/adapters/api/websocket-client.ts`:
- Around line 222-240: Update the JSDoc above sendMessage to document the
selectedModel parameter, describing it as the optional selected model identifier
used for the query.
In `@frontends/ui/src/features/layout/components/AgentCard.tsx`:
- Around line 87-176: Update AgentCard’s hasExpandableContent and expandable
body to include agent.output, allowing completed agents with output but no task
or tool calls to expand and display their result. Preserve the existing
currentTask and tool-call rendering, and ensure the expandability, disabled
state, and rendered content use the same output-aware condition.
In `@frontends/ui/src/shared/components/Actions/CopyButton.tsx`:
- Around line 44-55: Add a visually hidden aria-live="polite" announcement
alongside the icon in the CopyButton component, announcing “Copied to clipboard”
when copied becomes true. Keep the existing button label, title, focus behavior,
and icon swap unchanged.
In `@frontends/ui/src/shared/components/CollapsibleBlock/CollapsibleBlock.tsx`:
- Around line 62-91: Update the collapsible trigger in CollapsibleBlock so
aria-controls is only set while the controlled motion.div is mounted, matching
the (open || !collapsible) rendering condition. Preserve regionId on the panel
and the existing expanded-state behavior.
---
Duplicate comments:
In `@frontends/ui/src/shared/components/MarkdownRenderer/Citation.tsx`:
- Around line 32-47: Update the `chip` anchor in `Citation` to expose explicit
button semantics when `src?.url` is absent, such as by adding the appropriate
conditional role while preserving normal link semantics for URL-backed
citations.
🪄 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: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Enterprise
Run ID: 6be407cf-77dd-4806-b614-9bafb8c0c5cb
📒 Files selected for processing (87)
frontends/ui/src/adapters/api/websocket-client.tsfrontends/ui/src/app/globals.cssfrontends/ui/src/app/page.tsxfrontends/ui/src/app/providers.tsxfrontends/ui/src/features/chat/components/AgentPrompt.spec.tsxfrontends/ui/src/features/chat/components/AgentPrompt.tsxfrontends/ui/src/features/chat/components/AgentResponse.spec.tsxfrontends/ui/src/features/chat/components/AgentResponse.tsxfrontends/ui/src/features/chat/components/ChatThinking.spec.tsxfrontends/ui/src/features/chat/components/ChatThinking.tsxfrontends/ui/src/features/chat/components/DeepResearchBanner.tsxfrontends/ui/src/features/chat/components/ErrorBanner.tsxfrontends/ui/src/features/chat/components/FileUploadBanner.tsxfrontends/ui/src/features/chat/components/NoSourcesBanner.tsxfrontends/ui/src/features/chat/components/UserMessage.tsxfrontends/ui/src/features/chat/components/index.tsfrontends/ui/src/features/chat/hooks/use-websocket-chat.tsfrontends/ui/src/features/chat/lib/deep-research-trace.spec.tsfrontends/ui/src/features/chat/lib/deep-research-trace.tsfrontends/ui/src/features/chat/lib/intermediate-step-parser.spec.tsfrontends/ui/src/features/chat/lib/intermediate-step-parser.tsfrontends/ui/src/features/chat/lib/session-activity.tsfrontends/ui/src/features/chat/store.spec.tsfrontends/ui/src/features/chat/store.tsfrontends/ui/src/features/chat/types.tsfrontends/ui/src/features/layout/components/AgentCard.spec.tsxfrontends/ui/src/features/layout/components/AgentCard.tsxfrontends/ui/src/features/layout/components/AgentsTab.spec.tsxfrontends/ui/src/features/layout/components/AgentsTab.tsxfrontends/ui/src/features/layout/components/AppBar.spec.tsxfrontends/ui/src/features/layout/components/AppBar.tsxfrontends/ui/src/features/layout/components/ChatArea.autoscroll.spec.tsxfrontends/ui/src/features/layout/components/ChatArea.spec.tsxfrontends/ui/src/features/layout/components/ChatArea.tsxfrontends/ui/src/features/layout/components/CitationCard.spec.tsxfrontends/ui/src/features/layout/components/CitationCard.tsxfrontends/ui/src/features/layout/components/DataConnectionCard.tsxfrontends/ui/src/features/layout/components/DataConnectionsTab.spec.tsxfrontends/ui/src/features/layout/components/DataConnectionsTab.tsxfrontends/ui/src/features/layout/components/DataSourcesPanel.spec.tsxfrontends/ui/src/features/layout/components/DataSourcesPanel.tsxfrontends/ui/src/features/layout/components/FileCard.tsxfrontends/ui/src/features/layout/components/FileSourceCard.spec.tsxfrontends/ui/src/features/layout/components/FileSourceCard.tsxfrontends/ui/src/features/layout/components/FileSourcesTab.spec.tsxfrontends/ui/src/features/layout/components/FileSourcesTab.tsxfrontends/ui/src/features/layout/components/InputArea.tsxfrontends/ui/src/features/layout/components/MainLayout.spec.tsxfrontends/ui/src/features/layout/components/MainLayout.tsxfrontends/ui/src/features/layout/components/ReportCard.spec.tsxfrontends/ui/src/features/layout/components/ReportCard.tsxfrontends/ui/src/features/layout/components/ReportTab.spec.tsxfrontends/ui/src/features/layout/components/ReportTab.tsxfrontends/ui/src/features/layout/components/ResearchPanel.spec.tsxfrontends/ui/src/features/layout/components/ResearchPanel.tsxfrontends/ui/src/features/layout/components/SessionsPanel.spec.tsxfrontends/ui/src/features/layout/components/SessionsPanel.tsxfrontends/ui/src/features/layout/components/SettingsPanel.spec.tsxfrontends/ui/src/features/layout/components/SettingsPanel.tsxfrontends/ui/src/features/layout/components/SourceCard.spec.tsxfrontends/ui/src/features/layout/components/SourceCard.tsxfrontends/ui/src/features/layout/components/TaskCard.spec.tsxfrontends/ui/src/features/layout/components/TaskCard.tsxfrontends/ui/src/features/layout/components/TasksTab.spec.tsxfrontends/ui/src/features/layout/components/TasksTab.tsxfrontends/ui/src/features/layout/components/ThinkingTab.spec.tsxfrontends/ui/src/features/layout/components/ThinkingTab.tsxfrontends/ui/src/features/layout/components/ThoughtCard.spec.tsxfrontends/ui/src/features/layout/components/ThoughtCard.tsxfrontends/ui/src/features/layout/components/index.tsfrontends/ui/src/features/layout/data-sources.spec.tsfrontends/ui/src/features/layout/data-sources.tsfrontends/ui/src/features/layout/index.tsfrontends/ui/src/features/layout/store.spec.tsfrontends/ui/src/features/layout/store.tsfrontends/ui/src/features/layout/types.tsfrontends/ui/src/shared/components/Actions/CopyButton.tsxfrontends/ui/src/shared/components/CollapsibleBlock/CollapsibleBlock.spec.tsxfrontends/ui/src/shared/components/CollapsibleBlock/CollapsibleBlock.tsxfrontends/ui/src/shared/components/MarkdownRenderer/Citation.tsxfrontends/ui/src/shared/components/MarkdownRenderer/rehype-citations.tsfrontends/ui/src/shared/components/Sources/SourceList.spec.tsxfrontends/ui/src/shared/components/Sources/SourceList.tsxfrontends/ui/src/shared/components/Sources/SourceStrip.tsxfrontends/ui/src/shared/components/Sources/source-utils.tsfrontends/ui/src/shared/lib/scroll.spec.tsfrontends/ui/src/shared/lib/scroll.ts
💤 Files with no reviewable changes (14)
- frontends/ui/src/features/layout/components/SourceCard.spec.tsx
- frontends/ui/src/features/chat/components/ErrorBanner.tsx
- frontends/ui/src/features/layout/components/DataConnectionsTab.spec.tsx
- frontends/ui/src/features/layout/components/index.ts
- frontends/ui/src/features/layout/components/ResearchPanel.spec.tsx
- frontends/ui/src/features/chat/components/NoSourcesBanner.tsx
- frontends/ui/src/features/chat/components/FileUploadBanner.tsx
- frontends/ui/src/features/layout/components/SettingsPanel.spec.tsx
- frontends/ui/src/features/chat/components/DeepResearchBanner.tsx
- frontends/ui/src/features/layout/components/TasksTab.spec.tsx
- frontends/ui/src/features/layout/components/FileSourcesTab.spec.tsx
- frontends/ui/src/features/layout/components/ReportCard.spec.tsx
- frontends/ui/src/features/chat/components/index.ts
- frontends/ui/src/features/layout/components/CitationCard.spec.tsx
📜 Review details
🧰 Additional context used
📓 Path-based instructions (3)
frontends/ui/**/*.{js,ts,jsx,tsx,vue}
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Run npm lint, type-check, and build validation for UI changes in frontends/ui
Files:
frontends/ui/src/shared/lib/scroll.spec.tsfrontends/ui/src/shared/lib/scroll.tsfrontends/ui/src/shared/components/CollapsibleBlock/CollapsibleBlock.spec.tsxfrontends/ui/src/features/layout/components/TaskCard.spec.tsxfrontends/ui/src/features/layout/data-sources.spec.tsfrontends/ui/src/features/layout/index.tsfrontends/ui/src/features/layout/components/CitationCard.tsxfrontends/ui/src/features/layout/components/DataConnectionCard.tsxfrontends/ui/src/app/page.tsxfrontends/ui/src/features/chat/components/UserMessage.tsxfrontends/ui/src/features/layout/components/AgentsTab.tsxfrontends/ui/src/shared/components/Sources/SourceList.spec.tsxfrontends/ui/src/features/layout/components/SettingsPanel.tsxfrontends/ui/src/features/layout/components/DataSourcesPanel.spec.tsxfrontends/ui/src/features/layout/components/SourceCard.tsxfrontends/ui/src/features/layout/components/TaskCard.tsxfrontends/ui/src/features/layout/components/ReportTab.spec.tsxfrontends/ui/src/features/layout/components/AgentsTab.spec.tsxfrontends/ui/src/app/providers.tsxfrontends/ui/src/features/layout/components/ReportCard.tsxfrontends/ui/src/shared/components/MarkdownRenderer/rehype-citations.tsfrontends/ui/src/shared/components/Sources/SourceStrip.tsxfrontends/ui/src/features/layout/store.spec.tsfrontends/ui/src/shared/components/CollapsibleBlock/CollapsibleBlock.tsxfrontends/ui/src/features/chat/lib/deep-research-trace.tsfrontends/ui/src/shared/components/Sources/SourceList.tsxfrontends/ui/src/features/layout/components/ReportTab.tsxfrontends/ui/src/features/chat/lib/intermediate-step-parser.spec.tsfrontends/ui/src/shared/components/Actions/CopyButton.tsxfrontends/ui/src/features/layout/components/FileSourceCard.spec.tsxfrontends/ui/src/features/chat/lib/deep-research-trace.spec.tsfrontends/ui/src/features/layout/store.tsfrontends/ui/src/adapters/api/websocket-client.tsfrontends/ui/src/features/layout/components/ThoughtCard.spec.tsxfrontends/ui/src/features/layout/data-sources.tsfrontends/ui/src/shared/components/MarkdownRenderer/Citation.tsxfrontends/ui/src/features/layout/components/ChatArea.autoscroll.spec.tsxfrontends/ui/src/features/layout/components/InputArea.tsxfrontends/ui/src/features/layout/components/FileSourceCard.tsxfrontends/ui/src/features/chat/types.tsfrontends/ui/src/features/chat/store.tsfrontends/ui/src/features/chat/components/AgentResponse.tsxfrontends/ui/src/features/layout/components/ThinkingTab.tsxfrontends/ui/src/features/chat/lib/intermediate-step-parser.tsfrontends/ui/src/features/chat/store.spec.tsfrontends/ui/src/features/chat/components/AgentResponse.spec.tsxfrontends/ui/src/features/chat/components/AgentPrompt.spec.tsxfrontends/ui/src/features/layout/types.tsfrontends/ui/src/features/layout/components/ChatArea.spec.tsxfrontends/ui/src/features/layout/components/FileCard.tsxfrontends/ui/src/features/chat/components/ChatThinking.spec.tsxfrontends/ui/src/shared/components/Sources/source-utils.tsfrontends/ui/src/features/chat/lib/session-activity.tsfrontends/ui/src/features/layout/components/AppBar.spec.tsxfrontends/ui/src/features/layout/components/TasksTab.tsxfrontends/ui/src/features/layout/components/DataConnectionsTab.tsxfrontends/ui/src/features/layout/components/AppBar.tsxfrontends/ui/src/features/layout/components/MainLayout.tsxfrontends/ui/src/features/layout/components/ThoughtCard.tsxfrontends/ui/src/features/layout/components/MainLayout.spec.tsxfrontends/ui/src/features/layout/components/ResearchPanel.tsxfrontends/ui/src/features/layout/components/SessionsPanel.tsxfrontends/ui/src/features/layout/components/ThinkingTab.spec.tsxfrontends/ui/src/features/chat/hooks/use-websocket-chat.tsfrontends/ui/src/features/layout/components/AgentCard.tsxfrontends/ui/src/features/layout/components/AgentCard.spec.tsxfrontends/ui/src/features/chat/components/ChatThinking.tsxfrontends/ui/src/features/layout/components/DataSourcesPanel.tsxfrontends/ui/src/features/layout/components/FileSourcesTab.tsxfrontends/ui/src/features/layout/components/SessionsPanel.spec.tsxfrontends/ui/src/features/layout/components/ChatArea.tsxfrontends/ui/src/features/chat/components/AgentPrompt.tsx
frontends/ui/**/*.{ts,tsx,jsx,js}
📄 CodeRabbit inference engine (AGENTS.md)
frontends/ui/**/*.{ts,tsx,jsx,js}: The UI is built with Next.js / React / TypeScript / Tailwind with KUI components; reuse existing KUI components and visual patterns rather than introducing new ones
Validate UI-affecting changes with npm run lint, npm run type-check, and npm run test:ci, and include a screenshot for visible changes
Files:
frontends/ui/src/shared/lib/scroll.spec.tsfrontends/ui/src/shared/lib/scroll.tsfrontends/ui/src/shared/components/CollapsibleBlock/CollapsibleBlock.spec.tsxfrontends/ui/src/features/layout/components/TaskCard.spec.tsxfrontends/ui/src/features/layout/data-sources.spec.tsfrontends/ui/src/features/layout/index.tsfrontends/ui/src/features/layout/components/CitationCard.tsxfrontends/ui/src/features/layout/components/DataConnectionCard.tsxfrontends/ui/src/app/page.tsxfrontends/ui/src/features/chat/components/UserMessage.tsxfrontends/ui/src/features/layout/components/AgentsTab.tsxfrontends/ui/src/shared/components/Sources/SourceList.spec.tsxfrontends/ui/src/features/layout/components/SettingsPanel.tsxfrontends/ui/src/features/layout/components/DataSourcesPanel.spec.tsxfrontends/ui/src/features/layout/components/SourceCard.tsxfrontends/ui/src/features/layout/components/TaskCard.tsxfrontends/ui/src/features/layout/components/ReportTab.spec.tsxfrontends/ui/src/features/layout/components/AgentsTab.spec.tsxfrontends/ui/src/app/providers.tsxfrontends/ui/src/features/layout/components/ReportCard.tsxfrontends/ui/src/shared/components/MarkdownRenderer/rehype-citations.tsfrontends/ui/src/shared/components/Sources/SourceStrip.tsxfrontends/ui/src/features/layout/store.spec.tsfrontends/ui/src/shared/components/CollapsibleBlock/CollapsibleBlock.tsxfrontends/ui/src/features/chat/lib/deep-research-trace.tsfrontends/ui/src/shared/components/Sources/SourceList.tsxfrontends/ui/src/features/layout/components/ReportTab.tsxfrontends/ui/src/features/chat/lib/intermediate-step-parser.spec.tsfrontends/ui/src/shared/components/Actions/CopyButton.tsxfrontends/ui/src/features/layout/components/FileSourceCard.spec.tsxfrontends/ui/src/features/chat/lib/deep-research-trace.spec.tsfrontends/ui/src/features/layout/store.tsfrontends/ui/src/adapters/api/websocket-client.tsfrontends/ui/src/features/layout/components/ThoughtCard.spec.tsxfrontends/ui/src/features/layout/data-sources.tsfrontends/ui/src/shared/components/MarkdownRenderer/Citation.tsxfrontends/ui/src/features/layout/components/ChatArea.autoscroll.spec.tsxfrontends/ui/src/features/layout/components/InputArea.tsxfrontends/ui/src/features/layout/components/FileSourceCard.tsxfrontends/ui/src/features/chat/types.tsfrontends/ui/src/features/chat/store.tsfrontends/ui/src/features/chat/components/AgentResponse.tsxfrontends/ui/src/features/layout/components/ThinkingTab.tsxfrontends/ui/src/features/chat/lib/intermediate-step-parser.tsfrontends/ui/src/features/chat/store.spec.tsfrontends/ui/src/features/chat/components/AgentResponse.spec.tsxfrontends/ui/src/features/chat/components/AgentPrompt.spec.tsxfrontends/ui/src/features/layout/types.tsfrontends/ui/src/features/layout/components/ChatArea.spec.tsxfrontends/ui/src/features/layout/components/FileCard.tsxfrontends/ui/src/features/chat/components/ChatThinking.spec.tsxfrontends/ui/src/shared/components/Sources/source-utils.tsfrontends/ui/src/features/chat/lib/session-activity.tsfrontends/ui/src/features/layout/components/AppBar.spec.tsxfrontends/ui/src/features/layout/components/TasksTab.tsxfrontends/ui/src/features/layout/components/DataConnectionsTab.tsxfrontends/ui/src/features/layout/components/AppBar.tsxfrontends/ui/src/features/layout/components/MainLayout.tsxfrontends/ui/src/features/layout/components/ThoughtCard.tsxfrontends/ui/src/features/layout/components/MainLayout.spec.tsxfrontends/ui/src/features/layout/components/ResearchPanel.tsxfrontends/ui/src/features/layout/components/SessionsPanel.tsxfrontends/ui/src/features/layout/components/ThinkingTab.spec.tsxfrontends/ui/src/features/chat/hooks/use-websocket-chat.tsfrontends/ui/src/features/layout/components/AgentCard.tsxfrontends/ui/src/features/layout/components/AgentCard.spec.tsxfrontends/ui/src/features/chat/components/ChatThinking.tsxfrontends/ui/src/features/layout/components/DataSourcesPanel.tsxfrontends/ui/src/features/layout/components/FileSourcesTab.tsxfrontends/ui/src/features/layout/components/SessionsPanel.spec.tsxfrontends/ui/src/features/layout/components/ChatArea.tsxfrontends/ui/src/features/chat/components/AgentPrompt.tsx
frontends/ui/**/*
⚙️ CodeRabbit configuration file
frontends/ui/**/*: Review UI changes for strict TypeScript behavior, API contract alignment, auth/session handling, accessible controls,
resilient loading and error states, and report/chat state consistency. Prefer existing UI patterns and require tests
for changed user-visible workflows.
Files:
frontends/ui/src/shared/lib/scroll.spec.tsfrontends/ui/src/shared/lib/scroll.tsfrontends/ui/src/shared/components/CollapsibleBlock/CollapsibleBlock.spec.tsxfrontends/ui/src/features/layout/components/TaskCard.spec.tsxfrontends/ui/src/features/layout/data-sources.spec.tsfrontends/ui/src/features/layout/index.tsfrontends/ui/src/features/layout/components/CitationCard.tsxfrontends/ui/src/features/layout/components/DataConnectionCard.tsxfrontends/ui/src/app/page.tsxfrontends/ui/src/features/chat/components/UserMessage.tsxfrontends/ui/src/features/layout/components/AgentsTab.tsxfrontends/ui/src/shared/components/Sources/SourceList.spec.tsxfrontends/ui/src/features/layout/components/SettingsPanel.tsxfrontends/ui/src/features/layout/components/DataSourcesPanel.spec.tsxfrontends/ui/src/features/layout/components/SourceCard.tsxfrontends/ui/src/features/layout/components/TaskCard.tsxfrontends/ui/src/features/layout/components/ReportTab.spec.tsxfrontends/ui/src/features/layout/components/AgentsTab.spec.tsxfrontends/ui/src/app/providers.tsxfrontends/ui/src/features/layout/components/ReportCard.tsxfrontends/ui/src/shared/components/MarkdownRenderer/rehype-citations.tsfrontends/ui/src/shared/components/Sources/SourceStrip.tsxfrontends/ui/src/features/layout/store.spec.tsfrontends/ui/src/shared/components/CollapsibleBlock/CollapsibleBlock.tsxfrontends/ui/src/features/chat/lib/deep-research-trace.tsfrontends/ui/src/shared/components/Sources/SourceList.tsxfrontends/ui/src/features/layout/components/ReportTab.tsxfrontends/ui/src/features/chat/lib/intermediate-step-parser.spec.tsfrontends/ui/src/shared/components/Actions/CopyButton.tsxfrontends/ui/src/features/layout/components/FileSourceCard.spec.tsxfrontends/ui/src/features/chat/lib/deep-research-trace.spec.tsfrontends/ui/src/features/layout/store.tsfrontends/ui/src/adapters/api/websocket-client.tsfrontends/ui/src/features/layout/components/ThoughtCard.spec.tsxfrontends/ui/src/features/layout/data-sources.tsfrontends/ui/src/shared/components/MarkdownRenderer/Citation.tsxfrontends/ui/src/features/layout/components/ChatArea.autoscroll.spec.tsxfrontends/ui/src/features/layout/components/InputArea.tsxfrontends/ui/src/features/layout/components/FileSourceCard.tsxfrontends/ui/src/features/chat/types.tsfrontends/ui/src/features/chat/store.tsfrontends/ui/src/features/chat/components/AgentResponse.tsxfrontends/ui/src/features/layout/components/ThinkingTab.tsxfrontends/ui/src/features/chat/lib/intermediate-step-parser.tsfrontends/ui/src/features/chat/store.spec.tsfrontends/ui/src/features/chat/components/AgentResponse.spec.tsxfrontends/ui/src/features/chat/components/AgentPrompt.spec.tsxfrontends/ui/src/features/layout/types.tsfrontends/ui/src/features/layout/components/ChatArea.spec.tsxfrontends/ui/src/features/layout/components/FileCard.tsxfrontends/ui/src/features/chat/components/ChatThinking.spec.tsxfrontends/ui/src/shared/components/Sources/source-utils.tsfrontends/ui/src/features/chat/lib/session-activity.tsfrontends/ui/src/features/layout/components/AppBar.spec.tsxfrontends/ui/src/features/layout/components/TasksTab.tsxfrontends/ui/src/features/layout/components/DataConnectionsTab.tsxfrontends/ui/src/features/layout/components/AppBar.tsxfrontends/ui/src/features/layout/components/MainLayout.tsxfrontends/ui/src/features/layout/components/ThoughtCard.tsxfrontends/ui/src/features/layout/components/MainLayout.spec.tsxfrontends/ui/src/features/layout/components/ResearchPanel.tsxfrontends/ui/src/features/layout/components/SessionsPanel.tsxfrontends/ui/src/features/layout/components/ThinkingTab.spec.tsxfrontends/ui/src/features/chat/hooks/use-websocket-chat.tsfrontends/ui/src/features/layout/components/AgentCard.tsxfrontends/ui/src/features/layout/components/AgentCard.spec.tsxfrontends/ui/src/features/chat/components/ChatThinking.tsxfrontends/ui/src/features/layout/components/DataSourcesPanel.tsxfrontends/ui/src/features/layout/components/FileSourcesTab.tsxfrontends/ui/src/features/layout/components/SessionsPanel.spec.tsxfrontends/ui/src/features/layout/components/ChatArea.tsxfrontends/ui/src/features/chat/components/AgentPrompt.tsxfrontends/ui/src/app/globals.css
🪛 Stylelint (17.14.0)
frontends/ui/src/app/globals.css
[error] 670-670: Deprecated keyword "break-word" for property "word-break" (declaration-property-value-keyword-no-deprecated)
(declaration-property-value-keyword-no-deprecated)
[error] 453-453: Expected keyframe name "assistantTurnIn" to be kebab-case (keyframes-name-pattern)
(keyframes-name-pattern)
[error] 522-522: Expected keyframe name "thinkingDot" to be kebab-case (keyframes-name-pattern)
(keyframes-name-pattern)
[error] 596-596: Expected keyframe name "thinkSweep" to be kebab-case (keyframes-name-pattern)
(keyframes-name-pattern)
[error] 745-745: Expected keyframe name "answerBlockReveal" to be kebab-case (keyframes-name-pattern)
(keyframes-name-pattern)
|
/ok to test 69fc3d1 |
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (3)
frontends/ui/src/features/chat/components/ChatThinking.tsx (3)
583-603: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick winKeep reasoning-only phases renderable.
realStepsremoves reasoning/explanation entries, whilebuildPhases(visibleSteps)retains them in phase metadata and supports fallback phases. A reasoning-only stream can therefore have renderablephasesbut still hit thereturn nullguard at Line [602], hiding the live trace before any tool phase appears.Gate on
phases.length(or another renderable-phase predicate) and add a reasoning-only regression test.Proposed fix
- if (realSteps.length === 0 && !hasDataSources && !hasFiles) { + if (phases.length === 0 && !hasDataSources && !hasFiles) { return null }🤖 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 `@frontends/ui/src/features/chat/components/ChatThinking.tsx` around lines 583 - 603, Update the render guard in ChatThinking so reasoning-only streams remain renderable: use the built phases collection (such as phases.length) rather than realSteps.length when deciding to return null, while preserving the existing data-source and file checks. Add a regression test covering a reasoning-only visibleSteps stream and verifying its phase metadata is rendered.
697-704: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick winAssociate the disclosure with the trace region.
aria-expandedneeds a matchingaria-controlstarget, and the trace panel should have a stableid. Whenphases.length === 0, render a static header instead of a button so it doesn’t imply a panel that isn’t there.🤖 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 `@frontends/ui/src/features/chat/components/ChatThinking.tsx` around lines 697 - 704, Update the ChatThinking disclosure so the button’s aria-expanded is paired with aria-controls referencing a stable id on the trace panel. When phases.length is zero, render a non-interactive static header instead of the disclosure button; preserve the existing toggle behavior and trace content for non-empty phases.Source: Path instructions
552-555: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick winUpdate
responseNowwhen thinking stops. WhenresponseCompletedAtis absent, the timer can freeze on the last 1s tick, soresponseDurationmay render up to a second short after thinking ends. SetresponseNowtoDate.now()alongsidestoppedAtinfrontends/ui/src/features/chat/components/ChatThinking.tsx:552-555.🤖 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 `@frontends/ui/src/features/chat/components/ChatThinking.tsx` around lines 552 - 555, Update the thinking-stop branch guarded by wasThinkingRef.current to also set responseNow to Date.now() alongside stoppedAt, ensuring the final responseDuration calculation uses the stop timestamp when responseCompletedAt is absent.
🤖 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.
Outside diff comments:
In `@frontends/ui/src/features/chat/components/ChatThinking.tsx`:
- Around line 583-603: Update the render guard in ChatThinking so reasoning-only
streams remain renderable: use the built phases collection (such as
phases.length) rather than realSteps.length when deciding to return null, while
preserving the existing data-source and file checks. Add a regression test
covering a reasoning-only visibleSteps stream and verifying its phase metadata
is rendered.
- Around line 697-704: Update the ChatThinking disclosure so the button’s
aria-expanded is paired with aria-controls referencing a stable id on the trace
panel. When phases.length is zero, render a non-interactive static header
instead of the disclosure button; preserve the existing toggle behavior and
trace content for non-empty phases.
- Around line 552-555: Update the thinking-stop branch guarded by
wasThinkingRef.current to also set responseNow to Date.now() alongside
stoppedAt, ensuring the final responseDuration calculation uses the stop
timestamp when responseCompletedAt is absent.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Enterprise
Run ID: fb0315fa-5198-485c-aa3d-7cb5cfe5a460
📒 Files selected for processing (2)
frontends/ui/src/app/globals.cssfrontends/ui/src/features/chat/components/ChatThinking.tsx
📜 Review details
🧰 Additional context used
📓 Path-based instructions (3)
frontends/ui/**/*.{js,ts,jsx,tsx,vue}
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Run npm lint, type-check, and build validation for UI changes in frontends/ui
Files:
frontends/ui/src/features/chat/components/ChatThinking.tsx
frontends/ui/**/*.{ts,tsx,jsx,js}
📄 CodeRabbit inference engine (AGENTS.md)
frontends/ui/**/*.{ts,tsx,jsx,js}: The UI is built with Next.js / React / TypeScript / Tailwind with KUI components; reuse existing KUI components and visual patterns rather than introducing new ones
Validate UI-affecting changes with npm run lint, npm run type-check, and npm run test:ci, and include a screenshot for visible changes
Files:
frontends/ui/src/features/chat/components/ChatThinking.tsx
frontends/ui/**/*
⚙️ CodeRabbit configuration file
frontends/ui/**/*: Review UI changes for strict TypeScript behavior, API contract alignment, auth/session handling, accessible controls,
resilient loading and error states, and report/chat state consistency. Prefer existing UI patterns and require tests
for changed user-visible workflows.
Files:
frontends/ui/src/features/chat/components/ChatThinking.tsxfrontends/ui/src/app/globals.css
🪛 Stylelint (17.14.0)
frontends/ui/src/app/globals.css
[error] 130-130: Expected "optimizeLegibility" to be "optimizelegibility" (value-keyword-case)
(value-keyword-case)
🔇 Additional comments (2)
frontends/ui/src/app/globals.css (1)
127-130: 📐 Maintainability & Code QualityNo change needed.
text-rendering: optimizeLegibilityis valid CSS, and this frontend config doesn’t include a Stylelint rule that requires a lowercase keyword form.> Likely an incorrect or invalid review comment.frontends/ui/src/features/chat/components/ChatThinking.tsx (1)
641-643: 🎯 Functional CorrectnessNo issue here:
phasesonly contains observed steps.buildPhases()creates each phase from an actualThinkingStep, and the trace contract says top-level steps are emitted in start order.laterStartedis just using the next observed phase as the completion boundary for earlier phases.> Likely an incorrect or invalid review comment.
Signed-off-by: Manush Maheshwari <manushm@nvidia.com>
Additive state and streaming plumbing that a later UI PR consumes; no visual change and no prod capability removed. - chat types: optional ThinkingStep fields (completedAt, status, argSummary), ChatMessage.selectedModel, and a plan_approval prompt type. - intermediate-step-parser: generic folded reasoning/reflection/explanation sentinels and predicates, splitPayload/extractFoldedOutput, and label lookup via the shared tool-label engine. - deep-research-trace: replays a stored deep run into the same ThinkingStep stream so reloaded reports show an identical trace. - store + use-websocket-chat: populate the new step fields as the run streams, fail steps on error, and thread the selected model through send. - layout store: a sidebar collapse model added alongside the existing panel API, a prompt draft, a selected-model slot, and data-source display helpers. Per-user auth, WebSocket token rotation, artifact handling, and HITL are preserved unchanged. No predictive/analytical/warehouse plumbing is ported. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Signed-off-by: Manush Maheshwari <manushm@nvidia.com>
- deep-research-trace: preserve tool calls whose referenced agent is missing (dangling agentId), not just calls with no agent, and add a regression test. - store: scope deep-research hydration to the current user's conversations. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Signed-off-by: Manush Maheshwari <manushm@nvidia.com>
Signed-off-by: Manush Maheshwari <manushm@nvidia.com>
ba52d13 to
6d43fc5
Compare
There was a problem hiding this comment.
Actionable comments posted: 33
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
frontends/ui/src/features/layout/components/ThinkingTab.spec.tsx (1)
86-120: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winCover the zero-match Cited filter state.
Add a case containing only uncited sources, select
Cited (0), and assert the filter-specific empty message rather than the global Sources empty state.As per path instructions, require tests for changed user-visible workflows.
🤖 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 `@frontends/ui/src/features/layout/components/ThinkingTab.spec.tsx` around lines 86 - 120, Add a test alongside the existing source-filter test that configures only uncited entries in mockState, renders ThinkingTab, selects the “Cited (0)” radio control, and asserts the filter-specific empty-state message is shown while the global Sources empty message is not.Source: Path instructions
🤖 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 `@docs/source/customization/configuration-reference.md`:
- Line 605: Update the configuration-profile count in the introduction of
configuration-reference.md from nine to ten, matching the ten profiles listed in
the table, including configs/config_web_azure_ai_search.yml. Review nearby
documentation for stale examples of the old count and update only those
references.
In `@docs/source/customization/knowledge-layer.md`:
- Around line 488-489: Update the environment-variable table in the
knowledge-layer customization documentation to include AZURE_SEARCH_ENDPOINT,
AZURE_SEARCH_API_KEY, AIQ_AZURE_SEARCH_INDEX_PREFIX, and AIQ_EMBED_DIM. Extend
the existing AIQ_EMBED_MODEL/AIQ_EMBED_BASE_URL entry to cover Azure AI Search,
keeping the table consistent with the Azure configuration documented in the
earlier section and correcting any stale or inaccurate examples encountered
there.
In `@docs/source/deployment/openshell.md`:
- Around line 203-211: Update the canonical openshell gateway command in the
deployment documentation to include --reuse-existing for external gateways.
Clearly label any command that omits this flag as the local packaged-service
variant where the launcher may start systemd, and keep the documented lifecycle
behavior consistent with the surrounding guidance.
In `@frontends/ui/src/app/globals.css`:
- Line 88: Update the light and dark theme values for --text-color-subtle to
achieve at least 4.5:1 contrast against their respective base and raised
surfaces, then validate both theme combinations. Add or update tests covering
the affected user-visible UI workflows and accessible controls.
- Line 130: Update the text-rendering declaration to use Stylelint’s canonical
casing for the optimizeLegibility keyword, while preserving the existing
property and value.
In `@frontends/ui/src/features/chat/components/AgentPrompt.tsx`:
- Around line 200-237: The global keydown handler in the AgentPrompt useEffect
must not intercept activation of focused interactive controls, especially the
Reject button. Extend isTyping or otherwise detect focused buttons and other
interactive targets before handling shortcuts, preserving native
Enter/activation behavior; add a regression test that focuses Reject and
activates it with Enter, verifying rejection occurs instead of handleApprove.
- Around line 143-154: Update AgentPrompt to use the destructured prompt type as
the primary approval determination, treating type="approval" as an approval
prompt regardless of content; retain the APPROVAL_PROMPT_RE check only as a
compatibility fallback if required. Add coverage for an approval-typed prompt
whose content lacks the legacy phrase, verifying the approval controls are
rendered.
In `@frontends/ui/src/features/chat/components/ChatThinking.tsx`:
- Around line 333-337: Update childState and its callers to accept the parent
phase state, propagating error or interrupted terminal outcomes to children that
are not complete instead of marking them done. Preserve child-level
error/success handling and running-phase behavior for active phases. Add focused
tests covering incomplete children under errored and interrupted phases while
preserving report/chat state consistency.
- Around line 66-71: Update formatDuration to round the non-negative duration to
whole seconds before calculating minutes and remaining seconds, then derive both
values using quotient and modulo arithmetic so carry-over values such as
119600ms render as 2m 0s while sub-minute durations retain the existing
one-decimal format.
- Around line 179-198: Replace the label-only filtering and argument merging in
the topLevelLabels/nestedSummaries/enriched flow, since same-label calls may
have different inputs and non-tool rows must not be removed. Preserve ambiguous
rows and defer deduplication to the existing exact label/input grouping logic
below, while retaining identifiable-call deduplication. Add focused regression
tests for same-label calls with different arguments and same-label non-tool
rows, ensuring report and chat state remain consistent.
In `@frontends/ui/src/features/chat/lib/deep-research-trace.ts`:
- Around line 35-56: Update the trace deduplication logic in the step-processing
flow, including sameCall, sameFold, and lastToolIndex, to use each tool or fold
step’s event ID as identity rather than function, arguments, or content. Replace
an existing snapshot when the ID matches, while preserving distinct steps with
identical inputs and ensuring newer snapshots replace stale explanation content.
Add regression coverage for distinct IDs with identical inputs and updated
snapshots sharing one ID.
In `@frontends/ui/src/features/layout/components/AgentCard.spec.tsx`:
- Around line 219-225: Extend the disabled/no-content AgentCard test to verify
its accessible button state: assert aria-expanded is "false" and aria-controls
is absent when no content region is rendered. Keep the existing expandable-case
assertions unchanged.
In `@frontends/ui/src/features/layout/components/AgentCard.tsx`:
- Around line 102-108: Update the AgentCard button’s accessibility attributes so
aria-expanded is false and aria-controls is omitted whenever canExpand is false,
while preserving the existing expanded state and controlled-region reference for
expandable cards. Add assertions in
frontends/ui/src/features/layout/components/AgentCard.spec.tsx:219-225 for the
no-content case;
frontends/ui/src/features/layout/components/AgentCard.tsx:102-108 requires the
implementation change.
In `@frontends/ui/src/features/layout/components/AppBar.spec.tsx`:
- Around line 105-122: Add tests in the AppBar interaction suite covering the
already-open data-sources state and the dark-theme state. Configure the relevant
mocked state before rendering AppBar, click the existing Add Sources and
theme-toggle buttons, and assert mockCloseRightPanel and mockSetTheme are called
with 'light' respectively, while preserving the existing opposite-direction
cases.
In `@frontends/ui/src/features/layout/components/DataSourcesPanel.tsx`:
- Around line 316-365: Remove the row’s interactive button semantics and
handlers from the Flex container, including role, tabIndex, click, keyboard, and
button-specific ARIA attributes. Keep the KUI Switch as the sole interactive
control, preserving its checked state, disabled behavior, accessible label, and
handleToggleAll callback; retain suitable visual styling without relying on
interactive-row behavior.
- Around line 388-395: Update the Retry button’s onClick handler in
DataSourcesPanel to call fetchDataSources with the current idToken, matching the
existing authenticated refresh path and preserving the API contract. Add or
update the relevant test to verify the token is forwarded on retry.
- Around line 220-245: Update the DataSourcesPanel close flow to move focus back
to the AppBar “Add data sources” trigger before or when the panel becomes
aria-hidden, rather than leaving focus inside the panel. Reuse the trigger’s
existing ref or accessible identifier, and add a regression test that opens the
panel, closes it, and verifies focus returns to that trigger.
In `@frontends/ui/src/features/layout/components/MainLayout.spec.tsx`:
- Around line 121-125: Update the unauthenticated MainLayout test to also assert
that the element identified by data-sources-panel is absent, matching the
existing sessions-panel assertion and the test’s stated coverage.
In `@frontends/ui/src/features/layout/components/SessionsPanel.tsx`:
- Around line 303-317: Restore a visible keyboard focus indicator on both inputs
in SessionsPanel.tsx: add the existing KUI input focus treatment or an
equivalent focus-visible ring to the search input at lines 303-317 and the
rename input at lines 612-622, replacing the ineffective outline-none-only
styling while preserving their current behavior.
- Around line 418-424: Apply the same streaming and pending-HITL navigation
guard used by the top “New Session” action to the empty-state button’s
handleNewSession path in SessionsPanel. Preserve the existing search visibility
condition, and add regression coverage verifying the empty-state button cannot
navigate during streaming or pending HITL.
In `@frontends/ui/src/features/layout/components/ThinkingTab.tsx`:
- Around line 97-106: Update the empty-state branch in ThinkingTab so a
non-empty source collection with no cited items displays “No cited sources yet,”
while the existing research-empty message remains for genuinely source-free
states; add a regression test in ThinkingTab.spec.tsx covering only uncited
sources and selecting Cited (0).
In `@scripts/openshell/check_versions.py`:
- Line 24: Update _VERSION_PATTERN used by _extract_version() to require a valid
suffix boundary after the supported version formats, preventing matches within
rc, post, or local-version strings. Add tests covering 0.0.80rc1, 0.0.80.post1,
and 0.0.80+local, while preserving matches for the existing supported
development and git-suffix forms.
In `@scripts/openshell/setup_openshell.sh`:
- Line 83: Update the help text in setup_openshell.sh to derive the example
version from the certified version value loaded from pyproject.toml instead of
hardcoding 0.0.80. Apply the same change to both the option description and the
corresponding usage example, preserving the existing certified-version contract.
- Around line 148-151: Update the --landlock-compatibility handling in the
option-parsing logic to validate that a value argument exists before reading $2,
including under set -u; when missing, emit the intended CLI error and exit
through the existing validation path, otherwise preserve the current assignment
and shift behavior.
In `@scripts/openshell/smoke_openshell_isolation.py`:
- Around line 71-73: Update the environment construction logic around the
allow_best_effort_landlock flag so AIQ_OPENSHELL_LIVE_ALLOW_BEST_EFFORT is
removed from env when the flag is absent, and set to "1" only when the flag is
enabled. Preserve the existing return env behavior.
In `@scripts/openshell/version_contract.py`:
- Around line 24-27: Update OpenShellContract.adapter_version to the required
str type, matching load_contract()’s validation and string return contract; do
not add optional handling unless the loader and extra-version comparison are
explicitly changed to support None.
In `@sources/knowledge_layer/src/azure_ai_search/adapter.py`:
- Around line 761-762: Validate job_config metadata in submit_job before
json.dumps() and before any {**file_metadata, ...} expansion, requiring a
dict/mapping and rejecting other values explicitly. Preserve the existing
empty-metadata default, and ensure invalid metadata follows the failed-job
recording path instead of raising during submission.
- Around line 1231-1249: Update upload_file around submit_job and the subsequent
_jobs[job_id].file_details access to handle a job with no file details when the
file disappears between validation checks. Return a failed FileInfo with the
file path, collection, and clear error message when file_details is empty, while
preserving the existing detail-copy path when a detail is available.
- Around line 1127-1131: Update _update_file_progress so it revalidates the
collection’s active state immediately before calling _write_file_manifest,
preventing a concurrent delete_collection from allowing the manifest write.
Preserve summary registration only when the manifest write remains valid, and
use the existing collection status/deletion state symbols.
- Around line 1258-1283: Update delete_file and delete_collection in
sources/knowledge_layer/src/azure_ai_search/adapter.py at lines 1258-1283 and
1182-1201 so they wait for all deleted Azure Search records to disappear before
returning. In delete_file, extend the post-delete _wait_for_search_state check
beyond the file manifest to include its chunk records; in delete_collection, add
an equivalent absence wait for the collection’s content after issuing deletions.
In `@src/aiq_agent/agents/deep_researcher/register.py`:
- Around line 298-306: The synchronous provider cleanup in the deep-researcher
finalization path and the API job terminal cleanup remain unbounded. Add
provider-level deadlines and call-site timeouts around the
`active_agent.finalize` flow in `register.py` and the corresponding terminal
cleanup in `runner.py`; preserve agent async cancellation semantics and the API
async job lifecycle while ensuring both request/task completions cannot wait
indefinitely.
In `@tests/aiq_agent/jobs/test_runner.py`:
- Around line 1189-1200: Update _get_worker_function_type to safely treat a
missing workflow.use_async_deep_research attribute as False, while preserving
the existing enabled and disabled behavior. Restore coverage using a workflow
configuration without the async flag and add the required job state transition
tests for the job-runner change.
- Around line 888-891: Update the job-runner failure handling that calls
mock_job_store.update_status with JobStatus.FAILURE so externally persisted
errors use a stable sanitized message instead of str(error). Keep detailed
exception information restricted to secret-safe server logging, and adjust the
expectation around update_status accordingly.
---
Outside diff comments:
In `@frontends/ui/src/features/layout/components/ThinkingTab.spec.tsx`:
- Around line 86-120: Add a test alongside the existing source-filter test that
configures only uncited entries in mockState, renders ThinkingTab, selects the
“Cited (0)” radio control, and asserts the filter-specific empty-state message
is shown while the global Sources empty message is not.
🪄 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: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Enterprise
Run ID: 85c6fd14-a7d1-4cfa-9696-5212b4bc4f6d
⛔ Files ignored due to path filters (1)
uv.lockis excluded by!**/*.lock
📒 Files selected for processing (154)
.secrets.baselineconfigs/config_openshell.ymlconfigs/config_web_azure_ai_search.ymlconfigs/openshell/README.mdconfigs/openshell/aiq-research-policy.yamldeploy/.env.exampledeploy/openshell/Dockerfile.aiq-demodocs/source/architecture/agents/sandbox.mddocs/source/customization/configuration-reference.mddocs/source/customization/knowledge-layer.mddocs/source/deployment/index.mddocs/source/deployment/openshell.mddocs/source/deployment/production.mddocs/source/examples/azure-ai-search.mddocs/source/examples/index.mddocs/source/index.mddocs/source/integration/rest-api.mddocs/source/resources/troubleshooting.mdfrontends/aiq_api/src/aiq_api/jobs/runner.pyfrontends/ui/src/adapters/api/websocket-client.tsfrontends/ui/src/app/globals.cssfrontends/ui/src/app/page.tsxfrontends/ui/src/app/providers.tsxfrontends/ui/src/features/chat/components/AgentPrompt.spec.tsxfrontends/ui/src/features/chat/components/AgentPrompt.tsxfrontends/ui/src/features/chat/components/AgentResponse.spec.tsxfrontends/ui/src/features/chat/components/AgentResponse.tsxfrontends/ui/src/features/chat/components/ChatThinking.spec.tsxfrontends/ui/src/features/chat/components/ChatThinking.tsxfrontends/ui/src/features/chat/components/DeepResearchBanner.tsxfrontends/ui/src/features/chat/components/ErrorBanner.tsxfrontends/ui/src/features/chat/components/FileUploadBanner.tsxfrontends/ui/src/features/chat/components/NoSourcesBanner.tsxfrontends/ui/src/features/chat/components/UserMessage.tsxfrontends/ui/src/features/chat/components/index.tsfrontends/ui/src/features/chat/hooks/use-websocket-chat.tsfrontends/ui/src/features/chat/lib/deep-research-trace.spec.tsfrontends/ui/src/features/chat/lib/deep-research-trace.tsfrontends/ui/src/features/chat/lib/intermediate-step-parser.spec.tsfrontends/ui/src/features/chat/lib/intermediate-step-parser.tsfrontends/ui/src/features/chat/lib/session-activity.tsfrontends/ui/src/features/chat/store.spec.tsfrontends/ui/src/features/chat/store.tsfrontends/ui/src/features/chat/types.tsfrontends/ui/src/features/layout/components/AgentCard.spec.tsxfrontends/ui/src/features/layout/components/AgentCard.tsxfrontends/ui/src/features/layout/components/AgentsTab.spec.tsxfrontends/ui/src/features/layout/components/AgentsTab.tsxfrontends/ui/src/features/layout/components/AppBar.spec.tsxfrontends/ui/src/features/layout/components/AppBar.tsxfrontends/ui/src/features/layout/components/ChatArea.autoscroll.spec.tsxfrontends/ui/src/features/layout/components/ChatArea.spec.tsxfrontends/ui/src/features/layout/components/ChatArea.tsxfrontends/ui/src/features/layout/components/CitationCard.spec.tsxfrontends/ui/src/features/layout/components/CitationCard.tsxfrontends/ui/src/features/layout/components/DataConnectionCard.tsxfrontends/ui/src/features/layout/components/DataConnectionsTab.spec.tsxfrontends/ui/src/features/layout/components/DataConnectionsTab.tsxfrontends/ui/src/features/layout/components/DataSourcesPanel.spec.tsxfrontends/ui/src/features/layout/components/DataSourcesPanel.tsxfrontends/ui/src/features/layout/components/FileCard.tsxfrontends/ui/src/features/layout/components/FileSourceCard.spec.tsxfrontends/ui/src/features/layout/components/FileSourceCard.tsxfrontends/ui/src/features/layout/components/FileSourcesTab.spec.tsxfrontends/ui/src/features/layout/components/FileSourcesTab.tsxfrontends/ui/src/features/layout/components/InputArea.tsxfrontends/ui/src/features/layout/components/MainLayout.spec.tsxfrontends/ui/src/features/layout/components/MainLayout.tsxfrontends/ui/src/features/layout/components/ReportCard.spec.tsxfrontends/ui/src/features/layout/components/ReportCard.tsxfrontends/ui/src/features/layout/components/ReportTab.spec.tsxfrontends/ui/src/features/layout/components/ReportTab.tsxfrontends/ui/src/features/layout/components/ResearchPanel.spec.tsxfrontends/ui/src/features/layout/components/ResearchPanel.tsxfrontends/ui/src/features/layout/components/SessionsPanel.spec.tsxfrontends/ui/src/features/layout/components/SessionsPanel.tsxfrontends/ui/src/features/layout/components/SettingsPanel.spec.tsxfrontends/ui/src/features/layout/components/SettingsPanel.tsxfrontends/ui/src/features/layout/components/SourceCard.spec.tsxfrontends/ui/src/features/layout/components/SourceCard.tsxfrontends/ui/src/features/layout/components/TaskCard.spec.tsxfrontends/ui/src/features/layout/components/TaskCard.tsxfrontends/ui/src/features/layout/components/TasksTab.spec.tsxfrontends/ui/src/features/layout/components/TasksTab.tsxfrontends/ui/src/features/layout/components/ThinkingTab.spec.tsxfrontends/ui/src/features/layout/components/ThinkingTab.tsxfrontends/ui/src/features/layout/components/ThoughtCard.spec.tsxfrontends/ui/src/features/layout/components/ThoughtCard.tsxfrontends/ui/src/features/layout/components/index.tsfrontends/ui/src/features/layout/data-sources.spec.tsfrontends/ui/src/features/layout/data-sources.tsfrontends/ui/src/features/layout/index.tsfrontends/ui/src/features/layout/store.spec.tsfrontends/ui/src/features/layout/store.tsfrontends/ui/src/features/layout/types.tsfrontends/ui/src/shared/components/CollapsibleBlock/CollapsibleBlock.tsxfrontends/ui/src/shared/components/Mermaid/MermaidBlock.spec.tsxfrontends/ui/src/shared/components/Mermaid/MermaidBlock.tsxfrontends/ui/src/shared/components/Sources/SourceStrip.spec.tsxfrontends/ui/src/shared/components/Sources/SourceStrip.tsxfrontends/ui/src/shared/components/Sources/parse-references.spec.tsfrontends/ui/src/shared/lib/motion.spec.tsxfrontends/ui/src/shared/lib/scroll.spec.tsfrontends/ui/src/shared/lib/scroll.tspyproject.tomlscripts/README.mdscripts/openshell/check_openshell_readiness.pyscripts/openshell/check_versions.pyscripts/openshell/install_gateway.shscripts/openshell/setup_openshell.shscripts/openshell/smoke_openshell_isolation.pyscripts/openshell/start_openshell_gateway.shscripts/openshell/version_contract.pyscripts/start_e2e.shsources/knowledge_layer/KNOWLEDGE-LAYER-SETUP.mdsources/knowledge_layer/README.mdsources/knowledge_layer/pyproject.tomlsources/knowledge_layer/src/__init__.pysources/knowledge_layer/src/azure_ai_search/README.mdsources/knowledge_layer/src/azure_ai_search/__init__.pysources/knowledge_layer/src/azure_ai_search/adapter.pysources/knowledge_layer/src/register.pysrc/aiq_agent/agents/deep_researcher/agent.pysrc/aiq_agent/agents/deep_researcher/custom_middleware.pysrc/aiq_agent/agents/deep_researcher/deepagents_runtime.pysrc/aiq_agent/agents/deep_researcher/factory.pysrc/aiq_agent/agents/deep_researcher/prompts/writer.j2src/aiq_agent/agents/deep_researcher/register.pysrc/aiq_agent/agents/deep_researcher/sandbox/README.mdsrc/aiq_agent/agents/deep_researcher/sandbox/artifacts/manager.pysrc/aiq_agent/agents/deep_researcher/sandbox/artifacts/store.pysrc/aiq_agent/agents/deep_researcher/sandbox/base.pysrc/aiq_agent/agents/deep_researcher/sandbox/config.pysrc/aiq_agent/agents/deep_researcher/sandbox/logging_utils.pysrc/aiq_agent/agents/deep_researcher/sandbox/providers/openshell.pysrc/aiq_agent/agents/deep_researcher/sandbox/registry.pysrc/aiq_agent/agents/deep_researcher/skills/research/chart-generation/SKILL.mdtests/aiq_agent/agents/deep_researcher/sandbox/test_artifacts.pytests/aiq_agent/agents/deep_researcher/sandbox/test_openshell_live.pytests/aiq_agent/agents/deep_researcher/sandbox/test_openshell_provider.pytests/aiq_agent/agents/deep_researcher/sandbox/test_sandbox_runtime.pytests/aiq_agent/agents/deep_researcher/test_agent.pytests/aiq_agent/agents/deep_researcher/test_chart_artifact_contract.pytests/aiq_agent/agents/deep_researcher/test_custom_middleware.pytests/aiq_agent/agents/deep_researcher/test_deepagents_runtime.pytests/aiq_agent/agents/deep_researcher/test_factory.pytests/aiq_agent/jobs/test_runner.pytests/knowledge_layer_tests/run_adapter_compliance.pytests/knowledge_layer_tests/test_azure_ai_search.pytests/scripts/test_openshell_gateway_installer.pytests/scripts/test_openshell_lifecycle_scripts.pytests/scripts/test_openshell_readiness_checker.pytests/scripts/test_openshell_smoke_wrapper.pytests/scripts/test_openshell_version_tools.py
💤 Files with no reviewable changes (14)
- frontends/ui/src/features/layout/components/FileSourcesTab.spec.tsx
- frontends/ui/src/features/chat/components/ErrorBanner.tsx
- frontends/ui/src/features/layout/components/ResearchPanel.spec.tsx
- frontends/ui/src/features/chat/components/FileUploadBanner.tsx
- frontends/ui/src/features/layout/components/CitationCard.spec.tsx
- frontends/ui/src/features/layout/components/SourceCard.spec.tsx
- frontends/ui/src/features/chat/components/index.ts
- frontends/ui/src/features/chat/components/DeepResearchBanner.tsx
- frontends/ui/src/features/layout/components/ReportCard.spec.tsx
- frontends/ui/src/features/layout/components/SettingsPanel.spec.tsx
- frontends/ui/src/features/chat/components/NoSourcesBanner.tsx
- frontends/ui/src/features/layout/components/index.ts
- frontends/ui/src/features/layout/components/DataConnectionsTab.spec.tsx
- frontends/ui/src/features/layout/components/TasksTab.spec.tsx
📜 Review details
🧰 Additional context used
📓 Path-based instructions (14)
frontends/ui/**/*.{js,ts,jsx,tsx,vue}
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Run npm lint, type-check, and build validation for UI changes in frontends/ui
Files:
frontends/ui/src/features/layout/components/SettingsPanel.tsxfrontends/ui/src/shared/lib/scroll.tsfrontends/ui/src/app/page.tsxfrontends/ui/src/features/layout/components/FileCard.tsxfrontends/ui/src/shared/lib/motion.spec.tsxfrontends/ui/src/shared/lib/scroll.spec.tsfrontends/ui/src/app/providers.tsxfrontends/ui/src/features/layout/data-sources.spec.tsfrontends/ui/src/features/layout/components/DataSourcesPanel.spec.tsxfrontends/ui/src/features/layout/components/TasksTab.tsxfrontends/ui/src/adapters/api/websocket-client.tsfrontends/ui/src/features/layout/components/DataConnectionsTab.tsxfrontends/ui/src/features/layout/components/TaskCard.tsxfrontends/ui/src/features/layout/components/CitationCard.tsxfrontends/ui/src/features/layout/components/ReportTab.tsxfrontends/ui/src/features/layout/data-sources.tsfrontends/ui/src/shared/components/Sources/SourceStrip.spec.tsxfrontends/ui/src/features/chat/components/UserMessage.tsxfrontends/ui/src/features/layout/index.tsfrontends/ui/src/features/layout/store.spec.tsfrontends/ui/src/features/layout/components/AgentsTab.tsxfrontends/ui/src/features/layout/components/ReportTab.spec.tsxfrontends/ui/src/features/layout/components/DataConnectionCard.tsxfrontends/ui/src/features/chat/components/ChatThinking.spec.tsxfrontends/ui/src/features/layout/types.tsfrontends/ui/src/shared/components/Sources/parse-references.spec.tsfrontends/ui/src/features/layout/components/AppBar.tsxfrontends/ui/src/features/layout/components/SourceCard.tsxfrontends/ui/src/features/layout/components/TaskCard.spec.tsxfrontends/ui/src/shared/components/Mermaid/MermaidBlock.spec.tsxfrontends/ui/src/features/layout/components/FileSourceCard.tsxfrontends/ui/src/features/layout/store.tsfrontends/ui/src/features/layout/components/FileSourceCard.spec.tsxfrontends/ui/src/features/chat/components/AgentResponse.tsxfrontends/ui/src/features/layout/components/ChatArea.autoscroll.spec.tsxfrontends/ui/src/features/chat/lib/deep-research-trace.tsfrontends/ui/src/features/chat/lib/session-activity.tsfrontends/ui/src/features/chat/store.spec.tsfrontends/ui/src/shared/components/Mermaid/MermaidBlock.tsxfrontends/ui/src/shared/components/CollapsibleBlock/CollapsibleBlock.tsxfrontends/ui/src/features/layout/components/InputArea.tsxfrontends/ui/src/shared/components/Sources/SourceStrip.tsxfrontends/ui/src/features/chat/components/AgentPrompt.spec.tsxfrontends/ui/src/features/chat/lib/intermediate-step-parser.spec.tsfrontends/ui/src/features/layout/components/ReportCard.tsxfrontends/ui/src/features/layout/components/ThinkingTab.tsxfrontends/ui/src/features/chat/store.tsfrontends/ui/src/features/layout/components/AppBar.spec.tsxfrontends/ui/src/features/layout/components/ChatArea.spec.tsxfrontends/ui/src/features/chat/components/ChatThinking.tsxfrontends/ui/src/features/layout/components/ThoughtCard.spec.tsxfrontends/ui/src/features/layout/components/ThinkingTab.spec.tsxfrontends/ui/src/features/layout/components/MainLayout.spec.tsxfrontends/ui/src/features/chat/lib/deep-research-trace.spec.tsfrontends/ui/src/features/layout/components/AgentCard.spec.tsxfrontends/ui/src/features/layout/components/AgentsTab.spec.tsxfrontends/ui/src/features/chat/hooks/use-websocket-chat.tsfrontends/ui/src/features/chat/components/AgentPrompt.tsxfrontends/ui/src/features/chat/lib/intermediate-step-parser.tsfrontends/ui/src/features/layout/components/MainLayout.tsxfrontends/ui/src/features/layout/components/DataSourcesPanel.tsxfrontends/ui/src/features/layout/components/AgentCard.tsxfrontends/ui/src/features/chat/types.tsfrontends/ui/src/features/layout/components/ResearchPanel.tsxfrontends/ui/src/features/chat/components/AgentResponse.spec.tsxfrontends/ui/src/features/layout/components/ThoughtCard.tsxfrontends/ui/src/features/layout/components/SessionsPanel.tsxfrontends/ui/src/features/layout/components/ChatArea.tsxfrontends/ui/src/features/layout/components/FileSourcesTab.tsxfrontends/ui/src/features/layout/components/SessionsPanel.spec.tsx
frontends/ui/**/*.{ts,tsx,jsx,js}
📄 CodeRabbit inference engine (AGENTS.md)
frontends/ui/**/*.{ts,tsx,jsx,js}: The UI is built with Next.js / React / TypeScript / Tailwind with KUI components; reuse existing KUI components and visual patterns rather than introducing new ones
Validate UI-affecting changes with npm run lint, npm run type-check, and npm run test:ci, and include a screenshot for visible changes
Files:
frontends/ui/src/features/layout/components/SettingsPanel.tsxfrontends/ui/src/shared/lib/scroll.tsfrontends/ui/src/app/page.tsxfrontends/ui/src/features/layout/components/FileCard.tsxfrontends/ui/src/shared/lib/motion.spec.tsxfrontends/ui/src/shared/lib/scroll.spec.tsfrontends/ui/src/app/providers.tsxfrontends/ui/src/features/layout/data-sources.spec.tsfrontends/ui/src/features/layout/components/DataSourcesPanel.spec.tsxfrontends/ui/src/features/layout/components/TasksTab.tsxfrontends/ui/src/adapters/api/websocket-client.tsfrontends/ui/src/features/layout/components/DataConnectionsTab.tsxfrontends/ui/src/features/layout/components/TaskCard.tsxfrontends/ui/src/features/layout/components/CitationCard.tsxfrontends/ui/src/features/layout/components/ReportTab.tsxfrontends/ui/src/features/layout/data-sources.tsfrontends/ui/src/shared/components/Sources/SourceStrip.spec.tsxfrontends/ui/src/features/chat/components/UserMessage.tsxfrontends/ui/src/features/layout/index.tsfrontends/ui/src/features/layout/store.spec.tsfrontends/ui/src/features/layout/components/AgentsTab.tsxfrontends/ui/src/features/layout/components/ReportTab.spec.tsxfrontends/ui/src/features/layout/components/DataConnectionCard.tsxfrontends/ui/src/features/chat/components/ChatThinking.spec.tsxfrontends/ui/src/features/layout/types.tsfrontends/ui/src/shared/components/Sources/parse-references.spec.tsfrontends/ui/src/features/layout/components/AppBar.tsxfrontends/ui/src/features/layout/components/SourceCard.tsxfrontends/ui/src/features/layout/components/TaskCard.spec.tsxfrontends/ui/src/shared/components/Mermaid/MermaidBlock.spec.tsxfrontends/ui/src/features/layout/components/FileSourceCard.tsxfrontends/ui/src/features/layout/store.tsfrontends/ui/src/features/layout/components/FileSourceCard.spec.tsxfrontends/ui/src/features/chat/components/AgentResponse.tsxfrontends/ui/src/features/layout/components/ChatArea.autoscroll.spec.tsxfrontends/ui/src/features/chat/lib/deep-research-trace.tsfrontends/ui/src/features/chat/lib/session-activity.tsfrontends/ui/src/features/chat/store.spec.tsfrontends/ui/src/shared/components/Mermaid/MermaidBlock.tsxfrontends/ui/src/shared/components/CollapsibleBlock/CollapsibleBlock.tsxfrontends/ui/src/features/layout/components/InputArea.tsxfrontends/ui/src/shared/components/Sources/SourceStrip.tsxfrontends/ui/src/features/chat/components/AgentPrompt.spec.tsxfrontends/ui/src/features/chat/lib/intermediate-step-parser.spec.tsfrontends/ui/src/features/layout/components/ReportCard.tsxfrontends/ui/src/features/layout/components/ThinkingTab.tsxfrontends/ui/src/features/chat/store.tsfrontends/ui/src/features/layout/components/AppBar.spec.tsxfrontends/ui/src/features/layout/components/ChatArea.spec.tsxfrontends/ui/src/features/chat/components/ChatThinking.tsxfrontends/ui/src/features/layout/components/ThoughtCard.spec.tsxfrontends/ui/src/features/layout/components/ThinkingTab.spec.tsxfrontends/ui/src/features/layout/components/MainLayout.spec.tsxfrontends/ui/src/features/chat/lib/deep-research-trace.spec.tsfrontends/ui/src/features/layout/components/AgentCard.spec.tsxfrontends/ui/src/features/layout/components/AgentsTab.spec.tsxfrontends/ui/src/features/chat/hooks/use-websocket-chat.tsfrontends/ui/src/features/chat/components/AgentPrompt.tsxfrontends/ui/src/features/chat/lib/intermediate-step-parser.tsfrontends/ui/src/features/layout/components/MainLayout.tsxfrontends/ui/src/features/layout/components/DataSourcesPanel.tsxfrontends/ui/src/features/layout/components/AgentCard.tsxfrontends/ui/src/features/chat/types.tsfrontends/ui/src/features/layout/components/ResearchPanel.tsxfrontends/ui/src/features/chat/components/AgentResponse.spec.tsxfrontends/ui/src/features/layout/components/ThoughtCard.tsxfrontends/ui/src/features/layout/components/SessionsPanel.tsxfrontends/ui/src/features/layout/components/ChatArea.tsxfrontends/ui/src/features/layout/components/FileSourcesTab.tsxfrontends/ui/src/features/layout/components/SessionsPanel.spec.tsx
frontends/ui/**/*
⚙️ CodeRabbit configuration file
frontends/ui/**/*: Review UI changes for strict TypeScript behavior, API contract alignment, auth/session handling, accessible controls,
resilient loading and error states, and report/chat state consistency. Prefer existing UI patterns and require tests
for changed user-visible workflows.
Files:
frontends/ui/src/features/layout/components/SettingsPanel.tsxfrontends/ui/src/shared/lib/scroll.tsfrontends/ui/src/app/page.tsxfrontends/ui/src/features/layout/components/FileCard.tsxfrontends/ui/src/shared/lib/motion.spec.tsxfrontends/ui/src/shared/lib/scroll.spec.tsfrontends/ui/src/app/providers.tsxfrontends/ui/src/features/layout/data-sources.spec.tsfrontends/ui/src/features/layout/components/DataSourcesPanel.spec.tsxfrontends/ui/src/features/layout/components/TasksTab.tsxfrontends/ui/src/adapters/api/websocket-client.tsfrontends/ui/src/features/layout/components/DataConnectionsTab.tsxfrontends/ui/src/features/layout/components/TaskCard.tsxfrontends/ui/src/features/layout/components/CitationCard.tsxfrontends/ui/src/features/layout/components/ReportTab.tsxfrontends/ui/src/features/layout/data-sources.tsfrontends/ui/src/shared/components/Sources/SourceStrip.spec.tsxfrontends/ui/src/features/chat/components/UserMessage.tsxfrontends/ui/src/features/layout/index.tsfrontends/ui/src/features/layout/store.spec.tsfrontends/ui/src/features/layout/components/AgentsTab.tsxfrontends/ui/src/features/layout/components/ReportTab.spec.tsxfrontends/ui/src/features/layout/components/DataConnectionCard.tsxfrontends/ui/src/features/chat/components/ChatThinking.spec.tsxfrontends/ui/src/features/layout/types.tsfrontends/ui/src/shared/components/Sources/parse-references.spec.tsfrontends/ui/src/features/layout/components/AppBar.tsxfrontends/ui/src/features/layout/components/SourceCard.tsxfrontends/ui/src/features/layout/components/TaskCard.spec.tsxfrontends/ui/src/shared/components/Mermaid/MermaidBlock.spec.tsxfrontends/ui/src/features/layout/components/FileSourceCard.tsxfrontends/ui/src/features/layout/store.tsfrontends/ui/src/features/layout/components/FileSourceCard.spec.tsxfrontends/ui/src/features/chat/components/AgentResponse.tsxfrontends/ui/src/features/layout/components/ChatArea.autoscroll.spec.tsxfrontends/ui/src/features/chat/lib/deep-research-trace.tsfrontends/ui/src/features/chat/lib/session-activity.tsfrontends/ui/src/features/chat/store.spec.tsfrontends/ui/src/shared/components/Mermaid/MermaidBlock.tsxfrontends/ui/src/shared/components/CollapsibleBlock/CollapsibleBlock.tsxfrontends/ui/src/features/layout/components/InputArea.tsxfrontends/ui/src/shared/components/Sources/SourceStrip.tsxfrontends/ui/src/features/chat/components/AgentPrompt.spec.tsxfrontends/ui/src/features/chat/lib/intermediate-step-parser.spec.tsfrontends/ui/src/features/layout/components/ReportCard.tsxfrontends/ui/src/features/layout/components/ThinkingTab.tsxfrontends/ui/src/features/chat/store.tsfrontends/ui/src/features/layout/components/AppBar.spec.tsxfrontends/ui/src/features/layout/components/ChatArea.spec.tsxfrontends/ui/src/features/chat/components/ChatThinking.tsxfrontends/ui/src/features/layout/components/ThoughtCard.spec.tsxfrontends/ui/src/features/layout/components/ThinkingTab.spec.tsxfrontends/ui/src/features/layout/components/MainLayout.spec.tsxfrontends/ui/src/features/chat/lib/deep-research-trace.spec.tsfrontends/ui/src/features/layout/components/AgentCard.spec.tsxfrontends/ui/src/features/layout/components/AgentsTab.spec.tsxfrontends/ui/src/features/chat/hooks/use-websocket-chat.tsfrontends/ui/src/features/chat/components/AgentPrompt.tsxfrontends/ui/src/features/chat/lib/intermediate-step-parser.tsfrontends/ui/src/features/layout/components/MainLayout.tsxfrontends/ui/src/features/layout/components/DataSourcesPanel.tsxfrontends/ui/src/features/layout/components/AgentCard.tsxfrontends/ui/src/features/chat/types.tsfrontends/ui/src/features/layout/components/ResearchPanel.tsxfrontends/ui/src/features/chat/components/AgentResponse.spec.tsxfrontends/ui/src/features/layout/components/ThoughtCard.tsxfrontends/ui/src/features/layout/components/SessionsPanel.tsxfrontends/ui/src/features/layout/components/ChatArea.tsxfrontends/ui/src/app/globals.cssfrontends/ui/src/features/layout/components/FileSourcesTab.tsxfrontends/ui/src/features/layout/components/SessionsPanel.spec.tsx
docs/source/**/*
📄 CodeRabbit inference engine (AGENTS.md)
Update the docs under docs/source/ when behavior, configuration, or workflows change
Files:
docs/source/resources/troubleshooting.mddocs/source/deployment/index.mddocs/source/index.mddocs/source/examples/index.mddocs/source/deployment/production.mddocs/source/integration/rest-api.mddocs/source/examples/azure-ai-search.mddocs/source/architecture/agents/sandbox.mddocs/source/customization/configuration-reference.mddocs/source/customization/knowledge-layer.mddocs/source/deployment/openshell.md
{docs/**,README.md,CONTRIBUTING.md,SECURITY.md,CODE-OF-CONDUCT.md}
⚙️ CodeRabbit configuration file
{docs/**,README.md,CONTRIBUTING.md,SECURITY.md,CODE-OF-CONDUCT.md}: Review documentation for command accuracy, branch-name consistency, current CI and copy-pr-bot behavior, public
vs internal boundary clarity, stale examples, and links that no longer match the repository layout.
Files:
docs/source/resources/troubleshooting.mddocs/source/deployment/index.mddocs/source/index.mddocs/source/examples/index.mddocs/source/deployment/production.mddocs/source/integration/rest-api.mddocs/source/examples/azure-ai-search.mddocs/source/architecture/agents/sandbox.mddocs/source/customization/configuration-reference.mddocs/source/customization/knowledge-layer.mddocs/source/deployment/openshell.md
{.github/**,ci/**,.pre-commit-config.yaml,pyproject.toml,uv.lock}
⚙️ CodeRabbit configuration file
{.github/**,ci/**,.pre-commit-config.yaml,pyproject.toml,uv.lock}: Review automation and packaging changes for least-privilege permissions, pinned versions where appropriate,
copy-pr-bot pull-request/ branch behavior, reproducible uv/npm setup, secret handling, and consistency with
the documented validation matrix.
Files:
pyproject.toml
{deploy/**,configs/**}
⚙️ CodeRabbit configuration file
{deploy/**,configs/**}: Review deployment and config changes for secret separation, safe defaults, local-vs-production behavior, Helm and
Docker portability, and documentation parity. Flag committed credentials, environment-specific NVIDIA internals in
public defaults, and changes that make examples diverge from CI-tested paths.
Files:
configs/openshell/README.mddeploy/openshell/Dockerfile.aiq-democonfigs/config_web_azure_ai_search.ymlconfigs/openshell/aiq-research-policy.yamlconfigs/config_openshell.yml
**/*.py
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Run ruff check and ruff format validation for Python code changes
**/*.py: Python code must be linted and formatted with Ruff using line length 120, target Python 3.11, rule sets E,F,W,I,PL,UP, and isort force-single-line configuration
Never commit secrets, tokens, or environment-specific hostnames; use environment variables and SecretStr instead, resolving API keys at runtime
Never print or log secret values, including in tool output or error messages
Missing-secret paths must degrade gracefully (stub/skip), not crash or leak
Do not hand-reformat unrelated code when making changes; match the existing import and formatting style
Files:
src/aiq_agent/agents/deep_researcher/register.pyscripts/openshell/smoke_openshell_isolation.pyscripts/openshell/check_openshell_readiness.pyscripts/openshell/check_versions.pyfrontends/aiq_api/src/aiq_api/jobs/runner.pytests/aiq_agent/jobs/test_runner.pyscripts/openshell/version_contract.pysources/knowledge_layer/src/azure_ai_search/adapter.pytests/aiq_agent/agents/deep_researcher/sandbox/test_openshell_live.py
src/aiq_agent/**/*.py
📄 CodeRabbit inference engine (AGENTS.md)
src/aiq_agent/**/*.py: Respect authenticated data sources by honoring requires_auth, per-user token pass-through, and backend token validators; apply owner guardrails before loading protected report or artifact context into an agent
Do not weaken or bypass AuthMiddleware, validators, or auth gating without a prior design discussion
Files:
src/aiq_agent/agents/deep_researcher/register.py
src/aiq_agent/agents/**/*
⚙️ CodeRabbit configuration file
src/aiq_agent/agents/**/*: Review agent changes for research workflow correctness, graph state transitions, prompt/tool contracts,
HITL behavior, and failure handling. Flag changes that weaken source attribution, report generation,
async cancellation, checkpointing, or data-source selection without focused tests and docs.
Files:
src/aiq_agent/agents/deep_researcher/register.py
{src/aiq_agent/fastapi_extensions/**,frontends/aiq_api/src/aiq_api/**}
⚙️ CodeRabbit configuration file
{src/aiq_agent/fastapi_extensions/**,frontends/aiq_api/src/aiq_api/**}: Treat API, auth, and job-runner changes as externally visible contracts. Check authorization boundaries,
request tracing, async job lifecycle, websocket reconnect behavior, error responses, and cross-user data isolation.
Require tests for route behavior, access decisions, and job state transitions when those surfaces change.
Files:
frontends/aiq_api/src/aiq_api/jobs/runner.py
**/*test*.py
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Run pytest for all behavior changes in Python code
Files:
tests/aiq_agent/jobs/test_runner.pytests/aiq_agent/agents/deep_researcher/sandbox/test_openshell_live.py
sources/**/*.py
📄 CodeRabbit inference engine (AGENTS.md)
New tools and data sources must be NAT functions registered with
@register_functiondecorator
Files:
sources/knowledge_layer/src/azure_ai_search/adapter.py
{src/aiq_agent/knowledge/**,sources/**}
⚙️ CodeRabbit configuration file
{src/aiq_agent/knowledge/**,sources/**}: Review data-source and knowledge-layer changes for optional dependency boundaries, external API error handling,
retry/rate-limit behavior, deterministic tests, and registration consistency. New source packages should include
package metadata, plugin registration when applicable, and source-level tests.
Files:
sources/knowledge_layer/src/azure_ai_search/adapter.py
🪛 ast-grep (0.44.1)
scripts/openshell/smoke_openshell_isolation.py
[error] 81-86: Command coming from incoming request
Context: subprocess.run( # noqa: S603 - fixed argv, no shell, operator-selected interpreter
_command(),
cwd=_REPO_ROOT,
env=_environment(args),
check=False,
)
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').
(subprocess-from-request)
scripts/openshell/check_openshell_readiness.py
[error] 53-59: Command coming from incoming request
Context: subprocess.run(
[str(binary), "--version"],
check=False,
capture_output=True,
text=True,
timeout=10,
)
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').
(subprocess-from-request)
scripts/openshell/check_versions.py
[error] 46-46: Use of unsanitized data to create processes
Context: subprocess.run(command, check=False, capture_output=True, text=True, timeout=15)
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').
(os-system-unsanitized-data)
[error] 46-46: Command coming from incoming request
Context: subprocess.run(command, check=False, capture_output=True, text=True, timeout=15)
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').
(subprocess-from-request)
[info] 226-226: use jsonify instead of json.dumps for JSON output
Context: json.dumps(asdict(report), sort_keys=True)
Note: [CWE-116] Improper Encoding or Escaping of Output.
(use-jsonify)
scripts/openshell/version_contract.py
[info] 76-76: use jsonify instead of json.dumps for JSON output
Context: json.dumps(asdict(contract), sort_keys=True)
Note: [CWE-116] Improper Encoding or Escaping of Output.
(use-jsonify)
sources/knowledge_layer/src/azure_ai_search/adapter.py
[info] 161-161: use jsonify instead of json.dumps for JSON output
Context: json.dumps(marker, separators=(",", ":"), sort_keys=True)
Note: [CWE-116] Improper Encoding or Escaping of Output.
(use-jsonify)
[info] 255-255: use jsonify instead of json.dumps for JSON output
Context: json.dumps(payload, default=_json_default, ensure_ascii=False, separators=(",", ":"))
Note: [CWE-116] Improper Encoding or Escaping of Output.
(use-jsonify)
[info] 651-651: use jsonify instead of json.dumps for JSON output
Context: json.dumps(merged_metadata, separators=(",", ":"), sort_keys=True)
Note: [CWE-116] Improper Encoding or Escaping of Output.
(use-jsonify)
[info] 692-692: use jsonify instead of json.dumps for JSON output
Context: json.dumps(metadata, separators=(",", ":"), sort_keys=True)
Note: [CWE-116] Improper Encoding or Escaping of Output.
(use-jsonify)
[info] 761-761: use jsonify instead of json.dumps for JSON output
Context: json.dumps(file_metadata, separators=(",", ":"), sort_keys=True)
Note: [CWE-116] Improper Encoding or Escaping of Output.
(use-jsonify)
[info] 950-950: use jsonify instead of json.dumps for JSON output
Context: json.dumps(metadata, separators=(",", ":"), sort_keys=True)
Note: [CWE-116] Improper Encoding or Escaping of Output.
(use-jsonify)
tests/aiq_agent/agents/deep_researcher/sandbox/test_openshell_live.py
[info] 408-408: use jsonify instead of json.dumps for JSON output
Context: json.dumps(events, default=str)
Note: [CWE-116] Improper Encoding or Escaping of Output.
(use-jsonify)
🪛 LanguageTool
scripts/README.md
[style] ~88-~88: Consider a different adjective to strengthen your wording.
Context: ...Mode Starts the NAT FastAPI server for deep research with async job support. ```ba...
(DEEP_PROFOUND)
docs/source/deployment/openshell.md
[style] ~48-~48: Consider a different adjective to strengthen your wording.
Context: ...penShell executes code generated during deep research. AI-Q orchestration, inference...
(DEEP_PROFOUND)
🪛 Stylelint (17.14.0)
frontends/ui/src/app/globals.css
[error] 130-130: Expected "optimizeLegibility" to be "optimizelegibility" (value-keyword-case)
(value-keyword-case)
ebd4826 to
860114e
Compare
There was a problem hiding this comment.
Caution
Inline review comments failed to post. This is likely due to GitHub's internal server error or limits when posting large numbers of comments. If you are seeing this consistently it is likely a permissions issue. Please check "Moderation" -> "Code review limits" under your organization settings.
🛑 Comments failed to post (33)
docs/source/customization/configuration-reference.md (1)
605-605: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Correct the configuration-profile count.
The introduction says there are nine profiles, but this table now lists ten after adding the Azure profile. Update the count to avoid misleading operators.
As per path instructions, review documentation for “stale examples”.
🤖 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 `@docs/source/customization/configuration-reference.md` at line 605, Update the configuration-profile count in the introduction of configuration-reference.md from nine to ten, matching the ten profiles listed in the table, including configs/config_web_azure_ai_search.yml. Review nearby documentation for stale examples of the old count and update only those references.Source: Path instructions
docs/source/customization/knowledge-layer.md (1)
488-489: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Complete the environment-variable table for Azure AI Search.
Add
AZURE_SEARCH_ENDPOINT,AZURE_SEARCH_API_KEY,AIQ_AZURE_SEARCH_INDEX_PREFIX, andAIQ_EMBED_DIM. Also include Azure in the existingAIQ_EMBED_MODEL/AIQ_EMBED_BASE_URLrow; otherwise this central reference contradicts Lines 181-189.As per path instructions, review documentation for “command accuracy” and “stale examples.”
🤖 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 `@docs/source/customization/knowledge-layer.md` around lines 488 - 489, Update the environment-variable table in the knowledge-layer customization documentation to include AZURE_SEARCH_ENDPOINT, AZURE_SEARCH_API_KEY, AIQ_AZURE_SEARCH_INDEX_PREFIX, and AIQ_EMBED_DIM. Extend the existing AIQ_EMBED_MODEL/AIQ_EMBED_BASE_URL entry to cover Azure AI Search, keeping the table consistent with the Azure configuration documented in the earlier section and correcting any stale or inaccurate examples encountered there.Source: Path instructions
docs/source/deployment/openshell.md (1)
203-211: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
Make the production command safe for external gateways.
The text says
--reuse-existingmust be used unless the launcher may start a local packaged service, but the canonical command omits it. External-gateway operators will therefore run the wrong lifecycle mode.Proposed correction
./scripts/openshell/start_openshell_gateway.sh \ --gateway-name openshell \ + --reuse-existing \ --image-name aiq-openshell-demo:latest \ --policy-file configs/openshell/generated/aiq-openshell-policy.yamlDocument omitting the flag as the local packaged-service variant.
As per path instructions, review documentation for “command accuracy” and current deployment behavior.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.execution, and deletion capabilities. Omit `--reuse-existing` only when the gateway is a local packaged service that the launcher may start through systemd.🤖 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 `@docs/source/deployment/openshell.md` around lines 203 - 211, Update the canonical openshell gateway command in the deployment documentation to include --reuse-existing for external gateways. Clearly label any command that omits this flag as the local packaged-service variant where the launcher may start systemd, and keep the documented lifecycle behavior consistent with the surrounding guidance.Source: Path instructions
frontends/ui/src/app/globals.css (2)
88-88: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
Increase the subtle-text token contrast.
These colors provide approximately 2.6:1 contrast in light mode and 3.1:1 in dark mode. They are used for small labels and metadata that require at least 4.5:1 contrast.
Validate both theme values against their base and raised surfaces after adjustment.
As per path instructions, review UI changes for accessible controls and require tests for changed user-visible workflows.
Also applies to: 113-113
🤖 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 `@frontends/ui/src/app/globals.css` at line 88, Update the light and dark theme values for --text-color-subtle to achieve at least 4.5:1 contrast against their respective base and raised surfaces, then validate both theme combinations. Add or update tests covering the affected user-visible UI workflows and accessible controls.Source: Path instructions
130-130: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Use Stylelint’s canonical keyword casing.
The supplied validation reports this declaration as an error.
Proposed fix
- text-rendering: optimizeLegibility; + text-rendering: optimizelegibility;📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.text-rendering: optimizelegibility;🧰 Tools
🪛 Stylelint (17.14.0)
[error] 130-130: Expected "optimizeLegibility" to be "optimizelegibility" (value-keyword-case)
(value-keyword-case)
🤖 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 `@frontends/ui/src/app/globals.css` at line 130, Update the text-rendering declaration to use Stylelint’s canonical casing for the optimizeLegibility keyword, while preserving the existing property and value.Source: Linters/SAST tools
frontends/ui/src/features/chat/components/AgentPrompt.tsx (2)
143-154: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
Use the prompt type instead of relying on exact English copy.
A
type="approval"prompt whose wording differs fromAPPROVAL_PROMPT_REbecomes a clarification prompt with text/cancel controls. Preserve compatibility fallback if needed, but honor the explicit contract first.Proposed fix
export const AgentPrompt: FC<AgentPromptProps> = ({ - type: _type, + type, ... - const isApprovalPrompt = APPROVAL_PROMPT_RE.test(content) + const isApprovalPrompt = type === 'approval' || APPROVAL_PROMPT_RE.test(content)Add coverage for an approval type whose content does not contain the legacy phrase.
As per path instructions, review UI changes for “API contract alignment” and “require tests for changed user-visible workflows.”
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.export const AgentPrompt: FC<AgentPromptProps> = ({ type, content, options = [], isResponded = false, response, variant = 'default', }) => { const respondToInteractionFn = useChatStore((state) => state.respondToInteractionFn) const isApprovalPrompt = type === 'approval' || APPROVAL_PROMPT_RE.test(content) const canRespond = !isResponded && !!respondToInteractionFn const showApprovalButtons = isApprovalPrompt && canRespond🤖 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 `@frontends/ui/src/features/chat/components/AgentPrompt.tsx` around lines 143 - 154, Update AgentPrompt to use the destructured prompt type as the primary approval determination, treating type="approval" as an approval prompt regardless of content; retain the APPROVAL_PROMPT_RE check only as a compatibility fallback if required. Add coverage for an approval-typed prompt whose content lacks the legacy phrase, verifying the approval controls are rendered.Source: Path instructions
200-237: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
Do not let global shortcuts override focused controls.
When keyboard focus is on Reject, pressing Enter reaches this window listener, calls
handleApprove(), and prevents the button’s native reject activation. Ignore interactive event targets or scope shortcuts to the prompt container; add a regression test activating Reject with Enter.As per path instructions, review UI changes for “accessible controls” and require tests for changed workflows.
🤖 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 `@frontends/ui/src/features/chat/components/AgentPrompt.tsx` around lines 200 - 237, The global keydown handler in the AgentPrompt useEffect must not intercept activation of focused interactive controls, especially the Reject button. Extend isTyping or otherwise detect focused buttons and other interactive targets before handling shortcuts, preserving native Enter/activation behavior; add a regression test that focuses Reject and activates it with Enter, verifying rejection occurs instead of handleApprove.Source: Path instructions
frontends/ui/src/features/chat/components/ChatThinking.tsx (3)
66-71: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Normalize rounded seconds before splitting minutes.
For example,
119600msrenders as1m 60s. Round once and use modulo arithmetic.Proposed fix
const formatDuration = (ms: number): string => { const seconds = Math.max(0, ms) / 1000 if (seconds < 60) return `${seconds.toFixed(1)}s` - const m = Math.floor(seconds / 60) - const s = Math.round(seconds % 60) + const totalSeconds = Math.round(seconds) + const m = Math.floor(totalSeconds / 60) + const s = totalSeconds % 60 return `${m}m ${s}s` }📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.const formatDuration = (ms: number): string => { const seconds = Math.max(0, ms) / 1000 if (seconds < 60) return `${seconds.toFixed(1)}s` const totalSeconds = Math.round(seconds) const m = Math.floor(totalSeconds / 60) const s = totalSeconds % 60 return `${m}m ${s}s`🤖 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 `@frontends/ui/src/features/chat/components/ChatThinking.tsx` around lines 66 - 71, Update formatDuration to round the non-negative duration to whole seconds before calculating minutes and remaining seconds, then derive both values using quotient and modulo arithmetic so carry-over values such as 119600ms render as 2m 0s while sub-minute durations retain the existing one-decimal format.
179-198: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
Do not deduplicate calls using only their display label.
This pass removes every nested row sharing a top-level label before checking
isKnownToolorargSummary. Repeated searches with different inputs can therefore be dropped or have one call’s arguments assigned to another; non-tool rows can also be removed.Prefer preserving ambiguous rows and let the exact label/input grouping below deduplicate identifiable calls:
Safe fallback
- const topLevelLabels = new Set( - steps.filter((s) => s.isTopLevel).map((s) => getToolLabel(s.functionName).label) - ) - const nestedSummaries = new Map<string, string>() - for (const step of steps) { - if (step.isTopLevel || !step.argSummary) continue - const label = getToolLabel(step.functionName).label - const existing = nestedSummaries.get(label) - if (!existing || step.argSummary.length > existing.length) { - nestedSummaries.set(label, step.argSummary) - } - } - const enriched = steps - .filter((s) => s.isTopLevel || !topLevelLabels.has(getToolLabel(s.functionName).label)) - .map((step) => { - if (!step.isTopLevel) return step - const nestedSummary = nestedSummaries.get(getToolLabel(step.functionName).label) - if (!nestedSummary || nestedSummary.length <= (step.argSummary?.length ?? 0)) return step - return { ...step, argSummary: nestedSummary } - }) + const enriched = stepsAdd regression cases for same-label calls with different arguments and same-label non-tool rows.
As per path instructions, UI changes must preserve report/chat state consistency and include focused tests.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.const enriched = steps🤖 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 `@frontends/ui/src/features/chat/components/ChatThinking.tsx` around lines 179 - 198, Replace the label-only filtering and argument merging in the topLevelLabels/nestedSummaries/enriched flow, since same-label calls may have different inputs and non-tool rows must not be removed. Preserve ambiguous rows and defer deduplication to the existing exact label/input grouping logic below, while retaining identifiable-call deduplication. Add focused regression tests for same-label calls with different arguments and same-label non-tool rows, ensuring report and chat state remain consistent.Source: Path instructions
333-337: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
Propagate terminal phase failures to unfinished child calls.
An incomplete child under an errored or interrupted phase currently renders as
done. Pass the parent state so unfinished calls retain the correct terminal outcome.Proposed fix
-const childState = (child: ThinkingStep, isLastInRunningPhase: boolean): NodeState => { +const childState = ( + child: ThinkingStep, + parentState: NodeState, + isLastChild: boolean +): NodeState => { if (child.status === 'error') return 'error' if (child.status === 'success' || child.isComplete) return 'done' - return isLastInRunningPhase ? 'running' : 'done' + if (parentState === 'running') return isLastChild ? 'running' : 'done' + if (parentState === 'error') return 'error' + if (parentState === 'interrupted') return 'interrupted' + if (parentState === 'waiting') return 'waiting' + return 'done' }- status={childState(child, state === 'running' && childIndex === childCount - 1)} + status={childState(child, state, childIndex === childCount - 1)}Add coverage for incomplete children beneath error and interrupted phases.
As per path instructions, UI changes must preserve report/chat state consistency and include focused tests.
Also applies to: 512-519
🤖 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 `@frontends/ui/src/features/chat/components/ChatThinking.tsx` around lines 333 - 337, Update childState and its callers to accept the parent phase state, propagating error or interrupted terminal outcomes to children that are not complete instead of marking them done. Preserve child-level error/success handling and running-phase behavior for active phases. Add focused tests covering incomplete children under errored and interrupted phases while preserving report/chat state consistency.Source: Path instructions
frontends/ui/src/features/chat/lib/deep-research-trace.ts (1)
35-56: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
Deduplicate trace updates by event ID, not call contents.
Distinct calls with the same function and arguments are currently merged. Fold updates can also leave stale explanation content. Use the tool/fold ID as identity and replace newer snapshots of that ID.
Proposed fix
const sameCall = (a: ThinkingStep, b: ThinkingStep): boolean => - a.isTopLevel === b.isTopLevel && - a.functionName === b.functionName && - (a.argSummary ?? '') === (b.argSummary ?? '') + a.id === b.id const sameFold = (a: ThinkingStep, b: ThinkingStep): boolean => - a.functionName === b.functionName && a.content === b.content + a.id === b.id ... if (isFold(step)) { const prev = out[out.length - 1] - if (prev && isFold(prev) && sameFold(prev, step)) continue + if (prev && isFold(prev) && sameFold(prev, step)) { + out[out.length - 1] = step + continue + }Add regression coverage for distinct IDs with identical inputs and updated snapshots sharing one ID.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.const sameCall = (a: ThinkingStep, b: ThinkingStep): boolean => a.id === b.id const sameFold = (a: ThinkingStep, b: ThinkingStep): boolean => a.id === b.id let lastToolIndex = -1 for (const step of steps) { if (step.category === 'tools') { const lastTool = lastToolIndex >= 0 ? out[lastToolIndex] : undefined if (lastTool && sameCall(lastTool, step)) { out[lastToolIndex] = { ...step, id: lastTool.id } } else { out.push(step) lastToolIndex = out.length - 1 } continue } if (isFold(step)) { const prev = out[out.length - 1] if (prev && isFold(prev) && sameFold(prev, step)) { out[out.length - 1] = step continue }🤖 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 `@frontends/ui/src/features/chat/lib/deep-research-trace.ts` around lines 35 - 56, Update the trace deduplication logic in the step-processing flow, including sameCall, sameFold, and lastToolIndex, to use each tool or fold step’s event ID as identity rather than function, arguments, or content. Replace an existing snapshot when the ID matches, while preserving distinct steps with identical inputs and ensuring newer snapshots replace stale explanation content. Add regression coverage for distinct IDs with identical inputs and updated snapshots sharing one ID.frontends/ui/src/features/layout/components/AgentCard.spec.tsx (1)
219-225: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win
Cover the non-expandable ARIA state.
Extend the disabled/no-content case to assert
aria-expanded="false"and noaria-controls, preventing references to an unrendered region.As per path instructions, review UI changes for “accessible controls” and require tests for changed workflows.
🤖 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 `@frontends/ui/src/features/layout/components/AgentCard.spec.tsx` around lines 219 - 225, Extend the disabled/no-content AgentCard test to verify its accessible button state: assert aria-expanded is "false" and aria-controls is absent when no content region is rendered. Keep the existing expandable-case assertions unchanged.Source: Path instructions
frontends/ui/src/features/layout/components/AgentCard.tsx (1)
102-108: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Correct the disabled AgentCard expansion semantics. A contentless card currently claims to be expanded and references an absent controlled region.
frontends/ui/src/features/layout/components/AgentCard.tsx#L102-L108: setaria-expandedto false and omitaria-controlswhencanExpandis false.frontends/ui/src/features/layout/components/AgentCard.spec.tsx#L219-L225: assert those attributes for the no-content case.As per path instructions, review UI changes for accessible controls and require tests for changed workflows.
📍 Affects 2 files
frontends/ui/src/features/layout/components/AgentCard.tsx#L102-L108(this comment)frontends/ui/src/features/layout/components/AgentCard.spec.tsx#L219-L225🤖 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 `@frontends/ui/src/features/layout/components/AgentCard.tsx` around lines 102 - 108, Update the AgentCard button’s accessibility attributes so aria-expanded is false and aria-controls is omitted whenever canExpand is false, while preserving the existing expanded state and controlled-region reference for expandable cards. Add assertions in frontends/ui/src/features/layout/components/AgentCard.spec.tsx:219-225 for the no-content case; frontends/ui/src/features/layout/components/AgentCard.tsx:102-108 requires the implementation change.Source: Path instructions
frontends/ui/src/features/layout/components/AppBar.spec.tsx (1)
105-122: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win
Cover both toggle directions.
Add cases where
rightPanelis alreadydata-sourcesand wherethemeisdark; assertcloseRightPanel()andsetTheme('light')respectively.As per path instructions, “Prefer existing UI patterns and require tests for changed user-visible workflows.” <path_instructions>
🤖 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 `@frontends/ui/src/features/layout/components/AppBar.spec.tsx` around lines 105 - 122, Add tests in the AppBar interaction suite covering the already-open data-sources state and the dark-theme state. Configure the relevant mocked state before rendering AppBar, click the existing Add Sources and theme-toggle buttons, and assert mockCloseRightPanel and mockSetTheme are called with 'light' respectively, while preserving the existing opposite-direction cases.Source: Path instructions
frontends/ui/src/features/layout/components/DataSourcesPanel.tsx (3)
220-245: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash set -euo pipefail # Locate the component and related tests. git ls-files 'frontends/ui/src/features/layout/components/DataSourcesPanel.tsx' \ 'frontends/ui/src/features/layout/components/*DataSources*' \ 'frontends/ui/src/features/layout/**/__tests__/*' \ 'frontends/ui/src/features/layout/**/*.test.*' \ 'frontends/ui/src/features/layout/**/*.spec.*' # Search for focus handling in the feature area. rg -n --hidden --glob 'frontends/ui/src/features/layout/**' \ 'focus|focused|restoreFocus|triggerRef|buttonRef|aria-hidden|onClose|onOpen|useRef|useEffect' \ frontends/ui/src/features/layout # Show a compact AST outline for the target component if present. ast-grep outline frontends/ui/src/features/layout/components/DataSourcesPanel.tsx --view expanded || trueRepository: NVIDIA-AI-Blueprints/aiq
Length of output: 16704
🏁 Script executed:
#!/bin/bash set -euo pipefail file='frontends/ui/src/features/layout/components/DataSourcesPanel.tsx' echo "=== FILE EXISTS ===" git ls-files "$file" echo "=== KEY EXCERPT A ===" sed -n '1,340p' "$file" | cat -n | sed -n '1,340p' echo "=== TEST SEARCH ===" rg -n --hidden --glob 'frontends/ui/src/features/layout/**/*.{test,spec}.{ts,tsx,js,jsx}' \ 'DataSourcesPanel|data sources|focus|aria-hidden|trigger' frontends/ui/src/features/layout || trueRepository: NVIDIA-AI-Blueprints/aiq
Length of output: 25165
🏁 Script executed:
#!/bin/bash set -euo pipefail file='frontends/ui/src/features/layout/components/DataSourcesPanel.tsx' echo "=== 180-310 ===" sed -n '180,310p' "$file" | cat -n echo "=== 310-END ===" sed -n '310,420p' "$file" | cat -nRepository: NVIDIA-AI-Blueprints/aiq
Length of output: 11426
🏁 Script executed:
#!/bin/bash set -euo pipefail rg -n --hidden --glob 'frontends/ui/src/**/*.{ts,tsx,js,jsx}' \ 'focus\(\)|restore.*focus|return.*focus|triggerRef|buttonRef|onClose.*focus|close.*focus' \ frontends/ui/src | head -n 200Repository: NVIDIA-AI-Blueprints/aiq
Length of output: 1139
🏁 Script executed:
#!/bin/bash set -euo pipefail echo "=== STORE: close/open panel logic ===" rg -n --hidden --glob 'frontends/ui/src/features/layout/**' \ 'closeRightPanel|rightPanel|data-sources|open.*data sources|add data sources|setRightPanel|openRightPanel' \ frontends/ui/src/features/layout/store* frontends/ui/src/features/layout/components/AppBar.tsx frontends/ui/src/features/layout/components/MainLayout.tsx frontends/ui/src/features/layout/components/DataSourcesPanel.spec.tsx echo echo "=== APPBAR EXCERPT ===" sed -n '1,420p' frontends/ui/src/features/layout/components/AppBar.tsx | cat -n | sed -n '1,420p' echo echo "=== STORE EXCERPT ===" sed -n '1,360p' frontends/ui/src/features/layout/store.ts | cat -n | sed -n '1,360p' echo echo "=== DATASOURCESPANEL SPEC CLOSE AREA ===" sed -n '1,340p' frontends/ui/src/features/layout/components/DataSourcesPanel.spec.tsx | cat -n | sed -n '1,340p'Repository: NVIDIA-AI-Blueprints/aiq
Length of output: 50380
🏁 Script executed:
#!/bin/bash set -euo pipefail echo "=== STORE SEARCH ===" rg -n --hidden --glob 'frontends/ui/src/features/layout/store.ts' \ 'closeRightPanel|rightPanel|setRightPanel|openRightPanel|data-sources' \ frontends/ui/src/features/layout/store.ts echo echo "=== APPBAR SEARCH ===" rg -n --hidden --glob 'frontends/ui/src/features/layout/components/AppBar.tsx' \ 'data sources|add data sources|rightPanel|closeRightPanel|openRightPanel|setRightPanel|button|focus|ref' \ frontends/ui/src/features/layout/components/AppBar.tsx echo echo "=== DATA SOURCES SPEC SEARCH ===" rg -n --hidden --glob 'frontends/ui/src/features/layout/components/DataSourcesPanel.spec.tsx' \ 'close|focus|aria-hidden|trigger|button|open|panel' \ frontends/ui/src/features/layout/components/DataSourcesPanel.spec.tsxRepository: NVIDIA-AI-Blueprints/aiq
Length of output: 4740
🏁 Script executed:
#!/bin/bash set -euo pipefail echo "=== STORE (1-260) ===" sed -n '1,260p' frontends/ui/src/features/layout/store.ts | cat -n | sed -n '1,260p' echo echo "=== APPBAR (240-360) ===" sed -n '240,360p' frontends/ui/src/features/layout/components/AppBar.tsx | cat -n | sed -n '240,360p' echo echo "=== DATASOURCESPANEL SPEC (1-340) ===" sed -n '1,340p' frontends/ui/src/features/layout/components/DataSourcesPanel.spec.tsx | cat -n | sed -n '1,340p'Repository: NVIDIA-AI-Blueprints/aiq
Length of output: 26374
🏁 Script executed:
#!/bin/bash set -euo pipefail python3 - <<'PY' from pathlib import Path files = [ ('frontends/ui/src/features/layout/store.ts', 1, 220), ('frontends/ui/src/features/layout/components/AppBar.tsx', 240, 360), ('frontends/ui/src/features/layout/components/DataSourcesPanel.spec.tsx', 1, 340), ] for path, start, end in files: print(f"=== {path} {start}-{end} ===") lines = Path(path).read_text().splitlines() for i in range(start-1, min(end, len(lines))): print(f"{i+1:4d} {lines[i]}") print() PYRepository: NVIDIA-AI-Blueprints/aiq
Length of output: 28952
Return focus to the Add data sources trigger on close
The close button leaves focus inside an
aria-hiddenpanel. Restore focus to the AppBar trigger when dismissing the panel, and add a regression test for the close flow.🤖 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 `@frontends/ui/src/features/layout/components/DataSourcesPanel.tsx` around lines 220 - 245, Update the DataSourcesPanel close flow to move focus back to the AppBar “Add data sources” trigger before or when the panel becomes aria-hidden, rather than leaving focus inside the panel. Reuse the trigger’s existing ref or accessible identifier, and add a regression test that opens the panel, closes it, and verifies focus returns to that trigger.Source: Path instructions
316-365: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Avoid nesting the switch inside another interactive control.
The
role="button"row and its childSwitchcreate duplicate keyboard stops and conflicting semantics for one action. Keep the row non-interactive and use the KUISwitchas the sole control.As per path instructions, UI changes must be reviewed for accessible controls.
🤖 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 `@frontends/ui/src/features/layout/components/DataSourcesPanel.tsx` around lines 316 - 365, Remove the row’s interactive button semantics and handlers from the Flex container, including role, tabIndex, click, keyboard, and button-specific ARIA attributes. Keep the KUI Switch as the sole interactive control, preserving its checked state, disabled behavior, accessible label, and handleToggleAll callback; retain suitable visual styling without relying on interactive-row behavior.Source: Path instructions
388-395: 🔒 Security & Privacy | 🟠 Major | ⚡ Quick win
Pass the authentication token when retrying.
This retry uses
fetchDataSources()while the other refresh path passesidToken; protected-source retries can therefore repeat an unauthenticated request. UsefetchDataSources(idToken)and test token forwarding.As per path instructions, UI changes must preserve auth/session handling and API contract alignment.
🤖 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 `@frontends/ui/src/features/layout/components/DataSourcesPanel.tsx` around lines 388 - 395, Update the Retry button’s onClick handler in DataSourcesPanel to call fetchDataSources with the current idToken, matching the existing authenticated refresh path and preserving the API contract. Add or update the relevant test to verify the token is forwarded on retry.Source: Path instructions
frontends/ui/src/features/layout/components/MainLayout.spec.tsx (1)
121-125: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Assert that the Data Sources panel is absent.
The test name promises both panels are hidden, but it only checks
sessions-panel. Add the correspondingdata-sources-panelassertion.Proposed fix
expect(screen.getByTestId('app-bar')).toBeInTheDocument() expect(screen.queryByTestId('sessions-panel')).not.toBeInTheDocument() +expect(screen.queryByTestId('data-sources-panel')).not.toBeInTheDocument()As per path instructions, “require tests for changed user-visible workflows.”
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.test('hides the sessions sidebar and data sources panel when unauthenticated', () => { render(<MainLayout />) expect(screen.getByTestId('app-bar')).toBeInTheDocument() expect(screen.queryByTestId('sessions-panel')).not.toBeInTheDocument() expect(screen.queryByTestId('data-sources-panel')).not.toBeInTheDocument()🤖 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 `@frontends/ui/src/features/layout/components/MainLayout.spec.tsx` around lines 121 - 125, Update the unauthenticated MainLayout test to also assert that the element identified by data-sources-panel is absent, matching the existing sessions-panel assertion and the test’s stated coverage.Source: Path instructions
frontends/ui/src/features/layout/components/SessionsPanel.tsx (2)
303-317: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
Restore visible keyboard focus on sidebar inputs.
Both inputs use
outline-nonewithout a replacement focus style, leaving keyboard users without a visible focus indicator.
frontends/ui/src/features/layout/components/SessionsPanel.tsx#L303-L317: add afocus-visiblering or the existing KUI input pattern to the search input.frontends/ui/src/features/layout/components/SessionsPanel.tsx#L612-L622: add the same visible focus treatment to the rename input.As per path instructions, review UI changes for accessible controls.
📍 Affects 1 file
frontends/ui/src/features/layout/components/SessionsPanel.tsx#L303-L317(this comment)frontends/ui/src/features/layout/components/SessionsPanel.tsx#L612-L622🤖 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 `@frontends/ui/src/features/layout/components/SessionsPanel.tsx` around lines 303 - 317, Restore a visible keyboard focus indicator on both inputs in SessionsPanel.tsx: add the existing KUI input focus treatment or an equivalent focus-visible ring to the search input at lines 303-317 and the rename input at lines 612-622, replacing the ineffective outline-none-only styling while preserving their current behavior.Source: Path instructions
418-424: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
Apply the navigation guard to the empty-state action.
During streaming or pending HITL, the top “New Session” action is disabled, but this button still invokes
handleNewSession. An active unsaved session with no named history can therefore bypass the guard.Proposed fix
-<Button kind="secondary" size="small" onClick={handleNewSession} className="mt-1"> +<Button + kind="secondary" + size="small" + onClick={handleNewSession} + disabled={isNavigationBlocked} + className="mt-1" +>Add a regression test for the empty-state button during streaming and pending HITL. As per path instructions, review session handling and require tests for changed user-visible workflows.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.{!(searchOpen && searchQuery.trim()) && ( <Button kind="secondary" size="small" onClick={handleNewSession} disabled={isNavigationBlocked} className="mt-1" > <Flex align="center" gap="2"> <Plus className="h-4 w-4" /> <Text kind="label/bold/sm">Start a new session</Text> </Flex> </Button>🤖 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 `@frontends/ui/src/features/layout/components/SessionsPanel.tsx` around lines 418 - 424, Apply the same streaming and pending-HITL navigation guard used by the top “New Session” action to the empty-state button’s handleNewSession path in SessionsPanel. Preserve the existing search visibility condition, and add regression coverage verifying the empty-state button cannot navigate during streaming or pending HITL.Source: Path instructions
frontends/ui/src/features/layout/components/ThinkingTab.tsx (1)
97-106: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Use a distinct empty state for
Cited (0). The current branch conflates a zero-match filter with having no sources.
frontends/ui/src/features/layout/components/ThinkingTab.tsx#L97-L106: render “No cited sources yet” when uncited sources exist but the Cited filter is empty.frontends/ui/src/features/layout/components/ThinkingTab.spec.tsx#L86-L120: add a regression test containing only uncited sources and selectCited (0).As per path instructions, review UI changes for resilient states, state consistency, and workflow tests.
📍 Affects 2 files
frontends/ui/src/features/layout/components/ThinkingTab.tsx#L97-L106(this comment)frontends/ui/src/features/layout/components/ThinkingTab.spec.tsx#L86-L120🤖 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 `@frontends/ui/src/features/layout/components/ThinkingTab.tsx` around lines 97 - 106, Update the empty-state branch in ThinkingTab so a non-empty source collection with no cited items displays “No cited sources yet,” while the existing research-empty message remains for genuinely source-free states; add a regression test in ThinkingTab.spec.tsx covering only uncited sources and selecting Cited (0).Source: Path instructions
scripts/openshell/check_versions.py (1)
24-24: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
sed -n '1,220p' scripts/openshell/check_versions.pyRepository: NVIDIA-AI-Blueprints/aiq
Length of output: 8704
🏁 Script executed:
python3 - <<'PY' import re pat = re.compile(r"\d+\.\d+\.\d+(?:(?:-dev\.|\.dev)\d+(?:\+g[0-9a-fA-F]+)?)?") samples = [ "0.0.80", "0.0.80rc1", "0.0.80.post1", "0.0.80+local", "0.0.80-dev.1", "0.0.80.dev1+gabc1234", "v0.0.80rc1", "version 0.0.80.post1 build", ] for s in samples: m = pat.search(s) print(f"{s!r:28} -> {m.group(0) if m else None!r}") PYRepository: NVIDIA-AI-Blueprints/aiq
Length of output: 510
Reject unsupported suffixes in
_VERSION_PATTERN._extract_version()matches prefixes inside0.0.80rc1,0.0.80.post1, and0.0.80+local, which can make unsupported versions look certified. Add a suffix boundary/lookahead and cover rc, post, and local-version cases in tests.🤖 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 `@scripts/openshell/check_versions.py` at line 24, Update _VERSION_PATTERN used by _extract_version() to require a valid suffix boundary after the supported version formats, preventing matches within rc, post, or local-version strings. Add tests covering 0.0.80rc1, 0.0.80.post1, and 0.0.80+local, while preserving matches for the existing supported development and git-suffix forms.scripts/openshell/setup_openshell.sh (2)
83-83: 📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win
Derive help examples from the certified version contract.
Hardcoding
0.0.80duplicates the value already loaded frompyproject.tomland will make the CLI guidance stale on the next certified upgrade.Proposed fix
- --openshell-version VERSION Certified exact OpenShell version only (0.0.80). + --openshell-version VERSION Certified exact OpenShell version only ($DEFAULT_OPENSHELL_VERSION). ... - scripts/openshell/setup_openshell.sh --openshell-version 0.0.80 --policy offline + scripts/openshell/setup_openshell.sh --openshell-version $DEFAULT_OPENSHELL_VERSION --policy offlineAlso applies to: 111-111
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@scripts/openshell/setup_openshell.sh` at line 83, Update the help text in setup_openshell.sh to derive the example version from the certified version value loaded from pyproject.toml instead of hardcoding 0.0.80. Apply the same change to both the option description and the corresponding usage example, preserving the existing certified-version contract.
148-151: 🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win
Validate the option value before reading
$2.With
set -u,--landlock-compatibilitywithout a value terminates with an unbound-variable error instead of the intended CLI message.Proposed fix
--landlock-compatibility) + [[ $# -ge 2 ]] || fail "--landlock-compatibility requires a mode" LANDLOCK_COMPATIBILITY="$2"📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.--landlock-compatibility) [[ $# -ge 2 ]] || fail "--landlock-compatibility requires a mode" LANDLOCK_COMPATIBILITY="$2" LANDLOCK_COMPATIBILITY_CLI=true shift 2🤖 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 `@scripts/openshell/setup_openshell.sh` around lines 148 - 151, Update the --landlock-compatibility handling in the option-parsing logic to validate that a value argument exists before reading $2, including under set -u; when missing, emit the intended CLI error and exit through the existing validation path, otherwise preserve the current assignment and shift behavior.scripts/openshell/smoke_openshell_isolation.py (1)
71-73: 🔒 Security & Privacy | 🟠 Major | ⚡ Quick win
Do not inherit best-effort Landlock implicitly.
When the flag is absent, an existing
AIQ_OPENSHELL_LIVE_ALLOW_BEST_EFFORTremains inenv, allowing strict acceptance to run with weakened isolation.Proposed fix
if args.allow_best_effort_landlock: env["AIQ_OPENSHELL_LIVE_ALLOW_BEST_EFFORT"] = "1" + else: + env.pop("AIQ_OPENSHELL_LIVE_ALLOW_BEST_EFFORT", None) return env📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.if args.allow_best_effort_landlock: env["AIQ_OPENSHELL_LIVE_ALLOW_BEST_EFFORT"] = "1" else: env.pop("AIQ_OPENSHELL_LIVE_ALLOW_BEST_EFFORT", None) return env🤖 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 `@scripts/openshell/smoke_openshell_isolation.py` around lines 71 - 73, Update the environment construction logic around the allow_best_effort_landlock flag so AIQ_OPENSHELL_LIVE_ALLOW_BEST_EFFORT is removed from env when the flag is absent, and set to "1" only when the flag is enabled. Preserve the existing return env behavior.scripts/openshell/version_contract.py (1)
24-27: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash set -euo pipefail echo '--- scripts/openshell/version_contract.py (outline) ---' ast-grep outline scripts/openshell/version_contract.py --view expanded || true echo echo '--- scripts/openshell/version_contract.py (selected lines) ---' nl -ba scripts/openshell/version_contract.py | sed -n '1,140p' echo echo '--- adapter_version usages ---' rg -n "adapter_version" -S .Repository: NVIDIA-AI-Blueprints/aiq
Length of output: 807
🏁 Script executed:
#!/bin/bash set -euo pipefail echo '--- scripts/openshell/version_contract.py ---' awk '{printf "%4d %s\n", NR, $0}' scripts/openshell/version_contract.py | sed -n '1,140p' echo echo '--- adapter_version usages ---' rg -n "adapter_version" scripts . || trueRepository: NVIDIA-AI-Blueprints/aiq
Length of output: 5652
Make
adapter_versionrequired in the contract.
load_contract()rejects missing or non-stringadapter-versionvalues and always returns a string, soOpenShellContract.adapter_versionshould bestrrather thanstr | None. If missing values are intended, the loader and extra-version comparison need to handleNoneexplicitly.🤖 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 `@scripts/openshell/version_contract.py` around lines 24 - 27, Update OpenShellContract.adapter_version to the required str type, matching load_contract()’s validation and string return contract; do not add optional handling unless the loader and extra-version comparison are explicitly changed to support None.sources/knowledge_layer/src/azure_ai_search/adapter.py (4)
761-762: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win
Validate
metadatais a mapping before unpacking it.
json.dumps()accepts lists and strings, but the later{**file_metadata, ...}requires a mapping. Invalid metadata therefore crashessubmit_job()before a failed job can be recorded. Reject non-dict metadata explicitly.Also applies to: 789-792
🧰 Tools
🪛 ast-grep (0.44.1)
[info] 761-761: use jsonify instead of json.dumps for JSON output
Context: json.dumps(file_metadata, separators=(",", ":"), sort_keys=True)
Note: [CWE-116] Improper Encoding or Escaping of Output.(use-jsonify)
🤖 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 `@sources/knowledge_layer/src/azure_ai_search/adapter.py` around lines 761 - 762, Validate job_config metadata in submit_job before json.dumps() and before any {**file_metadata, ...} expansion, requiring a dict/mapping and rejecting other values explicitly. Preserve the existing empty-metadata default, and ensure invalid metadata follows the failed-job recording path instead of raising during submission.
1127-1131: 🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash set -euo pipefail printf '\n== adapter.py around target lines ==\n' sed -n '1080,1160p' sources/knowledge_layer/src/azure_ai_search/adapter.py printf '\n== search for _write_file_manifest and delete_collection ==\n' rg -n "_write_file_manifest|delete_collection|_get_collection_manifest|_COLLECTION_ACTIVE|register_summary" sources/knowledge_layer/src/azure_ai_search/adapter.py printf '\n== surrounding definitions ==\n' python3 - <<'PY' from pathlib import Path path = Path('sources/knowledge_layer/src/azure_ai_search/adapter.py') text = path.read_text() for needle in ['def _write_file_manifest', 'def delete_collection', 'def _get_collection_manifest', 'class', 'async def delete_collection']: idx = text.find(needle) if idx != -1: start = text.rfind('\n', 0, idx) print(f"\n--- {needle} ---") print(text[max(0, start-400): idx+1200]) PYRepository: NVIDIA-AI-Blueprints/aiq
Length of output: 12725
🏁 Script executed:
#!/bin/bash set -euo pipefail printf '\n== delete_collection continuation ==\n' sed -n '1167,1245p' sources/knowledge_layer/src/azure_ai_search/adapter.py printf '\n== _write_document implementation ==\n' rg -n "def _write_document|def _delete_document|_deleted_files|_jobs_lock" sources/knowledge_layer/src/azure_ai_search/adapter.py sed -n '520,760p' sources/knowledge_layer/src/azure_ai_search/adapter.py printf '\n== file lifecycle helpers around deletion/writes ==\n' sed -n '760,910p' sources/knowledge_layer/src/azure_ai_search/adapter.pyRepository: NVIDIA-AI-Blueprints/aiq
Length of output: 22316
Prevent file-manifest writes after deletion begins.
_update_file_progress()checks the collection once, then writes the file manifest later; a concurrentdelete_collection()can still remove the collection and its files in that gap, recreating an orphaned record. Recheck the collection state right before_write_file_manifest(), or gate progress writes on a deletion/deleted flag.🤖 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 `@sources/knowledge_layer/src/azure_ai_search/adapter.py` around lines 1127 - 1131, Update _update_file_progress so it revalidates the collection’s active state immediately before calling _write_file_manifest, preventing a concurrent delete_collection from allowing the manifest write. Preserve summary registration only when the manifest write remains valid, and use the existing collection status/deletion state symbols.
1231-1249: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win
Handle a file disappearing between the two existence checks.
If the file is removed after
upload_file()checksis_file()but beforesubmit_job()validates it, the failed job has nofile_details; indexing[0]then raisesIndexError. Return a failedFileInfowhen no detail exists, or makesubmit_job()create an explicit failed detail.🤖 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 `@sources/knowledge_layer/src/azure_ai_search/adapter.py` around lines 1231 - 1249, Update upload_file around submit_job and the subsequent _jobs[job_id].file_details access to handle a job with no file details when the file disappears between validation checks. Return a failed FileInfo with the file path, collection, and clear error message when file_details is empty, while preserving the existing detail-copy path when a detail is available.
1258-1283: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash set -euo pipefail FILE='sources/knowledge_layer/src/azure_ai_search/adapter.py' echo '--- outline ---' ast-grep outline "$FILE" --view expanded | sed -n '1,220p' echo echo '--- relevant ranges ---' sed -n '1120,1315p' "$FILE" | cat -n echo echo '--- wait/search helpers ---' rg -n "_wait_for_search_state|_delete_document_ids|_iter_documents|_delete_file_documents|_get_validated_search_client|_record_filter|_RECORD_FILE|_RECORD_COLLECTION" "$FILE"Repository: NVIDIA-AI-Blueprints/aiq
Length of output: 19801
🏁 Script executed:
#!/bin/bash set -euo pipefail FILE='sources/knowledge_layer/src/azure_ai_search/adapter.py' python3 - <<'PY' from pathlib import Path path = Path('sources/knowledge_layer/src/azure_ai_search/adapter.py') text = path.read_text() for needle in ['def _wait_for_search_state', 'def _delete_document_ids', 'def _delete_file_documents', 'def delete_collection', 'def delete_file', 'def _iter_documents']: idx = text.find(needle) if idx != -1: start = text.rfind('\n', 0, idx) + 1 end = text.find('\nclass ', idx) if end == -1: end = len(text) print(f'\n### {needle}\n') print(text[start:end][:5000]) PYRepository: NVIDIA-AI-Blueprints/aiq
Length of output: 29262
🏁 Script executed:
#!/bin/bash set -euo pipefail FILE='sources/knowledge_layer/src/azure_ai_search/adapter.py' python3 - <<'PY' from pathlib import Path path = Path('sources/knowledge_layer/src/azure_ai_search/adapter.py') lines = path.read_text().splitlines() targets = [ 'def _wait_for_search_state', 'def _delete_document_ids', 'def _delete_file_documents', 'def delete_collection', 'def delete_file', 'def _iter_documents', ] for target in targets: for i, line in enumerate(lines): if line.startswith(target): start = max(0, i - 10) end = min(len(lines), i + 120) print(f"\n### {target} @ line {i+1}\n") for j in range(start, end): print(f"{j+1:5d}: {lines[j]}") break else: print(f"\n### {target} not found\n") PYRepository: NVIDIA-AI-Blueprints/aiq
Length of output: 395
Wait for all deleted Azure Search records to disappear before returning.
sources/knowledge_layer/src/azure_ai_search/adapter.py#L1182-L1201:delete_collectionissues deletes but never waits for the collection content to become absent.sources/knowledge_layer/src/azure_ai_search/adapter.py#L1258-L1283:delete_filewaits only on the file manifest; include the chunk records in the post-delete check too.📍 Affects 1 file
sources/knowledge_layer/src/azure_ai_search/adapter.py#L1258-L1283(this comment)sources/knowledge_layer/src/azure_ai_search/adapter.py#L1182-L1201🤖 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 `@sources/knowledge_layer/src/azure_ai_search/adapter.py` around lines 1258 - 1283, Update delete_file and delete_collection in sources/knowledge_layer/src/azure_ai_search/adapter.py at lines 1258-1283 and 1182-1201 so they wait for all deleted Azure Search records to disappear before returning. In delete_file, extend the post-delete _wait_for_search_state check beyond the file manifest to include its chunk records; in delete_collection, add an equivalent absence wait for the collection’s content after issuing deletions.src/aiq_agent/agents/deep_researcher/register.py (1)
298-306: 🩺 Stability & Availability | 🟠 Major | 🏗️ Heavy lift
Sandbox finalization remains unbounded despite using
to_thread().Both terminal paths await synchronous provider cleanup indefinitely; moving it to a thread protects the event loop, not request or worker completion.
src/aiq_agent/agents/deep_researcher/register.py#L298-L306: bound request-scoped finalization so cancellation always completes.frontends/aiq_api/src/aiq_api/jobs/runner.py#L886-L893: bound terminal cleanup so a Dask task cannot remain occupied indefinitely.Prefer provider-level deadlines, with a call-site timeout as containment.
As per path instructions, preserve agent “async cancellation” and API “async job lifecycle” behavior.
📍 Affects 2 files
src/aiq_agent/agents/deep_researcher/register.py#L298-L306(this comment)frontends/aiq_api/src/aiq_api/jobs/runner.py#L886-L893🤖 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/aiq_agent/agents/deep_researcher/register.py` around lines 298 - 306, The synchronous provider cleanup in the deep-researcher finalization path and the API job terminal cleanup remain unbounded. Add provider-level deadlines and call-site timeouts around the `active_agent.finalize` flow in `register.py` and the corresponding terminal cleanup in `runner.py`; preserve agent async cancellation semantics and the API async job lifecycle while ensuring both request/task completions cannot wait indefinitely.Source: Path instructions
tests/aiq_agent/jobs/test_runner.py (2)
888-891: 🔒 Security & Privacy | 🟠 Major | ⚡ Quick win
Do not persist raw backend exception messages.
This expectation codifies exposing
str(error)through externally visible job status. Database exceptions can contain queries, hosts, identifiers, or credentials; retain a stable sanitized message and log the detailed exception only through secret-safe server logging.Proposed expectation
- error="transient database failure", + error="failed to persist encrypted job events",As per coding guidelines, “Never print or log secret values, including in tool output or error messages.” As per path instructions, treat job-runner changes as “externally visible contracts” and check “error responses.”
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.mock_job_store.update_status.assert_awaited_with( "job-1", JobStatus.FAILURE, error="failed to persist encrypted job events",🤖 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 `@tests/aiq_agent/jobs/test_runner.py` around lines 888 - 891, Update the job-runner failure handling that calls mock_job_store.update_status with JobStatus.FAILURE so externally persisted errors use a stable sanitized message instead of str(error). Keep detailed exception information restricted to secret-safe server logging, and adjust the expectation around update_status accordingly.Sources: Coding guidelines, Path instructions
1189-1200: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win
Restore coverage for workflow configs without the async flag.
_get_worker_function_typedirectly readsconfig.workflow.use_async_deep_research; removing the missing-attribute case permits anAttributeErrorfor legacy or alternate workflow configurations. Retain that test and default the absent flag toFalse, for example withgetattr.As per path instructions, job-runner changes require tests for “job state transitions.”
🤖 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 `@tests/aiq_agent/jobs/test_runner.py` around lines 1189 - 1200, Update _get_worker_function_type to safely treat a missing workflow.use_async_deep_research attribute as False, while preserving the existing enabled and disabled behavior. Restore coverage using a workflow configuration without the async flag and add the required job state transition tests for the job-runner change.Source: Path instructions
Brings the chat UI to the premium layout: a live phased "thinking" trace (status dots, durations, tool-call rows, a "using" source chip), answers with superscript citations and a styled source list, an interactive clarifier, a restyled composer with a stop control, a collapsible sessions rail, and push-style data-source and research panels. - chat: ChatThinking (phased live trace), AgentResponse (citations + sources + copy + answer reveal), AgentPrompt (interactive clarifier with plan approval), UserMessage and banner polish. - layout: MainLayout push panels, ChatArea turn grouping + run lane + pinned autoscroll, AppBar theme toggle + active data-sources state, InputArea composer restyle + stop, SessionsPanel collapsible rail, DataSourcesPanel push re-skin, and the research-panel tabs and cards. - app: mount the reduced-motion Motion provider at the root. Per-user OAuth, human-in-the-loop navigation blocking, and rich artifact/file handling are preserved. The model picker is omitted (prod exposes no selectable models). No predictive/analytical/warehouse UI is ported. Full suite green. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Signed-off-by: Manush Maheshwari <manushm@nvidia.com>
- AgentPrompt: do not show "Plan approved" when a responded prompt has no response (neutral state). - AgentResponse: surface report-load failures inline with role="alert" and a Retry button instead of only a title tooltip. - AgentCard: keep distinct tool calls with unrecognized inputs separate, and let a terminal state replace a stale running row. - AgentsTab: count rendered groups (agents plus orphan tool calls), not just the agent list. - ReportTab: bound the expanded generated-files list with a scroll area. - SessionsPanel: return focus to the search trigger when the search closes. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Signed-off-by: Manush Maheshwari <manushm@nvidia.com>
The re-skin dropped aiq-rfm's custom surface/text/border palette and the base NVIDIA Sans font-family, so surfaces fell back to KUI defaults. Restore the light and dark token overrides and the html/body font-family + smoothing so the theme matches aiq-rfm. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Signed-off-by: Manush Maheshwari <manushm@nvidia.com>
There is no model selector in the composer, so drop the model favicon + name badge from the response summary bar (and the local favicon helper). The model data field is left in place, only the display is removed. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Signed-off-by: Manush Maheshwari <manushm@nvidia.com>
Signed-off-by: Manush Mohan <manushm@nvidia.com>
860114e to
4305114
Compare
There was a problem hiding this comment.
Actionable comments posted: 17
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
frontends/ui/src/features/layout/components/MainLayout.tsx (1)
169-198: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick winCentralize the new-session guard across bootstrap and active interactions.
New-session safety is currently caller-local, leaving two unguarded paths:
frontends/ui/src/features/layout/components/MainLayout.tsx#L169-L198: include bootstrap/user hydration in a shared disabled state and guardhandleNewSession.frontends/ui/src/features/layout/components/SessionsPanel.tsx#L418-L424: disable the empty-state CTA using that same guard.🤖 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 `@frontends/ui/src/features/layout/components/MainLayout.tsx` around lines 169 - 198, The new-session guard must cover bootstrap and user-hydration state across all entry points. In frontends/ui/src/features/layout/components/MainLayout.tsx lines 169-198, include those states in the shared disabled condition and guard handleNewSession; in frontends/ui/src/features/layout/components/SessionsPanel.tsx lines 418-424, reuse that same guard to disable the empty-state CTA.Source: Path instructions
♻️ Duplicate comments (2)
frontends/ui/src/features/layout/components/AgentCard.tsx (1)
70-75: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick winDo not deduplicate by a truncated display label.
getToolArgSummarytruncates values, so distinct long arguments with the same prefix collapse into one row. Build the key from full canonical input while retaining the summary only for display, and add a collision regression test.As per path instructions, preserve report/chat state consistency and require tests for changed workflows.
🤖 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 `@frontends/ui/src/features/layout/components/AgentCard.tsx` around lines 70 - 75, Update dedupeToolCalls so its Map key uses the full canonicalized tc.input together with tc.name (and an appropriate fallback for unavailable input), rather than the truncated getToolArgSummary result; keep the summary solely for display. Add a regression test covering distinct long inputs sharing the same truncated prefix, and verify report/chat state remains consistent across the affected workflows.Source: Path instructions
frontends/ui/src/features/layout/components/AgentsTab.tsx (1)
46-51: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick winDerive header state from the same visible phases that
ChatThinkingrenders.These counts include internal steps such as
<workflow>, whileChatThinkingfilters them. A wrapper-only run can therefore show a count or “running” badge beside an empty trace. Share the visibility/phase derivation and add wrapper-only coverage.As per path instructions, review UI changes for “report/chat state consistency.”
Also applies to: 79-92
🤖 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 `@frontends/ui/src/features/layout/components/AgentsTab.tsx` around lines 46 - 51, Update AgentsTab’s isEmpty, runningCount, and renderedGroupCount to use the same visible-phase filtering and derivation as ChatThinking, excluding internal wrapper steps such as <workflow>. Share or reuse that visibility logic rather than maintaining separate filters, and add coverage for a wrapper-only run so the header shows no count or running badge beside an empty trace.Source: Path instructions
🤖 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 `@frontends/ui/src/app/globals.css`:
- Line 88: Update the --text-color-subtle definitions, including the theme and
raised-surface variants, to use contrast-validated light and dark values meeting
at least 4.5:1 against their respective base surfaces; preserve the existing
token usage by .mono-label.
- Line 130: Update the text-rendering value in the global stylesheet to
lowercase `optimizelegibility` to satisfy the configured Stylelint
value-keyword-case rule, then run the UI lint, type-check, tests, and build
validation.
In `@frontends/ui/src/features/chat/components/AgentPrompt.tsx`:
- Around line 143-154: Update AgentPrompt to retain and prioritize the incoming
type prop when determining approval prompts: treat type="approval" as approval
regardless of content, while preserving APPROVAL_PROMPT_RE as a legacy fallback
for prompts without that type. Add a test covering type="approval" with
non-matching content and verify the approval controls render.
- Around line 200-219: Update the keydown logic in AgentPrompt’s
useEffect/onKeyDown flow to detect when focus is on an interactive control and
return without handling Enter, preserving native activation of the focused
Reject button. Ensure keyboard approval still works when focus is not on a
control, and add a regression test that tabs to Reject and presses Enter,
verifying rejection rather than approval.
In `@frontends/ui/src/features/chat/components/AgentResponse.tsx`:
- Around line 93-94: Update the historical report action in AgentResponse, using
isAnotherJobStreaming, so a completed job’s “View Report” cannot route to
another currently streaming job; disable the action or make the alternate
behavior explicit while preserving the normal path when no other job is
streaming. Add or update tests covering this user-visible branch and report/chat
state consistency.
In `@frontends/ui/src/features/chat/components/ChatThinking.tsx`:
- Around line 672-679: Update phaseEnd in ChatThinking so the fallback for
phases with children uses the final child’s completion timestamp rather than its
start timestamp. Preserve the existing precedence for head.completedAt,
subsequent phases, active thinking, and stoppedAt, and retain the start-time
fallback when no children exist.
- Around line 604-609: Update the realSteps useMemo to also filter out
reflection nodes, using the existing reflection-identification helper or
predicate, so reflection-only streams produce an empty realSteps result and
follow the existing empty-state path. Preserve the current reasoning and
explanation exclusions.
- Around line 179-197: The filtering in the enriched steps flow incorrectly
removes nested calls based only on the tool label. Update the logic around
topLevelLabels and enriched so calls use a stable call ID when available;
otherwise retain nested rows unless both their label and original input summary
match the top-level call. Add a regression test covering top-level and nested
web_search_tool calls with different inputs.
In `@frontends/ui/src/features/chat/lib/session-activity.ts`:
- Around line 22-43: The lastUserMessageTime function currently recognizes user
messages only through messageType, so messages with role: 'user' and an
undefined messageType are ignored. Update its user-message classification to
match ChatArea’s fallback behavior, treating role-only user messages as user
messages while preserving explicit non-user messageType handling and the
existing recency sorting flow.
In `@frontends/ui/src/features/layout/components/AgentCard.tsx`:
- Around line 102-108: Update the disclosure button in AgentCard so
aria-expanded and aria-controls are only rendered when canExpand is true;
otherwise omit both attributes while preserving the disabled behavior and
existing values for agents with controlled content.
- Around line 90-94: Update AgentCard’s expandability and rendering logic to
preserve the public AgentInfo.output contract: a completed agent with only
output must remain enabled and display its result. Include output alongside tool
calls/currentTask where determining expandable content and rendering the card,
while preserving report/chat state consistency. Add coverage for the output-only
completed-agent workflow.
In `@frontends/ui/src/features/layout/components/AgentsTab.tsx`:
- Around line 53-59: Update the scroll logic in the useEffect associated with
scrollRef to reuse the shared isPinnedToBottom predicate instead of calculating
nearBottom locally. Preserve the existing auto-scroll behavior and the
predicate’s inclusive <=120px boundary.
In `@frontends/ui/src/features/layout/components/DataConnectionsTab.tsx`:
- Around line 43-57: Update the displaySources mapping in DataConnectionsTab to
preserve each source’s per-user OAuth metadata using the same mapping as
DataSourcesPanel, including the perUserAuth field consumed by
DataConnectionCard. Ensure disconnected protected sources render
Connect/Reconnect and cannot be selected before OAuth completes, and add a
regression test covering that state.
In `@frontends/ui/src/features/layout/components/DataSourcesPanel.tsx`:
- Around line 220-246: Update the panel controlled by the existing isOpen state
in DataSourcesPanel so closing it immediately disables descendant interaction
while the width/opacity transition continues, using the appropriate inert
behavior alongside aria-hidden. Track the opener element and restore focus to it
when the panel closes, while preserving normal focusability and focus behavior
when the panel is open.
- Around line 316-365: Update the “Disable / Enable All” control around the
outer Flex and Switch so the Switch is the sole interactive control: remove the
outer role="button", tabIndex, click and keyboard handlers, button-specific ARIA
attributes, and event-stopping wrapper. Preserve the existing label, checked
state, busy-state disabling, and handleToggleAll behavior through the Switch.
- Around line 388-395: Update the Retry Button’s onClick handler to call
fetchDataSources with the existing idToken, matching the authenticated refresh
path. Preserve the current retry behavior while ensuring authenticated
deployments reuse the token.
In `@frontends/ui/src/features/layout/components/ThinkingTab.tsx`:
- Around line 82-105: Update the empty-state branch in ThinkingTab so the cited
filter with no results does not display the generic “Sources the agent reads
will appear here” message; either hide/disable the cited filter when
cited.length is zero or render a filter-specific “No sources were cited in the
report” state. Preserve the existing empty state when no sources exist, and add
or update the spec to cover the cited-empty workflow along with resilient
loading and error states.
---
Outside diff comments:
In `@frontends/ui/src/features/layout/components/MainLayout.tsx`:
- Around line 169-198: The new-session guard must cover bootstrap and
user-hydration state across all entry points. In
frontends/ui/src/features/layout/components/MainLayout.tsx lines 169-198,
include those states in the shared disabled condition and guard
handleNewSession; in
frontends/ui/src/features/layout/components/SessionsPanel.tsx lines 418-424,
reuse that same guard to disable the empty-state CTA.
---
Duplicate comments:
In `@frontends/ui/src/features/layout/components/AgentCard.tsx`:
- Around line 70-75: Update dedupeToolCalls so its Map key uses the full
canonicalized tc.input together with tc.name (and an appropriate fallback for
unavailable input), rather than the truncated getToolArgSummary result; keep the
summary solely for display. Add a regression test covering distinct long inputs
sharing the same truncated prefix, and verify report/chat state remains
consistent across the affected workflows.
In `@frontends/ui/src/features/layout/components/AgentsTab.tsx`:
- Around line 46-51: Update AgentsTab’s isEmpty, runningCount, and
renderedGroupCount to use the same visible-phase filtering and derivation as
ChatThinking, excluding internal wrapper steps such as <workflow>. Share or
reuse that visibility logic rather than maintaining separate filters, and add
coverage for a wrapper-only run so the header shows no count or running badge
beside an empty trace.
🪄 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: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Enterprise
Run ID: e3b52cb2-55e1-4df3-9a89-c3e28b70c137
📒 Files selected for processing (65)
frontends/ui/src/app/globals.cssfrontends/ui/src/app/page.tsxfrontends/ui/src/app/providers.tsxfrontends/ui/src/features/chat/components/AgentPrompt.spec.tsxfrontends/ui/src/features/chat/components/AgentPrompt.tsxfrontends/ui/src/features/chat/components/AgentResponse.spec.tsxfrontends/ui/src/features/chat/components/AgentResponse.tsxfrontends/ui/src/features/chat/components/ChatThinking.spec.tsxfrontends/ui/src/features/chat/components/ChatThinking.tsxfrontends/ui/src/features/chat/components/DeepResearchBanner.tsxfrontends/ui/src/features/chat/components/ErrorBanner.tsxfrontends/ui/src/features/chat/components/FileUploadBanner.tsxfrontends/ui/src/features/chat/components/NoSourcesBanner.tsxfrontends/ui/src/features/chat/components/UserMessage.tsxfrontends/ui/src/features/chat/components/index.tsfrontends/ui/src/features/chat/lib/session-activity.tsfrontends/ui/src/features/layout/components/AgentCard.spec.tsxfrontends/ui/src/features/layout/components/AgentCard.tsxfrontends/ui/src/features/layout/components/AgentsTab.spec.tsxfrontends/ui/src/features/layout/components/AgentsTab.tsxfrontends/ui/src/features/layout/components/AppBar.spec.tsxfrontends/ui/src/features/layout/components/AppBar.tsxfrontends/ui/src/features/layout/components/ChatArea.autoscroll.spec.tsxfrontends/ui/src/features/layout/components/ChatArea.spec.tsxfrontends/ui/src/features/layout/components/ChatArea.tsxfrontends/ui/src/features/layout/components/CitationCard.spec.tsxfrontends/ui/src/features/layout/components/CitationCard.tsxfrontends/ui/src/features/layout/components/DataConnectionCard.tsxfrontends/ui/src/features/layout/components/DataConnectionsTab.spec.tsxfrontends/ui/src/features/layout/components/DataConnectionsTab.tsxfrontends/ui/src/features/layout/components/DataSourcesPanel.spec.tsxfrontends/ui/src/features/layout/components/DataSourcesPanel.tsxfrontends/ui/src/features/layout/components/FileCard.tsxfrontends/ui/src/features/layout/components/FileSourceCard.spec.tsxfrontends/ui/src/features/layout/components/FileSourceCard.tsxfrontends/ui/src/features/layout/components/FileSourcesTab.spec.tsxfrontends/ui/src/features/layout/components/FileSourcesTab.tsxfrontends/ui/src/features/layout/components/InputArea.tsxfrontends/ui/src/features/layout/components/MainLayout.spec.tsxfrontends/ui/src/features/layout/components/MainLayout.tsxfrontends/ui/src/features/layout/components/ReportCard.spec.tsxfrontends/ui/src/features/layout/components/ReportCard.tsxfrontends/ui/src/features/layout/components/ReportTab.spec.tsxfrontends/ui/src/features/layout/components/ReportTab.tsxfrontends/ui/src/features/layout/components/ResearchPanel.spec.tsxfrontends/ui/src/features/layout/components/ResearchPanel.tsxfrontends/ui/src/features/layout/components/SessionsPanel.spec.tsxfrontends/ui/src/features/layout/components/SessionsPanel.tsxfrontends/ui/src/features/layout/components/SettingsPanel.spec.tsxfrontends/ui/src/features/layout/components/SettingsPanel.tsxfrontends/ui/src/features/layout/components/SourceCard.spec.tsxfrontends/ui/src/features/layout/components/SourceCard.tsxfrontends/ui/src/features/layout/components/TaskCard.spec.tsxfrontends/ui/src/features/layout/components/TaskCard.tsxfrontends/ui/src/features/layout/components/TasksTab.spec.tsxfrontends/ui/src/features/layout/components/TasksTab.tsxfrontends/ui/src/features/layout/components/ThinkingTab.spec.tsxfrontends/ui/src/features/layout/components/ThinkingTab.tsxfrontends/ui/src/features/layout/components/ThoughtCard.spec.tsxfrontends/ui/src/features/layout/components/ThoughtCard.tsxfrontends/ui/src/features/layout/components/index.tsfrontends/ui/src/features/layout/index.tsfrontends/ui/src/features/layout/store.spec.tsfrontends/ui/src/shared/lib/scroll.spec.tsfrontends/ui/src/shared/lib/scroll.ts
💤 Files with no reviewable changes (14)
- frontends/ui/src/features/chat/components/NoSourcesBanner.tsx
- frontends/ui/src/features/chat/components/ErrorBanner.tsx
- frontends/ui/src/features/layout/components/SourceCard.spec.tsx
- frontends/ui/src/features/layout/components/TasksTab.spec.tsx
- frontends/ui/src/features/chat/components/FileUploadBanner.tsx
- frontends/ui/src/features/layout/components/CitationCard.spec.tsx
- frontends/ui/src/features/layout/components/DataConnectionsTab.spec.tsx
- frontends/ui/src/features/layout/components/ResearchPanel.spec.tsx
- frontends/ui/src/features/chat/components/DeepResearchBanner.tsx
- frontends/ui/src/features/layout/components/FileSourcesTab.spec.tsx
- frontends/ui/src/features/chat/components/index.ts
- frontends/ui/src/features/layout/components/ReportCard.spec.tsx
- frontends/ui/src/features/layout/components/index.ts
- frontends/ui/src/features/layout/components/SettingsPanel.spec.tsx
📜 Review details
🧰 Additional context used
📓 Path-based instructions (3)
frontends/ui/**/*.{js,ts,jsx,tsx,vue}
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Run npm lint, type-check, and build validation for UI changes in frontends/ui
Files:
frontends/ui/src/features/layout/components/SettingsPanel.tsxfrontends/ui/src/features/layout/components/ChatArea.autoscroll.spec.tsxfrontends/ui/src/shared/lib/scroll.tsfrontends/ui/src/app/page.tsxfrontends/ui/src/features/layout/components/TaskCard.spec.tsxfrontends/ui/src/shared/lib/scroll.spec.tsfrontends/ui/src/features/layout/components/DataSourcesPanel.spec.tsxfrontends/ui/src/features/layout/components/SourceCard.tsxfrontends/ui/src/features/layout/index.tsfrontends/ui/src/features/layout/store.spec.tsfrontends/ui/src/app/providers.tsxfrontends/ui/src/features/layout/components/CitationCard.tsxfrontends/ui/src/features/chat/components/UserMessage.tsxfrontends/ui/src/features/layout/components/FileCard.tsxfrontends/ui/src/features/layout/components/AgentsTab.tsxfrontends/ui/src/features/chat/lib/session-activity.tsfrontends/ui/src/features/layout/components/DataConnectionCard.tsxfrontends/ui/src/features/layout/components/TaskCard.tsxfrontends/ui/src/features/layout/components/ThinkingTab.tsxfrontends/ui/src/features/layout/components/TasksTab.tsxfrontends/ui/src/features/layout/components/ThoughtCard.tsxfrontends/ui/src/features/chat/components/AgentResponse.tsxfrontends/ui/src/features/layout/components/ReportTab.tsxfrontends/ui/src/features/layout/components/AgentsTab.spec.tsxfrontends/ui/src/features/layout/components/ReportCard.tsxfrontends/ui/src/features/chat/components/AgentPrompt.spec.tsxfrontends/ui/src/features/layout/components/ThoughtCard.spec.tsxfrontends/ui/src/features/layout/components/InputArea.tsxfrontends/ui/src/features/layout/components/ReportTab.spec.tsxfrontends/ui/src/features/layout/components/AgentCard.spec.tsxfrontends/ui/src/features/layout/components/AgentCard.tsxfrontends/ui/src/features/layout/components/DataSourcesPanel.tsxfrontends/ui/src/features/chat/components/ChatThinking.spec.tsxfrontends/ui/src/features/layout/components/DataConnectionsTab.tsxfrontends/ui/src/features/layout/components/FileSourcesTab.tsxfrontends/ui/src/features/layout/components/MainLayout.spec.tsxfrontends/ui/src/features/chat/components/AgentPrompt.tsxfrontends/ui/src/features/chat/components/AgentResponse.spec.tsxfrontends/ui/src/features/layout/components/ThinkingTab.spec.tsxfrontends/ui/src/features/layout/components/MainLayout.tsxfrontends/ui/src/features/layout/components/FileSourceCard.tsxfrontends/ui/src/features/layout/components/FileSourceCard.spec.tsxfrontends/ui/src/features/chat/components/ChatThinking.tsxfrontends/ui/src/features/layout/components/ChatArea.spec.tsxfrontends/ui/src/features/layout/components/ResearchPanel.tsxfrontends/ui/src/features/layout/components/ChatArea.tsxfrontends/ui/src/features/layout/components/AppBar.spec.tsxfrontends/ui/src/features/layout/components/SessionsPanel.tsxfrontends/ui/src/features/layout/components/SessionsPanel.spec.tsxfrontends/ui/src/features/layout/components/AppBar.tsx
frontends/ui/**/*.{ts,tsx,jsx,js}
📄 CodeRabbit inference engine (AGENTS.md)
frontends/ui/**/*.{ts,tsx,jsx,js}: The UI is built with Next.js / React / TypeScript / Tailwind with KUI components; reuse existing KUI components and visual patterns rather than introducing new ones
Validate UI-affecting changes with npm run lint, npm run type-check, and npm run test:ci, and include a screenshot for visible changes
Files:
frontends/ui/src/features/layout/components/SettingsPanel.tsxfrontends/ui/src/features/layout/components/ChatArea.autoscroll.spec.tsxfrontends/ui/src/shared/lib/scroll.tsfrontends/ui/src/app/page.tsxfrontends/ui/src/features/layout/components/TaskCard.spec.tsxfrontends/ui/src/shared/lib/scroll.spec.tsfrontends/ui/src/features/layout/components/DataSourcesPanel.spec.tsxfrontends/ui/src/features/layout/components/SourceCard.tsxfrontends/ui/src/features/layout/index.tsfrontends/ui/src/features/layout/store.spec.tsfrontends/ui/src/app/providers.tsxfrontends/ui/src/features/layout/components/CitationCard.tsxfrontends/ui/src/features/chat/components/UserMessage.tsxfrontends/ui/src/features/layout/components/FileCard.tsxfrontends/ui/src/features/layout/components/AgentsTab.tsxfrontends/ui/src/features/chat/lib/session-activity.tsfrontends/ui/src/features/layout/components/DataConnectionCard.tsxfrontends/ui/src/features/layout/components/TaskCard.tsxfrontends/ui/src/features/layout/components/ThinkingTab.tsxfrontends/ui/src/features/layout/components/TasksTab.tsxfrontends/ui/src/features/layout/components/ThoughtCard.tsxfrontends/ui/src/features/chat/components/AgentResponse.tsxfrontends/ui/src/features/layout/components/ReportTab.tsxfrontends/ui/src/features/layout/components/AgentsTab.spec.tsxfrontends/ui/src/features/layout/components/ReportCard.tsxfrontends/ui/src/features/chat/components/AgentPrompt.spec.tsxfrontends/ui/src/features/layout/components/ThoughtCard.spec.tsxfrontends/ui/src/features/layout/components/InputArea.tsxfrontends/ui/src/features/layout/components/ReportTab.spec.tsxfrontends/ui/src/features/layout/components/AgentCard.spec.tsxfrontends/ui/src/features/layout/components/AgentCard.tsxfrontends/ui/src/features/layout/components/DataSourcesPanel.tsxfrontends/ui/src/features/chat/components/ChatThinking.spec.tsxfrontends/ui/src/features/layout/components/DataConnectionsTab.tsxfrontends/ui/src/features/layout/components/FileSourcesTab.tsxfrontends/ui/src/features/layout/components/MainLayout.spec.tsxfrontends/ui/src/features/chat/components/AgentPrompt.tsxfrontends/ui/src/features/chat/components/AgentResponse.spec.tsxfrontends/ui/src/features/layout/components/ThinkingTab.spec.tsxfrontends/ui/src/features/layout/components/MainLayout.tsxfrontends/ui/src/features/layout/components/FileSourceCard.tsxfrontends/ui/src/features/layout/components/FileSourceCard.spec.tsxfrontends/ui/src/features/chat/components/ChatThinking.tsxfrontends/ui/src/features/layout/components/ChatArea.spec.tsxfrontends/ui/src/features/layout/components/ResearchPanel.tsxfrontends/ui/src/features/layout/components/ChatArea.tsxfrontends/ui/src/features/layout/components/AppBar.spec.tsxfrontends/ui/src/features/layout/components/SessionsPanel.tsxfrontends/ui/src/features/layout/components/SessionsPanel.spec.tsxfrontends/ui/src/features/layout/components/AppBar.tsx
frontends/ui/**/*
⚙️ CodeRabbit configuration file
frontends/ui/**/*: Review UI changes for strict TypeScript behavior, API contract alignment, auth/session handling, accessible controls,
resilient loading and error states, and report/chat state consistency. Prefer existing UI patterns and require tests
for changed user-visible workflows.
Files:
frontends/ui/src/features/layout/components/SettingsPanel.tsxfrontends/ui/src/features/layout/components/ChatArea.autoscroll.spec.tsxfrontends/ui/src/shared/lib/scroll.tsfrontends/ui/src/app/page.tsxfrontends/ui/src/features/layout/components/TaskCard.spec.tsxfrontends/ui/src/shared/lib/scroll.spec.tsfrontends/ui/src/features/layout/components/DataSourcesPanel.spec.tsxfrontends/ui/src/features/layout/components/SourceCard.tsxfrontends/ui/src/features/layout/index.tsfrontends/ui/src/features/layout/store.spec.tsfrontends/ui/src/app/providers.tsxfrontends/ui/src/features/layout/components/CitationCard.tsxfrontends/ui/src/features/chat/components/UserMessage.tsxfrontends/ui/src/features/layout/components/FileCard.tsxfrontends/ui/src/features/layout/components/AgentsTab.tsxfrontends/ui/src/features/chat/lib/session-activity.tsfrontends/ui/src/features/layout/components/DataConnectionCard.tsxfrontends/ui/src/features/layout/components/TaskCard.tsxfrontends/ui/src/features/layout/components/ThinkingTab.tsxfrontends/ui/src/features/layout/components/TasksTab.tsxfrontends/ui/src/features/layout/components/ThoughtCard.tsxfrontends/ui/src/features/chat/components/AgentResponse.tsxfrontends/ui/src/features/layout/components/ReportTab.tsxfrontends/ui/src/features/layout/components/AgentsTab.spec.tsxfrontends/ui/src/features/layout/components/ReportCard.tsxfrontends/ui/src/features/chat/components/AgentPrompt.spec.tsxfrontends/ui/src/features/layout/components/ThoughtCard.spec.tsxfrontends/ui/src/features/layout/components/InputArea.tsxfrontends/ui/src/features/layout/components/ReportTab.spec.tsxfrontends/ui/src/features/layout/components/AgentCard.spec.tsxfrontends/ui/src/features/layout/components/AgentCard.tsxfrontends/ui/src/features/layout/components/DataSourcesPanel.tsxfrontends/ui/src/features/chat/components/ChatThinking.spec.tsxfrontends/ui/src/features/layout/components/DataConnectionsTab.tsxfrontends/ui/src/features/layout/components/FileSourcesTab.tsxfrontends/ui/src/features/layout/components/MainLayout.spec.tsxfrontends/ui/src/features/chat/components/AgentPrompt.tsxfrontends/ui/src/features/chat/components/AgentResponse.spec.tsxfrontends/ui/src/features/layout/components/ThinkingTab.spec.tsxfrontends/ui/src/features/layout/components/MainLayout.tsxfrontends/ui/src/features/layout/components/FileSourceCard.tsxfrontends/ui/src/features/layout/components/FileSourceCard.spec.tsxfrontends/ui/src/features/chat/components/ChatThinking.tsxfrontends/ui/src/features/layout/components/ChatArea.spec.tsxfrontends/ui/src/features/layout/components/ResearchPanel.tsxfrontends/ui/src/features/layout/components/ChatArea.tsxfrontends/ui/src/features/layout/components/AppBar.spec.tsxfrontends/ui/src/app/globals.cssfrontends/ui/src/features/layout/components/SessionsPanel.tsxfrontends/ui/src/features/layout/components/SessionsPanel.spec.tsxfrontends/ui/src/features/layout/components/AppBar.tsx
🪛 Stylelint (17.14.0)
frontends/ui/src/app/globals.css
[error] 130-130: Expected "optimizeLegibility" to be "optimizelegibility" (value-keyword-case)
(value-keyword-case)
🔇 Additional comments (52)
frontends/ui/src/features/layout/components/CitationCard.tsx (1)
62-64: LGTM!Also applies to: 81-81, 94-100
frontends/ui/src/features/layout/components/FileSourceCard.spec.tsx (1)
9-9: LGTM!Also applies to: 51-58, 83-83, 143-143, 155-155
frontends/ui/src/features/layout/components/FileSourceCard.tsx (1)
143-144: LGTM!Also applies to: 194-194, 205-207, 227-236, 248-248, 262-270
frontends/ui/src/shared/lib/scroll.ts (1)
1-26: 📐 Maintainability & Code QualityConfirm the required UI build validation.
The PR summary covers lint, type-check, tests, browser verification, and screenshots, but not the required build result. Please confirm
npm run buildcompleted successfully.Source: Coding guidelines
frontends/ui/src/shared/lib/scroll.spec.ts (1)
4-42: LGTM!frontends/ui/src/features/layout/components/AgentsTab.tsx (1)
5-44: LGTM!Also applies to: 61-78
frontends/ui/src/features/layout/components/AgentsTab.spec.tsx (1)
4-119: LGTM!frontends/ui/src/features/layout/components/ReportCard.tsx (1)
50-50: LGTM!Also applies to: 98-98, 113-118
frontends/ui/src/features/layout/components/ReportTab.spec.tsx (1)
36-42: LGTM!Also applies to: 117-140
frontends/ui/src/features/layout/components/AgentCard.spec.tsx (1)
12-147: LGTM!Also applies to: 149-195, 205-231
frontends/ui/src/features/layout/components/AgentCard.tsx (1)
7-62: LGTM!Also applies to: 76-89, 96-100, 110-139
frontends/ui/src/features/layout/components/MainLayout.spec.tsx (1)
18-24: LGTM!Also applies to: 50-51, 63-64, 103-104, 121-125, 169-170, 222-226
frontends/ui/src/features/layout/components/MainLayout.tsx (1)
9-12: LGTM!Also applies to: 22-34, 38-42, 62-64, 96-96, 143-163, 208-213
frontends/ui/src/features/layout/components/AppBar.tsx (1)
18-22: LGTM!Also applies to: 62-81, 106-106, 127-128, 153-173
frontends/ui/src/features/layout/components/AppBar.spec.tsx (1)
9-13: LGTM!Also applies to: 47-48, 74-75, 82-83, 102-122, 133-139, 165-166, 187-188, 205-209, 229-235
frontends/ui/src/features/layout/components/SessionsPanel.spec.tsx (1)
4-27: LGTM!Also applies to: 79-90, 105-105, 129-162, 176-190, 216-229, 239-298, 376-399, 420-456, 485-527, 545-551, 559-600, 640-648
frontends/ui/src/features/layout/components/SessionsPanel.tsx (1)
7-417: LGTM!Also applies to: 425-745
frontends/ui/src/features/layout/components/DataSourcesPanel.spec.tsx (1)
233-237: Target the panel wrapper directly.This selector remains descendant-wide and can be satisfied by another hidden
div. Assert thatcontainer.firstElementChildhasaria-hidden="true".frontends/ui/src/features/layout/store.spec.ts (1)
200-202: LGTM!frontends/ui/src/features/layout/components/DataSourcesPanel.tsx (2)
14-23: LGTM!Also applies to: 90-126
220-447: 📐 Maintainability & Code QualityConfirm the required production build validation.
The PR reports lint, type-check, tests, and browser verification, but not the required
npm run buildresult.As per coding guidelines, “Run npm lint, type-check, and build validation for UI changes in frontends/ui.”
Source: Coding guidelines
frontends/ui/src/features/layout/components/FileSourcesTab.tsx (1)
19-24: LGTM!Also applies to: 40-46, 59-71, 86-112, 121-121, 128-129, 142-171, 187-187, 197-226, 241-241
frontends/ui/src/features/layout/components/SettingsPanel.tsx (1)
68-70: LGTM!frontends/ui/src/features/layout/components/SourceCard.tsx (1)
81-108: LGTM!frontends/ui/src/features/layout/components/TaskCard.spec.tsx (1)
47-69: LGTM!Also applies to: 103-103
frontends/ui/src/features/layout/components/DataConnectionCard.tsx (2)
15-17: LGTM!Also applies to: 111-120, 133-144
111-120: 📐 Maintainability & Code QualityRecord the required build validation.
The PR summary records lint, type-check, tests, and browser screenshots, but not the required production build validation. As per coding guidelines, “Run npm lint, type-check, and build validation for UI changes in frontends/ui.”
Source: Coding guidelines
frontends/ui/src/features/layout/components/DataConnectionsTab.tsx (1)
18-18: LGTM!Also applies to: 104-107
frontends/ui/src/features/layout/components/ReportTab.tsx (1)
17-27: LGTM!Also applies to: 40-61, 103-148
frontends/ui/src/features/layout/components/ResearchPanel.tsx (1)
95-100: LGTM!Also applies to: 178-287
frontends/ui/src/features/layout/components/TaskCard.tsx (1)
9-40: LGTM!Also applies to: 58-75
frontends/ui/src/features/layout/components/TasksTab.tsx (1)
27-93: LGTM!frontends/ui/src/features/layout/components/FileCard.tsx (1)
189-192: LGTM!frontends/ui/src/features/layout/components/ThinkingTab.spec.tsx (1)
9-12: LGTM!Also applies to: 24-30, 42-50, 62-86, 99-155
frontends/ui/src/features/layout/components/ThinkingTab.tsx (2)
7-20: 📐 Maintainability & Code QualityComplete the required production build validation.
The supplied PR evidence covers lint, type-check, tests, and browser verification, but does not explicitly confirm
npm run build.As per coding guidelines, “Run npm lint, type-check, and build validation for UI changes in frontends/ui.”
Source: Coding guidelines
22-67: LGTM!Also applies to: 69-81, 106-147, 149-226
frontends/ui/src/features/layout/components/ThoughtCard.spec.tsx (1)
30-33: LGTM!Also applies to: 137-137, 164-166, 183-183
frontends/ui/src/features/layout/components/ThoughtCard.tsx (1)
22-22: LGTM!Also applies to: 83-96, 109-110, 119-119, 128-142, 157-187
frontends/ui/src/features/layout/index.ts (1)
31-32: 🎯 Functional CorrectnessRemove the
ToolCallInfobarrel export warning. No in-repo consumer importsToolCallInfofrom@/features/layout; it’s only used via./components/ToolCallCard, so dropping that re-export does not break current callers.> Likely an incorrect or invalid review comment.frontends/ui/src/features/layout/components/ChatArea.tsx (2)
219-219: Restore actionable file handling instead of the inert status row.The retry callback is still empty and file messages still omit retry, cancel, and delete controls. This is the same unresolved finding from the previous review.
Also applies to: 279-285, 308-316, 433-449
17-210: LGTM!Also applies to: 221-278, 286-307, 317-432, 450-576
frontends/ui/src/features/chat/lib/session-activity.ts (1)
17-21: LGTM!frontends/ui/src/features/chat/components/AgentResponse.spec.tsx (1)
9-80: LGTM!Also applies to: 91-97, 141-150, 162-216
frontends/ui/src/features/chat/components/AgentResponse.tsx (1)
14-26: LGTM!Also applies to: 65-92, 95-97, 110-111, 131-229
frontends/ui/src/features/layout/components/ChatArea.autoscroll.spec.tsx (1)
1-132: LGTM!frontends/ui/src/features/layout/components/ChatArea.spec.tsx (1)
59-68: LGTM!Also applies to: 273-296, 341-355, 379-389, 404-442
frontends/ui/src/features/layout/components/InputArea.tsx (3)
25-25: LGTM!Also applies to: 173-199
337-408: 📐 Maintainability & Code QualityConfirm the required production validation commands.
The supplied PR evidence covers lint, type-check, tests, screenshots, and browser verification, but does not explicitly confirm
npm run test:ciandnpm run build.As per coding guidelines, “Run npm lint, type-check, and build validation for UI changes” and validate visible changes with “npm run test:ci.”
Also applies to: 510-531
Source: Coding guidelines
152-157: 🩺 Stability & Availability
disconnect()already handles stop semantics. It marks the close intentional, clearsisStreaming/isLoading, and suppresses reconnect churn; the stop path is already covered inuse-websocket-chat.spec.ts.> Likely an incorrect or invalid review comment.frontends/ui/src/features/chat/components/UserMessage.tsx (1)
19-19: LGTM!Also applies to: 29-34
frontends/ui/src/app/page.tsx (1)
21-26: LGTM!frontends/ui/src/app/providers.tsx (1)
20-20: LGTM!Also applies to: 138-138
Signed-off-by: Manush Maheshwari <manushm@nvidia.com>
What this does
PR 3 (final) of the UI-only chat port: brings the chat experience to the premium layout. Verified in a browser against a live agent.
ChatThinking): the intermediate stream folds into a phased spine with status dots, real durations, human tool-call rows, a response timer, and a "using" source chip. Collapses to a summary when done.AgentResponse): superscript citations with hover popovers, a styled source list, a copy button, and an answer-reveal animation.AgentPrompt): collapsible, with plan approve/reject, clickable options, keyboard shortcuts, and inline free-text.Preserved (no regression)
Per-user MCP OAuth, human-in-the-loop navigation blocking, and rich artifact/file handling are all kept. The model picker is intentionally omitted (prod exposes no selectable models). No predictive/analytical/warehouse UI is ported.
Testing
type-checkandlintclean (0 errors).Screenshots
The chat on the restored aiq-rfm theme (composer, push panels, NVIDIA Sans base font), and a response summary with the model badge removed (there is no model selector, so the model icon/name is no longer shown next to the timer):
🤖 Generated with Claude Code
Summary by CodeRabbit
New Features
Bug Fixes