Commit Graph
2 Commits
Author SHA1 Message Date
Lyubomir BozhinovandJoseph Magly 9cce68e804 feat(settings): Universal API Config panel with server-side model fetch (#90) (#101)
* feat(settings): Universal API Config panel with server-side model fetch (#90)

Consolidates provider configuration into one "Universal API Config" panel in
Settings — provider dropdown (OpenAI-compatible / Anthropic), base URL, API key,
model with a live "Fetch models" button, and max context tokens — above the
existing per-provider key sections.

Backward-compatible by design: the panel reads and writes the SAME state.settings
keys the individual sections already use (${provider}Key, selectedModel), so
nothing migrates and nothing is lost; the individual sections keep working and
stay in sync.

- src/config/provider-models.ts (new): listProviderModels queries a provider's
  own model endpoint (OpenAI-compatible Bearer /models, Anthropic x-api-key
  /v1/models, OpenRouter public list); resolveModels wraps it fail-open.
- POST /api/models (new route): server-side so the browser dodges provider CORS.
  Binds key+baseUrl by source — a caller-supplied base URL must bring its own
  key, so the server never lends its configured key to a body-chosen URL. Always
  responds, failing open to the static AVAILABLE_MODELS list on a missing key,
  network error, or unknown provider (incl. local-agent) — never hangs.
- Model options are built via the DOM API (createElement/textContent), never
  innerHTML, so untrusted provider-returned model ids cannot inject markup.

Scope notes: augment-not-replace (removing the individual sections is deferred
to maintainer preference); base URL + context cap are stored and used for model
discovery and server/agent flows — in-browser mission routing still uses
OpenRouter/Venice, matching the existing "not wired" hints; the "Model Reasoning
(Eino)" sub-proposal is a separate follow-up pending a mapping.

Verified on macOS: 12 unit tests (RED->GREEN) for the model module, full suite
462 green, and Playwright QA (17 checks) driving the real panel — render,
provider switch, persistence across reload, backward-compat, and both the static
and live Fetch paths.

Refs #90

* fix(settings): harden model list fetch

---------

Co-authored-by: Joseph Magly <1159087+jmagly@users.noreply.github.com>
2026-07-20 11:34:26 -04:00
Lyubomir Bozhinov 5b4ac700ad fix(agents): detect local CLIs via well-known install dirs (#83)
A T3MP3ST server launched from Finder, the desktop app, or any non-interactive
shell inherits launchd's minimal PATH (/usr/bin:/bin:/usr/sbin:/sbin). The
local-agent detector resolved `claude`/`codex`/`hermes` against that PATH via
execFile, so an installed, authed CLI in ~/.local/bin (Claude Code's native
installer), Homebrew, npm-global, or a version-manager shim (mise/nvm/fnm) threw
ENOENT and was reported installed:false — the Settings "Connect Local Agents"
checkboxes went dead and it read like a UI bug.

Add resolveBin(): pure-fs (no shell) resolution over PATH plus a curated set of
well-known install dirs under the real agent home (agentHome(), so a HOME
redirect can't hide them), with an executable-file access check and fail-open to
the bare name — an unresolved name yields the same ENOENT → installed:false as
before, so true-absence detection is unchanged. Route the detector and both spawn
sites (runLocalAgent, localAgentChat) through it, so a CLI detected under a
minimal PATH also actually spawns. Bound the keychain auth-probe with a 2s
timeout so a locked/headless keychain (the same non-interactive launch context)
can't hang detection.

POSIX/macOS-scoped: resolveBin short-circuits on win32 — Windows resolution
(where.exe / .cmd shims) is handled by the complementary open PR #18.

Verified on macOS: RED->GREEN unit + integration tests (resolver, detector
wiring, and both spawn sites), and manual QA driving the real Web UI under a
reproduced minimal PATH (Claude Code flips from "Not installed" to detected).

Refs #78 — fixes the macOS/POSIX variant. The original report was a Windows
Sandbox environment (PR #18's domain), so this intentionally does not auto-close
that issue.
2026-07-15 19:39:59 -04:00