build every agent from the agent-base template
Delete nix/templates/ruth.nix, the ruth nixosConfiguration, module and toplevel, the hive-c0re managerToplevel option, and the meta flake's isManager switch with lifecycle::MANAGER_NAME. Every agent, ruth included, now builds from nix/templates/agent.nix. The template's only content beyond agent.nix was docs.enable = mkDefault true; docs.enable is off by default for every agent and ruth's own agent.nix turns it on. Refs #5377
This commit is contained in:
parent
1f214f9f01
commit
1b60084bf0
15 changed files with 85 additions and 95 deletions
|
|
@ -174,8 +174,8 @@ Swarm-level:
|
||||||
`nix/packages/swarm-ui.nix`, not in `packages.default`'s closure).
|
`nix/packages/swarm-ui.nix`, not in `packages.default`'s closure).
|
||||||
- **`nix/`** — `host-modules/` (the host stack), `agent-modules/`
|
- **`nix/`** — `host-modules/` (the host stack), `agent-modules/`
|
||||||
(per-agent harness features), `container-modules/` (guest side of
|
(per-agent harness features), `container-modules/` (guest side of
|
||||||
service containers), `templates/{agent,ruth}.nix` (container entry
|
service containers), `templates/agent.nix` (the container entry
|
||||||
points), `packages/`, `docs/` (options doc), `module-eval/` (NixOS
|
point), `packages/`, `docs/` (options doc), `module-eval/` (NixOS
|
||||||
module-eval tests), `builder/` (`check-flake`), `script-tests/`, plus
|
module-eval tests), `builder/` (`check-flake`), `script-tests/`, plus
|
||||||
`sources.nix` / `rust.nix` / `checks.nix` / `devshell.nix` /
|
`sources.nix` / `rust.nix` / `checks.nix` / `devshell.nix` /
|
||||||
`treefmt.nix` behind the thin `flake.nix`.
|
`treefmt.nix` behind the thin `flake.nix`.
|
||||||
|
|
|
||||||
|
|
@ -330,8 +330,10 @@ same as any other agent.
|
||||||
|
|
||||||
Differences from sub-agents:
|
Differences from sub-agents:
|
||||||
|
|
||||||
- `flake.nix` extends `hyperhive.nixosConfigurations.ruth`
|
- Reference docs: her `agent.nix` turns on `services.hyperhive.agent.docs.enable`.
|
||||||
(vs `agent-base`).
|
Her container builds from `agent-base` like every agent, and the seeded
|
||||||
|
`agent.nix` is the same for every name, so a newly created ruth has no docs
|
||||||
|
until a config PR adds that line.
|
||||||
- Web UI port via `lifecycle::agent_web_port("ruth")` — same
|
- Web UI port via `lifecycle::agent_web_port("ruth")` — same
|
||||||
FNV-1a hash as every other agent (8100..8999 range).
|
FNV-1a hash as every other agent (8100..8999 range).
|
||||||
- The root agent holds `manage_root_agent` (the swarm UI's setup
|
- The root agent holds `manage_root_agent` (the swarm UI's setup
|
||||||
|
|
|
||||||
|
|
@ -183,11 +183,10 @@ sibling), one shared `nix/agent-modules/` tree, one service unit
|
||||||
differences live in the agent's swarm permissions and the broker socket (which tools
|
differences live in the agent's swarm permissions and the broker socket (which tools
|
||||||
and manager-surface calls each agent receives).
|
and manager-surface calls each agent receives).
|
||||||
|
|
||||||
`agent.nix` and `ruth.nix` both import the shared `nix/agent-modules/`.
|
`nix/templates/agent.nix` is the one entry point every agent builds from, and
|
||||||
`ruth.nix` additionally defaults
|
it imports the shared `nix/agent-modules/`.
|
||||||
`services.hyperhive.agent.docs.enable` to `true`, so the root/manager
|
`services.hyperhive.agent.docs.enable` defaults to `false` for every agent,
|
||||||
gets the hyperhive reference docs readable at `$HIVE_DOCS_DIR` by
|
ruth included; an agent opts in from its own `agent.nix` (see
|
||||||
default; other agents opt in per `agent.nix` (see
|
|
||||||
[config.md](config.md), "Reference docs").
|
[config.md](config.md), "Reference docs").
|
||||||
|
|
||||||
### Environment variables set on the unit
|
### Environment variables set on the unit
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ Absent means the default. (The claude spawn + compaction themselves live in
|
||||||
## Reference docs (`services.hyperhive.agent.docs.enable`)
|
## Reference docs (`services.hyperhive.agent.docs.enable`)
|
||||||
|
|
||||||
```nix
|
```nix
|
||||||
services.hyperhive.agent.docs.enable = true; # default: false (true for the manager agent)
|
services.hyperhive.agent.docs.enable = true; # default: false
|
||||||
```
|
```
|
||||||
|
|
||||||
Makes the hyperhive `docs/` tree available inside the container at a nix
|
Makes the hyperhive `docs/` tree available inside the container at a nix
|
||||||
|
|
@ -17,8 +17,8 @@ sentence into the agent's system prompt so it knows the docs exist and
|
||||||
where to find them. `claude --add-dir` serves the tree so the full
|
where to find them. `claude --add-dir` serves the tree so the full
|
||||||
markdown is readable during every turn.
|
markdown is readable during every turn.
|
||||||
|
|
||||||
Enabled by default only for the root/manager agent (`nix/templates/ruth.nix`). Any
|
Off by default for every agent, ruth included. An agent opts in by adding the
|
||||||
agent can opt in by adding the line above to its `agent.nix`.
|
line above to its `agent.nix`.
|
||||||
|
|
||||||
The `docs/` source is a narrow flake input (`hyperhive-docs`) tracked
|
The `docs/` source is a narrow flake input (`hyperhive-docs`) tracked
|
||||||
separately from the main `hyperhive` flake so editing docs re-locks only
|
separately from the main `hyperhive` flake so editing docs re-locks only
|
||||||
|
|
|
||||||
|
|
@ -109,10 +109,6 @@
|
||||||
./nix/templates/agent.nix
|
./nix/templates/agent.nix
|
||||||
agentPackages
|
agentPackages
|
||||||
];
|
];
|
||||||
ruth.imports = [
|
|
||||||
./nix/templates/ruth.nix
|
|
||||||
agentPackages
|
|
||||||
];
|
|
||||||
# The full host stack (nix/host-modules/default.nix aggregator) plus
|
# The full host stack (nix/host-modules/default.nix aggregator) plus
|
||||||
# the package/source wiring from this flake. The wiring is a
|
# the package/source wiring from this flake. The wiring is a
|
||||||
# plain config module setting the `services.hyperhive.c0re.*`
|
# plain config module setting the `services.hyperhive.c0re.*`
|
||||||
|
|
@ -135,7 +131,7 @@
|
||||||
# Narrow docs/ source, threaded as its own meta-flake input
|
# Narrow docs/ source, threaded as its own meta-flake input
|
||||||
# so doc edits don't re-hash the whole flake source.
|
# so doc edits don't re-hash the whole flake source.
|
||||||
hyperhiveDocs = lib.mkDefault "${sources.hyperhiveDocsSource}";
|
hyperhiveDocs = lib.mkDefault "${sources.hyperhiveDocsSource}";
|
||||||
# Per-container toplevels — wired into
|
# The agent-base toplevel every container builds from — wired into
|
||||||
# `system.extraDependencies` when
|
# `system.extraDependencies` when
|
||||||
# `services.hyperhive.c0re.preBuildAgentTemplates` is on so
|
# `services.hyperhive.c0re.preBuildAgentTemplates` is on so
|
||||||
# the host system closure pre-fetches the heavy build
|
# the host system closure pre-fetches the heavy build
|
||||||
|
|
@ -143,7 +139,6 @@
|
||||||
# hardcoded to that system); the gate keeps aarch64 hosts
|
# hardcoded to that system); the gate keeps aarch64 hosts
|
||||||
# from pulling them in via cross-build.
|
# from pulling them in via cross-build.
|
||||||
agentBaseToplevel = lib.mkDefault self.packages.x86_64-linux.agent-base-toplevel;
|
agentBaseToplevel = lib.mkDefault self.packages.x86_64-linux.agent-base-toplevel;
|
||||||
managerToplevel = lib.mkDefault self.packages.x86_64-linux.ruth-toplevel;
|
|
||||||
};
|
};
|
||||||
services.hyperhive.deploy.swarm-controller.package =
|
services.hyperhive.deploy.swarm-controller.package =
|
||||||
lib.mkDefault
|
lib.mkDefault
|
||||||
|
|
@ -208,7 +203,6 @@
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
agent-base = mkContainer self.nixosModules.agent-base;
|
agent-base = mkContainer self.nixosModules.agent-base;
|
||||||
ruth = mkContainer self.nixosModules.ruth;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
devShells = forAllSystems ({ pkgs, rust, ... }: import ./nix/devshell.nix { inherit pkgs rust; });
|
devShells = forAllSystems ({ pkgs, rust, ... }: import ./nix/devshell.nix { inherit pkgs rust; });
|
||||||
|
|
|
||||||
|
|
@ -530,7 +530,7 @@ async fn set_nspawn_flags(
|
||||||
// Claude credentials land at `/home/<agent>/.claude` so the
|
// Claude credentials land at `/home/<agent>/.claude` so the
|
||||||
// `claude` CLI (which reads `$HOME/.claude`) finds them. The
|
// `claude` CLI (which reads `$HOME/.claude`) finds them. The
|
||||||
// harness service's environment sets `HOME` to the same path
|
// harness service's environment sets `HOME` to the same path
|
||||||
// (`agent.nix` / `ruth.nix` templates), so no `--setenv` plumbing
|
// (`agent.nix` template), so no `--setenv` plumbing
|
||||||
// is needed here — the bind alone is enough.
|
// is needed here — the bind alone is enough.
|
||||||
let claude_mount = container_claude_mount(agent_name);
|
let claude_mount = container_claude_mount(agent_name);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -31,9 +31,6 @@ pub use hive_host_sock::{AGENT_PREFIX, container_name};
|
||||||
/// 11 chars (it gets encoded into network interface names) and `AGENT_PREFIX`
|
/// 11 chars (it gets encoded into network interface names) and `AGENT_PREFIX`
|
||||||
/// (`h-`) takes 2, so the agent name itself is at most `MAX_AGENT_NAME` chars.
|
/// (`h-`) takes 2, so the agent name itself is at most `MAX_AGENT_NAME` chars.
|
||||||
pub const MAX_AGENT_NAME: usize = 9;
|
pub const MAX_AGENT_NAME: usize = 9;
|
||||||
/// Logical name of the manager agent (broker recipient, state-dir key,
|
|
||||||
/// meta flake attribute). All persistent state lives under `ruth/`.
|
|
||||||
pub const MANAGER_NAME: &str = "ruth";
|
|
||||||
/// Mount point of the per-agent runtime directory inside the container.
|
/// Mount point of the per-agent runtime directory inside the container.
|
||||||
pub const CONTAINER_RUNTIME_MOUNT: &str = "/run/hive";
|
pub const CONTAINER_RUNTIME_MOUNT: &str = "/run/hive";
|
||||||
|
|
||||||
|
|
@ -327,7 +324,6 @@ async fn agents_for_meta(name_to_add: Option<&str>) -> Result<Vec<crate::meta::A
|
||||||
.filter_map(|c| {
|
.filter_map(|c| {
|
||||||
let name = c.strip_prefix(AGENT_PREFIX)?.to_owned();
|
let name = c.strip_prefix(AGENT_PREFIX)?.to_owned();
|
||||||
Some(crate::meta::AgentSpec {
|
Some(crate::meta::AgentSpec {
|
||||||
is_manager: name == MANAGER_NAME,
|
|
||||||
port: agent_web_port(&name),
|
port: agent_web_port(&name),
|
||||||
name,
|
name,
|
||||||
})
|
})
|
||||||
|
|
@ -337,7 +333,6 @@ async fn agents_for_meta(name_to_add: Option<&str>) -> Result<Vec<crate::meta::A
|
||||||
&& !out.iter().any(|a| a.name == extra)
|
&& !out.iter().any(|a| a.name == extra)
|
||||||
{
|
{
|
||||||
out.push(crate::meta::AgentSpec {
|
out.push(crate::meta::AgentSpec {
|
||||||
is_manager: extra == MANAGER_NAME,
|
|
||||||
port: agent_web_port(extra),
|
port: agent_web_port(extra),
|
||||||
name: extra.to_owned(),
|
name: extra.to_owned(),
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,6 @@ pub const CONTAINER_MANAGER_META_MOUNT: &str = "/meta";
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct AgentSpec {
|
pub struct AgentSpec {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub is_manager: bool,
|
|
||||||
pub port: u16,
|
pub port: u16,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -804,13 +803,11 @@ where
|
||||||
out.push_str(" };\n outputs =\n { self, hyperhive, ... }@inputs:\n let\n");
|
out.push_str(" };\n outputs =\n { self, hyperhive, ... }@inputs:\n let\n");
|
||||||
let _ = writeln!(
|
let _ = writeln!(
|
||||||
out,
|
out,
|
||||||
" dashboardPort = {dashboard_port};\n mkAgent = {{ name, isManager, port }}:"
|
" dashboardPort = {dashboard_port};\n mkAgent = {{ name, port }}:"
|
||||||
);
|
);
|
||||||
out.push_str(
|
out.push_str(
|
||||||
r#" let
|
r#" let
|
||||||
base = if isManager
|
base = hyperhive.nixosConfigurations.agent-base;
|
||||||
then hyperhive.nixosConfigurations.ruth
|
|
||||||
else hyperhive.nixosConfigurations.agent-base;
|
|
||||||
input = inputs."agent-${name}";
|
input = inputs."agent-${name}";
|
||||||
service = "hive-agent";
|
service = "hive-agent";
|
||||||
in
|
in
|
||||||
|
|
@ -1013,11 +1010,8 @@ where
|
||||||
for spec in agents {
|
for spec in agents {
|
||||||
let _ = writeln!(
|
let _ = writeln!(
|
||||||
out,
|
out,
|
||||||
" {} = mkAgent {{ name = \"{}\"; isManager = {}; port = {}; }};",
|
" {} = mkAgent {{ name = \"{}\"; port = {}; }};",
|
||||||
spec.name,
|
spec.name, spec.name, spec.port,
|
||||||
spec.name,
|
|
||||||
if spec.is_manager { "true" } else { "false" },
|
|
||||||
spec.port,
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
out.push_str(" };\n };\n}\n");
|
out.push_str(" };\n };\n}\n");
|
||||||
|
|
@ -1229,10 +1223,9 @@ mod tests {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sample_spec(name: &str, is_manager: bool, port: u16) -> AgentSpec {
|
fn sample_spec(name: &str, port: u16) -> AgentSpec {
|
||||||
AgentSpec {
|
AgentSpec {
|
||||||
name: name.to_owned(),
|
name: name.to_owned(),
|
||||||
is_manager,
|
|
||||||
port,
|
port,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1259,7 +1252,7 @@ mod tests {
|
||||||
"path:/nix/store/aaaa-nixpkgs-source",
|
"path:/nix/store/aaaa-nixpkgs-source",
|
||||||
None,
|
None,
|
||||||
8000,
|
8000,
|
||||||
&[sample_spec("alice", false, 9001)],
|
&[sample_spec("alice", 9001)],
|
||||||
);
|
);
|
||||||
// nixpkgs is a top-level input with an explicit URL; hyperhive
|
// nixpkgs is a top-level input with an explicit URL; hyperhive
|
||||||
// follows it.
|
// follows it.
|
||||||
|
|
@ -1303,7 +1296,7 @@ mod tests {
|
||||||
"path:/nix/store/aaaa-nixpkgs-source",
|
"path:/nix/store/aaaa-nixpkgs-source",
|
||||||
None,
|
None,
|
||||||
8000,
|
8000,
|
||||||
&[sample_spec("alice", false, 9001)],
|
&[sample_spec("alice", 9001)],
|
||||||
);
|
);
|
||||||
assert!(
|
assert!(
|
||||||
!out.contains("hyperhive-docs"),
|
!out.contains("hyperhive-docs"),
|
||||||
|
|
@ -1319,7 +1312,7 @@ mod tests {
|
||||||
"path:/nix/store/aaaa-nixpkgs-source",
|
"path:/nix/store/aaaa-nixpkgs-source",
|
||||||
None,
|
None,
|
||||||
8000,
|
8000,
|
||||||
&[sample_spec("alice", false, 9001)],
|
&[sample_spec("alice", 9001)],
|
||||||
);
|
);
|
||||||
assert!(
|
assert!(
|
||||||
out.contains(r#"networking.hostName = "h-${name}";"#),
|
out.contains(r#"networking.hostName = "h-${name}";"#),
|
||||||
|
|
@ -1357,7 +1350,7 @@ mod tests {
|
||||||
"path:/nix/store/aaaa-nixpkgs-source",
|
"path:/nix/store/aaaa-nixpkgs-source",
|
||||||
Some("/nix/store/cccc-claude-code-2.1.220"),
|
Some("/nix/store/cccc-claude-code-2.1.220"),
|
||||||
8000,
|
8000,
|
||||||
&[sample_spec("alice", false, 9001)],
|
&[sample_spec("alice", 9001)],
|
||||||
);
|
);
|
||||||
assert!(
|
assert!(
|
||||||
out.contains(
|
out.contains(
|
||||||
|
|
@ -1383,7 +1376,7 @@ mod tests {
|
||||||
"path:/nix/store/aaaa-nixpkgs-source",
|
"path:/nix/store/aaaa-nixpkgs-source",
|
||||||
None,
|
None,
|
||||||
8000,
|
8000,
|
||||||
&[sample_spec("alice", false, 9001)],
|
&[sample_spec("alice", 9001)],
|
||||||
);
|
);
|
||||||
assert!(
|
assert!(
|
||||||
!out.contains("claudeCodePath"),
|
!out.contains("claudeCodePath"),
|
||||||
|
|
@ -1401,7 +1394,7 @@ mod tests {
|
||||||
"",
|
"",
|
||||||
None,
|
None,
|
||||||
8000,
|
8000,
|
||||||
&[sample_spec("alice", false, 9001)],
|
&[sample_spec("alice", 9001)],
|
||||||
);
|
);
|
||||||
assert!(
|
assert!(
|
||||||
out.contains("nixpkgs.follows = \"hyperhive/nixpkgs\""),
|
out.contains("nixpkgs.follows = \"hyperhive/nixpkgs\""),
|
||||||
|
|
@ -1430,9 +1423,9 @@ mod tests {
|
||||||
None,
|
None,
|
||||||
8000,
|
8000,
|
||||||
&[
|
&[
|
||||||
sample_spec("argus", false, 9001),
|
sample_spec("argus", 9001),
|
||||||
sample_spec("bitburner", false, 9002),
|
sample_spec("bitburner", 9002),
|
||||||
sample_spec("dmatrix", false, 9003),
|
sample_spec("dmatrix", 9003),
|
||||||
],
|
],
|
||||||
lookup,
|
lookup,
|
||||||
);
|
);
|
||||||
|
|
@ -1452,6 +1445,33 @@ mod tests {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn render_flake_builds_every_agent_from_agent_base() {
|
||||||
|
let out = render_flake(
|
||||||
|
"github:example/hyperhive",
|
||||||
|
"path:/nix/store/bbbb-hyperhive-docs-source",
|
||||||
|
"path:/nix/store/aaaa-nixpkgs-source",
|
||||||
|
None,
|
||||||
|
8000,
|
||||||
|
&[sample_spec("alice", 9001), sample_spec("ruth", 9002)],
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
out.matches("hyperhive.nixosConfigurations.").count(),
|
||||||
|
1,
|
||||||
|
"one base for every agent:\n{out}"
|
||||||
|
);
|
||||||
|
assert!(
|
||||||
|
out.contains("base = hyperhive.nixosConfigurations.agent-base;"),
|
||||||
|
"{out}"
|
||||||
|
);
|
||||||
|
for line in [
|
||||||
|
"alice = mkAgent { name = \"alice\"; port = 9001; };",
|
||||||
|
"ruth = mkAgent { name = \"ruth\"; port = 9002; };",
|
||||||
|
] {
|
||||||
|
assert!(out.contains(line), "missing `{line}`:\n{out}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn render_flake_skips_canonical_follows_when_lookup_returns_empty() {
|
fn render_flake_skips_canonical_follows_when_lookup_returns_empty() {
|
||||||
let out = render_flake_with_lookup(
|
let out = render_flake_with_lookup(
|
||||||
|
|
@ -1460,7 +1480,7 @@ mod tests {
|
||||||
"path:/nix/store/aaaa-nixpkgs-source",
|
"path:/nix/store/aaaa-nixpkgs-source",
|
||||||
None,
|
None,
|
||||||
8000,
|
8000,
|
||||||
&[sample_spec("alice", false, 9001)],
|
&[sample_spec("alice", 9001)],
|
||||||
|_| Vec::new(),
|
|_| Vec::new(),
|
||||||
);
|
);
|
||||||
// No agent-side follows when the lookup reports nothing
|
// No agent-side follows when the lookup reports nothing
|
||||||
|
|
@ -1496,7 +1516,7 @@ mod tests {
|
||||||
"path:/nix/store/aaaa-nixpkgs-source",
|
"path:/nix/store/aaaa-nixpkgs-source",
|
||||||
None,
|
None,
|
||||||
8000,
|
8000,
|
||||||
&[sample_spec("alice", false, 9001)],
|
&[sample_spec("alice", 9001)],
|
||||||
);
|
);
|
||||||
unsafe {
|
unsafe {
|
||||||
std::env::remove_var("HIVE_FORGE_URL");
|
std::env::remove_var("HIVE_FORGE_URL");
|
||||||
|
|
@ -1539,7 +1559,7 @@ mod tests {
|
||||||
"path:/nix/store/aaaa-nixpkgs-source",
|
"path:/nix/store/aaaa-nixpkgs-source",
|
||||||
None,
|
None,
|
||||||
8000,
|
8000,
|
||||||
&[sample_spec("alice", false, 9001)],
|
&[sample_spec("alice", 9001)],
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
let alpha = render_on("alpha-hive", "alpha-hive.example.test");
|
let alpha = render_on("alpha-hive", "alpha-hive.example.test");
|
||||||
|
|
@ -1717,7 +1737,7 @@ mod tests {
|
||||||
"path:/nix/store/aaaa-nixpkgs-source",
|
"path:/nix/store/aaaa-nixpkgs-source",
|
||||||
None,
|
None,
|
||||||
8000,
|
8000,
|
||||||
&[sample_spec("alice", false, 9001)],
|
&[sample_spec("alice", 9001)],
|
||||||
);
|
);
|
||||||
unsafe {
|
unsafe {
|
||||||
std::env::remove_var("HIVE_FORGE_URL");
|
std::env::remove_var("HIVE_FORGE_URL");
|
||||||
|
|
@ -1751,7 +1771,7 @@ mod tests {
|
||||||
"path:/nix/store/aaaa-nixpkgs-source",
|
"path:/nix/store/aaaa-nixpkgs-source",
|
||||||
None,
|
None,
|
||||||
8000,
|
8000,
|
||||||
&[sample_spec("alice", false, 9001)],
|
&[sample_spec("alice", 9001)],
|
||||||
);
|
);
|
||||||
let want = format!(
|
let want = format!(
|
||||||
"agent-alice.url = \"git+file://{}\"",
|
"agent-alice.url = \"git+file://{}\"",
|
||||||
|
|
@ -1793,7 +1813,7 @@ mod tests {
|
||||||
"path:/nix/store/aaaa-nixpkgs-source",
|
"path:/nix/store/aaaa-nixpkgs-source",
|
||||||
None,
|
None,
|
||||||
8000,
|
8000,
|
||||||
&[sample_spec("alice", false, 9001)],
|
&[sample_spec("alice", 9001)],
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -1883,7 +1903,7 @@ mod tests {
|
||||||
"path:/nix/store/aaaa-nixpkgs-source",
|
"path:/nix/store/aaaa-nixpkgs-source",
|
||||||
None,
|
None,
|
||||||
8000,
|
8000,
|
||||||
&[sample_spec("alice", false, 9001)],
|
&[sample_spec("alice", 9001)],
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
unsafe {
|
unsafe {
|
||||||
|
|
@ -1955,7 +1975,7 @@ mod tests {
|
||||||
"path:/nix/store/aaaa-nixpkgs-source",
|
"path:/nix/store/aaaa-nixpkgs-source",
|
||||||
None,
|
None,
|
||||||
8000,
|
8000,
|
||||||
&[sample_spec("alice", false, 9001)],
|
&[sample_spec("alice", 9001)],
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
unsafe {
|
unsafe {
|
||||||
|
|
@ -1987,7 +2007,7 @@ mod tests {
|
||||||
agent_memory_max: cap.to_owned(),
|
agent_memory_max: cap.to_owned(),
|
||||||
..HiveEnv::default()
|
..HiveEnv::default()
|
||||||
};
|
};
|
||||||
let agents = [sample_spec("alice", false, 9001)];
|
let agents = [sample_spec("alice", 9001)];
|
||||||
let small = render_hive_flake(&hive("4G"), &agents);
|
let small = render_hive_flake(&hive("4G"), &agents);
|
||||||
let large = render_hive_flake(&hive("16G"), &agents);
|
let large = render_hive_flake(&hive("16G"), &agents);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
# Shared scaffolding for every hyperhive harness container.
|
# Shared scaffolding for every hyperhive harness container.
|
||||||
# `../templates/agent.nix` and `../templates/ruth.nix` both import
|
# `../templates/agent.nix`, the one entry point every agent builds from,
|
||||||
# agents use the same service unit regardless of which entry-point
|
# imports it.
|
||||||
# they came from.
|
|
||||||
#
|
#
|
||||||
# This is the core module: container plumbing (boot/nix/nixpkgs),
|
# This is the core module: container plumbing (boot/nix/nixpkgs),
|
||||||
# base tooling, and the cross-cutting `services.hyperhive.agent.icon` option. Each
|
# base tooling, and the cross-cutting `services.hyperhive.agent.icon` option. Each
|
||||||
|
|
|
||||||
|
|
@ -14,9 +14,8 @@
|
||||||
via `claude --add-dir`, so the markdown is readable at
|
via `claude --add-dir`, so the markdown is readable at
|
||||||
`$HIVE_DOCS_DIR/`, and appends a single pointer sentence to the agent's
|
`$HIVE_DOCS_DIR/`, and appends a single pointer sentence to the agent's
|
||||||
system prompt so it knows the docs exist (see
|
system prompt so it knows the docs exist (see
|
||||||
`hive-agent::prompt::render`). Default-on for the root/manager agent
|
`hive-agent::prompt::render`). Off by default for every agent; an agent
|
||||||
(see `../templates/ruth.nix`), off elsewhere; any agent can flip it from its
|
turns it on from its `agent.nix`.
|
||||||
`agent.nix`.
|
|
||||||
'';
|
'';
|
||||||
|
|
||||||
options.services.hyperhive.agent.docs.source = lib.mkOption {
|
options.services.hyperhive.agent.docs.source = lib.mkOption {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
# The hyperhive-built packages the harness modules consume, threaded
|
# The hyperhive-built packages the harness modules consume, threaded
|
||||||
# in explicitly as an option — no overlay. The flake's
|
# in explicitly as an option — no overlay. The flake's
|
||||||
# `nixosModules.{agent-base,ruth}` set this to the flake's own package
|
# `nixosModules.agent-base` sets this to the flake's own package
|
||||||
# outputs via `lib.mkDefault`, so a per-agent override of an
|
# outputs via `lib.mkDefault`, so a per-agent override of an
|
||||||
# individual key still wins.
|
# individual key still wins.
|
||||||
{ lib, ... }:
|
{ lib, ... }:
|
||||||
|
|
@ -15,8 +15,8 @@
|
||||||
`hive-forge`, `hive-forge-notify`, `hive-github-notify`,
|
`hive-forge`, `hive-forge-notify`, `hive-github-notify`,
|
||||||
`hive-matrix-daemon`,
|
`hive-matrix-daemon`,
|
||||||
`hive-metric`, `hive-screen-mcp`) plus the `assets`, `frontend`,
|
`hive-metric`, `hive-screen-mcp`) plus the `assets`, `frontend`,
|
||||||
`reference-docs` and `claude-plugins` trees. Wired by the flake's agent-base/ruth
|
`reference-docs` and `claude-plugins` trees. Wired by the flake's agent-base
|
||||||
nixosModules to `hyperhive.packages.<system>.*`; override an
|
nixosModule to `hyperhive.packages.<system>.*`; override an
|
||||||
individual key per-agent to swap in a patched binary.
|
individual key per-agent to swap in a patched binary.
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -189,7 +189,7 @@ in
|
||||||
# above for the rationale.
|
# above for the rationale.
|
||||||
environment.etc."hyperhive/serve.json".text = serveConfigJson;
|
environment.etc."hyperhive/serve.json".text = serveConfigJson;
|
||||||
|
|
||||||
# Pull the per-container toplevels into the host system closure.
|
# Pull the agent-base toplevel into the host system closure.
|
||||||
# `system.extraDependencies` adds paths to the system build
|
# `system.extraDependencies` adds paths to the system build
|
||||||
# without referencing them at runtime — nixos-rebuild fetches /
|
# without referencing them at runtime — nixos-rebuild fetches /
|
||||||
# builds them, they end up in /nix/store, and the first
|
# builds them, they end up in /nix/store, and the first
|
||||||
|
|
@ -197,7 +197,6 @@ in
|
||||||
# do. Gated because the closure is sizeable and pinned to x86_64.
|
# do. Gated because the closure is sizeable and pinned to x86_64.
|
||||||
system.extraDependencies = lib.optionals cfg.preBuildAgentTemplates [
|
system.extraDependencies = lib.optionals cfg.preBuildAgentTemplates [
|
||||||
cfg.agentBaseToplevel
|
cfg.agentBaseToplevel
|
||||||
cfg.managerToplevel
|
|
||||||
];
|
];
|
||||||
|
|
||||||
# Unprivileged coordinator user. hive-c0re runs as this user;
|
# Unprivileged coordinator user. hive-c0re runs as this user;
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,12 @@
|
||||||
...
|
...
|
||||||
}:
|
}:
|
||||||
{
|
{
|
||||||
|
imports = [
|
||||||
|
(lib.mkRemovedOptionModule [ "services" "hyperhive" "c0re" "managerToplevel" ] ''
|
||||||
|
Every agent, ruth included, builds from `agentBaseToplevel`. Remove this definition.
|
||||||
|
'')
|
||||||
|
];
|
||||||
|
|
||||||
options.services.hyperhive.c0re = {
|
options.services.hyperhive.c0re = {
|
||||||
package = lib.mkOption {
|
package = lib.mkOption {
|
||||||
type = lib.types.package;
|
type = lib.types.package;
|
||||||
|
|
@ -92,14 +98,6 @@
|
||||||
enabled.
|
enabled.
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
managerToplevel = lib.mkOption {
|
|
||||||
type = lib.types.package;
|
|
||||||
defaultText = lib.literalExpression "hyperhive.packages.x86_64-linux.ruth-toplevel";
|
|
||||||
description = ''
|
|
||||||
Pre-built manager (ruth) container system closure — see
|
|
||||||
`agentBaseToplevel`.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
nixpkgsFlake = lib.mkOption {
|
nixpkgsFlake = lib.mkOption {
|
||||||
type = lib.types.str;
|
type = lib.types.str;
|
||||||
default = "path:${pkgs.path}";
|
default = "path:${pkgs.path}";
|
||||||
|
|
@ -176,8 +174,8 @@
|
||||||
default = false;
|
default = false;
|
||||||
example = true;
|
example = true;
|
||||||
description = ''
|
description = ''
|
||||||
Pre-fetch the per-container system closures (agent-base +
|
Pre-fetch the agent-base container system closure, which every
|
||||||
manager toplevels) into the host's /nix/store as part of this
|
agent builds from, into the host's /nix/store as part of this
|
||||||
host's NixOS build, instead of letting the first agent spawn
|
host's NixOS build, instead of letting the first agent spawn
|
||||||
do all the work.
|
do all the work.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -273,7 +273,7 @@ in
|
||||||
# is exposed too since it's independently useful/inspectable.
|
# is exposed too since it's independently useful/inspectable.
|
||||||
inherit swagger-ui-dist swagger-ui-theme;
|
inherit swagger-ui-dist swagger-ui-theme;
|
||||||
|
|
||||||
# Pre-built per-container system closures. Exposed as packages
|
# Pre-built system closure every agent container builds from. Exposed as a package
|
||||||
# so operators can `nix build .#agent-base-toplevel` (or wire
|
# so operators can `nix build .#agent-base-toplevel` (or wire
|
||||||
# them into their host system closure via the
|
# them into their host system closure via the
|
||||||
# `preBuildAgentTemplates` option on the hive-c0re module —
|
# `preBuildAgentTemplates` option on the hive-c0re module —
|
||||||
|
|
@ -283,13 +283,12 @@ in
|
||||||
# when the meta evaluator goes to build the container.
|
# when the meta evaluator goes to build the container.
|
||||||
#
|
#
|
||||||
# nixosConfigurations are pinned to x86_64-linux (nixos-
|
# nixosConfigurations are pinned to x86_64-linux (nixos-
|
||||||
# containers only run native arch), so these toplevels are
|
# containers only run native arch), so this toplevel is
|
||||||
# only useful on an x86_64-linux host — flake check across
|
# only useful on an x86_64-linux host — flake check across
|
||||||
# systems still tolerates evaluating them on aarch64 because
|
# systems still tolerates evaluating it on aarch64 because
|
||||||
# they're plain derivations, but `nix build` from a non-x86
|
# it's a plain derivation, but `nix build` from a non-x86
|
||||||
# host would only succeed via a remote x86 builder.
|
# host would only succeed via a remote x86 builder.
|
||||||
agent-base-toplevel = self.nixosConfigurations.agent-base.config.system.build.toplevel;
|
agent-base-toplevel = self.nixosConfigurations.agent-base.config.system.build.toplevel;
|
||||||
ruth-toplevel = self.nixosConfigurations.ruth.config.system.build.toplevel;
|
|
||||||
|
|
||||||
# Auto-generated nix options reference for hyperhive.
|
# Auto-generated nix options reference for hyperhive.
|
||||||
# `docs` bundles host + swarm + deploy + agent pages into one tree;
|
# `docs` bundles host + swarm + deploy + agent pages into one tree;
|
||||||
|
|
|
||||||
|
|
@ -1,14 +0,0 @@
|
||||||
{ lib, ... }:
|
|
||||||
{
|
|
||||||
# Entry-point for the privileged root agent (ruth). Referenced from
|
|
||||||
# `flake.nix` (`nixosConfigurations.ruth`) and the meta-flake's
|
|
||||||
# `applied/ruth/flake.nix`.
|
|
||||||
imports = [ ../agent-modules ];
|
|
||||||
|
|
||||||
# The root/manager bootstraps a fresh hive, so it gets the hyperhive
|
|
||||||
# reference docs made available by default (readable at
|
|
||||||
# `$HIVE_DOCS_DIR/`, added via `claude --add-dir`). `mkDefault` so a
|
|
||||||
# manager's own `agent.nix` can still turn it off. Other agents default
|
|
||||||
# off.
|
|
||||||
services.hyperhive.agent.docs.enable = lib.mkDefault true;
|
|
||||||
}
|
|
||||||
Loading…
Reference in a new issue