hyperview 0.6.2__tar.gz → 1.0.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.
Files changed (123) hide show
  1. {hyperview-0.6.2 → hyperview-1.0.0}/.agents/skills/hyperview-cli/SKILL.md +46 -10
  2. {hyperview-0.6.2 → hyperview-1.0.0}/.agents/skills/hyperview-cli/references/commands.md +155 -6
  3. {hyperview-0.6.2 → hyperview-1.0.0}/.agents/skills/hyperview-cli/references/extensions.md +65 -44
  4. hyperview-1.0.0/.agents/skills/hyperview-cli/references/panel-modules.md +226 -0
  5. {hyperview-0.6.2 → hyperview-1.0.0}/.gitignore +8 -2
  6. {hyperview-0.6.2 → hyperview-1.0.0}/PKG-INFO +29 -9
  7. {hyperview-0.6.2 → hyperview-1.0.0}/README.md +23 -4
  8. {hyperview-0.6.2 → hyperview-1.0.0}/pyproject.toml +7 -3
  9. hyperview-1.0.0/src/hyperview/__init__.py +34 -0
  10. hyperview-1.0.0/src/hyperview/_compat.py +27 -0
  11. {hyperview-0.6.2 → hyperview-1.0.0}/src/hyperview/_version.py +2 -2
  12. {hyperview-0.6.2 → hyperview-1.0.0}/src/hyperview/api.py +404 -54
  13. {hyperview-0.6.2 → hyperview-1.0.0}/src/hyperview/cli.py +519 -135
  14. hyperview-1.0.0/src/hyperview/control/__init__.py +24 -0
  15. hyperview-1.0.0/src/hyperview/control/aliases.py +54 -0
  16. hyperview-1.0.0/src/hyperview/control/models.py +75 -0
  17. hyperview-1.0.0/src/hyperview/control/registry.py +86 -0
  18. hyperview-1.0.0/src/hyperview/control/runtime_commands.py +374 -0
  19. hyperview-1.0.0/src/hyperview/control/service.py +101 -0
  20. hyperview-1.0.0/src/hyperview/control/ui_panel.py +902 -0
  21. {hyperview-0.6.2 → hyperview-1.0.0}/src/hyperview/core/dataset.py +397 -18
  22. {hyperview-0.6.2 → hyperview-1.0.0}/src/hyperview/core/sample.py +42 -13
  23. {hyperview-0.6.2 → hyperview-1.0.0}/src/hyperview/core/selection.py +13 -1
  24. {hyperview-0.6.2 → hyperview-1.0.0}/src/hyperview/embeddings/engine.py +84 -21
  25. {hyperview-0.6.2 → hyperview-1.0.0}/src/hyperview/embeddings/pipelines.py +57 -6
  26. {hyperview-0.6.2 → hyperview-1.0.0}/src/hyperview/embeddings/providers/lancedb_providers.py +64 -1
  27. hyperview-1.0.0/src/hyperview/extensions.py +421 -0
  28. hyperview-1.0.0/src/hyperview/panel_definitions.py +139 -0
  29. hyperview-1.0.0/src/hyperview/runtime.py +3226 -0
  30. {hyperview-0.6.2 → hyperview-1.0.0}/src/hyperview/server/app.py +643 -319
  31. hyperview-1.0.0/src/hyperview/server/security.py +144 -0
  32. hyperview-1.0.0/src/hyperview/server/static/404/index.html +1 -0
  33. hyperview-1.0.0/src/hyperview/server/static/404.html +1 -0
  34. hyperview-1.0.0/src/hyperview/server/static/__next.__PAGE__.txt +23 -0
  35. hyperview-1.0.0/src/hyperview/server/static/__next._full.txt +18 -0
  36. hyperview-1.0.0/src/hyperview/server/static/__next._tree.txt +2 -0
  37. hyperview-1.0.0/src/hyperview/server/static/_next/static/98olFRaLYmqH0ChUkGkaU/_clientMiddlewareManifest.js +1 -0
  38. hyperview-1.0.0/src/hyperview/server/static/_next/static/chunks/1si__g5rfxfy5.js +31 -0
  39. hyperview-1.0.0/src/hyperview/server/static/_next/static/chunks/1z1-ay5ba8832.js +8 -0
  40. hyperview-0.6.2/src/hyperview/server/static/_next/static/chunks/661a08547c83f565.js → hyperview-1.0.0/src/hyperview/server/static/_next/static/chunks/283_7pyqafe21.js +15 -15
  41. hyperview-1.0.0/src/hyperview/server/static/_next/static/chunks/2iw0scz5_gelo.css +2 -0
  42. hyperview-1.0.0/src/hyperview/server/static/_next/static/chunks/2l5mr6qhcmcif.js +22 -0
  43. hyperview-1.0.0/src/hyperview/server/static/_next/static/chunks/2zbk7fyb76ii0.js +1 -0
  44. hyperview-1.0.0/src/hyperview/server/static/_next/static/chunks/3xaos2q7f0t1a.js +1 -0
  45. hyperview-1.0.0/src/hyperview/server/static/_next/static/chunks/3xo3o0sovd-os.js +1 -0
  46. hyperview-1.0.0/src/hyperview/server/static/_next/static/chunks/turbopack-0iv3v71mo2dd1.js +1 -0
  47. hyperview-1.0.0/src/hyperview/server/static/_next/static/media/icon.0nasg43ry7r55.png +0 -0
  48. hyperview-1.0.0/src/hyperview/server/static/_not-found/__next._full.txt +16 -0
  49. hyperview-1.0.0/src/hyperview/server/static/_not-found/__next._not-found.__PAGE__.txt +22 -0
  50. hyperview-1.0.0/src/hyperview/server/static/_not-found/__next._tree.txt +2 -0
  51. hyperview-1.0.0/src/hyperview/server/static/_not-found/index.html +1 -0
  52. hyperview-1.0.0/src/hyperview/server/static/_not-found/index.txt +16 -0
  53. hyperview-1.0.0/src/hyperview/server/static/icon.png +0 -0
  54. hyperview-1.0.0/src/hyperview/server/static/index.html +1 -0
  55. hyperview-1.0.0/src/hyperview/server/static/index.txt +18 -0
  56. hyperview-1.0.0/src/hyperview/shipped_extensions/core/extension.toml +58 -0
  57. hyperview-1.0.0/src/hyperview/shipped_extensions/reference/extension.toml +25 -0
  58. hyperview-1.0.0/src/hyperview/shipped_extensions/reference/panel.jsx +54 -0
  59. hyperview-1.0.0/src/hyperview/shipped_extensions/reference/tools.py +17 -0
  60. hyperview-1.0.0/src/hyperview/static_export.py +1032 -0
  61. {hyperview-0.6.2 → hyperview-1.0.0}/src/hyperview/storage/backend.py +31 -0
  62. hyperview-1.0.0/src/hyperview/storage/fields.py +42 -0
  63. {hyperview-0.6.2 → hyperview-1.0.0}/src/hyperview/storage/lancedb_backend.py +41 -3
  64. {hyperview-0.6.2 → hyperview-1.0.0}/src/hyperview/storage/memory_backend.py +19 -2
  65. {hyperview-0.6.2 → hyperview-1.0.0}/src/hyperview/storage/schema.py +91 -2
  66. {hyperview-0.6.2 → hyperview-1.0.0}/src/hyperview/ui.py +32 -5
  67. hyperview-0.6.2/.agents/skills/hyperview-cli/references/panel-modules.md +0 -171
  68. hyperview-0.6.2/src/hyperview/__init__.py +0 -22
  69. hyperview-0.6.2/src/hyperview/extensions.py +0 -230
  70. hyperview-0.6.2/src/hyperview/runtime.py +0 -1732
  71. hyperview-0.6.2/src/hyperview/server/static/404/index.html +0 -1
  72. hyperview-0.6.2/src/hyperview/server/static/404.html +0 -1
  73. hyperview-0.6.2/src/hyperview/server/static/__next.__PAGE__.txt +0 -9
  74. hyperview-0.6.2/src/hyperview/server/static/__next._full.txt +0 -18
  75. hyperview-0.6.2/src/hyperview/server/static/__next._head.txt +0 -5
  76. hyperview-0.6.2/src/hyperview/server/static/__next._index.txt +0 -5
  77. hyperview-0.6.2/src/hyperview/server/static/__next._tree.txt +0 -3
  78. hyperview-0.6.2/src/hyperview/server/static/_next/static/_W0V_8-00bWcS7EniWKJf/_clientMiddlewareManifest.json +0 -1
  79. hyperview-0.6.2/src/hyperview/server/static/_next/static/chunks/1daeab61a412190e.js +0 -8
  80. hyperview-0.6.2/src/hyperview/server/static/_next/static/chunks/567993cf36cd4ab1.js +0 -5
  81. hyperview-0.6.2/src/hyperview/server/static/_next/static/chunks/57c4c11f21d10377.css +0 -3
  82. hyperview-0.6.2/src/hyperview/server/static/_next/static/chunks/86c1fc4cf542f408.js +0 -1
  83. hyperview-0.6.2/src/hyperview/server/static/_next/static/chunks/a6dad97d9634a72d.js.map +0 -1
  84. hyperview-0.6.2/src/hyperview/server/static/_next/static/chunks/e954ba82c0a04100.js +0 -1
  85. hyperview-0.6.2/src/hyperview/server/static/_next/static/chunks/eac713f252f03efd.js +0 -1
  86. hyperview-0.6.2/src/hyperview/server/static/_next/static/chunks/f29dd35a99c216ea.js +0 -1
  87. hyperview-0.6.2/src/hyperview/server/static/_next/static/chunks/turbopack-cb59e03a04a579d1.js +0 -4
  88. hyperview-0.6.2/src/hyperview/server/static/_next/static/media/1bffadaabf893a1e-s.7cd81963.woff2 +0 -0
  89. hyperview-0.6.2/src/hyperview/server/static/_next/static/media/2bbe8d2671613f1f-s.76dcb0b2.woff2 +0 -0
  90. hyperview-0.6.2/src/hyperview/server/static/_next/static/media/2c55a0e60120577a-s.2a48534a.woff2 +0 -0
  91. hyperview-0.6.2/src/hyperview/server/static/_next/static/media/5476f68d60460930-s.c995e352.woff2 +0 -0
  92. hyperview-0.6.2/src/hyperview/server/static/_next/static/media/83afe278b6a6bb3c-s.p.3a6ba036.woff2 +0 -0
  93. hyperview-0.6.2/src/hyperview/server/static/_next/static/media/9c72aa0f40e4eef8-s.18a48cbc.woff2 +0 -0
  94. hyperview-0.6.2/src/hyperview/server/static/_next/static/media/ad66f9afd8947f86-s.7a40eb73.woff2 +0 -0
  95. hyperview-0.6.2/src/hyperview/server/static/_not-found/__next._full.txt +0 -13
  96. hyperview-0.6.2/src/hyperview/server/static/_not-found/__next._head.txt +0 -5
  97. hyperview-0.6.2/src/hyperview/server/static/_not-found/__next._index.txt +0 -5
  98. hyperview-0.6.2/src/hyperview/server/static/_not-found/__next._not-found.__PAGE__.txt +0 -5
  99. hyperview-0.6.2/src/hyperview/server/static/_not-found/__next._not-found.txt +0 -4
  100. hyperview-0.6.2/src/hyperview/server/static/_not-found/__next._tree.txt +0 -2
  101. hyperview-0.6.2/src/hyperview/server/static/_not-found/index.html +0 -1
  102. hyperview-0.6.2/src/hyperview/server/static/_not-found/index.txt +0 -13
  103. hyperview-0.6.2/src/hyperview/server/static/index.html +0 -1
  104. hyperview-0.6.2/src/hyperview/server/static/index.txt +0 -18
  105. {hyperview-0.6.2 → hyperview-1.0.0}/LICENSE +0 -0
  106. {hyperview-0.6.2 → hyperview-1.0.0}/src/hyperview/core/__init__.py +0 -0
  107. {hyperview-0.6.2 → hyperview-1.0.0}/src/hyperview/embeddings/__init__.py +0 -0
  108. {hyperview-0.6.2 → hyperview-1.0.0}/src/hyperview/embeddings/compute.py +0 -0
  109. {hyperview-0.6.2 → hyperview-1.0.0}/src/hyperview/embeddings/projection.py +0 -0
  110. {hyperview-0.6.2 → hyperview-1.0.0}/src/hyperview/embeddings/providers/__init__.py +0 -0
  111. {hyperview-0.6.2 → hyperview-1.0.0}/src/hyperview/figures/__init__.py +0 -0
  112. {hyperview-0.6.2 → hyperview-1.0.0}/src/hyperview/figures/colors.py +0 -0
  113. {hyperview-0.6.2 → hyperview-1.0.0}/src/hyperview/figures/render.py +0 -0
  114. {hyperview-0.6.2 → hyperview-1.0.0}/src/hyperview/server/__init__.py +0 -0
  115. {hyperview-0.6.2/src/hyperview/server/static/_next/static/_W0V_8-00bWcS7EniWKJf → hyperview-1.0.0/src/hyperview/server/static/_next/static/98olFRaLYmqH0ChUkGkaU}/_buildManifest.js +0 -0
  116. {hyperview-0.6.2/src/hyperview/server/static/_next/static/_W0V_8-00bWcS7EniWKJf → hyperview-1.0.0/src/hyperview/server/static/_next/static/98olFRaLYmqH0ChUkGkaU}/_ssgManifest.js +0 -0
  117. /hyperview-0.6.2/src/hyperview/server/static/_next/static/chunks/a6dad97d9634a72d.js → /hyperview-1.0.0/src/hyperview/server/static/_next/static/chunks/0cz1d0mv5g_q7.js +0 -0
  118. {hyperview-0.6.2 → hyperview-1.0.0}/src/hyperview/skill_install.py +0 -0
  119. {hyperview-0.6.2 → hyperview-1.0.0}/src/hyperview/storage/__init__.py +0 -0
  120. {hyperview-0.6.2 → hyperview-1.0.0}/src/hyperview/storage/config.py +0 -0
  121. {hyperview-0.6.2 → hyperview-1.0.0}/src/hyperview/storage/geometry.py +0 -0
  122. {hyperview-0.6.2 → hyperview-1.0.0}/src/hyperview/storage/metrics.py +0 -0
  123. {hyperview-0.6.2 → hyperview-1.0.0}/src/hyperview/tools.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, browserless paper figure export, runtime jobs, ui layout set, ui selection set, ui panel add/update, extension add, tools run, panel modules, Python tools, and local HyperView extension workflows.
