Commit Graph
3 Commits
Author SHA1 Message Date
enricobuehler 3d4a659959 feat(host,sdk,kit): store claims, launcher entries, and plugin sources on the wire
M2 of design/library-scanner-plugins-implementation-plan.md. Everything a
library scanner plugin needs is now expressible over the API; all additive.

WP2.1/2.2 — store claims (D2). library.json gains a v2 shape ({entries, claims})
that loads the v1 bare array unchanged and is written on the first mutation.
PUT /library/provider/{p}?store=<s> claims a store for a provider: its entries
then surface with deterministic <store>:<external_id> ids and the store's own
badge instead of opaque custom:<id> ones. That identity is the whole point —
entry ids, GameStream FNV app ids, client art caches and Moonlight pins all
survive a title moving from an in-host scanner to a plugin. One provider per
store (409 otherwise); DELETE releases; an empty reconcile does NOT (a store can
legitimately have zero titles). While a claim is held, all_games() skips the
matching built-in scanner, so the two never double-list during the bridge.

WP2.3 — DetectHint gains steam_appid and env_marker, the two store-derived
signals the host used to read for itself. Without them a steam plugin's lease
tracking would drop from reaper-exact to dir-prefix, and Heroic-under-Proton
would lose the only signal that works. Malformed markers are dropped, not
honoured — this feeds a path that can end processes.

WP2.4/2.5 — role: game|launcher on the entry shapes (serde-default, skipped when
default), and a steam_ui launch kind valued bigpicture|desktop that opens the
Steam client itself. Validated inbound as well as at launch.

WP2.6 — GET/PUT /library/scanners generalizes to SOURCES: built-in scanners
minus claimed ones, plus claimed stores, plus any provider with entries. The
same library-scanners.json disabled-set backs all of them and the ids match by
construction, so a user's disabled state carries over verbatim through the whole
migration. A disabled plugin source has its entries filtered at read time,
exactly like a disabled scanner.

WP2.7/2.8 — plugin registration gains a category field (the console keeps
library plugins out of the nav); index entries gain categories and per-platform
detect probes, evaluated existence-only into CatalogEntry.detected so the host
never re-grows per-store knowledge. Index SCHEMA stays 1 — additive.

WP2.9 — OpenAPI + SDK regenerated on Linux; kit wire widened (LaunchSpec.kind is
now a plain string documented against the host's vocabulary — closes G3), and
ProviderClient.reconcile takes an optional store and returns the host's echoed
entries so a caller can detect a pre-M2 host silently ignoring the claim.

Also fixes a bug the S3 spike turned up: is_steam_launch gated on a steam:// URI,
so a steam_ui launcher entry would have skipped BOTH gamescope's --steam mode and
the B1 single-instance free — on a box autologged into game mode, the nested
second Steam would see the first and exit, crashing the spawn. It now tests the
first token.

Gates on .21: workspace tests green (punktfunk-host 425 passed), workspace
clippy -D warnings clean, cargo fmt --all --check clean, OpenAPI drift test
green. plugin-kit: tsc clean, 20 tests pass.
2026-08-05 09:39:31 +02:00
enricobuehlerandClaude Fable 5 da259d5b79 feat(plugin-kit): browser-safe ./wire subpath for provider schemas (0.1.1)
apple / swift (push) Successful in 1m22s
apple / screenshots (push) Successful in 6m35s
ci / web (push) Successful in 1m13s
ci / docs-site (push) Successful in 1m14s
android / android (push) Successful in 17m3s
decky / build-publish (push) Successful in 18s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 11s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 10s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 9s
docker / build-push (ci, ci/rust-ci-noble.Dockerfile, punktfunk-rust-ci-noble) (push) Successful in 9s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 9s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 8s
arch / build-publish (push) Successful in 16m33s
ci / bench (push) Successful in 14m48s
deb / build-publish (push) Successful in 14m48s
ci / rust (push) Successful in 22m36s
deb / build-publish-host (push) Successful in 18m16s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Successful in 18m30s
docker / deploy-docs (push) Successful in 23s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Successful in 28m25s
Plugin contracts share ProviderEntry/Artwork/LaunchSpec/PrepStep with their
UIs; the kit root stays node-only (reconcile keeps the HostClient transport).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-20 18:49:13 +02:00
enricobuehlerandClaude Fable 5 8d72e1d27e feat(plugin-kit): @punktfunk/plugin-kit 0.1.0 — the Effect plugin framework
ci / rust (push) Has been cancelled
android / android (push) Has been cancelled
apple / swift (push) Has been cancelled
apple / screenshots (push) Has been cancelled
arch / build-publish (push) Has been cancelled
ci / web (push) Has been cancelled
ci / bench (push) Has been cancelled
ci / docs-site (push) Has been cancelled
deb / build-publish-host (push) Has been cancelled
deb / build-publish (push) Has been cancelled
decky / build-publish (push) Has been cancelled
docker / build-push (ci, ci/rust-ci-noble.Dockerfile, punktfunk-rust-ci-noble) (push) Has been cancelled
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Has been cancelled
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Has been cancelled
docker / deploy-docs (push) Has been cancelled
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Has been cancelled
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Has been cancelled
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Has been cancelled
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Has been cancelled
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Has been cancelled
windows-host / package (push) Has been cancelled
The ~80% of every plugin that was copy-pasted (rom-manager ↔ playnite),
extracted as one Effect-v4 package:

- runtime: definePluginKit — async-main boundary hiding a ManagedRuntime
  (two-effect-instances discipline), signal-driven interruption with a
  bounded shutdown grace
- config: Schema-driven raw round-trip (defaults only in the Schema via
  withDecodingDefaultKey + encodingStrategy omit; file stays authored-shape),
  atomic writes, world-writable refusal, changes stream
- cache-store: disposable derived state, corrupt→empty, write-through
- reconcile: kit-owned provider wire schemas + typed client over the
  skew-safe untyped pf.request seam
- sync-engine: generic poll/watch/debounce/single-flight-coalesce/
  fingerprint-skip engine with a status PubSub (the SSE feed)
- ui-server + sse: effect/unstable/httpapi behind servePluginUi with
  core-only env layers (validated by the phase-0 spikes); raw SSE route
  (httpapi has no event-stream media type)
- cli: minimal command dispatcher reusing the plugin layer graph
  (deliberately not effect/unstable/cli — it needs platform packages)
- react subpath: plugin router (path→hash→fallback deep-link restore +
  pf-ui:navigate bridge), ResultGate, sseAtom, resolvePluginBase
- theme.css: the console's violet identity packaged for plugin UIs

18 bun tests incl. the two phase-0 spikes; publish workflow mirrors
sdk-publish (tag plugin-kit-v*; 0.1.0 published manually).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-20 18:41:11 +02:00