Skip to content

feat: add realtime session browsing and log filtering UI#2342

Merged
akshaydeo merged 6 commits intov1.5.0from
feature/03-27-feat_add_realtime_session_browsing_and_log_filtering_ui
Apr 7, 2026
Merged

feat: add realtime session browsing and log filtering UI#2342
akshaydeo merged 6 commits intov1.5.0from
feature/03-27-feat_add_realtime_session_browsing_and_log_filtering_ui

Conversation

@danpiths
Copy link
Copy Markdown
Collaborator

@danpiths danpiths commented Mar 27, 2026

Summary

Adds the frontend for realtime session browsing and log filtering. Introduces a
session details sheet with summary polling, extracts log detail rendering into a
reusable component, adds parent_request_id filtering across the logs page, and
supports realtime.turn display in columns with multi-role message rendering.

Changes

  • sessionDetailsSheet.tsx: Replaced client-side delta computation with
    server-side getLogSessionSummaryById polling (5s interval). Summary cards
    show logs count, cost, tokens, timestamps, and duration from polled data
  • logDetailView.tsx: Extracted from logDetailsSheet.tsx as pure display
    component with parent request ID clickable link for session navigation. Fixed
    overflow-x-hidden causing 0-height header, added data-testid attributes
    to interactive elements
  • logDetailsSheet.tsx: Simplified to thin wrapper around LogDetailView
  • columns.tsx: Added LogMessageCell shared component,
    getRealtimeTurnMessages for multi-role display (Tool/User/Assistant),
    removed metadataKeys parameter from createColumns
  • page.tsx: Added session state management, handleFilterByParentRequestId
    callback, wired SessionDetailsSheet and session navigation
  • filters.tsx / filterPopover.tsx: Added parent_request_id text input
    filter, showParentRequestIdFilter prop
  • logsApi.ts: Added getLogSessionById and getLogSessionSummaryById query
    endpoints
  • logs.ts types: Added LogSessionSummaryResponse interface, added
    parent_request_id to LogEntry/LogFilters
  • logs.ts constants: Added realtime.turn to RequestTypes,
    RequestTypeLabels, RequestTypeColors

Type of change

  • Bug fix
  • Feature
  • Refactor
  • Documentation
  • Chore/CI

Affected areas

  • Core (Go)
  • Transports (HTTP)
  • Providers/Integrations
  • Plugins
  • UI (Next.js)
  • Docs

How to test

cd ui
npm i
npm run build
npm test -- --run columns
npm test -- --run logs
  • Open the logs page, filter by parent_request_id
  • Click a realtime.turn log to see session details sheet
  • Verify summary cards update via polling every 5s
  • Verify "View Session" button is visible in log detail sheet header

Screenshots/Recordings

N/A — UI changes require running application

Breaking changes

  • Yes
  • No

Related issues

N/A

Security considerations

No new security implications — all data flows through existing authenticated API
endpoints.

Checklist

  • I read docs/contributing/README.md and followed the guidelines
  • I added/updated tests where appropriate
  • I updated documentation where needed
  • I verified builds succeed (Go and UI)
  • I verified the CI pipeline passes locally if applicable

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Mar 27, 2026

📝 Walkthrough

Walkthrough

Adds session-level log viewing and parent_request_id filtering, extracts detailed log UI to LogDetailView, introduces SessionDetailsSheet and a session API endpoint, adds realtime.turn request type, accepts single-string parent_request_id in filters, and removes metadata-driven log columns.

Changes

