hyperview 0.4.2__tar.gz → 0.6.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {hyperview-0.4.2 → hyperview-0.6.0}/.agents/skills/hyperview-cli/SKILL.md +25 -15
- {hyperview-0.4.2 → hyperview-0.6.0}/.agents/skills/hyperview-cli/references/commands.md +101 -9
- hyperview-0.4.2/.agents/skills/hyperview-cli/references/plugins.md → hyperview-0.6.0/.agents/skills/hyperview-cli/references/extensions.md +72 -14
- hyperview-0.6.0/.agents/skills/hyperview-cli/references/panel-modules.md +171 -0
- hyperview-0.6.0/PKG-INFO +161 -0
- hyperview-0.6.0/README.md +110 -0
- {hyperview-0.4.2 → hyperview-0.6.0}/src/hyperview/__init__.py +4 -0
- {hyperview-0.4.2 → hyperview-0.6.0}/src/hyperview/_version.py +2 -2
- {hyperview-0.4.2 → hyperview-0.6.0}/src/hyperview/api.py +172 -15
- {hyperview-0.4.2 → hyperview-0.6.0}/src/hyperview/cli.py +172 -19
- {hyperview-0.4.2 → hyperview-0.6.0}/src/hyperview/core/dataset.py +21 -1
- {hyperview-0.4.2 → hyperview-0.6.0}/src/hyperview/core/selection.py +20 -0
- {hyperview-0.4.2 → hyperview-0.6.0}/src/hyperview/embeddings/engine.py +10 -1
- {hyperview-0.4.2 → hyperview-0.6.0}/src/hyperview/embeddings/pipelines.py +2 -1
- {hyperview-0.4.2 → hyperview-0.6.0}/src/hyperview/embeddings/projection.py +15 -3
- hyperview-0.6.0/src/hyperview/figures/__init__.py +13 -0
- hyperview-0.6.0/src/hyperview/figures/colors.py +102 -0
- hyperview-0.6.0/src/hyperview/figures/render.py +628 -0
- {hyperview-0.4.2 → hyperview-0.6.0}/src/hyperview/runtime.py +327 -36
- {hyperview-0.4.2 → hyperview-0.6.0}/src/hyperview/server/app.py +269 -13
- {hyperview-0.4.2 → hyperview-0.6.0}/src/hyperview/server/static/404/index.html +1 -1
- {hyperview-0.4.2 → hyperview-0.6.0}/src/hyperview/server/static/404.html +1 -1
- {hyperview-0.4.2 → hyperview-0.6.0}/src/hyperview/server/static/__next.__PAGE__.txt +2 -2
- {hyperview-0.4.2 → hyperview-0.6.0}/src/hyperview/server/static/__next._full.txt +3 -3
- {hyperview-0.4.2 → hyperview-0.6.0}/src/hyperview/server/static/__next._head.txt +1 -1
- {hyperview-0.4.2 → hyperview-0.6.0}/src/hyperview/server/static/__next._index.txt +2 -2
- {hyperview-0.4.2 → hyperview-0.6.0}/src/hyperview/server/static/__next._tree.txt +2 -2
- {hyperview-0.4.2/src/hyperview/server/static/_next/static/z3NN_l9swds_iWzQNtTap → hyperview-0.6.0/src/hyperview/server/static/_next/static/VXRlYGcnYv3zp0mzwnWWb}/_buildManifest.js +1 -5
- hyperview-0.6.0/src/hyperview/server/static/_next/static/chunks/0c17ee078faaeb62.js +8 -0
- hyperview-0.4.2/src/hyperview/server/static/_next/static/chunks/4899f901f4ca16ad.css → hyperview-0.6.0/src/hyperview/server/static/_next/static/chunks/7acade957a14420e.css +1 -1
- {hyperview-0.4.2 → hyperview-0.6.0}/src/hyperview/server/static/_not-found/__next._full.txt +2 -2
- {hyperview-0.4.2 → hyperview-0.6.0}/src/hyperview/server/static/_not-found/__next._head.txt +1 -1
- {hyperview-0.4.2 → hyperview-0.6.0}/src/hyperview/server/static/_not-found/__next._index.txt +2 -2
- {hyperview-0.4.2 → hyperview-0.6.0}/src/hyperview/server/static/_not-found/__next._not-found.__PAGE__.txt +1 -1
- {hyperview-0.4.2 → hyperview-0.6.0}/src/hyperview/server/static/_not-found/__next._not-found.txt +1 -1
- {hyperview-0.4.2 → hyperview-0.6.0}/src/hyperview/server/static/_not-found/__next._tree.txt +2 -2
- {hyperview-0.4.2 → hyperview-0.6.0}/src/hyperview/server/static/_not-found/index.html +1 -1
- {hyperview-0.4.2 → hyperview-0.6.0}/src/hyperview/server/static/_not-found/index.txt +2 -2
- {hyperview-0.4.2 → hyperview-0.6.0}/src/hyperview/server/static/index.html +1 -1
- {hyperview-0.4.2 → hyperview-0.6.0}/src/hyperview/server/static/index.txt +3 -3
- hyperview-0.6.0/src/hyperview/storage/geometry.py +118 -0
- {hyperview-0.4.2 → hyperview-0.6.0}/src/hyperview/storage/lancedb_backend.py +74 -2
- {hyperview-0.4.2 → hyperview-0.6.0}/src/hyperview/storage/memory_backend.py +29 -9
- hyperview-0.6.0/src/hyperview/storage/metrics.py +136 -0
- {hyperview-0.4.2 → hyperview-0.6.0}/src/hyperview/tools.py +3 -3
- hyperview-0.6.0/src/hyperview/ui.py +251 -0
- hyperview-0.4.2/.agents/skills/hyperview-cli/references/native-panels.md +0 -138
- hyperview-0.4.2/PKG-INFO +0 -237
- hyperview-0.4.2/README.md +0 -186
- hyperview-0.4.2/src/hyperview/server/static/_next/static/chunks/52ce757ecb4458ef.js +0 -8
- {hyperview-0.4.2 → hyperview-0.6.0}/.gitignore +0 -0
- {hyperview-0.4.2 → hyperview-0.6.0}/LICENSE +0 -0
- {hyperview-0.4.2 → hyperview-0.6.0}/pyproject.toml +0 -0
- {hyperview-0.4.2 → hyperview-0.6.0}/src/hyperview/core/__init__.py +0 -0
- {hyperview-0.4.2 → hyperview-0.6.0}/src/hyperview/core/sample.py +0 -0
- {hyperview-0.4.2 → hyperview-0.6.0}/src/hyperview/embeddings/__init__.py +0 -0
- {hyperview-0.4.2 → hyperview-0.6.0}/src/hyperview/embeddings/compute.py +0 -0
- {hyperview-0.4.2 → hyperview-0.6.0}/src/hyperview/embeddings/providers/__init__.py +0 -0
- {hyperview-0.4.2 → hyperview-0.6.0}/src/hyperview/embeddings/providers/lancedb_providers.py +0 -0
- {hyperview-0.4.2 → hyperview-0.6.0}/src/hyperview/extensions.py +0 -0
- {hyperview-0.4.2 → hyperview-0.6.0}/src/hyperview/server/__init__.py +0 -0
- {hyperview-0.4.2/src/hyperview/server/static/_next/static/z3NN_l9swds_iWzQNtTap → hyperview-0.6.0/src/hyperview/server/static/_next/static/VXRlYGcnYv3zp0mzwnWWb}/_clientMiddlewareManifest.json +0 -0
- {hyperview-0.4.2/src/hyperview/server/static/_next/static/z3NN_l9swds_iWzQNtTap → hyperview-0.6.0/src/hyperview/server/static/_next/static/VXRlYGcnYv3zp0mzwnWWb}/_ssgManifest.js +0 -0
- {hyperview-0.4.2 → hyperview-0.6.0}/src/hyperview/server/static/_next/static/chunks/567993cf36cd4ab1.js +0 -0
- {hyperview-0.4.2 → hyperview-0.6.0}/src/hyperview/server/static/_next/static/chunks/661a08547c83f565.js +0 -0
- {hyperview-0.4.2 → hyperview-0.6.0}/src/hyperview/server/static/_next/static/chunks/86c1fc4cf542f408.js +0 -0
- {hyperview-0.4.2 → hyperview-0.6.0}/src/hyperview/server/static/_next/static/chunks/a6dad97d9634a72d.js +0 -0
- {hyperview-0.4.2 → hyperview-0.6.0}/src/hyperview/server/static/_next/static/chunks/a6dad97d9634a72d.js.map +0 -0
- {hyperview-0.4.2 → hyperview-0.6.0}/src/hyperview/server/static/_next/static/chunks/e954ba82c0a04100.js +0 -0
- {hyperview-0.4.2 → hyperview-0.6.0}/src/hyperview/server/static/_next/static/chunks/eac713f252f03efd.js +0 -0
- {hyperview-0.4.2 → hyperview-0.6.0}/src/hyperview/server/static/_next/static/chunks/f29dd35a99c216ea.js +0 -0
- {hyperview-0.4.2 → hyperview-0.6.0}/src/hyperview/server/static/_next/static/chunks/turbopack-cb59e03a04a579d1.js +0 -0
- {hyperview-0.4.2 → hyperview-0.6.0}/src/hyperview/server/static/_next/static/media/1bffadaabf893a1e-s.7cd81963.woff2 +0 -0
- {hyperview-0.4.2 → hyperview-0.6.0}/src/hyperview/server/static/_next/static/media/2bbe8d2671613f1f-s.76dcb0b2.woff2 +0 -0
- {hyperview-0.4.2 → hyperview-0.6.0}/src/hyperview/server/static/_next/static/media/2c55a0e60120577a-s.2a48534a.woff2 +0 -0
- {hyperview-0.4.2 → hyperview-0.6.0}/src/hyperview/server/static/_next/static/media/5476f68d60460930-s.c995e352.woff2 +0 -0
- {hyperview-0.4.2 → hyperview-0.6.0}/src/hyperview/server/static/_next/static/media/83afe278b6a6bb3c-s.p.3a6ba036.woff2 +0 -0
- {hyperview-0.4.2 → hyperview-0.6.0}/src/hyperview/server/static/_next/static/media/9c72aa0f40e4eef8-s.18a48cbc.woff2 +0 -0
- {hyperview-0.4.2 → hyperview-0.6.0}/src/hyperview/server/static/_next/static/media/ad66f9afd8947f86-s.7a40eb73.woff2 +0 -0
- {hyperview-0.4.2 → hyperview-0.6.0}/src/hyperview/skill_install.py +0 -0
- {hyperview-0.4.2 → hyperview-0.6.0}/src/hyperview/storage/__init__.py +0 -0
- {hyperview-0.4.2 → hyperview-0.6.0}/src/hyperview/storage/backend.py +0 -0
- {hyperview-0.4.2 → hyperview-0.6.0}/src/hyperview/storage/config.py +0 -0
- {hyperview-0.4.2 → hyperview-0.6.0}/src/hyperview/storage/schema.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: hyperview-cli
|
|
3
|
-
description: Use HyperView's control-plane CLI for hyperview serve, dataset create, workspace create, embeddings compute, layouts compute, runtime jobs, ui layout set, ui selection set, ui panel add, extension add, tools run,
|
|
3
|
+
description: Use HyperView's control-plane CLI for hyperview serve, dataset create, workspace create, embeddings compute, layouts compute, browserless paper figure export, runtime jobs, ui layout set, ui selection set, ui panel add, extension add, tools run, panel modules, backend tools, and local HyperView extension workflows.
|
|
4
4
|
license: MIT
|
|
5
5
|
compatibility: Requires Python 3.10-3.13 and the hyperview CLI (`uv tool install --python 3.12 hyperview`). Runtime-control commands require a running HyperView server.
|
|
6
6
|
metadata:
|
|
@@ -29,9 +29,10 @@ HyperView currently supports Python 3.10 through 3.13; `--python 3.12` keeps the
|
|
|
29
29
|
- Start or control a running HyperView runtime.
|
|
30
30
|
- Register a custom embedding provider.
|
|
31
31
|
- Compute embeddings or layouts without restarting the UI.
|
|
32
|
+
- Export paper-ready static 3D embedding figures without a browser or Node runtime.
|
|
32
33
|
- Switch the active workspace, layout, or selection in a running session.
|
|
33
|
-
- Add or
|
|
34
|
-
- Create, install, reload, or test a local
|
|
34
|
+
- Add, remove, or compose extension-backed panel instances.
|
|
35
|
+
- Create, install, reload, or test a local extension with Python backend tools and a frontend panel.
|
|
35
36
|
|
|
36
37
|
## Core workflow
|
|
37
38
|
|
|
@@ -41,7 +42,8 @@ HyperView currently supports Python 3.10 through 3.13; `--python 3.12` keeps the
|
|
|
41
42
|
4. Register a provider if needed.
|
|
42
43
|
5. Submit embedding or layout jobs through the runtime.
|
|
43
44
|
6. Use `hyperview ui ...` commands to switch what the live UI shows.
|
|
44
|
-
7.
|
|
45
|
+
7. Export paper figures with `hyperview figure export` when the user needs screenshots or publication diagrams.
|
|
46
|
+
8. For extensions, create an extension folder and install it into the running workspace.
|
|
45
47
|
|
|
46
48
|
## Current model
|
|
47
49
|
|
|
@@ -49,32 +51,40 @@ HyperView currently supports Python 3.10 through 3.13; `--python 3.12` keeps the
|
|
|
49
51
|
- Datasets are created separately from workspaces.
|
|
50
52
|
- The workspace owns the dataset selection.
|
|
51
53
|
- `ui layout set` changes the active layout and the frontend opens the matching built-in scatter panel.
|
|
52
|
-
-
|
|
54
|
+
- `ui similarity set` selects an anchor sample and pins the nearest-neighbor context to an explicit layout or space.
|
|
55
|
+
- Runtime-added panels can be typed scatter instances bound to explicit layout keys, or extension-backed panel modules loaded into the host React tree.
|
|
53
56
|
- Runtime-added panels use the stable `HyperViewPanelSDK` surface on `window`.
|
|
54
|
-
-
|
|
55
|
-
-
|
|
57
|
+
- Extensions are repo-local folders with `extension.toml`, optional Python tools, and optional panel modules.
|
|
58
|
+
- Extension panels call backend tools through `HyperViewPanelSDK.hooks.useTool()` or `hyperview tools run`.
|
|
59
|
+
- Extensions define reusable tools/panels; workspace views compose concrete panel instances and layout. In Python launch scripts, register extensions with `session.ui.add_extension(...)` and place panels with `hv.ui.ExtensionPanel(...)`.
|
|
56
60
|
- In practice, create datasets and workspaces before starting the runtime for that workspace. The current runtime loads workspace registry state on startup.
|
|
61
|
+
- `figure export` is browserless and supports 3D layouts only. It reuses the persisted 3D camera for the layout when available, otherwise it chooses a paper-oriented default view.
|
|
62
|
+
- Paper figure defaults are square, white-background, opaque PNGs with a faint sphere guide and direct labels for small label sets.
|
|
57
63
|
|
|
58
|
-
Read [references/commands.md](references/commands.md) for command recipes covering datasets, workspaces, providers, embeddings, layouts, runtime UI state, selections, and jobs.
|
|
59
|
-
Read [references/
|
|
60
|
-
Read [references/
|
|
64
|
+
Read [references/commands.md](references/commands.md) for command recipes covering datasets, workspaces, providers, embeddings, layouts, paper figures, runtime UI state, selections, and jobs.
|
|
65
|
+
Read [references/panel-modules.md](references/panel-modules.md) when the task involves authoring a browser panel module.
|
|
66
|
+
Read [references/extensions.md](references/extensions.md) when the task involves packaging or registering custom panel code or backend tools.
|
|
61
67
|
|
|
62
68
|
## Agent guidance
|
|
63
69
|
|
|
64
70
|
- Prefer CLI commands over direct file edits when the goal is to operate a running HyperView session.
|
|
65
71
|
- Treat dataset creation and workspace binding as separate steps when needed: `dataset create ...` creates persisted data, `workspace create --dataset ...` or `workspace set-dataset ...` binds it to a workspace.
|
|
66
72
|
- Prefer `workspace create --dataset ...` over separate create and dataset-attach calls when setting up a new workspace.
|
|
67
|
-
- For custom
|
|
73
|
+
- For custom panel code, create an extension under `.hyperview/extensions/<extension-name>/`; do not register arbitrary panel module files directly.
|
|
68
74
|
- For side-by-side embedding comparisons, add typed scatter panels through `hyperview ui panel add --kind scatter --layout-key ... --reference-panel-id ... --direction right`.
|
|
69
|
-
- For
|
|
75
|
+
- For nearest-neighbor comparisons, use `hyperview ui similarity set --sample-id ... --layout-key ...` or panel SDK `commands.showSimilar(...)`; do not infer neighbor space from whichever scatter panel is focused.
|
|
76
|
+
- For extensions, prefer `.hyperview/extensions/<extension-name>/` in the project root. `hyperview serve` auto-discovers those folders and attaches them to the launched workspace, so they can live in version control with the dataset/project code.
|
|
77
|
+
- For demos/spaces that launch HyperView from Python, compose panels with `hv.ui.Horizontal`, `hv.ui.Vertical`, `hv.ui.Scatter`, and `hv.ui.ExtensionPanel`; keep extension manifests focused on reusable panel/tool definitions.
|
|
70
78
|
- Tools can write files under `ctx.extension_storage` and return `ctx.url_for(path)` for panel-renderable artifact URLs.
|
|
71
|
-
- Keep
|
|
79
|
+
- Keep extensions self-contained: `extension.toml`, `tools.py`, `panel.js` or `panel.jsx`, and any local assets in the same folder.
|
|
72
80
|
- Prefer `--json` output when chaining commands or inspecting results programmatically.
|
|
73
81
|
- Wait for embedding/layout jobs to finish before issuing layout-switch commands that depend on their results.
|
|
74
82
|
- Use `hyperview jobs list` or `hyperview jobs inspect <job-id>` if a compute command is long-running or you started it with `--no-wait`.
|
|
75
83
|
- For provider args, use repeated `--provider-arg key=value` flags.
|
|
76
84
|
- Treat the workspace as the durable unit. Changing datasets means setting a new workspace dataset, not switching among many datasets inside one workspace.
|
|
77
|
-
- Prefer
|
|
85
|
+
- Prefer panel modules over raw HTML. The panel system no longer relies on iframes.
|
|
86
|
+
- For paper diagrams, prefer `hyperview figure export` over browser screenshots unless the user explicitly needs exact UI chrome. It does not require Playwright, browser bundling, or Node at runtime.
|
|
87
|
+
- For publication figures, keep the defaults first: `--theme light`, `--guide-style paper`, and `--legend auto`. Use `--show-selection` only when selected samples are meaningful and will be explained in the caption.
|
|
78
88
|
- The first `uv run hyperview ...` invocation in a session can take 30+ seconds (torch/datasets imports). Allow generous timeouts and avoid sending SIGINT.
|
|
79
89
|
|
|
80
90
|
## Inspecting runtime state
|
|
@@ -85,4 +95,4 @@ The runtime exposes JSON discovery endpoints alongside the CLI. Use them to obta
|
|
|
85
95
|
- `GET /api/embeddings?workspace_id=<ws>` — the active or default layout, including `layout_key`, `geometry`, and sample `ids`. Use the returned `layout_key` for `hyperview ui layout set --layout-key ...` and pick from `ids` for `hyperview ui selection set --ids ...`.
|
|
86
96
|
- `GET /api/tools` — registered tool URIs (also returned by `hyperview tools list --json`).
|
|
87
97
|
|
|
88
|
-
Layout keys encode geometry and dimension as a substring (e.g. `..._euclidean_umap__2d_...`, `..._hyperbolic_umap__3d_...`). Match on those substrings when filtering by geometry/dimension.
|
|
98
|
+
Layout keys encode geometry and dimension as a substring (e.g. `..._euclidean_umap__2d_...`, `..._hyperbolic_umap__3d_...`). Match on those substrings when filtering by geometry/dimension.
|
|
@@ -46,7 +46,7 @@ Preview destinations without writing files:
|
|
|
46
46
|
hyperview skill install --dry-run --json
|
|
47
47
|
```
|
|
48
48
|
|
|
49
|
-
This is different from `hyperview extension add`, which installs a runtime
|
|
49
|
+
This is different from `hyperview extension add`, which installs a runtime extension into a running HyperView workspace.
|
|
50
50
|
|
|
51
51
|
## Datasets and Workspaces
|
|
52
52
|
|
|
@@ -131,6 +131,63 @@ hyperview jobs list --json
|
|
|
131
131
|
hyperview jobs inspect <job-id> --json
|
|
132
132
|
```
|
|
133
133
|
|
|
134
|
+
## Paper Figures
|
|
135
|
+
|
|
136
|
+
Export a browserless, paper-ready PNG from the active 3D layout:
|
|
137
|
+
|
|
138
|
+
```bash
|
|
139
|
+
hyperview figure export figures/embedding-sphere.png \
|
|
140
|
+
--workspace research \
|
|
141
|
+
--layout active \
|
|
142
|
+
--json
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
If `--layout` is omitted, HyperView uses the active 3D layout when one is set, otherwise the first available 3D layout. Use `--layout active` when you specifically want the live UI's active layout and want the command to fail if none is active.
|
|
146
|
+
|
|
147
|
+
The export path is pure Python and does not require Playwright, browser bundling, Node, or a running frontend. It supports 3D layouts only; 2D layouts are rejected with a validation message.
|
|
148
|
+
|
|
149
|
+
Paper defaults are tuned for academic figures:
|
|
150
|
+
|
|
151
|
+
- `--width 900 --height 900 --scale 2`
|
|
152
|
+
- `--theme light`
|
|
153
|
+
- `--guide-style paper`
|
|
154
|
+
- `--legend auto` (direct labels for small label sets)
|
|
155
|
+
- opaque PNG output
|
|
156
|
+
- selection rings hidden unless explicitly requested
|
|
157
|
+
|
|
158
|
+
Use the 3D view selected in the UI by rotating the scatter panel first. HyperView persists the layout camera and `figure export` reuses it for that layout.
|
|
159
|
+
|
|
160
|
+
Common variants:
|
|
161
|
+
|
|
162
|
+
```bash
|
|
163
|
+
# Cleanest sphere context: silhouette only.
|
|
164
|
+
hyperview figure export figures/embedding-outline.png \
|
|
165
|
+
--workspace research \
|
|
166
|
+
--layout active \
|
|
167
|
+
--guide-style outline
|
|
168
|
+
|
|
169
|
+
# No sphere guide, useful when the embedding separation is the whole message.
|
|
170
|
+
hyperview figure export figures/embedding-clean.png \
|
|
171
|
+
--workspace research \
|
|
172
|
+
--layout active \
|
|
173
|
+
--guide-style none \
|
|
174
|
+
--legend direct
|
|
175
|
+
|
|
176
|
+
# Browser-like guide rings and current selection markers.
|
|
177
|
+
hyperview figure export figures/embedding-ui-like.png \
|
|
178
|
+
--workspace research \
|
|
179
|
+
--layout active \
|
|
180
|
+
--guide-style rings \
|
|
181
|
+
--legend on \
|
|
182
|
+
--show-selection
|
|
183
|
+
|
|
184
|
+
# Add a short panel title when the figure will stand alone.
|
|
185
|
+
hyperview figure export figures/embedding-panel-a.png \
|
|
186
|
+
--workspace research \
|
|
187
|
+
--layout active \
|
|
188
|
+
--title "ArcFace spherical embeddings"
|
|
189
|
+
```
|
|
190
|
+
|
|
134
191
|
## Runtime UI
|
|
135
192
|
|
|
136
193
|
Discover an existing layout key and sample IDs before mutating runtime state:
|
|
@@ -151,15 +208,18 @@ hyperview ui selection set --workspace research --ids sample-1,sample-8
|
|
|
151
208
|
|
|
152
209
|
`--layout-key` must be an existing layout (use the `layout_key` returned by `/api/embeddings`). When the chosen layout is Euclidean 3D, HyperView opens or focuses the Euclidean 3D scatter panel.
|
|
153
210
|
|
|
154
|
-
Add a
|
|
211
|
+
Add a custom panel through an extension:
|
|
155
212
|
|
|
156
213
|
```bash
|
|
214
|
+
hyperview extension add .hyperview/extensions/label-histogram \
|
|
215
|
+
--workspace research
|
|
216
|
+
|
|
157
217
|
hyperview ui panel add \
|
|
158
218
|
--workspace research \
|
|
159
219
|
--panel-id label-histogram \
|
|
160
|
-
--
|
|
220
|
+
--extension label-histogram \
|
|
221
|
+
--extension-panel label-histogram \
|
|
161
222
|
--position right \
|
|
162
|
-
--module-file agent-context/panels/label-histogram/index.js
|
|
163
223
|
```
|
|
164
224
|
|
|
165
225
|
Add two runtime scatter panels bound to explicit layouts, side by side:
|
|
@@ -184,6 +244,22 @@ hyperview ui panel add \
|
|
|
184
244
|
--direction right
|
|
185
245
|
```
|
|
186
246
|
|
|
247
|
+
Python launch scripts can encode the same composition without calling runtime
|
|
248
|
+
internals:
|
|
249
|
+
|
|
250
|
+
```python
|
|
251
|
+
view = hv.ui.View(
|
|
252
|
+
hv.ui.Horizontal(
|
|
253
|
+
hv.ui.Scatter("uncha-poincare", title="UNCHA", layout_key=uncha_layout),
|
|
254
|
+
hv.ui.Scatter("hycoclip-poincare", title="HyCoCLIP", layout_key=hycoclip_layout),
|
|
255
|
+
),
|
|
256
|
+
hv.ui.ExtensionPanel("notes", extension="notes", panel="notes", position="right"),
|
|
257
|
+
)
|
|
258
|
+
session = hv.launch(dataset, block=False)
|
|
259
|
+
session.ui.add_extension(".hyperview/extensions/notes")
|
|
260
|
+
session.ui.apply_view(view)
|
|
261
|
+
```
|
|
262
|
+
|
|
187
263
|
Remove a runtime panel by id:
|
|
188
264
|
|
|
189
265
|
```bash
|
|
@@ -192,9 +268,25 @@ hyperview ui panel remove \
|
|
|
192
268
|
--panel-id hycoclip-poincare
|
|
193
269
|
```
|
|
194
270
|
|
|
195
|
-
|
|
271
|
+
Pin nearest-neighbor results to a specific embedding layout:
|
|
272
|
+
|
|
273
|
+
```bash
|
|
274
|
+
hyperview ui similarity set \
|
|
275
|
+
--workspace research \
|
|
276
|
+
--sample-id <sample-id> \
|
|
277
|
+
--layout-key <layout-key> \
|
|
278
|
+
--k 18
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
Clear the explicit nearest-neighbor context:
|
|
282
|
+
|
|
283
|
+
```bash
|
|
284
|
+
hyperview ui similarity clear --workspace research
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
## Extensions and Tools
|
|
196
288
|
|
|
197
|
-
Create backend-plus-frontend
|
|
289
|
+
Create backend-plus-frontend extensions under `.hyperview/extensions/<name>/` so they can be versioned with the project and auto-registered on `hyperview serve`. For a server that is already running, install one explicitly:
|
|
198
290
|
|
|
199
291
|
```bash
|
|
200
292
|
hyperview extension add .hyperview/extensions/selection-profile \
|
|
@@ -202,11 +294,11 @@ hyperview extension add .hyperview/extensions/selection-profile \
|
|
|
202
294
|
--json
|
|
203
295
|
```
|
|
204
296
|
|
|
205
|
-
Inspect and run installed
|
|
297
|
+
Inspect and run installed extension tools:
|
|
206
298
|
|
|
207
299
|
```bash
|
|
208
300
|
hyperview extension list --json
|
|
209
|
-
# => {"extensions":[{"name":"selection-profile","folder":"...","workspace_id":"research","
|
|
301
|
+
# => {"extensions":[{"name":"selection-profile","folder":"...","workspace_id":"research","panel_definitions":[{"id":"selection-profile",...}],"tools":[{"uri":"selection_profile.summarize",...}]}]}
|
|
210
302
|
|
|
211
303
|
hyperview tools list --json
|
|
212
304
|
hyperview tools run selection_profile.summarize \
|
|
@@ -220,4 +312,4 @@ hyperview tools run selection_profile.summarize \
|
|
|
220
312
|
- `--param 'top_k=5'` for numbers
|
|
221
313
|
- `--param 'enabled=true'` for booleans
|
|
222
314
|
- `--param 'name=foo'` for short strings (raw fallback) or `--param 'name="foo bar"'` for explicit JSON strings
|
|
223
|
-
- `--param 'ids=["a","b"]'` or `--param 'opts={"k":1}'` for arrays/objects
|
|
315
|
+
- `--param 'ids=["a","b"]'` or `--param 'opts={"k":1}'` for arrays/objects
|
|
@@ -1,12 +1,17 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Extensions
|
|
2
2
|
|
|
3
|
-
Use this guide when creating a HyperView
|
|
3
|
+
Use this guide when creating a HyperView extension that includes backend Python tools and a frontend panel.
|
|
4
4
|
|
|
5
5
|
## Model
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
An extension is a local folder with an `extension.toml` manifest. One folder can register Python tools, panel modules, or both.
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
Extensions define reusable capabilities. They should not encode a whole workspace
|
|
10
|
+
layout or know about sibling panels. Compose concrete demo/workspace layouts
|
|
11
|
+
from Python with `hv.ui.View(...)` and `session.ui.apply_view(...)`, or from
|
|
12
|
+
the CLI with `hyperview ui panel add --extension ...`.
|
|
13
|
+
|
|
14
|
+
Preferred shape for agent-authored, project-versioned extensions:
|
|
10
15
|
|
|
11
16
|
```text
|
|
12
17
|
.hyperview/extensions/selection-profile/
|
|
@@ -37,6 +42,10 @@ file = "panel.jsx"
|
|
|
37
42
|
|
|
38
43
|
Valid panel positions are `right`, `bottom`, and `center`.
|
|
39
44
|
|
|
45
|
+
Treat `position` as a weak default for where the panel usually belongs. Cross-panel
|
|
46
|
+
relationships such as "this scatter is right of that scatter" belong to the
|
|
47
|
+
workspace view/composition layer, not the extension manifest.
|
|
48
|
+
|
|
40
49
|
## Backend Tools
|
|
41
50
|
|
|
42
51
|
Tools are plain Python functions decorated with `@tool("namespace.name")`. The first argument is a `RunContext`.
|
|
@@ -69,13 +78,13 @@ def summarize_selection(ctx: RunContext, *, sample_ids: list[str] | None = None)
|
|
|
69
78
|
}
|
|
70
79
|
```
|
|
71
80
|
|
|
72
|
-
Use `ctx.dataset` for active dataset reads, `ctx.workspace` for workspace UI state, `ctx.extension_storage` for per-
|
|
81
|
+
Use `ctx.dataset` for active dataset reads, `ctx.workspace` for workspace UI state, `ctx.extension_storage` for per-extension writable files, `ctx.url_for(path)` for renderable artifact URLs, and `ctx.submit_job(...)` for long-running work.
|
|
73
82
|
|
|
74
83
|
### RunContext and Sample shapes
|
|
75
84
|
|
|
76
85
|
- `ctx.dataset` — the active `Dataset`. Iterate samples with `for s in ctx.dataset.samples:` (returns `list[Sample]`). Look up by id with `ctx.dataset.get_samples_by_ids(ids)`.
|
|
77
86
|
- `ctx.workspace.ui.selected_ids` — current selection (`list[str]`).
|
|
78
|
-
- `ctx.extension_storage` — `pathlib.Path` to a writable per-
|
|
87
|
+
- `ctx.extension_storage` — `pathlib.Path` to a writable per-extension folder.
|
|
79
88
|
- `ctx.url_for(path)` — returns a fetchable URL for a file under `extension_storage`.
|
|
80
89
|
- `ctx.submit_job(...)` — schedule long-running work; returns a job handle.
|
|
81
90
|
|
|
@@ -123,9 +132,22 @@ export default function SelectionProfilePanel() {
|
|
|
123
132
|
}
|
|
124
133
|
```
|
|
125
134
|
|
|
126
|
-
Available SDK hooks include `usePanelRuntimeState`, `usePanelDatasetInfo`, `usePanelSamplesView`, `usePanelSelection`, `usePanelCommands`, `usePanelUiState`, `usePanelClient`, and `useTool`.
|
|
135
|
+
Available SDK hooks include `usePanelRuntimeState`, `usePanelHostState`, `usePanelDatasetInfo`, `usePanelSamplesView`, `usePanelSelectedSamples`, `usePanelSelection`, `usePanelHover`, `usePanelLayouts`, `usePanelLayoutView`, `usePanelCommands`, `usePanelUiState`, `usePanelClient`, and `useTool`.
|
|
136
|
+
|
|
137
|
+
For dataset-wide panel behavior, prefer `usePanelClient().querySamples(...)`,
|
|
138
|
+
`aggregateSamples(...)`, `selectSamples(...)`, `getSamplesByIds(...)`,
|
|
139
|
+
`searchSimilar(...)`, or a backend tool over scanning a fixed
|
|
140
|
+
`listSamples({ limit: ... })` page or hand-building API URLs in the browser.
|
|
141
|
+
|
|
142
|
+
Use `usePanelHostState()` for low-level synchronized host state instead of
|
|
143
|
+
importing frontend internals. Use narrower hooks such as `usePanelSelection()`,
|
|
144
|
+
`usePanelSelectedSamples()`, `usePanelHover()`, `usePanelLayouts()`, and
|
|
145
|
+
`usePanelLayoutView()` when the panel only needs one part of that state. Use
|
|
146
|
+
`usePanelCommands()` for host writes. Selection and active-layout changes
|
|
147
|
+
persist to runtime UI state by default; pass `{ persist: false }` only for
|
|
148
|
+
local transient UI changes.
|
|
127
149
|
|
|
128
|
-
`useTool(uri)` returns `{ run, result, loading, error, reset }`. Call `run(params)` to invoke the tool; `result` holds the last successful return value, `loading` is true while a call is in flight, and `error` is the last failure message (or `null`). See [
|
|
150
|
+
`useTool(uri)` returns `{ run, result, loading, error, reset }`. Call `run(params)` to invoke the tool; `result` holds the last successful return value, `loading` is true while a call is in flight, and `error` is the last failure message (or `null`). See [panel-modules.md](panel-modules.md#hook-return-shapes) for the full hook return shape table.
|
|
129
151
|
|
|
130
152
|
## CLI Workflow
|
|
131
153
|
|
|
@@ -135,7 +157,7 @@ Start a runtime for an existing workspace and dataset:
|
|
|
135
157
|
hyperview serve --workspace research --dataset cifar10_demo --no-browser
|
|
136
158
|
```
|
|
137
159
|
|
|
138
|
-
If the
|
|
160
|
+
If the extension already exists under `.hyperview/extensions/`, starting `hyperview serve` registers it automatically. For a server that is already running, install or reload the extension explicitly:
|
|
139
161
|
|
|
140
162
|
```bash
|
|
141
163
|
hyperview extension add .hyperview/extensions/selection-profile \
|
|
@@ -143,6 +165,19 @@ hyperview extension add .hyperview/extensions/selection-profile \
|
|
|
143
165
|
--json
|
|
144
166
|
```
|
|
145
167
|
|
|
168
|
+
Installing an extension registers its tools and panel definitions. To instantiate
|
|
169
|
+
a panel from the CLI, add an extension-backed panel instance:
|
|
170
|
+
|
|
171
|
+
```bash
|
|
172
|
+
hyperview ui panel add \
|
|
173
|
+
--workspace research \
|
|
174
|
+
--panel-id selection-profile \
|
|
175
|
+
--extension selection-profile \
|
|
176
|
+
--extension-panel selection-profile \
|
|
177
|
+
--position right \
|
|
178
|
+
--json
|
|
179
|
+
```
|
|
180
|
+
|
|
146
181
|
Inspect the result:
|
|
147
182
|
|
|
148
183
|
```bash
|
|
@@ -166,11 +201,34 @@ Reload after editing files:
|
|
|
166
201
|
hyperview extension reload selection-profile --json
|
|
167
202
|
```
|
|
168
203
|
|
|
204
|
+
Compose a demo view from Python instead of importing runtime internals:
|
|
205
|
+
|
|
206
|
+
```python
|
|
207
|
+
import hyperview as hv
|
|
208
|
+
|
|
209
|
+
view = hv.ui.View(
|
|
210
|
+
hv.ui.Horizontal(
|
|
211
|
+
hv.ui.Scatter("clip-map", title="CLIP", layout_key=clip_layout),
|
|
212
|
+
hv.ui.Scatter("hycoclip-map", title="HyCoCLIP", layout_key=hycoclip_layout),
|
|
213
|
+
),
|
|
214
|
+
hv.ui.ExtensionPanel(
|
|
215
|
+
"readout",
|
|
216
|
+
extension="catalog-readout",
|
|
217
|
+
panel="readout",
|
|
218
|
+
position="right",
|
|
219
|
+
),
|
|
220
|
+
)
|
|
221
|
+
|
|
222
|
+
session = hv.launch(dataset, block=False)
|
|
223
|
+
session.ui.add_extension(".hyperview/extensions/catalog-readout")
|
|
224
|
+
session.ui.apply_view(view)
|
|
225
|
+
```
|
|
226
|
+
|
|
169
227
|
## Verification
|
|
170
228
|
|
|
171
|
-
A good
|
|
229
|
+
A good extension smoke test proves all of these paths:
|
|
172
230
|
|
|
173
|
-
- `extension add` returns the
|
|
231
|
+
- `extension add` returns the extension with expected tools and panel definitions.
|
|
174
232
|
- `GET /api/tools` (or `hyperview tools list --json`) includes the tool URI.
|
|
175
233
|
- `hyperview tools run ...` returns data from the active dataset.
|
|
176
234
|
- Tool-generated files under `ctx.extension_storage` are fetchable from URLs returned by `ctx.url_for(...)`.
|
|
@@ -180,7 +238,7 @@ A good plugin smoke test proves all of these paths:
|
|
|
180
238
|
|
|
181
239
|
## Constraints
|
|
182
240
|
|
|
183
|
-
- Treat
|
|
241
|
+
- Treat extensions as trusted local code. Python tools are imported and executed in the HyperView runtime process.
|
|
184
242
|
- Do not use bare npm imports in panel modules unless you bundle first.
|
|
185
|
-
- Keep
|
|
186
|
-
- Keep
|
|
243
|
+
- Keep extension source outside `frontend/src`; the runtime loads panel modules from local extension files.
|
|
244
|
+
- Keep extension examples small and high-level. Avoid private HyperView APIs in user-facing examples.
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
# Panel Modules
|
|
2
|
+
|
|
3
|
+
Use this guide when writing a custom HyperView panel module that should behave like a built-in panel. Panel modules are shipped through [extensions.md](extensions.md).
|
|
4
|
+
|
|
5
|
+
## Model
|
|
6
|
+
|
|
7
|
+
HyperView no longer treats runtime-added panels as iframe HTML pages.
|
|
8
|
+
|
|
9
|
+
Runtime custom panels are now panel modules:
|
|
10
|
+
|
|
11
|
+
- the user writes a local JavaScript module file
|
|
12
|
+
- the module is declared in an extension manifest
|
|
13
|
+
- the module is instantiated through `hv.ui.ExtensionPanel(...)` or `hyperview ui panel add --extension ...`
|
|
14
|
+
- HyperView loads that module directly into the host React tree
|
|
15
|
+
- the module can use the stable `window.HyperViewPanelSDK` surface
|
|
16
|
+
|
|
17
|
+
Built-in panels and runtime panels now share the same host panel system.
|
|
18
|
+
|
|
19
|
+
Use this surface for frontend-only panel code. Package it as an extension even
|
|
20
|
+
when it does not need Python tools. If the task is to open several panels in a
|
|
21
|
+
particular arrangement, use a workspace view from Python
|
|
22
|
+
(`hv.ui.View(...)` with `hv.launch(..., view=...)`) or the CLI `hyperview ui ...`
|
|
23
|
+
commands. Do not import `HyperViewRuntime`, `CustomPanelSpec`, or `Session` from
|
|
24
|
+
demo/user-facing scripts just to arrange panels.
|
|
25
|
+
|
|
26
|
+
## Panel Module Contract
|
|
27
|
+
|
|
28
|
+
A runtime panel module must export either:
|
|
29
|
+
|
|
30
|
+
- a default React component
|
|
31
|
+
- or a named export `Panel`
|
|
32
|
+
|
|
33
|
+
The module runs in the browser and should use the SDK from `window.HyperViewPanelSDK`.
|
|
34
|
+
When a Python view provides panel `props`, HyperView passes them to the component
|
|
35
|
+
as the `props` prop, alongside `panel` and `panelId`; panel code can also read
|
|
36
|
+
them with `HyperViewPanelSDK.hooks.usePanelProps()`.
|
|
37
|
+
|
|
38
|
+
Minimal example:
|
|
39
|
+
|
|
40
|
+
```js
|
|
41
|
+
const sdk = globalThis.HyperViewPanelSDK;
|
|
42
|
+
const { React, components, hooks } = sdk;
|
|
43
|
+
const { Panel, PanelToolbar } = components;
|
|
44
|
+
const { usePanelRuntimeState } = hooks;
|
|
45
|
+
|
|
46
|
+
export default function MyPanel() {
|
|
47
|
+
const { runtimeDatasetName } = usePanelRuntimeState();
|
|
48
|
+
|
|
49
|
+
return React.createElement(
|
|
50
|
+
Panel,
|
|
51
|
+
{ className: "h-full" },
|
|
52
|
+
React.createElement(PanelToolbar, {
|
|
53
|
+
items: [{ id: "dataset", label: "Dataset", value: runtimeDatasetName || "unknown" }],
|
|
54
|
+
}),
|
|
55
|
+
React.createElement("div", { style: { padding: 12 } }, "Hello from a panel module")
|
|
56
|
+
);
|
|
57
|
+
}
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## Stable SDK Surface
|
|
61
|
+
|
|
62
|
+
Current global SDK fields:
|
|
63
|
+
|
|
64
|
+
- `React`
|
|
65
|
+
- `components.Panel`
|
|
66
|
+
- `components.PanelHeader`
|
|
67
|
+
- `components.PanelTitle`
|
|
68
|
+
- `components.PanelToolbar`
|
|
69
|
+
- `components.PanelToolbarButton`
|
|
70
|
+
- `components.PanelToolbarMenu`
|
|
71
|
+
- `hooks.usePanelClient()`
|
|
72
|
+
- `hooks.usePanelCommands()`
|
|
73
|
+
- `hooks.usePanelDatasetInfo()`
|
|
74
|
+
- `hooks.usePanelHostState()`
|
|
75
|
+
- `hooks.usePanelHover()`
|
|
76
|
+
- `hooks.usePanelInstance()`
|
|
77
|
+
- `hooks.usePanelLayouts()`
|
|
78
|
+
- `hooks.usePanelLayoutView()`
|
|
79
|
+
- `hooks.usePanelProps()`
|
|
80
|
+
- `hooks.usePanelRuntimeState()`
|
|
81
|
+
- `hooks.usePanelSamples()`
|
|
82
|
+
- `hooks.usePanelSamplesView()`
|
|
83
|
+
- `hooks.usePanelSelectedSamples()`
|
|
84
|
+
- `hooks.usePanelSelection()`
|
|
85
|
+
- `hooks.usePanelUiState()`
|
|
86
|
+
- `hooks.useTool(uri)`
|
|
87
|
+
- `createClient(workspaceId)`
|
|
88
|
+
|
|
89
|
+
Important distinction:
|
|
90
|
+
|
|
91
|
+
- `usePanelSamplesView()` gives access to host-managed collection state and is the best hook for panels that should stay synchronized with the visible HyperView UI.
|
|
92
|
+
- `usePanelHostState()` gives low-level read access to the same host state used by built-in panels, without importing frontend internals.
|
|
93
|
+
- `usePanelClient()` or `createClient()` is the escape hatch for direct backend reads and control-plane calls.
|
|
94
|
+
- `useTool(uri)` calls an installed backend tool registered by an extension and returns `{ loading, result, error, run, reset }`.
|
|
95
|
+
|
|
96
|
+
### Hook return shapes
|
|
97
|
+
|
|
98
|
+
Verified against the current `panel-sdk` surface:
|
|
99
|
+
|
|
100
|
+
- `usePanelSelection()` → `{ selectedIds: string[], selectionSource: SelectionUpdateSource }`
|
|
101
|
+
- `usePanelCommands()` → `{ setLabelFilter, setHoveredId, clearLassoSelection, clearSelection(): void, setSelection(ids, { source?, persist?, clearLasso? }): Promise<RuntimeSnapshot | null>, showSimilar({ sampleId, layoutKey?, spaceKey?, k?, source?, focus?, persist? }): Promise<RuntimeSnapshot | null>, setActiveLayout(layoutKey, { persist? }): Promise<RuntimeSnapshot | null>, setLayoutViewCamera(layoutKey, camera3d): void, setLayoutViewCameraPersisted(layoutKey, camera3d): Promise<null>, focusPanel(panelId): boolean, focusBuiltin(role): boolean, focusPanelByRole(role): boolean, closePanel(panelId): boolean }`
|
|
102
|
+
- `usePanelHover()` → `{ hoveredId, setHoveredId(id), clearHover() }`
|
|
103
|
+
- `usePanelLayoutView(layoutKey?)` → `{ layoutKey, view, camera3d, setCamera3d(camera3d) }`
|
|
104
|
+
- `usePanelLayouts()` → `{ layouts, spaces, get(layoutKey), getSpace(spaceKey), find(query), filter(query) }`; query supports `layoutKey`, `spaceKey`, `geometry`, `modelId`, and `dimension`.
|
|
105
|
+
- `usePanelSelectedSamples({ includeThumbnails? })` → `{ selectedIds, samples, loading, error }`
|
|
106
|
+
- `usePanelRuntimeState()` → `{ activeWorkspaceId, runtimeDatasetName, activeLayoutKey, activeSimilarityQuery, requestedLayoutKey, workspaces, customPanels, viewRevision, layoutViews }`
|
|
107
|
+
- `usePanelHostState()` → grouped low-level host state: `{ instance, runtime, datasetInfo, samples, samplesView, selection, hover, ui, filters, lasso, neighbors }`
|
|
108
|
+
- `usePanelProps()` → props supplied by the concrete `hv.ui.ExtensionPanel(...)` instance
|
|
109
|
+
- `usePanelUiState()` → `{ sampleGridSize, setSampleGridSize, scatterLabelOverlayMode, setScatterLabelOverlayMode }`
|
|
110
|
+
- `usePanelDatasetInfo()` / `usePanelSamples()` / `usePanelSamplesView()` → host-managed dataset and view state
|
|
111
|
+
- `useTool(uri)` → `{ loading: boolean, result: TResult | null, error: string | null, run(params?): Promise<TResult | null>, reset(): void }`
|
|
112
|
+
- `usePanelClient()` → low-level client; pair with `createClient(workspaceId)` for direct API calls. Useful methods include `querySamples`, `aggregateSamples`, `getSamplesByIds`, `searchSimilar`, `setSimilarityQuery`, `clearSimilarityQuery`, `setSelection`, and `selectSamples`.
|
|
113
|
+
|
|
114
|
+
To clear the current selection from a panel and persist it to the runtime, use `await usePanelCommands().setSelection([])`. Pass `{ persist: false }` only for local transient UI changes.
|
|
115
|
+
|
|
116
|
+
## Placement
|
|
117
|
+
|
|
118
|
+
Extension-backed panel instances can be added in:
|
|
119
|
+
|
|
120
|
+
- `right`
|
|
121
|
+
- `bottom`
|
|
122
|
+
- `center`
|
|
123
|
+
|
|
124
|
+
Center placement lets a runtime panel behave like a normal center tab.
|
|
125
|
+
|
|
126
|
+
## CLI Registration
|
|
127
|
+
|
|
128
|
+
Register the extension, then instantiate a panel module into a running workspace:
|
|
129
|
+
|
|
130
|
+
```bash
|
|
131
|
+
hyperview extension add .hyperview/extensions/label-histogram \
|
|
132
|
+
--workspace imagenette-cli-20260412
|
|
133
|
+
|
|
134
|
+
hyperview ui panel add \
|
|
135
|
+
--host 127.0.0.1 \
|
|
136
|
+
--port 6262 \
|
|
137
|
+
--workspace imagenette-cli-20260412 \
|
|
138
|
+
--panel-id label-histogram \
|
|
139
|
+
--extension label-histogram \
|
|
140
|
+
--extension-panel label-histogram \
|
|
141
|
+
--position right
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
## Verification
|
|
145
|
+
|
|
146
|
+
After `hyperview ui panel add --extension ...`:
|
|
147
|
+
|
|
148
|
+
- `curl 'http://127.0.0.1:6262/api/runtime?workspace_id=<ws>'` should list the panel under `workspace.ui.custom_panels[*]` with `data.module_src` set to a `/api/panels/content/<ws>/<panel-id>/<file>` URL.
|
|
149
|
+
- Fetching `data.module_src` should return `application/javascript` with your module body.
|
|
150
|
+
- The panel should appear in the live UI in the requested `position` slot.
|
|
151
|
+
|
|
152
|
+
## Good Practices
|
|
153
|
+
|
|
154
|
+
- Prefer panel modules over HTML or iframe content.
|
|
155
|
+
- Use `usePanelSamplesView()` for view-synchronized behavior.
|
|
156
|
+
- Use `usePanelCommands()` for host interactions such as label filtering or selection changes.
|
|
157
|
+
- Use `usePanelHostState()` when a custom panel needs low-level synchronized host state such as hover, selection, lasso, neighbors, layout views, or active workspace context.
|
|
158
|
+
- Use `usePanelLayouts()` for layout/space lookup instead of scanning `datasetInfo.layouts` by hand.
|
|
159
|
+
- Use `usePanelSelectedSamples()` for selected sample metadata instead of manually watching selected ids and fetching samples.
|
|
160
|
+
- Use `usePanelClient()` only for data that is not already available through the host state.
|
|
161
|
+
- Use `usePanelClient().querySamples(...)`, `aggregateSamples(...)`, or `selectSamples(...)` for dataset-wide behavior instead of fixed-limit client scans.
|
|
162
|
+
- Use `usePanelClient().searchSimilar(...)` instead of hand-building `/api/search/similar/...` URLs.
|
|
163
|
+
- Keep the panel self-contained under `.hyperview/extensions/<extension-name>/`.
|
|
164
|
+
- If the panel needs sibling assets, keep them next to the module and reference them with relative URLs.
|
|
165
|
+
- Do not render a second title/header inside a normal Dockview runtime panel unless there is a strong reason. Dockview already provides the tab title. Built-in center and runtime panels should usually start with the standardized `PanelToolbar` row.
|
|
166
|
+
|
|
167
|
+
## Current Limitation
|
|
168
|
+
|
|
169
|
+
Panel modules should currently be authored as browser-loadable JavaScript modules.
|
|
170
|
+
|
|
171
|
+
If an agent wants TypeScript or JSX ergonomics, it should bundle or transpile to JavaScript before registration.
|