* Fix Windows bundled Hermes CLI launcher
* Update kanban service tests for Hermes process wrapper
---------
Co-authored-by: xingzhi <chuzihao.czh@alibaba-inc.com>
* fix windows coding agent status detection
* fix windows coding agents detection and terminal launch
- Fix Claude Code status detection on Windows by prioritizing .cmd files over unix-style scripts when using 'where' command
- Fix command execution logic for .cmd/.bat files to use proper cmd.exe quoting instead of complex cmdQuote function
- Fix native terminal launch on Windows by properly escaping shellCommand in PowerShell Start-Process instead of using empty $args[0]
These changes resolve issues where Claude Code was incorrectly detected as uninstalled on Windows and native terminal launch failed with PowerShell argument errors.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix claude code custom model launch
* fix windows filename sanitization for coding agent config paths
- Replace invalid filename characters (< > : " / \ | ? *) with underscores in provider/profile names
- Prevents ENOENT errors when provider names contain Windows-invalid characters like colons
- Fixes issue where 'custom:glm-coding-plan' provider would fail to create config directory on Windows
This change ensures that coding agent configuration paths are valid on all platforms while preserving the semantic meaning of provider names.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* remove stale planning docs
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(bridge): refresh terminal env from profile config on profile switch
Profile switching changes HERMES_HOME but the TERMINAL_* environment
variables (TERMINAL_ENV, TERMINAL_SSH_HOST, etc.) still point to the
root config's terminal settings set at gateway startup.
Add _refresh_terminal_env() that re-reads terminal config from the
active profile's config.yaml and sets the corresponding TERMINAL_* env
vars. Call it in:
- AgentPool.get_or_create(): when creating a session for a profile
- AgentPool._run_chat(): before agent execution, inside _profile_env
Errors are handled gracefully: YAML parse failures log to stderr,
terminal_tool cache invalidation failures are silently ignored, and
missing config files are skipped without error.
* fix(bridge): refresh terminal env in worker profile setup
_set_worker_profile_env() handles broker-spawned worker subprocesses
that are isolated per profile. The worker inherits TERMINAL_* env vars
from the broker (root config), and _profile_env() is a no-op in worker
mode, so terminal config was never refreshed for non-default profiles.
Adding _refresh_terminal_env() here means each worker subprocess reads
its own profile's config.yaml terminal section on startup, solving
profile-isolated terminal backends (e.g. SSH per profile).
* fix bridge terminal env refresh scope
* refresh worker profile env for new agents
* avoid bridge worker restart for channel config
* align config controller bridge restart tests
---------
Co-authored-by: GoldenFish123321 <goldfishx@gmail.com>
Co-authored-by: GoldenFishX <golden_fish@foxmail.com>
* fix: don't drop pending tool-call-marker prefix on tool.started/run.done
The `filterBridgeToolCallMarkupDelta` filter holds back any text that
ends in a partial prefix of `[Calling tool:` (i.e. `[`, `[C`, `[Ca`,
..., `[Calling tool`) so it can decide whether the buffered chars are
the start of a tool-call markup block to be hidden, or just regular
text to be released by the next delta.
The bug: that "release on next delta" assumption breaks at TWO points:
1. **On `tool.started`**: the next chunk for this assistant message is
the tool call itself, NOT a follow-up text delta. Buffered chars
sit there forever and nothing flushes them — they vanish silently
from the user-visible stream.
2. **On run completion**: the code did
`state.bridgePendingToolCallMarkup = undefined` directly, dropping
any pending chars without forwarding them.
Both cases produce the user-visible symptom of "abrupt cuts in text
right before/after tool calls (terminal, read_file, write_file...)" —
1 to 13 characters disappear at exactly the boundary where the model
was emitting natural prose that happened to end with `[`.
The fix introduces `flushPendingToolCallMarkup(state)` and calls it:
- In the `tool.started` branch BEFORE recording the tool call, so the
buffered chars are appended to the open assistant message and emitted
as a normal `message.delta` to the client.
- At run-done BEFORE clearing the buffer, same flush path.
This is a pure recovery patch — no change to the marker detection
logic itself. If the buffer turns out to actually be a real
`[Calling tool: ...]` marker that just hasn't completed yet, that
case is still caught by the existing `markerIdx >= 0` branch in the
filter on the next delta. The only behavioral change is that the
"orphan" cases (text that ends with `[` but never becomes a marker)
are no longer dropped.
* fix bridge marker flush persistence
---------
Co-authored-by: Paulo Cavallari <paulocavallari@users.noreply.github.com>
* Allow bridge sessions to run concurrently
* Stabilize bridge concurrency test
* Set bridge approval timeout to 120 seconds
* harden bridge approval concurrency
---------
Co-authored-by: Codex <codex@openai.com>