Cohort / File(s) Summary
Pages / Routing
ui/app/workspace/dashboard/page.tsx, ui/app/workspace/logs/page.tsx
Adds URL-backed parent_request_id state and session selection/highlight state; handlers to open SessionDetailsSheet and apply parent_request_id filtering; dashboard disables parent_request_id filter UI on certain tabs.
Log Detail — View & Sheet
ui/app/workspace/logs/sheets/logDetailView.tsx, ui/app/workspace/logs/sheets/logDetailsSheet.tsx
Introduces LogDetailView (new exported component) that renders full log details; LogDetailSheet now delegates to LogDetailView, retains loading/polling and keyboard navigation, and adds onViewSession/onFilterByParentRequestId props.
Session Details Sheet
ui/app/workspace/logs/sheets/sessionDetailsSheet.tsx
Adds SessionDetailsSheet (new exported component): paginated session fetch, aggregates (cost/tokens/duration), load-more pagination, sort toggle, highlighted-row support, live websocket updates filtered by parent_request_id, and callbacks for log click and filtering.
Table Columns & Message Extraction
ui/app/workspace/logs/views/columns.tsx, ui/app/workspace/logs/views/columns.test.ts
Adds helpers getMessageFromContent, getRealtimeTurnMessages, exports getMessage and LogMessageCell; special-case formatting for realtime.turn; removes metadata-based dynamic columns; adds unit tests for message formatting.
Logs Table & Filters
ui/app/workspace/logs/views/logsTable.tsx, ui/app/workspace/logs/views/filters.tsx
Removes metadataKeys prop/metadata column generation; updates handleFilterChange to accept `string[]
Filter Popover UI
ui/components/filters/filterPopover.tsx
Extends FilterPopoverProps.onFilterChange type, adds showParentRequestIdFilter?: boolean (default true), and conditionally renders a "Session" Input bound to filters.parent_request_id that emits string updates.
API, Types & Store
ui/lib/store/apis/logsApi.ts, ui/lib/types/logs.ts
Includes parent_request_id in filter→query param mapping; adds RTK Query endpoint getLogSessionById and exported hook useLazyGetLogSessionByIdQuery; adds parent_request_id to LogEntry/LogFilters; adds LogSessionDetailResponse type.
Constants & Tests
ui/lib/constants/logs.ts, ui/lib/constants/logs.test.ts
Adds realtime.turn to RequestTypes with label/color and unit test asserting presence and mappings.
Providers utils
ui/app/workspace/providers/fragments/openaiConfigFormFragment.tsx, ui/app/workspace/providers/views/utils.ts
Provider update now built via buildProviderUpdatePayload(...); buildProviderUpdatePayload now includes openai_config resolution.
Misc Tests
ui/app/workspace/logs/views/columns.test.ts
Adds Vitest cases validating message extraction/formatting for tool/user/assistant scenarios.

Sequence Diagram(s)

sequenceDiagram
    participant User as User
    participant LogsPage as LogsPage
    participant LogDetailSheet as LogDetailSheet
    participant LogDetailView as LogDetailView
    participant SessionSheet as SessionDetailsSheet
    participant API as API Server

    User->>LogsPage: Click log row
    LogsPage->>LogDetailSheet: open(logId)
    LogDetailSheet->>API: GET /logs/:id
    API-->>LogDetailSheet: full LogEntry
    LogDetailSheet->>LogDetailView: render(full LogEntry)

    User->>LogDetailView: Click "View Session"
    LogDetailView->>LogsPage: onViewSession(sessionId, logId)
    LogsPage->>SessionSheet: open(sessionId, highlightedLogId)
    SessionSheet->>API: GET /logs/sessions/:sessionId?limit&offset&order
    API-->>SessionSheet: session logs + aggregates
    SessionSheet-->>User: display session logs

    User->>SessionSheet: Click parent_request_id
    SessionSheet->>LogsPage: onFilterByParentRequestId(parentId)
    LogsPage->>API: GET /logs?parent_request_id=parentId
    API-->>LogsPage: filtered logs
    LogsPage-->>User: show filtered list
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~65 minutes

Poem

🐰 I hopped through traces, followed a thread,
Parent IDs led where sessions were spread,
Views split tidy, details take stage,
Streams and tables now share the page,
Tests and types humming — a bright carrot on the ledge!

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 6.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely summarizes the main feature: adding realtime session browsing and log filtering UI. It accurately reflects the primary changes across the codebase.
Description check ✅ Passed The PR description follows the template structure with all required sections present and adequately filled out, including Summary, Changes, Type of change, Affected areas, How to test, Breaking changes, and Checklist.

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

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/03-27-feat_add_realtime_session_browsing_and_log_filtering_ui

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

@CLAassistant
Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.
You have signed the CLA already but the status is still pending? Let us recheck it.

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented Mar 27, 2026

Confidence Score: 4/5

Not safe to merge — the session details sheet cannot be closed due to an undefined handler reference

All previously flagged P1 concerns from earlier review rounds are resolved. One new P1 remains: handleSessionSheetOpenChange at page.tsx:940 is undeclared, causing both a TypeScript compile failure and a ReferenceError at runtime on every sheet-close action. Once this one-function gap is filled the PR is otherwise well-structured.

ui/app/workspace/logs/page.tsx — missing handleSessionSheetOpenChange definition before the return statement

Important Files Changed

Filename Overview
ui/app/workspace/logs/page.tsx Session browsing wiring added, but handleSessionSheetOpenChange passed to SessionDetailsSheet is never defined — TypeScript error and runtime crash on sheet close
ui/app/workspace/logs/sheets/sessionDetailsSheet.tsx New sheet with paginated session log loading, 5 s summary polling, and WebSocket live-update subscription; previously flagged issues (ref stability, onOpenChange instability) resolved
ui/app/workspace/logs/sheets/logDetailView.tsx Extracted from logDetailsSheet as a pure display component; copyRequestBody guards and parent_request_id clickable link added correctly
ui/app/workspace/logs/sheets/logDetailsSheet.tsx Simplified to thin wrapper around LogDetailView with onViewSession navigation prop
ui/app/workspace/logs/views/columns.tsx Added shared LogMessageCell and getRealtimeTurnMessages helper for multi-role realtime.turn display in table columns
ui/components/filters/filterPopover.tsx Added parent_request_id text input filter under a Session group, gated by showParentRequestIdFilter prop (defaults to true)
ui/lib/store/apis/logsApi.ts Added getLogSessionById and getLogSessionSummaryById RTK Query endpoints with correct tag wiring
ui/lib/types/logs.ts Added LogSessionDetailResponse and LogSessionSummaryResponse; parent_request_id added to LogEntry and LogFilters; sort_by union kept narrow
ui/lib/constants/logs.ts realtime.turn added to RequestTypes, RequestTypeLabels, and RequestTypeColors with appropriate cyan colour

Reviews (16): Last reviewed commit: "feat: add realtime session browsing and ..." | Re-trigger Greptile

Comment thread ui/app/workspace/logs/sheets/logDetailView.tsx Outdated
Comment thread ui/app/workspace/logs/sheets/sessionDetailsSheet.tsx Outdated
Comment thread ui/lib/types/logs.ts
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 10

Caution

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

⚠️ Outside diff range comments (1)
ui/app/workspace/logs/sheets/logDetailsSheet.tsx (1)

31-42: ⚠️ Potential issue | 🟠 Major

Don't block the detail sheet on the follow-up fetch.

displayLog already falls back to the row payload, but Lines 37-41 still render only the spinner until fullLog.id === log.id. If useLazyGetLogByIdQuery errors, the sheet never exits loading even though log is available.

Suggested adjustment
-	const isFullDataReady = fullLog?.id === log.id && !isFetching;
-	const displayLog = isFullDataReady ? fullLog : log;
+	const hasFetchedCurrentLog = fullLog?.id === log.id;
+	const displayLog = hasFetchedCurrentLog ? fullLog : log;
@@
-				{!isFullDataReady ? (
-					<div className="flex h-full items-center justify-center">
-						<Loader2 className="text-muted-foreground h-6 w-6 animate-spin" />
-					</div>
-				) : (
-					<LogDetailView
-						log={displayLog}
-						handleDelete={handleDelete}
-						onClose={() => onOpenChange(false)}
-						onFilterByParentRequestId={onFilterByParentRequestId}
-						headerAction={
-							displayLog.parent_request_id && onViewSession ? (
-								<Button
-									variant="outline"
-									size="sm"
-									onClick={() => onViewSession(displayLog.parent_request_id as string, displayLog.id)}
-								>
-									View Session
-								</Button>
-							) : null
-						}
-					/>
-				)}
+				<LogDetailView
+					log={displayLog}
+					loading={isFetching && !hasFetchedCurrentLog}
+					handleDelete={handleDelete}
+					onClose={() => onOpenChange(false)}
+					onFilterByParentRequestId={onFilterByParentRequestId}
+					headerAction={
+						displayLog.parent_request_id && onViewSession ? (
+							<Button
+								variant="outline"
+								size="sm"
+								onClick={() => onViewSession(displayLog.parent_request_id, displayLog.id)}
+							>
+								View Session
+							</Button>
+						) : null
+					}
+				/>
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ui/app/workspace/logs/sheets/logDetailsSheet.tsx` around lines 31 - 42, The
sheet is blocked waiting for the follow-up fetch because the JSX uses
isFullDataReady to decide between Loader2 and LogDetailView; instead render
LogDetailView whenever displayLog is available (displayLog = fullLog?.id ===
log.id && !isFetching ? fullLog : log) so the row payload shows immediately, and
only show the spinner as an overlay/state when isFetching && fullLog?.id !==
log.id (or when the lazy query is loading); also surface the lazy query error
(from useLazyGetLogByIdQuery) to stop the spinner and allow displayLog to
render, or pass isFetching/isError into LogDetailView so it can show field-level
loading/error states.
🧹 Nitpick comments (4)
ui/app/workspace/providers/fragments/openaiConfigFormFragment.tsx (1)

15-15: Use @/... alias import instead of relative path in ui/ TSX

Line 15 should use the project alias for consistency with the providers UI convention.

♻️ Suggested change
-import { buildProviderUpdatePayload } from "../views/utils";
+import { buildProviderUpdatePayload } from "@/app/workspace/providers/views/utils";

Based on learnings: in ui/app/workspace/providers/, TSX files should consistently use @/... alias imports instead of relative paths.

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

In `@ui/app/workspace/providers/fragments/openaiConfigFormFragment.tsx` at line
15, Replace the relative import of buildProviderUpdatePayload with the project
alias import used across the providers UI; update the import statement that
references buildProviderUpdatePayload in openaiConfigFormFragment.tsx to use the
"@/workspace/providers/views/utils" (or the correct `@/`... path matching your
aliases) so it follows the providers UI convention and stays consistent with
other TSX files.
ui/app/workspace/providers/views/utils.ts (1)

18-18: Consider merging partial config updates to prevent future data loss

The current pattern updates.openai_config ?? provider.openai_config replaces the entire object when a partial update is provided. While OpenAIConfig currently has only disable_store, this approach is fragile if new properties are added.

Note: This same pattern exists throughout the function for network_config, proxy_config, and custom_provider_config. If addressing this, consider applying the fix consistently to all config objects or deferring as part of a broader refactor.

