Watch
0
0
Fork
You've already forked hyperhive
0

remove the hive dashboard's stats page and the price table behind it

The ST4TS page (/stats.html), GET /api/stats-hive, hive-c0re's hive_stats
rollup and the modelPrices option that only fed its cost estimate are
gone. Each agent's own /stats page and the turn-stats database it reads
are unchanged. Setting modelPrices now fails evaluation with a message
saying so.
This commit is contained in:
iris 2026-11-02 23:15:51 +01:00 • committed by mara
commit 5e9a22cb38
5 changed files with 112 additions and 1207 deletions

View file

@ -242,10 +242,6 @@ in
"c0re"
"preBuildAgentTemplates"
] agentPrebuildRemoved)
(lib.mkRenamedOptionModule
[ "services" "hyperhive" "c0re" "modelPrices" ]
[ "services" "hyperhive" "deploy" "hive-controller" "modelPrices" ]
)
(lib.mkRenamedOptionModule
[ "services" "hyperhive" "c0re" "agentCpuQuota" ]
[ "services" "hyperhive" "deploy" "hive-controller" "agentCpuQuota" ]

View file

@ -61,8 +61,7 @@ let
# The `hive-c0re serve` config JSON. Keys are snake_case to match the
# `ServeConfig` serde shape the daemon deserialises (the
# container-injected HiveEnv fields, flattened, plus the hive-c0re-local
# model_prices table); per-flag overrides still work for ad-hoc
# invocations.
# build_slots); per-flag overrides still work for ad-hoc invocations.
#
# Written to `/etc/hyperhive/serve.json` (managed by
# `environment.etc`) rather than embedded as a store-path argument in
@ -97,7 +96,6 @@ let
agent_memory_max = controllerCfg.agentMemoryMax;
agent_cpu_weight = controllerCfg.agentCpuWeight;
agent_io_weight = controllerCfg.agentIoWeight;
model_prices = controllerCfg.modelPrices;
build_slots = controllerCfg.buildSlots;
};
in

View file

