ADR 0169: Classified file preview and live workspace events for plugin views
- Status: Accepted
- Date: 2026-09-06
- Deciders: PI-Desktop core
- Related: ADR 0104 · ADR 0105 · ADR 0109 · ADR 0111 · D332 · E2E-153
Context
The bundled pi.files view is a public plugin consumer (ADR 0105). After it replaced the host Files tool, several first-party browsing behaviors were missing or broken:
fs.readTextcannot classify images, binary files, or oversized files, so the plugin reported images as unavailable and could load large binaries as UTF-8.fs.openDefaultexisted (ADR 0109) but left the Files UI when reveal replaced the header action (ADR 0111).- Panel events such as
appearance:changedwere broadcast only to detachedui.panelwindows. Docked work-panel views never received them. workspace:changedwas specified as planned. The Files view polledworkspace.getevery two seconds instead.
Decision
- Add
pi.fs.readPreview(pathFromRoot)and the panel channelfs.readPreview, gated by the existingfs.readpermission and the complete declared-scope checks. The host classifies one existing regular file astext,image,binary, ortooLarge, using the same size caps as the host Files tab (512 KiB text, 5 MiB image). Images return a data URL; binary and oversized files return no payload bytes. Directories are rejected. - Broadcast every plugin panel event to both detached panel windows and live docked views over the same
pi-plugin-panel-event:<event>preload channel. - Deliver
workspace:changedto panels and plugin processes whenever the cached workspace path changes. The payload matchesworkspace.get():{ path, name } | null. - Restore Open with default app in the bundled Files viewer, add search through
fs.glob, copy the root-relative path from a user gesture, and preview images throughfs.readPreview. No private bundled-plugin channel is introduced.
Consequences
- Third-party plugins can preview images and oversized files without inventing a second read API.
- A docked view follows theme, locale, and project switches live.
- The Files plugin remains a public-API consumer; transcript
file:<path>tabs stay host-owned.
Alternatives considered
Reuse fs.readText and detect images in the plugin
Rejected: UTF-8 decoding of PNG/JPEG is lossy, has no size cap, and cannot produce a data URL without a binary channel.
A private Files IPC channel
Rejected: that would recreate the host/plugin exception ADR 0105 removed.