@oh-my-pi/pi-coding-agent 15.9.67 → 15.10.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +136 -0
- package/dist/types/cli/args.d.ts +1 -1
- package/dist/types/cli/dry-balance-cli.d.ts +15 -1
- package/dist/types/cli/gallery-cli.d.ts +43 -0
- package/dist/types/cli/gallery-fixtures/agentic.d.ts +2 -0
- package/dist/types/cli/gallery-fixtures/codeintel.d.ts +3 -0
- package/dist/types/cli/gallery-fixtures/edit.d.ts +3 -0
- package/dist/types/cli/gallery-fixtures/fs.d.ts +2 -0
- package/dist/types/cli/gallery-fixtures/index.d.ts +4 -0
- package/dist/types/cli/gallery-fixtures/interaction.d.ts +3 -0
- package/dist/types/cli/gallery-fixtures/memory.d.ts +2 -0
- package/dist/types/cli/gallery-fixtures/misc.d.ts +3 -0
- package/dist/types/cli/gallery-fixtures/search.d.ts +3 -0
- package/dist/types/cli/gallery-fixtures/shell.d.ts +3 -0
- package/dist/types/cli/gallery-fixtures/types.d.ts +44 -0
- package/dist/types/cli/gallery-fixtures/web.d.ts +2 -0
- package/dist/types/cli/gallery-screenshot.d.ts +35 -0
- package/dist/types/commands/gallery.d.ts +47 -0
- package/dist/types/commit/analysis/conventional.d.ts +2 -2
- package/dist/types/commit/analysis/summary.d.ts +2 -2
- package/dist/types/commit/changelog/generate.d.ts +2 -2
- package/dist/types/commit/changelog/index.d.ts +2 -2
- package/dist/types/commit/map-reduce/index.d.ts +3 -3
- package/dist/types/commit/map-reduce/map-phase.d.ts +2 -2
- package/dist/types/commit/map-reduce/reduce-phase.d.ts +2 -2
- package/dist/types/commit/model-selection.d.ts +10 -4
- package/dist/types/config/api-key-resolver.d.ts +34 -0
- package/dist/types/config/keybindings.d.ts +6 -1
- package/dist/types/config/model-id-affixes.d.ts +2 -0
- package/dist/types/config/model-registry.d.ts +25 -2
- package/dist/types/config/settings-schema.d.ts +41 -6
- package/dist/types/dap/config.d.ts +14 -1
- package/dist/types/dap/types.d.ts +10 -0
- package/dist/types/extensibility/plugins/marketplace-auto-update.d.ts +8 -0
- package/dist/types/lsp/types.d.ts +10 -0
- package/dist/types/lsp/utils.d.ts +3 -2
- package/dist/types/main.d.ts +3 -2
- package/dist/types/memory-backend/index.d.ts +2 -1
- package/dist/types/memory-backend/resolve.d.ts +1 -1
- package/dist/types/memory-backend/types.d.ts +1 -1
- package/dist/types/modes/components/chat-block.d.ts +64 -0
- package/dist/types/modes/components/custom-editor.d.ts +5 -1
- package/dist/types/modes/components/overlay-box.d.ts +17 -0
- package/dist/types/modes/components/plan-review-overlay.d.ts +59 -0
- package/dist/types/modes/components/plan-toc.d.ts +41 -0
- package/dist/types/modes/components/read-tool-group.d.ts +2 -0
- package/dist/types/modes/components/tool-execution.d.ts +18 -0
- package/dist/types/modes/components/transcript-container.d.ts +11 -0
- package/dist/types/modes/controllers/command-controller.d.ts +1 -0
- package/dist/types/modes/controllers/event-controller.d.ts +0 -1
- package/dist/types/modes/controllers/extension-ui-controller.d.ts +0 -1
- package/dist/types/modes/controllers/input-controller.d.ts +1 -1
- package/dist/types/modes/controllers/selector-controller.d.ts +1 -1
- package/dist/types/modes/controllers/streaming-reveal.d.ts +22 -0
- package/dist/types/modes/controllers/tan-command-controller.d.ts +6 -0
- package/dist/types/modes/index.d.ts +5 -4
- package/dist/types/modes/interactive-mode.d.ts +16 -6
- package/dist/types/modes/setup-version.d.ts +11 -0
- package/dist/types/modes/setup-wizard/index.d.ts +2 -1
- package/dist/types/modes/setup-wizard/scenes/web-search.d.ts +2 -1
- package/dist/types/modes/theme/theme.d.ts +1 -1
- package/dist/types/modes/types.d.ts +19 -6
- package/dist/types/modes/utils/copy-targets.d.ts +21 -1
- package/dist/types/plan-mode/approved-plan.d.ts +27 -8
- package/dist/types/plan-mode/plan-protection.d.ts +4 -4
- package/dist/types/sdk.d.ts +3 -1
- package/dist/types/session/agent-session.d.ts +21 -0
- package/dist/types/session/messages.d.ts +12 -0
- package/dist/types/session/session-manager.d.ts +3 -1
- package/dist/types/slash-commands/types.d.ts +4 -6
- package/dist/types/task/executor.d.ts +14 -0
- package/dist/types/task/index.d.ts +1 -0
- package/dist/types/task/render.d.ts +3 -2
- package/dist/types/telemetry-export.d.ts +1 -1
- package/dist/types/tools/archive-reader.d.ts +5 -0
- package/dist/types/tools/ast-edit.d.ts +3 -0
- package/dist/types/tools/ast-grep.d.ts +3 -0
- package/dist/types/tools/bash.d.ts +1 -0
- package/dist/types/tools/eval-render.d.ts +1 -8
- package/dist/types/tools/fetch.d.ts +15 -7
- package/dist/types/tools/find.d.ts +8 -4
- package/dist/types/tools/grouped-file-output.d.ts +95 -12
- package/dist/types/tools/memory-render.d.ts +4 -1
- package/dist/types/tools/plan-mode-guard.d.ts +8 -9
- package/dist/types/tools/render-utils.d.ts +13 -9
- package/dist/types/tools/renderers.d.ts +16 -2
- package/dist/types/tools/search.d.ts +5 -1
- package/dist/types/tools/sqlite-reader.d.ts +1 -0
- package/dist/types/tools/todo.d.ts +3 -2
- package/dist/types/tools/write.d.ts +5 -0
- package/dist/types/tui/output-block.d.ts +16 -4
- package/dist/types/tui/status-line.d.ts +3 -0
- package/dist/types/utils/enhanced-paste.d.ts +20 -0
- package/dist/types/web/scrapers/github.d.ts +22 -0
- package/dist/types/web/search/providers/kimi.d.ts +1 -1
- package/dist/types/web/search/providers/perplexity.d.ts +8 -1
- package/dist/types/web/search/types.d.ts +1 -1
- package/package.json +9 -9
- package/scripts/dev-launch +42 -0
- package/scripts/dev-launch-preload.ts +19 -0
- package/src/auto-thinking/classifier.ts +5 -1
- package/src/cli/args.ts +2 -2
- package/src/cli/dry-balance-cli.ts +52 -17
- package/src/cli/gallery-cli.ts +226 -0
- package/src/cli/gallery-fixtures/agentic.ts +292 -0
- package/src/cli/gallery-fixtures/codeintel.ts +188 -0
- package/src/cli/gallery-fixtures/edit.ts +194 -0
- package/src/cli/gallery-fixtures/fs.ts +153 -0
- package/src/cli/gallery-fixtures/index.ts +40 -0
- package/src/cli/gallery-fixtures/interaction.ts +49 -0
- package/src/cli/gallery-fixtures/memory.ts +81 -0
- package/src/cli/gallery-fixtures/misc.ts +250 -0
- package/src/cli/gallery-fixtures/search.ts +213 -0
- package/src/cli/gallery-fixtures/shell.ts +167 -0
- package/src/cli/gallery-fixtures/types.ts +41 -0
- package/src/cli/gallery-fixtures/web.ts +158 -0
- package/src/cli/gallery-screenshot.ts +279 -0
- package/src/cli-commands.ts +1 -0
- package/src/commands/gallery.ts +52 -0
- package/src/commands/launch.ts +1 -1
- package/src/commit/analysis/conventional.ts +2 -2
- package/src/commit/analysis/summary.ts +2 -2
- package/src/commit/changelog/generate.ts +2 -2
- package/src/commit/changelog/index.ts +2 -2
- package/src/commit/map-reduce/index.ts +3 -3
- package/src/commit/map-reduce/map-phase.ts +2 -2
- package/src/commit/map-reduce/reduce-phase.ts +2 -2
- package/src/commit/model-selection.ts +33 -9
- package/src/commit/pipeline.ts +4 -4
- package/src/config/api-key-resolver.ts +58 -0
- package/src/config/keybindings.ts +15 -6
- package/src/config/model-equivalence.ts +35 -12
- package/src/config/model-id-affixes.ts +39 -22
- package/src/config/model-registry.ts +41 -18
- package/src/config/settings-schema.ts +28 -5
- package/src/config/settings.ts +31 -2
- package/src/dap/client.ts +14 -16
- package/src/dap/config.ts +41 -2
- package/src/dap/defaults.json +1 -0
- package/src/dap/session.ts +1 -0
- package/src/dap/types.ts +10 -0
- package/src/debug/index.ts +40 -54
- package/src/edit/renderer.ts +111 -119
- package/src/eval/__tests__/agent-bridge.test.ts +75 -32
- package/src/eval/__tests__/llm-bridge.test.ts +90 -31
- package/src/eval/agent-bridge.ts +34 -7
- package/src/eval/llm-bridge.ts +8 -3
- package/src/extensibility/extensions/runner.ts +1 -0
- package/src/extensibility/plugins/doctor.ts +0 -1
- package/src/extensibility/plugins/marketplace-auto-update.ts +49 -0
- package/src/goals/tools/goal-tool.ts +37 -27
- package/src/internal-urls/docs-index.generated.ts +10 -10
- package/src/lsp/client.ts +104 -55
- package/src/lsp/types.ts +10 -0
- package/src/lsp/utils.ts +3 -2
- package/src/main.ts +53 -56
- package/src/memories/index.ts +12 -5
- package/src/memory-backend/index.ts +13 -1
- package/src/memory-backend/resolve.ts +3 -5
- package/src/memory-backend/types.ts +1 -1
- package/src/mnemopi/backend.ts +5 -1
- package/src/modes/acp/acp-agent.ts +33 -26
- package/src/modes/components/assistant-message.ts +2 -9
- package/src/modes/components/chat-block.ts +111 -0
- package/src/modes/components/copy-selector.ts +1 -44
- package/src/modes/components/custom-editor.ts +33 -1
- package/src/modes/components/custom-message.ts +1 -3
- package/src/modes/components/execution-shared.ts +1 -2
- package/src/modes/components/hook-message.ts +1 -3
- package/src/modes/components/overlay-box.ts +108 -0
- package/src/modes/components/plan-review-overlay.ts +799 -0
- package/src/modes/components/plan-toc.ts +138 -0
- package/src/modes/components/read-tool-group.ts +20 -4
- package/src/modes/components/skill-message.ts +0 -1
- package/src/modes/components/status-line.ts +3 -5
- package/src/modes/components/tips.txt +1 -0
- package/src/modes/components/todo-reminder.ts +0 -2
- package/src/modes/components/tool-execution.ts +115 -90
- package/src/modes/components/transcript-container.ts +84 -24
- package/src/modes/components/user-message.ts +1 -2
- package/src/modes/controllers/command-controller-shared.ts +7 -6
- package/src/modes/controllers/command-controller.ts +70 -57
- package/src/modes/controllers/event-controller.ts +41 -40
- package/src/modes/controllers/extension-ui-controller.ts +10 -73
- package/src/modes/controllers/input-controller.ts +135 -122
- package/src/modes/controllers/mcp-command-controller.ts +69 -60
- package/src/modes/controllers/selector-controller.ts +25 -27
- package/src/modes/controllers/streaming-reveal.ts +212 -0
- package/src/modes/controllers/tan-command-controller.ts +173 -0
- package/src/modes/index.ts +5 -4
- package/src/modes/interactive-mode.ts +171 -82
- package/src/modes/setup-version.ts +11 -0
- package/src/modes/setup-wizard/index.ts +3 -2
- package/src/modes/setup-wizard/scenes/web-search.ts +3 -2
- package/src/modes/setup-wizard/wizard-overlay.ts +1 -1
- package/src/modes/theme/theme-schema.json +1 -1
- package/src/modes/theme/theme.ts +8 -4
- package/src/modes/types.ts +19 -8
- package/src/modes/utils/context-usage.ts +10 -6
- package/src/modes/utils/copy-targets.ts +133 -27
- package/src/modes/utils/hotkeys-markdown.ts +1 -0
- package/src/modes/utils/ui-helpers.ts +44 -46
- package/src/plan-mode/approved-plan.ts +66 -43
- package/src/plan-mode/plan-protection.ts +4 -4
- package/src/prompts/system/background-tan-dispatch.md +8 -0
- package/src/prompts/system/plan-mode-active.md +67 -58
- package/src/prompts/system/plan-mode-approved.md +1 -1
- package/src/sdk.ts +32 -60
- package/src/session/agent-session.ts +89 -13
- package/src/session/messages.ts +26 -0
- package/src/session/session-manager.ts +13 -5
- package/src/slash-commands/builtin-registry.ts +37 -10
- package/src/slash-commands/helpers/usage-report.ts +2 -0
- package/src/slash-commands/types.ts +4 -6
- package/src/task/executor.ts +25 -4
- package/src/task/index.ts +4 -0
- package/src/task/render.ts +212 -148
- package/src/telemetry-export.ts +25 -7
- package/src/tools/archive-reader.ts +64 -0
- package/src/tools/ask.ts +119 -164
- package/src/tools/ast-edit.ts +98 -71
- package/src/tools/ast-grep.ts +37 -43
- package/src/tools/bash.ts +50 -6
- package/src/tools/debug.ts +20 -8
- package/src/tools/eval-backends.ts +6 -17
- package/src/tools/eval-render.ts +21 -18
- package/src/tools/eval.ts +5 -4
- package/src/tools/fetch.ts +391 -91
- package/src/tools/find.ts +44 -30
- package/src/tools/gh-renderer.ts +81 -42
- package/src/tools/grouped-file-output.ts +272 -48
- package/src/tools/image-gen.ts +150 -103
- package/src/tools/inspect-image-renderer.ts +63 -41
- package/src/tools/inspect-image.ts +8 -1
- package/src/tools/job.ts +3 -4
- package/src/tools/memory-render.ts +4 -1
- package/src/tools/plan-mode-guard.ts +21 -39
- package/src/tools/read.ts +23 -16
- package/src/tools/render-utils.ts +38 -40
- package/src/tools/renderers.ts +16 -1
- package/src/tools/report-tool-issue.ts +1 -1
- package/src/tools/resolve.ts +14 -0
- package/src/tools/search-tool-bm25.ts +36 -23
- package/src/tools/search.ts +189 -95
- package/src/tools/sqlite-reader.ts +9 -12
- package/src/tools/todo.ts +138 -59
- package/src/tools/write.ts +100 -60
- package/src/tui/output-block.ts +60 -13
- package/src/tui/status-line.ts +5 -1
- package/src/utils/commit-message-generator.ts +9 -1
- package/src/utils/enhanced-paste.ts +202 -0
- package/src/utils/title-generator.ts +2 -1
- package/src/web/scrapers/github.ts +255 -3
- package/src/web/scrapers/youtube.ts +3 -2
- package/src/web/search/providers/anthropic.ts +25 -19
- package/src/web/search/providers/exa.ts +11 -3
- package/src/web/search/providers/kimi.ts +28 -17
- package/src/web/search/providers/parallel.ts +35 -24
- package/src/web/search/providers/perplexity.ts +199 -51
- package/src/web/search/providers/synthetic.ts +8 -6
- package/src/web/search/providers/tavily.ts +9 -8
- package/src/web/search/providers/zai.ts +8 -6
- package/src/web/search/render.ts +39 -54
- package/src/web/search/types.ts +5 -1
- package/dist/types/eval/__tests__/shared-executors.test.d.ts +0 -1
- package/src/eval/__tests__/shared-executors.test.ts +0 -609
package/CHANGELOG.md
CHANGED
|
@@ -2,7 +2,143 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [15.10.1] - 2026-06-07
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
- Added `display.smoothStreaming` setting (default `true`) to let users enable or disable smooth assistant-stream text reveal
|
|
10
|
+
- Added `/tan <work>` slash command to fork the current conversation into a background agent so tangential work can continue asynchronously while your main session stays active
|
|
11
|
+
- Added a background `/tan` dispatch message that records the handoff in the transcript and marks the delegated work as non-blocking
|
|
12
|
+
- Added `providerPromptCacheKey` support to `CreateAgentSessionOptions` so `/tan` background sessions can reuse the parent session’s prompt-cache lineage
|
|
13
|
+
- Added session cloning for `/tan` runs with copied artifacts and shared MCP proxy tools
|
|
14
|
+
- Added `SessionManager.forkFrom`’s optional `suppressBreadcrumb` mode to avoid breadcrumb updates when forking background `/tan` sessions
|
|
15
|
+
- Added OSC 5522 enhanced paste handling in `InputController`, so terminal clipboard events are decoded as image or text payloads and inserted without passing raw paste sequences to the editor
|
|
16
|
+
- Added bracketed image-path paste support in `CustomEditor` so a single pasted image file path (PNG/JPEG/GIF/WEBP) is loaded from disk and inserted as an image candidate
|
|
17
|
+
- Added direct support for `Image #N` insertion from pasted local image paths by routing successful image-path pastes through the same image normalization and resize flow as clipboard image pastes
|
|
18
|
+
- Added `/fresh` to rotate the provider-facing session id and clear in-memory provider stream/cache state without changing the local session file.
|
|
19
|
+
- Added a `ChatBlock` transcript primitive (`modes/components/chat-block.ts`) and a single `ctx.present(...)` sink (with `ctx.resetTranscript()`) so chat output is mounted in one place instead of the repeated `chatContainer.addChild(...)` + `ui.requestRender()` pattern scattered across controllers. `ChatBlock` carries a React/Svelte-style lifecycle — `onMount` starts effects, `onCleanup` registers teardown, `finish()` self-completes (stops timers and freezes the block at its final content), and `dispose()`/`resetTranscript()` tears everything down — so animated blocks own their own resources instead of leaking `setInterval`/`requestRender` bookkeeping into callers. The MCP "Connecting…" spinner is now such a block.
|
|
20
|
+
- Added a `framedBlock` output-block helper (`tui/output-block.ts`) plus a `borderColor` override and `applyBg: false` (no background fill) on output blocks, a `renderStatusLine` `iconOverride`, and an `icon.search` (magnifier) theme symbol — so tool renderers can draw self-contained muted-outline frames and search-family tools can show a magnifier instead of a checkmark.
|
|
21
|
+
|
|
22
|
+
### Changed
|
|
23
|
+
|
|
24
|
+
- Changed the bash tool frame to use a plain top rule instead of repeating "Bash" in the title bar, and folded minimizer raw-output artifact links into the status footer as `Artifact: <id>`.
|
|
25
|
+
|
|
26
|
+
- Changed grouped `read` output to use a white filled-circle mark for the group/single-read success state and omit duplicate per-file success marks inside multi-read groups.
|
|
27
|
+
|
|
28
|
+
- Changed assistant streaming output to reveal text incrementally at 30 FPS with grapheme-safe adaptive catch-up, instead of replacing the whole message chunk-by-chunk
|
|
29
|
+
- Changed shimmer-driven TUI animations (working text, pending bash/eval borders, and theme activity-spinner documentation) to render at 30fps instead of 60fps.
|
|
30
|
+
- Changed running `task` tool agent rows to use a static `•` marker and shimmer only the subagent name, leaving descriptions, stats, and nested tool detail text solid while removing the rotating status glyph from those rows.
|
|
31
|
+
- Changed settings singleton method access to reuse bound methods for the active instance instead of allocating a new bound function on every `settings.get` lookup.
|
|
32
|
+
- Changed plan-mode approval to keep the drafted `local://<slug>-plan.md` file at its original name as the canonical plan path, so approved plans are no longer renamed when leaving plan mode
|
|
33
|
+
- Changed plan-mode write enforcement so only `local://` artifact files are writable during planning, blocking working-tree edits and allowing scratch or draft plan files in the local artifact area
|
|
34
|
+
- Changed the `todo` tool result renderer to stop redrawing every phase's full task list on each update: when a multi-phase list is rendered collapsed (the default, not manually expanded), only phases the latest update touched — the phase holding the in_progress task, any phase with a just-completed task, and phases named by the ops that ran (`init` counts as touching all) — render their tasks; untouched phases collapse to a one-line `N. Name done/total` summary. When call args are unavailable (e.g. transcript rebuilds) it falls back to the in_progress/completed-transition signals, and the manual expand toggle still shows every task. Also dropped the blank separator line previously inserted between phases.
|
|
35
|
+
- Changed non-agent API operations (title and commit-message generation, image generation, web search, eval `llm()`, auto-thinking classifier, memory consolidation) to use session-aware API key resolution with auth retries via `registry.resolver()` / `authStorage.resolver()`, refreshing the active credential before rotating to another account
|
|
36
|
+
- Changed image generation to wrap every provider fetch branch in `withAuth`, so 401 / usage-limit errors trigger credential force-refresh and rotation for authStorage-backed providers (OpenAI-hosted, antigravity, xai-oauth) while env-only providers (openrouter, gemini) stay single-attempt
|
|
37
|
+
- Changed web-search providers using `authStorage.getApiKey` (anthropic, exa, tavily, parallel, synthetic, zai, kimi) to wrap HTTP calls in `withAuth` for automatic credential rotation on 401 / usage-limit errors
|
|
38
|
+
- Changed the directory grouping for `find`, `search`, `ast_grep`, `ast_edit`, and `lsp` diagnostics from a single flat `# dir/` heading per immediate directory to a multi-level tree that folds the common path prefix into one heading. Previously every group repeated the full directory path — so results rooted outside cwd printed the absolute prefix (e.g. `/Users/me/proj/`) on every heading and nested directories were never collapsed. Now a single-child directory chain folds into one heading (`# packages/pkg/src/`, including an absolute root for out-of-cwd results), subdirectories nest one `#` deeper (`## nested/` → `### child.ts`), and each directory's own files are listed before its subdirectories. TUI hyperlink reconstruction tracks the nested directory stack across the whole output so file and code-frame links keep resolving to the correct absolute paths.
|
|
39
|
+
- Changed the plan-mode approval surface from an inline transcript block plus a separate bottom selector into a single fullscreen overlay (like `/copy`) and overhauled its navigation. The overlay now renders the plan per-section through `ScrollView` (line-level ↑/↓ scroll, Shift+↑/↓ to scroll faster, PgUp/PgDn, g/G) with no stray per-line `…`, and — when the terminal is wide enough and the plan has ≥2 headings — shows a compact VS Code-style section sidebar (the redundant plan-title heading and any "Contents" label are omitted). Focus moves between regions with Tab/Shift+Tab (and flows at the edges: Down past the last section or the bottom of the body drops into the approval options; Up steps back), while the sidebar glows to track the scrolled section. The sidebar can fast-jump between sections, delete a section (with `u` undo), and annotate sections with feedback (`a`); deletions and annotations are collected into refinement feedback that is submitted back to the model when the operator picks "Refine plan". Mouse works too: clicking an approval option activates it, clicking a sidebar section jumps to it, and the wheel scrolls the plan. ←/→ always drive the model-tier slider, Enter confirms, the external-editor key opens the plan, and Esc cancels. The overlay borrows the terminal's alternate screen buffer for its lifetime (`fullscreen` overlay), so the transcript stays put on the normal screen instead of bleeding through scrollback behind the modal.
|
|
40
|
+
- Changed the interactive controllers (command, MCP, selector, extension-UI, event), debug panels, and the status/error/warning helpers to render chat output through `ctx.present(...)` instead of appending to `chatContainer` and calling `ui.requestRender()` directly; transcript rebuilds dispose live blocks via `ctx.resetTranscript()` so animated blocks' timers stop on reset.
|
|
41
|
+
- Changed tool-execution block rendering so the container (`ToolExecutionComponent`) is a transparent passthrough — it no longer inserts a top/bottom blank line, adds left/right padding, or paints a state-colored background behind tool output. Tools with substantial body now self-frame with a muted outline and the tool title in the frame's top bar (`edit`/`apply_patch`, `write`, `ask`, `todo`, `github`, `goal`, `inspect_image`, `search_tool_bm25`, `task`), matching the already-framed `bash`/`read`/`eval`/`debug`/`web_search`/`lsp` blocks, while streaming/in-progress and trivial results collapse to a clean status line. The search-family list tools (`find`, `search`, `ast_grep`) and `job` render frameless/minimal; `find`/`search`/`ast_grep` show a magnifier on success instead of a checkmark, and `job` drops its `Job:` label prefix (the per-job rows are self-describing). The `search_tool_bm25`, `github`, and `inspect_image` frames draw with no background fill, and `inspect_image`'s label was shortened to `Inspect`.
|
|
42
|
+
- Changed the plan-mode active prompt (`prompts/system/plan-mode-active.md`) to make plans decision-complete and cut filler. Added an Objective framing ("another engineer can execute end-to-end without making a single design decision"), a shared "Resolving Unknowns" section (explore discoverable facts before asking; reserve `ask` for non-derivable preferences/tradeoffs with 2–4 options + a recommended default), and a single shared "The Plan" structure (Context / Approach grouped by behavior not file-by-file / ≤5 Critical files / Verification / Assumptions) that replaces the per-branch structure guidance previously duplicated across the iterative and parallel workflows. Added explicit prohibitions on sections that decide nothing (Non-Goals, Out of Scope, Alternatives Considered, Risks/Mitigations boilerplate, Future Work), on enumerating every file/line, and on inventing schema/validation/precedence policy the request never established.
|
|
43
|
+
- Changed completion notifications (`completion.notify`) to fire whenever the agent yields its turn, including in the foreground. The `agent_end` notification was previously gated behind background mode (`isBackgrounded`), so an ordinary foreground turn never emitted one; the gate is gone and the desktop toast now fires on every normal turn completion (still skipped for aborted/error turns and when `completion.notify` is `off`).
|
|
44
|
+
- Changed the in-progress `task` tool block to keep the shared `context` brief (`# Goal` / `# Constraints` background) visible after the first progress snapshot arrives, instead of dropping it the moment the streaming call view was replaced by the result frame, and to stop animating a spinner/clock next to the `Task` frame header while running — the per-agent body lines already carry their own running spinner, so the header now shows a static state icon (matching the completed/failed header icons). The context is rendered through a shared `buildContextSection` helper that also undoes per-field double-encoding, so the brief reads cleanly in the result frame even though `renderResult` receives the raw (un-repaired) tool args.
|
|
45
|
+
- Changed the messaging shown when you press Esc to interrupt a streaming turn from the ambiguous `Operation aborted` / `Tool execution was aborted: Request was aborted` to `Interrupted by user`, so a deliberate user interrupt no longer reads like an internal failure. Every Esc/flush interrupt path (`onEscape` while streaming, the queued-message restore-and-abort path, and the empty-submit queue flush) threads the reason through `AgentSession.abort({ reason })` → `Agent.abort(reason)` so it rides the `AbortController` onto the aborted assistant message's `errorMessage`; the turn label renders it verbatim on both the live and replay paths, and the synthetic placeholder results paired with in-flight tool calls now read `Tool execution was aborted: Interrupted by user`. Aborts that carry no reason still fall back to the retry-aware `Operation aborted` generic. Transcript label resolution is centralized in `resolveAbortLabel` (`session/messages.ts`).
|
|
46
|
+
|
|
47
|
+
### Removed
|
|
48
|
+
|
|
49
|
+
- Removed the `/background` (and `/bg`) slash command and the background-mode subsystem it was the sole entry point for — `InteractiveMode.isBackgrounded`, `createBackgroundUiContext`, `handleBackgroundEvent`, and every `isBackgrounded` guard across the input/event/extension-UI controllers and UI helpers. The command suspended the whole process group via `SIGTSTP` (a leftover testing shortcut) instead of detaching the running agent, which is not the expected workflow — use terminal panes or a multiplexer instead.
|
|
50
|
+
|
|
51
|
+
### Fixed
|
|
52
|
+
|
|
53
|
+
- Fixed inline `find` and `search` result blocks to align with grouped `read` output and render their success headers with the normal tool-title color instead of accent blue.
|
|
54
|
+
|
|
55
|
+
- Fixed the working-status shimmer to opt into the loader's 30fps animated-message repaint path while keeping both the status spinner and pending bash/eval tool spinners on their normal 80 ms glyph cadence.
|
|
56
|
+
- Fixed consecutive `read` tool calls failing to collapse into a single grouped block when a reasoning model emits one read per completion (`[thinking, read]`). The read group was reset on every assistant `message_start`, so each read rendered as its own one-entry `Read …` line; now a read run accretes across completions and is broken only by a rendered non-empty text/thinking block, a non-read tool, or a user/IRC message — matching the transcript-rebuild path. `ReadToolGroupComponent` now reports its live/finalized state so the growing `Read (N)` header repaints correctly on native-scrollback (risk) terminals.
|
|
57
|
+
- Fixed the `task` tool shared-context brief rendering raw Markdown headings (`# Goal`, `# Constraints`) inside framed call/result blocks instead of using the normal Markdown renderer.
|
|
58
|
+
- Fixed the animated pending border on `bash`/`eval` blocks leaving a frozen dark "bar" segment behind after a backgrounded command finalized through the async update path. Once a command is auto-backgrounded (`details.async.state === "running"`) the block stays "partial" in the TUI until the async job-manager delivers the final result, but it also gets committed to native scrollback — so a mid-sweep shimmer frame baked a stray darkened border segment into the committed copy. The border now stops animating (and the 60fps redraw loop stops) the moment a block enters the backgrounded state, so the committed frame is a clean static border.
|
|
59
|
+
- Fixed cold `omp` launch to clear native terminal history on the first paint, avoiding a once-per-launch duplicate welcome/transcript copy before the normal session replay.
|
|
60
|
+
- Fixed plan approval resolution so `resolve` with `action: "apply"` can still find the plan file when `extra.title` is missing or stale by falling back to the current plan path and most-recent local plan artifacts
|
|
61
|
+
- Fixed the search-family tool magnifier glyph (`find`, `search`, `ast_grep`, `search_tool_bm25`) to use the `accent` title color instead of `success` green, so the icon matches the tool title in the status header instead of standing out
|
|
62
|
+
- Fixed TTSR stream interrupts to pass the matched rule name through the abort reason, so aborted in-flight tool placeholders say why they were stopped instead of `Request was aborted`.
|
|
63
|
+
- Fixed URL reads for binary/special payloads to reuse local readers: remote archives list their root entries, SQLite databases show their table overview, notebooks render as editable cells, and unrenderable binary returns a metadata notice instead of decoded byte garbage.
|
|
64
|
+
- Fixed pasted image-file paths that cannot be loaded to fall back to normal text paste with status feedback instead of disappearing.
|
|
65
|
+
- Fixed tool-output file paths not being clickable OSC 8 `file://` hyperlinks in several renderers. `read` titles for plain text and image files (the common case) emitted no link at all because the renderer only linked when a `resolvedPath` was recorded — which the ordinary file/image read paths never set, keeping the absolute path only in `meta.source`; the renderer now falls back to that source path. `write` headers were never wrapped in a hyperlink and now link to the absolute path written (file, archive entry, SQLite, and conflict resolutions). `edit`/`apply_patch` headers wrapped the model-supplied (often cwd-relative) argument path, producing a root-anchored `file:///rel/path` URI; they now link the absolute `details.path` instead. Finally, `search`, `ast_grep`, and `ast_edit` produced doubled link targets (`/proj/src/src/file.ts`) for searches scoped to a subdirectory, because the renderer resolved the cwd-relative display paths against the scope directory rather than cwd — the scoped-search base is now the session cwd (with the scoped file's absolute path still seeding single-file body lines).
|
|
66
|
+
- Fixed `omp dry-balance --bench` to recover from 401 token failures by re-minting the failing OAuth credential in place before switching accounts
|
|
67
|
+
- Fixed the bash tool corrupting commands that embed multi-byte UTF-8 (e.g. `✓`/`×` inside a `grep -E` pattern) ahead of a trailing `| head`/`| tail`. The `bash.stripTrailingHeadTail` rewrite cut at char-offset positions reported by `brush-parser` while slicing the command by byte offset, so the trailing-pipe strip landed mid-pattern and dropped the closing quote — turning `… |✓|×|XCTAssert" | tail -80` into `… |✓|×-80` and making execution fail with `pi-natives:command: unterminated double quote`. Fixed in `pi_shell::fixup` (`@oh-my-pi/pi-natives`).
|
|
68
|
+
- Fixed `omp dry-balance --bench` to recover from 401 token failures by re-minting the failing OAuth credential in place before switching accounts
|
|
69
|
+
- Fixed duplicate file entries in grouped outputs for `find`, `search`, `ast_grep`, `ast_edit`, and `lsp` diagnostics when the same path appeared multiple times
|
|
70
|
+
- Fixed search, grep, and edit output rendering so repeated directory group blank-line boundaries no longer break nested path/link reconstruction
|
|
71
|
+
- Fixed `omp dry-balance --bench` flooding the terminal with staircased, duplicated spinner/status lines (and an indented summary) when the tty has ONLCR/OPOST disabled (raw mode). The interactive progress region separated rows with a bare LF and repositioned with a column-preserving `\x1b[<n>A` cursor-up, both of which only land at column 0 when the terminal translates LF→CRLF; with that translation off, every 80 ms redraw cascaded down and to the right into scrollback. The live region now carriage-returns before every cleared row, terminates each row with CRLF, and caps each row to the terminal width so a wrapped line cannot desync the cursor-up from the logical line count.
|
|
72
|
+
- Fixed inconsistent vertical spacing between transcript blocks: some blocks (tool results from `search`/`find` and other renderer-backed tools) rendered with a doubled gap (a leading `Spacer` plus the content box's own `paddingY`), while others (the grouped `read` card, file-mention lists, IRC cards) rendered with no gap at all. Vertical spacing is now owned entirely by the chat renderer: `TranscriptContainer` strips each block's plain-blank top/bottom edges and inserts exactly one blank line between consecutive blocks, so every block is separated by a single consistent gap regardless of which component produced it. Individual components (assistant/user/tool/read-group/bash/eval/skill/custom/hook/compaction/branch/todo-reminder/plan-review messages) no longer emit their own leading `Spacer`/`paddingY` for separation, and multi-row groups (IRC cards, file-mention lists, completed-job batches, and the bordered command/`/changelog`/`/context`/version/OAuth/debug panels) are wrapped as single `TranscriptBlock` children so the renderer spaces them as one unit. Background-colored box padding is preserved as block-internal design.
|
|
73
|
+
- Fixed `resolve` with `action: "discard"` surfacing a hard `isError` "No pending action to resolve" failure to the model when the agent asked to cancel a staged action (e.g. an `ast_edit` preview) but nothing was pending. A discard is a request to reach the "no staged change" end-state, which already holds in that case, so it is now honored as a successful cancellation (`"Nothing to discard; no pending action remains."` with `details.action: "discard"`) instead of an error. `action: "apply"` with no pending action still errors.
|
|
74
|
+
- Fixed the collapsed tool-output expand hint rendering double brackets (e.g. `((Ctrl+O for more))`) — the `EXPAND_HINT` text already carried its own parentheses and then `formatExpandHint` wrapped it again with the theme's bracket glyphs. The hint now resolves the key actually bound to `app.tools.expand` at render time and reads `⟨<key>: Expand⟩` (e.g. `⟨Ctrl+O: Expand⟩`), so a single bracket pair surrounds it and a user remap of the expand keybinding is reflected instead of a hard-coded `Ctrl+O`.
|
|
75
|
+
- Fixed the `edit`/`apply_patch` tool dropping its outlined frame while streaming/in-progress (only the final result was framed); the in-progress diff preview now renders inside the same muted frame as the completed result.
|
|
76
|
+
- Fixed the `todo` and `job` tools rendering a success icon and success styling on a failed/error result; error results now show the error icon and a red frame border.
|
|
77
|
+
- Fixed `debug` tool refusing every `dlv` launch on Go modules. The launch handler ran `validateLaunchProgram` before adapter selection and rejected any directory program with `launch program resolves to a directory`, while dlv's default `mode=debug` requires a Go package path (a directory or `.go` source file). Adapter resolution now precedes validation, directory programs prefer adapters that advertise `acceptsDirectoryProgram` before falling back to native extensionless debuggers, the rejection only fires when the resolved adapter does not advertise that flag (set on `dlv` in `dap/defaults.json`), and dlv's `mode` is derived from the program shape — directories and `.go` files launch as `mode=debug`, other files as `mode=exec` — so `omp` can debug both Go packages and pre-built binaries ([#2020](https://github.com/can1357/oh-my-pi/issues/2020)).
|
|
78
|
+
|
|
79
|
+
## [15.10.0] - 2026-06-06
|
|
80
|
+
|
|
81
|
+
### Breaking Changes
|
|
82
|
+
|
|
83
|
+
- Replaced the `providers.parallelFetch` boolean setting with the `providers.fetch` enum (`auto` / `native` / `trafilatura` / `lynx` / `parallel` / `jina`) that selects the URL reader-backend priority for the `read`/`fetch` tool, mirroring `providers.image`/`providers.webSearch`. Existing configs are migrated automatically: the legacy key is dropped and the new `auto` default applies.
|
|
84
|
+
|
|
85
|
+
### Added
|
|
86
|
+
|
|
87
|
+
- Added a GitHub Actions read handler to the `read`/web-fetch GitHub scraper. Fetching `github.com/{owner}/{repo}/actions/runs/{id}` renders the run metadata plus a per-job breakdown (steps listed for any job that did not succeed), and `…/actions/runs/{id}/job/{id}` (also the API-style `…/jobs/{id}`) renders a single job's metadata, step table, and full plain-text logs. Logs are fetched via the `actions/jobs/{id}/logs` redirect using `GITHUB_TOKEN`/`GH_TOKEN` when present, with the per-line ISO timestamp prefix and leading BOM stripped; the section degrades to an explicit notice when logs are unavailable (no token, private repo, or expired/unfinalized run).
|
|
88
|
+
|
|
89
|
+
### Changed
|
|
90
|
+
|
|
91
|
+
- Changed eval `agent()` subagents so they are never subject to the `task.maxRuntimeMs` wall-clock cap. The parent cell's idle watchdog is already suspended for the entire bridge call (`withBridgeTimeoutPause`), so a long-running fan-out/recovery workflow must not be killed by a per-subagent runtime limit. `runEvalAgent` now passes `maxRuntimeMs: 0` to `runSubprocess`, which honors an explicit `ExecutorOptions.maxRuntimeMs` override over the inherited setting.
|
|
92
|
+
- Changed interactive timing behavior so `PI_TIMING=x pi` preloads the module timer before the CLI graph loads and includes the `(modules)` report. `PI_TIMING=full` now also exits after printing, matching `PI_TIMING=x`, so full module reports are usable for cold-start measurement without launching the TUI. Added the root `dev:timing` script for the same profiled startup path.
|
|
93
|
+
- Changed coding-agent startup imports so normal TUI launch imports `InteractiveMode` directly, keeps print/RPC/ACP runners on their branch-only paths, and moves marketplace auto-update work behind a lightweight deferred starter.
|
|
94
|
+
- Changed cold-launch setup gating so the full setup wizard (every scene plus the overlay and their TUI/OAuth/web-search/theme dependencies) is no longer statically imported by `main.ts`. The current setup version now lives in a tiny dependency-free `modes/setup-version` module, and the wizard barrel is lazy-loaded only when the stored setup version is stale or the wizard is forced — the common up-to-date launch skips loading it entirely.
|
|
95
|
+
- Changed cold-launch startup imports so the hot-path CLI files no longer pull the full `@oh-my-pi/pi-ai` barrel: `commands/launch.ts` and `cli/args.ts` import `THINKING_EFFORTS`/`Effort` from the tiny `@oh-my-pi/pi-ai/effort` module, and `config/model-registry.ts` now imports its ~20 symbols from narrow subpaths (`api-registry`, `model-cache`, `model-manager`, `model-thinking`, `models`, `provider-models`, `types`, `utils/event-stream`) instead of the barrel — so launching no longer eagerly loads every provider, auth, OAuth, and usage module re-exported by the barrel.
|
|
96
|
+
- Changed the `read`/`fetch` HTML reader-backend priority to `native > trafilatura > lynx > parallel > jina` (was `parallel > jina > trafilatura > lynx > native`). The in-process native `htmlToMarkdown` runs first — instant, no network, full-fidelity — so the common case no longer depends on a remote service, and a stalled remote backend can no longer mask it. Selecting a specific backend via `providers.fetch` tries it first, then the rest fall back. The low-quality gate (`>100` chars and not `isLowQualityOutput`) now applies uniformly to every backend; when none clears it, the highest-priority substantial-but-low-quality output is still surfaced so the `llms.txt` / document-extraction fallbacks keep running.
|
|
97
|
+
|
|
98
|
+
### Fixed
|
|
99
|
+
|
|
100
|
+
- Fixed eval `agent()` failures surfacing as an opaque `RuntimeError: bridge call '__agent__' failed` with no reason. When a subagent aborted, `runEvalAgent` built its failure message with `result.error ?? result.stderr ?? result.abortReason ?? …`, but `result.stderr` is the empty string on a clean abort (and `result.error` is gated on a non-empty `stderr`), so the nullish chain stopped at `""` and never reached `abortReason`. The empty string propagated through the loopback bridge and the Python prelude's `RuntimeError(msg or "bridge call … failed")`, discarding the real reason. The chain now uses `||` so an empty `stderr` falls through to `abortReason`.
|
|
101
|
+
- Fixed subagent aborts being mislabeled as the generic "Cancelled by caller" when the abort originated inside the subagent's own turn (`stopReason: "aborted"` with no caller signal and no runtime-limit timer). `runSubprocess` now prefers the aborted assistant message's `errorMessage` (e.g. "Request was aborted" or a specific stream error) for that case, while a real caller signal or wall-clock abort still reports its precise reason.
|
|
102
|
+
- Fixed a long streaming tool preview that alone overflows the viewport dropping its scrolled-off head on ED3-risk terminals (ghostty/kitty/iTerm2/…). When expanded with `Ctrl+O`, a streaming `write` (content streaming in) and a streaming `eval` (stdout streaming below its fixed code cell) render top-anchored and grow append-only, but the tool block never reported itself append-only to the transcript, so the renderer's commit-as-you-go boundary stopped at the block start and the earlier rows that scrolled above the viewport were committed nowhere — they vanished, leaving the preview looking like a viewport-tall circular buffer. `ToolExecutionComponent` now implements `isTranscriptBlockAppendOnly()` (gated on `isTranscriptBlockFinalized()`, so it also covers partial-result streams like `eval`), delegating to a renderer-declared `isStreamingPreviewAppendOnly` predicate so the expanded stream commits its head exactly like a streamed assistant reply. Collapsed previews (bounded sliding tail windows) and finalized/result previews (which can collapse to a capped view) stay deferred.
|
|
103
|
+
- Fixed `read`/`fetch` silently dropping whole list sections on pages with malformed list markup — stray `<img>`, text, or `<video>` nodes as direct children of `<ul>` (e.g. the Alacritty changelog). The Jina reader (previously tried before the local renderers) mis-extracts such lists, returning empty `Added`/`Changed` sections; the native in-process renderer now runs first and preserves the full content.
|
|
104
|
+
- Fixed `/usage` aggregate amount fallback using raw `limits.length` as account count — now counts unique `accountId` values from limit scopes, so N limits from a single account no longer display as "N accts".
|
|
105
|
+
- Fixed `/usage` account labeling falling back to "account N" for providers that use `projectId` as their primary identity (e.g. Google Antigravity, Gemini CLI) — `projectId` from report metadata is now considered before the generic fallback.
|
|
106
|
+
- Fixed the `todo` tool's TUI renderer crashing with `TypeError: args?.ops?.map is not a function` when a streaming tool-call delta surfaced a non-array `ops` field (mid-stream `parseStreamingJson` shapes like `{ ops: "[{" }`, or `[null]` entries before fields arrive). The renderer now treats non-array `ops`, non-object entries, and non-array `items` as missing structure instead of crashing, which also stops the spam-warn cascade that followed each malformed delta. Paired with the Anthropic-side reasoning-replay fix in `packages/ai` ([#2005](https://github.com/can1357/oh-my-pi/issues/2005)).
|
|
107
|
+
- Fixed Python eval `agent()` collapsing subagent runtime-limit aborts (and other empty-stderr aborts) into a generic `RuntimeError: bridge call '__agent__' failed`. `runEvalAgent` coalesced the failure message with `??`, which stopped at the empty `stderr` and never reached `abortReason`, shipping an empty error through the loopback bridge. The bridge now prefers `abortReason` for aborts and trims empty `stderr`/`error` out of the fallback chain, so Python surfaces the actionable reason (e.g. `Subagent runtime limit exceeded (task.maxRuntimeMs=900000)`) ([#2006](https://github.com/can1357/oh-my-pi/issues/2006)).
|
|
108
|
+
|
|
109
|
+
## [15.9.69] - 2026-06-06
|
|
110
|
+
|
|
111
|
+
### Added
|
|
112
|
+
|
|
113
|
+
- Added anonymous fallback for Perplexity web search, allowing `web_search` and explicit Perplexity provider usage when no Perplexity credentials are configured
|
|
114
|
+
- Added `gallery` CLI command to render built-in tool renderer output across streaming, in-progress, success, and failure states
|
|
115
|
+
- Added `omp gallery` filtering and rendering options (`--tool`, `--state`, `--width`, `--expanded`, and `--plain`) for focused renderer previews and plain-text output
|
|
116
|
+
- Added `omp gallery` fidelity for tools whose renderers are attached on the tool instance (`lsp`, `task`): the gallery now drives them through the same custom-tool render branch production uses, so regressions in that path surface in the gallery rather than only in a live session.
|
|
117
|
+
- Added `omp gallery --screenshot`, which renders the gallery through a real virtual terminal (VHS) and writes PNG screenshot(s) instead of ANSI, so agents (and anything that can only read raw bytes) can actually see the rendered output. The capture forces truecolor and matches the active theme/symbol preset; tall galleries split across multiple images (whole renderers are never cut). Tune with `--out`, `--font`, and `--font-size`; requires `vhs` on `PATH` and fails with install guidance when absent.
|
|
118
|
+
- Added `app.display.reset`, bound to `Ctrl+L` by default, to force an immediate terminal display reset/redraw without resizing the window.
|
|
119
|
+
|
|
120
|
+
### Changed
|
|
121
|
+
|
|
122
|
+
- Changed authenticated Perplexity ask requests to default to the `experimental` model preference, matching the anonymous fallback.
|
|
123
|
+
- Changed Perplexity explicit provider availability checks so the setup wizard can mark `perplexity` as available for manual selection without credentials, while auto provider discovery still requires auth
|
|
124
|
+
- Changed the default persistent model selector shortcut from `Ctrl+L` to `Alt+M`, leaving `Ctrl+L` for display reset. Existing user remaps in `keybindings.yml` are preserved.
|
|
125
|
+
- Changed the edit tool result header to carry the diff change stats (`+N / -M / K hunks`) inline next to the file path, and removed the redundant lone language-icon metadata row and the blank line between the header and the diff body, so a single-hunk edit renders as `✔ Edit: <icon> path:LINE ⟨+3 / 1 hunk⟩` immediately followed by the diff.
|
|
126
|
+
- Changed the `web_search` tool result rendering: the answer text now shows in full instead of being truncated to a "… N more lines" preview (the `omp q` CLI still caps its compact output), each source renders as a single `title (domain) · age` line with the URL linked on the title (dropping the snippet and bare-URL rows), and the metadata block collapses to one `Provider: <model> @ <provider> (<auth>)` line plus `Usage:` (removing the redundant Sources/Citations/Request/Queries rows).
|
|
127
|
+
|
|
128
|
+
### Fixed
|
|
129
|
+
|
|
130
|
+
- Fixed Perplexity `perplexity_ask` response parsing so OAuth, cookie, and anonymous searches correctly extract answer text and sources from JSON payloads
|
|
131
|
+
- Fixed framed read results rendering with an extra blank row above and below the output block.
|
|
132
|
+
- Fixed collapsed search result previews that could show only "… N more matches" when the first grouped section exceeded the preview budget. Collapsed search output now compacts to match rows, fills the budget with visible hits before the summary, and keeps truncation details out of the bottom user-visible notice.
|
|
133
|
+
- Fixed the expanded search result view dumping every match when all hits live in one file. A single file's matches collapse into one blank-line group, and the expanded tree list ignored the line budget, so a hot file whose matches span its whole length rendered every row (e.g. lines 374–2858). Expanded search output is now bounded by a larger-than-collapsed budget (`EXPANDED_LINES × 2`), keeps surrounding context rows, and appends a `… N more matches` summary when truncated.
|
|
134
|
+
- Fixed boolean environment flag overrides that were ORed with settings, so `PI_INTENT_TRACING=0`, `PI_AUTO_QA=0`, and per-backend eval flags now take precedence when present while falling back to config when unset.
|
|
135
|
+
- Fixed custom-rendered tools that set `mergeCallAndResult` (e.g. `lsp`) rendering a redundant tool-name line above the framed result once a result arrived. `ToolExecutionComponent`'s custom-tool branch now emits the fallback label only when the tool has no `renderCall` and the call is not suppressed by an existing result, matching the built-in renderer branch.
|
|
136
|
+
- Fixed the `write` tool result rendering with a green success checkmark even when the write failed. `writeToolRenderer.renderResult` now branches on `result.isError`, rendering the error status icon plus the failure message instead of the success header and content preview.
|
|
137
|
+
- Fixed Perplexity OAuth/cookie web search returning a refusal answer ("I don't currently have access to the web-search tools in this turn") despite returning real sources. `callPerplexityOAuth` was prepending the API-style `web-search` system prompt to the query (`query_str = systemPrompt + "\n\n" + query`), but the consumer `www.perplexity.ai/rest/sse/perplexity_ask` endpoint has no system-message slot and reads the prepended instruction as a meta-prompt, making the model decline. The OAuth/cookie path now sends the bare query; the API-key path still passes the system prompt as a proper `system` message.
|
|
138
|
+
- Fixed Perplexity OAuth web search always returning the free `turbo` model instead of the account's Pro model (e.g. `pplx_pro_upgraded`/Sonar). The `www.perplexity.ai/rest/sse/perplexity_ask` endpoint authenticates via the `__Secure-next-auth.session-token` cookie and ignores the `Authorization: Bearer` header entirely — so sending the OAuth session token as a bearer was treated as an anonymous request, which silently downgrades to `turbo` regardless of `model_preference`. The stored Perplexity OAuth token is itself the next-auth session JWT (the macOS app injects the same value as that cookie), so `callPerplexityAsk` now sends it as the `__Secure-next-auth.session-token` cookie, unlocking Pro model selection.
|
|
139
|
+
|
|
5
140
|
## [15.9.67] - 2026-06-06
|
|
141
|
+
|
|
6
142
|
### Added
|
|
7
143
|
|
|
8
144
|
- Added `timeout-pause` and `timeout-resume` eval bridge status events emitted around `agent()`/`llm()` operations
|
package/dist/types/cli/args.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Api, AssistantMessageEventStream, Context, Model, OAuthAccess, OAuthAccessResolution, SimpleStreamOptions } from "@oh-my-pi/pi-ai";
|
|
1
|
+
import type { Api, AssistantMessageEventStream, AuthCredentialSnapshotEntry, Context, Model, OAuthAccess, OAuthAccessResolution, SimpleStreamOptions } from "@oh-my-pi/pi-ai";
|
|
2
2
|
import type { CanonicalModelVariant } from "../config/model-equivalence";
|
|
3
3
|
import { type CanonicalModelQueryOptions } from "../config/model-registry";
|
|
4
4
|
import { Settings } from "../config/settings";
|
|
@@ -20,6 +20,12 @@ export interface DryBalanceAuthOptions {
|
|
|
20
20
|
export interface DryBalanceAuthStorage {
|
|
21
21
|
getOAuthAccess(provider: string, sessionId?: string, options?: DryBalanceAuthOptions): Promise<OAuthAccess | undefined>;
|
|
22
22
|
getOAuthAccesses?(provider: string, options?: DryBalanceAuthOptions): Promise<OAuthAccessResolution[]>;
|
|
23
|
+
/**
|
|
24
|
+
* Force-refresh a single credential by id (step (b) of the auth-retry
|
|
25
|
+
* policy). The bench re-mints the failing account's token in place on a
|
|
26
|
+
* 401 rather than rotating accounts — it is measuring each account.
|
|
27
|
+
*/
|
|
28
|
+
forceRefreshCredentialById?(id: number, signal?: AbortSignal): Promise<AuthCredentialSnapshotEntry>;
|
|
23
29
|
}
|
|
24
30
|
export interface DryBalanceModelRegistry {
|
|
25
31
|
authStorage: DryBalanceAuthStorage;
|
|
@@ -98,7 +104,15 @@ export interface DryBalanceDependencies {
|
|
|
98
104
|
now?: () => number;
|
|
99
105
|
stdoutIsTTY?: boolean;
|
|
100
106
|
stderrIsTTY?: boolean;
|
|
107
|
+
stdoutColumns?: number;
|
|
108
|
+
stderrColumns?: number;
|
|
101
109
|
}
|
|
110
|
+
interface DryBalanceBenchProgressSink {
|
|
111
|
+
markRunning(index: number, account: string): void;
|
|
112
|
+
complete(index: number, result: DryBalanceBenchResult): void;
|
|
113
|
+
close(): void;
|
|
114
|
+
}
|
|
115
|
+
export declare function createBenchProgressSink(total: number, write: (text: string) => void, interactive: boolean, columns: number): DryBalanceBenchProgressSink;
|
|
102
116
|
export declare function formatDryBalanceText(summary: DryBalanceSummary): string;
|
|
103
117
|
export declare function runDryBalanceCommand(command: DryBalanceCommandArgs, deps?: DryBalanceDependencies): Promise<DryBalanceSummary>;
|
|
104
118
|
export {};
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { type GalleryFixture } from "./gallery-fixtures";
|
|
2
|
+
/** Lifecycle states the gallery renders, in display order. */
|
|
3
|
+
export declare const GALLERY_STATES: readonly ["streaming", "progress", "success", "error"];
|
|
4
|
+
export type GalleryState = (typeof GALLERY_STATES)[number];
|
|
5
|
+
export interface GalleryCommandArgs {
|
|
6
|
+
/** Render width in columns (defaults to terminal width, clamped). */
|
|
7
|
+
width?: number;
|
|
8
|
+
/** Restrict to a single tool name. */
|
|
9
|
+
tool?: string;
|
|
10
|
+
/** Restrict to specific lifecycle states. */
|
|
11
|
+
states?: GalleryState[];
|
|
12
|
+
/** Render the expanded variant of each renderer. */
|
|
13
|
+
expanded?: boolean;
|
|
14
|
+
/** Strip ANSI styling from the output (useful when redirecting to a file). */
|
|
15
|
+
plain?: boolean;
|
|
16
|
+
/** Capture the rendered gallery as PNG screenshot(s) via VHS instead of printing ANSI. */
|
|
17
|
+
screenshot?: boolean;
|
|
18
|
+
/** Screenshot output path (single image) or base path (suffixed when split across images). */
|
|
19
|
+
out?: string;
|
|
20
|
+
/** Font family for screenshots (must be installed; Nerd Font recommended for icon glyphs). */
|
|
21
|
+
font?: string;
|
|
22
|
+
/** Font size in points for screenshots. */
|
|
23
|
+
fontSize?: number;
|
|
24
|
+
}
|
|
25
|
+
/** One tool's rendered lifecycle, as ANSI lines: a leading blank, the section rule, then each state. */
|
|
26
|
+
export interface GallerySection {
|
|
27
|
+
heading: string;
|
|
28
|
+
lines: string[];
|
|
29
|
+
}
|
|
30
|
+
/** The curated fixture for a tool, or a generic one for registry tools lacking sample data. */
|
|
31
|
+
export declare function resolveFixture(name: string): GalleryFixture;
|
|
32
|
+
/**
|
|
33
|
+
* Render a single tool/state pair to lines. Builds a fresh component, drives it
|
|
34
|
+
* to the requested state, settles any async edit preview, then snapshots the
|
|
35
|
+
* render and stops all animation timers.
|
|
36
|
+
*/
|
|
37
|
+
export declare function renderGalleryState(name: string, fixture: GalleryFixture, state: GalleryState, width: number, expanded?: boolean): Promise<string[]>;
|
|
38
|
+
/**
|
|
39
|
+
* Render the gallery. Iterates the renderer registry (or a single tool),
|
|
40
|
+
* printing each requested lifecycle state under a labeled section — or, with
|
|
41
|
+
* `screenshot`, capturing the rendered output as PNG(s) via VHS.
|
|
42
|
+
*/
|
|
43
|
+
export declare function runGalleryCommand(args: GalleryCommandArgs): Promise<void>;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Types for `omp gallery` sample data. See {@link ./index} for the aggregated
|
|
3
|
+
* fixture registry and the contract each fixture must satisfy.
|
|
4
|
+
*/
|
|
5
|
+
import type { EditMode } from "../../edit";
|
|
6
|
+
/** A tool result snapshot, matching the shape `ToolExecutionComponent` consumes. */
|
|
7
|
+
export interface GalleryResult {
|
|
8
|
+
content: Array<{
|
|
9
|
+
type: string;
|
|
10
|
+
text?: string;
|
|
11
|
+
data?: string;
|
|
12
|
+
mimeType?: string;
|
|
13
|
+
}>;
|
|
14
|
+
details?: unknown;
|
|
15
|
+
isError?: boolean;
|
|
16
|
+
}
|
|
17
|
+
export interface GalleryFixture {
|
|
18
|
+
/** Display label for the tool header (defaults to the tool name). */
|
|
19
|
+
label?: string;
|
|
20
|
+
/** Edit mode for edit-like tools so the streaming preview dispatches correctly. */
|
|
21
|
+
editMode?: EditMode;
|
|
22
|
+
/**
|
|
23
|
+
* Set for tools whose real `AgentTool` attaches `renderCall`/`renderResult`
|
|
24
|
+
* directly on the instance (e.g. `lsp`, `task`). The harness then attaches
|
|
25
|
+
* the registry renderer onto the fake tool so the component routes through
|
|
26
|
+
* the custom-tool branch — the same path production takes — instead of the
|
|
27
|
+
* built-in registry branch. The two branches can diverge, so exercising the
|
|
28
|
+
* real one keeps the gallery honest for these tools.
|
|
29
|
+
*/
|
|
30
|
+
customRendered?: boolean;
|
|
31
|
+
/**
|
|
32
|
+
* Arguments shown during the streaming state — a partial view of {@link args}
|
|
33
|
+
* as if the tool-call JSON were still arriving. May include `__partialJson`
|
|
34
|
+
* for renderers (bash, edit) that surface fields before the object closes.
|
|
35
|
+
* Defaults to {@link args} when omitted.
|
|
36
|
+
*/
|
|
37
|
+
streamingArgs?: unknown;
|
|
38
|
+
/** Complete arguments shown for the in-progress, success, and error states. */
|
|
39
|
+
args: unknown;
|
|
40
|
+
/** Successful result. */
|
|
41
|
+
result: GalleryResult;
|
|
42
|
+
/** Failed result. Falls back to a generic error when omitted. */
|
|
43
|
+
errorResult?: GalleryResult;
|
|
44
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { GallerySection } from "./gallery-cli";
|
|
2
|
+
/** Nerd Font family so the gallery's icon glyphs (PUA) render instead of tofu. */
|
|
3
|
+
export declare const DEFAULT_SCREENSHOT_FONT = "JetBrainsMono Nerd Font";
|
|
4
|
+
export declare const DEFAULT_SCREENSHOT_FONT_SIZE = 18;
|
|
5
|
+
export interface GalleryScreenshotOptions {
|
|
6
|
+
/** Gallery render width in columns (matches the ANSI line width). */
|
|
7
|
+
width: number;
|
|
8
|
+
/** VHS `FontFamily`. */
|
|
9
|
+
font?: string;
|
|
10
|
+
/** VHS `FontSize`. */
|
|
11
|
+
fontSize?: number;
|
|
12
|
+
/**
|
|
13
|
+
* Output destination. When omitted, PNGs land in a fresh temp directory.
|
|
14
|
+
* With multiple images the path is suffixed (`name-01.png`, `name-02.png`).
|
|
15
|
+
*/
|
|
16
|
+
out?: string;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Capture the gallery sections as one or more PNGs and return their absolute
|
|
20
|
+
* paths. Tall galleries are split across images so no single capture exceeds
|
|
21
|
+
* the terminal-canvas height limit.
|
|
22
|
+
*/
|
|
23
|
+
export declare function captureGalleryScreenshots(sections: GallerySection[], options: GalleryScreenshotOptions): Promise<string[]>;
|
|
24
|
+
/**
|
|
25
|
+
* Resolve a chunk's PNG path. A single image keeps the bare name (or the exact
|
|
26
|
+
* `out`); multiple images gain a zero-padded `-NN` suffix so they sort and never
|
|
27
|
+
* collide.
|
|
28
|
+
*/
|
|
29
|
+
export declare function resolveScreenshotOutputPath(out: string | undefined, baseDir: string, index: number, total: number): string;
|
|
30
|
+
/**
|
|
31
|
+
* Group whole tool sections into chunks that stay under `rowBudget` rows. A
|
|
32
|
+
* single section larger than the budget gets its own (taller) image rather than
|
|
33
|
+
* being split mid-renderer.
|
|
34
|
+
*/
|
|
35
|
+
export declare function chunkGallerySections(sections: GallerySection[], rowBudget: number): GallerySection[][];
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Render every built-in tool's renderer across its lifecycle states.
|
|
3
|
+
*/
|
|
4
|
+
import { Command } from "@oh-my-pi/pi-utils/cli";
|
|
5
|
+
export default class Gallery extends Command {
|
|
6
|
+
static description: string;
|
|
7
|
+
static flags: {
|
|
8
|
+
tool: import("@oh-my-pi/pi-utils/cli").FlagDescriptor<"string"> & {
|
|
9
|
+
char: string;
|
|
10
|
+
description: string;
|
|
11
|
+
};
|
|
12
|
+
state: import("@oh-my-pi/pi-utils/cli").FlagDescriptor<"string"> & {
|
|
13
|
+
char: string;
|
|
14
|
+
description: string;
|
|
15
|
+
options: ("error" | "progress" | "streaming" | "success")[];
|
|
16
|
+
multiple: true;
|
|
17
|
+
};
|
|
18
|
+
width: import("@oh-my-pi/pi-utils/cli").FlagDescriptor<"integer"> & {
|
|
19
|
+
char: string;
|
|
20
|
+
description: string;
|
|
21
|
+
};
|
|
22
|
+
expanded: import("@oh-my-pi/pi-utils/cli").FlagDescriptor<"boolean"> & {
|
|
23
|
+
char: string;
|
|
24
|
+
description: string;
|
|
25
|
+
default: boolean;
|
|
26
|
+
};
|
|
27
|
+
plain: import("@oh-my-pi/pi-utils/cli").FlagDescriptor<"boolean"> & {
|
|
28
|
+
description: string;
|
|
29
|
+
default: boolean;
|
|
30
|
+
};
|
|
31
|
+
screenshot: import("@oh-my-pi/pi-utils/cli").FlagDescriptor<"boolean"> & {
|
|
32
|
+
description: string;
|
|
33
|
+
default: boolean;
|
|
34
|
+
};
|
|
35
|
+
out: import("@oh-my-pi/pi-utils/cli").FlagDescriptor<"string"> & {
|
|
36
|
+
char: string;
|
|
37
|
+
description: string;
|
|
38
|
+
};
|
|
39
|
+
font: import("@oh-my-pi/pi-utils/cli").FlagDescriptor<"string"> & {
|
|
40
|
+
description: string;
|
|
41
|
+
};
|
|
42
|
+
"font-size": import("@oh-my-pi/pi-utils/cli").FlagDescriptor<"integer"> & {
|
|
43
|
+
description: string;
|
|
44
|
+
};
|
|
45
|
+
};
|
|
46
|
+
run(): Promise<void>;
|
|
47
|
+
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import type { ThinkingLevel } from "@oh-my-pi/pi-agent-core";
|
|
2
|
-
import type { Api, Model } from "@oh-my-pi/pi-ai";
|
|
2
|
+
import type { Api, ApiKey, Model } from "@oh-my-pi/pi-ai";
|
|
3
3
|
import type { ConventionalAnalysis } from "../../commit/types";
|
|
4
4
|
export interface ConventionalAnalysisInput {
|
|
5
5
|
model: Model<Api>;
|
|
6
|
-
apiKey:
|
|
6
|
+
apiKey: ApiKey;
|
|
7
7
|
thinkingLevel?: ThinkingLevel;
|
|
8
8
|
contextFiles?: Array<{
|
|
9
9
|
path: string;
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import type { ThinkingLevel } from "@oh-my-pi/pi-agent-core";
|
|
2
|
-
import type { Api, Model } from "@oh-my-pi/pi-ai";
|
|
2
|
+
import type { Api, ApiKey, Model } from "@oh-my-pi/pi-ai";
|
|
3
3
|
import type { CommitSummary } from "../../commit/types";
|
|
4
4
|
export interface SummaryInput {
|
|
5
5
|
model: Model<Api>;
|
|
6
|
-
apiKey:
|
|
6
|
+
apiKey: ApiKey;
|
|
7
7
|
thinkingLevel?: ThinkingLevel;
|
|
8
8
|
commitType: string;
|
|
9
9
|
scope: string | null;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { ThinkingLevel } from "@oh-my-pi/pi-agent-core";
|
|
2
|
-
import type { Api, Model } from "@oh-my-pi/pi-ai";
|
|
2
|
+
import type { Api, ApiKey, Model } from "@oh-my-pi/pi-ai";
|
|
3
3
|
import * as z from "zod/v4";
|
|
4
4
|
import { type ChangelogGenerationResult } from "../../commit/types";
|
|
5
5
|
export declare const changelogTool: {
|
|
@@ -19,7 +19,7 @@ export declare const changelogTool: {
|
|
|
19
19
|
};
|
|
20
20
|
export interface ChangelogPromptInput {
|
|
21
21
|
model: Model<Api>;
|
|
22
|
-
apiKey:
|
|
22
|
+
apiKey: ApiKey;
|
|
23
23
|
thinkingLevel?: ThinkingLevel;
|
|
24
24
|
changelogPath: string;
|
|
25
25
|
isPackageChangelog: boolean;
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import type { ThinkingLevel } from "@oh-my-pi/pi-agent-core";
|
|
2
|
-
import type { Api, Model } from "@oh-my-pi/pi-ai";
|
|
2
|
+
import type { Api, ApiKey, Model } from "@oh-my-pi/pi-ai";
|
|
3
3
|
export interface ChangelogFlowInput {
|
|
4
4
|
cwd: string;
|
|
5
5
|
model: Model<Api>;
|
|
6
|
-
apiKey:
|
|
6
|
+
apiKey: ApiKey;
|
|
7
7
|
thinkingLevel?: ThinkingLevel;
|
|
8
8
|
stagedFiles: string[];
|
|
9
9
|
dryRun: boolean;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { ThinkingLevel } from "@oh-my-pi/pi-agent-core";
|
|
2
|
-
import type { Api, Model } from "@oh-my-pi/pi-ai";
|
|
2
|
+
import type { Api, ApiKey, Model } from "@oh-my-pi/pi-ai";
|
|
3
3
|
import type { ConventionalAnalysis } from "../../commit/types";
|
|
4
4
|
export interface MapReduceSettings {
|
|
5
5
|
enabled?: boolean;
|
|
@@ -10,10 +10,10 @@ export interface MapReduceSettings {
|
|
|
10
10
|
}
|
|
11
11
|
export interface MapReduceInput {
|
|
12
12
|
model: Model<Api>;
|
|
13
|
-
apiKey:
|
|
13
|
+
apiKey: ApiKey;
|
|
14
14
|
thinkingLevel?: ThinkingLevel;
|
|
15
15
|
smolModel: Model<Api>;
|
|
16
|
-
smolApiKey:
|
|
16
|
+
smolApiKey: ApiKey;
|
|
17
17
|
smolThinkingLevel?: ThinkingLevel;
|
|
18
18
|
diff: string;
|
|
19
19
|
stat: string;
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import type { ThinkingLevel } from "@oh-my-pi/pi-agent-core";
|
|
2
|
-
import type { Api, Model } from "@oh-my-pi/pi-ai";
|
|
2
|
+
import type { Api, ApiKey, Model } from "@oh-my-pi/pi-ai";
|
|
3
3
|
import type { FileDiff, FileObservation } from "../../commit/types";
|
|
4
4
|
export interface MapPhaseInput {
|
|
5
5
|
model: Model<Api>;
|
|
6
|
-
apiKey:
|
|
6
|
+
apiKey: ApiKey;
|
|
7
7
|
thinkingLevel?: ThinkingLevel;
|
|
8
8
|
files: FileDiff[];
|
|
9
9
|
config?: {
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import type { ThinkingLevel } from "@oh-my-pi/pi-agent-core";
|
|
2
|
-
import type { Api, Model } from "@oh-my-pi/pi-ai";
|
|
2
|
+
import type { Api, ApiKey, Model } from "@oh-my-pi/pi-ai";
|
|
3
3
|
import type { ConventionalAnalysis, FileObservation } from "../../commit/types";
|
|
4
4
|
export interface ReducePhaseInput {
|
|
5
5
|
model: Model<Api>;
|
|
6
|
-
apiKey:
|
|
6
|
+
apiKey: ApiKey;
|
|
7
7
|
thinkingLevel?: ThinkingLevel;
|
|
8
8
|
observations: FileObservation[];
|
|
9
9
|
stat: string;
|
|
@@ -1,15 +1,21 @@
|
|
|
1
1
|
import type { ThinkingLevel } from "@oh-my-pi/pi-agent-core";
|
|
2
|
-
import type { Api, Model } from "@oh-my-pi/pi-ai";
|
|
2
|
+
import type { Api, ApiKey, Model } from "@oh-my-pi/pi-ai";
|
|
3
|
+
import type { ApiKeyResolverRegistry } from "../config/api-key-resolver";
|
|
3
4
|
import { type ModelLookupRegistry } from "../config/model-resolver";
|
|
4
5
|
import type { Settings } from "../config/settings";
|
|
5
6
|
export interface ResolvedCommitModel {
|
|
6
7
|
model: Model<Api>;
|
|
7
|
-
|
|
8
|
+
/**
|
|
9
|
+
* Resolver for the model's bearer: re-resolves on 401 / usage-limit so the
|
|
10
|
+
* whole commit pipeline (analysis, map/reduce, changelog) inherits the
|
|
11
|
+
* central force-refresh + account-rotation policy.
|
|
12
|
+
*/
|
|
13
|
+
apiKey: ApiKey;
|
|
8
14
|
thinkingLevel?: ThinkingLevel;
|
|
9
15
|
}
|
|
10
|
-
type CommitModelRegistry = ModelLookupRegistry & {
|
|
16
|
+
type CommitModelRegistry = ModelLookupRegistry & ApiKeyResolverRegistry & {
|
|
11
17
|
getApiKey: (model: Model<Api>) => Promise<string | undefined>;
|
|
12
18
|
};
|
|
13
19
|
export declare function resolvePrimaryModel(override: string | undefined, settings: Settings, modelRegistry: CommitModelRegistry): Promise<ResolvedCommitModel>;
|
|
14
|
-
export declare function resolveSmolModel(settings: Settings, modelRegistry: CommitModelRegistry, fallbackModel: Model<Api>, fallbackApiKey:
|
|
20
|
+
export declare function resolveSmolModel(settings: Settings, modelRegistry: CommitModelRegistry, fallbackModel: Model<Api>, fallbackApiKey: ApiKey): Promise<ResolvedCommitModel>;
|
|
15
21
|
export {};
|