Prepare dependency generations before selecting them. Keep shipped tool bytes separate from writable additions, and store facts beside their entries. Validate proposed plugin sets before config publication. Restore the previous config if the facts write fails. Consolidate duplicate updater, backup, setup, and voice helpers. Repair launcher selection, dependency consumers, download ownership, update feeds, and native Windows process and file handling. Verification: 206 changed/prior-failing Python files reported 4630 passed, one failed, and 330 skipped. Fix the remaining Hindsight fixture boundary. The final targeted rerun reported 234 passed and two skipped. The store review regression batch reported 83 passed and one skipped. Desktop TypeScript checks, 56 selected Electron tests, 24 release tests, and the removed-import/compatibility guards passed. This is an integration checkpoint, not full audit acceptance. The complete Python suite has not run on this fixed tree. Crash-atomic plugin publication, generation cleanup, receipt correlation, and packaged lifecycle acceptance remain open in docs/pm-audit-status.md.
96 lines
4.1 KiB
Bash
96 lines
4.1 KiB
Bash
#!/bin/bash
|
|
# ============================================================================
|
|
# venv-style activation for the Hermes dev environment (pm-managed tools).
|
|
#
|
|
# source ./activate (bash / zsh, repo root)
|
|
# .\activate.ps1 (PowerShell)
|
|
#
|
|
# Emits the composed pm env (PATH + tool vars) into the CURRENT shell, with
|
|
# save/restore: `deactivate` undoes exactly what activation changed.
|
|
#
|
|
# Requires a completed `./setup-hermes.sh` — it never invokes uv. It runs
|
|
# the pm store's pinned python (fallback: the repo venv) to emit the env
|
|
# JSON, then exports it here.
|
|
# ============================================================================
|
|
# Guard against double-sourcing: venv activate precedent (re-activating is a
|
|
# no-op re-save; we keep it idempotent by deactivating first).
|
|
if [ -n "${__HERMES_ACTIVATED:-}" ]; then
|
|
deactivate
|
|
fi
|
|
|
|
_HERMES_REPO="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
|
|
# Bootstrap Python only emits the environment; it does not install anything.
|
|
_hermes_repo="$_HERMES_REPO"
|
|
_hermes_py=""
|
|
for _hermes_candidate in "$_hermes_repo/.venv/bin/python" "$_hermes_repo/.venv/Scripts/python.exe" \
|
|
"$_hermes_repo/venv/bin/python" "$_hermes_repo/venv/Scripts/python.exe"; do
|
|
[ -x "$_hermes_candidate" ] && { _hermes_py="$_hermes_candidate"; break; }
|
|
done
|
|
if [ -z "$_hermes_py" ]; then
|
|
for _hermes_store in "${HERMES_RUNTIME_DIR:-}" "$_hermes_repo/../tools" "${HERMES_HOME:-$HOME/.hermes}/tools"; do
|
|
[ -n "$_hermes_store" ] || continue
|
|
for _hermes_candidate in "$_hermes_store"/python-*/bin/python3 "$_hermes_store"/python-*/python.exe "$_hermes_store"/python-*/bin/python "$_hermes_store"/python-*/bin/python.exe; do
|
|
[ -x "$_hermes_candidate" ] && { _hermes_py="$_hermes_candidate"; break; }
|
|
done
|
|
[ -n "$_hermes_py" ] && break
|
|
done
|
|
fi
|
|
if [ -z "$_hermes_py" ]; then
|
|
echo "activate: no bootstrap Python found; run setup-hermes.sh" >&2
|
|
return 1 2>/dev/null || exit 1
|
|
fi
|
|
|
|
# --- emit export lines from `pm env` ---
|
|
_hermes_json="$(PYTHONHOME= PYTHONPATH="$_hermes_repo" "$_hermes_py" -m hermes_cli.runtime_paths)"
|
|
if [ -z "$_hermes_json" ] || [ "${_hermes_json#*{}" = "$_hermes_json" ]; then
|
|
echo "activate: could not read pm env (run ./setup-hermes.sh first)" >&2
|
|
unset _hermes_repo _hermes_os _hermes_arch _hermes_target _hermes_store _hermes_py _hermes_json
|
|
return 1 2>/dev/null || exit 1
|
|
fi
|
|
|
|
_hermes_keys="$(printf '%s' "$_hermes_json" | "$_hermes_py" -c 'import json,sys; print(" ".join(json.load(sys.stdin)))' \
|
|
| tr ' ' '\n' | grep -E '^[A-Za-z_][A-Za-z0-9_]*$' | tr '\n' ' ')"
|
|
[ -n "$_hermes_keys" ] || _hermes_keys="PATH"
|
|
|
|
# --- snapshot what we are about to change (deactivate restores this) ---
|
|
__HERMES_ACTIVATED=1
|
|
__HERMES_SAVED_PATH="$PATH"
|
|
for _hermes_k in $_hermes_keys; do
|
|
eval "__HERMES_SAVED_$_hermes_k=\"\${$_hermes_k+set}\""
|
|
eval "__HERMES_PRIOR_$_hermes_k=\${$_hermes_k-__HERMES_UNSET__}"
|
|
done
|
|
|
|
eval "$(printf '%s' "$_hermes_json" | "$_hermes_py" -c '
|
|
import json, sys, shlex, re
|
|
for k, v in json.load(sys.stdin).items():
|
|
# Windows carries names like ProgramFiles(ARM) that are not valid
|
|
# bash identifiers — skip them (they pass through untouched).
|
|
if not re.fullmatch(r"[A-Za-z_][A-Za-z0-9_]*", k):
|
|
continue
|
|
print("export %s=%s" % (k, shlex.quote(str(v))))')"
|
|
|
|
deactivate() {
|
|
export PATH="$__HERMES_SAVED_PATH"
|
|
for _hermes_k in $__HERMES_KEY_LIST; do
|
|
eval "_hermes_was=\"\$__HERMES_SAVED_$_hermes_k\""
|
|
eval "_hermes_old=\"\$__HERMES_PRIOR_$_hermes_k\""
|
|
if [ "$_hermes_was" != "set" ]; then
|
|
unset "$_hermes_k"
|
|
else
|
|
export "$_hermes_k=$_hermes_old"
|
|
fi
|
|
unset "__HERMES_SAVED_$_hermes_k" "__HERMES_PRIOR_$_hermes_k"
|
|
done
|
|
unset __HERMES_SAVED_PATH __HERMES_KEY_LIST __HERMES_ACTIVATED
|
|
unset -f deactivate
|
|
unset _hermes_k _hermes_was _hermes_old
|
|
}
|
|
|
|
# remember the key list for deactivate (kept out of the loop vars above)
|
|
__HERMES_KEY_LIST="$_hermes_keys"
|
|
|
|
unset _hermes_repo _hermes_os _hermes_arch _hermes_target _hermes_store \
|
|
_hermes_py _hermes_json _hermes_keys _hermes_k _hermes_entry _hermes_venvpy \
|
|
_hermes_winarch
|