Repository navigation
Saved AI providers (desktop + mobile) + shared model picker #95
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
3 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,17 @@ | ||
| # v2.5.9 | ||
|
|
||
| ## Added | ||
|
|
||
| - **Save and switch between AI providers.** The AI settings (Settings → AI, Cloud / Local API) now let you save several named OpenAI-compatible connections — each with its own name, base URL, API key, and default model — and switch the active one from a dropdown instead of retyping your endpoint every time you change services. Add a provider for OpenAI, another for OpenRouter or Together, one for a local Ollama / LM Studio server, and flip between them in a click; the active provider fills the endpoint, key, and model fields below and is used everywhere the app talks to the cloud/local API (chat, inline AI, PRD writer, summaries). Add, edit, and delete providers inline. Your existing endpoint carries over unchanged — nothing to reconfigure. The On-Device Llama option is unaffected and keeps its own toggle. | ||
| - **The Coding Agent shares the same saved providers.** The Coding Agent settings (Settings → Agents → Cairn Coding Agent) use the *same* list of saved providers as AI Chat — add or edit a connection once and it's available in both places. The agent keeps its own active selection, so you can point it at a higher-capacity model while chat stays on a cheaper one. Deleting or editing a provider updates both consistently. | ||
|
|
||
| ## Changed | ||
|
|
||
| - **Cleaner endpoint settings.** Now that saved providers cover switching endpoints, the old OpenAI / Ollama / LM Studio quick-preset pills under the Base URL field have been removed from both the AI settings and the Coding Agent settings — pick or add a saved provider instead. The provider picker now uses Cairn's standard dropdown menu (matching the model picker and other settings) instead of a plain OS select box, and shows each provider's model beneath its name. | ||
| - **Consistent model picker everywhere.** The model selector from the in-chat quick settings — a searchable dropdown of the endpoint's models with a Refresh action and a "Custom model…" option for anything the endpoint doesn't list — is now used across the app: in Settings → AI, in the Coding Agent settings, and in the saved-provider Add/Edit form. This replaces the older text box + Fetch button + wall of model pills, so choosing a model looks and behaves the same in every place. | ||
| - **The model dropdown only shows real models.** It no longer pre-fills with a hardcoded list of guessed model names. Instead each endpoint's model list is fetched and cached per endpoint (base URL + key), so it appears instantly the next time you open the picker; if nothing is cached yet, it fetches once automatically. You can still Refresh to re-query or enter a custom model id. Cached lists refresh after a week. | ||
|
|
||
| ## Fixed | ||
|
|
||
| - **AI settings no longer crash with an infinite render loop.** Opening Settings → AI could throw "The result of getSnapshot should be cached to avoid an infinite loop" because the saved-providers list was rebuilt on every render. The provider switcher now reads a stable list reference, so the settings panel renders cleanly. | ||
| - **Local endpoints work with `127.0.0.1`, not just `localhost`.** Pointing an endpoint at `http://127.0.0.1:<port>` (instead of `http://localhost:<port>`) previously failed to fetch models or test the connection — the app's content-security-policy allowed `localhost` but not the equivalent `127.0.0.1` loopback address (CSP matches the origin string literally, so the two are treated as different). Both loopback spellings are now allowed, so a local server (Ollama, LM Studio, llama.cpp, …) works with whichever address you use. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🔒 Security & Privacy | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
Repository: ddutchie/cairn
Length of output: 23053
🏁 Script executed:
Repository: ddutchie/cairn
Length of output: 14080
Store saved-provider secrets through the encrypted store.
saavedProviderscarriesapiKey, andpersistAi()writes the full object tolocalStorageplus callssaveAiSettings(), which persists it toai-settings-cache.jsonvia plain JSON. Use the same OS-keychain-backed secret store used for MCP/service secrets, or store only provider references inlocalStorage/cache and keep the raw keys on the Electron side encrypted.📍 Affects 2 files
electron/lib/config-cache.ts#L106-L111(this comment)src/store/slices/ui.ts#L72-L86🤖 Prompt for AI Agents
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will follow up with quick PR
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ddutchie, sounds good. The finding will remain open until the follow-up PR moves saved-provider API keys out of renderer/plain-JSON persistence and into the encrypted secret store.Would you like me to open a GitHub issue to track it?