Watch
0
0
Fork
You've already forked hyperhive
0

hive-agent: stop writing active_model to the harness state file, nothing reads it

This commit is contained in:
damocles 2026-11-15 14:10:50 +01:00 • committed by mara
commit 05c193859f
2 changed files with 13 additions and 38 deletions

View file

@ -393,15 +393,10 @@ impl Bus {
let (tx, _) = broadcast::channel(CHANNEL_CAPACITY);
let (initial_model, model_source) = local_model(configured_model());
let (initial_effort, effort_source) = local_effort(configured_effort());
// Restore rate_limited (and needs_login) from the consolidated
// harness state file so the dashboard shows the correct status
// on cold load if the harness crashed while parked.
let (was_rate_limited, was_needs_login, _) = read_harness_state();
// Write the resolved active model to hyperhive-harness.json on
// startup so hive-c0re can surface the model badge without reading
// hyperhive-model directly. Written once here; updated on every
// apply_model() call and emit_status() call.
write_harness_state(was_rate_limited, was_needs_login, Some(&initial_model));
// Restore rate_limited from the consolidated harness state file so
// the dashboard shows the correct status on cold load if the harness
// crashed while parked.
let (was_rate_limited, _) = read_harness_state();
Self {
tx: Arc::new(tx),
event_seq: Arc::new(AtomicU64::new(0)),
@ -575,11 +570,6 @@ impl Bus {
pub fn apply_model(&self, value: String, source: Source) {
self.model.lock().unwrap().clone_from(&value);
*self.model_source.lock().unwrap() = source;
// Mirror the resolved model into hyperhive-harness.json so
// hive-c0re can surface it on the dashboard badge without reading
// the hyperhive-model override file directly.
let (rate_limited, needs_login, _) = read_harness_state();
write_harness_state(rate_limited, needs_login, Some(&value));
self.emit(LiveEvent::ModelChanged { model: value });
}
@ -905,7 +895,7 @@ impl Bus {
// turns, so the two callers never overlap. Documented rather than
// locked because adding a Mutex here would be overkill for the
// actual call pattern.
let (_, current_needs_login, _) = read_harness_state();
let (_, current_needs_login) = read_harness_state();
let new_needs_login = if status == "needs_login_idle" {
true
} else if status == "online" {
@ -913,8 +903,7 @@ impl Bus {
} else {
current_needs_login
};
let current_model = self.model.lock().unwrap().clone();
write_harness_state(new_rate_limited, new_needs_login, Some(&current_model));
write_harness_state(new_rate_limited, new_needs_login);
self.emit(LiveEvent::StatusChanged { status });
}

View file

@ -131,7 +131,7 @@ fn write_harness_json(v: &serde_json::Value) {
}
}
pub(crate) fn read_harness_state() -> (bool, bool, Option<String>) {
pub(crate) fn read_harness_state() -> (bool, bool) {
// Try the new consolidated file first.
if let Ok(raw) = std::fs::read_to_string(harness_json_path())
&& let Ok(v) = serde_json::from_str::<serde_json::Value>(&raw)
@ -144,38 +144,25 @@ pub(crate) fn read_harness_state() -> (bool, bool, Option<String>) {
.get("needs_login")
.and_then(serde_json::Value::as_bool)
.unwrap_or(false);
let active_model = v
.get("active_model")
.and_then(serde_json::Value::as_str)
.filter(|s| !s.is_empty())
.map(str::to_owned);
return (rate_limited, needs_login, active_model);
return (rate_limited, needs_login);
}
// Fall back to legacy sentinel files written by older harness builds.
let state_dir = crate::paths::state_dir();
let rate_limited = state_dir.join("hyperhive-rate-limited").exists();
let needs_login = state_dir.join("hyperhive-needs-login").exists();
(rate_limited, needs_login, None)
(rate_limited, needs_login)
}
/// Write the turn-loop's harness state fields via a read-modify-write so
/// any other writer's fields in the consolidated state file survive.
/// Pass `active_model: Some(s)` to update the resolved model (surfaced in
/// the dashboard badge); `None` leaves the stored value untouched.
pub(crate) fn write_harness_state(
rate_limited: bool,
needs_login: bool,
active_model: Option<&str>,
) {
/// any other field in the consolidated state file survives, including an
/// `active_model` an older harness left behind (nothing reads it).
pub(crate) fn write_harness_state(rate_limited: bool, needs_login: bool) {
let _guard = HARNESS_JSON_LOCK
.lock()
.unwrap_or_else(std::sync::PoisonError::into_inner);
let mut v = read_harness_json();
v["rate_limited"] = rate_limited.into();
v["needs_login"] = needs_login.into();
if let Some(model) = active_model {
v["active_model"] = model.into();
}
write_harness_json(&v);
}