feat(dashboard): rename vis → dashboard and add agent-tracing dashboard - #137
Conversation
…ackaging) Introduce `pythinker dashboard` — a local web UI for inspecting agent sessions: wire events, context messages, state, sub-agents, a dual view, tool statistics, and usage over time. Served by a FastAPI backend (`pythinker_code.dashboard`) under `/api/dashboard`, with the React/Vite frontend bundled at build time (`make build-dashboard`, wired into the wheel, PyInstaller binaries, and the Linux/Windows installers). Reachable from the interactive shell via `/reports` (alias `/dashboard`). Also fixes correctness issues found in review: attach the session auth header to the import and delete calls; log previously-swallowed exceptions in the session/statistics APIs and the build script; group sub-agent events by a stable key; and gate the number-key tab shortcuts to the in-session view.
Add the dashboard reference page, wire up navigation and cross-links, refresh the architecture and configuration docs, and add a CHANGELOG entry introducing `pythinker dashboard`.
|
Warning Review limit reached
More reviews will be available in 4 minutes and 57 seconds. Learn how PR review limits work. Your organization has used up its prepaid credits, and credit purchases are no longer available. Enable the review add-on in the billing tab to keep reviews running — you're only billed for reviews past your plan's rate limits ($0.25/file). ⌛ How to resolve this issue?After more reviews become available, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available. Please see our Fair Usage Limits Policy for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Pro Plus Run ID: ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (9)
📝 WalkthroughWalkthroughRenames the Changesvis → dashboard rename
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Suggested labels
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Codecov Report❌ Patch coverage is 📢 Thoughts on this report? Let us know! |
There was a problem hiding this comment.
Actionable comments posted: 5
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
src/pythinker_code/dashboard/app.py (1)
141-150:⚠️ Potential issue | 🟠 Major | ⚡ Quick winInclude IPv6 any-address in allowed origins (or avoid opening
[::]).Line 141 excludes
::fromorigin_hosts, but Line 150 opens the browser athttp://[::]:.... With origin enforcement enabled, dashboard API requests from that origin can be rejected.Suggested fix
- origin_hosts = ["localhost", "127.0.0.1"] - if host not in {"0.0.0.0", "::"}: + origin_hosts = ["localhost", "127.0.0.1"] + if host not in {"0.0.0.0", "::"}: origin_hosts.append(host) elif host == "0.0.0.0": origin_hosts.extend(get_network_addresses()) + else: # host == "::" + origin_hosts.extend(["::1", "::"]) allowed_origins = [format_url(addr, actual_port) for addr in dict.fromkeys(origin_hosts)] os.environ[_ENV_ALLOWED_ORIGINS] = ",".join(allowed_origins) # Browser should open localhost - browser_host = "localhost" if host == "0.0.0.0" else host + browser_host = "localhost" if host in {"0.0.0.0", "::"} else host🤖 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/pythinker_code/dashboard/app.py` around lines 141 - 150, The code excludes the IPv6 any-address (::) from origin_hosts on line 141, but the browser_host logic on line 150 does not account for this, allowing the browser to open at an origin that is not in the allowed_origins list. Fix this by treating :: similarly to 0.0.0.0: either add special handling in the elif block to expand :: to specific IPv6 addresses (similar to get_network_addresses()), or update the browser_host assignment to use "localhost" when host is :: (by extending the ternary condition to check for both "0.0.0.0" and "::"). The simpler approach is to update the browser_host ternary condition to treat both cases the same way.tests/web/test_web_ui_assets.py (1)
31-42:⚠️ Potential issue | 🟡 MinorAdd missing assertion for asset path in dashboard error response.
The dashboard test should verify that the specific missing asset path appears in the error response, matching the web test pattern. The
missing_ui_page()function includes the asset path in the HTML output, so the assertion should confirm it:assert "pythinker_code/dashboard/static/index.html" in resp.textThe concern about auth requirements is not valid—the "/" endpoint is not authentication-gated for either app (AuthMiddleware only enforces auth on
/api/paths), so both tests correctly access it without session credentials.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@tests/web/test_web_ui_assets.py` around lines 31 - 42, The test_dashboard_root_explains_missing_assets function is missing an assertion to verify that the specific missing asset path appears in the error response. Add an assertion after the existing "make build-dashboard" assertion to confirm that the asset path "pythinker_code/dashboard/static/index.html" is present in resp.text, which will verify that the error response correctly identifies the missing asset.
🤖 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 `@AGENTS.md`:
- Around line 147-148: Update the inline comments for the make commands in
AGENTS.md to use the current naming convention instead of the old
"visualization" terminology. Replace the comment for `make dashboard-back` that
currently says "visualization backend on port 5495" and the comment for `make
dashboard-front` that currently says "visualization frontend dev server" with
descriptions that align with the renamed target names and use the "dashboard-"
nomenclature consistently throughout the documentation.
In `@dashboard/src/App.tsx`:
- Around line 384-385: The numeric tab shortcuts (1–5) are gated behind a
sessionId check at line 384–385, meaning they only function when a session is
active. However, the help overlay text presents these shortcuts as globally
available, creating an inaccurate representation. Update the help content to
either conditionally render the 1–5 shortcut descriptions only when a session is
selected (when sessionId is truthy), or explicitly label them as "session view"
shortcuts in the help text. Address this mismatch at the location where the help
overlay defines the shortcut descriptions, ensuring the displayed shortcuts
accurately reflect their actual availability constraints.
In `@dashboard/src/hooks/use-theme.ts`:
- Around line 13-14: The localStorage read in the use-theme.ts file currently
only checks for the "dashboard-theme" key, but existing users may have
previously saved their theme preference under the old "vis-theme" key. Modify
the localStorage.getItem call to add a fallback mechanism: first attempt to read
from "dashboard-theme", and if that returns null, then read from "vis-theme" as
a fallback before returning the system theme default. This ensures backward
compatibility for users upgrading from the previous version.
In `@src/pythinker_code/cli/__init__.py`:
- Around line 42-44: The __init__ method of the SwitchToDashboard class is
missing the required return type annotation. Add `-> None` to the method
signature of the __init__ method to comply with the repository's type annotation
requirements for public methods. The method signature should declare its return
type explicitly even though __init__ methods implicitly return None.
In `@src/pythinker_code/ui/shell/slash.py`:
- Line 2003: The `reports` function declares an `args` parameter that is not
used anywhere in the function body, which triggers the Ruff ARG001 lint warning.
To fix this, rename the unused `args` parameter to `_args` in the function
signature to follow Python convention for intentionally unused parameters and
satisfy the linter.
---
Outside diff comments:
In `@src/pythinker_code/dashboard/app.py`:
- Around line 141-150: The code excludes the IPv6 any-address (::) from
origin_hosts on line 141, but the browser_host logic on line 150 does not
account for this, allowing the browser to open at an origin that is not in the
allowed_origins list. Fix this by treating :: similarly to 0.0.0.0: either add
special handling in the elif block to expand :: to specific IPv6 addresses
(similar to get_network_addresses()), or update the browser_host assignment to
use "localhost" when host is :: (by extending the ternary condition to check for
both "0.0.0.0" and "::"). The simpler approach is to update the browser_host
ternary condition to treat both cases the same way.
In `@tests/web/test_web_ui_assets.py`:
- Around line 31-42: The test_dashboard_root_explains_missing_assets function is
missing an assertion to verify that the specific missing asset path appears in
the error response. Add an assertion after the existing "make build-dashboard"
assertion to confirm that the asset path
"pythinker_code/dashboard/static/index.html" is present in resp.text, which will
verify that the error response correctly identifies the missing asset.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 41de849d-230a-4466-b8eb-3ece71c8e5bd
⛔ Files ignored due to path filters (10)
dashboard/package-lock.jsonis excluded by!**/package-lock.jsondocs/.vitepress/config.tsis excluded by!docs/**docs/AGENTS.mdis excluded by!docs/**docs/en/configuration/data-locations.mdis excluded by!docs/**docs/en/customization/agent-architecture.mdis excluded by!docs/**docs/en/customization/architecture.mdis excluded by!docs/**docs/en/reference/pythinker-command.mdis excluded by!docs/**docs/en/reference/pythinker-dashboard.mdis excluded by!docs/**docs/en/reference/slash-commands.mdis excluded by!docs/**docs/en/release-notes/changelog.mdis excluded by!docs/**
📒 Files selected for processing (86)
.github/dependabot.yml.github/workflows/linux-installer.yml.github/workflows/windows-installer.yml.gitignoreAGENTS.mdCHANGELOG.mdMakefileREADME.mddashboard/AGENTS.mddashboard/components.jsondashboard/index.htmldashboard/package.jsondashboard/src/App.tsxdashboard/src/components/markdown.tsxdashboard/src/components/metric-card.tsxdashboard/src/components/ui/alert-dialog.tsxdashboard/src/components/ui/card.tsxdashboard/src/components/ui/select.tsxdashboard/src/components/ui/tooltip.tsxdashboard/src/features/agents-panel/agent-scope-bar.tsxdashboard/src/features/agents-panel/agents-panel.tsxdashboard/src/features/context-viewer/assistant-message.tsxdashboard/src/features/context-viewer/context-space-map.tsxdashboard/src/features/context-viewer/context-viewer.tsxdashboard/src/features/context-viewer/tool-call-block.tsxdashboard/src/features/context-viewer/user-message.tsxdashboard/src/features/dual-view/dual-view.tsxdashboard/src/features/session-picker/session-picker.tsxdashboard/src/features/sessions-explorer/explorer-toolbar.tsxdashboard/src/features/sessions-explorer/project-group.tsxdashboard/src/features/sessions-explorer/session-card.tsxdashboard/src/features/sessions-explorer/sessions-explorer.tsxdashboard/src/features/state-viewer/state-viewer.tsxdashboard/src/features/statistics/statistics-view.tsxdashboard/src/features/usage/usage-heatmap.tsxdashboard/src/features/usage/usage-trend-chart.tsxdashboard/src/features/usage/usage-view.tsxdashboard/src/features/wire-viewer/decision-path.tsxdashboard/src/features/wire-viewer/integrity-check.tsxdashboard/src/features/wire-viewer/timeline-view.tsxdashboard/src/features/wire-viewer/tool-call-detail.tsxdashboard/src/features/wire-viewer/tool-stats-dashboard.tsxdashboard/src/features/wire-viewer/turn-efficiency.tsxdashboard/src/features/wire-viewer/turn-tree.tsxdashboard/src/features/wire-viewer/usage-chart.tsxdashboard/src/features/wire-viewer/wire-event-card.tsxdashboard/src/features/wire-viewer/wire-filters.tsxdashboard/src/features/wire-viewer/wire-viewer.tsxdashboard/src/hooks/use-theme.tsdashboard/src/index.cssdashboard/src/lib/api.tsdashboard/src/lib/cache.tsdashboard/src/lib/utils.tsdashboard/src/main.tsxdashboard/tsconfig.app.jsondashboard/tsconfig.jsondashboard/tsconfig.node.jsondashboard/vite.config.tspackages/linux-installer/pythinker.specpackages/windows-installer/pythinker.specpythinker.specscripts/build_dashboard.pysrc/pythinker_code/cli/__init__.pysrc/pythinker_code/cli/_lazy_group.pysrc/pythinker_code/cli/dashboard.pysrc/pythinker_code/dashboard/__init__.pysrc/pythinker_code/dashboard/api/__init__.pysrc/pythinker_code/dashboard/api/sessions.pysrc/pythinker_code/dashboard/api/statistics.pysrc/pythinker_code/dashboard/api/system.pysrc/pythinker_code/dashboard/app.pysrc/pythinker_code/ui/shell/__init__.pysrc/pythinker_code/ui/shell/slash.pysrc/pythinker_code/utils/pyinstaller.pysrc/pythinker_code/utils/server.pysrc/pythinker_code/utils/subprocess_env.pysrc/pythinker_code/vis/api/__init__.pytests/core/test_cli_reload.pytests/core/test_startup_imports.pytests/core/test_wire_file_compat.pytests/dashboard/test_app.pytests/tools/test_memory_routing_guard.pytests/ui_and_conv/test_shell_switch_slash.pytests/utils/test_pyinstaller_utils.pytests/utils/test_subprocess_env.pytests/web/test_web_ui_assets.py
💤 Files with no reviewable changes (1)
- src/pythinker_code/vis/api/init.py
- Regenerate dashboard/package-lock.json to restore the nested @emnapi deps so the onefile build's `npm ci` succeeds (was failing on every platform in PR #137 CI). - Open the browser at localhost for `::` binds, not just `0.0.0.0`, so the URL stays within the allowed origins (loopback_browser_host helper + test). - use-theme: fall back to the legacy "vis-theme" key for upgraders. - Help overlay: move the session-gated 1-5 tab shortcuts out of "Global" into a "Session Views" group. - AGENTS.md: drop stale "visualization" wording for the dashboard targets. - Assert the dashboard missing-assets 503 names the expected static path.
The Daily Usage line chart stretched to the full 1400px content width, leaving the sparse 30-day series looking over-extended. Cap the card at max-w-3xl and center it (matching loading skeleton) so it stays centered and readable on wide screens.
…sync - Add -> None return type to SwitchToDashboard.__init__ (ANN204) - Rename unused args to _args in reports() slash command (ARG001) - Add IPv6 :: host to allowed_origins in dashboard app - Add @emnapi/core@1.11.1 and @emnapi/runtime@1.11.1 to dashboard lockfile The build was failing on all platforms because npm ci could not find @emnapi/core@1.11.1 and @emnapi/runtime@1.11.1 in the lockfile. These are needed by @tailwindcss/oxide-wasm32-wasi which pins ^1.10.0 (now resolved to 1.11.1 on the registry). Added the missing top-level entries.
Summary
vis/pythinker vissubsystem todashboard/pythinker dashboardthroughout — CLI command, Python package, frontend app directory, build scripts, tests, and docs.pythinker dashboard— a local web UI for inspecting agent sessions: wire events, context messages, state, sub-agents, a dual view, tool statistics, and usage over time.pythinker_code.dashboard) under/api/dashboard, with the React/Vite frontend bundled at build time (make build-dashboard), wired into the wheel, PyInstaller binaries, and the Linux/Windows installers./reports(alias/dashboard).Test plan
make check-pythinker-codepasses (ruff + pyright)make test-pythinker-codepasses (unit tests, including renamedtests/dashboard/)make check-webpassesmake build-dashboardproducesdashboard/dist/and syncs tosrc/pythinker_code/dashboard/static/pythinker dashboardlaunches the web UI and is accessible in browser/reportsand/dashboardslash commands open the dashboard from the shellpythinker.spec, linux/windows variants) include the renamed dashboard staticsSummary by CodeRabbit
New Features
pythinker dashboardcommand and/dashboardalias in the interactive shell.Documentation