feat(#513): inject HIVE_TOOL_GROUPS from meta tool-groups.json per agent
This commit is contained in:
parent
98d9204ebf
commit
816523861c
4 changed files with 129 additions and 5 deletions
|
|
@ -141,6 +141,13 @@ pub async fn sync_agents(
|
|||
if crate::topology::topology_path().exists() {
|
||||
git(&dir, &["add", "topology.json"]).await?;
|
||||
}
|
||||
// Stage tool-groups.json when it exists. Created on first
|
||||
// `set_groups` call (operator-driven); absent = all agents on
|
||||
// their role defaults, no file needed. git add is a no-op when
|
||||
// the file is unchanged.
|
||||
if crate::tool_groups::tool_groups_path().exists() {
|
||||
git(&dir, &["add", "tool-groups.json"]).await?;
|
||||
}
|
||||
nix(&dir, &["flake", "lock"]).await?;
|
||||
if std::path::Path::new(&dir).join("flake.lock").exists() {
|
||||
git(&dir, &["add", "flake.lock"]).await?;
|
||||
|
|
@ -436,7 +443,7 @@ where
|
|||
let pronouns_escaped = operator_pronouns.replace('\\', "\\\\").replace('"', "\\\"");
|
||||
let _ = writeln!(
|
||||
out,
|
||||
" dashboardPort = {dashboard_port};\n operatorPronouns = \"{pronouns_escaped}\";\n mkAgent = {{ name, isManager, port, parent ? null }}:"
|
||||
" dashboardPort = {dashboard_port};\n operatorPronouns = \"{pronouns_escaped}\";\n mkAgent = {{ name, isManager, port, parent ? null, toolGroups ? null }}:"
|
||||
);
|
||||
out.push_str(
|
||||
r#" let
|
||||
|
|
@ -446,6 +453,7 @@ where
|
|||
input = inputs."agent-${name}";
|
||||
service = if isManager then "hive-m1nd" else "hive-ag3nt";
|
||||
parentEnv = if parent == null then {} else { HIVE_PARENT = parent; };
|
||||
toolGroupsEnv = if toolGroups == null then {} else { HIVE_TOOL_GROUPS = toolGroups; };
|
||||
in
|
||||
base.extendModules {
|
||||
modules = [
|
||||
|
|
@ -477,7 +485,7 @@ where
|
|||
HIVE_LABEL = name;
|
||||
HYPERHIVE_STATE_DIR = "/agents/${name}/state";
|
||||
};
|
||||
systemd.services.${service}.environment = parentEnv // {
|
||||
systemd.services.${service}.environment = parentEnv // toolGroupsEnv // {
|
||||
HIVE_PORT = toString port;
|
||||
HIVE_LABEL = name;
|
||||
HIVE_DASHBOARD_PORT = toString dashboardPort;
|
||||
|
|
@ -527,19 +535,32 @@ where
|
|||
// (every container at root). `meta::sync_agents` seeds the file
|
||||
// on first run with manager as root + everyone else under manager.
|
||||
let topology = crate::topology::read();
|
||||
let tool_groups_map = crate::tool_groups::read();
|
||||
for spec in agents {
|
||||
let parent_attr = topology
|
||||
.get(&spec.name)
|
||||
.and_then(|p| p.as_ref())
|
||||
.map_or_else(|| "null".to_owned(), |p| format!("\"{p}\""));
|
||||
// Emit `toolGroups = "group1,group2"` when the operator has
|
||||
// explicitly configured groups for this agent. Absent entry = null
|
||||
// = harness falls back to its role default (no env var emitted,
|
||||
// no rebuild cascade for agents whose groups haven't changed).
|
||||
let groups = tool_groups_map.get(&spec.name).cloned().unwrap_or_default();
|
||||
let tool_groups_attr = if groups.is_empty() {
|
||||
"null".to_owned()
|
||||
} else {
|
||||
let joined = groups.join(",");
|
||||
format!("\"{joined}\"")
|
||||
};
|
||||
let _ = writeln!(
|
||||
out,
|
||||
" {} = mkAgent {{ name = \"{}\"; isManager = {}; port = {}; parent = {}; }};",
|
||||
" {} = mkAgent {{ name = \"{}\"; isManager = {}; port = {}; parent = {}; toolGroups = {}; }};",
|
||||
spec.name,
|
||||
spec.name,
|
||||
if spec.is_manager { "true" } else { "false" },
|
||||
spec.port,
|
||||
parent_attr,
|
||||
tool_groups_attr,
|
||||
);
|
||||
}
|
||||
out.push_str(" };\n };\n}\n");
|
||||
|
|
|
|||
Loading…
Reference in a new issue