Three symptoms on .21, two defects. Lutris and Heroic appeared in the console sidebar
they explicitly opt out of; Lutris's settings were unreachable from the Library
screen; and Lutris and Steam logged `sync (startup) failed: HostRequestError`.
**The sidebar is a publish gap.** The console is correct — it keeps
`category: "library"` plugins out of the nav (`uiPlugins`, app-shell.tsx) — but the
host reports no category for them at all. `defineLibraryPlugin` sets it and
`sdk/src/ui.ts` forwards it; what SHIPS does not. `@punktfunk/host` was bumped to
0.1.2 on 2026-07-20 and `category` landed 2026-08-05 without a bump, so the registry's
0.1.2 is the pre-category build and every installed scanner registers without one.
Bumps the SDK to 0.1.3 — **inert until it is published**.
Because the field rides the untyped `pf.request` seam so an older host ignores it
rather than rejecting the registration, dropping it is silent by design. `serveUi` now
reads its own directory entry back and warns once when a requested category did not
land, the same way `defineLibraryPlugin` already warns when a store claim did not take.
That is what turns the next occurrence into a log line instead of a bug report.
**The missing settings and the failed sync are ONE defect: a write/read disagreement
about `file://`.** `local_art_bytes` decodes a `file://` value before testing
containment; `validate_art_paths` handed the raw value to `Path::new`, where
`file:///home/u/c.jpg` is a RELATIVE path whose first component is `file:`. It
canonicalized against the cwd, failed, and read as "outside every art root". So the
host refused every cover the kit's own `fileUrl` helper emits — the documented way for
a plugin to publish local art — while the read path would have served those same files.
That the two symptoms share a cause is not obvious and is why this is one commit: the
Library screen's settings control renders only for `origin: "plugin"`, and a source
becomes `plugin` only once it holds a store CLAIM, which is taken during a successful
reconcile. Lutris failed at entry 0 and Steam at entry 3, so neither ever claimed its
store, both stayed `origin: "builtin"`, and neither got a settings button. Heroic
reconciled (its art is http(s)) and has had its settings all along; rom-manager was
never affected because zero entries meant it never applied.
`art_path_is_servable` now decodes first, so both halves of the confinement judge the
same string. Confinement itself is unchanged: an out-of-root path is still refused in
`file://` clothing, which the test asserts alongside the accept case.
Diagnosing this took the HOST's journal, because both surfaces that should have
explained it lied. `HostRequestError` stringified to its bare tag, so the sync engine's
`${e.cause}` logged `HostRequestError` and discarded the method, the path and the
host's own message; it now renders all three, including an object-shaped cause that
used to print `[object Object]`. And the host logged "payload carries a field this lane
may not set" for BOTH refusals in `check_entry_fields`, so a 400 about an art path read
as an auth problem — it now logs the real reason and the entry title.
Verified on .21 (Linux): 463 host tests pass, clippy clean under `-D warnings`,
`cargo fmt --all --check` clean. The new art test fails without the fix and passes with
it. plugin-kit 71 and SDK 72 tests pass, both typecheck clean, biome clean.
63 lines
1.7 KiB
JSON
63 lines
1.7 KiB
JSON
{
|
|
"name": "@punktfunk/host",
|
|
"version": "0.1.3",
|
|
"description": "TypeScript SDK for the punktfunk streaming host: typed management-API client + lifecycle event stream, built on Effect.",
|
|
"type": "module",
|
|
"license": "MIT OR Apache-2.0",
|
|
"homepage": "https://git.unom.io/unom/punktfunk/src/branch/main/sdk",
|
|
"repository": {
|
|
"type": "git",
|
|
"url": "https://git.unom.io/unom/punktfunk.git",
|
|
"directory": "sdk"
|
|
},
|
|
"bugs": {
|
|
"url": "https://git.unom.io/unom/punktfunk/issues"
|
|
},
|
|
"keywords": ["punktfunk", "game-streaming", "automation", "sdk", "effect"],
|
|
"main": "./dist/index.js",
|
|
"types": "./dist/index.d.ts",
|
|
"exports": {
|
|
".": {
|
|
"types": "./dist/index.d.ts",
|
|
"default": "./dist/index.js"
|
|
},
|
|
"./effect": {
|
|
"types": "./dist/effect.d.ts",
|
|
"default": "./dist/effect.js"
|
|
}
|
|
},
|
|
"bin": {
|
|
"punktfunk-scripting": "./dist/runner-cli.js"
|
|
},
|
|
"files": ["dist", "README.md"],
|
|
"publishConfig": {
|
|
"registry": "https://git.unom.io/api/packages/unom/npm/"
|
|
},
|
|
"scripts": {
|
|
"prepare": "bun2nix -o bun.nix",
|
|
"gen": "openapigen --spec ../api/openapi.json --name Punktfunk --format httpclient > src/gen/punktfunk.ts",
|
|
"typecheck": "tsc --noEmit",
|
|
"build": "tsc -p tsconfig.build.json",
|
|
"test": "bun test",
|
|
"runner": "bun src/runner-cli.ts",
|
|
"prepublishOnly": "bun run build"
|
|
},
|
|
"peerDependencies": {
|
|
"effect": "^4.0.0-beta.98"
|
|
},
|
|
"devDependencies": {
|
|
"effect": "^4.0.0-beta.98",
|
|
"@effect/openapi-generator": "4.0.0-beta.98",
|
|
"@effect/platform-node": "4.0.0-beta.98",
|
|
"@types/bun": "^1.3.0",
|
|
"bun2nix": "2.1.2",
|
|
"typescript": "^5.9.3"
|
|
},
|
|
"optionalDependencies": {
|
|
"undici": "^7.0.0"
|
|
},
|
|
"overrides": {
|
|
"undici": "^8.9.0"
|
|
}
|
|
}
|