Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions full-ai-cluster/nixos/hosts/control-plane/configuration.nix
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,9 @@
# architectural pattern). Operator can disable any persona via
# `systemctl disable zeta-<persona>` per NCI HC-8 revocable consent.
zeta.aiAgents.enable.otto = true;
zeta.aiAgents.enable.lior = true; # B-0850.3d SHIPPED (Gemini CLI 2nd vendor — Anthropic + Google)
zeta.aiAgents.enable.lior = true; # B-0850.3d SHIPPED (Gemini CLI 2nd vendor)
zeta.aiAgents.enable.vera = true; # B-0850.3c SHIPPED (Codex 3rd vendor — hits ≥3 BFT floor: Anthropic + Google + OpenAI)
# zeta.aiAgents.enable.alexa = true; # B-0850.3a pending (Kiro/Qwen)
# zeta.aiAgents.enable.vera = true; # B-0850.3c pending (Codex/OpenAI)
# zeta.aiAgents.enable.riven = true; # B-0850.3b pending (Grok)
Comment thread
AceHack marked this conversation as resolved.

# Static IP recommended so worker nodes have a stable serverAddr.
Expand Down
42 changes: 28 additions & 14 deletions full-ai-cluster/nixos/modules/zeta-ai-agent.nix
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,10 @@ let
otto = {
vendor = "anthropic";
binary = "claude";
# Claude Code uses --print for non-interactive one-shot mode
# with the <<autonomous-loop>> sentinel triggering the
# autonomous-loop skill (per `.claude/rules/tick-must-never-stop.md`).
invocationArgs = [ "--print" "<<autonomous-loop>>" ];
description = "Otto AI agent — Claude Code (Anthropic)";
};

Expand All @@ -60,27 +64,39 @@ let
alexa = {
vendor = "alibaba-qwen";
binary = "kiro"; # placeholder; verify per sub-row
invocationArgs = [ ]; # placeholder per sub-row
description = "Alexa AI agent — Kiro (Qwen Coder)";
};

# Sub-row B-0850.3b target — Grok integration
riven = {
vendor = "xai-grok";
binary = "grok"; # placeholder; grok-build CLI per peer-call
invocationArgs = [ ]; # placeholder per sub-row
description = "Riven AI agent — Grok / Grok-Build (xAI)";
};

# Sub-row B-0850.3c target — Codex/OpenAI integration
# Sub-row B-0850.3c — Codex/OpenAI integration (shipped this PR).
# Codex uses `exec` SUBCOMMAND (not a --print flag) for non-
# interactive mode per the codex CLI docs. The <<autonomous-loop>>
# string is a Claude Code sentinel; codex sees it as a literal
# prompt and responds conversationally (acceptable for first ship;
# B-0850 Phase 3.x can introduce per-vendor prompt mapping).
vera = {
vendor = "openai";
binary = "codex"; # placeholder; verify per sub-row
binary = "codex";
invocationArgs = [ "exec" "<<autonomous-loop>>" ];
description = "Vera AI agent — Codex (OpenAI)";
};

