Skip to content

feat(events): live domain event stream log panel#2653

Open
Sathvik-1007 wants to merge 18 commits into
tinyhumansai:mainfrom
Sathvik-1007:feat/1849-live-event-stream-log
Open

feat(events): live domain event stream log panel#2653
Sathvik-1007 wants to merge 18 commits into
tinyhumansai:mainfrom
Sathvik-1007:feat/1849-live-event-stream-log

Conversation

@Sathvik-1007
Copy link
Copy Markdown
Contributor

@Sathvik-1007 Sathvik-1007 commented May 25, 2026

Summary

Implements #1849 — live typed event stream log in the dashboard.

Add a live typed event stream log to the OpenHuman dashboard that displays every agent event in real time as a scrolling, colour-coded feed. Each entry shows a timestamp, agent name, event type, and message - giving operators an instant, continuous view of what every agent in the swarm is doing without tailing raw log files.

Changes

Backend (Rust):

  • GET /events/domain — authenticated SSE endpoint streaming all DomainEvent bus events
  • DomainEvent::variant_name() — stable variant name extraction (no Debug format coupling)
  • DomainEvent::agent_hint() — best-effort agent/session identifier per event
  • DashboardConfig + EventStreamConfig — config schema for dashboard.event_stream.{enabled, max_entries, new_entries}
  • SSE sends config as first event: config message so frontend applies server settings
  • Respects enabled: false (returns 404)

Frontend (React):

  • EventLogPanel.tsx — Settings > Developer Options panel
  • Colour-coded domain badges (blue/green/purple/amber/slate per domain)
  • Agent name column from SSE agent field
  • Auto-reconnect with 3s backoff on disconnect
  • Config-driven max_entries and new_entries order from server
  • Auto-scroll with pause detection + "Jump to latest" button
  • Domain filter dropdown + free-text agent/event search
  • ndjson export

i18n: 22 keys across en.ts, en-5.ts, and all 12 locale chunk files.

Acceptance criteria

  • Live feed - agent events appear in the dashboard stream in real time via SSE, with no manual refresh required
  • Typed entries - each entry shows timestamp, agent name, message, and a colour-coded type badge (TOOL / OK / WARN / ERR / INFO)
  • Colour coding - badge and entry colours match the defined scheme (blue / green / amber / red)
  • Max entries enforced - feed drops oldest entries when max_entries is reached
  • Auto-scroll - feed auto-scrolls to latest; pauses if operator scrolls up; shows "Jump to latest" button when paused
  • Type filter - operators can toggle individual event types on/off; filter applies client-side instantly
  • Agent filter - free-text search filters entries by agent name client-side
  • Download log - exports current feed as newline-delimited JSON
  • Config-driven - max_entries and new_entries order are read from config.yaml
  • Diff coverage ≥ 80% - the implementing PR meets the changed-lines coverage gate (Vitest + cargo-llvm-cov, enforced by .github/workflows/coverage.yml)

Configuration

dashboard:
  event_stream:
    enabled: true
    max_entries: 200
    new_entries: top     # or: bottom

Closes #1849

Summary by CodeRabbit

  • New Features

    • Added an Event Log entry to the developer menu and a Settings page for viewing live domain events.
    • Live streaming of domain events with type/domain and agent filters, auto-scroll with “Jump to latest”, and export of filtered events as NDJSON.
    • Connection status indicators and automatic reconnect behavior.
  • Internationalization

    • Event Log translations added for 13 languages.
  • Tests

    • Comprehensive test suite for Event Log behaviors.

Review Change Stack

@Sathvik-1007 Sathvik-1007 requested a review from a team May 25, 2026 23:14
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 25, 2026

Note

Reviews paused

It 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 reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds an authenticated SSE backend endpoint at /events/domain and a new Event Log settings panel that streams, parses, filters, auto-scrolls, displays, and exports live domain events.

Changes

Event Log Dashboard Feature

