* feat(config): add agent config descriptor protocol and advertise via runner capability
Introduce shared agent configuration descriptors covering model, effort,
permission, and secondary settings per agent flavor, plus the canonical
HAPI YOLO -> native permission mode mapping. Runners advertise the
builtin descriptors through the runner-state capability so hubs and web
can render configuration without hardcoded flavor branches.
Migrate the OpenCode create-session model picker from a bespoke radio
list to the shared SelectControl combobox.
* feat(web): render create-session permission from agent config descriptor
Replace the flavor-branched Grok/Codex-family/YOLO permission block with
a descriptor-driven PermissionField. Pi now reports permission as managed
instead of silently ignoring the YOLO toggle, and YOLO-only flavors show
the native permission mode the preference maps to.
Removes the superseded GrokPermissionModeSelector and
CodexFamilyPermissionModeSelector components.
* ci: retry flaky claudeRemote 5s-timeout failure
* fix(web): persist explicit OpenCode Default selection instead of restoring a concrete model
The parent initialization effect treated every null selected model as
'uninitialized' and auto-picked a concrete advertised model, clobbering
the user's explicit Default choice (and a restored Default preference).
null now means explicit Default and is preserved; only undefined (no
choice made yet) triggers probe-based initialization. Add parent-level
regression tests for Default persistence and remembered-model restore.
* fix(web): accept undefined selected model in OpencodeModelSelector props
* feat(web+cli+hub): unify create-session model/effort fields and add Pi model/effort support
Pi's agent config descriptor now advertises model (machine) and effort
(static thinking levels) for create AND session availability:
- cli: ListPiModelsForMachine RPC runs 'pi --list-models' (cached, inflight
deduped) and parses the provider/model table; startup model match accepts
provider-qualified ids
- hub: GET /api/machines/:id/pi-models route + rpcGateway/syncEngine passthrough
- web: NewSession renders Pi models grouped by provider through the generic
ModelSelector and a new descriptor-driven EffortField (replaces the
per-flavor LaunchEffortSelector/ReasoningEffortSelector pair); launch payload
forwards Pi model + thinking-level effort (runner already supported --model/
--effort for pi)
* fix(web): render Pi provider groups in ModelSelector and scope Grok availability warning
- ModelSelector now renders grouped options as <optgroup> (Pi models are
provider-grouped; identical modelIds from different providers stay distinct)
- PermissionField only receives autoPermissionModeSupported for Grok — a
cached Grok probe result no longer leaks the Grok warning onto other agents
Addresses HAPI Bot Minor findings on #1469.
* fix(web): drop Object.groupBy from ModelSelector; revalidate restored Pi models against the catalog
- ModelSelector buckets options with a reduce instead of Object.groupBy
(Safari < 17.4 has no polyfill — New Session would throw on those clients)
- Pi restored model/effort are cleared when the value is absent from the live
machine catalog, and Create waits for the catalog while a non-default Pi
choice is being validated (mirrors Codex/Grok/Copilot handling)
Addresses HAPI Bot findings on #1469.
* fix(pi+web): serialize startup model before thinking level; hide Pi launch controls during history import
- PiSession gains startupModelSettled; the startup set_thinking_level waits for
the requested model's set_model attempt to settle first, so a level the
default model rejects is not lost before the requested model is confirmed
(set_model and set_thinking_level were already serialized by the runtime
mutation lock; this pins the model-first ordering)
- Create Session hides Pi model/effort controls while a Pi history import is
selected — the import reopens the native session as-is and would silently
ignore launch-only model/effort values
Addresses HAPI Bot findings on #1469.
* fix(pi): settle startup-model gate when model discovery fails or returns no models
A failed or empty get_available_models response would leave the
startupModelSettled gate unresolved, stranding a requested startup effort
indefinitely. Resolve the gate on the error path and the empty-models path;
adds regression tests for both.