agents: remove the hive-level /effort control too
mara on #5034: "effort shares /models fate". The per-agent web UI no longer sets effort: the `/effort` slash command, the effort picker, `POST /api/effort`, `Bus::set_effort`, the `hyperhive-effort` writer, `EFFORT_LEVELS`/`is_valid_effort` and the ACP effort-list payload are gone, and `lib/modelEffort.ts` with them. The effort chip is display-only and shows its source (`effort_source` in `/api/state`); on ACP it stays hidden while the session offers no effort level. The read side is unchanged: with no swarm value an agent runs an existing `hyperhive-effort` file, else its agent.nix effort, else medium. Existing files are not touched. Refs #5034
This commit is contained in:
parent
594693f4c7
commit
ed271e655f
25 changed files with 170 additions and 464 deletions
|
|
@ -28,9 +28,9 @@ pub(crate) fn load_model() -> Option<String> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Path to the persisted effort-level file. Sibling of `hyperhive-model`,
|
||||
/// overridable via `HYPERHIVE_EFFORT_FILE` for dev / tests; otherwise
|
||||
/// derived from the agent's harness dir.
|
||||
/// Path to the `hyperhive-effort` file. The harness only reads it, as the
|
||||
/// fallback in [`local_effort`]. Overridable via `HYPERHIVE_EFFORT_FILE` for
|
||||
/// dev / tests; otherwise derived from the agent's harness dir.
|
||||
fn effort_file_path() -> PathBuf {
|
||||
std::env::var_os("HYPERHIVE_EFFORT_FILE").map_or_else(
|
||||
|| crate::paths::harness_dir().join("hyperhive-effort"),
|
||||
|
|
@ -65,10 +65,9 @@ fn model_from(configured: Option<&str>, file: Option<String>) -> (String, Source
|
|||
}
|
||||
|
||||
/// The effort this agent runs at when the swarm sets none, and where it
|
||||
/// comes from. The inverse of [`local_model`]: a persisted operator pick
|
||||
/// wins over `configured` (`HIVE_DEFAULT_EFFORT`), so the runtime choice
|
||||
/// survives a harness restart (it only resets on `--purge`); nix is the
|
||||
/// default for a never-touched agent.
|
||||
/// comes from. The inverse of [`local_model`]: an existing
|
||||
/// `hyperhive-effort` file wins over `configured` (`HIVE_DEFAULT_EFFORT`);
|
||||
/// nix is the default for an agent without one.
|
||||
pub(crate) fn local_effort(configured: Option<&str>) -> (String, Source) {
|
||||
effort_from(configured, load_effort())
|
||||
}
|
||||
|
|
@ -81,14 +80,6 @@ fn effort_from(configured: Option<&str>, file: Option<String>) -> (String, Sourc
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) fn persist_effort(level: &str) -> std::io::Result<()> {
|
||||
let path = effort_file_path();
|
||||
if let Some(parent) = path.parent() {
|
||||
let _ = std::fs::create_dir_all(parent);
|
||||
}
|
||||
std::fs::write(path, format!("{level}\n"))
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Consolidated harness state file
|
||||
// ---------------------------------------------------------------------------
|
||||
|
|
@ -233,22 +224,11 @@ pub fn configured_model() -> Option<&'static str> {
|
|||
/// into `prompts/claude-settings.json`.
|
||||
pub const DEFAULT_EFFORT: &str = "medium";
|
||||
|
||||
/// Valid claude `--effort` levels, ascending. The operator picker is
|
||||
/// constrained to these; [`is_valid_effort`] guards the persist path.
|
||||
pub const EFFORT_LEVELS: [&str; 5] = ["low", "medium", "high", "xhigh", "max"];
|
||||
|
||||
/// True iff `level` is one of [`EFFORT_LEVELS`].
|
||||
#[must_use]
|
||||
pub fn is_valid_effort(level: &str) -> bool {
|
||||
EFFORT_LEVELS.contains(&level)
|
||||
}
|
||||
|
||||
/// Return the effort level declared in `HIVE_DEFAULT_EFFORT` (set from
|
||||
/// `services.hyperhive.agent.effortLevel` in `agent.nix`), or `None` if absent / empty.
|
||||
/// Mirrors [`configured_model`]'s env shape. Unlike model, the persisted
|
||||
/// runtime override takes precedence over this baseline (see `Bus::new`):
|
||||
/// the operator's effort pick sticks across harness restart, with the nix
|
||||
/// value only the default when no override was ever set.
|
||||
/// Mirrors [`configured_model`]'s env shape. Unlike model, a
|
||||
/// `hyperhive-effort` file takes precedence over this baseline (see
|
||||
/// [`local_effort`]).
|
||||
#[must_use]
|
||||
pub fn configured_effort() -> Option<&'static str> {
|
||||
std::env::var("HIVE_DEFAULT_EFFORT")
|
||||
|
|
@ -298,28 +278,11 @@ pub fn context_window_tokens(model: &str) -> u64 {
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::{
|
||||
DEFAULT_EFFORT, DEFAULT_MODEL, EFFORT_LEVELS, Source, effort_from, is_valid_effort,
|
||||
model_from,
|
||||
};
|
||||
use super::{DEFAULT_EFFORT, DEFAULT_MODEL, Source, effort_from, model_from};
|
||||
|
||||
#[test]
|
||||
fn effort_validation_accepts_only_known_levels() {
|
||||
for level in EFFORT_LEVELS {
|
||||
assert!(is_valid_effort(level), "{level} should be valid");
|
||||
}
|
||||
// Out-of-set, empty, and wrong-case inputs are rejected so a bad
|
||||
// picker POST never reaches `claude --effort`.
|
||||
for bad in ["lowest", "", "MEDIUM", "ultra", "high "] {
|
||||
assert!(!is_valid_effort(bad), "{bad:?} should be rejected");
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn compiled_default_effort_is_selectable() {
|
||||
// The fallback must itself be a valid level, and match the value
|
||||
// baked into prompts/claude-settings.json.
|
||||
assert!(EFFORT_LEVELS.contains(&DEFAULT_EFFORT));
|
||||
fn compiled_default_effort_matches_claude_settings() {
|
||||
// The value baked into prompts/claude-settings.json.
|
||||
assert_eq!(DEFAULT_EFFORT, "medium");
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue