Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a4e4016214 | ||
|
|
ed1fce3329 |
2 changed files with 39 additions and 15 deletions
|
|
@ -12,8 +12,8 @@ let
|
||||||
homeDir = "/home/${userName}";
|
homeDir = "/home/${userName}";
|
||||||
# Same 512×512 rasterization of the agent icon the matrix avatar
|
# Same 512×512 rasterization of the agent icon the matrix avatar
|
||||||
# sync uses (./matrix.nix — identical derivation, same store path).
|
# sync uses (./matrix.nix — identical derivation, same store path).
|
||||||
# Only forced when an icon is configured (the avatar-sync unit below
|
# Only forced when an icon is configured AND a forge is (the avatar-sync
|
||||||
# is gated on `services.hyperhive.agent.icon != null`).
|
# unit below, the one thing that references this, is gated on both).
|
||||||
iconPng = pkgs.runCommand "hive-agent-icon.png" { nativeBuildInputs = [ pkgs.librsvg ]; } ''
|
iconPng = pkgs.runCommand "hive-agent-icon.png" { nativeBuildInputs = [ pkgs.librsvg ]; } ''
|
||||||
rsvg-convert -f png -w 512 -h 512 ${config.services.hyperhive.agent.icon} -o $out
|
rsvg-convert -f png -w 512 -h 512 ${config.services.hyperhive.agent.icon} -o $out
|
||||||
'';
|
'';
|
||||||
|
|
@ -266,7 +266,16 @@ in
|
||||||
# watches paths this unit has no business reacting to.
|
# watches paths this unit has no business reacting to.
|
||||||
# The service reads `$HYPERHIVE_STATE_DIR/forge-token`; this is the same
|
# The service reads `$HYPERHIVE_STATE_DIR/forge-token`; this is the same
|
||||||
# file, spelled the way `tea-login` above already spells it.
|
# file, spelled the way `tea-login` above already spells it.
|
||||||
systemd.paths.forge-avatar-sync = lib.mkIf (config.services.hyperhive.agent.icon != null) {
|
#
|
||||||
|
# ⚠️ Gated on the SAME condition as the service it triggers, not just on
|
||||||
|
# the icon: a `.path` unit whose `Unit=` does not exist is a unit pulled
|
||||||
|
# into multi-user.target that can only ever fail to activate. The two
|
||||||
|
# halves are one feature and appear together or not at all --- which is
|
||||||
|
# what `forge.url`'s own option doc promises.
|
||||||
|
systemd.paths.forge-avatar-sync =
|
||||||
|
lib.mkIf
|
||||||
|
(config.services.hyperhive.agent.icon != null && config.services.hyperhive.agent.forge.url != null)
|
||||||
|
{
|
||||||
description = "trigger forge-avatar-sync when forge-token appears";
|
description = "trigger forge-avatar-sync when forge-token appears";
|
||||||
wantedBy = [ "multi-user.target" ];
|
wantedBy = [ "multi-user.target" ];
|
||||||
pathConfig.PathChanged = "/agents/${userName}/state/forge-token";
|
pathConfig.PathChanged = "/agents/${userName}/state/forge-token";
|
||||||
|
|
|
||||||
|
|
@ -502,14 +502,6 @@ let
|
||||||
}
|
}
|
||||||
).allowedTCPPorts;
|
).allowedTCPPorts;
|
||||||
|
|
||||||
# A host that installs the modules and turns nothing on. The per-service
|
|
||||||
# deployment toggles are what decide whether the swarm-level services render
|
|
||||||
# here, and none of them is derived from the hive being on, so this renders
|
|
||||||
# the same absences `bare` does — the arms below assert both, because a
|
|
||||||
# service that had quietly become unconditional would still look right on
|
|
||||||
# only one of them.
|
|
||||||
centralToggleOff = hive { enable = false; };
|
|
||||||
|
|
||||||
# Ports asked for on such a host. The request is the whole condition: the
|
# Ports asked for on such a host. The request is the whole condition: the
|
||||||
# firewall hole exists because an operator named a port, not because the
|
# firewall hole exists because an operator named a port, not because the
|
||||||
# hive is running, and an agent reaching a host service is a claim about
|
# hive is running, and an agent reaching a host service is a claim about
|
||||||
|
|
@ -723,6 +715,15 @@ let
|
||||||
# get it installed twice.
|
# get it installed twice.
|
||||||
agentPluginsDuplicate = agent { claudePlugins = [ "base@hyperhive" ]; };
|
agentPluginsDuplicate = agent { claudePlugins = [ "base@hyperhive" ]; };
|
||||||
agentPlugins = machine: machine.services.hyperhive.agent.claudePlugins;
|
agentPlugins = machine: machine.services.hyperhive.agent.claudePlugins;
|
||||||
|
|
||||||
|
# An agent with an icon and no forge. Both halves of the avatar sync — the
|
||||||
|
# `.path` watcher and the oneshot it triggers — hang off the icon, but only
|
||||||
|
# the service can do anything with a forge URL, so the icon alone is the one
|
||||||
|
# input that can render half the feature. `pkgs.emptyFile` rather than a real
|
||||||
|
# SVG: the icon is only ever a gate here, and nothing this case reads
|
||||||
|
# rasterizes it.
|
||||||
|
agentIconNoForge = agentWith { services.hyperhive.agent.icon = pkgs.emptyFile; };
|
||||||
|
|
||||||
agentHarness = machine: machine.systemd.services.hive-agent;
|
agentHarness = machine: machine.systemd.services.hive-agent;
|
||||||
agentSubagentDaemon = machine: machine.systemd.services.hive-subagent-daemon;
|
agentSubagentDaemon = machine: machine.systemd.services.hive-subagent-daemon;
|
||||||
agentBaoIdentity = machine: machine.systemd.services.hive-agent-bao-identity;
|
agentBaoIdentity = machine: machine.systemd.services.hive-agent-bao-identity;
|
||||||
|
|
@ -2050,6 +2051,20 @@ let
|
||||||
name = "one subagent losing the OOM draw does not stop the daemon";
|
name = "one subagent losing the OOM draw does not stop the daemon";
|
||||||
ok = (agentSubagentDaemon agentUncapped).serviceConfig.OOMPolicy == "continue";
|
ok = (agentSubagentDaemon agentUncapped).serviceConfig.OOMPolicy == "continue";
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
# The absence class, and a gate asymmetry nothing else can see. A `.path`
|
||||||
|
# unit is `wantedBy = multi-user.target` and names a `Unit=` by
|
||||||
|
# convention rather than by reference, so one gated more loosely than the
|
||||||
|
# service it triggers evaluates clean, deploys clean, and then fails to
|
||||||
|
# activate the first time the watched file is written. `forge.url`'s own
|
||||||
|
# option doc already promises the avatar-sync units are "not generated at
|
||||||
|
# all" without a forge — this is the case that makes that sentence true
|
||||||
|
# of the watcher and not only of the oneshot.
|
||||||
|
name = "an agent with an icon and no forge renders neither avatar-sync unit";
|
||||||
|
ok =
|
||||||
|
!(agentIconNoForge.systemd.paths ? forge-avatar-sync)
|
||||||
|
&& !(agentIconNoForge.systemd.services ? forge-avatar-sync);
|
||||||
|
}
|
||||||
{
|
{
|
||||||
# A homeserver URL is the whole input: from it the module derives the
|
# A homeserver URL is the whole input: from it the module derives the
|
||||||
# hive-internal `main` account, and from a non-empty account set the three
|
# hive-internal `main` account, and from a non-empty account set the three
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue