events: HIVE_DEFAULT_MODEL takes priority over persisted model (closes #319)

This commit is contained in:
damocles 2026-05-23 00:38:17 +02:00
parent cd9831b39e
commit 77b249076f
2 changed files with 68 additions and 17 deletions

View file

@ -310,22 +310,27 @@ pub enum TurnState {
Compacting,
}
/// Default claude model when nothing's been set at runtime. Overridable
/// via the `HIVE_DEFAULT_MODEL` env var (set from `hyperhive.model` in
/// the container's `agent.nix`). The operator can also switch at runtime
/// via `/model <name>` in the web terminal; the chosen model is persisted
/// to the state dir so it survives restarts.
/// Compiled-in fallback model used when neither `HIVE_DEFAULT_MODEL` nor a
/// persisted runtime override is present.
pub const DEFAULT_MODEL: &str = "haiku";
/// Return the initial default model name: `HIVE_DEFAULT_MODEL` env var if
/// set to a non-empty string, otherwise `DEFAULT_MODEL`.
/// Return the model declared in `HIVE_DEFAULT_MODEL` (set from
/// `hyperhive.model` in `agent.nix`), or `None` if the env var is absent /
/// empty. When `Some`, this takes precedence over any persisted runtime
/// override so that nix config changes always take effect on rebuild.
#[must_use]
pub fn default_model() -> &'static str {
pub fn configured_model() -> Option<&'static str> {
// Leak once at startup — acceptable for a single config value.
std::env::var("HIVE_DEFAULT_MODEL")
.ok()
.filter(|s| !s.trim().is_empty())
.map_or(DEFAULT_MODEL, |s| Box::leak(s.into_boxed_str()))
.map(|s| &*Box::leak(s.into_boxed_str()))
}
/// Return the model to use when no config and no persisted override exist.
#[must_use]
pub fn default_model() -> &'static str {
configured_model().unwrap_or(DEFAULT_MODEL)
}
/// Context-window size in tokens for a given model name.
@ -441,7 +446,13 @@ impl Bus {
}
};
let (tx, _) = broadcast::channel(CHANNEL_CAPACITY);
let initial_model = load_model().unwrap_or_else(|| default_model().to_owned());
// Priority: HIVE_DEFAULT_MODEL (from hyperhive.model in agent.nix) >
// persisted runtime override > compiled-in DEFAULT_MODEL.
// The nix config always wins on rebuild; the persisted file is kept
// for within-session tracking only (see persist_model / set_model).
let initial_model = configured_model()
.map(str::to_owned)
.unwrap_or_else(|| load_model().unwrap_or_else(|| DEFAULT_MODEL.to_owned()));
// Restore rate_limited from the sentinel file — if the harness
// crashed while parked, we should still show the right status on
// cold load until the next turn clears it.