- 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`.
- 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
`CreateElicitationRequest` is a discriminated union — even after
narrowing on `mode === "form"`, both `ElicitationRequestScope` (no
`sessionId`) and `ElicitationSessionScope` (with `sessionId`)
remain in the union. The new live-getter regression test was reading
`calls[N]!.sessionId` directly, which CI tsgo rejected with TS2339.
Per-element `if (!call || call.mode !== "form" || !("sessionId"
in call))` narrows to the session-scoped variant. Spelled three times
because loop-style narrows don't propagate to the assertions below.
Matches the discriminator pattern used in the older 'translates select'
test at line ~927.
Co-Authored-By: omp <noreply@oh-my-pi.dev>
`biome check` enforces print-width on the two test-only call-sites that
`ast_edit` collapsed onto a single line during the sessionId-getter
rewrite. Auto-formatter wrap, no behavior change.
Co-Authored-By: omp <noreply@oh-my-pi.dev>
`AgentSession.sessionId` is a getter that reads through to
`sessionManager.getSessionId()` and mutates when an extension command
calls `ctx.newSession` or `ctx.switchSession` (both exposed in the
same #configureExtensions block). Snapshotting the id once at factory
time routed later elicitations to the pre-switch id — diverging from
every other sessionUpdate call in this file, which already reads
record.session.sessionId live.
createAcpExtensionUiContext now takes `getSessionId: () => string` and
calls it per elicitation. Caller passes `() => record.session.sessionId`
so each select / confirm / input picks up the current id.
Also simplifies elicitFromAcpClient: `onAbort` and `finish` had
identical settlement bodies differing only by the resolve value, with a
hand-rolled `removeEventListener` symmetry comment to keep them in
sync. Collapsed to a single settle path — `onAbort = () =>
finish(undefined)` — so future changes to settlement apply to both
paths automatically. Doc-comment tightened to call out that late SDK
`accept` responses (not just rejections) after abort/timeout are also
dropped silently.
New regression test asserts that mutating the captured sessionId
between elicitations is reflected in the next request.
Co-Authored-By: omp <noreply@oh-my-pi.dev>
OpenCode-Go and OpenCode-Zen handle reasoning content internally
and reject client-supplied reasoning_content in message history.
When retry fallback forwards conversation history to
opencode-go/kimi-k2.6, the compat layer was injecting synthetic
reasoning_content: '.' on assistant tool-call turns, causing
HTTP 400: 'Extra inputs are not permitted'.
Gate isKimiModel in requiresReasoningContentForToolCalls on
!isOpenCodeProvider so the injection path is skipped for
OpenCode providers while preserving existing behavior for
native Kimi API, DeepSeek, and OpenRouter.