feat(app): embed isolated Hermes profile sessions - #220
Conversation
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 8f99a7279e
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| HermesOrphanSidecarScanner.isVerifiedPostLaunchIdentity( | ||
| identity, | ||
| spec: spec, | ||
| profileName: profile.name, | ||
| hermesHome: hermesHome |
There was a problem hiding this comment.
Validate console entrypoints against the executable install
When hermes is a Python console script resolved from PATH or the explicitly searched ~/.local/bin, its script entrypoint is normally outside the profile-data directory ~/.hermes (and may itself be a symlink). Passing hermesHome here makes isVerifiedPostLaunchIdentity reject that otherwise valid process, so startup reaches the readiness sentinel and is then killed with “process identity could not be verified.” Validate against the resolved executable/installation location rather than the Hermes data home.
Useful? React with 👍 / 👎.
| while process.isRunning && Date() < termDeadline { | ||
| Thread.sleep(forTimeInterval: 0.05) |
There was a problem hiding this comment.
Move sidecar termination waits off the main actor
When a sidecar takes time to honor SIGTERM, this polling loop blocks for up to 2 seconds, followed by another 0.5 seconds after SIGKILL. HermesAgentStore is @MainActor and invokes stop() synchronously from overlay shutdown and profile switching, so closing Hermes or changing profiles can freeze the entire app UI for the full timeout; perform the wait asynchronously or on a background executor.
Useful? React with 👍 / 👎.
| private static func stderrSecrets(for spec: HermesServeLaunchSpec) -> [String] { | ||
| Array(Set(spec.environment.values + [spec.token])) | ||
| .filter { !$0.isEmpty } |
There was a problem hiding this comment.
Redact only secret-bearing environment values
On every sidecar startup failure, this treats every inherited and generated environment value as a secret. The launch environment always contains one-character values such as HERMES_YOLO_MODE=0/1 and HERMES_MTPLX_SHOW_REASONING=0/1, so every matching digit in stderr is replaced with [redacted]; ordinary values such as HOME, PATH, and the model name are also erased. This can make the only startup diagnostic unusable, so restrict the redaction list to actual credentials and tokens.
Useful? React with 👍 / 👎.
Hermes gives a profile's persisted model.provider precedence over HERMES_INFERENCE_PROVIDER, so an embedded launch could inherit an unrelated provider (for example openai-codex). Set HERMES_TUI_PROVIDER=custom in the launch env dict, the processEnvironment lane, the dotenv profile, and the shell export block, and pin the override in the env and dotenv tests.
The Hermes CLI writes base_url: '' for provider profiles without a custom endpoint (for example openai-codex). The routing parser rejected the quoted empty scalar, failed the whole model block, and marked the profile unavailable — disabling it in the picker and hiding its sessions. A quoted empty string is now a valid empty scalar and an empty base_url is treated the same as an omitted one. Regression test pins the openai-codex profile shape.
…es-agent-selection-pr
What
hermes -p <profile> serve --isolatedsidecar for the selected profileIsolation and lifecycle guarantees
config.yamland.envbyte-identicallyValidation
swift test --scratch-path /tmp/mtplx-hermes-textfield-tests --filter Hermes: 134 passed, 0 failedswift test --scratch-path /tmp/mtplx-hermes-textfield-tests: 663 executed, 1 skipped, 0 failedswift build --scratch-path /tmp/mtplx-hermes-textfield-build --product MTPLXApp: passed with Xcode-betauv build --wheel --out-dir dist: passedscripts/fresh_venv_smoke.sh: passedgit diff --check upstream/main...HEAD: passedupstream/mainuses Ornith; this PR changes no Python or Python-test filesScope
This branch is rebuilt directly on current
upstream/mainand contains only the Hermes app integration, its Swift tests, and the corresponding design/plan documents. Retrieval, embeddings, reranking, packaged-runtime, and local build-environment commits are deliberately excluded.