Suggested improvement
-		openai_config: updates.openai_config ?? provider.openai_config,
+		openai_config: updates.openai_config
+			? { ...(provider.openai_config ?? {}), ...updates.openai_config }
+			: provider.openai_config,
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ui/app/workspace/providers/views/utils.ts` at line 18, The assignment using
updates.openai_config ?? provider.openai_config will overwrite the whole config
when a partial update is provided; change it to merge partial updates instead
(e.g., set openai_config to a shallow merge of provider.openai_config and
updates.openai_config) so fields not present in updates are preserved, and apply
the same pattern for network_config, proxy_config, and custom_provider_config in
the same function (use the spread/merge of provider.* with updates.*).
ui/lib/store/apis/logsApi.ts (1)

85-139: Reduce filter param duplication to avoid drift.

getLogs and getLogsStats still hand-build params while buildFilterParams exists. This increases maintenance risk as filters evolve (like parent_request_id).

♻️ Suggested consolidation
 		getLogs: builder.query<...>({
 			query: ({ filters, pagination }) => {
-				const params: Record<string, string | number> = {
+				const params: Record<string, string | number> = {
 					limit: pagination.limit,
 					offset: pagination.offset,
 					sort_by: pagination.sort_by,
 					order: pagination.order,
+					...buildFilterParams(filters),
 				};
-
-				// Add filters to params if they exist
-				...
 				return { url: "/logs", params };
 			},
 		}),
...
 		getLogsStats: builder.query<...>({
 			query: ({ filters }) => {
-				const params: Record<string, string | number> = {};
-				// Add filters to params if they exist
-				...
+				const params = buildFilterParams(filters);
 				return { url: "/logs/stats", params };
 			},
 		}),

Also applies to: 168-217

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

In `@ui/lib/store/apis/logsApi.ts` around lines 85 - 139, The query handler in
getLogs manually recreates filter-to-param logic that buildFilterParams already
implements, causing duplication and drift; replace the entire manual params
construction in the getLogs query with a call to buildFilterParams (and reuse
the same call in getLogsStats), passing the incoming filters and pagination,
ensure the returned params still include pagination keys (limit, offset,
sort_by, order) and special handling for metadata_filters/parent_request_id
remains preserved by buildFilterParams, and update any dependent types or tests
to use the consolidated buildFilterParams output instead of the duplicated
params construction.
ui/lib/types/logs.ts (1)

511-515: Keep Pagination.sort_by narrowed to the supported log sort keys.

This shared type is still consumed by the main logs page/table as the four-key contract (timestamp, latency, tokens, cost). Widening it to string weakens that contract for every caller just to satisfy the session flow. A separate session-pagination shape is safer than loosening the shared one.

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

In `@ui/lib/types/logs.ts` around lines 511 - 515, The Pagination interface's
sort_by is too wide; change Pagination.sort_by from string to the union of
supported log keys ("timestamp" | "latency" | "tokens" | "cost") to restore the
four-key contract used by the logs page/table, and if session flow needs broader
keys, introduce a separate type (e.g., SessionPagination with sort_by: string)
for session-specific usage; update any callers that rely on the shared
Pagination to use the narrowed keys or the new SessionPagination as appropriate.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@ui/app/workspace/logs/sheets/logDetailsSheet.tsx`:
- Around line 47-55: Add a stable test selector to the new "View Session" Button
rendered in the headerAction conditional (the Button inside the block guarded by
displayLog.parent_request_id && onViewSession) by adding a data-testid attribute
following the project pattern, e.g. data-testid="session-button-view"
(entity=session, element=button, qualifier=view), so tests can reliably target
the onViewSession handler that uses displayLog.parent_request_id and
displayLog.id.

In `@ui/app/workspace/logs/sheets/logDetailView.tsx`:
- Around line 146-150: The Async badge currently checks
log.metadata?.isAsyncRequest by truthiness which renders for the string "false";
update the conditional in logDetailView (the JSX around
log.metadata?.isAsyncRequest) to compare the value explicitly (e.g.,
log.metadata?.isAsyncRequest === "true") or normalize the metadata value to a
boolean before rendering so the Badge only shows when the flag is actually
"true".
- Around line 127-140: Replace the non-focusable clickable <code> elements (the
Request ID copy block using log.id and navigator.clipboard.writeText with
toast.success/toast.error) with real interactive controls (e.g., <button> or <a
role="button">) so they are keyboard-focusable and accessible; update the click
handler from the inline onClick to the control's onClick and ensure proper
keyboard handling, and add data-testid attributes following the pattern
data-testid="request-id-copy-button" (and similarly for the parent-request
filter control referenced around lines 247-263, e.g.,
data-testid="parent-request-filter-button") to both new elements for testing.
Ensure the new controls still call navigator.clipboard.writeText(log.id) and
show toast success/error as before.
- Around line 210-219: The current rendering fabricates zero latency by using
`log.latency || 0`; change the End Timestamp and Latency render logic to treat
null/undefined separately: for `LogEntryDetailsView` labeled "End Timestamp"
only compute `moment(log.timestamp).add(log.latency, "ms")` when `log.latency`
is not null/undefined (use a nullish check) and otherwise show "N/A"; for the
"Latency" field use a nullish check on `log.latency` and render "N/A" when it is
null/undefined or NaN, otherwise format the numeric latency with `toFixed(2) +
"ms"`. Ensure you reference `LogEntryDetailsView`, `log.timestamp`, and
`log.latency` when making these changes.
- Around line 549-605: The copyRequestBody logic misclassifies realtime.turn (it
is treated as responses and only reads responses_input_history) and also uses
the wrong object type for embeddings; update the predicate checks and branching:
add a specific isRealtimeTurn flag (e.g., const isRealtimeTurn = log.object ===
"realtime.turn") and remove realtime.turn from isResponses, change isEmbedding
to match "embedding" instead of "list", and in the branch for realtime.turn
populate requestBody with the conversation input (use log.input_history/messages
similar to isChat) so turns include the actual input_history when serializing;
update the branches that set requestBody.input/messages to reference these
revised flags (isRealtimeTurn, isResponses, isEmbedding) and reuse
extractTextFromMessage/extractTextsFromMessage as needed.

In `@ui/app/workspace/logs/sheets/sessionDetailsSheet.tsx`:
- Around line 212-232: Replace the non-focusable clickable <code> element used
for filtering with a real interactive element (e.g., a <button> or <a>) so it
can be focused and activated by keyboard; wire its onClick to
onFilterByParentRequestId(sessionId) and keep the Tooltip wrapping behavior,
referencing sessionId and onFilterByParentRequestId to find the code. Add stable
data-testid attributes: session-details-filter-btn on the new filter button,
session-details-sort-btn on the sort Button that calls setSortOrder (and uses
sortOrder), and session-details-load-more-btn on the load-more control mentioned
around the 333-338 region; ensure these elements are semantic,
keyboard-accessible, and retain current visual styles and aria/tooltip behavior.
- Around line 188-201: Live socket updates modify sessionLogs, totalCount, and
hasMore but never update the derived summary fields or fetchedCount, causing UI
mismatch; update those derived values whenever you merge a live log. In the
setSessionLogs handler (and where operation === "create"/"update" is handled)
recalculate or adjust summary.totalCost, summary.totalTokens, summary.latestAt,
and summary.durationMs (either by applying a delta from the incoming log or by
aggregating the updated sessionLogs returned by sortSessionLogs), increment
fetchedCount when a new log is appended, and recompute hasMore using the updated
fetchedCount and totalCount; ensure you update the same state slice that renders
the cards (the summary object and fetchedCount) so cards and pager stay in sync
with setSessionLogs/setTotalCount changes.
- Around line 126-161: The fetch handler loadSessionPage currently ignores
triggerGetSession errors and treats them as empty results; update
loadSessionPage to explicitly check result.error after awaiting
triggerGetSession and handle it separately (e.g., set an error state or call a
provided onError handler, stop further processing, and avoid treating it like an
empty session or closing the sheet), so only successful responses update
setSummary, setSessionLogs, setTotalCount/setHasMore/setFetchedCount and only
the reset branch uses onOpenChange(false) when the result is a successful empty
session; reference loadSessionPage, triggerGetSession, result.error, setSummary,
setSessionLogs and onOpenChange when making the change.