@ -11,6 +11,10 @@
...
}:
let
modelPricesRemoved = ''
The hive dashboard no longer has a stats page, and the price table only fed
its cost estimate. Remove this definition.
'';
agentPrebuildRemoved = ''
Hives pull agent closures from the swarm cache; nothing builds locally, so
there is no agent-base closure to pre-fetch into the host store. Remove
@ -36,6 +40,14 @@ in
"hive-controller"
"preBuildAgentTemplates"
] agentPrebuildRemoved)
(lib.mkRemovedOptionModule [ "services" "hyperhive" "c0re" "modelPrices" ] modelPricesRemoved)
(lib.mkRemovedOptionModule [
"services"
"hyperhive"
"deploy"
"hive-controller"
"modelPrices"
] modelPricesRemoved)
(lib.mkRemovedOptionModule [ "services" "hyperhive" "c0re" "hyperhiveDocs" ] ''
Agents take their reference docs from the pinned `hyperhive` input, which
carries `docs/`. Remove this definition.
@ -121,80 +133,6 @@ in
'';
};
modelPrices = lib.mkOption {
type = lib.types.attrsOf (
lib.types.submodule {
options = {
input = lib.mkOption {
type = lib.types.numbers.nonnegative;
description = "USD per million input tokens.";
};
output = lib.mkOption {
type = lib.types.numbers.nonnegative;
description = "USD per million output tokens.";
};
cache_read = lib.mkOption {
type = lib.types.numbers.nonnegative;
description = "USD per million cache-read tokens.";
};
cache_write = lib.mkOption {
type = lib.types.numbers.nonnegative;
description = "USD per million cache-creation (write) tokens.";
};
};
}
);
# Current Anthropic list prices for the Claude 4.x family (Opus
# 4.x, Sonnet 4.x, Haiku 4.5); cache_write is the 1-hour cache-TTL
# price (the default through the Claude subscription the agents run
# on). Keep in sync with `builtin_prices` in
# hive-c0re/src/stats/hive_stats.rs.
default = {
opus = {
input = 5.0;
output = 25.0;
cache_read = 0.5;
cache_write = 10.0;
};
sonnet = {
input = 3.0;
output = 15.0;
cache_read = 0.3;
cache_write = 6.0;
};
haiku = {
input = 1.0;
output = 5.0;
cache_read = 0.1;
cache_write = 2.0;
};
};
example = {
sonnet = {
input = 3.0;
output = 15.0;
cache_read = 0.3;
cache_write = 6.0;
};
};
description = ''
Per-model USD prices (per **million** tokens) used for the
hive-wide cost *estimate* on the dashboard's ST4TS tab. Each key
is a model-family short name matched case-insensitively as a
substring of the active model id at runtime (e.g. `"sonnet"`
matches `"claude-sonnet-4-5"`); the longest matching key wins, so
a specific entry beats a generic family name. Any model not
covered by this table falls back to hive-c0re's built-in
estimate.
The defaults track Anthropic list pricing at the time of
writing — override them here to keep the estimate current
without a code change. Passed to `hive-c0re serve` as JSON via
`--model-prices`; read only by hive-c0re itself (not injected
into containers). Changes apply on the next host rebuild.
'';
};
agentCpuQuota = lib.mkOption {
type = lib.types.str;
default = "200%";

View file

@ -1470,12 +1470,6 @@ let
c0re.assets = pkgs.gnused;
c0re.xdgIcons = pkgs.gnugrep;
c0re.hyperhiveRev = "abc123";
c0re.modelPrices.sonnet = {
input = 1.0;
output = 2.0;
cache_read = 3.0;
cache_write = 4.0;
};
c0re.agentCpuQuota = "300%";
c0re.agentMemoryMax = "8G";
c0re.agentCpuWeight = 50;
@ -1501,7 +1495,6 @@ let
&& path c.xdgIcons == path pkgs.gnugrep
&& path c.servedFrontend == path pkgs.coreutils
&& c.hyperhiveRev == "abc123"
&& c.modelPrices.sonnet.cache_write == 4.0
&& c.agentCpuQuota == "300%"
&& c.agentMemoryMax == "8G"
&& c.agentCpuWeight == 50
@ -1516,7 +1509,6 @@ let
"assets"
"xdgIcons"
"hyperhiveRev"
"modelPrices"
"agentCpuQuota"
"agentMemoryMax"
"agentCpuWeight"
@ -1575,12 +1567,37 @@ let
&& !(lib.any (path: refused bare path) (lib.attrNames setting))
&& !(lib.any (path: refused sibling path) (lib.attrNames setting));
}
{
# The price table fed only the hive dashboard's stats page, which is gone.
# A definition under either namespace fails evaluation naming the option;
# a host that sets none, or a moved sibling, does not.
name = "a definition of the removed modelPrices option fails evaluation, naming the option";
ok =
let
refused =
m: path:
lib.any (
a: !a.assertion && lib.hasInfix "services.hyperhive.${path}.modelPrices" a.message
) m.assertions;
prices = {
sonnet = {
input = 3.0;
};
};
in
refused (hiveWithController { c0re.modelPrices = prices; }) "c0re"
&& refused (hiveWithController {
deploy.hive-controller.modelPrices = prices;
}) "deploy.hive-controller"
&& !(refused bare "c0re")
&& !(refused bare "deploy.hive-controller")
&& !(refused (hiveWithController { c0re.buildSlots = 3; }) "c0re");
}
{
# What the moved options render with their defaults: the flake source, the agent limits
# and build slots in serve.json, the sudoless-hivectl group's members,
# and the model price table. The same values the options held at their
# old paths.
name = "the flake source, agent limits, build slots, admin group and price table render their defaults unchanged";
# and build slots in serve.json, and the sudoless-hivectl group's
# members. The same values the options held at their old paths.
name = "the flake source, agent limits, build slots and admin group render their defaults unchanged";
ok =
let
serve = builtins.fromJSON (
@ -1597,8 +1614,6 @@ let
&& serve.agent_cpu_weight == 80
&& serve.agent_io_weight == 80
&& serve.build_slots == 1
&& serve.model_prices.opus.input == 5.0
&& serve.model_prices.haiku.cache_write == 2.0
&& allLocal.users.groups.hive-admin.members == [ ];
}
{

View file

@ -16,9 +16,9 @@
# $out/dashboard/ the hive-c0re dashboard assets (full layout in
# frontend/packages/dashboard/build.mjs):
# index.html (operator SPA, served at /)
# stats.html favicon.svg
# static/{tabs,stats,stream-worker}.js{,.map}
# static/{colors,theme,common,dashboard,stats}.css
# favicon.svg
# static/{tabs,stream-worker}.js{,.map}
# static/{colors,theme,common,dashboard}.css
# $out/agent/ the per-agent default UI (layered with
# services.hyperhive.agent.frontend.extraFiles at activation time)
# index.html stats.html screen.html