3
+ description: Use HyperView's control-plane CLI for hyperview serve, static workspace export, dataset create, workspace create, embeddings compute, layouts compute, browserless paper figure export, runtime jobs, ui layout set, ui selection set, ui panel add/update, extension add, tools run, panel modules, Python 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:
@@ -30,6 +30,7 @@ HyperView currently supports Python 3.10 through 3.13; `--python 3.12` keeps the
30
30
  - Register a custom embedding provider.
31
31
  - Compute embeddings or layouts without restarting the UI.
32
32
  - Export paper-ready static 3D embedding figures without opening the UI.
33
+ - Export read-only static demo bundles with `hyperview export`.
33
34
  - Switch the active workspace, layout, or selection in a running session.
34
35
  - Add, remove, or compose extension-backed panel instances.
35
36
  - Create, install, reload, or use a local extension with Python tools and browser panels.
@@ -43,7 +44,8 @@ HyperView currently supports Python 3.10 through 3.13; `--python 3.12` keeps the
43
44
  5. Submit embedding or layout jobs through the runtime.
44
45
  6. Use `hyperview ui ...` commands to switch what the live UI shows.
45
46
  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.
47
+ 8. Export read-only static demos with `hyperview export <workspace-id> --out bundle/`.
48
+ 9. For extensions, create an extension folder and install it into the running workspace.
47
49
 