In `@ui/app/workspace/logs/views/columns.tsx`:
- Around line 29-36: getRealtimeTurnMessages currently uses .find(...) which
returns only the first matching tool/user message, causing stale/incomplete
previews; update getRealtimeTurnMessages to collect all messages per role from
log.input_history (e.g., use .filter(...) for role === "tool" and role ===
"user"), map each to getMessageFromContent(message.content), and join them (or
alternatively pick the last matching message) to produce the tool and user
strings; keep the assistant behavior for log.output_message the same and ensure
empty-string fallback when no messages exist.

In `@ui/components/filters/filterPopover.tsx`:
- Around line 202-213: The new Input rendered when showParentRequestIdFilter is
true lacks a test selector; add a data-testid prop to that Input (the component
instance using value={filters.parent_request_id} and onChange={(e) =>
onFilterChange("parent_request_id", e.target.value)}) following the project
pattern entity-element-qualifier, e.g.
data-testid="request-parent-request-id-input", so tests can reliably target the
parent request ID control.

---

Outside diff comments:
In `@ui/app/workspace/logs/sheets/logDetailsSheet.tsx`:
- Around line 31-42: The sheet is blocked waiting for the follow-up fetch
because the JSX uses isFullDataReady to decide between Loader2 and
LogDetailView; instead render LogDetailView whenever displayLog is available
(displayLog = fullLog?.id === log.id && !isFetching ? fullLog : log) so the row
payload shows immediately, and only show the spinner as an overlay/state when
isFetching && fullLog?.id !== log.id (or when the lazy query is loading); also
surface the lazy query error (from useLazyGetLogByIdQuery) to stop the spinner
and allow displayLog to render, or pass isFetching/isError into LogDetailView so
it can show field-level loading/error states.

---

Nitpick comments:
In `@ui/app/workspace/providers/fragments/openaiConfigFormFragment.tsx`:
- Line 15: Replace the relative import of buildProviderUpdatePayload with the
project alias import used across the providers UI; update the import statement
that references buildProviderUpdatePayload in openaiConfigFormFragment.tsx to
use the "@/workspace/providers/views/utils" (or the correct `@/`... path matching
your aliases) so it follows the providers UI convention and stays consistent
with other TSX files.

In `@ui/app/workspace/providers/views/utils.ts`:
- Line 18: The assignment using updates.openai_config ?? provider.openai_config
will overwrite the whole config when a partial update is provided; change it to
merge partial updates instead (e.g., set openai_config to a shallow merge of
provider.openai_config and updates.openai_config) so fields not present in
updates are preserved, and apply the same pattern for network_config,
proxy_config, and custom_provider_config in the same function (use the
spread/merge of provider.* with updates.*).

In `@ui/lib/store/apis/logsApi.ts`:
- Around line 85-139: The query handler in getLogs manually recreates
filter-to-param logic that buildFilterParams already implements, causing
duplication and drift; replace the entire manual params construction in the
getLogs query with a call to buildFilterParams (and reuse the same call in
getLogsStats), passing the incoming filters and pagination, ensure the returned
params still include pagination keys (limit, offset, sort_by, order) and special
handling for metadata_filters/parent_request_id remains preserved by
buildFilterParams, and update any dependent types or tests to use the
consolidated buildFilterParams output instead of the duplicated params
construction.

In `@ui/lib/types/logs.ts`:
- Around line 511-515: The Pagination interface's sort_by is too wide; change
Pagination.sort_by from string to the union of supported log keys ("timestamp" |
"latency" | "tokens" | "cost") to restore the four-key contract used by the logs
page/table, and if session flow needs broader keys, introduce a separate type
(e.g., SessionPagination with sort_by: string) for session-specific usage;
update any callers that rely on the shared Pagination to use the narrowed keys
or the new SessionPagination as appropriate.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 87eb7b78-f7d3-4fd5-9d6f-e785e99f66cc

📥 Commits

Reviewing files that changed from the base of the PR and between 33a3e91 and cc0cadd.

📒 Files selected for processing (16)
  • ui/app/workspace/dashboard/page.tsx
  • ui/app/workspace/logs/page.tsx
  • ui/app/workspace/logs/sheets/logDetailView.tsx
  • ui/app/workspace/logs/sheets/logDetailsSheet.tsx
  • ui/app/workspace/logs/sheets/sessionDetailsSheet.tsx
  • ui/app/workspace/logs/views/columns.test.ts
  • ui/app/workspace/logs/views/columns.tsx
  • ui/app/workspace/logs/views/filters.tsx
  • ui/app/workspace/logs/views/logsTable.tsx
  • ui/app/workspace/providers/fragments/openaiConfigFormFragment.tsx
  • ui/app/workspace/providers/views/utils.ts
  • ui/components/filters/filterPopover.tsx
  • ui/lib/constants/logs.test.ts
  • ui/lib/constants/logs.ts
  • ui/lib/store/apis/logsApi.ts
  • ui/lib/types/logs.ts

Comment thread ui/app/workspace/logs/sheets/logDetailsSheet.tsx Outdated
Comment thread ui/app/workspace/logs/sheets/logDetailView.tsx
Comment thread ui/app/workspace/logs/sheets/logDetailView.tsx
Comment thread ui/app/workspace/logs/sheets/logDetailView.tsx
Comment thread ui/app/workspace/logs/sheets/logDetailView.tsx
Comment thread ui/app/workspace/logs/sheets/sessionDetailsSheet.tsx
Comment thread ui/app/workspace/logs/sheets/sessionDetailsSheet.tsx
Comment thread ui/app/workspace/logs/sheets/sessionDetailsSheet.tsx
Comment thread ui/app/workspace/logs/views/columns.tsx Outdated
Comment thread ui/components/filters/filterPopover.tsx
@danpiths danpiths force-pushed the feature/03-27-feat_add_realtime_websocket_webrtc_and_client_secret_handlers branch from 33a3e91 to 2d1c18b Compare March 30, 2026 10:24
@danpiths danpiths force-pushed the feature/03-27-feat_add_realtime_session_browsing_and_log_filtering_ui branch from cc0cadd to ecd583b Compare March 30, 2026 10:24
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
ui/app/workspace/logs/page.tsx (1)

58-60: Remove shadowed selectedLog state — it's never read.

Line 58 declares selectedLog state, but line 139 shadows it with a derived value (selectedLogFromData ?? fetchedLog). All subsequent references to selectedLog resolve to the shadowed variable, so the calls to setSelectedLog (lines 329, 914, 936, 954) update a value that is never consumed.

Consider removing the state entirely and using a local variable or renaming to avoid confusion:

♻️ Suggested cleanup
-	const [selectedLog, setSelectedLog] = useState<LogEntry | null>(null);
 	const [selectedSessionId, setSelectedSessionId] = useState<string | null>(null);
 	const [sessionHighlightedLogId, setSessionHighlightedLogId] = useState<string | null>(null);

Then remove the now-unused setSelectedLog calls throughout the file (lines 329, 914, 936, 954), as they serve no purpose.

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

