Files
hermes-agent/activate.ps1
ethernet a00ca233f8 fix(pm): voice enables audio-io through PM; public plugin-state readers; PM tests isolate the machine home
- voice_mode: `_import_audio` asks `pm.ensure_import("audio-io")` before importing
  sounddevice, so `/voice on` turns the feature on (or reports exactly why PM
  refused: lazy installs off, platform gate, restart needed) instead of printing a
  `python -c "from pm import sync_venv…"` one-liner for the user to run.
- pm.plugins_state: `read_home_selection` and `dependency_homes` are the public
  readers; memory_provider_migration and plugins_cmd stop importing underscored names.
- pm.store: the `sha256_file` shim is gone; the authority test asserts the Store has no
  file hash of its own rather than patching one.
- tests/pm/conftest: `isolated_machine_home` is autouse (Path.home, HOME, USERPROFILE,
  HERMES_HOME all under tmp_path); `@pytest.mark.real_machine_home` opts a module out
  — the four suites that spawn children with a home they build themselves.
- activate / activate.ps1 / Dockerfile followed hermes_cli.runtime_paths to
  pm.environments (the earlier sweep only covered .py).
- pm.registry loads builtins through importlib so a test patching `pm.packages` in
  sys.modules still registers the security packages.
2026-09-19 00:48:11 -04:00

78 lines
3.5 KiB
PowerShell
Executable File

# Source this file to sync and apply the PM environment; deactivate restores it.
$ErrorActionPreference = 'Stop'
$OutputEncoding = [System.Console]::OutputEncoding = [System.Console]::InputEncoding = [System.Text.Encoding]::UTF8
$PSDefaultParameterValues['*:Encoding'] = 'utf8'
$repo = $PSScriptRoot
$bootstrapSaved = @{}
foreach ($key in @('PYTHONPATH', 'PYTHONHOME', 'VIRTUAL_ENV')) {
$bootstrapSaved[$key] = [Environment]::GetEnvironmentVariable($key)
Remove-Item "env:$key" -ErrorAction SilentlyContinue
}
try {
# Run separately so setup's exit/failure cannot terminate the sourced shell.
$shell = (Get-Process -Id $PID).Path
& $shell -NoProfile -NonInteractive -ExecutionPolicy Bypass -File "$repo\setup-hermes.ps1" -RuntimeOnly | Out-Host
if ($LASTEXITCODE -ne 0) { throw 'activate: setup failed; shell environment unchanged' }
} finally {
foreach ($key in $bootstrapSaved.Keys) {
if ($null -eq $bootstrapSaved[$key]) { Remove-Item "env:$key" -ErrorAction SilentlyContinue }
else { Set-Item "env:$key" $bootstrapSaved[$key] }
}
}
if (Test-Path function:deactivate) { deactivate }
$py = $null
foreach ($candidate in @("$repo\.venv\Scripts\python.exe", "$repo\venv\Scripts\python.exe")) {
if (Test-Path -LiteralPath $candidate) { $py = $candidate; break }
}
if (-not $py) {
$roots = @($env:HERMES_RUNTIME_DIR, "$repo\..\tools")
$homeRoot = if ($env:HERMES_HOME) { $env:HERMES_HOME } else { "$env:LOCALAPPDATA\hermes" }
$roots += (Join-Path $homeRoot 'tools')
foreach ($root in $roots) {
if (-not $root) { continue }
foreach ($entry in @(Get-ChildItem -LiteralPath $root -Directory -Filter 'python-*' -ErrorAction SilentlyContinue)) {
$candidate = Join-Path $entry.FullName 'python.exe'
if (Test-Path -LiteralPath $candidate) { $py = $candidate; break }
}
if ($py) { break }
}
}
if (-not $py) { throw 'activate: no bootstrap Python found; run setup-hermes.ps1' }
$priorPath = $env:PYTHONPATH
$priorHome = $env:PYTHONHOME
try {
$env:PYTHONPATH = $repo
Remove-Item env:PYTHONHOME -ErrorAction SilentlyContinue
$json = (& $py -m pm.environments) -join "`n"
if ($LASTEXITCODE -ne 0) { throw 'activate: could not read the installed environment' }
$composed = $json | ConvertFrom-Json
} finally {
if ($null -eq $priorPath) { Remove-Item env:PYTHONPATH -ErrorAction SilentlyContinue } else { $env:PYTHONPATH = $priorPath }
if ($null -eq $priorHome) { Remove-Item env:PYTHONHOME -ErrorAction SilentlyContinue } else { $env:PYTHONHOME = $priorHome }
}
# __HERMES_ACTIVATED (the sentinel repo scripts and the shebang prologue read)
# is part of the composed env, so it is saved and restored with the rest.
$global:_hermesKeys = @($composed.PSObject.Properties.Name)
$global:_hermesSaved = @{}
foreach ($key in $global:_hermesKeys) {
$global:_hermesSaved[$key] = [pscustomobject]@{
WasSet = (Test-Path "env:$key")
Value = [Environment]::GetEnvironmentVariable($key)
}
}
foreach ($property in $composed.PSObject.Properties) {
Set-Item -Path "env:$($property.Name)" -Value ([string]$property.Value)
}
function global:deactivate {
foreach ($key in $global:_hermesKeys) {
$saved = $global:_hermesSaved[$key]
if ($saved.WasSet) { Set-Item -Path "env:$key" -Value $saved.Value }
else { Remove-Item -Path "env:$key" -ErrorAction SilentlyContinue }
}
$global:_hermesKeys = $null
$global:_hermesSaved = $null
Remove-Item function:deactivate
}