* fix(windows): SSH ControlMaster gating + stop hijacking the user's python Two Windows environment-integrity fixes: 1. tools/environments/ssh.py (#73927): Windows OpenSSH has no Unix-domain-socket ControlMaster support, so unconditionally passing ControlPath/ControlMaster/ControlPersist failed EVERY tool call on a Windows-hosted ssh terminal backend with 'getsockname failed: Not a socket'. Gate the three multiplexing options behind a module-level _SSH_MULTIPLEX = (os.name != 'nt'); the scp upload path is gated the same way. On Windows the backend now works without connection pooling (each command a fresh connection); POSIX behavior is unchanged. The teardown 'ssh -O exit' is naturally inert because the socket never exists on Windows. 2. scripts/install.ps1 (#83797): the installer put the whole venv\Scripts directory on the user PATH, which contains python.exe / pythonw.exe / pip.exe and so silently hijacked the 'python' command in every terminal on the machine — unrelated projects started resolving python to Hermes' runtime interpreter. Now copy only the launchers (hermes.exe, hermes-acp.exe) into a dedicated $InstallDir\bin and put THAT on PATH. Existing installs are migrated: the legacy venv\Scripts entry is stripped from the user PATH on the next install/update. The new bin dir is under $InstallDir (…\hermes-agent), which the uninstall PATH sweep already matches via its \hermes-agent marker. Updated the stale hermes_cli/update_cmd.py docstring that described the old venv\Scripts-on-PATH layout. Tests: SSH ControlMaster gating pinned both directions (multiplex on → flags present; off → absent but BatchMode/StrictHostKeyChecking retained). install.ps1 parses clean via the PowerShell AST parser. * docs: update windows-native install docs for the bin\ launcher layout CI (test_windows_native_docs) pins the docs and installer to the same PATH layout. The #83797 fix moved the PATH entry from venv\Scripts to a dedicated $InstallDir\bin holding only the hermes launchers, so update the Windows-native guide to match: PATH-after-install section, the install-steps list, the directory-layout table, the Get-Command verification line, and the 'command not found' pitfall. Test now asserts the bin\ layout and guards against a regression back to venv\Scripts on PATH. * fix: keep install.ps1 pure ASCII (PowerShell 5.1 codepage safety) The two comments I added in the #83797 PATH-hijack fix used em-dashes, tripping tests/test_install_ps1_ascii_only.py — Windows PowerShell 5.1 reads a BOM-less .ps1 in the system ANSI codepage (not UTF-8), so a non-ASCII byte can misdecode into a stray quote and desync the parser (issues #66994/#67000). Replace the em-dashes with ASCII '--'. |
||
|---|---|---|
| .. | ||
| dashboard_auth | ||
| observability | ||
| proxy | ||
| subcommands | ||
| web_routers | ||
| __init__.py | ||
| _early_recovery.py | ||
| _parser.py | ||
| _scan_venv_blockers.py | ||
| _startup_fast.py | ||
| _subprocess_compat.py | ||
| active_sessions.py | ||
| agent_import.py | ||
| agent_plugins.py | ||
| approval_mode.py | ||
| approvals_suggest.py | ||
| approvals_test.py | ||
| auth.py | ||
| auth_commands.py | ||
| azure_detect.py | ||
| backup.py | ||
| bang_shell.py | ||
| banner.py | ||
| blueprint_cmd.py | ||
| browser_connect.py | ||
| build_info.py | ||
| bundles.py | ||
| callbacks.py | ||
| checkpoints.py | ||
| claw.py | ||
| cli_agent_setup_mixin.py | ||
| cli_billing_mixin.py | ||
| cli_commands_mixin.py | ||
| cli_output.py | ||
| clipboard.py | ||
| codex_models.py | ||
| codex_runtime_plugin_migration.py | ||
| codex_runtime_switch.py | ||
| colors.py | ||
| commands.py | ||
| completion.py | ||
| config.py | ||
| config_defaults.py | ||
| config_migrations.py | ||
| console_engine.py | ||
| container_boot.py | ||
| context_switch_guard.py | ||
| copilot_auth.py | ||
| credential_lifecycle.py | ||
| cron.py | ||
| curator.py | ||
| curses_ui.py | ||
| dashboard_procs.py | ||
| dashboard_register.py | ||
| debug.py | ||
| default_soul.py | ||
| dep_ensure.py | ||
| diagnostics_upload.py | ||
| dingtalk_auth.py | ||
| doctor.py | ||
| doctor_live.py | ||
| dump.py | ||
| env_loader.py | ||
| fallback_cmd.py | ||
| fallback_config.py | ||
| focus_view.py | ||
| gateway.py | ||
| gateway_enroll.py | ||
| gateway_windows.py | ||
| goals.py | ||
| gui_uninstall.py | ||
| heartbeat.py | ||
| hooks.py | ||
| init_command.py | ||
| input_sanitize.py | ||
| inventory.py | ||
| journey.py | ||
| kanban.py | ||
| kanban_db.py | ||
| kanban_decompose.py | ||
| kanban_diagnostics.py | ||
| kanban_specify.py | ||
| kanban_swarm.py | ||
| lifecycle.py | ||
| linux_desktop_entry.py | ||
| logs.py | ||
| main.py | ||
| managed_scope.py | ||
| managed_uv.py | ||
| mcp_catalog.py | ||
| mcp_config.py | ||
| mcp_picker.py | ||
| mcp_security.py | ||
| mcp_startup.py | ||
| mem_trim.py | ||
| memory_oauth.py | ||
| memory_setup.py | ||
| middleware.py | ||
| migrate.py | ||
| moa_cmd.py | ||
| moa_config.py | ||
| model_catalog.py | ||
| model_cost_guard.py | ||
| model_normalize.py | ||
| model_search.py | ||
| model_setup_flows.py | ||
| model_switch.py | ||
| models.py | ||
| nous_account.py | ||
| nous_auth_keepalive.py | ||
| nous_billing.py | ||
| nous_subscription.py | ||
| npm_engine.py | ||
| onepassword_secrets_cli.py | ||
| oneshot.py | ||
| pairing.py | ||
| partial_compress.py | ||
| personality.py | ||
| pets.py | ||
| platforms.py | ||
| plugins.py | ||
| plugins_cmd.py | ||
| portal_cli.py | ||
| profile_describer.py | ||
| profile_distribution.py | ||
| profiles.py | ||
| projects_cmd.py | ||
| projects_db.py | ||
| prompt_size.py | ||
| prompt_stash.py | ||
| provider_catalog.py | ||
| providers.py | ||
| proxy_cli.py | ||
| psutil_android.py | ||
| pt_input_extras.py | ||
| pty_bridge.py | ||
| pty_session.py | ||
| relaunch.py | ||
| resource_limits.py | ||
| route_identity.py | ||
| runtime_provider.py | ||
| secret_prompt.py | ||
| secrets_cli.py | ||
| security_advisories.py | ||
| security_audit.py | ||
| security_audit_startup.py | ||
| send_cmd.py | ||
| service_manager.py | ||
| session_export.py | ||
| session_export_html.py | ||
| session_export_md.py | ||
| session_filters.py | ||
| session_listing.py | ||
| session_recap.py | ||
| session_recovery.py | ||
| sessions_cmd.py | ||
| setup.py | ||
| setup_hidden_env.py | ||
| setup_whatsapp_cloud.py | ||
| sizefmt.py | ||
| skills_config.py | ||
| skills_hub.py | ||
| skin_cmd.py | ||
| skin_engine.py | ||
| slack_cli.py | ||
| slash_exec.py | ||
| sqlite_runtime.py | ||
| sqlite_safe_read.py | ||
| sqlite_util.py | ||
| status.py | ||
| stdio.py | ||
| suggestions_cmd.py | ||
| telegram_managed_bot.py | ||
| timefmt.py | ||
| timeouts.py | ||
| tips.py | ||
| tools_config.py | ||
| toolset_validation.py | ||
| uninstall.py | ||
| update_cmd.py | ||
| update_lock.py | ||
| urllib_security.py | ||
| vercel_auth.py | ||
| verify_cmd.py | ||
| voice.py | ||
| web_deps.py | ||
| web_git.py | ||
| web_models.py | ||
| web_server.py | ||
| webhook.py | ||
| win_pty_bridge.py | ||
| windows_ssh_runtime.py | ||
| write_approval_commands.py | ||
| xai_retirement.py | ||