In `@ui/app/workspace/logs/page.tsx` around lines 58 - 60, The file declares a
useState hook const [selectedLog, setSelectedLog] = useState<LogEntry |
null>(null) but later a derived variable selectedLogFromData ?? fetchedLog
shadows and is actually used; remove the unused state to avoid confusion: delete
the selectedLog/useState declaration and remove all calls to setSelectedLog
(they have no effect), or alternatively if persistent state was intended, rename
the hook (e.g., selectedLogState/setSelectedLogState) and update usages to
consistently use that state instead of the derived
selectedLogFromData/fetchedLog; ensure references to selectedLogFromData and
fetchedLog remain unchanged and that no orphaned setSelectedLog calls remain.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@ui/app/workspace/logs/page.tsx`:
- Around line 58-60: The file declares a useState hook const [selectedLog,
setSelectedLog] = useState<LogEntry | null>(null) but later a derived variable
selectedLogFromData ?? fetchedLog shadows and is actually used; remove the
unused state to avoid confusion: delete the selectedLog/useState declaration and
remove all calls to setSelectedLog (they have no effect), or alternatively if
persistent state was intended, rename the hook (e.g.,
selectedLogState/setSelectedLogState) and update usages to consistently use that
state instead of the derived selectedLogFromData/fetchedLog; ensure references
to selectedLogFromData and fetchedLog remain unchanged and that no orphaned
setSelectedLog calls remain.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 98f294a7-9bb4-4ad2-8468-2f66a2ff5e4d

📥 Commits

Reviewing files that changed from the base of the PR and between cc0cadd and ecd583b.

📒 Files selected for processing (5)
  • ui/app/workspace/dashboard/page.tsx
  • ui/app/workspace/logs/page.tsx
  • ui/app/workspace/logs/sheets/logDetailView.tsx
  • ui/app/workspace/logs/sheets/logDetailsSheet.tsx
  • ui/app/workspace/logs/sheets/sessionDetailsSheet.tsx
✅ Files skipped from review due to trivial changes (1)
  • ui/app/workspace/logs/sheets/sessionDetailsSheet.tsx
🚧 Files skipped from review as they are similar to previous changes (2)
  • ui/app/workspace/dashboard/page.tsx
  • ui/app/workspace/logs/sheets/logDetailView.tsx

@danpiths danpiths force-pushed the feature/03-27-feat_add_realtime_websocket_webrtc_and_client_secret_handlers branch from 2d1c18b to b91d7ac Compare March 30, 2026 12:49
@danpiths danpiths force-pushed the feature/03-27-feat_add_realtime_session_browsing_and_log_filtering_ui branch from ecd583b to 839db86 Compare March 30, 2026 12:49
Comment thread ui/app/workspace/logs/page.tsx Outdated
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

Caution

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

⚠️ Outside diff range comments (1)
ui/app/workspace/logs/views/columns.tsx (1)

126-260: ⚠️ Potential issue | 🟠 Major

Don't drop the metadata columns from createColumns.

After this change the logs table can only render the base columns plus actions, so every metadata_* column disappears even though the rest of this stack still exposes metadata filtering. If the goal is to simplify the prop surface, move metadata-column generation elsewhere instead of removing it outright. Based on learnings, metadata_* columns in ui/app/workspace/logs/views/logsTable.tsx are intentionally shown visible by default to aid discoverability.

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

In `@ui/app/workspace/logs/views/columns.tsx` around lines 126 - 260, The
createColumns function removed generation of dynamic metadata_* columns causing
those columns to vanish; restore or reintroduce the metadata column logic by
generating metadata columns (those keyed as metadata_*) and appending them to
baseColumns before returning (keep using the existing ColumnDef<LogEntry>
shape), or move that generation into a helper used by createColumns so
logsTable.tsx can continue to show metadata columns by default; update
createColumns (and any helper it calls) to produce the metadata column
definitions and include them in the returned array alongside actionsColumn so
filtering in logsTable remains functional.
♻️ Duplicate comments (1)
ui/app/workspace/logs/sheets/logDetailView.tsx (1)

559-563: ⚠️ Potential issue | 🟠 Major

Match embedding in the copy-request-body guard.

isEmbedding still checks "list", so the embedding serializer never runs and the new copy action still rejects embedding logs as unsupported.

🔧 Proposed fix
-		const isEmbedding = log.object === "list";
+		const isEmbedding = log.object === "embedding";
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ui/app/workspace/logs/sheets/logDetailView.tsx` around lines 559 - 563, The
guard variable isEmbedding is still matching "list" so embedding logs are
treated as unsupported; update the check used to set isEmbedding (and any use in
the copy-request-body guard) to match the correct embedding object types (e.g.,
check log.object === "embedding" and, if applicable, "embedding.chunk") instead
of "list" so the embedding serializer runs for embedding logs (update the
isEmbedding assignment and any related conditional that references isEmbedding).
🧹 Nitpick comments (1)
ui/app/workspace/providers/fragments/openaiConfigFormFragment.tsx (1)

45-49: Preserve existing openai_config fields when updating one key.

This currently sends only { disable_store }. With the helper’s replace semantics, any future openai_config keys could be unintentionally dropped.

♻️ Suggested hardening
 		const updatedProvider = buildProviderUpdatePayload(provider, {
 			openai_config: {
+				...provider.openai_config,
 				disable_store: data.disable_store,
 			},
 		});
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ui/app/workspace/providers/fragments/openaiConfigFormFragment.tsx` around
lines 45 - 49, When building the update payload in buildProviderUpdatePayload,
preserve existing provider.openai_config keys instead of replacing the whole
object; merge the current provider.openai_config with the new field {
disable_store: data.disable_store } so other keys aren’t dropped. Locate the
code that constructs updatedProvider (uses provider and openai_config) and
change it to shallow-merge provider.openai_config with the new partial update
before passing to buildProviderUpdatePayload so only the disable_store field is
updated.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@ui/app/workspace/logs/views/columns.tsx`:
- Around line 13-26: getMessageFromContent currently only treats blocks with
type === "text" as carrying visible text, so structured blocks like "input_text"
and "output_text" are ignored; update getMessageFromContent to treat any block
that has a truthy block.text as text-bearing (or explicitly include "input_text"
and "output_text") and collect all such block.text values (e.g., push into an
array) and return them joined (e.g., with a space) instead of only returning the
last matching block; update references to lastTextContentBlock in the
getMessageFromContent function accordingly.

In `@ui/components/filters/filterPopover.tsx`:
- Around line 205-207: The parent_request_id Input currently calls
onFilterChange on every keystroke (Input value={filters.parent_request_id}
onChange={(e) => onFilterChange("parent_request_id", e.target.value)}), which
spams navigation/refetch; change this to use a local draft state for this field
(e.g., component state draftParentRequestId) and bind Input to that draft,
update the draft on every onChange, and only call
onFilterChange("parent_request_id", draft) when the user presses Enter
(onKeyDown) or onBlur; alternatively implement a debounced commit that uses
history.replace semantics when committing to avoid backstack clutter. Ensure you
update the Input handlers (onChange, onBlur, onKeyDown) and initialize the draft
from filters.parent_request_id when the popover mounts/shows.

---

Outside diff comments:
In `@ui/app/workspace/logs/views/columns.tsx`:
- Around line 126-260: The createColumns function removed generation of dynamic
metadata_* columns causing those columns to vanish; restore or reintroduce the
metadata column logic by generating metadata columns (those keyed as metadata_*)
and appending them to baseColumns before returning (keep using the existing
ColumnDef<LogEntry> shape), or move that generation into a helper used by
createColumns so logsTable.tsx can continue to show metadata columns by default;
update createColumns (and any helper it calls) to produce the metadata column
definitions and include them in the returned array alongside actionsColumn so
filtering in logsTable remains functional.

---