# Sub-row B-0850.3d target — Gemini CLI integration
# Sub-row B-0850.3d — Gemini CLI integration (shipped via PR #5397).
# Gemini uses -p flag (NOT --print) for non-interactive prompts.
# Like codex, the <<autonomous-loop>> sentinel is a Claude Code
# convention; gemini sees it as a literal prompt.
lior = {
vendor = "google-gemini";
binary = "gemini"; # placeholder; gemini-cli per peer-call
binary = "gemini";
invocationArgs = [ "-p" "<<autonomous-loop>>" ];
description = "Lior AI agent — Gemini CLI (Google)";
};
};
Expand Down Expand Up @@ -118,8 +134,11 @@ let
sleep 10
# Autonomous-loop ticks — fresh persona invocation per tick;
# substrate continuity via repo memory + git + bus envelopes.
# Per-persona invocationArgs (P0 fix per Copilot review on
# PR #5398: each CLI has different non-interactive flags —
# claude --print, gemini -p, codex exec — NOT all --print).
while true; do
${cfg.home}/.bun/bin/${persona.binary} --print "<<autonomous-loop>>" 2>&1 || true
${cfg.home}/.bun/bin/${persona.binary} ${lib.concatStringsSep " " (map (a: "\"${a}\"") persona.invocationArgs)} 2>&1 || true
sleep ${toString cfg.tickIntervalSec}
done
'';
Expand Down Expand Up @@ -223,15 +242,10 @@ in
ExecStart (binary grok doesn't exist at ~/.bun/bin/grok).
'';
}
{
assertion = !cfg.enable.vera;
message = ''
zeta.aiAgents.enable.vera = true requires B-0850.3c
(Vera/Codex install + login substrate) which has not shipped.
Enabling now would create a zeta-vera.service that fails
ExecStart (binary codex doesn't exist at ~/.bun/bin/codex).
'';
}
# B-0850.3c (Vera/Codex) shipped this PR — assertion removed.
# zeta-install.sh Step 6.95a-codex installs @openai/codex via
# bun + Step 6.95b-codex runs `codex login --device-auth`.
# Binary lands at ~/.bun/bin/codex; creds at ~/.codex/auth.json.
# B-0850.3d (Lior/Gemini) shipped this PR — assertion removed.
# zeta-install.sh Step 6.95a-gemini installs @google/gemini-cli
# via bun + Step 6.95b-gemini runs interactive gemini auth login.
Expand Down
55 changes: 53 additions & 2 deletions full-ai-cluster/usb-nixos-installer/zeta-install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -1104,8 +1104,12 @@ if [ -d "$ZETA_HOME" ]; then
sudo mkdir -p "$ZETA_HOME/.bun/bin"
sudo chown -R "$ZETA_UID:$ZETA_GID" "$ZETA_HOME/.bun"
# Source mise activation so the subshell finds bun via mise shims.
# tail -5 INSIDE the bash -c so pipefail covers the WHOLE pipeline
# (per Copilot review on PR #5398: outer pipe to tail -5 was masking
# bun install exit status; tail outside bash -c isn't covered by
# the inner shell's pipefail setting).
sudo HOME="$ZETA_HOME" BUN_INSTALL="$ZETA_HOME/.bun" -u "#$ZETA_UID" \
bash -c 'set -o pipefail; eval "$(mise activate bash 2>/dev/null || true)"; bun install --global @anthropic-ai/claude-code' 2>&1 | tail -5 || \
bash -c 'set -o pipefail; eval "$(mise activate bash 2>/dev/null || true)"; bun install --global @anthropic-ai/claude-code 2>&1 | tail -5' || \
echo "[iter-5.5.0] WARN: bun install claude-code FAILED — can retry post-reboot via 'bun install --global @anthropic-ai/claude-code'"

# 6.95a-gemini — install @google/gemini-cli via bun (B-0850 Phase 3d).
Expand All @@ -1115,9 +1119,19 @@ if [ -d "$ZETA_HOME" ]; then
# at implementation time (npm @google/gemini-cli is bun-compat).
echo "[iter-5.5.0] installing @google/gemini-cli via mise-managed bun (B-0850 Phase 3d Lior 2nd vendor)..."
sudo HOME="$ZETA_HOME" BUN_INSTALL="$ZETA_HOME/.bun" -u "#$ZETA_UID" \
bash -c 'set -o pipefail; eval "$(mise activate bash 2>/dev/null || true)"; bun install --global @google/gemini-cli' 2>&1 | tail -5 || \
bash -c 'set -o pipefail; eval "$(mise activate bash 2>/dev/null || true)"; bun install --global @google/gemini-cli 2>&1 | tail -5' || \
echo "[iter-5.5.0] WARN: bun install gemini-cli FAILED — can retry post-reboot via 'bun install --global @google/gemini-cli'"

# 6.95a-codex — install @openai/codex via bun (B-0850 Phase 3c).
# 3rd vendor — hits the ≥3 BFT floor (Anthropic + Google + OpenAI).
# WebSearch verified per dep-pin-search-first-authority at
# implementation time: npm @openai/codex is bun-compat; binary
# lands at ~/.bun/bin/codex.
echo "[iter-5.5.0] installing @openai/codex via mise-managed bun (B-0850 Phase 3c Vera 3rd vendor — hits ≥3 BFT floor)..."
sudo HOME="$ZETA_HOME" BUN_INSTALL="$ZETA_HOME/.bun" -u "#$ZETA_UID" \
bash -c 'set -o pipefail; eval "$(mise activate bash 2>/dev/null || true)"; bun install --global @openai/codex 2>&1 | tail -5' || \
echo "[iter-5.5.0] WARN: bun install codex FAILED — can retry post-reboot via 'bun install --global @openai/codex'"
Comment thread
AceHack marked this conversation as resolved.

# 6.95b — interactive claude login (mirror iter-5.4.0 gh auth login)
CLAUDE_BIN="$ZETA_HOME/.bun/bin/claude"
if [ -x "$CLAUDE_BIN" ]; then
Expand Down Expand Up @@ -1181,6 +1195,43 @@ if [ -d "$ZETA_HOME" ]; then
echo "[iter-5.5.0] gemini binary not found at $GEMINI_BIN; skipping interactive login"
fi

# 6.95b-codex — interactive codex login (B-0850 Phase 3c Vera).
# 3rd vendor login — codex CLI has the most explicit device-flow
# via `codex login --device-auth` (Anthropic claude device-flow
# analog; works on headless / no-local-browser systems by
# printing URL+code for paste into ANY browser). Credentials
# cache at ~/.codex/auth.json (NOT ~/.config/codex/ — codex
# uses its own dotdir convention per the codex docs).
CODEX_BIN="$ZETA_HOME/.bun/bin/codex"
if [ -x "$CODEX_BIN" ]; then
echo
echo "[iter-5.5.0] Trigger Codex CLI interactive device-flow login NOW (B-0850 Phase 3c Vera)?"
echo "[iter-5.5.0] - Uses 'codex login --device-auth' (clean device-flow shape)."
echo "[iter-5.5.0] - Prints URL + one-time code; visit on ANY browser on ANY device; paste code."
echo "[iter-5.5.0] - ChatGPT Plus/Pro/Business/Edu/Enterprise plans include Codex access."
echo "[iter-5.5.0] - Credentials land at $ZETA_HOME/.codex/auth.json (NOT ~/.config/codex)."
Comment thread
AceHack marked this conversation as resolved.
echo "[iter-5.5.0] - Default YES (press Enter); 'n' to skip + login post-reboot manually."
read -r -p "[iter-5.5.0] Run codex login --device-auth now? [Y/n]: " CODEX_AUTH_REPLY
case "${CODEX_AUTH_REPLY:-y}" in
[Yy]*|"")
echo "[iter-5.5.0] running 'codex login --device-auth' (interactive)..."
sudo HOME="$ZETA_HOME" -u "#$ZETA_UID" "$CODEX_BIN" login --device-auth || \
echo "[iter-5.5.0] WARN: codex login failed; can re-run post-reboot"
# Codex stores at ~/.codex/auth.json (not ~/.config/codex);
# restrict perms accordingly.
if [ -d "$ZETA_HOME/.codex" ]; then
sudo chown -R "$ZETA_UID:$ZETA_GID" "$ZETA_HOME/.codex"
sudo chmod -R go-rwx "$ZETA_HOME/.codex"
fi
;;
*)
echo "[iter-5.5.0] SKIPPED codex login; run 'codex login --device-auth' on first login"
;;
esac
else
echo "[iter-5.5.0] codex binary not found at $CODEX_BIN; skipping interactive login"
fi

# 6.95c — persist gh credentials from installer-root to installed-zeta
# Closes the iter-5.4.0 credential-persistence gap (Bug 8).
if [ -d /root/.config/gh ]; then
Expand Down
Loading