Skip to content

feat: Dashboard v2: Svelte rewrite + new Code, Stats, and Timeline views - #1526

Open
paul-basanets wants to merge 3 commits into
oraios:mainfrom
paul-basanets:dashboard-v2
Open

feat: Dashboard v2: Svelte rewrite + new Code, Stats, and Timeline views#1526
paul-basanets wants to merge 3 commits into
oraios:mainfrom
paul-basanets:dashboard-v2

Conversation

@paul-basanets

Copy link
Copy Markdown
Contributor

Dashboard v2: Svelte rewrite + new Code, Stats, and Timeline views

A full rewrite of the Serena dashboard with a refreshed look, three new top-level
views, and a much richer picture of what the agent is doing in real time.

What's new

Modern dashboard

A rewritten from legacy single-page app with a consistent visual language.

Live activity Timeline

A scrolling timeline of recent tool calls and queued executions, with per-row
duration, status, and error details, plus filtering and summary cards
("calls today", "active tools", "error rate", etc.) at the top of the page.

Stats view

Interactive charts of tool usage: sortable bar charts, duration and call-rate
views, a dual-axis token/call chart, and a drill-down panel for any single
tool showing its full call history, timing distribution, and error breakdown.

Code view

A new file-explorer experience powered by the language servers Serena already
runs:

  • File tree for browsing the active project.
  • Symbol outline per file, with breadcrumbs, filter, and copy.
  • Workspace symbol search across the project.
  • Diagnostics panel scoped to the current file or directory, routed to
    the correct language server, with a "how it works" explainer.

Better internals (user-visible)

  • Tool-call records now carry timing, error, and last-called metadata, which
    feeds the Timeline, Stats, and drill-down views.
  • Queued executions report their own timing so long-running tools are visible
    while still in progress.
  • Diagnostics for any file are dispatched to the language server that owns it.

This PR consists actually from 2 parts: rewrite of the dashboard to Svelte app so it's easier maintainable and extendable and couple of new features (Code tab, Stats updates, UI updates)

