Skip to content

fix: persist model name to .env so dotted names survive restart#426

Merged
ilblackdragon merged 2 commits intonearai:mainfrom
zmanian:fix/openai-compatible-model-name-persistence
Mar 1, 2026
Merged

fix: persist model name to .env so dotted names survive restart#426
ilblackdragon merged 2 commits intonearai:mainfrom
zmanian:fix/openai-compatible-model-name-persistence

Conversation

@zmanian
Copy link
Copy Markdown
Collaborator

@zmanian zmanian commented Feb 28, 2026

Summary

Fixes #400.

  • The setup wizard saved selected_model to the DB but not to .env. Since Config::from_env_with_toml() runs before the DB connects, the model name was lost on restart -- backends fell back to hardcoded defaults, truncating names like llama3.2 to llama3.
  • Added LlmBackend::model_env_var() as single source of truth for backend-to-env-var mapping
  • Wizard's write_bootstrap_env() now writes the model env var using the new method
  • Added selected_model fallback to all 6 backends (was missing from OpenAI, Anthropic, Ollama, and Tinfoil)

Test plan

  • cargo test -- all 1814 tests pass
  • cargo clippy --all --benches --tests --examples --all-features -- zero warnings
  • Manual: run wizard, select openai_compatible with a dotted model name (e.g. llama3.2), restart, verify model name is preserved in config

Generated with Claude Code

@github-actions github-actions Bot added scope: setup Onboarding / setup size: M 50-199 changed lines risk: high Safety, secrets, auth, or critical infrastructure labels Feb 28, 2026
@gemini-code-assist
Copy link
Copy Markdown
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request resolves a critical configuration issue where LLM model names, particularly those containing dots, were not correctly persisted across application restarts. The problem arose because the setup wizard saved selected_model only to the database, while the configuration loading process occurred before the database connection was established, leading to model names defaulting or being truncated. The changes introduce a standardized way to map LLM backends to environment variables, ensure the wizard writes the selected model to the .env file, and provide robust fallback mechanisms in the LLM configuration resolution for various backends, guaranteeing consistent model loading.

Highlights

  • Model Name Persistence: Implemented logic to persist the selected_model name to the .env file during the setup wizard's write_bootstrap_env() process, ensuring model names (especially those with dots) are retained across application restarts.
  • Centralized Environment Variable Mapping: Introduced a new method LlmBackend::model_env_var() to centralize the mapping of LLM backends to their respective model environment variables, ensuring consistency between configuration resolution and environment file writing.
  • Improved Model Resolution Fallback: Added selected_model as a fallback option for model resolution in OpenAi, Anthropic, Ollama, and Tinfoil LLM backend configurations, preventing models from defaulting or being truncated if their specific environment variables are not set.
  • New Unit Tests: Included new unit tests to verify that Ollama correctly uses the selected_model when its specific environment variable is unset, and that the OpenAI compatible backend accurately preserves dotted model names.
Changelog
  • src/config/llm.rs
    • Added model_env_var method to LlmBackend enum to provide a consistent way to get the environment variable name for each backend's model.
    • Modified LlmConfig::resolve to include settings.selected_model as a fallback for OPENAI_MODEL, ANTHROPIC_MODEL, OLLAMA_MODEL, and TINFOIL_MODEL if their respective environment variables are not set.
    • Added new tests: ollama_uses_selected_model_when_ollama_model_unset, ollama_model_env_overrides_selected_model, and openai_compatible_preserves_dotted_model_name.
  • src/setup/wizard.rs
    • Updated write_bootstrap_env to write the selected_model to the appropriate backend-specific environment variable in the .env file, utilizing the new LlmBackend::model_env_var() method.
Activity
  • All 1814 cargo test cases passed.
  • cargo clippy reported zero warnings.
  • A manual test plan was outlined to verify model name preservation after wizard setup and restart.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@github-actions github-actions Bot added the contributor: experienced 6-19 merged PRs label Feb 28, 2026
Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request correctly addresses the issue of persisting model names with dots by saving them to the .env file during setup. The changes are logical, introducing a centralized method for backend environment variables and applying fallbacks consistently. The added tests effectively verify the fix. I have one suggestion to refactor some duplicated code to improve maintainability, aligning with the practice of using specialized helpers for environment variable resolution.

Comment thread src/config/llm.rs Outdated
Comment on lines +268 to +270
let model = optional_env("OPENAI_MODEL")?
.or_else(|| settings.selected_model.clone())
.unwrap_or_else(|| "gpt-4o".to_string());
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

This pattern for resolving the model name is now used in several places (NearAi, OpenAi, Anthropic, Ollama, OpenAiCompatible, Tinfoil). To improve maintainability and reduce code duplication, consider extracting this logic into a private helper function inside impl LlmConfig.

For example, you could add a helper function:

fn resolve_model(env_var: &str, settings: &Settings, default: &str) -> Result<String, ConfigError> {
    Ok(optional_env(env_var)?
        .or_else(|| settings.selected_model.clone())
        .unwrap_or_else(|| default.to_string()))
}

And then simplify the call sites:

let model = Self::resolve_model("OPENAI_MODEL", settings, "gpt-4o")?;
References
  1. Use specialized helper functions like parse_option_env<T> when resolving environment variables into Option<T> fields to minimize boilerplate and maintain consistency across configuration files.

@zmanian
Copy link
Copy Markdown
Collaborator Author

zmanian commented Mar 1, 2026

Re: Gemini Code Assist review feedback

Verified false positive. Gemini suggests extracting a resolve_model helper. This helper already exists (resolve_model() function) and is used by all 6 providers. The suggestion is already implemented.

zmanian and others added 2 commits February 28, 2026 21:38
…ai#400)

The setup wizard saved selected_model to the DB but not to .env.
Since Config::from_env_with_toml() runs before the DB connects, the
model name was lost on restart -- backends fell back to hardcoded
defaults, truncating names like "llama3.2" to "llama3".

- Add LlmBackend::model_env_var() as single source of truth for the
  backend-to-env-var mapping
- Write the model env var in write_bootstrap_env() using the new method
- Add selected_model fallback to all 6 backends (was missing from
  OpenAI, Anthropic, Ollama, and Tinfoil)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Address review feedback: the env → settings → default model resolution
pattern was repeated across all 6 backends.  Centralise it in a single
LlmConfig::resolve_model() helper.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@zmanian zmanian force-pushed the fix/openai-compatible-model-name-persistence branch from c0dd0e7 to 1515a52 Compare March 1, 2026 05:38
@ilblackdragon ilblackdragon merged commit f62937d into nearai:main Mar 1, 2026
13 checks passed
@github-actions github-actions Bot mentioned this pull request Mar 1, 2026
zmanian added a commit to zmanian/ironclaw that referenced this pull request Mar 1, 2026
…ai#426)

* fix: persist model name to .env so dotted names survive restart (nearai#400)

The setup wizard saved selected_model to the DB but not to .env.
Since Config::from_env_with_toml() runs before the DB connects, the
model name was lost on restart -- backends fell back to hardcoded
defaults, truncating names like "llama3.2" to "llama3".

- Add LlmBackend::model_env_var() as single source of truth for the
  backend-to-env-var mapping
- Write the model env var in write_bootstrap_env() using the new method
- Add selected_model fallback to all 6 backends (was missing from
  OpenAI, Anthropic, Ollama, and Tinfoil)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* refactor: extract resolve_model() helper to reduce duplication

Address review feedback: the env → settings → default model resolution
pattern was repeated across all 6 backends.  Centralise it in a single
LlmConfig::resolve_model() helper.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
bkutasi pushed a commit to bkutasi/ironclaw that referenced this pull request Mar 28, 2026
…ai#426)

* fix: persist model name to .env so dotted names survive restart (nearai#400)

The setup wizard saved selected_model to the DB but not to .env.
Since Config::from_env_with_toml() runs before the DB connects, the
model name was lost on restart -- backends fell back to hardcoded
defaults, truncating names like "llama3.2" to "llama3".

- Add LlmBackend::model_env_var() as single source of truth for the
  backend-to-env-var mapping
- Write the model env var in write_bootstrap_env() using the new method
- Add selected_model fallback to all 6 backends (was missing from
  OpenAI, Anthropic, Ollama, and Tinfoil)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* refactor: extract resolve_model() helper to reduce duplication

Address review feedback: the env → settings → default model resolution
pattern was repeated across all 6 backends.  Centralise it in a single
LlmConfig::resolve_model() helper.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

contributor: experienced 6-19 merged PRs risk: high Safety, secrets, auth, or critical infrastructure scope: setup Onboarding / setup size: M 50-199 changed lines

Projects

None yet

Development

Successfully merging this pull request may close these issues.

openai_compatible backend truncates model name at dot (llama3.2 becomes llama3)

2 participants