galaxyproject / galaxyproject/loom
Orbit: configure local/custom models from Preferences UI
- Dominant language
- TypeScript
- Stars
- 14
- Forks
- 12
- Avg merge
- 6d 5h
- Merged PRs (30d)
- 17
Description
## Problem
Today, configuring a local model (Ollama, LiteLLM proxy, any OpenAI-compatible endpoint) requires hand-editing `~/.pi/agent/models.json`. Orbit's Preferences UI only exposes:
- Provider dropdown (hardcoded list of 7 in `app/src/renderer/index.html:175-183`)
- Model dropdown (hardcoded preset list per provider; \"(custom)\" free-form fallback for unknown IDs)
- API key
Missing:
- **Base URL** — can't point at a custom Ollama port, a LiteLLM proxy on `localhost:4000`, or any other server
- **Context window / max tokens** — pi-coding-agent needs these to size requests; without them a custom model fails silently
- **`litellm` provider** — not in the dropdown at all, even though README documents it as supported
- **Custom model registration with metadata** — the \"(custom)\" fallback accepts any ID but writes no model definition, so pi-coding-agent rejects unknown models
Result: every local-model user has to read pi-coding-agent's source to discover the `models.json` schema, then hand-edit JSON. UI is a viewing surface, not a configuration surface.
## Proposed shape
Extend Preferences with an \"Add custom model\" section that maps 1:1 to pi-coding-agent's `ModelDefinitionSchema` (see `node_modules/@mariozechner/pi-coding-agent/dist/core/model-registry.js`). Fields:
- Provider name (free-form; defaults to \"ollama\" / \"litellm\" / \"custom\")
- Base URL (e.g. `http://localhost:11434/v1`)
- API kind dropdown (`openai-completions` is the practical lingua franca)
- Model ID
- Display name
- Context window
- Max output tokens
- Cost per 1M tokens (in/out — optional, defaults to 0 for local)
Save writes to `~/.pi/agent/models.json` via the documented schema; provider dropdown re-reads it on next open.
## Two bonus wins this unlocks
1. **Discovery for Ollama** — once base URL is settable, Orbit can call `GET {baseUrl}/api/tags` and prepopulate the model list. Same idea for LiteLLM via `/v1/models`. (See #13 for the broader dynamic-list discussion.)
2. **Capability probing** — Ollama's `/api/show` returns context window per model; we can fill in the metadata without the user typing it.
## Tradeoff
Adds ~100 lines of HTML + form-handler JS + a small IPC bridge to write `~/.pi/agent/models.json`. Validation against `ModelsConfigSchema` already exists in pi-coding-agent — Orbit just needs to surface load errors.
Alternative — punt to documentation only: cheaper but the README walkthrough already exists and clearly hasn't been enough; the UI gap is real friction for anyone running local models.
## Related
- #13 (dynamic model list — provider-side discovery; complementary)
- README.md:271-287 documents the JSON-only path that this issue would replace
Contributor guide
No contributing guide indexed for this repository
Research direction
Start with the Preferences provider and model controls in app/src/renderer/index.html:175-183, then inspect pi-coding-agent's ModelDefinitionSchema in node_modules/@mariozechner/pi-coding-agent/dist/core/model-registry.js and the existing IPC bridge. Done means custom fields can be saved to ~/.pi/agent/models.json, validation errors are surfaced, and the provider list reloads the saved configuration.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- html, typescript
- Domain
- desktop, frontend
- Issue type
- Feature
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100