Per mara on #622 comment 7442: > follow up moving scripts and css and stuff out of the nix file. > can live in the same dir. Layout: nix/docs/ default.nix ← what was nix/docs.nix style.css ← extracted from inline `styleCSS = '' ... ''` `builtins.readFile ./style.css` loads the stylesheet at evaluation time, so the rendered HTML stays byte-identical (CSS inlined into each page's `<style>` block — verified). Future client-side scripts can land at `nix/docs/script.js` with the same `builtins.readFile` pattern. Bonus: the docs.nix stub NixOS eval was still force-disabling `hyperhive.{forge,matrix}.enable` on the pre-#615 namespace; updated to `services.hyperhive.{forge,matrix}.enable` so `nix flake check` passes against current main. (Same fix lives on PRs #619 + #620; whichever lands first wins, the others rebase to a no-op.) `flake.nix` references updated: `./nix/docs.nix` → `./nix/docs`. Verified: - `nix flake check --no-build` passes clean - `nix build .#docs` produces 5-file bundle identical to pre-PR shape - inline CSS still appears 3× per HTML page (one per index/host/agent)
254 lines
9.7 KiB
Nix
254 lines
9.7 KiB
Nix
{
|
|
pkgs,
|
|
lib,
|
|
self,
|
|
nixosSystem,
|
|
}:
|
|
# Options documentation for hyperhive's NixOS module surfaces.
|
|
# Closes #616. HTML output added per mara on internal-requests #8.
|
|
#
|
|
# Three rendering layers:
|
|
# CommonMark — `pkgs.nixosOptionsDoc.optionsCommonMark`. Source of
|
|
# truth; kept as `.md` files in the bundle.
|
|
# HTML — `pkgs.cmark-gfm` over the CommonMark output, wrapped
|
|
# in a minimal inline-CSS template. Primary surface; the
|
|
# bundle's `index.html` / `host.html` / `agent.html` are
|
|
# what the operator's nginx serves from
|
|
# `hyperhive.darkest.space/options/`.
|
|
#
|
|
# Three output trees consumed by `flake.nix`:
|
|
# docs-host — operator-facing host-module options
|
|
# (`services.hive-c0re.*`, `hyperhive.{domain,forge,matrix}.*`)
|
|
# docs-agent — per-agent harness options
|
|
# (`hyperhive.{model,allowedRecipients,extraMcpServers,…}`)
|
|
# docs — bundled static site (index + host + agent, .html + .md)
|
|
#
|
|
# All asset paths inside the rendered HTML are relative (e.g.
|
|
# `./host.html`) so the bundle can be mounted at any URL prefix
|
|
# without rewriting; styles are inline so there's no second-fetch
|
|
# request for the operator's browser.
|
|
let
|
|
# Evaluate the host module under a stub NixOS system. Stubs satisfy
|
|
# the few hard-required options (filesystems, stateVersion) without
|
|
# actually enabling the hive — we only want the option *declarations*
|
|
# to evaluate, not the config.
|
|
hostEval = nixosSystem {
|
|
system = pkgs.stdenv.hostPlatform.system;
|
|
modules = [
|
|
self.nixosModules.default
|
|
(
|
|
{ lib, ... }:
|
|
{
|
|
nixpkgs.overlays = [ self.overlays.default ];
|
|
fileSystems."/" = {
|
|
device = "/dev/null";
|
|
fsType = "tmpfs";
|
|
};
|
|
boot.loader.grub.enable = false;
|
|
system.stateVersion = "25.11";
|
|
# Force-disable every hyperhive subsystem so config evaluation
|
|
# doesn't pull in heavy build inputs (matrix container, forge,
|
|
# etc.). Options are still fully declared either way — that's
|
|
# what nixosOptionsDoc traverses.
|
|
services.hyperhive.enable = lib.mkForce false;
|
|
services.hyperhive.forge.enable = lib.mkForce false;
|
|
services.hyperhive.matrix.enable = lib.mkForce false;
|
|
services.hyperhive.gateway.enable = lib.mkForce false;
|
|
}
|
|
)
|
|
];
|
|
};
|
|
|
|
# Agent options live in the already-evaluated `agent-base` container
|
|
# config. Reusing it avoids re-evaluating the harness module against
|
|
# a fresh stub — the options tree is identical to what a real agent
|
|
# container sees.
|
|
agentEval = self.nixosConfigurations.agent-base;
|
|
|
|
# Strip the nix-store prefix from option declaration paths and rewrite
|
|
# them as forge URLs so the rendered docs link back to the source.
|
|
forgeRoot = "https://forge.darkest.space/hyperhive/hyperhive/src/branch/main";
|
|
storePrefix = toString self + "/";
|
|
transformOptions =
|
|
opt:
|
|
opt
|
|
// {
|
|
declarations = map (
|
|
decl:
|
|
let
|
|
declStr = toString decl;
|
|
relPath =
|
|
if lib.hasPrefix storePrefix declStr then
|
|
lib.removePrefix storePrefix declStr
|
|
else
|
|
baseNameOf declStr;
|
|
in
|
|
{
|
|
url = "${forgeRoot}/${relPath}";
|
|
name = relPath;
|
|
}
|
|
) opt.declarations;
|
|
};
|
|
|
|
# Filter an evaluated `options` tree down to a set of top-level
|
|
# subtrees we care about. Anything outside the listed roots is
|
|
# dropped — keeps the rendered docs focused on hyperhive's surface
|
|
# instead of NixOS's 10k+ default options.
|
|
pickSubtrees =
|
|
options: roots:
|
|
let
|
|
pick =
|
|
path:
|
|
if lib.hasAttrByPath path options then
|
|
lib.setAttrByPath path (lib.getAttrFromPath path options)
|
|
else
|
|
{ };
|
|
in
|
|
lib.foldl' lib.recursiveUpdate { } (map pick roots);
|
|
|
|
hostOptions = pickSubtrees hostEval.options [
|
|
[ "hyperhive" ]
|
|
[
|
|
"services"
|
|
"hive-c0re"
|
|
]
|
|
];
|
|
|
|
agentOptions = pickSubtrees agentEval.options [
|
|
[ "hyperhive" ]
|
|
];
|
|
|
|
hostDoc = pkgs.nixosOptionsDoc {
|
|
options = hostOptions;
|
|
inherit transformOptions;
|
|
};
|
|
|
|
agentDoc = pkgs.nixosOptionsDoc {
|
|
options = agentOptions;
|
|
inherit transformOptions;
|
|
};
|
|
|
|
# Plain-markdown page (with a short header). Source of truth; the
|
|
# HTML version is rendered from this.
|
|
mkMarkdownPage =
|
|
name: title: doc:
|
|
pkgs.runCommand "hyperhive-${name}.md" { } ''
|
|
{
|
|
echo "# ${title}"
|
|
echo
|
|
echo "<!-- Auto-generated from the hyperhive flake."
|
|
echo " Source: nix/docs/default.nix · regenerate with"
|
|
echo " \`nix build .#${name}\` -->"
|
|
echo
|
|
cat ${doc.optionsCommonMark}
|
|
} > $out
|
|
'';
|
|
|
|
# Inline-stylesheet, loaded as plain text from `./style.css` so it's
|
|
# editable with normal CSS tooling (#625). Inlined into every page
|
|
# so the bundle doesn't depend on a second HTTP fetch — keeps the
|
|
# `/options/` mount trivial for nginx (no MIME guessing for separate
|
|
# .css files, no cache-busting needed when this updates).
|
|
styleCSS = builtins.readFile ./style.css;
|
|
|
|
# HTML page: CommonMark → cmark-gfm → minimal template with inline
|
|
# CSS + relative-only links. cmark-gfm rather than plain cmark so
|
|
# any future tables / autolinks Just Work without revisiting.
|
|
mkHtmlPage =
|
|
name: title: doc:
|
|
pkgs.runCommand "hyperhive-${name}.html" { nativeBuildInputs = [ pkgs.cmark-gfm ]; } ''
|
|
{
|
|
echo '<!doctype html>'
|
|
echo '<html lang="en">'
|
|
echo '<head>'
|
|
echo '<meta charset="utf-8">'
|
|
echo '<meta name="viewport" content="width=device-width, initial-scale=1">'
|
|
echo '<title>${title}</title>'
|
|
echo '<style>'
|
|
cat ${pkgs.writeText "hyperhive-docs-style.css" styleCSS}
|
|
echo '</style>'
|
|
echo '</head>'
|
|
echo '<body>'
|
|
echo '<nav>'
|
|
echo '<a href="./index.html">index</a>'
|
|
echo '<a href="./host.html">host options</a>'
|
|
echo '<a href="./agent.html">agent options</a>'
|
|
echo '</nav>'
|
|
echo '<main>'
|
|
echo '<h1>${title}</h1>'
|
|
echo '<p><em>Auto-generated from the hyperhive flake. Source: <a href="${forgeRoot}/nix/docs/default.nix">nix/docs/default.nix</a>.</em></p>'
|
|
cmark-gfm ${doc.optionsCommonMark}
|
|
echo '</main>'
|
|
echo '<footer>'
|
|
echo '<p>hyperhive · <a href="${forgeRoot}">source</a></p>'
|
|
echo '</footer>'
|
|
echo '</body>'
|
|
echo '</html>'
|
|
} > $out
|
|
'';
|
|
|
|
# Landing page — same template shape as the option pages but
|
|
# hand-authored content (short intro + cross-links). Kept tight; the
|
|
# detail lives on the two option pages.
|
|
indexHTML = pkgs.runCommand "hyperhive-docs-index.html" { } ''
|
|
{
|
|
echo '<!doctype html>'
|
|
echo '<html lang="en">'
|
|
echo '<head>'
|
|
echo '<meta charset="utf-8">'
|
|
echo '<meta name="viewport" content="width=device-width, initial-scale=1">'
|
|
echo '<title>hyperhive — nix options reference</title>'
|
|
echo '<style>'
|
|
cat ${pkgs.writeText "hyperhive-docs-style.css" styleCSS}
|
|
echo '</style>'
|
|
echo '</head>'
|
|
echo '<body>'
|
|
echo '<nav>'
|
|
echo '<a href="./index.html">index</a>'
|
|
echo '<a href="./host.html">host options</a>'
|
|
echo '<a href="./agent.html">agent options</a>'
|
|
echo '</nav>'
|
|
echo '<main>'
|
|
echo '<h1>hyperhive — nix options reference</h1>'
|
|
echo '<p>Auto-generated from the <a href="${forgeRoot}">hyperhive flake</a>. Two reading paths:</p>'
|
|
echo '<h3><a href="./host.html">host options</a></h3>'
|
|
echo '<p>Options exposed by <code>hyperhive.nixosModules.default</code> to operator host configurations: <code>services.hyperhive.{enable,domain,c0re,forge,matrix,gateway}.*</code>.</p>'
|
|
echo '<h3><a href="./agent.html">agent options</a></h3>'
|
|
echo '<p>Per-agent options declared in <code>nix/templates/harness-base.nix</code> and visible from every <code>agent.nix</code>: <code>hyperhive.model</code>, <code>hyperhive.allowedRecipients</code>, <code>hyperhive.extraMcpServers</code>, <code>hyperhive.frontend.*</code>, <code>hyperhive.forge.*</code>, <code>hyperhive.matrix.*</code>, <code>hyperhive.gui.*</code>.</p>'
|
|
echo '<h3>Regenerate</h3>'
|
|
echo '<pre><code>nix build .#docs # bundled static site (index + host + agent)'
|
|
echo 'nix build .#docs-host # host page only (HTML)'
|
|
echo 'nix build .#docs-agent # agent page only (HTML)</code></pre>'
|
|
echo '<p>The bundle also ships <code>.md</code> versions of each page (<code>host.md</code>, <code>agent.md</code>) — same content, source-of-truth shape — alongside the HTML.</p>'
|
|
echo '</main>'
|
|
echo '<footer>'
|
|
echo '<p>hyperhive · <a href="${forgeRoot}">source</a></p>'
|
|
echo '</footer>'
|
|
echo '</body>'
|
|
echo '</html>'
|
|
} > $out
|
|
'';
|
|
|
|
hostHTML = mkHtmlPage "docs-host" "hyperhive — host options" hostDoc;
|
|
agentHTML = mkHtmlPage "docs-agent" "hyperhive — per-agent options" agentDoc;
|
|
hostMD = mkMarkdownPage "docs-host" "hyperhive — host options" hostDoc;
|
|
agentMD = mkMarkdownPage "docs-agent" "hyperhive — per-agent options" agentDoc;
|
|
in
|
|
{
|
|
# Individual page outputs (HTML is the primary surface; the .md
|
|
# source is one `nix build` step away if needed).
|
|
host = hostHTML;
|
|
agent = agentHTML;
|
|
|
|
# Bundled static site for nginx to serve at `/options/`. Asset paths
|
|
# are all relative, no root-absolute references, so the prefix can
|
|
# change without rebuild.
|
|
bundle = pkgs.runCommand "hyperhive-options-docs" { } ''
|
|
mkdir -p $out
|
|
cp ${indexHTML} $out/index.html
|
|
cp ${hostHTML} $out/host.html
|
|
cp ${agentHTML} $out/agent.html
|
|
cp ${hostMD} $out/host.md
|
|
cp ${agentMD} $out/agent.md
|
|
'';
|
|
}
|