Layer / File(s) Summary
Backend domain events SSE endpoint
src/core/jsonrpc.rs
New GET /events/domain route and domain_events_handler validate bearer tokens, subscribe to the global event bus, emit SSE events typed by domain with JSON payloads (domain, event, timestamp), and send 5s keep-alives; returns 401 or 503 on errors.
Routing, menu entry, and translations
app/src/pages/Settings.tsx, app/src/components/settings/panels/DeveloperOptionsPanel.tsx, app/src/lib/i18n/en.ts, app/src/lib/i18n/chunks/*
Imports and registers EventLogPanel route, adds an event-log menu item with i18n keys and inline SVG icon, and inserts settings.developerMenu.eventLog.* translation keys across English and locale chunks.
EventLogPanel: streaming, parsing, UI, and export
app/src/components/settings/panels/EventLogPanel.tsx, app/src/components/settings/panels/__tests__/EventLogPanel.test.tsx
Defines EventEntry and badge map; connects to ${baseUrl}/events/domain using getCoreRpcToken(), decodes newline-delimited data: SSE lines into JSON entries, respects server config (max_entries, new_entries), enforces entry cap, tracks isLive and reconnection, manages auto-scroll and "Jump to latest", applies client-side domain and substring filters, supports NDJSON export, and includes tests covering rendering and interactions.

Sequence Diagram(s)

sequenceDiagram
  participant SettingsUI
  participant EventLogPanel
  participant EventAPI
  participant CoreEventBus

  SettingsUI->>EventLogPanel: open panel / mount
  EventLogPanel->>EventAPI: GET /events/domain (Bearer token)
  EventAPI->>EventLogPanel: SSE stream (data: JSON lines, keep-alive)
  loop on each DomainEvent
    CoreEventBus->>EventAPI: DomainEvent
    EventAPI->>EventLogPanel: data: {domain,event,timestamp}
    EventLogPanel->>SettingsUI: render prepend/append entry, update filters/controls
  end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~40 minutes

Possibly related PRs

Suggested reviewers

  • sanil-23
  • graycyrus
  • senamakel

Poem

🐰 I watch the stream where timestamps glow,
Badges hop by in tidy row,
I filter, scroll, then jump to see —
NDJSON saved for you and me,
A little log, a rabbit's show.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely summarizes the main change: adding a live event stream log panel for the dashboard with proper feature convention.
Linked Issues check ✅ Passed All acceptance criteria from #1849 are met: live SSE feed [event log panel + backend handler], typed entries with timestamps/agents/messages/badges [EventLogPanel + SSE data parsing], colour coding [DOMAIN_BADGE_KEYS], max_entries enforcement [EventStreamConfig + component logic], auto-scroll with pause/jump [autoScroll state + UI], type filtering [domain filter dropdown], agent filtering [filterText search], NDJSON export [download button], config-driven behavior [EventStreamConfig fields + dashboard.rs], and test coverage provided.
Out of Scope Changes check ✅ Passed All changes directly support the event log feature: React components and routes for the UI, Rust SSE endpoint, i18n translations across multiple locales, config schema updates, and comprehensive tests. No unrelated code modifications.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

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


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@coderabbitai coderabbitai Bot added feature Net-new user-facing capability or product behavior. working A PR that is being worked on by the team. labels May 25, 2026
@Sathvik-1007 Sathvik-1007 reopened this May 25, 2026
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: 4

🧹 Nitpick comments (1)
app/src/components/settings/panels/EventLogPanel.tsx (1)

47-50: ⚡ Quick win

Remove the unused EventSource path to simplify ownership/cleanup.

The panel streams via fetch, so creating/closing/storing EventSource is dead code and makes lifecycle behavior harder to follow.

Proposed cleanup
-  const eventSourceRef = useRef<EventSource | null>(null);
@@
-    const es = new EventSource(url);
-
-    // EventSource doesn't support custom headers, so we use fetch-based SSE
-    es.close();
+    // EventSource doesn't support custom headers, so we use fetch-based SSE
@@
-    eventSourceRef.current = es;
     return () => {
       controller.abort();
     };
@@
     return () => {
       disconnect?.();
-      eventSourceRef.current?.close();
     };

Also applies to: 101-101, 110-110

🤖 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 `@app/src/components/settings/panels/EventLogPanel.tsx` around lines 47 - 50,
Remove the dead EventSource path: delete the instantiation and immediate close
of EventSource (the variable `es` created via `new EventSource(url)`) and any
other unused `EventSource` usage in EventLogPanel (including the occurrences
around lines referenced at 101 and 110) so the component only uses the
fetch-based SSE implementation; ensure no leftover references to `es` remain and
that ownership/cleanup logic is consolidated into the fetch/SSE cleanup handlers
in the EventLogPanel component.
🤖 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 `@app/src/components/settings/panels/EventLogPanel.tsx`:
- Around line 13-25: The component renders hard-coded UI text (badges and
status/button/count labels) — update it to use the i18n hook and keys: replace
visible literals like "Live", "Disconnected", "events", "Jump to latest" and
every badge label in EVENT_TYPE_COLORS with translation keys consumed via useT()
(e.g., change EVENT_TYPE_COLORS.{...}.label to a key string like
"eventLog.badge.tool" and when rendering call t('eventLog.badge.tool')). Add
corresponding entries to the English i18n file (app/src/lib/i18n/en.ts) for each
new key, update the JSX props (label/aria-label/button text/count suffix) to
call t(...) instead of hard-coded text, and ensure any tests or snapshots that
assert on these strings are updated accordingly.
- Line 3: The import for useT in EventLogPanel is using the wrong relative path
and causes a build error; update the import statement that currently references
'../../lib/i18n/I18nContext' to the correct relative path
'../../../lib/i18n/I18nContext' so the useT symbol is resolved (modify the
import line near the top of EventLogPanel.tsx to import useT from
'../../../lib/i18n/I18nContext').
- Around line 41-112: connect() creates an AbortController and starts the fetch
but the useEffect that calls connect() ignores its cleanup; update connect (the
function in EventLogPanel.tsx) to return a cleanup function that aborts the
controller and closes the EventSource/reader, then call that cleanup from the
useEffect's return so the streaming read loop is aborted on unmount (i.e., have
useEffect capture the cleanup = connect() and return () => { cleanup(); } or
store the controller in a ref and abort it in useEffect cleanup); ensure you
still set/clear eventSourceRef.current and call controller.abort() to prevent
state updates after unmount.

In `@app/src/lib/i18n/en.ts`:
- Around line 2960-2967: The new i18n keys under settings.developerMenu.eventLog
(for example 'settings.developerMenu.eventLog.title', '.desc', '.allTypes',
'.filterAgent', '.download', '.waiting', '.notConnected') were added only to
app/src/lib/i18n/en.ts; add these same keys (with English values) into each i18n
chunk file app/src/lib/i18n/chunks/en-1.ts ... en-5.ts and then add the
corresponding keys to each non-English locale chunk file (keeping existing
translations or adding placeholder translations) so all locale chunks include
the settings.developerMenu.eventLog.* entries to satisfy the i18n coverage gate.

---

Nitpick comments:
In `@app/src/components/settings/panels/EventLogPanel.tsx`:
- Around line 47-50: Remove the dead EventSource path: delete the instantiation
and immediate close of EventSource (the variable `es` created via `new
EventSource(url)`) and any other unused `EventSource` usage in EventLogPanel
(including the occurrences around lines referenced at 101 and 110) so the
component only uses the fetch-based SSE implementation; ensure no leftover
references to `es` remain and that ownership/cleanup logic is consolidated into
the fetch/SSE cleanup handlers in the EventLogPanel component.
🪄 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: ed93a8f5-d588-4eb9-afe5-a98150822c38

📥 Commits

Reviewing files that changed from the base of the PR and between e05cab9 and 8b04c54.

📒 Files selected for processing (5)
  • app/src/components/settings/panels/DeveloperOptionsPanel.tsx
  • app/src/components/settings/panels/EventLogPanel.tsx
  • app/src/lib/i18n/en.ts
  • app/src/pages/Settings.tsx
  • src/core/jsonrpc.rs

Comment thread app/src/components/settings/panels/EventLogPanel.tsx Outdated
Comment thread app/src/components/settings/panels/EventLogPanel.tsx Outdated
Comment thread app/src/components/settings/panels/EventLogPanel.tsx Outdated
Comment thread app/src/lib/i18n/en.ts
Comment on lines +2960 to +2967
'settings.developerMenu.eventLog.title': 'Event Log',
'settings.developerMenu.eventLog.desc':
'Live colour-coded stream of all agent, tool, and system events',
'settings.developerMenu.eventLog.allTypes': 'All types',
'settings.developerMenu.eventLog.filterAgent': 'Filter by agent...',
'settings.developerMenu.eventLog.download': 'Download',
'settings.developerMenu.eventLog.waiting': 'Waiting for events...',
'settings.developerMenu.eventLog.notConnected': 'Not connected to core',
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | 🏗️ Heavy lift

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Verify newly added event log keys exist across required locale files/chunks.
keys=(
  "settings.developerMenu.eventLog.title"
  "settings.developerMenu.eventLog.desc"
  "settings.developerMenu.eventLog.allTypes"
  "settings.developerMenu.eventLog.filterAgent"
  "settings.developerMenu.eventLog.download"
  "settings.developerMenu.eventLog.waiting"
  "settings.developerMenu.eventLog.notConnected"
)

echo "== Checking English chunk files =="
fd -a '^en-[1-5]\.ts$' app/src/lib/i18n | sort

echo "== Checking all locale files/chunks for key presence =="
for k in "${keys[@]}"; do
  echo "--- $k ---"
  rg -n --fixed-strings "'$k'" app/src/lib/i18n || true
done

Repository: tinyhumansai/openhuman

Length of output: 1381


🏁 Script executed:

#!/bin/bash
set -euo pipefail

keys=(
  "settings.developerMenu.eventLog.title"
  "settings.developerMenu.eventLog.desc"
  "settings.developerMenu.eventLog.allTypes"
  "settings.developerMenu.eventLog.filterAgent"
  "settings.developerMenu.eventLog.download"
  "settings.developerMenu.eventLog.waiting"
  "settings.developerMenu.eventLog.notConnected"
)

echo "== Search for eventLog in chunks =="
rg -n "settings\.developerMenu\.eventLog" app/src/lib/i18n/chunks || true

echo "== Search for each key (no quote dependency) in chunks =="
for k in "${keys[@]}"; do
  echo "--- $k ---"
  rg -n --fixed-strings "$k" app/src/lib/i18n/chunks || true
done

Repository: tinyhumansai/openhuman

Length of output: 502


Propagate settings.developerMenu.eventLog.* keys to all i18n chunk files

The new settings.developerMenu.eventLog keys exist only in app/src/lib/i18n/en.ts (lines 2960-2967) and are missing from app/src/lib/i18n/chunks/en-{1..5}.ts and the corresponding non-English locale chunk files. This will break the i18n coverage gate.

🤖 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 `@app/src/lib/i18n/en.ts` around lines 2960 - 2967, The new i18n keys under
settings.developerMenu.eventLog (for example
'settings.developerMenu.eventLog.title', '.desc', '.allTypes', '.filterAgent',
'.download', '.waiting', '.notConnected') were added only to
app/src/lib/i18n/en.ts; add these same keys (with English values) into each i18n
chunk file app/src/lib/i18n/chunks/en-1.ts ... en-5.ts and then add the
corresponding keys to each non-English locale chunk file (keeping existing
translations or adding placeholder translations) so all locale chunks include
the settings.developerMenu.eventLog.* entries to satisfy the i18n coverage gate.

@Sathvik-1007 Sathvik-1007 force-pushed the feat/1849-live-event-stream-log branch from 8b04c54 to 5505f38 Compare May 25, 2026 23:23
@coderabbitai coderabbitai Bot added the rust-core Core Rust runtime in src/: CLI, core_server, shared infrastructure. label May 25, 2026
@Sathvik-1007 Sathvik-1007 force-pushed the feat/1849-live-event-stream-log branch from 5505f38 to 5b81259 Compare May 25, 2026 23:26
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: 4

🤖 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 `@app/src/components/settings/panels/EventLogPanel.tsx`:
- Around line 30-31: The hard-coded MAX_ENTRIES and fixed newest-on-top behavior
in EventLogPanel should be driven by the app config keys
dashboard.event_stream.max_entries and dashboard.event_stream.new_entries:
update EventLogPanel to read those config values (or accept them as props)
instead of using the MAX_ENTRIES constant, use the configured max_entries to cap
the list length, and conditionally render/insert new events at the top when
new_entries is true (and at the bottom when false); replace references to
MAX_ENTRIES and the existing insertion/ordering logic (including the code around
the current newest-on-top handling at the area noted around lines 92-95) to
respect these config-driven settings.
- Around line 1-249: Prettier is failing for EventLogPanel.tsx; run the
project's Prettier formatter (or npm/yarn script such as "npm run format" /
"yarn format") and apply formatting to this file so it matches CI rules; ensure
you preserve exported symbol EventLogPanel and do not change logic in functions
like connect, exportLog, or constants DOMAIN_BADGE_KEYS and MAX_ENTRIES—only
reformat the file to satisfy prettier --check.
- Around line 71-104: The read loop for the SSE stream exits on EOF but never
clears the live flag, so call setIsLive(false) when the stream ends; inside the
async reader loop (the block using reader.read(), decoder, buffer and
idRef.current) setIsLive(false) right before/after breaking when done is true
(or move the setIsLive(false) into a finally/after-loop cleanup) so the
component's isLive state is set to disconnected when the stream completes or is
closed.

In `@app/src/pages/Settings.tsx`:
- Line 43: Run Prettier to format the Settings.tsx file to satisfy CI: run the
project's Prettier command (e.g., prettier --write) on the file and fix
formatting issues around the import for EventLogPanel and other locations noted
(approx. the Settings component top imports and the block around line 449).
Ensure the file compiles after formatting and commit the formatted file so
prettier --check passes in CI.
🪄 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: 97e5266e-bf94-474e-ab65-5735929bbfeb

📥 Commits

Reviewing files that changed from the base of the PR and between 5505f38 and 5b81259.

📒 Files selected for processing (18)
  • app/src/components/settings/panels/DeveloperOptionsPanel.tsx
  • app/src/components/settings/panels/EventLogPanel.tsx
  • app/src/lib/i18n/chunks/ar-5.ts
  • app/src/lib/i18n/chunks/bn-5.ts
  • app/src/lib/i18n/chunks/de-5.ts
  • app/src/lib/i18n/chunks/en-5.ts
  • app/src/lib/i18n/chunks/es-5.ts
  • app/src/lib/i18n/chunks/fr-5.ts
  • app/src/lib/i18n/chunks/hi-5.ts
  • app/src/lib/i18n/chunks/id-5.ts
  • app/src/lib/i18n/chunks/it-5.ts
  • app/src/lib/i18n/chunks/ko-5.ts
  • app/src/lib/i18n/chunks/pt-5.ts
  • app/src/lib/i18n/chunks/ru-5.ts
  • app/src/lib/i18n/chunks/zh-CN-5.ts
  • app/src/lib/i18n/en.ts
  • app/src/pages/Settings.tsx
  • src/core/jsonrpc.rs
✅ Files skipped from review due to trivial changes (5)
  • app/src/lib/i18n/chunks/de-5.ts
  • app/src/lib/i18n/chunks/ar-5.ts
  • app/src/lib/i18n/chunks/id-5.ts
  • app/src/lib/i18n/chunks/pt-5.ts
  • app/src/lib/i18n/chunks/zh-CN-5.ts

Comment thread app/src/components/settings/panels/EventLogPanel.tsx Outdated
Comment thread app/src/components/settings/panels/EventLogPanel.tsx
Comment thread app/src/components/settings/panels/EventLogPanel.tsx
Comment thread app/src/pages/Settings.tsx Outdated
@Sathvik-1007 Sathvik-1007 force-pushed the feat/1849-live-event-stream-log branch from 5b81259 to d5aedab Compare May 25, 2026 23:34
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

🧹 Nitpick comments (1)
src/core/jsonrpc.rs (1)

1077-1083: ⚡ Quick win

Harden event-name scrubbing for tuple-style debug output.

The current split logic misses Variant(...) shapes, so payload text can leak into event_name if tuple variants are introduced.

🔧 Suggested tweak
-            let event_name = variant
-                .split_once('{')
-                .or_else(|| variant.split_once(' '))
+            let event_name = variant
+                .split_once('{')
+                .or_else(|| variant.split_once('('))
+                .or_else(|| variant.split_once(' '))
                 .map(|(name, _)| name.trim())
                 .unwrap_or(&variant);
🤖 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/core/jsonrpc.rs` around lines 1077 - 1083, The event-name extraction for
the Debug-formatted `variant` (assigned to `variant` and used to create
`event_name`) currently only splits on '{' and ' ' and therefore can leak
payload text for tuple-style variants like `Variant(...)`; update the scrub
logic to also split on '(' (i.e., find the first occurrence of any of '{', ' ',
'('), then take the left part and trim it, so tuple payloads are stripped the
same as struct-style payloads; change the code that computes `event_name` (the
block that calls `split_once` on `variant`) to try these separators in a robust
order and fall back to the whole `variant` if none match.
🤖 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 `@app/src/components/settings/panels/EventLogPanel.tsx`:
- Around line 125-128: The current filteredEntries logic uses filterText against
e.event but the UI intends an agent-name filter; update the predicate to check
the entry's agent name field instead of e.event — e.g. replace the condition `if
(filterText && !e.event.toLowerCase().includes(filterText.toLowerCase()))` with
a check against the agent property (for example `const agentName = e.agent ||
e.agentName || e.actor` and `if (filterText &&
!agentName?.toLowerCase().includes(filterText.toLowerCase())) return false;`) so
the filterText matches agent names case-insensitively while keeping the existing
filterType check and final return.
- Around line 105-111: The cleanup in EventLogPanel's useEffect currently calls
setIsLive(false) which triggers the react-hooks/set-state-in-effect warning;
remove setIsLive(false) from the cleanup and instead ensure isLive is cleared
inside the connection lifecycle: update the connect() implementation to
setIsLive(false) on abort/error/finally and also make abort() set isLive false
(e.g., when controllerRef.current?.abort() is invoked handle the abort signal or
promise rejection to call setIsLive(false)), or if you intentionally must change
state in cleanup add a single-line eslint-disable comment with a clear
justification referencing why setIsLive must run on unmount and target
react-hooks/set-state-in-effect.

---

Nitpick comments:
In `@src/core/jsonrpc.rs`:
- Around line 1077-1083: The event-name extraction for the Debug-formatted
`variant` (assigned to `variant` and used to create `event_name`) currently only
splits on '{' and ' ' and therefore can leak payload text for tuple-style
variants like `Variant(...)`; update the scrub logic to also split on '(' (i.e.,
find the first occurrence of any of '{', ' ', '('), then take the left part and
trim it, so tuple payloads are stripped the same as struct-style payloads;
change the code that computes `event_name` (the block that calls `split_once` on
`variant`) to try these separators in a robust order and fall back to the whole
`variant` if none match.
🪄 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: fabe830f-8085-4beb-972e-64c5ba074386

📥 Commits

Reviewing files that changed from the base of the PR and between 5b81259 and d5aedab.

📒 Files selected for processing (18)
  • app/src/components/settings/panels/DeveloperOptionsPanel.tsx
  • app/src/components/settings/panels/EventLogPanel.tsx
  • app/src/lib/i18n/chunks/ar-5.ts
  • app/src/lib/i18n/chunks/bn-5.ts
  • app/src/lib/i18n/chunks/de-5.ts
  • app/src/lib/i18n/chunks/en-5.ts
  • app/src/lib/i18n/chunks/es-5.ts
  • app/src/lib/i18n/chunks/fr-5.ts
  • app/src/lib/i18n/chunks/hi-5.ts
  • app/src/lib/i18n/chunks/id-5.ts
  • app/src/lib/i18n/chunks/it-5.ts
  • app/src/lib/i18n/chunks/ko-5.ts
  • app/src/lib/i18n/chunks/pt-5.ts
  • app/src/lib/i18n/chunks/ru-5.ts
  • app/src/lib/i18n/chunks/zh-CN-5.ts
  • app/src/lib/i18n/en.ts
  • app/src/pages/Settings.tsx
  • src/core/jsonrpc.rs
✅ Files skipped from review due to trivial changes (8)
  • app/src/lib/i18n/chunks/bn-5.ts
  • app/src/lib/i18n/chunks/it-5.ts
  • app/src/lib/i18n/chunks/es-5.ts
  • app/src/lib/i18n/chunks/pt-5.ts
  • app/src/lib/i18n/chunks/ru-5.ts
  • app/src/lib/i18n/chunks/de-5.ts
  • app/src/lib/i18n/chunks/en-5.ts
  • app/src/lib/i18n/en.ts

Comment thread app/src/components/settings/panels/EventLogPanel.tsx
Comment thread app/src/components/settings/panels/EventLogPanel.tsx
@Sathvik-1007 Sathvik-1007 force-pushed the feat/1849-live-event-stream-log branch from 81f5e29 to 122be9e Compare May 26, 2026 06:29
Copy link
Copy Markdown
Contributor

@graycyrus graycyrus left a comment

Choose a reason for hiding this comment

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

Review — PR #2653

Solid foundation. The SSE plumbing in Rust is clean — auth check, proper error responses, keep-alive. The React panel has good structure: ring buffer, scroll handling, proper cleanup, i18n keys across all locales, and decent test coverage. Nice work.

But there are meaningful gaps against the acceptance criteria in #1849 that need to be closed before this ships.

Summary

File Area Changes
src/core/jsonrpc.rs Rust core New /events/domain SSE endpoint with bearer auth
EventLogPanel.tsx Frontend New panel: SSE consumer, filters, export, auto-scroll
EventLogPanel.test.tsx Tests 10 test cases covering rendering, filters, export, scroll
DeveloperOptionsPanel.tsx Frontend Menu entry for event log
Settings.tsx Frontend Route for event-log panel
*-5.ts (13 files) i18n Translation keys for all locales

Issues found (not covered by CodeRabbit)

3 major, 1 minor — see inline comments.

CodeRabbit already flagged: config-driven max_entries/new_entries order, agent filter logic mismatch. Not repeated here.

<span className="text-[10px] text-stone-400 dark:text-neutral-500 font-mono shrink-0 pt-0.5">
{entry.timestamp}
</span>
<span className="rounded-full bg-stone-200 dark:bg-neutral-800 px-2 py-0.5 text-[10px] text-stone-600 dark:text-neutral-300 shrink-0">
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.

[major] Every badge renders the same bg-stone-200 gray regardless of domain. Issue #1849 explicitly requires colour-coded badges (blue for TOOL, green for OK, amber for WARN, red for ERR).

You already have DOMAIN_BADGE_KEYS mapping domains to i18n keys. Add a parallel colour map and apply it here:

const DOMAIN_BADGE_COLORS: Record<string, { bg: string; text: string }> = {
  tool:     { bg: 'bg-blue-500/20',   text: 'text-blue-400' },
  agent:    { bg: 'bg-green-500/20',  text: 'text-green-400' },
  system:   { bg: 'bg-slate-500/20',  text: 'text-slate-400' },
  memory:   { bg: 'bg-purple-500/20', text: 'text-purple-400' },
  approval: { bg: 'bg-amber-500/20',  text: 'text-amber-400' },
  // ...
};

Then use DOMAIN_BADGE_COLORS[entry.domain]?.bg etc. instead of the hardcoded stone classes.

Comment thread src/core/jsonrpc.rs
.or_else(|| variant.split_once(' '))
.map(|(name, _)| name.trim())
.unwrap_or(&variant);
let data = json!({
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.

[major] Issue #1849 requires "each entry shows timestamp, agent name, message, and a colour-coded type badge." The emitted JSON only has domain, event, and timestamp — no agent identifier.

The DomainEvent payload likely carries an agent name. Extract it before stripping the rest:

let agent = event.agent_name().unwrap_or_default();
let data = json!({
    "domain": domain,
    "event": event_name,
    "agent": agent,
    "timestamp": chrono::Utc::now().format("%H:%M:%S").to_string(),
});

This also unblocks the frontend agent filter that CodeRabbit already flagged — right now there's no agent field to filter on.

}
}, []);

useEffect(() => {
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.

[major] No reconnect logic. When the SSE stream drops (server restart, network blip), the panel shows "Disconnected" and stays dead. For a live monitoring tool, auto-reconnect is table-stakes.

Add a retry with backoff in the catch/finally of connect():

} catch {
  setIsLive(false);
} finally {
  controllerRef.current = null;
  // Auto-reconnect after 3s unless component unmounted
  reconnectTimer.current = setTimeout(() => void connect(), 3000);
}

Clear reconnectTimer in the useEffect cleanup alongside the abort.

Comment thread src/core/jsonrpc.rs Outdated
Err(_) => return None,
};
let domain = event.domain().to_string();
let variant = format!("{:?}", event);
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.

[minor] format!("{:?}", event) + split_once to extract the variant name is fragile — it's coupled to the Debug impl and could silently break if the format changes.

Consider adding a variant_name(&self) -> &'static str method on DomainEvent (or using a match). Gives you a stable, clean event name and removes any risk of accidentally leaking payload data through Debug formatting.

@Sathvik-1007 Sathvik-1007 force-pushed the feat/1849-live-event-stream-log branch from 122be9e to 30d152b Compare May 27, 2026 03:18
@Sathvik-1007 Sathvik-1007 requested a review from graycyrus May 27, 2026 16:23
@oxoxDev oxoxDev assigned oxoxDev and unassigned oxoxDev May 28, 2026
@sanil-23 sanil-23 self-assigned this May 28, 2026
sanil-23 added 2 commits May 28, 2026 15:53
The auto-scroll and pause-detection paths hard-coded `scrollTop = 0` and
`scrollTop < 10`, so when `dashboard.event_stream.new_entries` is set to
`bottom` (newest-at-bottom mode), the feed never followed new events and
"Jump to latest" jumped to the top instead. Anchor on `scrollHeight` for
the bottom branch in both effect and handler.
`agent_hint()` returned the tool name for `ToolExecutionStarted` but
fell through to `None` for `ToolExecutionCompleted`, so the SSE feed
showed an empty agent column on completion events. Both variants carry
`tool_name` — surface it consistently.
sanil-23
sanil-23 previously approved these changes May 28, 2026
Copy link
Copy Markdown
Contributor

@sanil-23 sanil-23 left a comment

Choose a reason for hiding this comment

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

Live domain event stream log panel reviewed. Auto-scroll-bottom + ToolExecutionCompleted in agent_hint refactors (69dc812, e7e5e8f) address the review feedback. EventLogPanel 10/10, event_bus 21/21, dashboard config 3/3, full pnpm typecheck/lint/prettier clean. 25/0 CI all-green. LGTM.

@sanil-23
Copy link
Copy Markdown
Contributor

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 28, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot added the agent Built-in agents, prompts, orchestration, and agent runtime in src/openhuman/agent/. label May 28, 2026
coderabbitai[bot]
coderabbitai Bot previously requested changes May 28, 2026
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

🧹 Nitpick comments (1)
app/src/components/settings/panels/__tests__/EventLogPanel.test.tsx (1)

160-177: ⚡ Quick win

Query by role or testid instead of Tailwind class.

Line 168 queries by the Tailwind class .max-h-\[60vh\], which tests implementation details and is fragile if styling changes. Line 169 manually sets scrollTop via Object.defineProperty, which is also implementation-focused.

As per coding guidelines, prefer testing behavior over implementation details. Consider adding a data-testid to the scrollable container in EventLogPanel.tsx or querying by semantic role, then use Testing Library's user event simulation.

♻️ Suggested approach

In EventLogPanel.tsx, add a testid:

-<div className="max-h-[60vh] overflow-y-auto" ref={containerRef} onScroll={handleScroll}>
+<div className="max-h-[60vh] overflow-y-auto" ref={containerRef} onScroll={handleScroll} data-testid="event-log-scroll-container">

In the test:

-    const scrollDiv = container.querySelector('.max-h-\\[60vh\\]')!;
+    const scrollDiv = screen.getByTestId('event-log-scroll-container');
     Object.defineProperty(scrollDiv, 'scrollTop', { value: 100, writable: true });
     fireEvent.scroll(scrollDiv);

Alternatively, consider testing the scroll behavior more holistically by verifying that the "Jump to latest" button appears when the user would naturally scroll away (if you can simulate that behavior without directly manipulating scrollTop).

🤖 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 `@app/src/components/settings/panels/__tests__/EventLogPanel.test.tsx` around
lines 160 - 177, Replace the fragile Tailwind class query and manual
Object.defineProperty scrollTop manipulation by adding a stable data-testid on
the EventLogPanel's scrollable container (e.g., data-testid="event-log-scroll")
in EventLogPanel.tsx, then update the test in EventLogPanel.test.tsx to select
the container via getByTestId('event-log-scroll') (or by role if appropriate)
and simulate scrolling with Testing Library events (e.g.,
fireEvent.scroll(scrollEl, { target: { scrollTop: 100 } }) or use userEvent),
then assert the "Jump to latest" button appears and click it; this removes
dependence on implementation CSS and direct property stubbing while keeping the
same assertions around EventLogPanel behavior.
🤖 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 `@app/src/components/settings/panels/__tests__/EventLogPanel.test.tsx`:
- Around line 82-98: In the EventLogPanel.test.tsx test for "filters events by
domain type", replace the manual Event construction/dispatch on the select
element with Testing Library's fireEvent.change (target.value = 'tool') against
the select returned from container.querySelector('select'); after firing the
change, assert the filtering behavior by checking that "ToolA" remains visible
(e.g., getByText/finder) and "AgentB" is not present (e.g., queryByText returns
null), using waitFor if needed to await UI updates; keep the existing
mockFetchSSE and renderWithProviders setup and update only the event dispatch
and assertions.

In `@app/src/components/settings/panels/EventLogPanel.tsx`:
- Line 204: The filename for export assigned to a.download uses new
Date().toISOString().slice(0, 19) which contains ':' characters invalid on
Windows; sanitize the timestamp by replacing colons (and any other problematic
characters) with safe characters (e.g., '-' or '_') before assigning to
a.download so the generated name like event-log-<sanitized-timestamp>.ndjson is
cross-platform safe; update the code around the a.download assignment (the line
that builds the filename) to perform the replacement.

---

Nitpick comments:
In `@app/src/components/settings/panels/__tests__/EventLogPanel.test.tsx`:
- Around line 160-177: Replace the fragile Tailwind class query and manual
Object.defineProperty scrollTop manipulation by adding a stable data-testid on
the EventLogPanel's scrollable container (e.g., data-testid="event-log-scroll")
in EventLogPanel.tsx, then update the test in EventLogPanel.test.tsx to select
the container via getByTestId('event-log-scroll') (or by role if appropriate)
and simulate scrolling with Testing Library events (e.g.,
fireEvent.scroll(scrollEl, { target: { scrollTop: 100 } }) or use userEvent),
then assert the "Jump to latest" button appears and click it; this removes
dependence on implementation CSS and direct property stubbing while keeping the
same assertions around EventLogPanel behavior.
🪄 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: fc7b4732-ef4c-4b76-a740-13c5c3848b27

📥 Commits

Reviewing files that changed from the base of the PR and between d5aedab and e7e5e8f.

📒 Files selected for processing (18)
  • app/src/components/settings/panels/DeveloperOptionsPanel.tsx
  • app/src/components/settings/panels/EventLogPanel.tsx
  • app/src/components/settings/panels/__tests__/EventLogPanel.test.tsx
  • app/src/lib/i18n/chunks/ar-5.ts
  • app/src/lib/i18n/chunks/bn-5.ts
  • app/src/lib/i18n/chunks/de-5.ts
  • app/src/lib/i18n/chunks/en-5.ts
  • app/src/lib/i18n/chunks/es-5.ts
  • app/src/lib/i18n/chunks/fr-5.ts
  • app/src/lib/i18n/chunks/hi-5.ts
  • app/src/lib/i18n/chunks/id-5.ts
  • app/src/lib/i18n/chunks/it-5.ts
  • app/src/lib/i18n/chunks/ko-5.ts
  • app/src/lib/i18n/chunks/pt-5.ts
  • app/src/lib/i18n/chunks/ru-5.ts
  • app/src/lib/i18n/chunks/zh-CN-5.ts
  • app/src/lib/i18n/en.ts
  • app/src/pages/Settings.tsx
💤 Files with no reviewable changes (1)
  • app/src/pages/Settings.tsx
✅ Files skipped from review due to trivial changes (8)
  • app/src/lib/i18n/chunks/bn-5.ts
  • app/src/lib/i18n/chunks/fr-5.ts
  • app/src/lib/i18n/chunks/zh-CN-5.ts
  • app/src/lib/i18n/chunks/it-5.ts
  • app/src/lib/i18n/chunks/id-5.ts
  • app/src/lib/i18n/chunks/ko-5.ts
  • app/src/lib/i18n/en.ts
  • app/src/lib/i18n/chunks/hi-5.ts
🚧 Files skipped from review as they are similar to previous changes (4)
  • app/src/lib/i18n/chunks/de-5.ts
  • app/src/lib/i18n/chunks/pt-5.ts
  • app/src/lib/i18n/chunks/es-5.ts
  • app/src/lib/i18n/chunks/ru-5.ts

Comment thread app/src/components/settings/panels/__tests__/EventLogPanel.test.tsx
Comment thread app/src/components/settings/panels/EventLogPanel.tsx Outdated
# Conflicts:
#	app/src/pages/Settings.tsx
#	src/openhuman/config/schema/dashboard.rs
@sanil-23
Copy link
Copy Markdown
Contributor

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 28, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

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: 0

🧹 Nitpick comments (1)
src/openhuman/config/schema/dashboard.rs (1)

35-37: ⚡ Quick win

Constrain new_entries to an enum instead of free-form String.

new_entries currently accepts arbitrary text, so invalid config values can silently flow to clients. Model it as a serde enum (Top | Bottom) to enforce the contract at parse time.

Proposed refactor
+#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, Default)]
+#[serde(rename_all = "lowercase")]
+pub enum NewEntriesOrder {
+    #[default]
+    Top,
+    Bottom,
+}
+
 #[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
 #[serde(default)]
 pub struct EventStreamConfig {
@@
-    /// Where new entries appear: "top" (newest first) or "bottom" (oldest first).
-    #[serde(default = "default_new_entries")]
-    pub new_entries: String,
+    /// Where new entries appear: "top" (newest first) or "bottom" (oldest first).
+    #[serde(default)]
+    pub new_entries: NewEntriesOrder,
 }
@@
-fn default_new_entries() -> String {
-    "top".to_string()
-}
@@
         Self {
             enabled: true,
             max_entries: 200,
-            new_entries: "top".to_string(),
+            new_entries: NewEntriesOrder::Top,
         }
     }
 }

Also applies to: 46-47, 50-56

🤖 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/openhuman/config/schema/dashboard.rs` around lines 35 - 37, Replace the
free-form String type for the new_entries field with a serde-backed enum to
enforce valid values: define an enum NewEntries { Top, Bottom } with
#[derive(Deserialize, Serialize, Debug, Clone, PartialEq, Eq)] and
#[serde(rename_all = "lowercase")] (or explicit renames), implement or provide a
default function default_new_entries() -> NewEntries that returns
NewEntries::Top, then change the struct field signature from pub new_entries:
String to pub new_entries: NewEntries and keep #[serde(default =
"default_new_entries")]; update any code that reads or compares new_entries to
use the enum variants instead of string literals, and apply the same
enum+default pattern to the other similar fields referenced (lines 46-47,
50-56).
🤖 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.

Nitpick comments:
In `@src/openhuman/config/schema/dashboard.rs`:
- Around line 35-37: Replace the free-form String type for the new_entries field
with a serde-backed enum to enforce valid values: define an enum NewEntries {
Top, Bottom } with #[derive(Deserialize, Serialize, Debug, Clone, PartialEq,
Eq)] and #[serde(rename_all = "lowercase")] (or explicit renames), implement or
provide a default function default_new_entries() -> NewEntries that returns
NewEntries::Top, then change the struct field signature from pub new_entries:
String to pub new_entries: NewEntries and keep #[serde(default =
"default_new_entries")]; update any code that reads or compares new_entries to
use the enum variants instead of string literals, and apply the same
enum+default pattern to the other similar fields referenced (lines 46-47,
50-56).

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 78a3f0cb-aa96-4c63-8325-e561267ff5d6

📥 Commits

Reviewing files that changed from the base of the PR and between e7e5e8f and f572041.

📒 Files selected for processing (19)
  • app/src/components/settings/panels/DeveloperOptionsPanel.tsx
  • app/src/lib/i18n/chunks/ar-5.ts
  • app/src/lib/i18n/chunks/bn-5.ts
  • app/src/lib/i18n/chunks/de-5.ts
  • app/src/lib/i18n/chunks/en-5.ts
  • app/src/lib/i18n/chunks/es-5.ts
  • app/src/lib/i18n/chunks/fr-5.ts
  • app/src/lib/i18n/chunks/hi-5.ts
  • app/src/lib/i18n/chunks/id-5.ts
  • app/src/lib/i18n/chunks/it-5.ts
  • app/src/lib/i18n/chunks/ko-5.ts
  • app/src/lib/i18n/chunks/pt-5.ts
  • app/src/lib/i18n/chunks/ru-5.ts
  • app/src/lib/i18n/chunks/zh-CN-5.ts
  • app/src/lib/i18n/en.ts
  • app/src/pages/Settings.tsx
  • src/openhuman/config/schema/dashboard.rs
  • src/openhuman/config/schema/mod.rs
  • src/openhuman/config/schema/types.rs
✅ Files skipped from review due to trivial changes (8)
  • app/src/lib/i18n/chunks/zh-CN-5.ts
  • app/src/lib/i18n/chunks/pt-5.ts
  • app/src/lib/i18n/chunks/ru-5.ts
  • app/src/lib/i18n/chunks/bn-5.ts
  • app/src/lib/i18n/chunks/ar-5.ts
  • src/openhuman/config/schema/types.rs
  • app/src/lib/i18n/en.ts
  • app/src/lib/i18n/chunks/hi-5.ts
🚧 Files skipped from review as they are similar to previous changes (8)
  • app/src/components/settings/panels/DeveloperOptionsPanel.tsx
  • app/src/lib/i18n/chunks/es-5.ts
  • app/src/lib/i18n/chunks/it-5.ts
  • app/src/lib/i18n/chunks/fr-5.ts
  • app/src/lib/i18n/chunks/ko-5.ts
  • app/src/lib/i18n/chunks/de-5.ts
  • app/src/lib/i18n/chunks/id-5.ts
  • app/src/pages/Settings.tsx

sanil-23
sanil-23 previously approved these changes May 28, 2026
Copy link
Copy Markdown
Contributor

@sanil-23 sanil-23 left a comment

Choose a reason for hiding this comment

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

Re-approving after conflict-resolution merge f5720411 — kept #2653's full EventStreamConfig (enabled/max_entries/new_entries) + added #2823's ModelHealthConfig to DashboardConfig; preserved both /event-log + /model-health routes in Settings.tsx; deduped accidental double mod dashboard + pub dashboard field/Default that the auto-merge produced. cargo check + cargo fmt clean. CR re-reviewed → COMMENTED. LGTM.

Copy link
Copy Markdown
Contributor

@graycyrus graycyrus left a comment

Choose a reason for hiding this comment

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

Continuation Review — All Prior Issues Resolved

Prior REQUEST_CHANGES feedback has been addressed:

Issue Status Fix
Colour-coded badges ✓ Fixed DOMAIN_BADGE_COLORS with per-domain bg/text classes, applied to rendered badges
Agent name in SSE data ✓ Fixed agent_hint() method now includes ToolExecutionCompleted, data sent in SSE JSON
Auto-reconnect on disconnect ✓ Fixed 3s reconnect loop in finally block, properly guards against re-connect after unmount
Fragile variant extraction ✓ Fixed Proper match-based variant_name() method replaces Debug + split_once parsing

Configuration-driven settings also now in place: max_entries and new_entries order (top/bottom) are read from dashboard.event_stream config and applied via refs, respecting server settings sent in first SSE event.

Remaining minor findings (CodeRabbit):

  • Filename sanitization: Export uses toISOString().slice(0, 19) which includes colons invalid on Windows — should replace with hyphens or underscores for cross-platform safety
  • Test completeness: Filter test dispatches change event but does not assert that AgentB is hidden after filtering — add waitFor + queryByText check

Code is solid. Tests cover happy path + disconnect states. Coverage gate passing. Ready for approval once these two are addressed.

graycyrus
graycyrus previously approved these changes May 28, 2026
Copy link
Copy Markdown
Contributor

@graycyrus graycyrus left a comment

Choose a reason for hiding this comment

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

All prior major issues resolved — color badges properly implemented with per-domain Tailwind classes, agent name extraction via agent_hint() in SSE stream, auto-reconnect with 3s backoff, and config-driven entry limits working correctly. CI green, sanil-23 approved.

Two minor items remain unfixed but are non-blocking:

  1. Filename export timestamp still has colons (invalid on Windows filenames) — suggest: .replace(/:/g, '-')
  2. Filter test doesn't assert that filtering actually worked (test dispatches change event but never checks AgentB is hidden)

Code is clean and ready to go. Ship it.

@graycyrus graycyrus dismissed their stale review May 28, 2026 18:34

Auto-corrected: policy violation — approval should be COMMENT, not APPROVED. Clean PRs require manual approval gate.

Copy link
Copy Markdown
Contributor

@graycyrus graycyrus left a comment

Choose a reason for hiding this comment

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

All prior major issues resolved — color badges properly implemented with per-domain Tailwind classes, agent name extraction via agent_hint() in SSE stream, auto-reconnect with 3s backoff, and config-driven entry limits working correctly. CI green, sanil-23 approved.

Two minor items remain unfixed but are non-blocking:

  1. Filename export timestamp still has colons (invalid on Windows filenames) — suggest: .replace(/:/g, '-')
  2. Filter test doesn't assert that filtering actually worked (test dispatches change event but never checks AgentB is hidden)

Code is clean and ready to go.

@sanil-23
Copy link
Copy Markdown
Contributor

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 28, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Addresses graycyrus's two non-blocking review items (PR tinyhumansai#2653):

1. **Filename sanitization** — `toISOString().slice(0, 19)` produced colons,
   invalid in Windows filenames. Now `.replace(/:/g, '-')` so exports are
   cross-platform safe.

2. **Filter test completeness** — the domain-filter test dispatched a change
   event but never asserted the filter took effect. Now uses
   `fireEvent.change` + `waitFor` checking AgentB is hidden while ToolA
   remains visible.

Co-Authored-By: Claude <noreply@anthropic.com>
Copy link
Copy Markdown
Contributor

@sanil-23 sanil-23 left a comment

Choose a reason for hiding this comment

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

Re-approving after the two follow-up fixes (678957fc): filename sanitization (:/g, '-' on the export timestamp) + filter test now asserts AgentB is hidden + ToolA visible after dispatch. Addresses graycyrus's two non-blocking review items. CR re-reviewed → COMMENTED on prior head; will re-run on this push.

@sanil-23
Copy link
Copy Markdown
Contributor

@graycyrus addressed your two non-blocking items in 678957fc:

  1. Filename sanitizationevent-log-${ISO}.ndjson now does .replace(/:/g, '-') on the slice so Windows can save the export (app/src/components/settings/panels/EventLogPanel.tsx:204).
  2. Filter test completeness — the domain-filter test now uses fireEvent.change + waitFor to assert that AgentB is hidden and ToolA remains after selecting the tool filter (app/src/components/settings/panels/__tests__/EventLogPanel.test.tsx:93-103).

Re-requested your review. Sole remaining CI red is the inherited core::observability::classifies_embedding_api_invalid_token_401_as_session_expired test from #2786 (this PR doesn't touch src/core/observability.rs); reran twice, same persistent fail. Happy to leave it for an upstream observability follow-up.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agent Built-in agents, prompts, orchestration, and agent runtime in src/openhuman/agent/. feature Net-new user-facing capability or product behavior. rust-core Core Rust runtime in src/: CLI, core_server, shared infrastructure. working A PR that is being worked on by the team.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Feature Request : Live typed event stream log real-time colour-coded agent activity feed in the dashboard

4 participants