Duplicate comments:
In `@ui/app/workspace/logs/sheets/logDetailView.tsx`:
- Around line 559-563: The guard variable isEmbedding is still matching "list"
so embedding logs are treated as unsupported; update the check used to set
isEmbedding (and any use in the copy-request-body guard) to match the correct
embedding object types (e.g., check log.object === "embedding" and, if
applicable, "embedding.chunk") instead of "list" so the embedding serializer
runs for embedding logs (update the isEmbedding assignment and any related
conditional that references isEmbedding).

---

Nitpick comments:
In `@ui/app/workspace/providers/fragments/openaiConfigFormFragment.tsx`:
- Around line 45-49: When building the update payload in
buildProviderUpdatePayload, preserve existing provider.openai_config keys
instead of replacing the whole object; merge the current provider.openai_config
with the new field { disable_store: data.disable_store } so other keys aren’t
dropped. Locate the code that constructs updatedProvider (uses provider and
openai_config) and change it to shallow-merge provider.openai_config with the
new partial update before passing to buildProviderUpdatePayload so only the
disable_store field is updated.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 2df281fc-8a0f-4467-8dd3-2f2fba8659bc

📥 Commits

Reviewing files that changed from the base of the PR and between ecd583b and 839db86.

📒 Files selected for processing (16)
  • ui/app/workspace/dashboard/page.tsx
  • ui/app/workspace/logs/page.tsx
  • ui/app/workspace/logs/sheets/logDetailView.tsx
  • ui/app/workspace/logs/sheets/logDetailsSheet.tsx
  • ui/app/workspace/logs/sheets/sessionDetailsSheet.tsx
  • ui/app/workspace/logs/views/columns.test.ts
  • ui/app/workspace/logs/views/columns.tsx
  • ui/app/workspace/logs/views/filters.tsx
  • ui/app/workspace/logs/views/logsTable.tsx
  • ui/app/workspace/providers/fragments/openaiConfigFormFragment.tsx
  • ui/app/workspace/providers/views/utils.ts
  • ui/components/filters/filterPopover.tsx
  • ui/lib/constants/logs.test.ts
  • ui/lib/constants/logs.ts
  • ui/lib/store/apis/logsApi.ts
  • ui/lib/types/logs.ts
✅ Files skipped from review due to trivial changes (3)
  • ui/lib/constants/logs.test.ts
  • ui/app/workspace/logs/views/columns.test.ts
  • ui/app/workspace/logs/sheets/sessionDetailsSheet.tsx
🚧 Files skipped from review as they are similar to previous changes (5)
  • ui/app/workspace/providers/views/utils.ts
  • ui/app/workspace/logs/views/filters.tsx
  • ui/lib/constants/logs.ts
  • ui/app/workspace/dashboard/page.tsx
  • ui/lib/store/apis/logsApi.ts

Comment thread ui/app/workspace/logs/views/columns.tsx
Comment thread ui/components/filters/filterPopover.tsx
@danpiths danpiths force-pushed the feature/03-27-feat_add_realtime_websocket_webrtc_and_client_secret_handlers branch from b91d7ac to c3a8913 Compare March 30, 2026 14:50
@danpiths danpiths force-pushed the feature/03-27-feat_add_realtime_session_browsing_and_log_filtering_ui branch from 839db86 to c28e16f Compare March 30, 2026 14:50
Comment thread ui/app/workspace/logs/sheets/logDetailView.tsx
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

♻️ Duplicate comments (2)
ui/app/workspace/logs/sheets/sessionDetailsSheet.tsx (1)

203-237: ⚠️ Potential issue | 🟠 Major

Live merges still drift totals and pagination for unseen logs.

summary is seeded from whole-session backend totals, so when an off-page log arrives as an "update" and oldLog is undefined, the full cost/token values get added again. The "create" branch also computes hasMore from the pre-increment refs, so a fully loaded session can flip Load More back on after appending the new row. Only mutate summary/counts when the id was actually inserted, and derive hasMore from the post-insert counts.

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

In `@ui/app/workspace/logs/sheets/sessionDetailsSheet.tsx` around lines 203 - 237,
The live-merge logic updates totals and pagination even when an incoming
"update" doesn't insert a new row (oldLog undefined), causing double-counting
and incorrect hasMore; modify the block around
setSessionLogs/setTotalCount/setFetchedCount/setHasMore/setSummary so you only
apply totalCount/fetchedCount/summary deltas when the id was actually inserted
(i.e., detect insertion inside setSessionLogs using the same findIndex logic or
capture an "inserted" boolean when you build next), and compute hasMore from the
post-insert counts (use fetchedCountRef.current and totalCountRef.current after
increment or derive from the new counts) rather than the pre-increment refs;
keep sortSessionLogs and existing cost/token delta logic but guard it behind the
insertion check so updates that don't add a row don't change summary or counts.
ui/app/workspace/logs/sheets/logDetailView.tsx (1)

683-689: ⚠️ Potential issue | 🟠 Major

copyRequestBody still excludes actual embedding requests.

isEmbedding checks "list", so object === "embedding" logs still fall through the unsupported-type toast and never serialize their input.

🩹 Suggested fix
-		const isEmbedding = log.object === "list";
+		const isEmbedding = log.object === "embedding";

Also applies to: 716-757

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

