Add ad-hoc file open (ephemeral preview/edit outside the library) #34

Merged
parkerhdavis merged 3 commits from adhoc-file-open into main 2026-05-30 02:26:07 -06:00
parkerhdavis commented 2026-05-30 02:25:37 -06:00 (Migrated from github.com)

Lets a user point Garnet at a single file outside every library root and get the full preview + editor surfaces on it ad-hoc, without ingesting it into the catalog — a direct expression of Garnet's "surface over local files, no forced ingestion" principle. The file is opened as an ephemeral asset (a virtual Asset with no DB row).

This is Phase 1 (the 80%) of the design in 90-99 Agents/Transient/Ad-Hoc File Open Plan.md. Also includes an app-icon refresh and a version bump to 0.2.0.

Backend

  • describe_file(path) -> Asset: stats a loose file and returns the usual Asset shape with sentinel ids (-1) and root_path = dirname / relative_path = basename, so absPathFor() reconstructs the real path and every path-addressed call site works unchanged.

Frontend

  • New /preview?path= and /edit?path= routes mount AssetDetailPage / EditorPage in ephemeral mode (pages branch on the route's path param).
  • Ephemeral image + model previews and the editor's original-image src route through the loopback media server instead of asset://, since the file may sit outside the asset-protocol scope allow-list.
  • id-only features degrade: native-metadata + tag panels collapse into an "Add to library" upsell; model-thumbnail persistence is skipped.
  • "Add to library" upgrade path registers the file's parent folder as a library root, scans it, and re-resolves the now-indexed file to /asset/:id.
  • Entry points: Cmd/Ctrl+O global hotkey, an "Open file…" sidebar action above Workspaces, and an "Open a file" CTA in the library empty-state.
  • New shared lib/previewFormats.ts (preview-capable extension sets, moved out of AssetDetailPage) and lib/ephemeral.ts (routes, file picker, add-to-library orchestration).

Known caveat

Multi-file glTF (a .gltf referencing sidecar .bin/textures by relative URL) won't resolve its sidecars through the ephemeral media-server URL; single-file models (.glb/.obj/.stl/.ply/.fbx/.usdz, embedded .gltf) are fine, and catalog models are unaffected. Documented in the plan doc with a fix sketch.

Verification

tsc --noEmit, Biome, cargo clippy -D warnings, and 127 backend + 13 frontend tests all green.

Phases 2 (drag-and-drop, recents) and 3 (OS "Open with Garnet" file associations) are not started.

Lets a user point Garnet at a single file *outside* every library root and get the full preview + editor surfaces on it ad-hoc, **without ingesting it into the catalog** — a direct expression of Garnet's "surface over local files, no forced ingestion" principle. The file is opened as an *ephemeral* asset (a virtual `Asset` with no DB row). This is Phase 1 (the 80%) of the design in `90-99 Agents/Transient/Ad-Hoc File Open Plan.md`. Also includes an app-icon refresh and a version bump to 0.2.0. ## Backend - `describe_file(path) -> Asset`: stats a loose file and returns the usual `Asset` shape with sentinel ids (`-1`) and `root_path = dirname` / `relative_path = basename`, so `absPathFor()` reconstructs the real path and every path-addressed call site works unchanged. ## Frontend - New `/preview?path=` and `/edit?path=` routes mount `AssetDetailPage` / `EditorPage` in ephemeral mode (pages branch on the route's `path` param). - Ephemeral image + model previews and the editor's original-image src route through the loopback media server instead of `asset://`, since the file may sit outside the asset-protocol scope allow-list. - id-only features degrade: native-metadata + tag panels collapse into an "Add to library" upsell; model-thumbnail persistence is skipped. - "Add to library" upgrade path registers the file's parent folder as a library root, scans it, and re-resolves the now-indexed file to `/asset/:id`. - Entry points: `Cmd/Ctrl+O` global hotkey, an "Open file…" sidebar action above Workspaces, and an "Open a file" CTA in the library empty-state. - New shared `lib/previewFormats.ts` (preview-capable extension sets, moved out of `AssetDetailPage`) and `lib/ephemeral.ts` (routes, file picker, add-to-library orchestration). ## Known caveat Multi-file glTF (a `.gltf` referencing sidecar `.bin`/textures by relative URL) won't resolve its sidecars through the ephemeral media-server URL; single-file models (`.glb/.obj/.stl/.ply/.fbx/.usdz`, embedded `.gltf`) are fine, and catalog models are unaffected. Documented in the plan doc with a fix sketch. ## Verification `tsc --noEmit`, Biome, `cargo clippy -D warnings`, and 127 backend + 13 frontend tests all green. Phases 2 (drag-and-drop, recents) and 3 (OS "Open with Garnet" file associations) are not started.
Sign in to join this conversation.
No reviewers
No labels
No milestone
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
parker/garnet!34
No description provided.