nix: move the agent option namespace under services.hyperhive.agent

Every per-agent harness option lived at the top-level `hyperhive.*` while
the host tier has always been `services.hyperhive.*`. Move all 52 agent-tier
option leaves (33 top-level names across 16 modules) to
`services.hyperhive.agent.*`, repoint every read, and keep existing agent
configs evaluating through one `mkRenamedOptionModule` per old leaf path in
the new nix/agent-modules/renamed-options.nix.

The shims are per leaf rather than per namespace: `user`, `mcp`, `otel`,
`queue`, `docs`, `forge`, `frontend`, `github`, `gui`, `logs`, `matrix` and
`cargo` are plain attrsets of declarations, not submodule-typed options, so
a parent-path rename would not reach their children. Three read-only
options (`frontend.mergedDist`, `queue.clientIdFile`,
`queue.clientSecretFile`) deliberately get no shim — a rename contributes a
definition, which a read-only option refuses; the exclusions are commented
in place.

Refs #4473
This commit is contained in:
atlas 2026-09-17 19:29:17 +02:00
commit 3662eda440
21 changed files with 531 additions and 290 deletions

View file

@ -13,12 +13,12 @@
...
}:
let
userName = config.hyperhive.user.name;
userName = config.services.hyperhive.agent.user.name;
homeDir = "/home/${userName}";
# Hive-wide OpenTelemetry config (host-driven; baked in per-agent by
# meta.rs `otel_config`). Options declared in `otel.nix`, which also
# exports the generic OTLP environment this container's producers read.
otelCfg = config.hyperhive.otel;
otelCfg = config.services.hyperhive.agent.otel;
# Hive display name, read from the per-agent option meta.rs renders
# (NOT from `environment.variables` — that carries the same name at
# *runtime* only, so reading it here silently yielded "unknown" on
@ -26,12 +26,15 @@ let
# means the hive did not name itself; "unknown" is then an honest label
# rather than a guess.
hiveDisplayName =
if config.hyperhive.hiveName == null then "unknown" else config.hyperhive.hiveName;
if config.services.hyperhive.agent.hiveName == null then
"unknown"
else
config.services.hyperhive.agent.hiveName;
# Effective per-agent MemoryMax=, in bytes, injected by meta.rs's
# per-agent flake render (`hyperhive.claudeMemoryMaxBytes`). `null`
# per-agent flake render (`services.hyperhive.agent.claudeMemoryMaxBytes`). `null`
# when the effective cap is unbounded ("infinity") or a RAM
# percentage — see `resource_limits::effective_memory_bytes`.
memoryMaxBytes = config.hyperhive.claudeMemoryMaxBytes;
memoryMaxBytes = config.services.hyperhive.agent.claudeMemoryMaxBytes;
# Base claude-code environment applied to every agent regardless of OTEL.
# Shipped via the managed settings `env` block so claude and `hivectl
# choom` both inherit them without a launch wrapper.
@ -99,13 +102,13 @@ in
# `MemoryMax=` (per-agent `resource-limits.json` override, else the
# hive-wide `services.hyperhive.agentMemoryMax`) — see
# `resource_limits::effective_memory_bytes_from`. Not meant to be set
# directly in an agent.nix, same convention as `hyperhive.otel.*`
# directly in an agent.nix, same convention as `services.hyperhive.agent.otel.*`
# above; the host option (or `hivectl agent <name> set-limits`) is
# the real operator knob, and this only reflects the value baked in at
# the agent's *last rebuild* — `set-limits` still applies the
# cgroup cap live via a drop-in reload, but this derived heap ceiling
# needs a rebuild to pick up a new value.
options.hyperhive.hiveName = lib.mkOption {
options.services.hyperhive.agent.hiveName = lib.mkOption {
type = lib.types.nullOr lib.types.str;
default = null;
internal = true;
@ -122,7 +125,7 @@ in
'';
};
options.hyperhive.swarmName = lib.mkOption {
options.services.hyperhive.agent.swarmName = lib.mkOption {
type = lib.types.nullOr lib.types.str;
default = null;
internal = true;
@ -130,13 +133,13 @@ in
Human-readable swarm name, rendered per-agent by
`meta.rs::render_flake` from the host's
`services.hyperhive.swarm.name`. Same build-time/runtime split as
`hyperhive.hiveName`.
`services.hyperhive.agent.hiveName`.
`null` means the hive is not part of a named swarm.
'';
};
options.hyperhive.claudeMemoryMaxBytes = lib.mkOption {
options.services.hyperhive.agent.claudeMemoryMaxBytes = lib.mkOption {
type = lib.types.nullOr lib.types.ints.positive;
default = null;
internal = true;
@ -150,11 +153,11 @@ in
'';
};
options.hyperhive.claudeMarketplaces = lib.mkOption {
options.services.hyperhive.agent.claudeMarketplaces = lib.mkOption {
type = lib.types.listOf lib.types.str;
default = [
"anthropics/claude-plugins-official"
"${config.hyperhive.packages.claude-plugins}"
"${config.services.hyperhive.agent.packages.claude-plugins}"
];
defaultText = lib.literalMD ''
`[ "anthropics/claude-plugins-official" "''${hyperhive.packages.claude-plugins}" ]`
@ -169,7 +172,7 @@ in
entry is passed to `claude plugin marketplace add <source>`
(`owner/repo`, full git URL, or local path). Idempotent
re-adding an existing marketplace is treated as success.
Required before `hyperhive.claudePlugins` entries that
Required before `services.hyperhive.agent.claudePlugins` entries that
reference a marketplace (e.g. `foo@claude-plugins-official`).
Rendered to `/etc/hyperhive/claude-marketplaces.json`.
@ -185,7 +188,7 @@ in
'';
};
options.hyperhive.claudePlugins = lib.mkOption {
options.services.hyperhive.agent.claudePlugins = lib.mkOption {
type = lib.types.listOf lib.types.str;
default = [
"skill-creator@claude-plugins-official"
@ -224,7 +227,7 @@ in
'';
};
options.hyperhive.claudePluginsAutoUpdate = lib.mkOption {
options.services.hyperhive.agent.claudePluginsAutoUpdate = lib.mkOption {
type = lib.types.bool;
default = false;
description = ''
@ -239,13 +242,13 @@ in
config = {
environment.etc."hyperhive/claude-plugins.json".text =
builtins.toJSON config.hyperhive.claudePlugins;
builtins.toJSON config.services.hyperhive.agent.claudePlugins;
environment.etc."hyperhive/claude-marketplaces.json".text =
builtins.toJSON config.hyperhive.claudeMarketplaces;
builtins.toJSON config.services.hyperhive.agent.claudeMarketplaces;
environment.etc."hyperhive/claude-plugins-auto-update.json".text =
builtins.toJSON config.hyperhive.claudePluginsAutoUpdate;
builtins.toJSON config.services.hyperhive.agent.claudePluginsAutoUpdate;
# Hive-enforced claude settings. claude-code auto-discovers managed
# settings at this canonical Linux path (precedence #1, read-only,
@ -263,7 +266,7 @@ in
# `hivectl choom`) so no launch wrapper is needed.
environment.etc."claude-code/managed-settings.json".source =
let
baseSettings = "${config.hyperhive.packages.assets}/share/hyperhive/prompts/claude-settings.json";
baseSettings = "${config.services.hyperhive.agent.packages.assets}/share/hyperhive/prompts/claude-settings.json";
# Merge base env (always) with OTEL env (when enabled). jq is always
# run — `baseClaudeEnv` contains per-agent values (e.g.
# CLAUDE_REMOTE_CONTROL_SESSION_NAME_PREFIX) that can't live in the