- Exempted the `fmt:rs` task from the early-exit skip logic so formatting always runs.
- Reformatted `apply_command_env` signature in shell.rs to satisfy the formatter.
Brush-core applied POSIX parameter expansion to $env before dispatching a command, mangling PowerShell references like Write-Host $env:SystemRoot to :SystemRoot. Move the fix down to env-var application: every brush session now defines env=$env as an internal (non-exported) shell variable, so the bash expansion of $env yields the literal $env and PowerShell tokens reach the child intact. User assignments (env=prod; echo "$env:8080") still shadow the fallback in their command scope, so the POSIX bash contract is preserved.
Fixes#1079
- Stop now marks the client as closed via `_mark_closed` with `RpcProcessExitError`, so `_wait_for_agent_end` wakes immediately instead of waiting for a timeout.
- Added a regression test using a hanging server subprocess to verify `stop()` unblocks `prompt_and_wait` promptly and raises `RpcProcessExitError`.
- Updated Kimi compatibility tests to distinguish Moonshot-hosted models from OpenCode-hosted ones for `reasoning_content` and assistant-content tool-call behavior.
- Added a `resolveSearchRepoScope` helper that uses an explicit `repo` when provided, skips defaulting when a query already contains a repo/org/user/owner scope qualifier, and otherwise resolves the current checkout via `resolveDefaultRepoMemoized`.
- Updated `search_issues`, `search_prs`, `search_code`, and `search_commits` to use the resolver before composing API queries, defaulting `repo` when omitted but silently falling back to an unscoped search on resolution failure.
- Documented the new search-repo defaulting rules in tool prompts, user docs, and the package changelog.
- Added a new `.dockerignore` to keep build context clean by excluding targets, node_modules, logs, IDE files, OS junk, generated outputs, and secrets.
- Created a multi-stage Dockerfile that builds Linux `pi_natives.linux-*.node` and `omp-rpc` wheel artifacts in dedicated builder stages.
- Published a minimal scratch artifacts stage that only exports the compiled native addon and wheel into `/out/` for downstream image consumption.
The agentic commit pipeline (`omp commit`) wrote its commit and then sat
spinning on Ctrl+C because nothing in `Commit.run()` drained the lingering
event-loop handles: `installH2Fetch()` keeps idle HTTP/2 sockets warm to
the provider, the Settings autosave timer can still be armed, and the
AgentSession's extension/runner machinery holds onto async-job and OAuth
refresh state even after `session.dispose()` releases what it knows how
to. Mirror the `runPrintMode` exit path from `main.ts` by calling
`postmortem.quit(0)` once `runCommitCommand` resolves so the CLI returns
to the shell, runs registered cleanup callbacks, then exits — same model
the non-interactive launch flow already uses.
Also widens the private bash-tool helpers' `notices` parameter to
`readonly string[]` so `bun check:types` keeps passing — the public outer
arm already accepted `readonly string[]` and an upstream commit had only
partially propagated the change.
Fixes#1041
The previous examples used " • " in the source file and inserted "·"
as the new content. Some agents were copying the middle-dot literally
into real edits as if it were format scaffolding, since the demo
inserts were near-twins of the existing string.
The new example uses TITLE = "Mr" → "Mrs" with "Dr" inserts:
ASCII-only, clearly distinct from any payload separator, and obviously
domain content rather than punctuation the model could confuse for
syntax. Every original op shape is preserved (single-line replace,
multiline replace, insert AFTER/BEFORE, append, delete, blank, both
anti-patterns). Pure prompt change; parser/schema/runtime untouched.
- Added an explicit notice in the eval tool docs cautioning against using one-off `-c`/`-e` shell executions.
- Documented that the eval tool should be used instead for persistent runtimes, structured outputs, and cancellation or timeout support.
The ClaudePluginManifest interface was missing the `commands` field
(the standard Claude plugin format), and resolvePluginDir only checked
the legacy `slash-commands` key. Plugins declaring their command path
via `"commands": "..."` silently fell back to the hardcoded
`<plugin-root>/commands/` directory, which doesn't exist for
Claude-format plugins, so no slash commands were ever loaded.
Changes:
- Added `commands?: string` to ClaudePluginManifest.
- Changed resolvePluginDir to accept ReadonlyArray<keyof
ClaudePluginManifest> and iterate in priority order; the first
non-empty match wins.
- loadSlashCommands now passes ["commands", "slash-commands"] so
the canonical Claude plugin key takes precedence over the legacy one.
- Added two regression tests: one covering the `commands` key in
isolation, one verifying its precedence over `slash-commands` when
both fields are present.
Fixes#1076
- Updated `collectPayload` to treat blank lines inside a payload run as empty entries when subsequent payload text is present.
- Added lookahead-based end-of-run detection so blank lines before a non-payload operation remain section separators.
- Added tests verifying blank-line recovery inside payloads and non-consumption of trailing blanks between hashline sections.
- Converted several single-line guard-style `if let`/`let Some` exits in `fixup.rs` into multiline blocks for consistent style.
- Reformatted the safe-argument regex definition and normalized test case formatting in `fixup.rs` without altering assertions.
- Reordered `lib.rs` module exports by moving `fixup` ahead of `minimizer`.
Loaded cached standard provider discovery models into ModelRegistry at startup so retry fallback validation can resolve Ollama Cloud models that are already visible through --list-models.
Added regression coverage for cached ollama-cloud fallback selectors and fixed a readonly notices type error exposed by the focused type check.
Fixes#1052
- anthropic: add signal to AnthropicSearchParams, callSearch(), and
AnthropicProvider.search()
- exa: add signal to ExaSearchParams, callExaSearch(), and ExaProvider.search()
- jina: add signal to JinaSearchParams, callJinaSearch(), and JinaProvider.search()
- zai: add signal to ZaiSearchParams, callZaiTool(), and ZaiProvider.search()
- gemini: add signal to GeminiSearchParams, callGeminiSearch() and
buildInit() so both fetchWithRetry calls (initial + auth-refresh retry)
carry the signal
The five providers listed above never forwarded SearchParams.signal to the
underlying HTTP layer, so pressing Esc during a web_search call had no effect
and the session froze until the request resolved or Ctrl+C was pressed.
brave, kimi, perplexity, searxng, tavily, synthetic, codex, kagi, and parallel
already thread the signal correctly and are unchanged.
Fixes#1044
- Added stripOutputNotice to output-meta to remove appended truncation notices when output metadata is available.
- Updated bash, eval, browser, read, and ssh renderers to strip the notice before display so the styled warning line is not duplicated.
- Left fallback behavior unchanged so outputs without a notice continue through unchanged.
TypeScript 6 tightens mutability checks; the notices parameter was typed
as string[] but the caller held a readonly string[] (from the options
object). Widening both private method overloads to readonly string[]
satisfies the type checker without any runtime change — filter(Boolean)
works on readonly arrays.
discoverAgents() called listClaudePluginRoots() unconditionally, so agents
from Claude Code marketplace plugins appeared in /agents and the Agent
Control Center even when claude-plugins was listed in disabledProviders.
Guard the listClaudePluginRoots() call with isProviderEnabled("claude-plugins"),
returning an empty roots array when the provider is disabled — matching how
filterProviders() handles every other capability's provider set.
Added regression test that verifies both the enabled path (agents visible)
and the disabled path (agents absent) using a real temp-directory plugin
registry fixture.
Fixes#1075
- Added user, group, and extra_groups parameters to RpcClient initialization.
- Propagated those parameters through to subprocess startup calls.
- Added tests to verify the new kwargs are passed correctly, including None defaults and empty extra groups.
- Updated `formatBashFixupNotice` to wrap the stripped-pattern warning in a `<system-warning>` wrapper.
- Reworded the notice to clarify output is already truncated and stderr is merged into stdout.
- Extended the Bash interceptor test to verify the warning tag appears for head/tail stripping.
- Added a persistent asyncio event loop and coroutine-aware compiled-code execution for runner cells.
- Enabled compiling notebook cells with top-level await flags and awaiting coroutine results before rendering.
- Added an integration test confirming top-level await works across kernel cells with preserved state.
- Added top-level parsing and segment splitting to apply bash fixups only on safe command chunks.
- Replaced `stripTrailingHeadTail` usage with `applyBashFixups` and array-based notice formatting.
- Fixed terminal `| head`/`| tail` and redundant `2>&1` stripping while preserving command semantics.
- Updated fixup tests for cross-command cases and removed superseded head-tail-only test coverage.
- Added message-ID checks in both assistant and user message parsers so entries without valid ids are ignored.
- This filtering prevents legacy, unlinked message records from being treated as parseable assistant or user messages.
- Adjusted the test server in test_host_uris.py to re-emit host_uri_result frames as uri_echo notifications.
- Updated test client setup to attach an unknown-notification capture hook for uri_echo frames.
- Changed _await_echo to read captured uri_echo frames from that hook and fail fast if capture is missing.
- Added `_optional_str_list` to normalize `systemPrompt` payloads into a tuple when absent, a bare string, or a string array, and to reject invalid shapes.
- Updated `SessionState` to hold `system_prompt` as a tuple and to parse daemon payloads with the new helper in `parse_session_state`.
- Extended protocol tests to verify array and legacy string parsing, default empty tuple behavior, and invalid `systemPrompt` values.
Drop trailing `| head [args]` / `| tail [args]` pipes that exist purely
to limit output — the harness already truncates bash output and exposes
the full result via the bash-original artifact, so these pipes only
hide content from the agent.
Conservative gates (any failing leaves the command verbatim):
- single-line only; multi-line scripts may legitimately end pipelines
with head/tail to bound a generator or loop body
- whitelisted limit-only args (-nN, -n N, -cN, -N, -q, -v, --lines[=N],
--bytes[=N], --quiet, --verbose); rejects -f/-F/+N/filenames so
`tail -f`, `tail -n +2` etc. stay intact
- regex anchored at end of command; any downstream operator (`&&`,
`||`, `;`, `&`, `>`, `|`, `` ` ``, `$(…)`, `)`) blocks the match, so
`just build 2>&1 | tail -3 && just up && …` is untouched
- refuses to reduce the command to an empty string
- pipe boundary uses `[ \t]*`, not `\s*`, so a `|` on a continuation
line cannot be swallowed
Consolidates the existing `timeoutClampNotice` and the new strip notice
into a single `pendingNotices: string[]` array threaded through every
execute branch (async, auto-background, ACP terminal, local exec).
New setting `bash.stripTrailingHeadTail` (default `true`).
- Updated the status-line path segment to detect project directories under OS scratch roots and strip the scratch root when rendering.
- Switched scratch-root paths to use the new icon.scratchFolder glyph and registered that symbol across theme variants.
- Added tests covering scratch-root trimming, nested scratch subpaths, and non-scratch fallback icon behavior.
- Fixed legacy `pi-*` scope alias remapping to canonical packages, including `pi-ai/oauth` rewrites.
- Fixed restoration of `Key` on `@oh-my-pi/pi-tui` with canonical key strings and typed modifier helpers.
- Updated both package changelogs with unreleased notes for compatibility and `Key` restoration.
- Added `pi-scope-aliases.test.ts` coverage for alias remaps using fixture plugins and `loadExtensions`.
- Updated job label rendering to split labels on newlines and cap visible lines by collapsed or expanded view state.
- Truncated each visible label line to the existing max width and appended an ellipsis when extra lines were hidden.
- Printed additional visible label lines as indented follow-on lines beneath the job header.
- Added Windows node_modules staging checks so non-compiled addons are copied into versioned native directories.
- Updated loader candidate resolution to prefer embedded/staged/versioned candidates before default runtime paths when staging is enabled.
- Added runtime version-sentinel export __piNativesV15_0_1 and load-time validation to avoid stale binary drift.
- Added typing and release-flow updates to expose staging options and keep per-release sentinel IDs aligned.
- Updated shell minimizer line truncation to append `...[+N]` with the count of dropped Unicode scalars when truncation occurs.
- Updated read summary rendering to track `elidedLines`, include them in tool details, and append a recovery footer for `:raw` or line-range access whenever elided spans are present.
- Updated read-tool prompts/docs/tests to cover the new elision-footers and recovery guidance.
Fixes#1046