Comment thread src/serena/dashboard_code.py Fixed
Comment thread src/serena/dashboard_code.py Fixed
"""
candidate_paths: list[str] = []
truncated = False
for dirpath, dirnames, filenames in os.walk(walk_root, followlinks=False):
return _err(400, str(e))
except FileNotFoundError:
return _err(404, "directory not found")
if not os.path.isdir(resolved):

entries: list[_DirEntry] = []
try:
with os.scandir(resolved) as it:
Comment thread src/serena/dashboard_code.py Fixed
Comment thread src/serena/dashboard_code.py Fixed
Comment thread src/serena/dashboard_code.py Fixed
Comment thread src/serena/dashboard_code.py Fixed
Comment thread src/serena/dashboard_code.py Fixed
@paul-basanets
paul-basanets force-pushed the dashboard-v2 branch 5 times, most recently from 8f51bf9 to 727d702 Compare May 29, 2026 22:12
@paul-basanets

Copy link
Copy Markdown
Contributor Author

I believe those two types of issues from the security bot are actually false positives as we deal with local tool here:

  • This path depends on a [user-provided value]
  • Stack trace information flows to this location and may be exposed to an external user.

@opcode81

Copy link
Copy Markdown
Contributor

The biggest issue with this is that it is against our contribution guidelines. Please read them.

If we had wanted the dashboard to be implemented with Svelte, we would have done so.
We are not frontend developers and wanted it to be simple, first and foremost - without even a build process. This makes the dashboard implementation significantly more complicated - without any obvious benefits from my perspective.
We need to maintain this, and keeping it simple is important.

@paul-basanets

Copy link
Copy Markdown
Contributor Author

@opcode81
From my point of view the biggest benefit of new features - now user can see much more on what happens and some extra info regading tool calls - timings, token counts etc.

Anyway it's up to you, fell free to close the PR if you find it irrelevant.

@opcode81

Copy link
Copy Markdown
Contributor

It is not primarily about the new features, some of which we think are useful; it is about the switch to Svelte.

We greatly appreciate the work you have put into trying to improve Serena, but it is important that changes this large (and especially changes to the tech stack) be discussed in an issue prior to implementation - in order to produce a PR that aligns with the goals of the project and avoid unnecessary work. Please be sure to read our contribution guidelines.

We will further discuss this internally and get back to you.

@paul-basanets
paul-basanets force-pushed the dashboard-v2 branch 5 times, most recently from 631d6ad to 367d7ac Compare June 8, 2026 19:29
candidate = os.path.realpath(os.path.join(root_real, path))
if candidate != root_real and not candidate.startswith(root_real + os.sep):
raise ValueError(f"path escapes project root: {path!r}")
if not os.path.exists(candidate):
@MischaPanch

MischaPanch commented Jun 9, 2026

Copy link
Copy Markdown
Member

Hi @paul-basanets , I appreciate that you continue improving this. We have not forgotten about the overhaul of the dashboard, just that other things are more urgent. Just FYI, we will definitely get back to you about this.

@paul-basanets

Copy link
Copy Markdown
Contributor Author

@MischaPanch , no problem, thank you. To be honest i do it for myself and couple of other guys :)
Just the branch is wired to this PR so it's getting updated when i'm pushing here.

paul-basanets and others added 2 commits August 5, 2026 11:02
Replace the legacy jQuery dashboard with a Svelte 5 + TypeScript app.

- New Vite-based build pipeline + CI; remove the legacy jQuery dashboard.
- Banners, "What's New", and config-modal wiring; restore legacy visual parity.
- Shared modal-action / Confirm primitives, token-driven styles, a11y and a header menu.
- Test scaffolding (shared fetch/fixture helpers) and broadened store/component coverage.
- Single-pass highlightTools and escapeHtml hardening.
- analytics: ToolCallRecord ring buffer, Entry timing/error/last_called_at
  fields, 8KB truncation helper, cursor-based reads.
- Instrument agent tool dispatch (timing + error capture) and task-executor
  TaskInfo timing with a race fix around future resolution.
- Backend endpoints: timeline, totals, queued-exec timing; /code/* routes
  (list_dir, file_symbols, workspace_symbol_search, diagnostics_summary).
- Frontend: Timeline, SummaryCards, FilterDropdown, Stats charts
  (sort selector, duration, rate, drilldown), and the Code tab
  (store, FileTree, Symbols, Search).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
A tool call exceeding the tool timeout is cancelled and reported to the
client as a failure, but its thread keeps running. Nothing was recorded at
the point of the timeout, and the task's finally block later recorded the
same call as a success with the full over-timeout duration, so the dashboard
timeline showed a successful call for a request the client saw fail (or
nothing at all when the tool never finished).

Record the call at most once, via a lock-guarded recorder shared by the
waiter and the task: whichever completes first wins, so analytics holds
exactly one record and it matches what the client observed. The lock also
keeps a slow-then-completing call from being counted twice in the
aggregate stats.

TaskInfo.get_error_message() returned None for cancelled futures, leaving
the queued-executions panel blank; it now reports the cancellation without
claiming a specific cause, since a user-initiated cancel from the dashboard
reaches the same state.

Note that _log_tool_application reports frame.f_locals, which includes
closure variables of apply_ex.task(); the apply-kwargs construction has to
stay inside task() or the tool's parameters silently vanish from the log,
and the new recorder closure is excluded explicitly.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Version.is_at_least/is_at_most indexed self.components directly, raising
IndexError when the version had fewer components than the one it was
compared against. All three callers pass externally sourced version strings
- PyPI's latest release, `dotnet --version` output and JetBrains plugin
metadata - so none of them can guarantee the documented precondition.

The dashboard's newer-version check hit this on every construction in the
tests, where the dummy agent reports "test-version": _get_version_components
stops at the first non-numeric character, yielding no components at all and
an IndexError logged from the background thread.

Treat missing components as 0, so "1.6" compares as "1.6.0" and an
unparseable version compares as lowest rather than raising. is_equal already
handled short component lists via slicing and is left alone.

Also stop the dashboard tests from depending on network access: constructing
SerenaDashboardAPI spawns background threads querying GitHub for news and
PyPI for the version check, so disable both via an autouse fixture.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
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.

7 participants