feat(install): Higgsfield step 8.6; login offers test stdin alone

This commit is contained in:
bastien
2026-09-30 16:08:34 +02:00
parent acb6cd7cb4
commit 83043412d0
2 changed files with 100 additions and 3 deletions
+76 -3
View File
@@ -582,6 +582,8 @@ else
fi
# ctx7 auth — detect, then offer login ONLY in an interactive TTY. A non-interactive
# run (CI / headless / re-run) must never open a browser or block on OAuth.
# The test reads stdin alone: stdout is the tee pipe set up at the top of
# this script, never a terminal.
if command -v ctx7 &>/dev/null; then
# Deterministic offline oracle: ctx7's OAuth token lives here (XDG-aware).
# Present => authenticated; absent => anonymous. No subprocess, no network, no browser.
@@ -590,7 +592,7 @@ if command -v ctx7 &>/dev/null; then
ok "ctx7 authenticated (full rate limits)"
else
info "ctx7 works anonymously — docs + library already usable, no auth required."
if [ -t 0 ] && [ -t 1 ]; then
if [ -t 0 ]; then
# Interactive terminal: offer to log in now (opens a browser).
printf '%b' "${BLUE}→${NC} Authenticate ctx7 now for higher rate limits? [y/N] "
read -r ctx7_ans || ctx7_ans=""
@@ -990,6 +992,76 @@ for _stray in "$REPO/.agents/skills" "$REPO/.claude/skills"; do
done
echo ""
# ============================================================
# STEP 8.6 — HIGGSFIELD CLI + SKILL PACK
# ============================================================
# `@higgsfield/cli` (bins `higgsfield`, `higgs`): image, video, audio and
# brand media generation from the terminal, one browser login, metered
# credits. Its skills come from github.com/higgsfield-ai/skills, cloned by
# lib/higgsfield-skills.sh into skills-external/higgsfield-* (gitignored).
#
# Nothing is linked here. The pack is OFF by default and belongs to no
# profile: `lib/toggle-external.sh enable higgsfield` turns the media skills
# on, `enable higgsfield-websites` the landing-page aid. Keeping it out of
# link.sh and of every profile is what stops a re-run from re-enabling it
# (BDR-093). This step runs before Step 8.7 so the effort pins are still
# re-applied after the last vendoring step (BDR-108).
echo "── Step 8.6: Higgsfield CLI + skill pack ───────────────────"
echo ""
# shellcheck source=lib/higgsfield-skills.sh disable=SC1091
source "$REPO/lib/higgsfield-skills.sh"
HF_PKG="@higgsfield/cli"
# The package vendors its binary in a postinstall script that npm may hold
# back; this form lets that one script run.
HF_REMEDY="npm install -g --allow-scripts=${HF_PKG} ${HF_PKG}"
# higgsfield_cli_ok, not `command -v`: the npm shim can sit on PATH with no
# binary behind it, and only a probe tells the two apart.
if higgsfield_cli_ok; then
ok "Higgsfield CLI already installed"
else
HF_VER=$(pinned_version "higgsfield")
[ "$HF_VER" = "latest" ] || HF_PKG="${HF_PKG}@${HF_VER}"
info "Installing ${HF_PKG} (version from plugins.lock.json: ${HF_VER})..."
npm install -g "$HF_PKG" || true
if higgsfield_cli_ok; then
ok "Higgsfield CLI installed"
else
err "Higgsfield CLI install failed — run manually: $HF_REMEDY"
fi
fi
if higgsfield_cli_ok; then
# Skill pack — cloned to a stage, then moved under skills-external/.
if HF_N=$(higgsfield_sync_skills "$REPO"); then
ok "Higgsfield skill pack synced to skills-external/ ($HF_N skills)"
else
warn "Higgsfield skill pack sync failed — existing copies kept (check: git clone $HIGGSFIELD_SKILLS_URL)"
fi
# Auth — offer the login only when stdin is a terminal: a non-interactive
# run (CI / headless) must never open a browser or block on OAuth.
if higgsfield_signed_in; then
ok "Higgsfield: signed in"
elif [ -t 0 ]; then
printf '%b' "${BLUE}→${NC} Sign in to Higgsfield now? (opens a browser) [y/N] "
read -r hf_ans || hf_ans=""
if [[ "$hf_ans" =~ ^[Yy]([Ee][Ss])?$ ]]; then
if higgsfield auth login; then
ok "Higgsfield authenticated"
else
warn "Higgsfield login did not finish — re-run 'higgsfield auth login' anytime"
fi
else
info "Skipped — sign in later with: higgsfield auth login"
fi
else
info "Not signed in. Generation needs: higgsfield auth login"
fi
info "Pack is off by default — enable: bash lib/toggle-external.sh enable higgsfield"
fi
echo ""
# ============================================================
# STEP 8.7 — 21ST.DEV CLI + SKILL PACK
# ============================================================
@@ -1065,13 +1137,13 @@ apply_effort_pins "$REPO" || warn "effort pins: map lines rejected — fix lib/e
# Auth — detect, then offer login ONLY in an interactive TTY. A non-interactive
# run (CI / headless / re-run) must never open a browser or block on OAuth.
# Search and logo lookup are free; retrieving component code and 21st AI need
# the session. Mirrors the ctx7 auth block (Step 6).
# the session. Mirrors the ctx7 auth block (Step 6), stdin-only test included.
if command -v 21st &>/dev/null; then
# `whoami` is a local token read (no network): "Logged in as <user> (saved …)."
TFD_WHO="$(21st whoami 2>/dev/null | head -1)"
if [[ "$TFD_WHO" == "Logged in as "* ]]; then
ok "21st: ${TFD_WHO%.}"
elif [ -t 0 ] && [ -t 1 ]; then
elif [ -t 0 ]; then
printf '%b' "${BLUE}→${NC} Sign in to 21st now? (opens a browser) [y/N] "
read -r tfd_ans || tfd_ans=""
if [[ "$tfd_ans" =~ ^[Yy]([Ee][Ss])?$ ]]; then
@@ -1236,6 +1308,7 @@ echo " 🔄 agent-skills trio — observability-and-instrumentation, deprec
echo " 🔄 mengto scroll skills — scroll-world-storytelling, build-threejs-scroll-worlds, scroll-scrubbed-visual-sequence, scroll-scrubbed-word-reveal, scroll-progress-timeline (curl → symlink, pinned commit)"
echo " 🔄 darwin-skill — autonomous skill optimizer (npx skills, ~/.agents/skills/)"
echo " 🔄 21st skill pack — 21st.dev CLI skills; design ones follow the profile (full by default), publishing ones on demand (toggle: lib/toggle-external.sh enable 21st)"
echo " 🔄 higgsfield pack — Higgsfield CLI media skills (image, video, audio, brand), OFF by default (toggle: lib/toggle-external.sh enable higgsfield; landing-page aid: enable higgsfield-websites)"
echo ""
echo " All plugins installed at: user scope (~/.claude/plugins/)"
echo " GStack skills symlinked individually into ~/.claude/skills/ (→ submodule)"
+24
View File
@@ -312,5 +312,29 @@ expect profiles \
expect pins-map "$(count lib/effort-pins.txt higgsfield)" 0
verdict OFF_BY_DEFAULT_WIRING
# ln_first / ln_last <file> <fixed string> — line number of a match.
ln_first() { grep -nF -- "$2" "$ROOT/$1" | head -1 | cut -d: -f1; }
ln_last() { grep -nF -- "$2" "$ROOT/$1" | tail -1 | cut -d: -f1; }
# shellcheck disable=SC2016 # a literal to grep for, not an expansion
PINS='apply_effort_pins "$REPO"'
# install-plugins.sh: the sync sits in Step 8.6, before the effort pins
# (BDR-108); the CLI is proven by a probe, not by its shim; every login
# offer tests stdin alone (stdout is the tee pipe).
sync_ln="$(ln_last install-plugins.sh 'higgsfield_sync_skills')"
expect after-8.5 "$(yn test "$sync_ln" -gt \
"$(ln_first install-plugins.sh 'Step 8.5: External skills')")" yes
expect before-8.7 "$(yn test "$sync_ln" -lt \
"$(ln_first install-plugins.sh 'Step 8.7: 21st.dev')")" yes
expect before-pins "$(yn test "$sync_ln" -lt \
"$(ln_last install-plugins.sh "$PINS")")" yes
expect probe-gates \
"$(yn test "$(count install-plugins.sh 'if higgsfield_cli_ok')" -ge 3)" yes
expect control "$(echo 'if [ -t 0 ] && [ -t 1 ]; then' | grep -cF -- '-t 1')" 1
expect no-stdout-test "$(count install-plugins.sh '-t 1')" 0
expect stdin-tests \
"$(yn test "$(count install-plugins.sh '[ -t 0 ]')" -ge 3)" yes
verdict INSTALL_WIRING
# ── tally ───────────────────────────────────────────────────
printf 'PASS=%s FAIL=%s\n' "$pass" "$fail"; [ "$fail" -eq 0 ]