48
50
  ## Current model
49
51
 
@@ -51,15 +53,36 @@ HyperView currently supports Python 3.10 through 3.13; `--python 3.12` keeps the
51
53
  - Datasets are created separately from workspaces.
52
54
  - The workspace owns the dataset selection.
53
55
  - `ui layout set` changes the active layout and opens the matching built-in scatter panel.
54
- - `ui similarity set` selects an anchor sample and pins the nearest-neighbor context to an explicit layout or space.
56
+ - Samples retrieval state lives under the runtime-managed Samples panel state. `ui samples retrieval set-anchor` selects an anchor sample and pins nearest-neighbor context to an explicit layout or space.
55
57
  - Runtime-added panels can be built-in samples panels, typed scatter instances bound to explicit layout keys, or extension-backed panel modules loaded into the host React tree.
56
- - Runtime-added panels use the stable `HyperViewPanelSDK` surface on `window`.
58
+ - Runtime control commands use canonical namespaced ids: `workspace.*`, `panel.<type>.*`, and `collection.*`. Older command ids remain deprecated aliases for compatibility only.
59
+ - Command results carry the runtime snapshot in a `CommandResult` envelope (`ok`, `command`, `result`, `workspace`, `snapshot`, `revision`, `error`). Frontends and agents should apply the returned snapshot instead of doing an immediate `/api/runtime` refetch.
60
+ - Runtime-added panels use the stable thin `HyperViewPanelSDK` surface on `window`.
57
61
  - Extensions are repo-local folders with `extension.toml`, optional Python tools, and optional panel modules.
