mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-03 13:41:34 +00:00
* feat(ui): durable session board face and dashboards index Board face lived only in client-side boardSessionViews, capped at 50 entries, so the preference never followed the user to another device, evicted as sessions accumulated, and could not be seen as a set. Persist it as SessionEntry.boardFace, which rides the existing entry_json blob and so needs no SQLite schema change or version bump. Expose it on the session list row and add it to the sessions.patch write-scope allowlist alongside label, pinned, and archived: setting your own view preference is user-level chat organization, not policy. Unknown patch fields still fail closed to operator.admin. Generic navigation now reads the stored face, so the sidebar and session list open a thread on the face you left it on. boardSessionViews keeps only activeTabId and reopenDockByTab, which are genuinely per-device. Add /dashboards listing threads whose preferred face is dashboard. Filtering runs server-side in filterSessionEntries before pagination, because the client holds only a capped page and a client-side filter would silently omit dashboards. * test(protocol): assert the pre-rename face param is rejected The gateway-protocol validator test still passed the pre-rename 'face' key, which the closed schema rejects. Use boardFace, and pin the old name as a negative case so it cannot silently return. * chore(protocol): regenerate Swift bindings and docs map for boardFace Adding boardFace to the sessions schema changes two committed generated artifacts: the Swift gateway models (pnpm protocol:gen:swift) and the docs map (pnpm docs:map:gen), which now lists the dashboards index section.
114 lines
5.3 KiB
Markdown
114 lines
5.3 KiB
Markdown
---
|
|
summary: "Session dashboards: agent-built widgets, boards, tabs, and the docked chat"
|
|
read_when:
|
|
- Using or explaining session dashboards in the Control UI
|
|
- Deciding what agents can do on a board and what needs an operator grant
|
|
title: "Session Dashboards"
|
|
---
|
|
|
|
Every thread in the Control UI has two faces: the conversation you know, and a
|
|
**dashboard** — a grid of live widgets your agent builds for you. A thread with
|
|
no widgets is just chat. The moment a widget is pinned, a **Chat | Dashboard**
|
|
toggle appears in the header, and the dashboard becomes the main surface with
|
|
your chat docked beside it.
|
|
|
|
There is nothing to set up and no separate app to configure: dashboards are a
|
|
core feature, owned by the thread, stored with the agent, and they survive
|
|
`/new` and `/reset` (the conversation context clears; the board stays).
|
|
|
|
## Find your dashboards
|
|
|
|
Open `/dashboards` to see every thread whose preferred face is Dashboard, with
|
|
the most recently updated thread first. Open any row to go directly to that
|
|
thread's `/dashboard/<agent>/<sessionRef>` URL.
|
|
|
|
The Chat or Dashboard face preference is stored server-side per thread. It
|
|
therefore follows you when you connect to the same gateway from another device.
|
|
The active dashboard tab and remembered chat-dock position remain per-device UI
|
|
state, so each browser can keep its own working layout.
|
|
|
|
## Build a dashboard by asking
|
|
|
|
Ask your agent for what you want to see:
|
|
|
|
> Create a widget named revenue-graph: an interactive bar chart of monthly
|
|
> revenue. Add "Bars" and "Trend" buttons that switch views. Pin it to my
|
|
> dashboard.
|
|
|
|
The agent renders the widget inline in the chat first, so you can look at it
|
|
before it goes anywhere. From there:
|
|
|
|
- **You pin it**: hover an inline widget and choose **Pin to dashboard**.
|
|
- **Or the agent pins it** directly when you ask, and updates it later by
|
|
name — widgets have stable names, so "update revenue-graph with June's
|
|
numbers" replaces the content in place while the board stays put.
|
|
|
|
Widgets are self-contained little apps (HTML/JS/SVG in a hard sandbox). Buttons
|
|
and view toggles inside a widget work immediately — switching a chart view
|
|
never needs the agent.
|
|
|
|
## The board
|
|
|
|
- **Fluid grid.** Drag widgets by their handle; everything reflows and
|
|
compacts automatically. Resize by handle or pick a size preset (small,
|
|
medium, large, extra large) from the widget menu. Nobody places pixels —
|
|
not you, not the agent.
|
|
- **Tabs.** A board can have several pages — say, an overview tab and a
|
|
focused tab with one big widget. Each tab remembers its own chat-dock
|
|
position.
|
|
- **Docked chat.** On the dashboard face, your conversation docks to the
|
|
left, right, or bottom, resizes like the sidebar, and can be hidden
|
|
entirely — the agent still hears you when you bring it back.
|
|
- **Agent parity.** Everything you can do, the agent can do with its
|
|
`dashboard` tool: add, update, move, resize, and remove widgets, manage
|
|
tabs, switch the visible tab, and move or hide the chat dock. Ask "put the
|
|
chat on the left and show the finance tab" and watch it happen.
|
|
|
|
## What widgets are allowed to do
|
|
|
|
A widget that only renders needs no approval — it appears instantly, exactly
|
|
like inline chat widgets, and its network access is fully disabled.
|
|
|
|
Widgets that want **reach** must declare it, and you grant it once per widget
|
|
with one tap:
|
|
|
|
- **Network** (`net`): fetch declared HTTPS origins directly from the sandbox —
|
|
a weather card that refreshes itself from an API, for example.
|
|
- **Gateway data** (`data`): read-only feeds like sessions, usage, or cron
|
|
status, resolved by the gateway — the widget never holds your token.
|
|
- **Automation** (`actions`): trigger a specific cron job, so a button can run
|
|
a real task (which may use a smaller model) without waking your main
|
|
conversation.
|
|
- **Prompt** (`prompt`): send messages into your thread without the per-click
|
|
confirmation that unapproved widgets require.
|
|
|
|
Enabled plugins can add their own named read-only feeds and actions to these capability lists; disabling the plugin removes those integrations.
|
|
|
|
Grants are bound to the exact widget bytes and revision you reviewed. If the
|
|
agent changes the widget and asks for _more_ than you approved, it goes back
|
|
to pending; refreshing content within the same permissions keeps the grant.
|
|
Widget interactions the agent should know about (filters you clicked, views
|
|
you switched) reach it quietly as session notices — it stays informed without
|
|
being interrupted.
|
|
|
|
## MCP apps on the board
|
|
|
|
If your gateway has MCP servers configured, interactive MCP apps that appear
|
|
in chat can be pinned like any widget. Pinned apps come back to life on the
|
|
board with fresh sessions; by default they are display-only, and granting the
|
|
widget its declared server tools makes it fully interactive — with the same
|
|
one-tap, revision-bound approval as everything else.
|
|
|
|
## Good to know
|
|
|
|
- Resetting a thread that has a board asks for confirmation and keeps the
|
|
board.
|
|
- Deleting a thread deletes its board.
|
|
- Boards live on your gateway (in the owning agent's database) and appear on
|
|
every device you connect from.
|
|
- Switching a thread to the Dashboard face adds it to `/dashboards`. Switching
|
|
it back to Chat removes it.
|
|
- The security model, storage details, and design rationale live in
|
|
[Dashboard Architecture](/web/dashboard-architecture), including the
|
|
documented sandbox tradeoffs.
|