From 1ebdc1a05f4c71cb7ba23870336dc53339227972 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Troed=20S=C3=A5ngberg?= Date: Fri, 21 Aug 2026 10:55:08 +0200 Subject: [PATCH] docs: design spec for explicit server option --- ...026-08-21-explicit-server-option-design.md | 80 +++++++++++++++++++ 1 file changed, 80 insertions(+) create mode 100644 docs/superpowers/specs/2026-08-21-explicit-server-option-design.md diff --git a/docs/superpowers/specs/2026-08-21-explicit-server-option-design.md b/docs/superpowers/specs/2026-08-21-explicit-server-option-design.md new file mode 100644 index 0000000..10f7652 --- /dev/null +++ b/docs/superpowers/specs/2026-08-21-explicit-server-option-design.md @@ -0,0 +1,80 @@ +# Explicit `server` option for oc-ls-stats + +Date: 2026-08-21 +Status: Approved design, pending implementation plan + +## Problem + +The plugin discovers the llama-server URL by matching provider keys in the +OpenCode config whose name contains "llama" (excluding "ollama"). On hosts +where the provider is named differently (e.g. `"vision"` on headless.local), +discovery fails and the plugin falls back to `http://localhost:8080`, which is +wrong when llama-server runs on another host or port. + +## Goal + +Let the user configure the llama-server endpoint explicitly, independent of +provider naming. Single-server model: one endpoint per opencode instance. + +## Decision + +Use OpenCode's native TUI plugin options mechanism. `tui.json` accepts plugin +entries as `[name, options]` tuples and passes the options object as the second +argument to the plugin function (`TuiPlugin = (api, options, meta) => ...`). +The option key is singular (`server`) because only one server is supported. + +```json +{ + "plugin": [ + ["@troed/oc-ls-stats@latest", { "server": "http://headless.local:8080" }] + ] +} +``` + +### Resolution order + +Explicit replaces discovery: + +1. `options.server` if it is a non-empty string +2. Name-based detection from `api.state.config` ("llama" providers, existing behavior) +3. `http://localhost:8080` fallback + +### URL normalization + +The explicit value is normalized with the existing `stripBaseUrlPath`, so both +`http://host:8080` and an OpenCode-style `baseURL` ending in `/v1` work. The +value must be a string; anything else falls through to step 2 of the +resolution order after a single `console.warn`. + +## Changes + +- `src/stats.ts`: add pure function + `resolveServerUrls(options: unknown, config: unknown): string[]` + implementing the resolution order above. Reuses `stripBaseUrlPath` + (moved from `tui.tsx`) and `extractProviderUrls`. +- `tui.tsx`: accept the second plugin argument; replace the startup + `loadConfigUrls` block with a call to `resolveServerUrls`. Remove + `loadConfigUrls` if no longer referenced. +- Polling, backoff, slot classification, and rendering are unchanged. + +## Error handling + +No new failure modes at runtime. A malformed `server` value warns once at +startup and falls back to existing detection. Network errors continue to use +the existing per-server backoff. + +## Testing + +Extend the prepack test script pattern (`test-backoff.ts`) with cases for +`resolveServerUrls`: + +1. Explicit `server` wins over config detection. +2. `/v1` suffix is stripped from the explicit value. +3. Non-string `server` falls back to detection. +4. No options and no matching providers → `localhost:8080` fallback. + +## Docs and version + +- README "Server Discovery" section documents the option with the tui.json + example above. +- Version bump to 1.3.0 (new feature).