58
- - Extension panels call Python tools through `HyperViewPanelSDK.hooks.useTool()` or `hyperview tools run`.
62
+ - Extension panels run control commands through the SDK command client; Python tools are still reachable through `hyperview tools run`.
59
63
  - 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(...)`.
64
+ - Extensions distributed with HyperView use the same manifest and source format as repo-local extensions. Install them with `hyperview extension add --shipped <name>` or `session.ui.add_shipped_extension(...)`; promotion must not require panel/tool source changes.
60
65
  - In practice, create datasets and workspaces before starting the runtime for that workspace.
61
66
  - `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
67
  - Paper figure defaults are square, white-background, opaque PNGs with a faint sphere guide and direct labels for small label sets.
68
+ - `hyperview export <workspace-id> --out bundle/` writes a self-contained **Shared Space**: a static frontend + JSON/API/media bundle. It is intentionally read-only with respect to durable workspace and backend/model operations, while keeping normal local exploration available: visitors can browse, select, pan/zoom, switch prepared cases, inspect panels, and use exported precomputed data. Backend-only affordances such as arbitrary text inference are hidden when unavailable. The host identifies this mode with the concise `Shared Space` label.
69
+
70
+ ## Session authentication
71
+
72
+ A running server mints a session token. Reads are open; runtime commands that
73
+ mutate state answer `401 Missing or invalid HyperView session token` without
74
+ it. This bites agents that talk to `/api/control/commands/run` directly.
75
+
76
+ - The CLI resolves the token itself, from `HYPERVIEW_API_TOKEN` or from the
77
+ discovery file `server-<port>.json` next to the datasets directory. Prefer
78
+ the CLI over raw HTTP and this stays invisible.
79
+ - For raw HTTP, send `Authorization: Bearer <token>` or `?token=<token>`.
80
+ - Set `HYPERVIEW_NO_AUTH=1` to declare the server public — a Hugging Face
81
+ Space has no way to hand a visitor a token, so panel adds 401 without it.
82
+ Public is not open: anonymous callers keep the viewer commands
83
+ (`workspace.panel.*`, `panel.*`, `collection.*`, selection, active layout)
84
+ and get 403 on provider registration, extension install, `tools run`, and
85
+ embedding/layout compute. Drive those with a token, not by widening the flag.
63
86
 
64
87
  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
88
  Read [references/panel-modules.md](references/panel-modules.md) when the task involves authoring a browser panel module.
@@ -72,28 +95,41 @@ Read [references/extensions.md](references/extensions.md) when the task involves
72
95
  - Prefer `workspace create --dataset ...` over separate create and dataset-attach calls when setting up a new workspace.
73
96
  - In Python dataset setup code, use public ingestion helpers such as `dataset.add_samples([...])` or `dataset.add_images_dir(...)`.
74
97
  - Prefer built-in providers before registering custom providers. For Hyper3-CLIP, use `dataset.compute_embeddings(model="hyper3-clip-v0.5", provider="hyper-models")`.
98
+ - In comparison demos, fail fast when a required model/provider cannot compute embeddings; do not silently substitute the baseline model as a "candidate" fallback.
75
99
  - When a project truly needs a custom Python provider, use `hyperview provider register ...` from the CLI or `hv.register_provider(...)` in Python.
76
100
  - For custom panel code, create an extension under `.hyperview/extensions/<extension-name>/`; do not register arbitrary panel module files directly.
77
101
  - For side-by-side embedding comparisons, add typed scatter panels through `hyperview ui panel add --kind scatter --layout-key ... --reference-panel-id ... --direction right`.
78
102
  - Use first-class view layout fields for panel sizing and visibility: `hv.ui.PanelLayout(width=..., min_width=...)` in Python, or `hyperview ui panel resize/move/focus/close/show` from the CLI. Do not pass Dockview-specific sizing through panel props.
103
+ - Runtime panel add/update/remove, sizing, placement, focus, visibility, and state commands share the same control path in CLI and Python. Use `hyperview ui panel ...` or `session.ui`/`session.control`; do not call raw panel-control HTTP routes from examples or demos.
104
+ - Live text retrieval is available only when `/api/dataset` exposes an index whose `query_modes` includes `text`. HyperView derives this from the provider attached to the current runtime, so a stored space labelled multimodal is not sufficient by itself. Use `Session.ui.query_by_text(...)` or the native Samples search box; both resolve to a text-capable index and reject an explicitly requested image-only space.
105
+ - When invoking raw commands, prefer canonical command names: `workspace.panel.add/update/remove/resize/move/focus/close/show`, `workspace.panel.state.get/patch`, `panel.samples.retrieval.*`, `collection.neighbors.create`, and `collection.filter.set`. Treat legacy `ui.*` command ids as deprecated aliases.
79
106
  - To retitle an existing runtime panel or replace its props, use `hyperview ui panel update --panel-id ... --title ... --props-json ...` instead of remove/re-add when preserving panel identity matters.