In `@ui/app/workspace/logs/sheets/logDetailView.tsx` around lines 683 - 689, The
embedding branch is using the wrong object value so embedding logs fall through
as unsupported; update the log type checks and serialization in copyRequestBody
to treat embedding objects correctly by changing the isEmbedding check from
"list" to include "embedding" (e.g., const isEmbedding = log.object ===
"embedding" || log.object === "list") and then ensure copyRequestBody handles
embedding logs by serializing their input payload (use the same serialization
used for other request types) when isEmbedding is true so embedding requests are
copied rather than triggering the unsupported-type toast.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@ui/app/workspace/logs/sheets/sessionDetailsSheet.tsx`:
- Around line 130-168: loadSessionPage can apply stale responses because it
doesn't verify the request context after awaiting triggerGetSession; capture a
local request token (or the current sessionId and sortOrder) at the start of
loadSessionPage (e.g., const requestSession = sessionId; const requestSort =
sortOrder or increment a requestId), then after the await check that the
captured values still match the current sessionId/sortOrder (or that the
requestId is still the latest) before doing any state updates or calling
onOpenChange; bail out early if they differ so older responses cannot overwrite
setSessionLogs, setSummary, setTotalCount, setHasMore, setFetchedCount or call
onOpenChange.
- Around line 183-189: When starting a new session load (the block that calls
setSessionLogs([]), setFetchedCount(0), setTotalCount(0), sets
fetchedCountRef/totalCountRef to 0, setHasMore(false) and calls
loadSessionPage(0, true)), also reset the session summary state by calling the
summary setter (setSummary) to its initial/empty value so the summary cards
don't show stale totals/timestamps if the fetch fails; ensure this reset happens
before invoking loadSessionPage so the UI is cleared immediately.

---

Duplicate comments:
In `@ui/app/workspace/logs/sheets/logDetailView.tsx`:
- Around line 683-689: The embedding branch is using the wrong object value so
embedding logs fall through as unsupported; update the log type checks and
serialization in copyRequestBody to treat embedding objects correctly by
changing the isEmbedding check from "list" to include "embedding" (e.g., const
isEmbedding = log.object === "embedding" || log.object === "list") and then
ensure copyRequestBody handles embedding logs by serializing their input payload
(use the same serialization used for other request types) when isEmbedding is
true so embedding requests are copied rather than triggering the
unsupported-type toast.

In `@ui/app/workspace/logs/sheets/sessionDetailsSheet.tsx`:
- Around line 203-237: The live-merge logic updates totals and pagination even
when an incoming "update" doesn't insert a new row (oldLog undefined), causing
double-counting and incorrect hasMore; modify the block around
setSessionLogs/setTotalCount/setFetchedCount/setHasMore/setSummary so you only
apply totalCount/fetchedCount/summary deltas when the id was actually inserted
(i.e., detect insertion inside setSessionLogs using the same findIndex logic or
capture an "inserted" boolean when you build next), and compute hasMore from the
post-insert counts (use fetchedCountRef.current and totalCountRef.current after
increment or derive from the new counts) rather than the pre-increment refs;
keep sortSessionLogs and existing cost/token delta logic but guard it behind the
insertion check so updates that don't add a row don't change summary or counts.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 78c87a5d-935b-4f4a-9d06-dc2550f59b50

📥 Commits

Reviewing files that changed from the base of the PR and between 839db86 and c28e16f.

📒 Files selected for processing (16)
  • ui/app/workspace/dashboard/page.tsx
  • ui/app/workspace/logs/page.tsx
  • ui/app/workspace/logs/sheets/logDetailView.tsx
  • ui/app/workspace/logs/sheets/logDetailsSheet.tsx
  • ui/app/workspace/logs/sheets/sessionDetailsSheet.tsx
  • ui/app/workspace/logs/views/columns.test.ts
  • ui/app/workspace/logs/views/columns.tsx
  • ui/app/workspace/logs/views/filters.tsx
  • ui/app/workspace/logs/views/logsTable.tsx
  • ui/app/workspace/providers/fragments/openaiConfigFormFragment.tsx
  • ui/app/workspace/providers/views/utils.ts
  • ui/components/filters/filterPopover.tsx
  • ui/lib/constants/logs.test.ts
  • ui/lib/constants/logs.ts
  • ui/lib/store/apis/logsApi.ts
  • ui/lib/types/logs.ts
✅ Files skipped from review due to trivial changes (2)
  • ui/lib/constants/logs.ts
  • ui/app/workspace/logs/views/columns.test.ts
🚧 Files skipped from review as they are similar to previous changes (8)
  • ui/app/workspace/logs/views/filters.tsx
  • ui/lib/constants/logs.test.ts
  • ui/app/workspace/dashboard/page.tsx
  • ui/app/workspace/logs/views/logsTable.tsx
  • ui/components/filters/filterPopover.tsx
  • ui/app/workspace/providers/views/utils.ts
  • ui/lib/types/logs.ts
  • ui/app/workspace/logs/views/columns.tsx

Comment thread ui/app/workspace/logs/sheets/sessionDetailsSheet.tsx
Comment thread ui/app/workspace/logs/sheets/sessionDetailsSheet.tsx
@danpiths danpiths force-pushed the feature/03-27-feat_add_realtime_session_browsing_and_log_filtering_ui branch from c28e16f to bd6ac46 Compare March 30, 2026 17:00
@danpiths danpiths force-pushed the feature/03-27-feat_add_realtime_websocket_webrtc_and_client_secret_handlers branch from c3a8913 to 13ed4ad Compare March 30, 2026 17:00
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

Caution

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

⚠️ Outside diff range comments (1)
ui/app/workspace/logs/sheets/logDetailsSheet.tsx (1)

56-69: ⚠️ Potential issue | 🟠 Major

Render the fallback log when the detail refetch fails.

If useGetLogByIdQuery() errors, isFullDataReady never becomes true, so the sheet stays in the loading branch indefinitely even though displayLog already falls back to the row data.

💡 Suggested change
-				{!isFullDataReady ? (
+				{!isFullDataReady && !isError ? (
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ui/app/workspace/logs/sheets/logDetailsSheet.tsx` around lines 56 - 69, The
sheet currently shows a loader based only on isFullDataReady so when
useGetLogByIdQuery() errors the UI never falls back to the row data; change the
render condition to rely on displayLog (which already falls back to log) instead
of strict isFullDataReady. Concretely, in the Sheet render block replace the
check that shows the loader (currently using isFullDataReady) with a check that
shows the loader only when there is no displayLog (or when loading and
displayLog is undefined) so that when useGetLogByIdQuery() errors the component
renders <LogDetailView displayLog={displayLog}> using the row data (references:
isFullDataReady, fullLog, log, displayLog, useGetLogByIdQuery, LogDetailView).
♻️ Duplicate comments (1)
ui/app/workspace/logs/views/columns.tsx (1)

20-26: ⚠️ Potential issue | 🟡 Minor

This still keeps only the last text block.

getMessageFromContent() now recognizes input_text/output_text, but it still overwrites earlier segments inside the same content array. Multi-block prompts/responses will truncate to the final segment in both the main table and the session sheet.

💡 Suggested change
-	let lastTextContentBlock = "";
-	for (const block of content) {
-		if ((block.type === "text" || block.type === "input_text" || block.type === "output_text") && block.text) {
-			lastTextContentBlock = block.text;
-		}
-	}
-	return lastTextContentBlock;
+	return content
+		.filter((block) => block.type === "text" || block.type === "input_text" || block.type === "output_text")
+		.map((block) => block.text ?? "")
+		.filter(Boolean)
+		.join(" ");
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ui/app/workspace/logs/views/columns.tsx` around lines 20 - 26,
getMessageFromContent currently only keeps the last matching text segment (it
overwrites lastTextContentBlock), so multi-block prompts/responses are
truncated; change the logic to accumulate matching block.text values in order
(e.g., push them into an array or append with a space/separator) instead of
assigning, ensuring you still check block.type === "text" || "input_text" ||
"output_text" and block.text; return the concatenated string (trimmed) rather
than the final single segment so getMessageFromContent, the lastTextContentBlock
variable, and any consumers get the full combined message.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@ui/app/workspace/logs/sheets/sessionDetailsSheet.tsx`:
- Around line 205-214: The bug is that update events for logs not already in
sessionLogs cause oldLog to be undefined and summary deltas get applied
incorrectly; fix by changing the setSessionLogs/update handling so you only
compute or apply costDelta/tokensDelta when oldLog is found: in the
setSessionLogs callback (the block that finds idx and sets oldLog), keep the
current append behavior for idx < 0 (return sortSessionLogs([...prev, log])) but
ensure any summary-delta adjustments are guarded with a check like if (oldLog
!== undefined) so unseen updates are treated as new adds without applying
summary deltas; apply the same guard in the analogous code path around the lines
222-237.
- Around line 216-220: The current live "create" handler increments fetchedCount
(via setFetchedCount) which wrongly shifts the paging index and causes
loadSessionPage(fetchedCount) to skip historical rows; modify the "create"
branch so it only updates totalCount (setTotalCount) and adjusts hasMore based
on refs, but do NOT increment fetchedCount—use fetchedCountRef.current <
totalCountRef.current (or fetchedCountRef.current < totalCountRef.current + 1 if
you intentionally want the +1 behavior) when calling setHasMore; update the
block around setTotalCount, setFetchedCount, and setHasMore (the symbols to
change) accordingly.

---

Outside diff comments:
In `@ui/app/workspace/logs/sheets/logDetailsSheet.tsx`:
- Around line 56-69: The sheet currently shows a loader based only on
isFullDataReady so when useGetLogByIdQuery() errors the UI never falls back to
the row data; change the render condition to rely on displayLog (which already
falls back to log) instead of strict isFullDataReady. Concretely, in the Sheet
render block replace the check that shows the loader (currently using
isFullDataReady) with a check that shows the loader only when there is no
displayLog (or when loading and displayLog is undefined) so that when
useGetLogByIdQuery() errors the component renders <LogDetailView
displayLog={displayLog}> using the row data (references: isFullDataReady,
fullLog, log, displayLog, useGetLogByIdQuery, LogDetailView).

