Dashboard: preview widget β embed a live URL with reload + viewport controls#101334
Dashboard: preview widget β embed a live URL with reload + viewport controls#101334100yenadmin wants to merge 5 commits into
Conversation
New bundled plugin `extensions/dashboard`: a gateway-owned workspace document (atomic JSON store with undo, size caps, schema validation), 14 `dashboard.*` gateway methods with change broadcasts, an `openclaw dashboard` CLI, and 14 `dashboard_*` agent tools β all sharing one validated store so humans, the CLI, and agents mutate the dashboard through the same guarded path. Layout is data; no core changes. Part of the modular-dashboard series (backend layer).
β¦ (PR2) The Workspaces bundled tab view for the dashboard plugin: tab strip, grid with pointer drag/resize/collapse, the 9 builtin widgets + Overview-as-data default workspace, and the UX polish (themed dialogs, page header, onboarding, humane error cards, skeletons, (custom) suffix strip). Wires the plugin's Control UI descriptor (registerControlUiDescriptor) and the BUNDLED_TAB_VIEWS "dashboard/workspaces" entry, plus the #6 breadcrumb label (app-host -> app-topbar -> dashboard-header currentLabel) so "Plugin" reads "Workspaces". Custom-widget (custom:<name>) rendering is the sandboxed-host feature landing in the follow-up PR: this layer ships the TRUSTED widget-cell (builtin dispatch + neutral placeholder for custom kinds, no iframe) and the view without the manifest/custom-host plumbing, so it builds with no L5 files present. i18n: en.ts carries all dashboard.* keys; non-English bundles regenerated with English fallbacks (translation pass runs before the PR opens).
β¦n TM) Reuses existing dashboard.* translations from the integration branch's translation memory instead of an English-fallback sync, so the new Workspaces Control UI keys ship translated in all 20 locales without any LLM calls.
The custom-widget (custom:<name>) feature on top of the Workspaces UI: a sandboxed iframe host for approved widgets, the operator approve/reject gate, and the plugin HTTP route that serves approved widget assets under an auth:"plugin" static-file-only path (jailed per widget dir, GET only). Restores the FINAL widget-cell (custom-branch dispatch: approved -> iframe host, pending -> approval card, rejected -> neutral placeholder, never an iframe without a manifest) and the view's manifest-cache + custom-context plumbing that PR2 held back so it could build with no L5 files present. - extensions/dashboard/src: http-route, serve, manifest (+ tests) and the rpc-allowlist sync guard; index.ts registers the widgets HTTP route. - ui: dashboard-custom-widget host + bridge (+ tests, e2e); plugin-page passes basePath/sessionKey so the iframe src and prompt dispatch resolve. i18n keys (incl. approval.*) already shipped in PR2; no en.ts change.
β¦port controls Adds a trusted builtin:preview widget (phase 1) cloned from iframe-embed: embeds a URL in the same sandboxed frame (sandbox + external-URL policy unchanged), with a reload control and desktop/tablet/mobile viewport presets. - builtin:preview renderer + registration (BUILTIN_WIDGET_RENDERERS, BUILTIN_KIND_PATTERN) - reuses resolveEmbedSandbox + evaluateEmbedUrl (no sandbox weakening) - i18n keys dashboard.widget.preview.* + regenerated locale bundles Implements openclaw#101138 (phase 1). Phases 2-3 (dev-server, browser-backed) are follow-ons. Tests: ui dashboard 100, i18n check clean, build + oxlint green.
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
Dependency GuardThis PR changes dependency-related files. Maintainers should confirm these changes are intentional. Changed files:
Maintainer follow-up:
|
|
On the |
Dependency graph changes are blockedOpenClaw does not accept dependency graph changes through PRs unless a repository admin or security explicitly authorizes the current head SHA. Dependency updates are generated internally by maintainers so external PRs cannot change the resolved graph. Detected dependency graph changes:
Auto-scrub was not attempted because this PR changes package manifest dependency graph fields:
Dependency graph changes must be reviewed by security or handled by maintainers internally. Please remove lockfile changes manually if they are not needed. To remove lockfile changes, restore them from the target branch: git fetch origin
git checkout 'origin/main' -- 'pnpm-lock.yaml'
git commit -m 'chore: remove dependency lockfile change'
git pushIf this PR intentionally needs a dependency graph change, ask a repository admin or member of The action will approve the current head SHA ( |
|
Closing this PR because the author has more than 20 active PRs in this repo. Please reduce the active PR queue and reopen or resubmit once it is back under the limit. You can close your own PRs to get back under the limit. |
Closes #101138 (phase 1). Stacked on #101098 β targets
mainwith a cumulative diff; review the newpreviewwidget files as the delta.What problem this solves
Operators and maintainers have asked for a browser/preview panel in the dashboard for a long time (#27574). This delivers phase 1: a trusted
builtin:previewwidget that renders a URL inside the same sandboxed embed frame the dashboard already uses, with reload + viewport controls β so a preview is just another widget an agent or human can place.What's in this PR
builtin:previewwidget (ui/src/lib/dashboard/widgets/preview.ts) cloned fromiframe-embed, reusing its sandbox + external-URL policy unchanged.BUILTIN_WIDGET_RENDERERS;previewadded toBUILTIN_KIND_PATTERN.Scope
Phase 1 only β embed + reload + viewport. Phase 2 (agent-driven dev-server lifecycle + hot-reload) and phase 3 (browser-backed console/network/screenshot so the agent sees its own preview) are follow-on PRs tracked on #101138.
How it works
The preview widget reuses
resolveEmbedSandboxand the external-URL gating fromiframe-embedverbatim β it does not weaken the sandbox. The URL comes from the samestatic/rpcbinding path every builtin uses. The added chrome (reload, viewport) is pure view state around the existing sandboxed frame.Note: no new dependency β
pnpm-lock.yamlis unchanged. The diff includes regenerated i18n locale bundles for the newdashboard.widget.preview.*keys (via the repo'sui:i18n:synclocale workflow); those generated files can be skipped in review.Real behavior proof
Behavior or issue addressed: The dashboard has no preview/browser panel (#27574); there's no first-class way to watch a running dev server or a deployed URL inside a workspace. This adds a trusted
builtin:previewwidget with reload + viewport controls, reusing the existing sandboxed embed frame.Evidence:
pnpm vitest run src/lib/dashboardβ 100 passed (the preview widget renders the bound URL in a sandboxed frame, the reload control re-setssrc, viewport buttons swap the frame width, and the sandbox + external-URL policy matchiframe-embed);pnpm ui:buildgreen; oxlint clean;pnpm ui:i18n:checkclean after regenerating the locale bundles.