80
- - 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.
107
+ - For nearest-neighbor comparisons, use `hyperview ui samples retrieval set-anchor --sample-id ... --layout-key ...` or run `panel.samples.retrieval.set-anchor` / `collection.neighbors.create` through the SDK command client; do not infer neighbor space from whichever scatter panel is focused.
108
+ - For collection-backed Samples panel actions, use `hyperview panel samples show-results ...`, `hyperview panel samples reset`, `hyperview panel samples show-neighbors ...`, and `hyperview panel labels filter ...`; read the returned `result.collection_id` and `result.collection` when relevant. Use the canonical panel id `samples` for the primary shared search/result surface. When a prepared static workspace needs two independent result panes, bind each `hv.ui.Samples` panel with `props={"mode": "results", "collectionId": collection_id}` and update that documented prop through `usePanelActions()`.
109
+ - Use `hyperview ui panel state get/patch` or SDK `usePanelState()` when a panel needs durable panel-owned state. Keep durable state under runtime panel state instead of browser local storage or ad hoc events.
110
+ - For reset controls in panels, run the relevant runtime command through the SDK command client when both selection and nearest-neighbor context should be cleared.
111
+ - Do not use timers or browser storage to wait for panel readiness or guard startup state. Write the intended state through runtime commands or `usePanelState()`.
112
+ - In panel modules, use `hooks.useSampleResults()` to present a curated set in the canonical Samples panel and synchronize selection/focus. Use `hooks.usePanelActions().updateProps(panelId, props)` when one panel needs to update another panel's documented props, and `hooks.usePanelActions().focusPanel(panelId)` when a user action should activate the relevant sibling panel. These helpers work as durable runtime mutations in full mode and ephemeral client-side interactions in static mode; do not hand-roll panel-control requests or raw command envelopes for these common flows.
81
113
  - 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.
82
114
  - For demos/spaces that launch HyperView from Python, compose panels with `hv.ui.Horizontal`, `hv.ui.Vertical`, `hv.ui.Tabs`, `hv.ui.Grid`, `hv.ui.Scatter`, `hv.ui.Samples`, `hv.ui.ExtensionPanel`, and `hv.ui.PanelLayout`; keep extension manifests focused on reusable panel/tool definitions.
115
+ - An explicit Samples- or Extension-only `hv.ui.View` can launch from dataset records without an embedding or layout. Only include a Scatter panel when the demo genuinely needs a visualization; Scatter views still require a layout or embedding space.
83
116
  - Keep layout orchestration out of panel modules. A panel should not close, hide, or rearrange sibling panels on mount; use `hv.ui.View(...)` or `hyperview ui panel ...` to compose the workspace.
84
- - Treat local `focusPanel` and `closePanel` as transient user-action helpers, not as startup layout machinery. For durable control from a panel, use SDK commands such as `setActivePanel`, `setPanelVisible`, `resizePanel`, and `movePanel`.
117
+ - Treat host focus/resize helpers as transient user-action helpers, not as startup layout machinery. For durable control from a panel, run the corresponding `workspace.panel.*` command.
85
118
  - Pass only documented panel props through `hv.ui.ExtensionPanel(..., props=...)`.
86
119
  - Tools can write files under `ctx.extension_storage` and return `ctx.url_for(path)` for panel-renderable artifact URLs.
87
120
  - Put query results, benchmark tables, contact sheets, and other generated artifacts behind extension tools or compact panel props. Do not embed large base64 payloads or generated datasets inside panel JavaScript.
88
121
  - Keep cross-panel coordination in host/runtime state. Do not use `window.dispatchEvent` / `window.addEventListener` as shared panel state.
89
- - Keep extensions self-contained: `extension.toml`, `tools.py`, `panel.js` or `panel.jsx`, and any local assets in the same folder.
122
+ - Keep extensions self-contained: `extension.toml`, tools, a `panel.jsx` module (preferred over `.js`), and any local assets in the same folder.
90
123
  - Prefer `--json` output when chaining commands or inspecting results programmatically.
91
124
  - Wait for embedding/layout jobs to finish before issuing layout-switch commands that depend on their results.
92
125
  - Use `hyperview jobs list` or `hyperview jobs inspect <job-id>` if a compute command is long-running or you started it with `--no-wait`.
93
126
  - For provider args, use repeated `--provider-arg key=value` flags.
94
127
  - Treat the workspace as the durable unit. Changing datasets means setting a new workspace dataset, not switching among many datasets inside one workspace.
95
128
  - Prefer panel modules over raw HTML. The panel system no longer relies on iframes.
129
+ - Author custom panels as `panel.jsx` using `window.HyperViewPanelSDK` public hooks only. HyperView standardizes the data and interaction contract (props, selection, collections, sample results, sibling `updateProps`, panel state), not the panel's visual design. A panel is free to render any JSX, CSS, SVG, Canvas, or WebGL experience that fits its purpose.
130
+ - Do not reach for private runtime/frontend APIs from extension panels. If a behavior is not on the public SDK or CLI/API surface, do not invent a side channel.
96
131
  - For paper diagrams, prefer `hyperview figure export` over browser screenshots unless the user explicitly needs exact UI chrome.
132
+ - For public, read-only examples-gallery demos, create a Shared Space with `hyperview export <workspace-id> --out bundle/` instead of keeping a Python server awake. When a bundle belongs below a containing static site, pass its exact URL prefix with `--mount-path /spaces/<slug>` and copy the resulting bundle into that path. Use **Live Space** for the runtime-connected deployment that can run new queries, providers, and workspace mutations.
97
133
  - 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.
98
134
  - The first `uv run hyperview ...` invocation in a session can take 30+ seconds (torch/datasets imports). Allow generous timeouts and avoid sending SIGINT.
99
135
 
@@ -101,8 +137,8 @@ Read [references/extensions.md](references/extensions.md) when the task involves
101
137
 
102
138
  The runtime exposes JSON discovery endpoints alongside the CLI. Use them to obtain layout keys, sample IDs, and registered tools/panels for follow-up commands:
103
139
 
