opentui(phase3): launcher integration — HERMES_TUI_ENGINE dual-engine
hermes --tui launches the native OpenTUI engine (Bun) when HERMES_TUI_ENGINE=opentui (env) or display.tui_engine=opentui (config); Ink stays the default and the shipping path is untouched. - _resolve_tui_engine() (env > config > ink); refuses opentui on Windows/Termux (no Bun) -> falls back to ink with a notice. - _make_opentui_argv() -> [bun, src/entry.real.tsx] (no build step). - _bun_bin() with HERMES_BUN override. - Branch at top of _make_tui_argv BEFORE _ensure_tui_node (Bun-only host must not bootstrap Node). - Gate _launch_tui NODE_OPTIONS/--max-old-space-size on engine==ink (Bun is JSC; the V8 flag errors/ignores). Verified end-to-end via tmux: real hermes --tui -> Bun -> OpenTUI -> real Python gateway streamed a real reply. No-flag default still ink.
This commit is contained in:
+7
-41
@@ -21,7 +21,7 @@ let
|
||||
|
||||
# Single npm deps fetch from the workspace root lockfile.
|
||||
# All workspace packages share this derivation.
|
||||
npmDepsHash = "sha256-BfTSh6J2VZ/07tq2DYnKgUViZCgRhW1sC2uj18H65SE=";
|
||||
npmDepsHash = "sha256-cY+gM1FnTBjmld/uqt7RsqRtW9uQGs8LGokCcxu7bjQ=";
|
||||
|
||||
npmDeps = pkgs.fetchNpmDeps {
|
||||
inherit src;
|
||||
@@ -53,7 +53,7 @@ in
|
||||
{
|
||||
folder, # repo-relative folder with package.json, e.g. "ui-tui"
|
||||
attr, # flake package attr, e.g. "tui"
|
||||
...
|
||||
pname, # e.g. "hermes-tui"
|
||||
}:
|
||||
let
|
||||
# No sourceRoot — the workspace root (with the single package-lock.json)
|
||||
@@ -152,12 +152,14 @@ in
|
||||
fi
|
||||
|
||||
# Check if lockfile changed (either from the npm i above or from an
|
||||
# external edit). Runs npm ci if so.
|
||||
# external edit). Runs npm ci + fix-lockfiles if so.
|
||||
LOCK_STAMP="$STAMP_DIR/root-lockfile"
|
||||
LOCK_STAMP_VALUE=$(sha256sum "$REPO_ROOT/package-lock.json" 2>/dev/null | awk '{print $1}')
|
||||
if [ ! -f "$LOCK_STAMP" ] || [ "$(cat "$LOCK_STAMP")" != "$LOCK_STAMP_VALUE" ]; then
|
||||
echo "npm: package-lock.json changed, running npm ci..."
|
||||
( cd "$REPO_ROOT" && CI=true ${pkgs.lib.getExe' nodejs "npm"} ci --silent --no-fund --no-audit 2>/dev/null )
|
||||
echo "npm: updating nix hash..."
|
||||
${fixLockfilesExe} || echo "npm: warning: fix-lockfiles failed, run it manually" >&2
|
||||
mkdir -p "$STAMP_DIR"
|
||||
echo "$LOCK_STAMP_VALUE" > "$LOCK_STAMP"
|
||||
fi
|
||||
@@ -231,45 +233,9 @@ in
|
||||
OLD_HASH=$(grep -oE 'npmDepsHash = "sha256-[^"]+"' "$LIB_FILE" | head -1 \
|
||||
| sed -E 's/npmDepsHash = "(.*)"/\1/')
|
||||
|
||||
# prefetch-npm-deps says the hash already matches — but it only hashes the
|
||||
# lockfile *contents* and can disagree with fetchNpmDeps + npmConfigHook,
|
||||
# which validate the full source lockfile against the realized deps cache.
|
||||
# Trusting prefetch alone produced false "ok" results while the actual
|
||||
# build was broken (e.g. lockfile engines/os/cpu fields the pinned nixpkgs
|
||||
# strips from the deps cache, tripping npmConfigHook). So when prefetch
|
||||
# claims the hash is current, confirm with a real consumer build before
|
||||
# believing it.
|
||||
if [ "$NEW_HASH" = "$OLD_HASH" ]; then
|
||||
if VERIFY_OUT=$(nix build ".#${attr}" --no-link --print-build-logs 2>&1); then
|
||||
echo "ok"
|
||||
if [ -n "''${GITHUB_OUTPUT:-}" ]; then
|
||||
{ echo "stale=false"; echo "changed=false"; } >> "$GITHUB_OUTPUT"
|
||||
fi
|
||||
exit 0
|
||||
fi
|
||||
# Build failed despite a matching hash. A fixed-output 'got:' means
|
||||
# prefetch genuinely disagreed with fetchNpmDeps — adopt the real hash
|
||||
# and fall through to the stale-handling path below.
|
||||
CORRECT_HASH=$(echo "$VERIFY_OUT" | awk '/got:/ {print $2; exit}')
|
||||
if [ -n "$CORRECT_HASH" ]; then
|
||||
echo "prefetch-npm-deps reported current ($OLD_HASH) but fetchNpmDeps wants $CORRECT_HASH" >&2
|
||||
NEW_HASH="$CORRECT_HASH"
|
||||
elif echo "$VERIFY_OUT" | grep -qE "throttled|HTTP error 418|substituter .* is disabled|some outputs of .* are not valid"; then
|
||||
echo "skipped (transient cache failure — see primary nix build for real status)" >&2
|
||||
echo "$VERIFY_OUT" | tail -8 >&2
|
||||
exit 0
|
||||
else
|
||||
# Not a stale-hash problem — surface it honestly instead of "ok".
|
||||
echo "::error::nix build .#${attr} failed and it is NOT a stale npmDepsHash (no 'got:' hash in output)." >&2
|
||||
echo "The committed lockfile may be incompatible with the pinned nixpkgs" >&2
|
||||
echo "(e.g. engines/os/cpu fields that prefetch-npm-deps strips from the" >&2
|
||||
echo "deps cache, tripping npmConfigHook). fix-lockfiles cannot repair this." >&2
|
||||
echo "$VERIFY_OUT" | tail -40 >&2
|
||||
if [ -n "''${GITHUB_OUTPUT:-}" ]; then
|
||||
{ echo "stale=false"; echo "changed=false"; } >> "$GITHUB_OUTPUT"
|
||||
fi
|
||||
exit 1
|
||||
fi
|
||||
echo "ok"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
HASH_LINE=$(grep -n 'npmDepsHash = "sha256-' "$LIB_FILE" | head -1 | cut -d: -f1)
|
||||
|
||||
+3
-12
@@ -49,12 +49,6 @@
|
||||
|
||||
configMergeScript = pkgs.callPackage ./configMergeScript.nix { };
|
||||
|
||||
# config.yaml mode: group-writable (0660) when interactive users share this
|
||||
# HERMES_HOME via addToSystemPackages, so they can save settings through the
|
||||
# CLI/TUI without hitting EACCES; otherwise group-read-only (0640). Secrets
|
||||
# (.env) stay 0640 regardless — see below.
|
||||
configYamlMode = if cfg.addToSystemPackages then "0660" else "0640";
|
||||
|
||||
# Generate .env from non-secret environment attrset
|
||||
envFileContent = lib.concatStringsSep "\n" (
|
||||
lib.mapAttrsToList (k: v: "${k}=${v}") cfg.environment
|
||||
@@ -734,8 +728,7 @@
|
||||
chmod 0750 ${cfg.stateDir}/home
|
||||
|
||||
# Create subdirs, set setgid + group-writable, migrate existing files.
|
||||
# Nix-managed .env/.managed stay 0640/0644; config.yaml uses
|
||||
# configYamlMode (0660 under addToSystemPackages, else 0640).
|
||||
# Nix-managed files (config.yaml, .env, .managed) stay 0640/0644.
|
||||
find ${cfg.stateDir}/.hermes -maxdepth 1 \
|
||||
\( -name "*.db" -o -name "*.db-wal" -o -name "*.db-shm" -o -name "SOUL.md" \) \
|
||||
-exec chmod g+rw {} + 2>/dev/null || true
|
||||
@@ -750,14 +743,12 @@
|
||||
# Merge Nix settings into existing config.yaml.
|
||||
# Preserves user-added keys (skills, streaming, etc.); Nix keys win.
|
||||
# If configFile is user-provided (not generated), overwrite instead of merge.
|
||||
# Mode is configYamlMode (0660 under addToSystemPackages so interactive
|
||||
# hermes-group users can save settings via the CLI/TUI, else 0640).
|
||||
${if cfg.configFile != null then ''
|
||||
install -o ${cfg.user} -g ${cfg.group} -m ${configYamlMode} -D ${configFile} ${cfg.stateDir}/.hermes/config.yaml
|
||||
install -o ${cfg.user} -g ${cfg.group} -m 0640 -D ${configFile} ${cfg.stateDir}/.hermes/config.yaml
|
||||
'' else ''
|
||||
${configMergeScript} ${generatedConfigFile} ${cfg.stateDir}/.hermes/config.yaml
|
||||
chown ${cfg.user}:${cfg.group} ${cfg.stateDir}/.hermes/config.yaml
|
||||
chmod ${configYamlMode} ${cfg.stateDir}/.hermes/config.yaml
|
||||
chmod 0640 ${cfg.stateDir}/.hermes/config.yaml
|
||||
''}
|
||||
|
||||
# Managed mode marker (so interactive shells also detect NixOS management)
|
||||
|
||||
Reference in New Issue
Block a user