Watch
0
0
Fork
You've already forked hyperhive
0

remove c0re.operatorPronouns and c0re.contextWindowTokens

Both options are now ignored with a warning (the swarm-peers-removed.nix
shape), so a host that still sets one keeps evaluating.

- operatorPronouns: the agents' system prompt names the pronouns as
  she/her, the value the harness fell back to and the option's default.
  The --operator-pronouns flag, HiveEnv field, meta-flake let binding
  and HIVE_OPERATOR_PRONOUNS env var are gone.
- contextWindowTokens: the per-family defaults (haiku 200000, sonnet
  1000000, opus 1000000) move into hive-agent's harness_state as a
  table; the window the API reports after a turn still wins. The
  --context-window-tokens flag, HiveEnv field and the rendered
  HIVE_CONTEXT_WINDOW_TOKENS_<KEY> env vars are gone.
This commit is contained in:
atlas 2026-10-16 17:18:23 +02:00 • committed by mara
commit 4b5707768c
18 changed files with 151 additions and 258 deletions

View file

@ -67,20 +67,6 @@ pub struct Coordinator {
/// each per-agent flake so the agent's web UI can build the right
/// rebuild-button URL pointing back at the dashboard.
pub dashboard_port: u16,
/// Operator pronouns (free text) — `she/her` by default, set via
/// the NixOS module option `services.hive-c0re.operatorPronouns`.
/// Reaches each container as the `HIVE_OPERATOR_PRONOUNS` env var
/// (injected into `systemd.services.<harness>.environment` by the
/// meta flake); the harness substitutes it into the agent /
/// manager system prompt at boot.
pub operator_pronouns: String,
/// Per-model context-window sizes in tokens. Set via the host-level
/// `services.hive-c0re.contextWindowTokens` NixOS option; injected
/// into each container as `HIVE_CONTEXT_WINDOW_TOKENS_<KEY_UPPER>`
/// by the meta flake renderer. The harness uses these to derive
/// compaction / auto-reset watermarks and exposes the active value
/// on `/api/state` as `context_window_tokens`.
pub context_window_tokens: std::collections::HashMap<String, u64>,
/// Per-agent systemd `CPUQuota=` value (e.g. `"200%"`). Written into
/// the `container@h-<name>.service.d/` drop-in on every spawn/rebuild.
pub agent_cpu_quota: String,
@ -100,9 +86,8 @@ pub struct Coordinator {
/// estimate on the ST4TS tab. Set via `services.hyperhive.modelPrices`
/// and passed to `hive-c0re serve --model-prices <json>`. Models not
/// in the table fall back to the built-in estimate in `hive_stats`.
/// hive-c0re-local (read only by the `/api/stats-hive` handler), so —
/// unlike `context_window_tokens` — it is *not* part of `HiveEnv` and
/// is never injected into containers.
/// hive-c0re-local (read only by the `/api/stats-hive` handler), so it
/// is *not* part of `HiveEnv` and is never injected into containers.
pub model_prices: crate::hive_stats::PriceTable,
agents: Mutex<HashMap<String, AgentSocket>>,
/// Tombstone for transients that have JUST been cleared. The
@ -224,8 +209,6 @@ pub struct HiveEnv {
/// alive host-side by the module that resolved it.
pub claude_code_path: Option<String>,
pub dashboard_port: u16,
pub operator_pronouns: String,
pub context_window_tokens: std::collections::HashMap<String, u64>,
/// Per-agent systemd `CPUQuota=` value (e.g. `"200%"`).
pub agent_cpu_quota: String,
/// Per-agent systemd `MemoryMax=` value (e.g. `"4G"`).
@ -247,12 +230,6 @@ impl Default for HiveEnv {
nixpkgs_flake: String::new(),
claude_code_path: None,
dashboard_port: 7000,
operator_pronouns: "she/her".to_string(),
context_window_tokens: std::collections::HashMap::from([
("haiku".to_string(), 200_000),
("sonnet".to_string(), 1_000_000),
("opus".to_string(), 1_000_000),
]),
agent_cpu_quota: "200%".to_string(),
agent_memory_max: "4G".to_string(),
// Slightly below the kernel default of 100, so agent
@ -317,9 +294,7 @@ mod serve_config_tests {
assert_eq!(sc.env.hyperhive_flake, "/x");
assert_eq!(sc.env.dashboard_port, 1234);
// omitted → HiveEnv::default()
assert_eq!(sc.env.operator_pronouns, "she/her");
assert_eq!(sc.env.agent_cpu_quota, "200%");
assert_eq!(sc.env.context_window_tokens.get("sonnet"), Some(&1_000_000));
assert!(sc.model_prices.contains_key("opus"));
}
@ -432,8 +407,6 @@ impl Coordinator {
nixpkgs_flake,
claude_code_path,
dashboard_port,
operator_pronouns,
context_window_tokens,
agent_cpu_quota,
agent_memory_max,
agent_cpu_weight,
@ -473,8 +446,6 @@ impl Coordinator {
nixpkgs_flake,
claude_code_path,
dashboard_port,
operator_pronouns,
context_window_tokens,
agent_cpu_quota,
agent_memory_max,
agent_cpu_weight,
@ -506,8 +477,6 @@ impl Coordinator {
nixpkgs_flake: self.nixpkgs_flake.clone(),
claude_code_path: self.claude_code_path.clone(),
dashboard_port: self.dashboard_port,
operator_pronouns: self.operator_pronouns.clone(),
context_window_tokens: self.context_window_tokens.clone(),
agent_cpu_quota: self.agent_cpu_quota.clone(),
agent_memory_max: self.agent_memory_max.clone(),
agent_cpu_weight: self.agent_cpu_weight,

View file

@ -90,17 +90,6 @@ enum Cmd {
/// Override: dashboard HTTP port.
#[arg(long)]
dashboard_port: Option<u16>,
/// Override: operator pronouns (free text). Threaded into each
/// container's harness via `HIVE_OPERATOR_PRONOUNS`.
#[arg(long)]
operator_pronouns: Option<String>,
/// Override: per-model context-window sizes, as a JSON object
/// mapping model-family short name to token count. Threaded into
/// each container as `HIVE_CONTEXT_WINDOW_TOKENS_<KEY_UPPER>` env
/// vars. Set via the `services.hive-c0re.contextWindowTokens`
/// NixOS option.
#[arg(long)]
context_window_tokens: Option<String>,
/// Override: systemd `CPUQuota=` applied to every agent container
/// via a drop-in (e.g. `"200%"` = 2 cores). Set via
/// `services.hyperhive.agentCpuQuota`.
@ -150,8 +139,6 @@ async fn main() -> Result<()> {
hyperhive_flake,
nixpkgs_flake,
dashboard_port,
operator_pronouns,
context_window_tokens,
agent_cpu_quota,
agent_memory_max,
agent_cpu_weight,
@ -180,13 +167,6 @@ async fn main() -> Result<()> {
if let Some(v) = dashboard_port {
sc.env.dashboard_port = v;
}
if let Some(v) = operator_pronouns {
sc.env.operator_pronouns = v;
}
if let Some(v) = context_window_tokens {
sc.env.context_window_tokens =
serde_json::from_str(&v).context("--context-window-tokens: invalid JSON")?;
}
if let Some(v) = agent_cpu_quota {
sc.env.agent_cpu_quota = v;
}

View file

@ -334,25 +334,16 @@ fn render_hive_flake(hive: &HiveEnv, agents: &[AgentSpec]) -> String {
&hive.nixpkgs_flake,
hive.claude_code_path.as_deref(),
hive.dashboard_port,
&hive.operator_pronouns,
&hive.context_window_tokens,
agents,
)
}
#[allow(
clippy::too_many_arguments,
reason = "many genuine flake inputs (source flakes, port, pronouns, tokens, \
agents, forge base); a params struct would just move the same fields"
)]
fn render_flake(
hyperhive_flake: &str,
docs_flake: &str,
nixpkgs_flake: &str,
claude_code_path: Option<&str>,
dashboard_port: u16,
operator_pronouns: &str,
context_window_tokens: &std::collections::HashMap<String, u64>,
agents: &[AgentSpec],
) -> String {
render_flake_with_lookup(
@ -361,8 +352,6 @@ fn render_flake(
nixpkgs_flake,
claude_code_path,
dashboard_port,
operator_pronouns,
context_window_tokens,
agents,
agent_canonical_inputs,
)
@ -742,10 +731,8 @@ fn agent_canonical_inputs(name: &str) -> Vec<&'static str> {
/// agent flake-lock introspection.
#[allow(
clippy::too_many_lines,
clippy::too_many_arguments,
reason = "templated string-builder for the meta flake — the length is one \
contiguous fmt block, splitting it would just hide the shape; the \
args mirror the host-level config the flake is rendered from"
contiguous fmt block, splitting it would just hide the shape"
)]
fn render_flake_with_lookup<F>(
hyperhive_flake: &str,
@ -753,8 +740,6 @@ fn render_flake_with_lookup<F>(
nixpkgs_flake: &str,
claude_code_path: Option<&str>,
dashboard_port: u16,
operator_pronouns: &str,
context_window_tokens: &std::collections::HashMap<String, u64>,
agents: &[AgentSpec],
lookup: F,
) -> String
@ -830,13 +815,9 @@ where
}
}
out.push_str(" };\n outputs =\n { self, hyperhive, ... }@inputs:\n let\n");
// Free-text operator string — escape backslash + double-quote so a
// pronouns value like `he/him \ "rare"` round-trips into a valid
// nix string literal without breaking the flake.
let pronouns_escaped = operator_pronouns.replace('\\', "\\\\").replace('"', "\\\"");
let _ = writeln!(
out,
" dashboardPort = {dashboard_port};\n operatorPronouns = \"{pronouns_escaped}\";\n mkAgent = {{ name, isManager, port }}:"
" dashboardPort = {dashboard_port};\n mkAgent = {{ name, isManager, port }}:"
);
out.push_str(
r#" let
@ -1025,20 +1006,8 @@ where
HIVE_PORT = toString port;
HIVE_LABEL = name;
HIVE_DASHBOARD_PORT = toString dashboardPort;
HIVE_OPERATOR_PRONOUNS = operatorPronouns;",
",
);
// Per-model context-window env vars declared in the host-level
// `services.hive-c0re.contextWindowTokens` option. Use a sorted
// iterator for deterministic flake output (no spurious git diffs).
let mut sorted_tokens: Vec<(&String, &u64)> = context_window_tokens.iter().collect();
sorted_tokens.sort_by_key(|(k, _)| k.as_str());
for (key, val) in &sorted_tokens {
let upper_key = key.to_ascii_uppercase();
let _ = writeln!(
out,
" HIVE_CONTEXT_WINDOW_TOKENS_{upper_key} = \"{val}\";"
);
}
// Forwarded env vars — picked up from hive-c0re's own systemd unit
// env (`services.hyperhive.*` options flow through the hyperhive
// NixOS module into the host process). We copy whatever's set into
@ -1314,8 +1283,6 @@ mod tests {
"path:/nix/store/aaaa-nixpkgs-source",
None,
8000,
"she/her",
&std::collections::HashMap::new(),
&[sample_spec("alice", false, 9001)],
);
// nixpkgs is a top-level input with an explicit URL; hyperhive
@ -1360,8 +1327,6 @@ mod tests {
"path:/nix/store/aaaa-nixpkgs-source",
None,
8000,
"she/her",
&std::collections::HashMap::new(),
&[sample_spec("alice", false, 9001)],
);
assert!(
@ -1378,8 +1343,6 @@ mod tests {
"path:/nix/store/aaaa-nixpkgs-source",
None,
8000,
"she/her",
&std::collections::HashMap::new(),
&[sample_spec("alice", false, 9001)],
);
assert!(
@ -1418,8 +1381,6 @@ mod tests {
"path:/nix/store/aaaa-nixpkgs-source",
Some("/nix/store/cccc-claude-code-2.1.220"),
8000,
"she/her",
&std::collections::HashMap::new(),
&[sample_spec("alice", false, 9001)],
);
assert!(
@ -1446,8 +1407,6 @@ mod tests {
"path:/nix/store/aaaa-nixpkgs-source",
None,
8000,
"she/her",
&std::collections::HashMap::new(),
&[sample_spec("alice", false, 9001)],
);
assert!(
@ -1466,8 +1425,6 @@ mod tests {
"",
None,
8000,
"she/her",
&std::collections::HashMap::new(),
&[sample_spec("alice", false, 9001)],
);
assert!(
@ -1496,8 +1453,6 @@ mod tests {
"path:/nix/store/aaaa-nixpkgs-source",
None,
8000,
"she/her",
&std::collections::HashMap::new(),
&[
sample_spec("argus", false, 9001),
sample_spec("bitburner", false, 9002),
@ -1529,8 +1484,6 @@ mod tests {
"path:/nix/store/aaaa-nixpkgs-source",
None,
8000,
"she/her",
&std::collections::HashMap::new(),
&[sample_spec("alice", false, 9001)],
|_| Vec::new(),
);
@ -1567,8 +1520,6 @@ mod tests {
"path:/nix/store/aaaa-nixpkgs-source",
None,
8000,
"she/her",
&std::collections::HashMap::new(),
&[sample_spec("alice", false, 9001)],
);
unsafe {
@ -1612,8 +1563,6 @@ mod tests {
"path:/nix/store/aaaa-nixpkgs-source",
None,
8000,
"she/her",
&std::collections::HashMap::new(),
&[sample_spec("alice", false, 9001)],
)
};
@ -1792,8 +1741,6 @@ mod tests {
"path:/nix/store/aaaa-nixpkgs-source",
None,
8000,
"she/her",
&std::collections::HashMap::new(),
&[sample_spec("alice", false, 9001)],
);
unsafe {
@ -1828,8 +1775,6 @@ mod tests {
"path:/nix/store/aaaa-nixpkgs-source",
None,
8000,
"she/her",
&std::collections::HashMap::new(),
&[sample_spec("alice", false, 9001)],
);
let want = format!(
@ -1872,8 +1817,6 @@ mod tests {
"path:/nix/store/aaaa-nixpkgs-source",
None,
8000,
"she/her",
&std::collections::HashMap::new(),
&[sample_spec("alice", false, 9001)],
)
};
@ -1964,8 +1907,6 @@ mod tests {
"path:/nix/store/aaaa-nixpkgs-source",
None,
8000,
"she/her",
&std::collections::HashMap::new(),
&[sample_spec("alice", false, 9001)],
)
};
@ -2038,8 +1979,6 @@ mod tests {
"path:/nix/store/aaaa-nixpkgs-source",
None,
8000,
"she/her",
&std::collections::HashMap::new(),
&[sample_spec("alice", false, 9001)],
)
};