104
- - `GET /api/runtime?workspace_id=<ws>` &mdash; full snapshot. Read `workspace.ui.active_layout_key`, `workspace.ui.selected_ids`, `workspace.ui.custom_panels[*].data.module_src`, and registered `extensions`/`tools`.
140
+ - `GET /api/runtime?workspace_id=<ws>` &mdash; full snapshot. Read `workspace.ui.active_layout_key`, `workspace.ui.selected_ids`, `workspace.ui.panels`, `workspace.ui.custom_panels[*].state`, `workspace.ui.custom_panels[*].data.module_src`, and registered `extensions`/`tools`.
105
141
  - `GET /api/embeddings?workspace_id=<ws>` &mdash; 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 ...`.
106
142
  - `GET /api/tools` &mdash; registered tool URIs (also returned by `hyperview tools list --json`).
107
143
 
108
- Prefer layout metadata over parsing layout-key strings. Use `/api/dataset`, `usePanelLayouts()`, or `dataset.list_layouts()` when filtering by geometry, dimension, model, or space.
144
+ Prefer layout metadata over parsing layout-key strings. Use `/api/dataset`, exported runtime snapshots, or `dataset.list_layouts()` when filtering by geometry, dimension, model, or space.
@@ -60,6 +60,17 @@ hyperview dataset create cifar10_demo \
60
60
  --label-key label
61
61
  ```
62
62
 
63
+ Create a multimodal dataset with captions:
64
+
65
+ ```bash
66
+ hyperview dataset create coco_captions_demo \
67
+ --hf-dataset HuggingFaceM4/COCO \
68
+ --split train \
69
+ --image-key image \
70
+ --text-key sentences \
71
+ --samples 500
72
+ ```
73
+
63
74
  Create a persisted dataset from a local image directory:
64
75
 
65
76
  ```bash
@@ -204,6 +215,71 @@ hyperview figure export figures/embedding-panel-a.png \
204
215
  --title "ArcFace spherical embeddings"
205
216
  ```
206
217
 
218
+ ## Shared Spaces
219
+
220
+ Export a read-only, self-contained Shared Space for a workspace:
221
+
222
+ ```bash
223
+ hyperview export research --out dist/research-demo
224
+ ```
225
+
226
+ When the bundle will be copied below another static site, declare its stable
227
+ mount path during export:
228
+
229
+ ```bash
230
+ hyperview export research \
231
+ --out dist/research-demo \
232
+ --mount-path /spaces/research
233
+ ```
234
+
235
+ The exporter rebases the frontend shell and records `/spaces/research` in
236
+ `hyperview-static.json`. Copy the bundle contents into that exact directory
237
+ inside the containing site's document root. Static API, media, and panel-module
238
+ requests remain scoped to the mounted bundle; no proxy, cookie, or referrer
239
+ routing is required.
240
+
241
+ Sample similarity is omitted by default. Enable a bounded precomputed index
242
+ when the demo exposes nearest-neighbor browsing:
243
+
244
+ ```bash
245
+ hyperview export research --out dist/research-demo --similarity-k 25
246
+ ```
247
+
248
+ The bundle contains the packaged static frontend, `api/runtime.json`,
249
+ `api/dataset.json`, sample shards under `api/samples/`, media and thumbnails,
250
+ layout coordinate JSON under `api/embeddings/`, materialized collection items
251
+ under `api/collections/`, and extension panel modules under
252
+ `api/panels/content/`. It also writes a versioned `hyperview-static.json`
253
+ manifest and a static-assets-only `wrangler.jsonc` configuration. Deploy the
254
+ bundle to Cloudflare from its output directory with:
255
+
256
+ ```bash
257
+ npx wrangler deploy --config wrangler.jsonc
258
+ ```
259
+
260
+ The generated `index.html` sets `window.__HYPERVIEW_STATIC__ = true`. In this
261
+ mode the frontend reads JSON files from the bundle. Selection, prepared-case
262
+ panel prop changes, panel state, filtering, and result presentation remain
263
+ ephemeral client-side interactions. Durable workspace writes, Python tools,
264
+ model execution, and arbitrary inference/search are unavailable; controls for
265
+ those capabilities are hidden. The host shows the notice
266
+ `Shared Space`.
267
+
268
+ Python launch/session code can export the same bundle:
269
+
270
+ ```python
271
+ session = hv.launch(dataset, block=False)
272
+ session.export("dist/research-demo", workspace_id="research", similarity_k=25)
273
+ ```
274
+
275
+ For persisted workspaces, use the top-level API:
276
+
277
+ ```python
278
+ import hyperview as hv
279
+
280
+ hv.export_workspace("research", "dist/research-demo")
281
+ ```
282
+
207
283
  ## Runtime UI
208
284
 
209
285
  Discover an existing layout key and sample IDs before mutating runtime state:
@@ -215,6 +291,17 @@ curl --max-time 2 'http://127.0.0.1:6262/api/embeddings?workspace_id=research' |
215
291
 
216
292
  If no layout exists yet (`active_layout_key` is `null` and `/api/embeddings` returns nothing), create one with `hyperview embeddings compute ... --layout euclidean:2d` (creates embeddings + layout) or `hyperview layouts compute ... --space-key <space-key> --layout euclidean:2d` (adds a layout to an existing embedding space).
217
293
 
294
+ Runtime command ids are namespaced:
295
+
296
+ - `workspace.*` for workspace/view/panel placement and panel-owned state storage
297
+ - `panel.<type>.*` for panel-owned transitions such as Samples retrieval
298
+ - `collection.*` for materialized filters, neighbors, and query result sets
299
+
300
+ Every control command returns a `CommandResult` envelope with `ok`, `command`,
301
+ `result`, `workspace`, `snapshot`, `revision`, and optional `error`. Apply the
302
+ returned `snapshot` when present. Do not issue an immediate `/api/runtime`
303
+ refetch unless a legacy endpoint did not return a snapshot.
304
+
218
305
  Switch the live UI to a layout and selection:
219
306
 
220
307
  ```bash
@@ -224,12 +311,18 @@ hyperview ui selection set --workspace research --ids sample-1,sample-8
224
311
 
225
312
  `--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.
226
313
 
227
- Add a custom panel through an extension:
314
+ Add a custom panel through an extension. Panel add/update/remove and panel
315
+ layout controls share HyperView's public control command path; prefer these CLI
316
+ commands or the matching Python `session.ui` helpers in examples.
228
317
 
229
318
  ```bash
230
319
  hyperview extension add .hyperview/extensions/label-histogram \
231
320
  --workspace research
232
321
 
322
+ # The same manifest/source format can be distributed with HyperView.
323
+ hyperview extension add --shipped <extension-name> \
324
+ --workspace research
325
+
233
326
  hyperview ui panel add \
234
327
  --workspace research \
235
328
  --panel-id label-histogram \
@@ -328,6 +421,22 @@ hyperview ui panel close --workspace research --panel-id notes
328
421
  hyperview ui panel show --workspace research --panel-id notes
329
422
  ```
330
423
 
424
+ Read or patch durable panel-owned state:
425
+
426
+ ```bash
427
+ hyperview ui panel state get \
428
+ --workspace research \
429
+ --panel-id samples \
430
+ --json
431
+
432
+ hyperview ui panel state patch \
433
+ --workspace research \
434
+ --panel-id samples \
435
+ --state-json '{"settings":{"density":"compact"}}' \
436
+ --expected-revision 0 \
437
+ --json
438
+ ```
439
+
331
440
  Remove a runtime panel by id:
332
441
 
333
442
  ```bash
@@ -336,20 +445,60 @@ hyperview ui panel remove \
336
445
  --panel-id hycoclip-poincare
337
446
  ```
338
447
 
339
- Pin nearest-neighbor results to a specific embedding layout:
448
+ Pin nearest-neighbor results to the Samples panel state for a specific embedding layout:
340
449
 
341
450
  ```bash
342
- hyperview ui similarity set \
451
+ hyperview ui samples retrieval set-anchor \
343
452
  --workspace research \
344
453
  --sample-id <sample-id> \
345
- --layout-key <layout-key> \
454
+ --index-id space:<space-key> \
455
+ --k 18
456
+
457
+ hyperview ui samples retrieval set-k \
458
+ --workspace research \
459
+ --k 36
460
+
461
+ hyperview ui samples retrieval set-text \
462
+ --workspace research \
463
+ --query "a dog playing in the park" \
464
+ --index-id space:<space-key> \
346
465
  --k 18
347
466
  ```
348
467
 
349
- Clear the explicit nearest-neighbor context:
468
+ Clear the explicit Samples retrieval context:
350
469
 
351
470
  ```bash
352
- hyperview ui similarity clear --workspace research
471
+ hyperview ui samples retrieval clear --workspace research
472
+ ```
473
+
474
+ Use `hyperview ui samples retrieval ...` for compatibility with existing CLI
475
+ flows. Raw commands should use the canonical `panel.samples.retrieval.*`
476
+ command ids.
477
+
478
+ Use panel collection shortcuts when the desired outcome is a Samples panel collection:
479
+
480
+ ```bash
481
+ hyperview panel samples show-results \
482
+ --workspace research \
483
+ --sample-id sample-1 \
484
+ --sample-id sample-8 \
485
+ --json
486
+
487
+ hyperview panel samples reset --workspace research --json
488
+
489
+ hyperview panel samples show-neighbors \
490
+ --workspace research \
491
+ --sample-id <sample-id> \
492
+ --index-id space:<space-key> \
493
+ --k 18 \
494
+ --json
495
+
496
+ hyperview panel labels filter \
497
+ --workspace research \
498
+ --value cat \
499
+ --json
500
+
501
+ hyperview panel labels filter --workspace research --clear
353
502
  ```
354
503
 
355
504
  ## Extensions and Tools
@@ -45,6 +45,15 @@ position = "right"
45
45
  file = "panel.jsx"
46
46
  ```
47
47
 
48
+ Browser-only panels are static-compatible by default. A panel that requires a
49
+ live API or Python tool must declare that requirement so static exports can keep
50
+ the panel in the view without publishing an unusable module:
51
+
52
+ ```toml
53
+ static_compatible = false
54
+ static_reason = "Requires the selection_profile.summarize Python tool."
55
+ ```
56
+
48
57
  Valid panel positions are `right`, `bottom`, and `center`.
49
58
 
50
59
  Treat `position` as a weak default for where the panel usually belongs. Cross-panel
@@ -101,65 +110,64 @@ Use `ctx.dataset` for active dataset reads, `ctx.workspace` for workspace UI sta
101
110
 
102
111
  ## Browser Panel
103
112
 
104
- Panel modules must be browser-loadable JavaScript modules. They export a default React component or named `Panel`, and use `globalThis.HyperViewPanelSDK`.
113
+ Prefer `panel.jsx`. Modules export a default React component or named `Panel`,
114
+ and must use only `globalThis.HyperViewPanelSDK` public hooks. Prioritize the
115
+ data/interaction contract (props, selection, collections, sample results,
116
+ sibling prop updates, panel state) over visual polish.
105
117
 
106
- ```js
118
+ ```jsx
107
119
  const sdk = globalThis.HyperViewPanelSDK;
108
120
  if (!sdk) throw new Error("HyperViewPanelSDK is not available on window.");
109
121
 
110
- const { React, components, hooks } = sdk;
111
- const { Panel, PanelToolbar, PanelToolbarButton } = components;
112
- const { usePanelSelection, useTool } = hooks;
122
+ const { React, hooks } = sdk;
123
+ const { useSelection, usePanelState } = hooks;
113
124
 
114
125
  export default function SelectionProfilePanel() {
115
- const { selectedIds } = usePanelSelection();
116
- const profile = useTool("selection_profile.summarize");
126
+ const { selectedIds } = useSelection();
127
+ const { state, patchState } = usePanelState();
117
128
  const selectionKey = selectedIds.join("|");
118
129
 
119
130
  React.useEffect(() => {
120
- profile.run({ sample_ids: selectedIds });
121
- }, [profile.run, selectionKey]);
122
-
123
- const result = profile.result;
124
-
125
- return React.createElement(
126
- Panel,
127
- { className: "h-full" },
128
- React.createElement(PanelToolbar, {
129
- items: [
130
- { id: "selection", label: "Selection", value: String(selectedIds.length) },
131
- { id: "status", label: "Status", value: profile.loading ? "running" : result ? "ready" : "idle" },
132
- ],
133
- actions: React.createElement(PanelToolbarButton, { onClick: () => profile.run({ sample_ids: selectedIds }) }, "Refresh"),
134
- }),
135
- React.createElement("pre", { style: { padding: 12, overflow: "auto" } }, JSON.stringify(result, null, 2))
131
+ patchState({ last_selection: selectedIds });
132
+ }, [patchState, selectionKey]);
133
+
134
+ return (
135
+ <main style={{ padding: 12, font: "12px system-ui" }}>
136
+ <div>{`Selected: ${selectedIds.length}`}</div>
137
+ <pre>{JSON.stringify(state, null, 2)}</pre>
138
+ </main>
136
139
  );
137
140
  }
138
141
  ```