---

Duplicate comments:
In `@ui/app/workspace/logs/views/columns.tsx`:
- Around line 20-26: getMessageFromContent currently only keeps the last
matching text segment (it overwrites lastTextContentBlock), so multi-block
prompts/responses are truncated; change the logic to accumulate matching
block.text values in order (e.g., push them into an array or append with a
space/separator) instead of assigning, ensuring you still check block.type ===
"text" || "input_text" || "output_text" and block.text; return the concatenated
string (trimmed) rather than the final single segment so getMessageFromContent,
the lastTextContentBlock variable, and any consumers get the full combined
message.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: a8590533-e35c-4563-8d73-a2c34c4ee4b4

📥 Commits

Reviewing files that changed from the base of the PR and between c28e16f and bd6ac46.

⛔ Files ignored due to path filters (1)
  • ui/package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (16)
  • ui/app/workspace/dashboard/page.tsx
  • ui/app/workspace/logs/page.tsx
  • ui/app/workspace/logs/sheets/logDetailView.tsx
  • ui/app/workspace/logs/sheets/logDetailsSheet.tsx
  • ui/app/workspace/logs/sheets/sessionDetailsSheet.tsx
  • ui/app/workspace/logs/views/columns.test.ts
  • ui/app/workspace/logs/views/columns.tsx
  • ui/app/workspace/logs/views/filters.tsx
  • ui/app/workspace/logs/views/logsTable.tsx
  • ui/app/workspace/providers/fragments/openaiConfigFormFragment.tsx
  • ui/app/workspace/providers/views/utils.ts
  • ui/components/filters/filterPopover.tsx
  • ui/lib/constants/logs.test.ts
  • ui/lib/constants/logs.ts
  • ui/lib/store/apis/logsApi.ts
  • ui/lib/types/logs.ts
✅ Files skipped from review due to trivial changes (3)
  • ui/app/workspace/providers/fragments/openaiConfigFormFragment.tsx
  • ui/lib/constants/logs.ts
  • ui/app/workspace/logs/sheets/logDetailView.tsx
🚧 Files skipped from review as they are similar to previous changes (6)
  • ui/lib/constants/logs.test.ts
  • ui/app/workspace/providers/views/utils.ts
  • ui/app/workspace/dashboard/page.tsx
  • ui/app/workspace/logs/views/columns.test.ts
  • ui/app/workspace/logs/views/logsTable.tsx
  • ui/components/filters/filterPopover.tsx

Comment thread ui/app/workspace/logs/sheets/sessionDetailsSheet.tsx
Comment thread ui/app/workspace/logs/sheets/sessionDetailsSheet.tsx
@danpiths danpiths force-pushed the feature/03-27-feat_add_realtime_websocket_webrtc_and_client_secret_handlers branch from 13ed4ad to d86f3f5 Compare March 31, 2026 06:16
@danpiths danpiths force-pushed the feature/03-27-feat_add_realtime_session_browsing_and_log_filtering_ui branch from bd6ac46 to 9f9abc4 Compare March 31, 2026 06:16
@danpiths danpiths force-pushed the feature/03-27-feat_add_realtime_session_browsing_and_log_filtering_ui branch from 72339b5 to 9c9d36e Compare April 3, 2026 08:03
coderabbitai[bot]
coderabbitai Bot previously approved these changes Apr 3, 2026
Comment thread ui/app/workspace/logs/views/columns.tsx Outdated
@danpiths danpiths force-pushed the feature/03-27-feat_add_realtime_session_browsing_and_log_filtering_ui branch from 9c9d36e to 8c3e708 Compare April 3, 2026 11:07
@danpiths danpiths force-pushed the feature/03-27-feat_add_realtime_websocket_webrtc_and_client_secret_handlers branch 2 times, most recently from 7ed9dd7 to 29fc633 Compare April 6, 2026 06:17
@danpiths danpiths force-pushed the feature/03-27-feat_add_realtime_session_browsing_and_log_filtering_ui branch 2 times, most recently from 37d588c to d30e179 Compare April 7, 2026 07:45
@danpiths danpiths force-pushed the feature/03-27-feat_add_realtime_websocket_webrtc_and_client_secret_handlers branch from 29fc633 to c1558b5 Compare April 7, 2026 07:45
@danpiths danpiths force-pushed the feature/03-27-feat_add_realtime_websocket_webrtc_and_client_secret_handlers branch from c1558b5 to b25fc77 Compare April 7, 2026 09:09
@danpiths danpiths force-pushed the feature/03-27-feat_add_realtime_session_browsing_and_log_filtering_ui branch 2 times, most recently from 8448b2e to 67cde0e Compare April 7, 2026 10:59
@danpiths danpiths force-pushed the feature/03-27-feat_add_realtime_websocket_webrtc_and_client_secret_handlers branch from b25fc77 to 5b980ac Compare April 7, 2026 10:59
@danpiths danpiths force-pushed the feature/03-27-feat_add_realtime_websocket_webrtc_and_client_secret_handlers branch from 5b980ac to 5e43323 Compare April 7, 2026 12:33
@danpiths danpiths force-pushed the feature/03-27-feat_add_realtime_session_browsing_and_log_filtering_ui branch from 67cde0e to 3cb15fa Compare April 7, 2026 12:33
Comment thread ui/app/workspace/logs/sheets/sessionDetailsSheet.tsx
@danpiths danpiths force-pushed the feature/03-27-feat_add_realtime_session_browsing_and_log_filtering_ui branch from 3cb15fa to 7799ba5 Compare April 7, 2026 14:55
Copy link
Copy Markdown
Contributor

akshaydeo commented Apr 7, 2026

Merge activity

  • Apr 7, 2:56 PM UTC: A user started a stack merge that includes this pull request via Graphite.
  • Apr 7, 3:02 PM UTC: @akshaydeo merged this pull request with Graphite.

@akshaydeo akshaydeo changed the base branch from feature/03-27-feat_add_realtime_websocket_webrtc_and_client_secret_handlers to graphite-base/2342 April 7, 2026 15:01
@akshaydeo akshaydeo changed the base branch from graphite-base/2342 to v1.5.0 April 7, 2026 15:01
@akshaydeo akshaydeo dismissed coderabbitai[bot]’s stale review April 7, 2026 15:01

The base branch was changed.

sessionId={selectedSessionId}
highlightedLogId={sessionHighlightedLogId}
open={selectedSessionId !== null}
onOpenChange={handleSessionSheetOpenChange}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P1 handleSessionSheetOpenChange is undefined — runtime crash on sheet close

handleSessionSheetOpenChange is passed as onOpenChange but is never declared anywhere in this file (no useCallback, no plain function, no import). TypeScript will fail to compile, and at runtime any code path that triggers onOpenChange(false) — pressing Escape, clicking outside the sheet, or the early-exit in loadSessionPage when a session returns zero logs — will throw a ReferenceError, crashing the logs page. The analogous handler for LogDetailSheet at line 924 uses an inline arrow function directly; this prop is the only one left dangling.

Add a definition before the return statement:

const handleSessionSheetOpenChange = useCallback(
    (open: boolean) => {
        if (!open) {
            setSelectedSessionId(null);
            setSessionHighlightedLogId(null);
        }
    },
    [],
);

@akshaydeo akshaydeo merged commit a08e761 into v1.5.0 Apr 7, 2026
5 of 12 checks passed
@akshaydeo akshaydeo deleted the feature/03-27-feat_add_realtime_session_browsing_and_log_filtering_ui branch April 7, 2026 15:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants