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:
parent
60393d0e32
commit
3662eda440
21 changed files with 531 additions and 290 deletions
|
|
@ -8,14 +8,14 @@
|
|||
...
|
||||
}:
|
||||
let
|
||||
userName = config.hyperhive.user.name;
|
||||
userName = config.services.hyperhive.agent.user.name;
|
||||
homeDir = "/home/${userName}";
|
||||
# Same 512×512 rasterization of the agent icon the matrix avatar
|
||||
# sync uses (./matrix.nix — identical derivation, same store path).
|
||||
# Only forced when an icon is configured (the avatar-sync unit below
|
||||
# is gated on `hyperhive.icon != null`).
|
||||
# is gated on `services.hyperhive.agent.icon != null`).
|
||||
iconPng = pkgs.runCommand "hive-agent-icon.png" { nativeBuildInputs = [ pkgs.librsvg ]; } ''
|
||||
rsvg-convert -f png -w 512 -h 512 ${config.hyperhive.icon} -o $out
|
||||
rsvg-convert -f png -w 512 -h 512 ${config.services.hyperhive.agent.icon} -o $out
|
||||
'';
|
||||
|
||||
# git credential helper for the hive forge --- the exact shape
|
||||
|
|
@ -39,7 +39,7 @@ let
|
|||
'';
|
||||
in
|
||||
{
|
||||
options.hyperhive.forge.url = lib.mkOption {
|
||||
options.services.hyperhive.agent.forge.url = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.str;
|
||||
default = null;
|
||||
example = "http://forge.internal:3000";
|
||||
|
|
@ -80,10 +80,10 @@ in
|
|||
# is for, so reject it and name the option.
|
||||
{
|
||||
assertion =
|
||||
config.hyperhive.forge.url == null
|
||||
|| lib.hasPrefix "http://" config.hyperhive.forge.url
|
||||
|| lib.hasPrefix "https://" config.hyperhive.forge.url;
|
||||
message = "hyperhive.forge.url must be an http:// or https:// URL, or null for no forge (got: \"${toString config.hyperhive.forge.url}\")";
|
||||
config.services.hyperhive.agent.forge.url == null
|
||||
|| lib.hasPrefix "http://" config.services.hyperhive.agent.forge.url
|
||||
|| lib.hasPrefix "https://" config.services.hyperhive.agent.forge.url;
|
||||
message = "services.hyperhive.agent.forge.url must be an http:// or https:// URL, or null for no forge (got: \"${toString config.services.hyperhive.agent.forge.url}\")";
|
||||
}
|
||||
];
|
||||
|
||||
|
|
@ -95,9 +95,9 @@ in
|
|||
# hive-forge <verb>: CLI wrapping common Forgejo REST API operations
|
||||
# (view, pr, issue, comment, assign, close, labels, branches, etc.).
|
||||
# The per-bin split package — narrow closure, no hivectl/wireguard.
|
||||
config.hyperhive.packages.hive-forge
|
||||
config.services.hyperhive.agent.packages.hive-forge
|
||||
]
|
||||
++ lib.optional (config.hyperhive.forge.url != null) gitCredHelper;
|
||||
++ lib.optional (config.services.hyperhive.agent.forge.url != null) gitCredHelper;
|
||||
|
||||
# Wire the forge credential helper for `git push`, scoped to the forge
|
||||
# this agent is configured for.
|
||||
|
|
@ -135,9 +135,9 @@ in
|
|||
# works for any agent whose personal `~/.gitconfig` names the helper by
|
||||
# ABSOLUTE path — so this is masked exactly where it would be noticed,
|
||||
# and bites a fresh agent that has no such file.
|
||||
environment.etc."gitconfig" = lib.mkIf (config.hyperhive.forge.url != null) {
|
||||
environment.etc."gitconfig" = lib.mkIf (config.services.hyperhive.agent.forge.url != null) {
|
||||
text = ''
|
||||
[credential "${lib.removeSuffix "/" config.hyperhive.forge.url}"]
|
||||
[credential "${lib.removeSuffix "/" config.services.hyperhive.agent.forge.url}"]
|
||||
helper = hive-forge
|
||||
username = ${userName}
|
||||
'';
|
||||
|
|
@ -165,7 +165,7 @@ in
|
|||
# and the agent's `forge-token` from under the second.
|
||||
};
|
||||
serviceConfig = {
|
||||
ExecStart = "${config.hyperhive.packages.hive-forge-notify}/bin/hive-forge-notify";
|
||||
ExecStart = "${config.services.hyperhive.agent.packages.hive-forge-notify}/bin/hive-forge-notify";
|
||||
SyslogIdentifier = "hive-forge-notify";
|
||||
# `on-failure`, NOT `always`: an agent with no forge account is a
|
||||
# supported configuration, and the poller reports that by logging
|
||||
|
|
@ -183,7 +183,7 @@ in
|
|||
# docs/process/conventions.md::Best-effort oneshot services.
|
||||
# Not generated at all when no forge is configured: an absent
|
||||
# integration rather than one pointed at a guessed address.
|
||||
systemd.services.tea-login = lib.mkIf (config.hyperhive.forge.url != null) {
|
||||
systemd.services.tea-login = lib.mkIf (config.services.hyperhive.agent.forge.url != null) {
|
||||
description = "configure tea CLI from hive-forge token (best-effort)";
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
after = [ "local-fs.target" ];
|
||||
|
|
@ -202,7 +202,7 @@ in
|
|||
environment.AGENT_USER = userName;
|
||||
script = ''
|
||||
# No `set -e`: best-effort posture (see docs pointer above).
|
||||
FORGE_URL=${lib.escapeShellArg config.hyperhive.forge.url}
|
||||
FORGE_URL=${lib.escapeShellArg config.services.hyperhive.agent.forge.url}
|
||||
# $HYPERHIVE_STATE_DIR is system-wide via the meta flake.
|
||||
TOKEN_FILE="$HYPERHIVE_STATE_DIR/forge-token"
|
||||
if [ ! -f "$TOKEN_FILE" ]; then
|
||||
|
|
@ -266,13 +266,13 @@ in
|
|||
# watches paths this unit has no business reacting to.
|
||||
# The service reads `$HYPERHIVE_STATE_DIR/forge-token`; this is the same
|
||||
# file, spelled the way `tea-login` above already spells it.
|
||||
systemd.paths.forge-avatar-sync = lib.mkIf (config.hyperhive.icon != null) {
|
||||
systemd.paths.forge-avatar-sync = lib.mkIf (config.services.hyperhive.agent.icon != null) {
|
||||
description = "trigger forge-avatar-sync when forge-token appears";
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
pathConfig.PathChanged = "/agents/${userName}/state/forge-token";
|
||||
};
|
||||
|
||||
# One-shot: hyperhive.icon → Forgejo profile avatar. Shape contract:
|
||||
# One-shot: services.hyperhive.agent.icon → Forgejo profile avatar. Shape contract:
|
||||
# docs/process/conventions.md::Best-effort oneshot services.
|
||||
# RemainAfterExit = false so the .path trigger above can re-fire
|
||||
# this unit when the forge-token arrives after boot. The PNG is
|
||||
|
|
@ -281,7 +281,8 @@ in
|
|||
# and needs no librsvg at runtime — Forgejo's Go image library
|
||||
# can't decode SVG, hence PNG.
|
||||
systemd.services.forge-avatar-sync =
|
||||
lib.mkIf (config.hyperhive.icon != null && config.hyperhive.forge.url != null)
|
||||
lib.mkIf
|
||||
(config.services.hyperhive.agent.icon != null && config.services.hyperhive.agent.forge.url != null)
|
||||
{
|
||||
description = "sync agent icon to Forgejo user avatar (best-effort)";
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
|
|
@ -298,7 +299,7 @@ in
|
|||
pkgs.jq
|
||||
];
|
||||
script = ''
|
||||
FORGE_URL=${lib.escapeShellArg config.hyperhive.forge.url}
|
||||
FORGE_URL=${lib.escapeShellArg config.services.hyperhive.agent.forge.url}
|
||||
# $HYPERHIVE_STATE_DIR is set system-wide by the meta flake
|
||||
# (systemd.globalEnvironment) to `/agents/<name>/state`.
|
||||
TOKEN_FILE="$HYPERHIVE_STATE_DIR/forge-token"
|
||||
|
|
|
|||
Loading…
Reference in a new issue