139
142
 
140
- Available SDK hooks include `usePanelRuntimeState`, `usePanelHostState`, `usePanelDatasetInfo`, `usePanelSamplesView`, `usePanelSelectedSamples`, `usePanelSelection`, `usePanelHover`, `usePanelLayouts`, `usePanelLayoutView`, `usePanelCommands`, `usePanelUiState`, `usePanelClient`, and `useTool`.
141
-
142
- For dataset-wide panel behavior, prefer `usePanelClient().querySamples(...)`,
143
- `aggregateSamples(...)`, `selectSamples(...)`, `getSamplesByIds(...)`,
144
- `searchSimilar(...)`, or an extension tool over scanning a fixed
145
- `listSamples({ limit: ... })` page or hand-building API URLs in the browser.
146
- Sample reads default to `includeThumbnails: false`; use each sample's
147
- `thumbnail_url` for images, and request inline thumbnails only when a panel
148
- explicitly needs base64 data.
149
-
150
- Use `usePanelHostState()` for synchronized host state. Use narrower hooks such as `usePanelSelection()`,
151
- `usePanelSelectedSamples()`, `usePanelHover()`, `usePanelLayouts()`, and
152
- `usePanelLayoutView()` when the panel only needs one part of that state. Use
153
- `usePanelCommands()` for host writes. Selection and active-layout changes
154
- update host state immediately and persist to runtime UI state in the
155
- background by default. Pass `{ persist: true }` only when the caller must wait
156
- for durable runtime state, and pass `{ persist: false }` for local transient UI
157
- changes.
143
+ Available SDK hooks are intentionally thin: `useCommandClient`, `usePanelState`,
144
+ `usePanelActions`, `useSelection`, `useSampleResults`, `useCollection`,
145
+ `useSamples`, `useTool`, `listTools`, and `useHostAdapter`. See
146
+ [panel-modules.md](panel-modules.md) for return shapes.
147
+
148
+ For dataset-wide panel behavior, prefer runtime collections and
149
+ `useSamples(collectionId)` over scanning a fixed page or hand-building API URLs
150
+ in the browser. When a panel needs a new filtered or nearest-neighbor result
151
+ set, run `collection.filter.set`, `collection.neighbors.create`, or
152
+ `panel.samples.retrieval.*` through `useCommandClient()`.
153
+
154
+ Use `useSelection()` for synchronized selection state. Use `usePanelState()` for
155
+ panel-owned props/state. Use `usePanelActions().updateProps(...)` for documented
156
+ sibling panel prop changes (including prepared-case switching in static exports).
157
+ For two independent prepared result panes, construct each native Samples panel
158
+ with `props={{"mode": "results", "collectionId": collection_id}}`; then switch
159
+ the bound collection with `updateProps(panelId, { mode: "results", collectionId })`.
160
+ Result mode preserves prepared order, shows rank numbers, and suppresses the
161
+ live text-search bar. Use `useSampleResults()` instead when one canonical
162
+ Samples panel should own the shared result surface.
163
+ Use `useHostAdapter()` only for transient host actions such as focus; durable
164
+ layout/state changes should go through `workspace.*` commands. In static
165
+ exports, mutating backend commands are disabled, while selection and panel
166
+ state patches remain client-side and ephemeral.
158
167
 
159
168
  Do not use browser globals such as `window.dispatchEvent` to synchronize panels,
160
- and use SDK commands for control-plane writes.
161
-
162
- `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.
169
+ and use SDK commands for control-plane writes. Python tools are invoked with
170
+ `hyperview tools run` or from the panel via `useTool()` when the host exposes it.
163
171
 
164
172
  ## CLI Workflow
165
173
 
@@ -180,6 +188,19 @@ hyperview extension add .hyperview/extensions/selection-profile \
180
188
  Installing an extension registers its tools and panel definitions. To instantiate
181
189
  a panel from the CLI, add an extension-backed panel instance:
182
190
 
191
+ Extensions distributed with HyperView use the same folder, manifest, panel,
192
+ tool, props, state, command, query, and static-export contracts. Install one by
193
+ name without locating its package folder:
194
+
195
+ ```bash
196
+ hyperview extension add --shipped <extension-name> \
197
+ --workspace research \
198
+ --json
199
+ ```
200
+
201
+ Promotion from repo-local to shipped distribution must not require changes to
202
+ the extension's panel or tool source.
203
+
183
204
  ```bash
184
205
  hyperview ui panel add \
185
206
  --workspace research \